UNPKG

json-secure-store

Version:

Typed JSON storage wrapper for localStorage/sessionStorage with optional encryption.

225 lines (160 loc) 5.75 kB
# json-secure-store A lightweight, TypeScript-first utility for storing JSON objects in `localStorage` or `sessionStorage`, with optional encryption, expiration, type-safe access, and change listeners. Framework-agnostic and blazing fast. ## ✨ Features - Local/session storage support - Optional encryption (Web Crypto API, providing modern, dependency-free AES-GCM encryption with PBKDF2 key derivation.) - Typed access with interfaces or models - Expiration support (TTL) - Change listeners - Framework agnostic (works in Angular, React, Vue, plain JS, etc.) ## Usage ### Basic Store / Get / Remove ```typescript import { JsonStore } from 'json-secure-store'; const store = new JsonStore(); // Store an object await store.setItem('user', { name: 'Alice', role: 'admin' }); // Retrieve the object with type safety const user = await store.getItem<{ name: string; role: string }>('user'); console.log(user?.name); // "Alice" // Remove the item store.removeItem('user'); ``` ### With Encryption ```typescript import { JsonStore } from 'json-secure-store'; // Example: Using encryption (AES-GCM via Web Crypto API) const store = new JsonStore({ encrypt: true, encryptionKey: 'your-secret-key' }); await store.setItem('secureKey', { data: 'secret' }); const decrypted = await store.getItem<{ data: string }>('secureKey'); console.log(decrypted?.data); // "secret" ``` ### With Expiration ```typescript import { JsonStore } from 'json-secure-store'; const store = new JsonStore(); // Store an item that expires in 60 seconds await store.setItem('session', { userId: 123 }, { ttl: 60000 }); // Retrieve the item before it expires const session = await store.getItem<{ userId: number }>('session'); console.log(session?.userId); // 123 ``` ### Switching Between localStorage and sessionStorage: ```typescript import { JsonStore, StorageType } from 'json-secure-store'; const localStore = new JsonStore({ storageType: StorageType.Local }); const sessionStore = new JsonStore({ storageType: StorageType.Session }); // Store an item in localStorage await localStore.setItem('user', { name: 'Alice' }); // Store an item in sessionStorage await sessionStore.setItem('session', { sessionId: '12345' }); ``` ### Using Cache ```typescript import { JsonStore } from 'json-secure-store'; const store = new JsonStore({ cache: true }); // Store an item with caching enabled await store.setItem('user', { name: 'Alice' }); // Retrieve from cache if available const cachedUser = await store.getItem('user'); console.log(cachedUser?.name); // "Alice" ``` ### Listen for Changes ```typescript import { JsonStore } from 'json-secure-store'; const store = new JsonStore(); store.onChange((key, newValue) => { console.log(`Changed key: ${key}, new value:`, newValue); }); // Trigger a change await store.setItem('user', { name: 'Alice' }); ``` ## Angular Integration Example ### 1. Install the package: ```bash npm install json-secure-store ``` ### 2. Create a service to encapsulate storage operations: ```typescript import { Injectable } from '@angular/core'; import { JsonStore } from 'json-secure-store'; @Injectable({ providedIn: 'root', }) export class SecureStorageService { private store: JsonStore; constructor() { this.store = new JsonStore({ encrypt: true, encryptionKey: 'your-encryption-key' }); } async setItem<T>(key: string, value: T, ttl?: number): Promise<void> { await this.store.setItem(key, value, ttl ? { ttl } : undefined); } async getItem<T>(key: string): Promise<T | null> { return await this.store.getItem<T>(key); } removeItem(key: string): void { this.store.removeItem(key); } } ``` ### 3. Use the service in your components: ```typescript import { Component, OnInit } from '@angular/core'; import { SecureStorageService } from './secure-storage.service'; @Component({ selector: 'app-example', template: `<p>{{ userData?.name }}</p>`, }) export class ExampleComponent implements OnInit { userData: { name: string; role: string } | null = null; constructor(private secureStorageService: SecureStorageService) {} async ngOnInit(): Promise<void> { // Store data await this.secureStorageService.setItem('user', { name: 'Alice', role: 'admin' }); // Retrieve data this.userData = await this.secureStorageService.getItem<{ name: string; role: string }>('user'); } } ``` ## API ### Constructor Options ```typescript export interface StorageOptions { storageType?: StorageType; encrypt?: boolean; encryptionKey?: string; cache?: boolean; namespace?: string; defaultTTL?: number; } ``` ### Methods ```typescript store.setItem<T>(key: string, value: T, options?: { ttl?: number }): Promise<void>; store.getItem<T>(key: string): Promise<T | null>; store.removeItem(key: string): void; store.clear(): void; store.onChange(callback: (key: string, value: any) => void): void; store.raw(): Storage; ``` ## Encryption - Utilizes AES-GCM encryption via the Web Crypto API. - Requires encrypt: true and encryptionKey for encryption. ## Expiration (TTL) - Use `defaultTTL` (in milliseconds) to auto-expire items. - Items with expired TTL are removed on retrieval. ## Type Guards (Optional) ```typescript function isUser(val: any): val is User { return val && typeof val.name === 'string'; } const user = await store.getItem('user'); if (isUser(user)) { console.log(user.name); } ``` ## Testing ```bash npm run test ``` Utilizes [Vitest](https://vitest.dev) for fast, browser-like testing.