{"id":13778045,"url":"https://github.com/tymondesigns/angular-locker","last_synced_at":"2025-05-11T11:34:49.089Z","repository":{"id":18948524,"uuid":"22168580","full_name":"tymondesigns/angular-locker","owner":"tymondesigns","description":"🗄️ A simple \u0026 configurable abstraction for local/session storage in angular js projects","archived":true,"fork":false,"pushed_at":"2017-12-08T16:08:39.000Z","size":20827,"stargazers_count":314,"open_issues_count":9,"forks_count":41,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-11-03T20:06:42.382Z","etag":null,"topics":["angular","localstorage","sessionstorage","storage"],"latest_commit_sha":null,"homepage":"https://npm.im/angular-locker","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tymondesigns.png","metadata":{"files":{"readme":"README.md","changelog":"changes.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-07-23T18:34:04.000Z","updated_at":"2024-03-12T12:38:31.000Z","dependencies_parsed_at":"2022-08-31T00:02:16.898Z","dependency_job_id":null,"html_url":"https://github.com/tymondesigns/angular-locker","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tymondesigns%2Fangular-locker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tymondesigns%2Fangular-locker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tymondesigns%2Fangular-locker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tymondesigns%2Fangular-locker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tymondesigns","download_url":"https://codeload.github.com/tymondesigns/angular-locker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225043274,"owners_count":17411955,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","localstorage","sessionstorage","storage"],"created_at":"2024-08-03T18:00:50.738Z","updated_at":"2024-11-17T13:31:21.042Z","avatar_url":"https://github.com/tymondesigns.png","language":"JavaScript","readme":"angular-locker\n==============\n\nA simple \u0026 configurable abstraction for local/session storage in angular projects - providing a fluent api that is powerful and easy to use.\n\n[![Build Status](http://img.shields.io/travis/tymondesigns/angular-locker/master.svg?style=flat-square)](https://travis-ci.org/tymondesigns/angular-locker)\n[![Test Coverage](http://img.shields.io/codeclimate/coverage/github/tymondesigns/angular-locker.svg?style=flat-square)](https://codeclimate.com/github/tymondesigns/angular-locker)\n[![License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](http://www.opensource.org/licenses/MIT)\n[![NPM Release](https://img.shields.io/npm/v/angular-locker.svg?style=flat-square)](https://www.npmjs.org/package/angular-locker)\n[![NPM Monthly Downloads](https://img.shields.io/npm/dm/angular-locker.svg?style=flat-square)](https://www.npmjs.org/package/angular-locker)\n[![NPM Total Downloads](https://img.shields.io/npm/dt/angular-locker.svg?style=flat-square)](https://www.npmjs.org/package/angular-locker)\n\n* [Installation](#installation)\n* [Usage](#usage)\n    * [Adding to your project](#usage-adding-to-your-project)\n    * [Switching storage drivers](#usage-switching-storage-drivers)\n    * [Switching namespace](#usage-switching-namespace)\n    * [Adding items to locker](#usage-adding-items-to-locker)\n    * [Retrieving items from locker](#usage-retrieving-items-from-locker)\n    * [Checking item exists in locker](#usage-checking-item-exists-in-locker)\n    * [Removing items from locker](#usage-removing-items-from-locker)\n    * [Events](#usage-events)\n    * [Binding to a $scope property](#usage-binding-to-a-scope-property)\n* [Browser Compatibility](#browser-compatibility)\n* [Contributing](#contributing)\n* [Development](#development)\n* [License](#license)\n\n\n\u003ch2 id=\"installation\"\u003eInstallation\u003c/h2\u003e\n\n\u003ch4 id=\"installation-via-bower\"\u003evia bower\u003c/h4\u003e\n\n```bash\n$ bower install angular-locker\n```\n\n\u003ch4 id=\"installation-via-npm\"\u003evia npm\u003c/h4\u003e\n\n```bash\n$ npm install angular-locker\n```\n\n\u003ch4 id=\"installation-via-jsdelivr-cdn\"\u003evia jsDelivr CDN\u003c/h4\u003e\n\nhttp://www.jsdelivr.com/#!angular.locker\n\n\u003ch4 id=\"installation-manual\"\u003emanual\u003c/h4\u003e\n\nSimply download the zip file [HERE](https://github.com/tymondesigns/angular-locker/archive/master.zip) and include `dist/angular-locker.min.js` in your project.\n\n1.66 KB Minified \u0026 gzipped.\n\n\u003ch2 id=\"usage\"\u003eUsage\u003c/h2\u003e\n\n\u003ch3 id=\"usage-adding-to-your-project\"\u003eAdding to your project\u003c/h3\u003e\n\nAdd `angular-locker` as a dependency\n\n```js\nangular.module('myApp', ['angular-locker'])\n```\n\nConfigure via `lockerProvider` (*optional*)\n\n```js\n.config(['lockerProvider', function config(lockerProvider) {\n    lockerProvider.defaults({\n        driver: 'session',\n        namespace: 'myApp',\n        separator: '.',\n        eventsEnabled: true,\n        extend: {}\n    });\n}]);\n```\n\n*Note*: You can also pass `false` to `namespace` if you prefer to not have a namespace in your keys.\n\ninject `locker` into your controller/service/directive etc\n\n```js\n.factory('MyFactory', ['locker', function MyFactory(locker) {\n    locker.put('someKey', 'someVal');\n}]);\n```\n\n\u003ch4 id=\"usage-adding-to-your-project-extending-locker\"\u003eExtending Locker\u003c/h4\u003e\n\nYou can pass in an implementation of the [Storage Interface](https://developer.mozilla.org/en-US/docs/Web/API/Storage) to the `lockerProvider` as described above. e.g.\n\n```js\nlockerProvider.defaults({\n    extend: {\n        myCustomStore: function () {\n            // getItem\n            // setItem\n            // removeItem\n            // etc\n        }\n    }\n});\n\n// then use as normal\nlocker.driver('myCustomStore').put('foo', 'bar');\n```\n\nSee my [storageMock](https://github.com/tymondesigns/angular-locker/blob/master/test/mock/storageMock.js) for an example on how to define a custom implementation.\n\n----------------------------\n\n\u003ch3 id=\"usage-switching-storage-drivers\"\u003eSwitching storage drivers\u003c/h3\u003e\n\nThere may be times where you will want to dynamically switch between using local and session storage.\nTo achieve this, simply chain the `driver()` setter to specify what storage driver you want to use, as follows:\n\n```js\n// put an item into session storage\nlocker.driver('session').put('sessionKey', ['some', 'session', 'data']);\n\n// this time use local storage\nlocker.driver('local').put('localKey', ['some', 'persistent', 'things']);\n```\n\n\u003ch3 id=\"usage-switching-namespace\"\u003eSwitching namespace\u003c/h3\u003e\n\n```js\n// add an item within a different namespace\nlocker.namespace('otherNamespace').put('foo', 'bar');\n```\n\nOmitting the driver or namespace setters will respect whatever default was specified via `lockerProvider`.\n\n----------------------------\n\n\u003ch3 id=\"usage-adding-items-to-locker\"\u003eAdding items to locker\u003c/h3\u003e\n\nthere are several ways to add something to locker:\n\nYou can add Objects, Arrays, whatever :)\n\nlocker will automatically serialize your objects/arrays in local/session storage\n\n```js\nlocker.put('someString', 'anyDataType');\nlocker.put('someObject', { foo: 'I will be serialized', bar: 'pretty cool eh' });\nlocker.put('someArray', ['foo', 'bar', 'baz']);\n// etc\n```\n\n\u003ch4 id=\"usage-adding-items-to-locker-adding-via-value-function-param\"\u003eadding via value function param\u003c/h4\u003e\n\nInserts specified key and return value of function\n\n```js\nlocker.put('someKey', function() {\n    var obj = { foo: 'bar', bar: 'baz' };\n    // some other logic\n    return obj;\n});\n```\n\nThe current value will be passed into the function so you can perform logic on the current value, before returning it. e.g.\n\n```js\nlocker.put('someKey', ['foo', 'bar']);\n\nlocker.put('someKey', function(current) {\n    current.push('baz');\n\n    return current;\n});\n\nlocker.get('someKey'); // = ['foo', 'bar', 'baz']\n```\n\nIf the current value is not already set then you can pass a third parameter as a default that will be returned instead. e.g.\n\n```js\n// given locker.get('foo') is not defined\nlocker.put('foo', function (current) {\n    // current will equal 'bar'\n}, 'bar');\n```\n\n\u003ch4 id=\"usage-adding-items-to-locker-adding-multiple-items-at-once-by-passing-a-single-object\"\u003eadding multiple items at once by passing a single object\u003c/h4\u003e\n\nThis will add each key/value pair as a **separate** item in storage\n\n```js\nlocker.put({\n    someKey: 'johndoe',\n    anotherKey: ['some', 'random', 'array'],\n    boolKey: true\n});\n```\n\n\u003ch4 id=\"usage-adding-items-to-locker-adding-via-key-function-param\"\u003eadding via key function param\u003c/h4\u003e\n\nInserts each item from the returned Object, similar to above\n\n```js\nlocker.put(function() {\n    // some logic\n    return {\n        foo: ['lorem', 'ipsum', 'dolor'],\n        user: {\n            username: 'johndoe',\n            displayName: 'Johnny Doe',\n            active: true,\n            role: 'user'\n        }\n    };\n});\n```\n\n\u003ch4 id=\"usage-adding-items-to-locker-conditionally-adding-an-item-if-it-doesn-t-already-exist\"\u003econditionally adding an item if it doesn't already exist\u003c/h4\u003e\n\nFor this functionality you can use the `add()` method.\n\nIf the key already exists then no action will be taken and `false` will be returned\n\n```js\nlocker.add('someKey', 'someVal'); // true or false - whether the item was added or not\n```\n\n----------------------------\n\n\u003ch3 id=\"usage-retrieving-items-from-locker\"\u003eRetrieving items from locker\u003c/h3\u003e\n\n```js\n// locker.put('fooArray', ['bar', 'baz', 'bob']);\n\nlocker.get('fooArray'); // ['bar', 'baz', 'bob']\n```\n\n\u003ch4 id=\"usage-retrieving-items-from-locker-setting-a-default-value\"\u003esetting a default value\u003c/h4\u003e\n\nif the key does not exist then, if specified the default will be returned\n\n```js\nlocker.get('keyDoesNotExist', 'a default value'); // 'a default value'\n```\n\n\u003ch4 id=\"usage-retrieving-items-from-locker-retrieving-multiple-items-at-once\"\u003eretrieving multiple items at once\u003c/h4\u003e\n\nYou may pass an array to the `get()` method to return an Object containing the specified keys (if they exist)\n\n```js\nlocker.get(['someKey', 'anotherKey', 'foo']);\n\n// will return something like...\n{\n    someKey: 'someValue',\n    anotherKey: true,\n    foo: 'bar'\n}\n```\n\n\u003ch4 id=\"usage-retrieving-items-from-locker-deleting-afterwards\"\u003edeleting afterwards\u003c/h4\u003e\n\nYou can also retrieve an item and then delete it via the `pull()` method\n\n```js\n// locker.put('someKey', { foo: 'bar', baz: 'bob' });\n\nlocker.pull('someKey', 'defaultVal'); // { foo: 'bar', baz: 'bob' }\n\n// then...\n\nlocker.get('someKey', 'defaultVal'); // 'defaultVal'\n```\n\n\u003ch4 id=\"usage-retrieving-items-from-locker-all-items\"\u003eall items\u003c/h4\u003e\n\nYou can retrieve all items within the current namespace\n\nThis will return an object containing all the key/value pairs in storage\n\n```js\nlocker.all();\n// or\nlocker.namespace('somethingElse').all();\n```\n\n\u003ch4 id=\"usage-retrieving-items-from-locker-counting-items\"\u003ecounting items\u003c/h4\u003e\n\nTo count the number of items within a given namespace:\n\n```js\nlocker.count();\n// or\nlocker.namespace('somethingElse').count();\n```\n\n----------------------------\n\n\u003ch3 id=\"usage-checking-item-exists-in-locker\"\u003eChecking item exists in locker\u003c/h3\u003e\n\nYou can determine whether an item exists in the current namespace via\n\n```js\nlocker.has('someKey'); // true or false\n// or\nlocker.namespace('foo').has('bar');\n\n// e.g.\nif (locker.has('user.authToken') ) {\n    // we're logged in\n} else {\n    // go to login page or something\n}\n```\n\n----------------------------\n\n\u003ch3 id=\"usage-removing-items-from-locker\"\u003eRemoving items from locker\u003c/h3\u003e\n\nThe simplest way to remove an item is to pass the key to the `forget()` method\n\n```js\nlocker.forget('keyToRemove');\n// or\nlocker.driver('session').forget('sessionKey');\n// etc..\n```\n\n\u003ch4 id=\"usage-removing-items-from-locker-removing-multiple-items-at-once\"\u003eremoving multiple items at once\u003c/h4\u003e\n\nYou can also pass an array.\n\n```js\nlocker.forget(['keyToRemove', 'anotherKeyToRemove', 'something', 'else']);\n```\n\n\u003ch4 id=\"usage-removing-items-from-locker-removing-all-within-namespace\"\u003eremoving all within namespace\u003c/h4\u003e\n\nyou can remove all the items within the currently set namespace via the `clean()` method\n\n```js\nlocker.clean();\n// or\nlocker.namespace('someOtherNamespace').clean();\n```\n\u003ch4 id=\"usage-removing-items-from-locker-removing-all-items-within-the-currently-set-storage-driver\"\u003eremoving all items within the currently set storage driver\u003c/h4\u003e\n\n```js\nlocker.empty();\n```\n\n----------------------------\n\n\u003ch3 id=\"usage-events\"\u003eEvents\u003c/h3\u003e\n\nThere are 3 events that can be fired during various operations, these are:\n\n```js\n// fired when a new item is added to storage\n$rootScope.$on('locker.item.added', function (e, payload) {\n    // payload is equal to:\n    {\n        driver: 'local', // the driver that was set when the event was fired\n        namespace: 'locker', // the namespace that was set when the event was fired\n        key: 'foo', // the key that was added\n        value: 'bar' // the value that was added\n    }\n});\n```\n\n```js\n// fired when an item is removed from storage\n$rootScope.$on('locker.item.forgotten', function (e, payload) {\n    // payload is equal to:\n    {\n        driver: 'local', // the driver that was set when the event was fired\n        namespace: 'locker', // the namespace that was set when the event was fired\n        key: 'foo', // the key that was removed\n    }\n});\n```\n\n```js\n// fired when an item's value changes to something new\n$rootScope.$on('locker.item.updated', function (e, payload) {\n    // payload is equal to:\n    {\n        driver: 'local', // the driver that was set when the event was fired\n        namespace: 'locker', // the namespace that was set when the event was fired\n        key: 'foo', // the key that was updated\n        oldValue: 'bar', // the value that was set before the item was updated\n        newValue: 'baz' // the new value that the item was updated to\n    }\n});\n```\n\n----------------------------\n\n\u003ch3 id=\"usage-binding-to-a-scope-property\"\u003eBinding to a $scope property\u003c/h3\u003e\n\nYou can bind a scope property to a key in storage. Whenever the $scope value changes, it will automatically be persisted in storage. e.g.\n\n```js\napp.controller('AppCtrl', ['$scope', function ($scope) {\n\n    locker.bind($scope, 'foo');\n\n    $scope.foo = ['bar', 'baz'];\n\n    locker.get('foo'); // = ['bar', 'baz']\n\n}]);\n```\n\nYou can also set a default value via the third parameter:\n\n```js\napp.controller('AppCtrl', ['$scope', function ($scope) {\n\n    locker.bind($scope, 'foo', 'someDefault');\n\n    $scope.foo; // = 'someDefault'\n\n    locker.get('foo'); // = 'someDefault'\n\n}]);\n```\n\nTo unbind the $scope property, simply use the unbind method:\n\n\n```js\napp.controller('AppCtrl', ['$scope', function ($scope) {\n\n    locker.unbind($scope, 'foo');\n\n    $scope.foo; // = undefined\n\n    locker.get('foo'); // = undefined\n\n}]);\n```\n\n----------------------------\n\n\n\u003ch2 id=\"browser-compatibility\"\u003eBrowser Compatibility\u003c/h2\u003e\n\nIE8 is not supported because I am utilising `Object.keys()`\n\nTo check if the browser natively supports local and session storage, you can do the following:\n\n```js\nif (! locker.supported()) {\n    // load a polyfill?\n}\n```\n\nI would recommend using [Remy's Storage polyfill](https://gist.github.com/remy/350433) if you want to support older browsers.\n\nFor the latest browser compatibility chart see [HERE](http://caniuse.com/namevalue-storage)\n\n\u003ch2 id=\"contributing\"\u003eContributing\u003c/h2\u003e\n\nTake care to maintain the existing coding style using the provided `.jscsrc` file. Add unit tests for any new or changed functionality. Lint and test your code using Gulp.\n\n\u003ch2 id=\"development\"\u003eDevelopment\u003c/h2\u003e\n\n```bash\n$ npm install\n$ gulp\n```\n\n\u003ch2 id=\"license\"\u003eLicense\u003c/h2\u003e\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Sean Tymon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","funding_links":[],"categories":["Storage"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftymondesigns%2Fangular-locker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftymondesigns%2Fangular-locker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftymondesigns%2Fangular-locker/lists"}