diff --git a/README.md b/README.md index bd2854e..8dc506f 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Iterate supports early exit by returning non `undefined` value inside `iteratorC Resulting value will be passed to the promise as the result of iteration. You can use this to make a search in your data: ```js -$localForage.iterate(function(value, key) { +$localForage.iterate(function(value, key, iterationNumber) { if(angular.isInt(value) && value > 10) { return key; } @@ -156,13 +156,33 @@ You can use multiple instances of localForage at the same time. To create a new name: '2nd', driver: 'localStorageWrapper' }); + + var lf3 = $localForage.createInstance({ + name: '3rd', + storeName: 'kvpairs' + }); ``` The parameters will inherit the default parameters that you might have configured in the config phase of your application (See [above](#configure-the-provider-) for details), but the new config object will overwrite them. It means that you can have one instance using localStorage, and one instance using indexedDB/WebSQL, at the same time ! The instance will take the name that you will define in the config object. You can get an instance previously created by using the `instance` method: ```js + // DEPRECATED var lf2 = $localForage.instance('2nd'); + + // NEW USAGE + var lf2 = $localForage.instance({ + name: '2nd' + }); + + var lf3 = $localForage.instance({ + name: '3rd', + storeName: 'kvpairs' + }); + + var lf4 = $localForage.instance({ + storeName: 'example_store' + }); ``` The `instance` method will return the default instance if you don't give a name parameter. diff --git a/src/angular-localForage.js b/src/angular-localForage.js index 21e3d9b..977e936 100644 --- a/src/angular-localForage.js +++ b/src/angular-localForage.js @@ -18,7 +18,8 @@ angularLocalForage.provider('$localForage', function() { var lfInstances = {}, defaultConfig = { - name: 'lf' + name: 'lf', + storeName: 'keyvaluepairs', }, // Send signals for each of the following actions ? notify = { @@ -55,14 +56,17 @@ LocalForageInstance.prototype.createInstance = function createInstance(config) { if(angular.isObject(config)) { // create new instance config = angular.extend({}, defaultConfig, config); - if(angular.isDefined(lfInstances[config.name])) { - throw new Error('A localForage instance with the name ' + config.name + ' is already defined.'); + var lfInstanceName = config.name + '#' + config.storeName; + if(angular.isDefined(lfInstances[lfInstanceName])) { + throw new Error('A localForage instance with the name ' + + config.name + ' and storeName ' + + config.storeName + ' is already defined.'); } - lfInstances[config.name] = new LocalForageInstance(config); - return lfInstances[config.name]; + lfInstances[lfInstanceName] = new LocalForageInstance(config); + return lfInstances[lfInstanceName]; } else { - throw new Error('The parameter should be a config object.') + throw new Error('The parameter should be a config object.'); } }; @@ -70,13 +74,33 @@ if(angular.isUndefined(name)) { return lfInstances[defaultConfig.name]; } else if(angular.isString(name)) { - if(angular.isDefined(lfInstances[name])) { - return lfInstances[name]; + var lfInstanceName = name + '#' + defaultConfig.storeName; + if(angular.isDefined(lfInstances[lfInstanceName])) { + return lfInstances[lfInstanceName]; } else { - throw new Error('No localForage instance of that name exists.') + throw new Error('No localForage instance of that name exists.'); + } + } else if(angular.isObject(name)) { + // if it is an object with {name, storeName} properties, + // return corresponding instance + var instanceObj = name; + if(!angular.isDefined(instanceObj.name) && + !angular.isDefined(instanceObj.storeName)) { + throw new Error('instance parameter object needs to contain name or storeName'); + } + var n = (angular.isDefined(instanceObj.name) + ? instanceObj.name + : defaultConfig.name), + sn = (angular.isDefined(instanceObj.storeName) + ? instanceObj.storeName + : defaultConfig.storeName); + if(angular.isDefined(lfInstances[n + '#' + sn])) { + return lfInstances[n + '#' + sn]; + } else { + throw new Error('No localForage instance of that name exists.'); } } else { - throw new Error('The parameter should be a string.') + throw new Error('The parameter should be a string or object.'); } }; diff --git a/tests/angular-localForage.js b/tests/angular-localForage.js index e5c9f0b..4c35aa2 100644 --- a/tests/angular-localForage.js +++ b/tests/angular-localForage.js @@ -150,6 +150,18 @@ describe('Module: LocalForageModule', function() { }, done); }); + it('should have an iterationNumber with a 1-index', function(done) { + var count; + + $localForage.iterate(function(value, key, iterationNumber) { + count = iterationNumber; + }).then(function() { + stopDigests(interval); + expect(count).toEqual(3); + done(); + }, done); + }) + it('key/value filter should work', function(done) { //test key filter $localForage.iterate(function(value, key) { @@ -465,4 +477,74 @@ describe('Module: LocalForageModule', function() { }, done); }); }); + + describe("createInstance", function () { + beforeEach(function () { + $localForage.createInstance({ + name: 'DUPLICATE_INSTANCE_NAME' + }); + }); + it('should create a new instance', function () { + expect($localForage.createInstance({ + name: 'TEST_INSTANCE' + })).toBeDefined(); + }); + + it('should throw error if trying to create duplicate instance.', + function () { + expect($localForage.createInstance.bind($localForage, { + name: 'DUPLICATE_INSTANCE_NAME' + })).toThrowError(/already defined/); + }); + + it('should create instance with same name, different storeName', + function () { + expect($localForage.createInstance.bind($localForage, { + name: 'DUPLICATE_INSTANCE_NAME', + storeName: 'DIFFERENT_STORE_NAME' + })).not.toThrowError(/already defined/); + }); + }); + + describe("instance", function () { + beforeEach(function () { + $localForage.createInstance({ + name: 'TEST_INSTANCE_1' + }); + $localForage.createInstance({ + name: 'TEST_INSTANCE_2', + storeName: 'TEST_STORE_NAME_1' + }); + $localForage.createInstance({ + name: 'TEST_INSTANCE_2', + storeName: 'TEST_STORE_NAME_2' + }); + }); + + it('should get instance by name', function () { + expect($localForage.instance({ + name: 'TEST_INSTANCE_1' + })).toBeDefined(); + }); + + it('should throw exception if instance not exists', function () { + expect($localForage.instance.bind($localForage, { + name: 'NON_EXISTENT' + })).toThrowError(); + }); + + it('should get instances with same name, different storeNames', + function () { + var instance1 = $localForage.instance({ + name: 'TEST_INSTANCE_2', + storeName: 'TEST_STORE_NAME_1' + }); + var instance2 = $localForage.instance({ + name: 'TEST_INSTANCE_2', + storeName: 'TEST_STORE_NAME_2' + }); + expect(instance1).not.toBe(instance2); + } + ); + }); });