UNPKG

synapse-storage

Version:

Набор инструментов для управления состоянием и апи-запросами

250 lines (245 loc) 8.92 kB
import { handleOperationError } from "../../../_utils/error-handling.util.js"; /** * Sentinel object returned by middleware to signal that the value has not changed. * BaseStorage checks for this by reference equality to skip subscriber notifications. */ const VALUE_NOT_CHANGED = Symbol('VALUE_NOT_CHANGED'); // ─── Async Middleware Module ─────────────────────────────────────────────────── class AsyncMiddlewareModule { middlewares = []; api; initialized = false; dispatchFn; constructor(storage){ this.api = { dispatch: async (action)=>this.dispatch(action), getState: ()=>storage.getState(), storage: { doGet: storage.doGet.bind(storage), doSet: storage.doSet.bind(storage), doUpdate: storage.doUpdate.bind(storage), doDelete: storage.doDelete.bind(storage), doClear: storage.doClear.bind(storage), doKeys: storage.doKeys.bind(storage), notifySubscribers: storage.notifySubscribers.bind(storage) } }; } async baseOperation(action) { switch(action.type){ case 'get': { return this.api.storage.doGet(action.key); } case 'set': { await this.api.storage.doSet(action.key, action.value); return this.api.storage.doGet(action.key); } case 'update': { if (Array.isArray(action.value)) { await this.api.storage.doUpdate(action.value); return this.api.storage.doGet(''); } return action.value; } case 'delete': { return this.api.storage.doDelete(action.key); } case 'clear': { return this.api.storage.doClear(); } case 'reset': { if (action.value) { await this.api.storage.doClear(); await this.api.storage.doSet('', action.value); return this.api.storage.doGet(''); } return this.api.storage.doClear(); } case 'init': { const currentState = await this.api.storage.doGet(''); if (Object.keys(currentState || {}).length > 0) { return currentState; } if (action.value) { await this.api.storage.doSet('', action.value); return this.api.storage.doGet(''); } return currentState; } case 'keys': { return this.api.storage.doKeys(); } default: { throw new Error(`Unknown action type: ${action.type}`); } } } initializeMiddlewares() { if (this.initialized) return; let chain = this.baseOperation.bind(this); for (const middleware of [ ...this.middlewares ].reverse()){ const nextChain = chain; chain = async (action)=>{ const actionWithMeta = { ...action, metadata: { ...action.metadata, timestamp: action.metadata?.timestamp || Date.now() } }; return middleware.reducer(this.api)(nextChain)(actionWithMeta); }; } this.dispatchFn = chain; this.initialized = true; } use(middleware) { if (middleware.setup) { middleware.setup(this.api); } this.middlewares.push(middleware); this.initialized = false; } async dispatch(action) { if (!this.initialized) { this.initializeMiddlewares(); } try { return await this.dispatchFn(action); } catch (error) { handleOperationError('AsyncMiddlewareModule: error in middleware chain', error); } } } /** @deprecated Use AsyncMiddlewareModule */ class MiddlewareModule extends AsyncMiddlewareModule { } // ─── Sync Middleware Module ──────────────────────────────────────────────────── class SyncMiddlewareModule { middlewares = []; api; initialized = false; dispatchFn; constructor(storage){ this.api = { dispatch: (action)=>this.dispatch(action), getState: ()=>storage.getState(), storage: { doGet: storage.doGet.bind(storage), doSet: storage.doSet.bind(storage), doUpdate: storage.doUpdate.bind(storage), doRemove: storage.doRemove.bind(storage), doClear: storage.doClear.bind(storage), doKeys: storage.doKeys.bind(storage), notifySubscribers: storage.notifySubscribers.bind(storage) } }; } baseOperation(action) { switch(action.type){ case 'get': { return this.api.storage.doGet(action.key); } case 'set': { this.api.storage.doSet(action.key, action.value); return this.api.storage.doGet(action.key); } case 'update': { if (Array.isArray(action.value)) { this.api.storage.doUpdate(action.value); return this.api.storage.doGet(''); } return action.value; } case 'delete': { return this.api.storage.doRemove(action.key); } case 'clear': { return this.api.storage.doClear(); } case 'reset': { if (action.value) { this.api.storage.doClear(); this.api.storage.doSet('', action.value); return this.api.storage.doGet(''); } return this.api.storage.doClear(); } case 'init': { const currentState = this.api.storage.doGet(''); if (Object.keys(currentState || {}).length > 0) { return currentState; } if (action.value) { this.api.storage.doSet('', action.value); return this.api.storage.doGet(''); } return currentState; } case 'keys': { return this.api.storage.doKeys(); } default: { throw new Error(`Unknown action type: ${action.type}`); } } } initializeMiddlewares() { if (this.initialized) return; let chain = this.baseOperation.bind(this); for (const middleware of [ ...this.middlewares ].reverse()){ const nextChain = chain; chain = (action)=>{ const actionWithMeta = { ...action, metadata: { ...action.metadata, timestamp: action.metadata?.timestamp || Date.now() } }; return middleware.reducer(this.api)(nextChain)(actionWithMeta); }; } this.dispatchFn = chain; this.initialized = true; } use(middleware) { if (middleware.setup) { middleware.setup(this.api); } this.middlewares.push(middleware); this.initialized = false; } dispatch(action) { if (!this.initialized) { this.initializeMiddlewares(); } try { return this.dispatchFn(action); } catch (error) { handleOperationError('SyncMiddlewareModule: error in middleware chain', error); } } } export { AsyncMiddlewareModule, MiddlewareModule, SyncMiddlewareModule, VALUE_NOT_CHANGED }; //# sourceMappingURL=middleware-module.js.map