import { combineReducers , ReducersMapObject } from 'redux' ; import { action , Action , applyPatches , computed , createStore , enableES5 , enablePatches , getStagedState , identifierKey , Service , setAutoFreeze , setPatchesToggle , state , stateKey , Store , storeKey , subscribe , Subscription , subscriptionsKey , usm as usmAction , watch , } from '../usm-redux' ; setAutoFreeze ( false ) ; setPatchesToggle ( ! process . env . DISABLE_PATCHES ) ; if ( ! process . env . DISABLE_PATCHES ) { enablePatches ( ) ; } export const enum ModuleStatus { Pending = 'PENDING' , Initializing = 'INITIALIZING' , Ready = 'READY' , Resetting = 'RESETTING' } export const onceKey = Symbol ( 'once' ) ; export const onInitOnceKey = Symbol ( 'onInitOnce' ) ; export const notReadyModulesKey = Symbol ( 'notReadyModules' ) ; export const checkStatusChangeKey = Symbol ( 'checkStatusChange' ) ; export const enableCacheKey = Symbol ( 'enableCache' ) ; export const enableGlobalCacheKey = Symbol ( 'enableGlobalCache' ) ; export const storageKey = Symbol ( 'storage' ) ; export const storageStateKey = Symbol ( 'storageState' ) ; export const globalStorageStateKey = Symbol ( 'globalStorageState' ) ; export const spawnReducersKey = Symbol ( 'spawnReducers' ) ; export const spawnStorageReducersKey = Symbol ( 'spawnStorageReducers' ) ; export const ignoreReadyModulesKey = Symbol ( 'ignoreReadyModules' ) ; export interface RcModuleOptions < T > { deps ? : T & { storage ? : any ; globalStorage ? : any ; } ; enableCache ? : boolean ; enableGlobalCache ? : boolean ; storageKey ? : string ; } interface RcModuleV2 { parentModule : RcModuleV2 ; [ storageStateKey ] ? : string [ ] ; [ globalStorageStateKey ] ? : string [ ] ; [ stateKey ] : Record < string , any > ; [ identifierKey ] : string ; [ subscriptionsKey ] : Subscription [ ] ; [ storeKey ] : Store ; } abstract class RcModuleV2 < T = { } > { private [ onceKey ] = false ; private [ storageKey ] : string ; private [ enableCacheKey ] : boolean ; private [ enableGlobalCacheKey ] : boolean ; /**
     * background/client transport for browser extension
     */ protected _transport ? : any ; private [ ignoreReadyModulesKey ] = new Set < RcModuleV2 > ( ) ; protected initializeProxy ? ( ) ; /**
     * `onInit` life cycle for current initialization before all deps modules are all ready.
     */ protected onInit ? ( ) ; /**
     * `onInitOnce` once life cycle for current initialization before all deps modules are all ready.
     */ protected onInitOnce ? ( ) ; /**
     * `onInitSuccess` life cycle for current initialization after this module is ready.
     */ protected onInitSuccess ? ( ) ; /**
     * `onReset` life cycle for current reset before one of deps modules is not ready.
     */ protected onReset ? ( ) ; /**
     * Each Redux dispatch action will trigger `onStateChange` once.
     */ protected onStateChange ? ( ) ; protected _deps : T & { storage ? : any ; globalStorage ? : any ; } ; constructor ( { deps , enableCache = false , enableGlobalCache = false , ... options } = { } ) { this . _deps = deps ; this [ storageKey ] = options . storageKey ; this [ enableCacheKey ] = enableCache ; this [ enableGlobalCacheKey ] = enableGlobalCache ; subscribe ( this , ( ) => { if ( typeof this . onStateChange === 'function' ) { this . onStateChange ( ) ; } this [ checkStatusChangeKey ] ( ) ; } ) ; if ( ! this [ storageStateKey ] || ! this [ enableCacheKey ] || ! this . _deps . storage ) { this [ storageStateKey ] = [ ] ; } this [ storageStateKey ] . forEach ( ( key ) => delete this [ stateKey ] [ key ] ) ; if ( ! this [ globalStorageStateKey ] || ! this [ enableGlobalCacheKey ] || ! this . _deps . globalStorage ) { this [ globalStorageStateKey ] = [ ] ; } this [ globalStorageStateKey ] . forEach ( ( key ) => delete this [ stateKey ] [ key ] ) ; } @ state status = ModuleStatus . Pending ; @ action private _setStatus ( status ) { this . status = status ; } private async [ onInitOnceKey ] ( ) { if ( ! this [ onceKey ] ) { this [ onceKey ] = true ; if ( typeof this . onInitOnce === 'function' ) { await this . onInitOnce ( ) ; } } } private async [ checkStatusChangeKey ] ( ) { if ( this . _shouldInit ( ) ) { this . _setStatus ( ModuleStatus . Initializing ) ; await this [ onInitOnceKey ] ( ) ; if ( typeof this . onInit === 'function' ) { await this . onInit ( ) ; } this . _setStatus ( ModuleStatus . Ready ) ; if ( typeof this . onInitSuccess === 'function' ) { await this . onInitSuccess ( ) ; } } else if ( this . _shouldReset ( ) ) { this . _setStatus ( ModuleStatus . Resetting ) ; if ( typeof this . onReset === 'function' ) { await this . onReset ( ) ; } this . _setStatus ( ModuleStatus . Pending ) ; } } protected _ignoreModuleReadiness ( dep ) { this [ ignoreReadyModulesKey ] . add ( dep ) ; } private get [ notReadyModulesKey ] ( ) { const modules = Object . values ( this . _deps || { } ) . filter ( ( module ) => module && typeof module . ready !== 'undefined' ) ; return modules . filter ( ( module ) => ! module . ready && ! this [ ignoreReadyModulesKey ] . has ( module ) ) ; } _shouldInit ( ) { const areAllReady = this [ notReadyModulesKey ] . length === 0 ; return areAllReady && this . pending ; } _shouldReset ( ) { const areNotReady = this [ notReadyModulesKey ] . length > 0 ; return areNotReady && this . ready ; } _depsCheck ( checkedModules = [ this ] , pickedModules = [ ] ) { Object . values ( this . _deps ?? { } ) . forEach ( ( module ) => { if ( module instanceof RcModuleV2 && ! module . ready ) { const notReadyModules = Object . values ( module . _deps ?? { } ) . filter ( ( item ) => item instanceof RcModuleV2 && ! item . ready ) ; if ( notReadyModules . length > 0 && ! checkedModules . includes ( module ) ) { checkedModules . push ( module ) ; module . _depsCheck ( checkedModules , pickedModules ) ; } else if ( ! pickedModules . includes ( module ) && notReadyModules . length === 0 ) { pickedModules . push ( module ) ; } } } ) ; return pickedModules ; } @ action _changeState ( callback ) { callback ( ) ; } get pending ( ) { return this . status === ModuleStatus . Pending ; } get ready ( ) { return this . status === ModuleStatus . Ready ; } get resetting ( ) { return this . status === ModuleStatus . Resetting ; } get initializing ( ) { return this . status === ModuleStatus . Initializing ; } get store ( ) { return this [ storeKey ] ; } private [ spawnStorageReducersKey ] ( ) { const descriptors = { } ; /**
         * make storage reducer and state
         */ this [ storageStateKey ] . forEach ( ( key ) => { const descriptor = Object . getOwnPropertyDescriptor ( this , key ) ; if ( typeof descriptor === 'undefined' ) return ; const initialState = descriptor . value ; const storageReducerKey = `${ this [ storageKey ] }-${ key }` ; this . _deps . storage . registerReducer ( { key : storageReducerKey , reducer : ( state = initialState , action ) => action . _usm === usmAction ? this . _getStateV2 ( action . _state , 'storage' ) . data [ storageReducerKey ] : state } ) ; Object . assign ( descriptors , { [ key ] : { enumerable : true , configurable : false , get ( this ) { const stagedState = getStagedState ( ) ; return stagedState ? this . _getStateV2 ( stagedState , 'storage' ) . data ! [ storageReducerKey ] : this . _deps . storage . data ! [ storageReducerKey ] ; } , set ( this , value ) { const stagedState = getStagedState ( ) ; if ( stagedState ) { this . _getStateV2 ( stagedState , 'storage' ) . data ! [ storageReducerKey ] = value ; return ; } this . _deps . storage . data ! [ storageReducerKey ] = value ; } } } ) ; } ) ; /**
         * make global storage reducer and state
         */ this [ globalStorageStateKey ] . forEach ( ( key ) => { const descriptor = Object . getOwnPropertyDescriptor ( this , key ) ; if ( typeof descriptor === 'undefined' ) return ; const initialState = descriptor . value ; const storageReducerKey = `${ this [ storageKey ] }-${ key }` ; this . _deps . globalStorage . registerReducer ( { key : storageReducerKey , reducer : ( state = initialState , action ) => action . _usm === usmAction ? this . _getStateV2 ( action . _state , 'globalStorage' ) . data [ storageReducerKey ] : state } ) ; Object . assign ( descriptors , { [ key ] : { enumerable : true , configurable : false , get ( this ) { const stagedState = getStagedState ( ) ; return stagedState ? this . _getStateV2 ( stagedState , 'globalStorage' ) . data ! [ storageReducerKey ] : this . _deps . globalStorage . data ! [ storageReducerKey ] ; } , set ( this , value ) { const stagedState = getStagedState ( ) ; if ( stagedState ) { this . _getStateV2 ( stagedState , 'globalStorage' ) . data ! [ storageReducerKey ] = value ; return ; } this . _deps . globalStorage . data ! [ storageReducerKey ] = value ; } } } ) ; } ) ; Object . defineProperties ( this , descriptors ) ; } private _modulePath = 'root' ; private _initialized = false ; private _suppressInit ? : boolean ; protected _reducers : ReducersMapObject ; protected _getStateV2 = ( state , key ) => state [ key ] ; private _setStore ( ) { return this . _initModule ( ) ; } get _store ( ) { return this . store ; } private [ spawnReducersKey ] ( ) { const descriptors = { [ stateKey ] : { enumerable : false , configurable : false , get ( this ) { const stagedState = getStagedState ( ) ; return this . _getStateV2 ( stagedState ?? this [ storeKey ] ?. getState ( ) , this [ identifierKey ] ) ; } } } ; this . _reducers = Object . keys ( this [ stateKey ] ?? { } ) . reduce ( ( serviceReducersMapObject , key ) => { const descriptor = Object . getOwnPropertyDescriptor ( this , key ) ; if ( typeof descriptor === 'undefined' ) return serviceReducersMapObject ; const initialState = descriptor . value ; Object . assign ( descriptors , { [ key ] : { enumerable : true , configurable : false , get ( this ) { return this [ stateKey ] [ key ] ; } , set ( this , value ) { this [ stateKey ] [ key ] = value ; } } } ) ; return Object . assign ( serviceReducersMapObject , { [ key ] : ( state = initialState , action ) => action . _usm === usmAction ? this . _getStateV2 ( action . _state , this [ identifierKey ] ) [ key ] : state } ) ; } , { } ) ; const stateDescriptor = Object . getOwnPropertyDescriptor ( this , stateKey ) ; if ( stateDescriptor && typeof stateDescriptor . get === 'function' ) return ; Object . defineProperties ( this , descriptors ) ; } get reducer ( ) { if ( this . _reducers ) return combineReducers ( this . _reducers ) ; this [ spawnStorageReducersKey ] ( ) ; this [ spawnReducersKey ] ( ) ; return combineReducers ( this . _reducers ) ; } async _initModule ( ) { this . _initialized = true ; if ( ( this . parentModule && ! ( this . parentModule instanceof RcModuleV2 ) ) || ( ! this . parentModule && ! ( this instanceof RcModuleV2 ) ) ) { for ( const subscribe of this [ subscriptionsKey ] ?? [ ] ) { subscribe ( ) ; } this [ subscriptionsKey ] = [ ] ; } await this [ checkStatusChangeKey ] ( ) ; for ( const subModule in this ) { const subRcModule = this [ subModule ] as any ; if ( subRcModule && typeof subRcModule . _initModule === 'function' && ! subRcModule . _initialized && ! subRcModule . _suppressInit ) { subRcModule . _initModule ( ) ; } } } private get proxyReady ( ) { return this . ready ; } private get modulePath ( ) { return this . _modulePath ; } private addModule ( name , module ) { if ( Object . prototype . hasOwnProperty . call ( this , name ) ) { throw new Error ( `Property '${ name }' already exists...` ) ; } Object . defineProperty ( this , name , { get ( ) { return module ; } , enumerable : true } ) ; if ( ( this as any ) [ name ] . _modulePath === 'root' ) { ( this as any ) [ name ] . _modulePath = `${ this . modulePath }.${ name }` ; } } private get state ( ) { return this [ stateKey ] ; } private actionTypes ( ) { return { } ; } } export { RcModuleV2 , state , action , subscribe , computed , createStore , watch , stateKey , storeKey , identifierKey , applyPatches , usmAction , enableES5 , setAutoFreeze , } ;