Skip to content

Commit

Permalink
release(v0.6.0): add config previousPrefix for backward compatibility…
Browse files Browse the repository at this point in the history
… and safe config changes, update README, provide better functions accessibility, minor fixes and code improvements
  • Loading branch information
DanielKucal committed May 26, 2017
1 parent 2067f93 commit 8968429
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 39 deletions.
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ This library adds decorators that make it super easy to *automagically* save and
+ `get(key: string)`: gets JSON-parsed data from HTML5 Storage
+ `set(key: string, value: any)`: sets data in HTML5 Storage
+ `remove(key: string)` removes variable with given key
+ `clear()`: clears Storage out of variables with set prefix
+ `keys`: getter for keys of stored values
+ `clear(clearType: 'decorators' | 'prefix' | 'all')`: clears Storage out of variables with set prefix
+ `config`: getter for module config
+ `keys`: getter for keys of values stored by ngx-store (determined by prefix and decorators)
+ `utility`: access to [WebStorageUtility](https://github.com/zoomsphere/angular2-localstorage/blob/aot/src/utility/webstorage-utility.ts) class for advanced stuff
- Objects read from Storage have added `.save()` method to easily force save of made changes (configurable by `mutateObjects`)
- saving support for all `Array` methods that change array object's value (configurable by `mutateObjects`)
- Easy configuration of what you want (see [#configuration](#configuration) section)
- Compatibility: either with AoT compiler and previous versions including `angular2-localstorage`

## Upcoming (TODO)
- Handle data saved with previous prefix after its change
- Encoding of saved data
- Tests coverage
- Cookies fallback
Expand Down Expand Up @@ -47,9 +48,10 @@ As this project uses decorating functions, it's important to provide custom conf
```html
<script>
var NGXSTORE_CONFIG = {
prefix: 'myApp.', // default: ngx_
clearType: 'prefix', // possible values: decorators, prefix, all
mutateObjects: true // defines whether Array methods shall be modified to handle changes automatically and .save() method shall be added to stored objects
prefix: 'myApp.', // default: ngx_, you can set it to '', however using prefix is recommended
clearType: 'prefix', // defines default clear() method behavior, possible values are: decorators, prefix, all
mutateObjects: true // defines whether Array methods shall be modified to handle changes automatically and .save() method shall be added to stored objects (can be troublesome for object comparisons)
previousPrefix: 'angular2ws_' // you have to set it only if you were using custom prefix in old version ('angular2ws_' is a default value)
};
</script>
```
Expand All @@ -58,7 +60,7 @@ As this project uses decorating functions, it's important to provide custom conf
plugins: [
new webpack.DefinePlugin({
NGXSTORE_CONFIG: JSON.stringify({
prefix: '' // etc
prefix: '', // etc
})
}),
]
Expand Down Expand Up @@ -149,5 +151,6 @@ As this project uses decorating functions, it's important to provide custom conf

**Note**: Please don't store circular structures as this library uses JSON.stringify to encode before using LocalStorage.

**Note**: When you change prefix from '' (empty string) old values won't be removed automatically to avoid deleting necessary data. You should handle it manually or set clearType to 'all'.

**Contributions are welcome!**
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-store",
"version": "0.5.4",
"version": "0.6.0",
"main": "./dist/index",
"typings": "./dist/index",
"description": "Angular decorator to save and restore class properties automatically from LocalStorage and SessionStorage.",
Expand All @@ -12,20 +12,20 @@
},
"repository": {
"type": "git",
"url": "[email protected]:zoomsphere/angular2-localstorage.git"
"url": "[email protected]:zoomsphere/ngx-store.git"
},
"keywords": [
"Angular2",
"LocalStorage",
"SessionStorage",
"Storage"
],
"author": "Marc J. Schmidt",
"author": "Daniel Kucal & Marc J. Schmidt",
"license": "ISC",
"bugs": {
"url": "https://github.com/zoomsphere/angular2-localstorage/issues"
"url": "https://github.com/zoomsphere/ngx-store/issues"
},
"homepage": "https://github.com/zoomsphere/angular2-localstorage",
"homepage": "https://github.com/zoomsphere/ngx-store",
"peerDependencies": {
"@angular/core": ">=2.3.0",
"core-js": "^2.4.1",
Expand Down
30 changes: 24 additions & 6 deletions src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
import { WebStorageConfigInterface } from './config.interface';
import { ConfigHelper } from './config.helper';

// TODO allow to set different config for local and session storage
// TODO check if NGXSTORE_CONFIG implements WebStorageConfigInterface
// TODO allow to set configuration in node-config (`config` on npm)

const DefaultConfig: WebStorageConfigInterface = {
prefix: 'angular2_ws', // TODO: change default to 'ngx_'
clearType: 'decorators', // TODO: change default to 'prefix'
mutateObjects: true
prefix: 'ngx_',
previousPrefix: 'angular2ws_',
clearType: 'prefix',
mutateObjects: true,
};

// TODO allow to set configuration in node-config (`config` on npm)
// take configuration provided as a global variable
declare const NGXSTORE_CONFIG: WebStorageConfigInterface;

let ConfigFills: WebStorageConfigInterface = {};
let localStoragePrefix = ConfigHelper.getItem('prefix');
if (localStoragePrefix) {
ConfigFills.previousPrefix = localStoragePrefix;
} else if (NGXSTORE_CONFIG && NGXSTORE_CONFIG.previousPrefix !== undefined) {
ConfigFills.previousPrefix = NGXSTORE_CONFIG.previousPrefix;
} else {
ConfigFills.previousPrefix = DefaultConfig.previousPrefix;
}

/**
* @deprecated define global variable `NGXSTORE_CONFIG` instead
*/
export const WEBSTORAGE_CONFIG = DefaultConfig;
export let WEBSTORAGE_CONFIG = DefaultConfig;

// merge default config, deprecated config and global config all together
export const Config = Object.assign({}, DefaultConfig, WEBSTORAGE_CONFIG, NGXSTORE_CONFIG);
export const Config: WebStorageConfigInterface =
Object.assign({}, DefaultConfig, WEBSTORAGE_CONFIG, NGXSTORE_CONFIG, ConfigFills);

ConfigHelper.setItem('prefix', Config.prefix);
5 changes: 2 additions & 3 deletions src/decorator/webstorage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { localStorageUtility, sessionStorageUtility } from '../utility';
import { LocalStorageService, SessionStorageService, WebStorageServiceInterface } from '../service/webstorage.service';
import { localStorageUtility, sessionStorageUtility } from '../utility';
import { WebStorageUtility } from '../utility/webstorage-utility';
import * as isEmpty from 'is-empty';
import { Config } from '../config';
import { WebStorageUtility } from '../utility/webstorage-utility';

export function LocalStorage(key?: string) {
return WebStorage(localStorageUtility, LocalStorageService, key);
Expand All @@ -29,7 +29,6 @@ function WebStorage(webStorageUtility: WebStorageUtility, service: WebStorageSer
};
}

// let proxy = WebStorageUtility.get(webStorageUtility, key);
let proxy = webStorageUtility.get(key);
service.keys.push(key);

Expand Down
32 changes: 17 additions & 15 deletions src/service/webstorage.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,39 @@ export interface WebStorageServiceInterface {
}

export abstract class WebStorageService {
public static keys: Array<string>;
public static decoratorKeys: Array<string>;

protected _webStorageUtility: WebStorageUtility;

public constructor(protected webStorageUtility: WebStorageUtility) {
this._webStorageUtility = webStorageUtility;
}
public constructor(public utility: WebStorageUtility) { }

/**
* Gets keys from child class
* Gets keys for stored variables created by ngx-store,
* ignores keys that have not been created by decorators and have no prefix at once
* @returns {Array<string>}
*/
public get keys(): Array<string> {
return (<WebStorageServiceInterface>this.constructor).keys;
// get prefixed key if prefix is defined
let prefixKeys = this.utility.keys.filter(key => {
return this.utility.prefix && key.startsWith(this.utility.prefix);
});
let decoratorKeys = (<WebStorageServiceInterface>this.constructor).keys;
return prefixKeys.concat(decoratorKeys);
}

public get config(): WebStorageConfigInterface {
return Config;
}

public get(key: string): any {
return this._webStorageUtility.get(key);
return this.utility.get(key);
}

public set(key: string, value: any): void {
return this._webStorageUtility.set(key, value);
return this.utility.set(key, value);
}

// TODO return true if item existed and false otherwise (?)
public remove(key: string): void {
return this._webStorageUtility.remove(key);
return this.utility.remove(key);
}

/**
Expand All @@ -59,17 +61,17 @@ export abstract class WebStorageService {
clearType = clearType || Config.clearType;
if (clearType === 'decorators') {
for (let key of this.keys) {
this._webStorageUtility.remove(key);
this.remove(key);
}
} else if (clearType === 'prefix') {
prefix = prefix || Config.prefix;
this._webStorageUtility.forEach((key) => {
this.utility.forEach((key) => {
if (key.startsWith(prefix)) {
this._webStorageUtility.remove(key);
this.remove(this.utility.trimPrefix(key));
}
});
} else if (clearType === 'all') {
this._webStorageUtility.clear();
this.utility.clear();
}
}
}
Expand Down
44 changes: 41 additions & 3 deletions src/utility/webstorage-utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export class WebStorageUtility {
protected _storage: Storage;

public static getSettable(value: any): string {
return typeof value === "string" ? value : JSON.stringify(value);
return typeof value === 'string' ? value : JSON.stringify(value);
}

public static getGettable(value: string): any {
Expand All @@ -18,6 +18,32 @@ export class WebStorageUtility {
public constructor(storage: Storage, prefix: string, previousPrefix?: string) {
this._storage = storage;
this._prefix = prefix;

// handle previousPrefix for backward-compatibility and safe config changes below
if (prefix === previousPrefix) return;
if (previousPrefix === null) return;
if (previousPrefix === undefined) return;
this.forEach(key => {
// ignore config settings when previousPrefix = ''
if (key.startsWith(previousPrefix) && !key.startsWith('NGX-STORE_')) {
let nameWithoutPrefix = this.trimPrefix(key);
this.set(nameWithoutPrefix, this._storage.getItem(key));

if (previousPrefix !== '') {
this._storage.removeItem(key);
}
}
});
}

public get prefix(): string {
return this._prefix;
}

public get keys(): Array<string> {
let keys = [];
this.forEach(key => keys.push(key));
return keys;
}

public getStorageKey(key: string): string {
Expand Down Expand Up @@ -47,9 +73,21 @@ export class WebStorageUtility {
this._storage.clear();
}

public forEach(func: Function) {
public forEach(func: (key: string, value: any) => any): void {
for (let key in this._storage) {
func(key, this._storage[key]);
func(key, this.getGettable(this._storage[key]));
}
}

public getSettable(value: any): string {
return WebStorageUtility.getSettable(value);
}

public getGettable(value: string): any {
return WebStorageUtility.getGettable(value);
}

public trimPrefix(key: string): string {
return key.replace(this.prefix, '');
}
}

0 comments on commit 8968429

Please sign in to comment.