@vegajs/storage
v1.0.0-beta.31
Published
A flexible and type-safe storage service adapter for TypeScript and JavaScript. Supports various storage mechanisms like localStorage, query strings, and mock storage with both asynchronous and synchronous APIs.
Downloads
1,158
Maintainers
Readme
@vegajs/storage
Overview
@vegajs/storage
is a flexible, type-safe storage service interface that allows you to easily implement different storage mechanisms such as localStorage
, query-string
, and mock storage solutions. The service leverages the adapter pattern, making it easy to swap or implement custom storage adapters while maintaining a consistent API.
Key Features
- Adapter Pattern: Decouple the storage logic from your app by providing interchangeable storage adapters.
- Type safety: Provides strong typing with generics for different value types, ensuring type safety.
- Multiple Adapters: Supports out-of-the-box adapters for
localStorage
,query-string
, and a mock service for testing. - Synchronous and Asynchronous Support: Choose between synchronous and asynchronous methods depending on your needs.
Installation
Install the package via npm:
npm install @vegajs/storage
Quick Start
Using the LocalStorage Adapter
The package provides an adapter for localStorage
, making it easy to persist data in the browser.
import { StorageService, LocalStorageAdapter } from '@vegajs/storage';
const storageService = new StorageService(new LocalStorageAdapter());
// Set an item asynchronously
await storageService.setItem('key', 'value');
// Retrieve the item
const value = await storageService.getItem('key');
console.log(value); // Output: 'value'
// Check if the item exists
const hasKey = storageService.has('key');
console.log(hasKey); // Output: true
// Remove the item
storageService.clearItem('key');
Synchronous Usage Example
For applications that require synchronous access to storage, the storage service also supports synchronous methods.
// Set an item synchronously
storageService.setItemSync('syncKey', 'syncValue');
// Get an item synchronously
const syncValue = storageService.getItemSync('syncKey');
console.log(syncValue); // Output: 'syncValue'
// Check if the key exists
console.log(storageService.has('syncKey')); // Output: true
// Clear the item
storageService.clearItem('syncKey');
Using the Query String Adapter
You can also store and retrieve data via the URL query string. This can be useful for persisting state or filters.
import { StorageService } from '@vegajs/storage-service-adapter';
import { QueryStringAdapter } from '@vegajs/storage/adapters';
const queryStringStorage = new StorageService(new QueryStringAdapter());
// Set a value in the query string
await queryStringStorage.setItem('filter', { type: 'category', id: 123 });
// Get a value from the query string
const filter = await queryStringStorage.getItem('filter');
console.log(filter); // Output: { type: 'category', id: 123 }
// Check if the query string contains a key
console.log(queryStringStorage.has('filter')); // Output: true
// Clear all query string parameters
queryStringStorage.clear();
Mock Storage Service (For Testing)
Use the mock adapter for unit tests or when you need an in-memory storage implementation.
import { StorageService, MockStorageService } from '@vegajs/storage';
const mockStorage = new StorageService(new MockStorageService());
await mockStorage.setItem('key', 'mock value');
const value = await mockStorage.getItem('key');
console.log(value); // Output: 'mock value'
mockStorage.clearItem('key');
Extending with Custom Adapters
You can easily create your own adapter by implementing the StorageService
interface. This allows you to plug in any storage mechanism that meets your needs.
import { StorageService } from '@vegajs/storage';
class CustomStorageAdapter implements StorageService {
private data = new Map<string, unknown>();
async getItem<Value>(key: string): Promise<Value | null> {
return this.data.get(key) || null;
}
getItemSync<Value>(key: string): Value | null {
return this.data.get(key) || null;
}
async setItem<Value>(key: string, value: Value): Promise<void> {
this.data.set(key, value);
}
setItemSync<Value>(key: string, value: Value): void {
this.data.set(key, value);
}
has(key: string): boolean {
return this.data.has(key);
}
clearItem(key: string): void {
this.data.delete(key);
}
clear(): void {
this.data.clear();
}
}
// Usage
const customStorage = new StorageService(new CustomStorageAdapter());
await customStorage.setItem('customKey', 'customValue');
console.log(await customStorage.getItem('customKey')); // Output: 'customValue'
Advanced Usage
Working with JSON Values
All adapters handle JSON values seamlessly. You can store and retrieve complex objects without having to manually serialize or deserialize them.
await storageService.setItem('user', { id: 1, name: 'Alice' });
const user = await storageService.getItem<{ id: number; name: string }>('user');
console.log(user?.name); // Output: 'Alice'
Error Handling
When using storage adapters like localStorage
that might not be available in all environments, you can wrap your code in try-catch blocks to handle errors gracefully.
try {
await storageService.setItem('session', { token: '12345' });
} catch (error) {
console.error('Failed to store session data:', error);
}
API Reference
StorageService
Interface
The StorageService
interface defines the core methods that any storage adapter must implement.
export interface StorageService {
getItem<Value>(key: string): Promise<Value | null>;
getItemSync<Value>(key: string): Value | null;
setItem<Value>(key: string, value: Value): Promise<void>;
setItemSync<Value>(key: string, value: Value): void;
has(key: string): boolean;
clearItem(key: string): void;
clear(): void;
}
LocalStorageAdapter
The LocalStorageAdapter
is a concrete implementation of the StorageService
interface using the browser's localStorage
.
export class LocalStorageAdapter implements StorageService {
constructor();
public getItem<Value = unknown>(key: string): Promise<Value | null>;
public getItemSync<Value = unknown>(key: string): Value | null;
public setItem<Value = unknown>(key: string, value: Value): Promise<void>;
public setItemSync<Value = unknown>(key: string, value: Value): void;
public has(key: string): boolean;
public clearItem(key: string): void;
public clear(): void;
}
QueryStringAdapter
The QueryStringAdapter
manages key-value pairs in the URL query string.
export class QueryStringAdapter implements StorageService {
constructor();
public getItem<Value = unknown>(key: string): Promise<Value | null>;
public getItemSync<Value = unknown>(key: string): Value | null;
public setItem<Value = unknown>(key: string, value: Value): Promise<void>;
public setItemSync<Value = unknown>(key: string, value: Value): void;
public has(key: string): boolean;
public clearItem(key: string): void;
public clear(): void;
}
MockStorageAdapter
The MockStorageService
is an in-memory mock implementation of the StorageService
interface. It is useful for testing purposes.
export class MockStorageService implements StorageService {
constructor();
public getItem<Value = unknown>(key: string): Promise<Value | null>;
public getItemSync<Value = unknown>(key: string): Value | null;
public setItem<Value = unknown>(key: string, value: Value): Promise<void>;
public setItemSync<Value = unknown>(key: string, value: Value): void;
public has(key: string): boolean;
public clearItem(key: string): void;
public clear(): void;
}
Conclusion
@vegajs/storage
is a powerful and flexible library that simplifies working with storage in your applications. The library provides strong typing and offers multiple ready-to-use storage adapters. Whether you need to work with localStorage
, query strings, or mock storage for testing, this library has you covered.