diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 9125d46..4a8215f 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - node-version: [18.x, 20.x] + node-version: [18.x, 20.x, 22.x] steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index e74776a..4566d2f 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,60 @@ # Angular Storage -### Decorators and services for cookies, session- and localStorage -This library adds decorators that make it super easy to *automagically* save and restore variables using HTML5's `localStorage` and `sessionStorage`. It also provides Angular-Injectable Session- and LocalStorageService. +## Decorators and services for cookies, session- and localStorage + +This library adds decorators that make it super easy to *automagically* save and restore variables using HTML5's `localStorage` and `sessionStorage`. It also provides Angular-Injectable Session- and LocalStorageService. ## What's included? + - Decorator functions that are pretty easy to use and configure (see [Decorators config](#decorators-config)): - + `@LocalStorage()` - to save variable in HTML5 localStorage - + `@SessionStorage()` - to save variable in HTML5 sessionStorage - + `@CookieStorage()` - to save variable as a cookie - + `@SharedStorage()` - to keep variable in temporary memory that can be shared across classes - + `@TempStorage()` - alias for `SharedStorage` + - `@LocalStorage()` - to save variable in HTML5 localStorage + - `@SessionStorage()` - to save variable in HTML5 sessionStorage + - `@CookieStorage()` - to save variable as a cookie + - `@SharedStorage()` - to keep variable in temporary memory that can be shared across classes + - `@TempStorage()` - alias for `SharedStorage` - Injectable `LocalStorageService`, `SessionStorageService`, `CookiesStorageService` and `SharedStorageService` ([read more here](src/service#angular-storage)) - Possibility of [listening to storage changes](https://github.com/zoomsphere/ngx-store/tree/master/src/service#listening-to-changes) - Easy configuration (see [#configuration](#configuration) section) - Compatibility with: - + all previous versions - + Angular AoT compiler - + `angular2-localstorage` - + [nativescript-localstorage](https://github.com/NathanaelA/nativescript-localstorage) - + Angular v2, 4 and 5 - + your own project! + - all previous versions + - Angular AoT compiler + - `angular2-localstorage` + - [nativescript-localstorage](https://github.com/NathanaelA/nativescript-localstorage) + - Angular v2, 4 and 5 + - your own project! - Tests coverage -## CHANGELOG +### CHANGELOG + #### v8.0.0 - support for Angular 17 + #### v7.0.0 - support for Angular 16 + #### v6.0.0 - support for Angular 15 + #### v4.0.0 - support for Angular 10 + #### v3.0.0 - support for Angular 9 Version from Zoomsphere #### v2.1.0 - support for Angular 7 & TypeScript 3 + #### v2.0.0 - support for Angular 6 (RxJS v6) + #### v1.4.x + - standardized behavior for: - - more than 1 decorator, e.g. in `@LocalStorage() @CookieStorage() variable: any;` `CookieStorage` (decorator closer to variable) has higher priority, hence the value will be read from cookies only. The cookie value will be saved in `localStorage` regardless of its content to keep consistency. - - `WebStorageService.clear('all')` - now will remove everything except `ngx-store`'s config (stored in `localStorage`) + - more than 1 decorator, e.g. in `@LocalStorage() @CookieStorage() variable: any;` `CookieStorage` (decorator closer to variable) has higher priority, hence the value will be read from cookies only. The cookie value will be saved in `localStorage` regardless of its content to keep consistency. + - `WebStorageService.clear('all')` - now will remove everything except `ngx-store`'s config (stored in `localStorage`) - removed deprecated (since v0.5) `WEBSTORAGE_CONFIG` - `@SharedStorage` has now alias `@TempStorage` - introduced [builder pattern](https://github.com/zoomsphere/ngx-store/tree/master/src/service#builder-pattern) - added unit tests coverage - fixes for storage events - ## Upcoming (TODO) + - Storage events for keys removed from outside - Tests for storage events (accepting PRs) - Accepting Moment's instances as expiration date (accepting PRs) @@ -54,10 +64,11 @@ Version from Zoomsphere - Take configuration from [npm config](https://www.npmjs.com/package/config)'s file (?) - Automatically handle all data manipulations using [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) (ES6) - ## Installation + 1. Download the library: `npm i ngx-store --save` or `npm i ngx-store@RC` for latest version 2. Import the WebStorageModule in your `app.module.ts`: + ```typescript import { NgModule } from '@angular/core'; import { WebStorageModule } from 'ngx-store'; @@ -70,22 +81,25 @@ Version from Zoomsphere export class AppModule {} ``` - ## Configuration + Things you should take into consideration while configuring this module: + - Decorated objects have added `.save()` method to easily force save of made changes (configurable by `mutateObjects`) - Support for all `Array` methods that change array object's value can be disabled (configurable by `mutateObjects`) - Object mutation can be troublesome for object comparisons, so you can configure this feature for single field passing [decorator config](#decorators-config) - You may not use prefix (by setting it to `''`), however we recommend to use it, as it helps avoid conflicts with other libraries (configurable by `prefix`) - There are 3 ways to clear ngx-stored data: - + `'all'` - completely clears current Storage - + `'prefix'` - removes all variables prefixed by ngx-store - + `'decorators'` - removes only variables created by decorating functions (useful when not using prefix) + - `'all'` - completely clears current Storage + - `'prefix'` - removes all variables prefixed by ngx-store + - `'decorators'` - removes only variables created by decorating functions (useful when not using prefix) Default behaviour is specified by setting `clearType`, but it's possible to pass this parameter directly into service `clear()` method. - Examples for `cookiesScope` can be found in [this comment](https://github.com/zoomsphere/ngx-store/blob/master/src/utility/storage/cookies-storage.ts#L125) As this project uses decorating functions, it is important to provide custom configuration in global variable named `NGXSTORE_CONFIG` before Angular application load. Here are some ways to do it: + 1. Add ` ``` + 2. If you use webpack, you can provide global variable in your `webpack.js` file this way: + ```javascript plugins: [ new webpack.DefinePlugin({ @@ -110,16 +126,18 @@ As this project uses decorating functions, it is important to provide custom con ] ``` - ## Decorators config + Decorating functions can take config object with the following fields: + - `key: string` - key under the variable will be stored, default key is the variable name - `mutate: boolean` - enable or disable object mutation for instance, default depends on global config - `expires: Date` - for `@CookieStorage()` only, specifies expiration date, null = lifetime cookie - ## Usage + 1. Pretty easy to use decorators. Here is where the real magic happens. + ```typescript import { CookieStorage, LocalStorage, SessionStorage } from 'ngx-store'; @@ -148,6 +166,7 @@ Decorating functions can take config object with the following fields: ``` **Sharing variables across classes:** Decorated variables can be easily shared across different classes, e.g. Angular Components (also after their destruction) without need to create new service for this purpose. + ```typescript import { LocalStorage, SharedStorage } from 'ngx-store'; @@ -175,6 +194,7 @@ Decorating functions can take config object with the following fields: ``` **Force save changes:** If you need to modify stored object by not a direct assignment, then you can take advantage of `.save()` method to force save made changes. Example: + ```typescript import { CookieStorage, LocalStorage, SessionStorage, WebstorableArray } from 'ngx-store'; @@ -201,6 +221,7 @@ Decorating functions can take config object with the following fields: ``` **Limited lifecycle classes in AoT compilation:** There is a special case when Service or Component in your application containing decorated variable is being destroyed: + ```typescript import { OnDestroy } from '@angular/core'; import { LocalStorage } from 'ngx-store'; @@ -213,6 +234,7 @@ Decorating functions can take config object with the following fields: ``` 2. Use the [services](src/service#angular-storage) to manage your data: + ```typescript import { CookiesStorageService, LocalStorageService, SessionStorageService, SharedStorageService } from 'ngx-store'; diff --git a/package-lock.json b/package-lock.json index ad02673..e0d323a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "lodash.set": "^4.3.2", "rxjs": "^7.8.1", "ts-debug": "^1.3.0", - "tslib": "^2.6.2", + "tslib": "^2.8.1", "zone.js": "^0.15.0" }, "devDependencies": { @@ -35,7 +35,7 @@ "@types/lodash.isequal": "^4.5.8", "@types/lodash.merge": "^4.6.9", "@types/lodash.set": "^4.3.9", - "@types/node": "^20.10.3", + "@types/node": "^22.10.5", "codelyzer": "^6.0.2", "jasmine-core": "^4.6.0", "jasmine-spec-reporter": "^7.0.0", @@ -45,12 +45,12 @@ "karma-jasmine": "^5.1.0", "karma-jasmine-html-reporter": "^2.1.0", "ng-packagr": "^19.0.1", - "ts-node": "^10.9.1", + "ts-node": "^10.9.2", "tslint": "^6.1.3", "typescript": "^5.6.3" }, "engines": { - "node": ">= 18", + "node": ">= 18.19.1", "npm": ">= 8" } }, @@ -5425,7 +5425,8 @@ "version": "4.6.4", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.6.4.tgz", "integrity": "sha512-qCw5sVW+ylTnrEhe5kfX4l6MgU9REXIVDa/lWEcvTOUmd+LqDYwyjovDq+Zk9blElaEHOj1URDQ/djEBVRf+pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -5483,12 +5484,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "22.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", + "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/@types/node-forge": { @@ -9497,10 +9499,11 @@ } }, "node_modules/jasmine-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", - "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", - "dev": true + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", + "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", + "dev": true, + "license": "MIT" }, "node_modules/jasmine-spec-reporter": { "version": "7.0.0", @@ -9641,10 +9644,11 @@ "license": "MIT" }, "node_modules/karma": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", - "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.4.tgz", + "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, + "license": "MIT", "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -9665,7 +9669,7 @@ "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.4.1", + "socket.io": "^4.7.2", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", @@ -10552,7 +10556,7 @@ "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/log-update/node_modules/strip-ansi": { @@ -11340,15 +11344,10 @@ "dev": true, "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "p-limit": "^2.2.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, "node_modules/ng-packagr/node_modules/find-up": { @@ -14380,10 +14379,11 @@ "integrity": "sha512-sP9Q4Nfqu5ImWLH955PpxbjR2zgLWS3NIc2tCw/JZtZMFFxUZe3fvkhdA0vSIpjiGFKPwCg6v0drthjwnSQTGA==" }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -14588,10 +14588,11 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", diff --git a/package.json b/package.json index 9fe0c77..b572bef 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "lodash.set": "^4.3.2", "rxjs": "^7.8.1", "ts-debug": "^1.3.0", - "tslib": "^2.6.2", + "tslib": "^2.8.1", "zone.js": "^0.15.0" }, "devDependencies": { @@ -63,7 +63,7 @@ "@types/lodash.isequal": "^4.5.8", "@types/lodash.merge": "^4.6.9", "@types/lodash.set": "^4.3.9", - "@types/node": "^20.10.3", + "@types/node": "^22.10.5", "codelyzer": "^6.0.2", "jasmine-core": "^4.6.0", "jasmine-spec-reporter": "^7.0.0", @@ -73,13 +73,13 @@ "karma-jasmine": "^5.1.0", "karma-jasmine-html-reporter": "^2.1.0", "ng-packagr": "^19.0.1", - "ts-node": "^10.9.1", + "ts-node": "^10.9.2", "tslint": "^6.1.3", "typescript": "^5.6.3" }, "//": "\"engineStrict\": false,", "engines": { - "node": ">= 18", + "node": ">= 18.19.1", "npm": ">= 8" } } \ No newline at end of file diff --git a/projects/ngx-store/package.json b/projects/ngx-store/package.json index 38e026e..1b99fb9 100644 --- a/projects/ngx-store/package.json +++ b/projects/ngx-store/package.json @@ -12,8 +12,8 @@ "access": "public" }, "peerDependencies": { - "@angular/common": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "@angular/core": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + "@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0", + "@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "dependencies": { "lodash.get": "^4.4.2",