├── license-banner.txt ├── .gitignore ├── src ├── enums │ └── cache-storages.enum.ts ├── ng2-cache.module.ts ├── interfaces │ ├── storage-value.interface.ts │ └── cache-options.interface.ts ├── ng2-cache.ts └── services │ ├── storage │ ├── memory │ │ └── cache-memory.service.ts │ ├── cache-storage-abstract.service.ts │ ├── local-storage │ │ └── cache-local-storage.service.ts │ └── session-storage │ │ └── cache-session-storage.service.ts │ └── cache.service.ts ├── ng2-cache.ts ├── public_api.ts ├── .travis.yml ├── tslint.json ├── rollup.es.config.js ├── tsconfig.json ├── LICENSE ├── tsconfig-build.json ├── rollup.config.js ├── package.json ├── CHANGELOG.md └── README.md /license-banner.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @license ng2-cache 3 | * MIT license 4 | */ 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | $ cat .gitignore 2 | /node_modules 3 | /dist 4 | /documentation 5 | /coverage 6 | 7 | *.log 8 | *.tgz 9 | -------------------------------------------------------------------------------- /src/enums/cache-storages.enum.ts: -------------------------------------------------------------------------------- 1 | export const enum CacheStoragesEnum { 2 | LOCAL_STORAGE, 3 | SESSION_STORAGE, 4 | MEMORY 5 | } 6 | -------------------------------------------------------------------------------- /src/ng2-cache.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule} from '@angular/core'; 2 | import { CacheService } from './services/cache.service'; 3 | 4 | @NgModule({ 5 | providers: [ CacheService ] 6 | }) 7 | export class Ng2CacheModule {} 8 | -------------------------------------------------------------------------------- /ng2-cache.ts: -------------------------------------------------------------------------------- 1 | // This file is not used to build the module. It is only used during editing 2 | // by the TypeScript language service and during build for verification. `ngc` 3 | // replaces this file with production ng2-cache.ts when it rewrites 4 | // private symbol names. 5 | 6 | export * from './public_api'; 7 | -------------------------------------------------------------------------------- /src/interfaces/storage-value.interface.ts: -------------------------------------------------------------------------------- 1 | import {CacheOptionsInterface} from './cache-options.interface'; 2 | 3 | export interface StorageValueInterface { 4 | 5 | /** 6 | * Cached data 7 | */ 8 | value: any; 9 | 10 | /** 11 | * Cached options 12 | */ 13 | options: CacheOptionsInterface; 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/cache-options.interface.ts: -------------------------------------------------------------------------------- 1 | export interface CacheOptionsInterface { 2 | 3 | /** 4 | * Expires timestamp 5 | */ 6 | expires?: number; 7 | 8 | /** 9 | * Max age in seconds 10 | */ 11 | maxAge?: number; 12 | 13 | /** 14 | * Tag for this key 15 | */ 16 | tag?: string; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /public_api.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Angular library starter 3 | * Build an Angular library compatible with AoT compilation & Tree shaking like an official package 4 | * Copyright Roberto Simonetti 5 | * MIT license 6 | * https://github.com/robisim74/angular-library-starter 7 | */ 8 | 9 | /** 10 | * Entry point for all public APIs of the package. 11 | */ 12 | export * from './src/ng2-cache'; 13 | 14 | // This file only reexports content of the `src` folder. Keep it that way. 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | addons: 4 | apt: 5 | sources: 6 | - google-chrome 7 | packages: 8 | - google-chrome-stable 9 | language: node_js 10 | node_js: 11 | - "8" 12 | before_install: 13 | - npm i npm@^4 -g 14 | install: 15 | - npm install 16 | script: 17 | - npm test 18 | - npm run build 19 | before_script: 20 | - export DISPLAY=:99.0 21 | - sh -e /etc/init.d/xvfb start 22 | - sleep 3 23 | notifications: 24 | email: false 25 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-angular" 4 | ], 5 | "rules": { 6 | "directive-selector": [ 7 | true, 8 | "attribute", 9 | [ 10 | "dir-prefix1", 11 | "dir-prefix2" 12 | ], 13 | "camelCase" 14 | ], 15 | "component-selector": [ 16 | true, 17 | "element", 18 | [ 19 | "cmp-prefix1", 20 | "cmp-prefix2" 21 | ], 22 | "kebab-case" 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /rollup.es.config.js: -------------------------------------------------------------------------------- 1 | import sourcemaps from 'rollup-plugin-sourcemaps'; 2 | import license from 'rollup-plugin-license'; 3 | 4 | const path = require('path'); 5 | 6 | export default { 7 | output: { 8 | format: 'es', 9 | sourcemap: true 10 | }, 11 | plugins: [ 12 | sourcemaps(), 13 | license({ 14 | sourceMap: true, 15 | 16 | banner: { 17 | file: path.join(__dirname, 'license-banner.txt'), 18 | encoding: 'utf-8', 19 | } 20 | }) 21 | ], 22 | onwarn: () => { return } 23 | } 24 | -------------------------------------------------------------------------------- /src/ng2-cache.ts: -------------------------------------------------------------------------------- 1 | export {CacheService} from './services/cache.service'; 2 | export {CacheStorageAbstract} from './services/storage/cache-storage-abstract.service'; 3 | export {CacheStoragesEnum} from './enums/cache-storages.enum'; 4 | export {CacheLocalStorage} from './services/storage/local-storage/cache-local-storage.service'; 5 | export {CacheMemoryStorage} from './services/storage/memory/cache-memory.service'; 6 | export {CacheOptionsInterface} from './interfaces/cache-options.interface'; 7 | export {CacheSessionStorage} from 8 | './services/storage/session-storage/cache-session-storage.service'; 9 | export {Ng2CacheModule} from './ng2-cache.module'; 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "strict": true, 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "rootDir": ".", 10 | "sourceMap": true, 11 | "inlineSources": true, 12 | "target": "es5", 13 | "skipLibCheck": true, 14 | "lib": [ 15 | "es2015", 16 | "dom" 17 | ], 18 | "typeRoots": [ 19 | "node_modules/@types/" 20 | ] 21 | }, 22 | "exclude": [ 23 | "node_modules" 24 | ] 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 ng2-cache team 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /src/services/storage/memory/cache-memory.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {CacheStorageAbstract} from '../cache-storage-abstract.service'; 3 | import {CacheStoragesEnum} from '../../../enums/cache-storages.enum'; 4 | import {StorageValueInterface} from '../../../interfaces/storage-value.interface'; 5 | 6 | /** 7 | * Service for storing data in local storage 8 | */ 9 | @Injectable() 10 | export class CacheMemoryStorage extends CacheStorageAbstract { 11 | 12 | private _data: {[key: string]: any} = {}; 13 | 14 | public getItem(key: string) { 15 | return this._data[key] ? this._data[key] : null; 16 | } 17 | 18 | public setItem(key: string, value: StorageValueInterface) { 19 | this._data[key] = value; 20 | return true; 21 | } 22 | 23 | public removeItem(key: string) { 24 | delete this._data[key]; 25 | } 26 | 27 | public clear() { 28 | this._data = []; 29 | } 30 | 31 | public type() { 32 | return CacheStoragesEnum.MEMORY; 33 | } 34 | 35 | public isEnabled() { 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tsconfig-build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "baseUrl": ".", 5 | "paths": { 6 | "@angular/*": [ 7 | "node_modules/@angular/*" 8 | ] 9 | }, 10 | "outDir": "dist", 11 | "declaration": true, 12 | "strict": true, 13 | "moduleResolution": "node", 14 | "module": "es2015", 15 | "target": "es2015", 16 | "lib": [ 17 | "es2015", 18 | "dom" 19 | ], 20 | "skipLibCheck": true, 21 | "types": [], 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "sourceMap": true, 25 | "inlineSources": true 26 | }, 27 | "files": [ 28 | "public_api.ts", 29 | "node_modules/zone.js/dist/zone.js.d.ts" 30 | ], 31 | "angularCompilerOptions": { 32 | "skipTemplateCodegen": true, 33 | "annotateForClosureCompiler": true, 34 | "strictMetadataEmit": true, 35 | "flatModuleOutFile": "ng2-cache.js", 36 | "flatModuleId": "ng2-cache" 37 | } 38 | } -------------------------------------------------------------------------------- /src/services/storage/cache-storage-abstract.service.ts: -------------------------------------------------------------------------------- 1 | import {CacheStoragesEnum} from '../../enums/cache-storages.enum'; 2 | import {StorageValueInterface} from '../../interfaces/storage-value.interface'; 3 | 4 | /** 5 | * Abstract cache storage 6 | */ 7 | export abstract class CacheStorageAbstract { 8 | 9 | /** 10 | * Get item from storage 11 | * @param key 12 | */ 13 | public abstract getItem(key: string): StorageValueInterface; 14 | 15 | /** 16 | * Set item to storage 17 | * @param key 18 | * @param value 19 | */ 20 | public abstract setItem(key: string, value: StorageValueInterface): boolean; 21 | 22 | /** 23 | * Remove item from storage 24 | * @param key 25 | */ 26 | public abstract removeItem(key: string): void; 27 | 28 | /** 29 | * Clear item in storage 30 | */ 31 | public abstract clear(): void; 32 | 33 | /** 34 | * Get current storage type 35 | */ 36 | public abstract type(): CacheStoragesEnum; 37 | 38 | /** 39 | * Check if storage is enabled 40 | */ 41 | public abstract isEnabled(): boolean; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/services/storage/local-storage/cache-local-storage.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {CacheStorageAbstract} from '../cache-storage-abstract.service'; 3 | import {CacheStoragesEnum} from '../../../enums/cache-storages.enum'; 4 | import {StorageValueInterface} from '../../../interfaces/storage-value.interface'; 5 | 6 | /** 7 | * Service for storing data in local storage 8 | */ 9 | @Injectable() 10 | export class CacheLocalStorage extends CacheStorageAbstract { 11 | 12 | public getItem(key: string) { 13 | const value = localStorage.getItem(key); 14 | return value ? JSON.parse(value) : null; 15 | } 16 | 17 | public setItem(key: string, value: StorageValueInterface) { 18 | try { 19 | localStorage.setItem(key, JSON.stringify(value)); 20 | return true; 21 | } catch (e) { 22 | return false; 23 | } 24 | } 25 | 26 | public removeItem(key: string) { 27 | localStorage.removeItem(key); 28 | } 29 | 30 | public clear() { 31 | localStorage.clear(); 32 | } 33 | 34 | public type() { 35 | return CacheStoragesEnum.LOCAL_STORAGE; 36 | } 37 | 38 | public isEnabled() { 39 | try { 40 | localStorage.setItem('test', 'test'); 41 | localStorage.removeItem('test'); 42 | return true; 43 | } catch (e) { 44 | return false; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/services/storage/session-storage/cache-session-storage.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {CacheStorageAbstract} from '../cache-storage-abstract.service'; 3 | import {CacheStoragesEnum} from '../../../enums/cache-storages.enum'; 4 | import {StorageValueInterface} from '../../../interfaces/storage-value.interface'; 5 | 6 | /** 7 | * Service for storing data in session storage 8 | */ 9 | @Injectable() 10 | export class CacheSessionStorage extends CacheStorageAbstract { 11 | 12 | public getItem(key: string) { 13 | let value = sessionStorage.getItem(key); 14 | return value ? JSON.parse(value) : null; 15 | } 16 | 17 | public setItem(key: string, value: StorageValueInterface) { 18 | try { 19 | sessionStorage.setItem(key, JSON.stringify(value)); 20 | return true; 21 | } catch (e) { 22 | return false; 23 | } 24 | } 25 | 26 | public removeItem(key: string) { 27 | sessionStorage.removeItem(key); 28 | } 29 | 30 | public clear() { 31 | sessionStorage.clear(); 32 | } 33 | 34 | public type() { 35 | return CacheStoragesEnum.SESSION_STORAGE; 36 | } 37 | 38 | public isEnabled() { 39 | try { 40 | sessionStorage.setItem('test', 'test'); 41 | sessionStorage.removeItem('test'); 42 | return true; 43 | } catch (e) { 44 | return false; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import sourcemaps from 'rollup-plugin-sourcemaps'; 3 | 4 | /** 5 | * Add here external dependencies that actually you use. 6 | * 7 | * Angular dependencies 8 | * - '@angular/animations' => 'ng.animations' 9 | * - '@angular/animations/browser': 'ng.animations.browser' 10 | * - '@angular/common' => 'ng.common' 11 | * - '@angular/compiler' => 'ng.compiler' 12 | * - '@angular/core' => 'ng.core' 13 | * - '@angular/forms' => 'ng.forms' 14 | * - '@angular/common/http' => 'ng.common.http' 15 | * - '@angular/platform-browser-dynamic' => 'ng.platformBrowserDynamic' 16 | * - '@angular/platform-browser' => 'ng.platformBrowser' 17 | * - '@angular/platform-browser/animations' => 'ng.platformBrowser.animations' 18 | * - '@angular/platform-server' => 'ng.platformServer' 19 | * - '@angular/router' => 'ng.router' 20 | * 21 | * RxJS dependencies 22 | * Each RxJS functionality that you use in the library must be added as external dependency. 23 | * - For main classes use 'Rx': 24 | * e.g. import { Observable } from 'rxjs/Observable'; => 'rxjs/Observable': 'Rx' 25 | * - For observable methods use 'Rx.Observable': 26 | * e.g. import 'rxjs/add/observable/merge'; => 'rxjs/add/observable/merge': 'Rx.Observable' 27 | * or for lettable operators: 28 | * e.g. import { merge } from 'rxjs/observable/merge'; => 'rxjs/observable/merge': 'Rx.Observable' 29 | * - For operators use 'Rx.Observable.prototype': 30 | * e.g. import 'rxjs/add/operator/map'; => 'rxjs/add/operator/map': 'Rx.Observable.prototype' 31 | * or for lettable operators: 32 | * e.g. import { map } from 'rxjs/operators'; => 'rxjs/operators': 'Rx.Observable.prototype' 33 | * 34 | * Other dependencies 35 | * - Angular libraries: refer to their global namespace 36 | * - TypeScript/JavaScript libraries: 37 | * e.g. lodash: 'lodash' => 'lodash' 38 | * 39 | * Also, if the dependency uses CommonJS modules, such as lodash, 40 | * you should also use a plugin like rollup-plugin-commonjs, 41 | * to explicitly specify unresolvable "named exports". 42 | * 43 | */ 44 | const globals = { 45 | '@angular/core': 'ng.core', 46 | '@angular/common': 'ng.common', 47 | 'rxjs/Observable': 'Rx', 48 | 'rxjs/Observer': 'Rx' 49 | }; 50 | 51 | export default { 52 | external: Object.keys(globals), 53 | plugins: [resolve(), sourcemaps()], 54 | onwarn: () => { return }, 55 | output: { 56 | format: 'umd', 57 | name: 'ng.angularLibraryStarter', 58 | globals: globals, 59 | sourcemap: true, 60 | exports: 'named', 61 | amd: { id: 'ng2-cache' } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng2-cache", 3 | "version": "0.2.1", 4 | "description": "Client side caching for Angular5", 5 | "main": "./bundles/ng2-cache.umd.js", 6 | "module": "./esm5/ng2-cache.js", 7 | "es2015": "./esm2015/ng2-cache.js", 8 | "scripts": { 9 | "build": "node build.js", 10 | "pack:lib": "npm run build && npm pack ./dist", 11 | "publish:lib": "npm run build && npm publish ./dist", 12 | "publish:lib:next": "npm run build && npm publish --tag next ./dist", 13 | "compodoc": "compodoc -p tsconfig.json", 14 | "compodoc:serve": "compodoc -s" 15 | }, 16 | "typings": "./ng2-cache.d.ts", 17 | "author": "", 18 | "contributors": [ 19 | { 20 | "name": "Jackson88", 21 | "url": "https://github.com/Jackson88/" 22 | }, 23 | { 24 | "name": "Paritosh Patel", 25 | "email": "13868399+paritosh64ce@users.noreply.github.com", 26 | "url": "https://simplyfyingtechblog.wordpress.com" 27 | } 28 | ], 29 | "repository": { 30 | "type": "git", 31 | "url": "git+ssh://git@github.com:Jackson88/ng2-cache.git" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/Jackson88/ng2-cache/issues" 35 | }, 36 | "homepage": "https://github.com/Jackson88/ng2-cache", 37 | "keywords": [ 38 | "cache", 39 | "angular2", 40 | "angular5", 41 | "client-side", 42 | "caching" 43 | ], 44 | "license": "MIT", 45 | "dependencies": { 46 | "tslib": "^1.7.1" 47 | }, 48 | "peerDependencies": { 49 | "@angular/common": ">= 5.0.0", 50 | "@angular/core": ">= 5.0.0" 51 | }, 52 | "devDependencies": { 53 | "@angular/animations": "5.0.0", 54 | "@angular/common": "5.0.0", 55 | "@angular/compiler": "5.0.0", 56 | "@angular/compiler-cli": "5.0.0", 57 | "@angular/core": "5.0.0", 58 | "@angular/platform-browser": "5.0.0", 59 | "@angular/platform-browser-dynamic": "5.0.0", 60 | "@angular/platform-server": "5.0.0", 61 | "@compodoc/compodoc": "1.0.3", 62 | "@types/jasmine": "2.6.2", 63 | "@types/node": "8.0.47", 64 | "chalk": "2.3.0", 65 | "codelyzer": "4.0.2", 66 | "core-js": "2.5.1", 67 | "istanbul-instrumenter-loader": "3.0.0", 68 | "jasmine-core": "2.8.0", 69 | "karma": "1.7.1", 70 | "karma-chrome-launcher": "2.2.0", 71 | "karma-coverage-istanbul-reporter": "1.3.0", 72 | "karma-jasmine": "1.1.0", 73 | "karma-sourcemap-loader": "0.3.7", 74 | "karma-spec-reporter": "0.0.31", 75 | "karma-webpack": "2.0.5", 76 | "reflect-metadata": "0.1.10", 77 | "rollup": "0.50.0", 78 | "rollup-plugin-license": "0.6.0", 79 | "rollup-plugin-node-resolve": "3.0.0", 80 | "rollup-plugin-sourcemaps": "0.4.2", 81 | "rxjs": "5.5.2", 82 | "shelljs": "0.7.8", 83 | "source-map-loader": "0.2.3", 84 | "ts-loader": "3.1.1", 85 | "tslint": "5.8.0", 86 | "tslint-angular": "1.0.0", 87 | "typescript": "2.4.2", 88 | "uglify-js": "3.1.6", 89 | "webpack": "3.8.1", 90 | "zone.js": "0.8.18" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## ng2-cache library Changelog 2 | 3 | 4 | ### 0.2.0 5 | 6 | ## What changed 7 | 8 | - Used [angular-library-starter](https://github.com/robisim74/angular-library-starter/) as base. 9 | - Removed test cases related files from the base. 10 | - Code comment updated at some places to avoid `tslint` errors. No implementation code is updated. 11 | - To build, simple run `npm run publish:lib`. Files will be generated inside `/dist` folder as per `Angular Package` standard. 12 | - To consume `ng2-cache`, nothing changes. Removed the need to import `ng2-cache` inside `tsconfig.json` 13 | 14 | 15 | 16 | 17 | ### 0.1.12 18 | 19 | ## What changed 20 | 21 | The library is created as separate Angular module. 22 | 23 | After installing `npm install ng2-cache --save` 24 | 25 | 1. Import it in your main app module 26 | ``` 27 | @NgModule({ 28 | declarations: [ 29 | .... 30 | ], 31 | imports: [ 32 | .... 33 | Ng2CacheModule 34 | ], 35 | providers: [], 36 | bootstrap: [AppComponent] 37 | }) 38 | export class AppModule { } 39 | ``` 40 | 41 | 2. Use it inside your `Component` by DI 42 | 43 | ```` 44 | ... 45 | import { CacheService, CacheStoragesEnum } from 'ng2-cache'; 46 | ... 47 | 48 | export class AppComponent { 49 | 50 | constructor(private _cacheService: CacheService) { 51 | this._cacheService.set('key', ['some data']); 52 | } 53 | ```` 54 | 55 | 3. You might need to import it in yout tsconfig.json file 56 | 57 | ```` 58 | "include": [ 59 | "src/**/*", 60 | "node_modules/ng2-cache" 61 | ] 62 | ```` 63 | You'll need to import the same way in your tsconfig.spec.json if you are running test cases with karma/jasmine. 64 | 65 | 66 | # 0.1.11 67 | 68 | ## ng2-cache 69 | 70 | Client side caching service for Angular2 71 | 72 | ## Installation 73 | 74 | To install this library, run: 75 | 76 | ```bash 77 | $ npm install ng2-cache --save 78 | ``` 79 | 80 | Usage: 81 | 82 | ```typescript 83 | 84 | import {Component} from '@angular/core'; 85 | import {CacheService, CacheStoragesEnum} from 'ng2-cache/ng2-cache'; 86 | 87 | declare var BUILD_VERSION: string; 88 | 89 | @Component({ 90 | selector: 'some-selector', 91 | template: '
Template
', 92 | providers: [ CacheService ] 93 | }) 94 | export class ExampleComponent { 95 | 96 | constructor(private _cacheService: CacheService) {} 97 | 98 | public func() { 99 | 100 | //set global prefix as build version 101 | this._cacheService.setGlobalPrefix(BUILD_VERSION); 102 | 103 | //put some data to cache "forever" 104 | //returns true is data was cached successfully, otherwise - false 105 | let result: boolean = this._cacheService.set('key', ['some data']); 106 | 107 | //put some data to cache for 5 minutes (maxAge - in seconds) 108 | this._cacheService.set('key', ['some data'], {maxAge: 5 * 60}); 109 | 110 | //put some data to cache for 1 hour (expires - timestamp with milliseconds) 111 | this._cacheService.set('key', {'some': 'data'}, {expires: Date.now() + 1000 * 60 * 60}); 112 | 113 | //put some data to cache with tag "tag" 114 | this._cacheService.set('key', 'some data', {tag: 'tag'}); 115 | 116 | //get some data by key, null - if there is no data or data has expired 117 | let data: any|null = this._cacheService.get('key'); 118 | 119 | //check if data exists in cache 120 | let exists: boolean = this._cacheService.exists('key'); 121 | 122 | //remove all data from cache with tag "tag" 123 | this._cacheService.removeTag('tag'); 124 | 125 | //remove all from cache 126 | this._cacheService.removeAll(); 127 | 128 | //get all data related to tag "tag" : 129 | // {'key' => 'key data', ...} 130 | this._cacheService.getTagData('tag'); 131 | 132 | //change storage (returns new instance of service with needed storage) 133 | this._cacheService.useStorage(CacheStoragesEnum.LOCAL_STORAGE); 134 | 135 | } 136 | } 137 | 138 | ``` 139 | 140 | By default service store data in session storage, you could select one of storages: 141 | - session storage 142 | - local storage 143 | - memory 144 | 145 | If current storage is not available - service will choose memory storage. 146 | 147 | To change storage to local storage: 148 | 149 | ```typescript 150 | 151 | import {Component, provide} from 'angular2/core'; 152 | import {CacheService, CacheStorageAbstract, CacheLocalStorage} from 'ng2-cache/ng2-cache'; 153 | 154 | @Component({ 155 | selector: 'some-selector', 156 | template: '
Template
', 157 | providers: [ 158 | CacheService, 159 | {provide: CacheStorageAbstract, useClass:CacheLocalStorage} 160 | ] 161 | }) 162 | 163 | ``` 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ng2-cache 2 | ============== 3 | [![npm](https://img.shields.io/npm/dm/ng2-cache.svg)](https://www.npmjs.com/package/ng2-cache) 4 | [![npm](https://img.shields.io/npm/dt/ng2-cache.svg)](https://www.npmjs.com/package/ng2-cache) 5 | 6 | 7 | >ng2-cache library compatible with AoT compilation & Tree shaking like an official package. 8 | 9 | This lib allows you to use ng2-cache library for **Angular v5** apps written in _TypeScript_, _ES6_ or _ES5_. 10 | The project is based on the official _Angular_ packages. 11 | 12 | Get the [Changelog](./CHANGELOG.md). 13 | 14 | ## How to use 15 | 16 | 1. `npm install ng2-cache --save` 17 | 2. Import it in your main app module 18 | ``` 19 | @NgModule({ 20 | declarations: [ 21 | .... 22 | ], 23 | imports: [ 24 | .... 25 | Ng2CacheModule 26 | ], 27 | providers: [], 28 | bootstrap: [AppComponent] 29 | }) 30 | export class AppModule { } 31 | ``` 32 | 33 | 3. Use it inside your `Component` by DI 34 | 35 | ```` 36 | ... 37 | import { CacheService, CacheStoragesEnum } from 'ng2-cache'; 38 | ... 39 | 40 | export class AppComponent { 41 | 42 | constructor(private _cacheService: CacheService) { 43 | this._cacheService.set('key', ['some data']); 44 | } 45 | ```` 46 | That's it. Now you don't have to mention it's reference in `tsfoncig.json` 47 | 48 | ## Contents 49 | * [1 Project structure](#1) 50 | * [2 Building](#2) 51 | * [3 Publishing](#3) 52 | * [4 Using the library](#4) 53 | * [5 What it is important to know](#5) 54 | 55 | ## 1 Project structure 56 | - Library: 57 | - **src** folder for the classes 58 | - **public_api.ts** entry point for all public APIs of the package 59 | - **package.json** _npm_ options 60 | - **rollup.config.js** _Rollup_ configuration for building the _umd_ bundles 61 | - **rollup.es.config.js** _Rollup_ configuration for building the _es2015_ bundles 62 | - **tsconfig-build.json** _ngc_ compiler options for _AoT compilation_ 63 | - **build.js** building process using _ShellJS_ 64 | - Extra: 65 | - **tslint.json** _Angular TSLint Preset_ (_TypeScript_ linter rules with _Codelyzer_) 66 | - **travis.yml** _Travis CI_ configuration 67 | 68 | 69 | ## 2 Building 70 | The following command: 71 | ```Shell 72 | npm run build 73 | ``` 74 | - starts _TSLint_ with _Codelyzer_ using _Angular TSLint Preset_ 75 | - starts _AoT compilation_ using _ngc_ compiler 76 | - creates `dist` folder with all the files of distribution, following _Angular Package Format (APF) v5.0_: 77 | ``` 78 | └── dist 79 | ├── bundles 80 | | ├── ng2-cache.umd.js 81 | | ├── ng2-cache.umd.js.map 82 | | ├── ng2-cache.umd.min.js 83 | | └── ng2-cache.umd.min.js.map 84 | ├── esm5 85 | | ├── ng2-cache.js 86 | | └── ng2-cache.js.map 87 | ├── esm2015 88 | | ├── ng2-cache.js 89 | | └── ng2-cache.js.map 90 | ├── src 91 | | └── **/*.d.ts 92 | ├── ng2-cache.d.ts 93 | ├── ng2-cache.metadata.json 94 | ├── LICENSE 95 | ├── package.json 96 | ├── public_api.d.ts 97 | └── README 98 | ``` 99 | To test locally the npm package before publishing: 100 | ```Shell 101 | npm run pack:lib 102 | ``` 103 | Then you can install it in an app to test it: 104 | ```Shell 105 | npm install [path]ng2-cache-[version].tgz 106 | ``` 107 | 108 | ## 3 Publishing 109 | Before publishing the first time: 110 | - you can register your library on [Travis CI](https://travis-ci.org/): you have already configured `.travis.yml` file 111 | - you must have a user on the _npm_ registry: [Publishing npm packages](https://docs.npmjs.com/getting-started/publishing-npm-packages) 112 | 113 | ```Shell 114 | npm run publish:lib 115 | ``` 116 | 117 | ## 4 Using the library 118 | ### Installing 119 | ```Shell 120 | npm install ng2-cache --save 121 | ``` 122 | ### Loading 123 | #### Using SystemJS configuration 124 | ```JavaScript 125 | System.config({ 126 | map: { 127 | 'ng2-cache': 'node_modules/ng2-cache/bundles/ng2-cache.umd.js' 128 | } 129 | }); 130 | ``` 131 | #### Angular-CLI 132 | No need to set up anything, just import it in your code. 133 | #### Rollup or webpack 134 | No need to set up anything, just import it in your code. 135 | #### Plain JavaScript 136 | Include the `umd` bundle in your `index.html`: 137 | ```Html 138 | 139 | ``` 140 | and use global `ng.ng2Cache` namespace. 141 | 142 | ### AoT compilation 143 | The library is compatible with _AoT compilation_. 144 | 145 | ## 5 What it is important to know 146 | 1. `package.json` 147 | 148 | * `"main": "./bundles/ng2-cache.umd.js"` legacy module format 149 | * `"module": "./esm5/ng2-cache.js"` flat _ES_ module, for using module bundlers such as _Rollup_ or _webpack_: 150 | [package module](https://github.com/rollup/rollup/wiki/pkg.module) 151 | * `"es2015": "./esm2015/ng2-cache.js"` _ES2015_ flat _ESM_ format, experimental _ES2015_ build 152 | * `"peerDependencies"` the packages and their versions required by the library when it will be installed 153 | 154 | 2. `tsconfig.json` file used by _TypeScript_ compiler 155 | 156 | * Compiler options: 157 | * `"strict": true` enables _TypeScript_ `strict` master option 158 | 159 | 3. `tsconfig-build.json` file used by _ngc_ compiler 160 | 161 | * Compiler options: 162 | * `"declaration": true` to emit _TypeScript_ declaration files 163 | * `"module": "es2015"` & `"target": "es2015"` are used by _Rollup_ to create the _ES2015_ bundle 164 | 165 | * Angular Compiler Options: 166 | * `"skipTemplateCodegen": true,` skips generating _AoT_ files 167 | * `"annotateForClosureCompiler": true` for compatibility with _Google Closure compiler_ 168 | * `"strictMetadataEmit": true` without emitting metadata files, the library will not be compatible with _AoT compilation_: it is intended to report syntax errors immediately rather than produce a _.metadata.json_ file with errors 169 | * `"flatModuleId": "@scope/package"` full package name has to include scope as well, otherwise AOT compilation will fail in the consumed application 170 | 171 | 4. `rollup.config.js` file used by _Rollup_ 172 | 173 | * `format: 'umd'` the _Universal Module Definition_ pattern is used by _Angular_ for its bundles 174 | * `moduleName: 'ng.angularLibraryStarter'` defines the global namespace used by _JavaScript_ apps 175 | * `external` & `globals` declare the external packages 176 | 177 | 178 | ## License 179 | MIT 180 | -------------------------------------------------------------------------------- /src/services/cache.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable, Optional} from '@angular/core'; 2 | import {CacheOptionsInterface} from '../interfaces/cache-options.interface'; 3 | import {CacheStoragesEnum} from '../enums/cache-storages.enum'; 4 | import {CacheStorageAbstract} from './storage/cache-storage-abstract.service'; 5 | import {CacheSessionStorage} from './storage/session-storage/cache-session-storage.service'; 6 | import {CacheLocalStorage} from './storage/local-storage/cache-local-storage.service'; 7 | import {CacheMemoryStorage} from './storage/memory/cache-memory.service'; 8 | import {StorageValueInterface} from '../interfaces/storage-value.interface'; 9 | 10 | const CACHE_PREFIX = 'CacheService'; 11 | 12 | const DEFAULT_STORAGE = CacheStoragesEnum.SESSION_STORAGE; 13 | const DEFAULT_ENABLED_STORAGE = CacheStoragesEnum.MEMORY; 14 | 15 | @Injectable() 16 | export class CacheService { 17 | 18 | /** 19 | * Default cache options 20 | */ 21 | private _defaultOptions: CacheOptionsInterface = { 22 | expires: Number.MAX_VALUE, 23 | maxAge : Number.MAX_VALUE 24 | }; 25 | 26 | /** 27 | * Cache prefix 28 | */ 29 | private _prefix: string = CACHE_PREFIX; 30 | 31 | public constructor(@Optional() private _storage: CacheStorageAbstract) { 32 | this._validateStorage(); 33 | } 34 | 35 | /** 36 | * Set data to cache 37 | * @param key 38 | * @param value 39 | * @param options 40 | */ 41 | public set(key: string, value: any, options?: CacheOptionsInterface) { 42 | let storageKey = this._toStorageKey(key); 43 | options = options ? options : this._defaultOptions; 44 | if (this._storage.setItem(storageKey, this._toStorageValue(value, options))) { 45 | if (!this._isSystemKey(key) && options.tag) { 46 | this._saveTag(options.tag, storageKey); 47 | } 48 | return true; 49 | } 50 | return false; 51 | } 52 | 53 | 54 | /** 55 | * Get data from cache 56 | * @param key 57 | * @returns any 58 | */ 59 | public get(key: string): any { 60 | let storageValue = this._storage.getItem(this._toStorageKey(key)), 61 | value: any = null; 62 | if (storageValue) { 63 | if (this._validateStorageValue(storageValue)) { 64 | value = storageValue.value; 65 | } else { 66 | this.remove(key); 67 | } 68 | } 69 | return value; 70 | } 71 | 72 | /** 73 | * Check if value exists 74 | * @param key 75 | * @returns boolean 76 | */ 77 | public exists(key: string): boolean { 78 | return !!this.get(key); 79 | } 80 | 81 | /** 82 | * Remove item from cache 83 | * @param key 84 | */ 85 | public remove(key: string) { 86 | this._storage.removeItem(this._toStorageKey(key)); 87 | this._removeFromTag(this._toStorageKey(key)); 88 | } 89 | 90 | /** 91 | * Remove all from cache 92 | */ 93 | public removeAll() { 94 | this._storage.clear(); 95 | } 96 | 97 | /** 98 | * Get all tag data 99 | * @param tag 100 | * @returns Array 101 | */ 102 | public getTagData(tag: string) { 103 | let tags = this.get(this._tagsStorageKey()) || {}, 104 | result : {[key: string]: any} = {}; 105 | if (tags[tag]) { 106 | tags[tag].forEach((key: string) => { 107 | let data = this.get(this._fromStorageKey(key)); 108 | if (data) { 109 | result[this._fromStorageKey(key)] = data; 110 | } 111 | }); 112 | } 113 | return result; 114 | } 115 | 116 | /** 117 | * Create a new instance of cache with needed storage 118 | * @param type 119 | * returns CacheService 120 | */ 121 | public useStorage(type: CacheStoragesEnum) { 122 | let service = new CacheService(this._initStorage(type)); 123 | service.setGlobalPrefix(this._getCachePrefix()); 124 | return service; 125 | } 126 | 127 | /** 128 | * Remove all by tag 129 | * @param tag 130 | */ 131 | public removeTag(tag: string) { 132 | let tags = this.get(this._tagsStorageKey()) || {}; 133 | if (tags[tag]) { 134 | tags[tag].forEach((key: string) => { 135 | this._storage.removeItem(key); 136 | }); 137 | delete tags[tag]; 138 | this.set(this._tagsStorageKey(), tags); 139 | } 140 | } 141 | 142 | /** 143 | * Set global cache key prefix 144 | * @param prefix 145 | */ 146 | public setGlobalPrefix(prefix: string) { 147 | this._prefix = prefix; 148 | } 149 | 150 | /** 151 | * Validate cache storage 152 | */ 153 | private _validateStorage() { 154 | if (!this._storage) { 155 | this._storage = this._initStorage(DEFAULT_STORAGE); 156 | } 157 | if (!this._storage.isEnabled()) { 158 | this._storage = this._initStorage(DEFAULT_ENABLED_STORAGE); 159 | } 160 | } 161 | 162 | /** 163 | * Remove key from tags keys list 164 | * @param key 165 | */ 166 | private _removeFromTag(key: string) { 167 | let tags = this.get(this._tagsStorageKey()) || {}, 168 | index: number; 169 | for (let tag in tags) { 170 | index = tags[tag].indexOf(key); 171 | if (index !== -1) { 172 | tags[tag].splice(index, 1); 173 | this.set(this._tagsStorageKey(), tags); 174 | break; 175 | } 176 | } 177 | } 178 | 179 | /** 180 | * Init storage by type 181 | * @param type 182 | * @returns CacheStorageAbstract 183 | */ 184 | private _initStorage(type: CacheStoragesEnum) { 185 | let storage: CacheStorageAbstract; 186 | switch (type) { 187 | case CacheStoragesEnum.SESSION_STORAGE: 188 | storage = new CacheSessionStorage(); 189 | break; 190 | case CacheStoragesEnum.LOCAL_STORAGE: 191 | storage = new CacheLocalStorage(); 192 | break; 193 | default: storage = new CacheMemoryStorage(); 194 | } 195 | return storage; 196 | } 197 | 198 | private _toStorageKey(key: string) { 199 | return this._getCachePrefix() + key; 200 | } 201 | 202 | private _fromStorageKey(key: string) { 203 | return key.replace(this._getCachePrefix(), ''); 204 | } 205 | 206 | /** 207 | * Prepare value to set to storage 208 | * @param value 209 | * @param options 210 | * returns {value: any, options: CacheOptionsInterface} 211 | */ 212 | private _toStorageValue(value: any, options: CacheOptionsInterface): StorageValueInterface { 213 | return { 214 | value: value, 215 | options: this._toStorageOptions(options) 216 | }; 217 | } 218 | 219 | /** 220 | * Prepare options to set to storage 221 | * @param options 222 | * @returns CacheOptionsInterface 223 | */ 224 | private _toStorageOptions(options: CacheOptionsInterface): CacheOptionsInterface { 225 | var storageOptions: CacheOptionsInterface = {}; 226 | storageOptions.expires = options.expires ? options.expires : 227 | (options.maxAge ? Date.now() + (options.maxAge * 1000) : this._defaultOptions.expires); 228 | storageOptions.maxAge = options.maxAge ? options.maxAge : this._defaultOptions.maxAge; 229 | return storageOptions; 230 | } 231 | 232 | /** 233 | * Validate storage value 234 | * @param value 235 | * @returns boolean 236 | */ 237 | private _validateStorageValue(value: StorageValueInterface) { 238 | return !!value.options.expires && value.options.expires > Date.now(); 239 | } 240 | 241 | /** 242 | * check if its system cache key 243 | * @param key 244 | * returns boolean 245 | */ 246 | private _isSystemKey(key: string) { 247 | return [this._tagsStorageKey()].indexOf(key) !== -1; 248 | } 249 | 250 | /** 251 | * Save tag to list of tags 252 | * @param tag 253 | * @param key 254 | */ 255 | private _saveTag(tag: string, key: string) { 256 | let tags = this.get(this._tagsStorageKey()) || {}; 257 | if (!tags[tag]) { 258 | tags[tag] = [key]; 259 | } else { 260 | tags[tag].push(key); 261 | } 262 | this.set(this._tagsStorageKey(), tags); 263 | } 264 | 265 | /** 266 | * Get global cache prefix 267 | * returns {string} 268 | * private 269 | */ 270 | private _getCachePrefix() { 271 | return this._prefix; 272 | } 273 | 274 | private _tagsStorageKey() { 275 | return 'CacheService_tags'; 276 | } 277 | 278 | } 279 | --------------------------------------------------------------------------------