import * as plugins from './smartstate.plugins.js'; import { StatePart } from './smartstate.classes.statepart.js'; export type TInitMode = 'soft' | 'mandatory' | 'force' | 'persistent'; /** * Smartstate takes care of providing state */ export class Smartstate { public statePartMap: { [key in StatePartNameType]?: StatePart } = {}; constructor() {} /** * Allows getting and initializing a new statepart * initMode === 'soft' (default) - returns existing statepart if exists, creates new if not * initMode === 'mandatory' - requires statepart to not exist, fails if it does * initMode === 'force' - always creates new statepart, overwriting any existing * initMode === 'persistent' - like 'soft' but with webstore persistence * @param statePartNameArg * @param initialArg * @param initMode */ public async getStatePart( statePartNameArg: StatePartNameType, initialArg?: PayloadType, initMode: TInitMode = 'soft' ): Promise> { const existingStatePart = this.statePartMap[statePartNameArg]; if (existingStatePart) { switch (initMode) { case 'mandatory': throw new Error( `State part '${statePartNameArg}' already exists, but initMode is 'mandatory'` ); case 'force': // Force mode: create new state part return this.createStatePart(statePartNameArg, initialArg, initMode); case 'soft': case 'persistent': default: // Return existing state part return existingStatePart as StatePart; } } else { // State part doesn't exist if (!initialArg) { throw new Error( `State part '${statePartNameArg}' does not exist and no initial state provided` ); } return this.createStatePart(statePartNameArg, initialArg, initMode); } } /** * Creates a statepart * @param statePartName * @param initialPayloadArg * @param initMode */ private async createStatePart( statePartName: StatePartNameType, initialPayloadArg: PayloadType, initMode: TInitMode = 'soft' ): Promise> { const newState = new StatePart( statePartName, initMode === 'persistent' ? { dbName: 'smartstate', storeName: statePartName, } : null ); await newState.init(); const currentState = newState.getState(); await newState.setState({ ...currentState, ...initialPayloadArg, }); this.statePartMap[statePartName] = newState; return newState; } }