UNPKG

strikejs-react

Version:

A state management framework for ReactJS applications.

719 lines (654 loc) 24.2 kB
declare module "strikejs-react" { import * as React from 'react'; /** * Returns value at a given key with in an object literal. * * @export * @param {object} object the object to use * @param {string} path the path to return its value * @param {string} p path separator, defaults to '.' * @returns {any} the value at the given key */ export function getDataAt<T>(object: any, path: string, p: string): T /** * Routing params to be propagated if found */ export type RouteParams = Dictionary<any> & {test(path:string):any,path:string,route:string}; /** * Extracts the names of the parameters from functions * * @export * @param {Function} fn the function to extract its parameters' names. * @returns {Array<string>} array of parameters names */ export function extractArgumentsFromFunction(fn: Function): any; /** * Represents an action triggered with-in the application. * * @export * @interface Action */ export interface Action{ /** * Uniquely identifies the action across the application. * * @type {(string|number)} */ type:string|number; /** * Any data attached to the action. Action data should only include data primitives i.e. number, string, boolean. * * @type {*} */ data?:any; /** * * * @type {string} * @memberOf Action */ app?:string; } /** * Represents an action generating a promise. This type of actions are supposed to be caught using {Promisify} middleware. * * @export * @interface PromiseAction * @extends {Action} * @template T */ export interface PromiseAction<T> extends Action{ /** * A promise to be caught by the {Promisify} middleware. * * @type {Promise<T>} */ promise: Promise<T>; } /** * A function to be used in conjunction with {Injectable} middleware. This middleware uses the application's dependency injection module to * provide the parameters of the function. * * @export * @interface ServiceFunction */ export interface ServiceFunction { (...args: any[]): Action; /** * an array of component names to be injected into the service function. * * @type {string[]} */ $inject:string[]; } /** * An action that requires action to services registered within the application's dependency injection module. * * @export * @interface ServiceAction * @extends {Action} */ export interface ServiceAction extends Action { /** * A service function to be injected using the application's depenecy injection module. * * @type {ServiceFunction} */ service: ServiceFunction; $inject:string[]; } /** * Data store */ export interface DataStore { get(key:string):any; set(key:string,val:any):any; } /** * Properties that will be passed to the wrapped controller components. * The state of the wrapping component will be passed inside `data`. */ export interface ControllerProps<V>{ /** * The data as passed by the wrapping controller component. */ data:V; /** * The store of the application. */ store:IStore; /** * Dispatches an action within the store. * @param {Action} action the action to dispatch. * @throws {Error} if no action is provided */ dispatch:DispatchFn; routeParams?:RouteParams; dataStore?:DataStore; router?:any; persistenceStrategy?:PersistenceStrategy|FunctionalPersistenceStrategy; } /** * Returns value at a given key with in an object literal. * * @export * @param {object} object the object to use * @param {string} path the path to return its value * @param {string} p path separator, defaults to '.' * @returns {any} the value at the given key */ export function getDataAt<T>(object: any, path: string, p: string): T; export interface DispatchFn { <V,R>(fn:(dispatch:DispatchFn,getState:StateGetter,extra:V)=>R,extra:V):R; <V>(fn:(dispatch:DispatchFn,getState:StateGetter)=>V):V; <V>(action:Action,cb:()=>void):void; (action:Action):Promise<void>; } export interface FunctionalComponent<T>{ (props:T):React.ReactElement<T>; } export interface ControllerViewConfig<State,Props extends ControllerProps<State>> { reducer?(state:any,action:Action):void; initialState?:State|((props:Props)=>State); stateKey:string; component:React.ComponentClass<Props>|FunctionalComponent<Props>; deps?:string[]|Dictionary<string>; propsToPropagate?:string[]; propsToData?:(props:Props,data:State)=>State; propsModifier?(props:Props,dest:Dictionary<any>):void; } export function createControllerView<State,Props extends ControllerProps<State>>({ component, reducer, initialState, deps,propsModifier, propsToPropagate, propsToData, stateKey}:ControllerViewConfig<State,Props>); /** * Creates a middleware that can handle {PromiseAction} * * @export * @param {Injector} injector an injector instance to use for dependency resolution. * @returns {Middleware} a middleware. */ export function Injectable(injector:Injector):IMiddleware; /** * A dependency injection module inspired by AngularJS's dependency injection. * * @export * @class Injector */ export class Injector { /** * an object literal containing all registered components. * * @type {Dictionary<any>} */ components: Dictionary<any>; /** * an object literal containing instances of the registered components. * * @type {Dictionary<any>} */ instances: Dictionary<any>; /** * Used internally to resolve dependencies. */ private stack: Array<any>; /** * Adds an instance to the list of registered instances within the module. * * @param {string} name the name of the instance * @param {*} c the instance, this can be a primitive, function, or an object. * @returns the registered instance. */ public addInstance(name:string,c:any); /** * Adds a component to the list of registered components within the module. * ES6 class components should implement a static function `factory` and should include * a static member `$inject` including a list of dependencies. The module will resolve the required * dependencies and pass them to the static `factory` method which should return an instance of the * compnent. * * @param {string} name the name of the component. * @param {*} c the component to register * @returns the component. */ public addComponent(name:string,c:any); /** * Checks whether a component exists or not * * @param {string} name the name of the component. * @returns {boolean} true if the component exists false otherwise. */ public hasComponent(name:string):boolean; /** * Checks whether an instance is registered or not. * * @param {string} name the name of the component. * @returns {boolean} returns the instance or undefined otherwise. */ public hasInstance(name:string):boolean; /** * Given a function that requires access to some components, this method injects the function with the required * * @param {Function|ServiceFunction} fn the function to inject * @param {*} [ctx] (description) * @param {...any[]} args (description) * @returns (description) */ public injectFunction(fn:any,ctx?:any,...args:any[]); private _inject(name:string, c:any):any; /** * (description) * * @param {string} name (description) * @returns {*} (description) */ public get(name:string):any; /** * (description) * * @param {string} name (description) * @param {Object} o (description) * @returns {Injector} (description) */ public register(name: string, o: Object): Injector; /** * (description) * * @param {string} name (description) * @param {number} n (description) * @returns {Injector} (description) */ public register(name: string, n: number): Injector; /** * (description) * * @param {string} name (description) * @param {Function} fn (description) * @returns {Injector} (description) */ public register(name: string, fn: Function): Injector; /** * (description) * * @param {string} name (description) * @param {Array<any>} array (description) * @returns {Injector} (description) */ public register(name:string, array: Array<any>): Injector; /** * (description) * * @param {Array<any>} array (description) * @returns {Injector} (description) */ public register(array: Array<any>): Injector; /** * (description) * * @returns {Injector} (description) */ public register():Injector; } export interface Dictionary<T>{ [idx:string]:T; } export interface DependencyContainer{ get<T>(key:string):T|Promise<T>; } /** * Creates a persistence storage based on the localStorage. * @returns {PersistenceStrategy} */ export function localStorageStrategy():PersistenceStrategy; /** * Represents an internal state used by the state container to emulate immutability. */ export interface IManagedState<V> { /** * Sets a specific attribute on the state. * @param {string} key the key to set its value. * @param {any} val the value of the state. * @returns {IManagedState} the managed state instance. Useful for chaining changes. */ $set<T>(key:keyof V,val:T):this; /** * Gets a specific attribute in the state. * @param {string} key the key to get its value. * @returns {any} the value at the provided key. */ $get<T>(key:keyof V):T; /** * Push a new element to a specific attribute */ $push(key:keyof V,...args:any[]):this; /** * Removes an element from the beginning of an array */ $shift<T>(key:keyof V):T; /** * Adds an item to the beginning of an array */ $unshift<T>(key:keyof V,val:T):this; /** * Remoes an element from the end of an array */ $pop<T>(key:keyof V):T; /** * Removes an element at a specific position */ $splice(key:keyof V,index:number,count?:number,...args:any[]); /** * Sets the state object managed by this managed state. * @param {any} st the new state. * @returns {IManagedState} the managed state instance. */ setState<T>(st:T):this; /** * Checks whether the managed state has any changes or not. * @returns {boolean} */ hasChanges():boolean; /** * Apply multiple mutations to the state */ withMutations(cb:(state:IManagedState<V>)=>void):void; /** * Returns the changes made to the managed state. * @returns {Dictionary<any>} */ changes():Dictionary<any>; } /** * Creates a managed state object * @param {any} s the initial state to manage * @returns {IManagedState} */ export function createManagedState<V>(s?:Dictionary<any>):IManagedState<V>; /** * A function that receives the currently dispatched {Action} and the application store and returns either a new {Action} object or * null to stop the execution of the dispatched action. * Middlewares are useful in handling specific types of actions such as actions that need to wait for a promise to be resolved, or * require access some third-party APIs, etc. * @see {IntegerPromisifyMiddleware} * @see {PromisifyMiddleware} * @see {InjectableMiddleware} */ export interface IMiddleware { (action:Action,store:IStore,next:IMiddlewareNext):void; } /** * Represents a callback to trigger the next middleware */ export interface IMiddlewareNext { (action?:Action):void } /** * A persistence strategy for the state container. */ export interface PersistenceStrategy { /** * Save data at a given key. * @param {string} key the key to store the data at. * @param {any} data the data to store. * @returns {Promise<any>} */ put<T>(key:string,data:T):Promise<any>; /** * Save data at a given key. * @param {string} key the key to store the data at. * @param {any} data the data to store. * @param {function} cb a callback after. */ put<T>(key:string,data:T,cb:(err:Error,data?:any)=>void):void; /** * Returns a state at a given key * @param {string} key the key to retrieve its data. * @returns {Promise<any>} a promise resolving to the data. */ get<T>(key:string):Promise<T>; /** * Returns a state at a given key * @param {string} key the key to retrieve its data. * @param {function} cb a NodeJS style callback with error as its first param, and the data as its second. */ get<T>(key:string,cb:(err:Error,data:T)=>void):void } export interface FunctionalPersistenceStrategy{ /** * A function to rertrieve data from a persistence store. * @param {string} key the key to the data. * @param {function} cb a NodeJS style callback with error as its first param, and the data as its second. */ <T>(key:string,cb:(err:Error,data:T)=>void):void; /** * A function persistence strategy to store data in a persistence store. * @param {string} key the key to the data. * @param {any} data the data to store. * @param {function} cb a NodeJS style callback with error as its first param, and the data as its second. */ <T>(key:string,val:T,cb:(err:Error,data?:any)=>void):void; } /** * An object pool */ export interface Pool<V> { /** * Returns an object from the pool. * @param {any} v an optional to be passed to the generator function if provided. Otherwise, it is ignored. * @returns {V} */ get(v?:any):V; /** * Adds an object to the pool. * @param {V} v object to add */ put(v:V):void; } /** * Creates an object pool to help with object reuse. * This is to optimise garabage collection in JS application. * @param {function} make an object generator function. If provided, the function will be called when no the pool is empty. * @returns {Pool} */ export function createPool<T>(make?:(...args:any[])=>T):Pool<T>; /** * Creates a middleware to handle action with ES6 Promises. * @param {number|string} fetching fetching prefix for the actoin. Defaults to 'Fetching' * @param {number|string} resolved resolved prefix for the action. Defaults to 'Resolved' * @param {number|string} rejected rejected prefix for the action. Defaults to 'Rejected' * @returns {IMiddlware} the promisify middleware. */ export function PromisifyMiddleware(fetching:number|string,resolved:number|string,rejected:number|string):IMiddleware; /** * A function that receives the current state of a {ControllerView} component, and an {Action}, and it returns * either the new state of the {ControllerView} component if the {Action} changes the state, or a * the current state if no changes were made to the state. * @export * @interface Reducer */ export interface Reducer<V>{ (state:IManagedState<V>,action:Action):void; } /** * Represents a stateful component */ export interface StatefulComponent<V,T> { /** * Set the state of the component * @param {T} newState the new state or partial state */ setState<T>(newState:T):void; /** * Set the state of the component * @param {function} updater an updater function that receives the previous state, * and the properties of the component and returns an object containing the changes * that needs to be applied to the state. */ setState<T>(updater:(prevState:T,props:V)=>T,cb?:()=>void):void; /** * Returns the state key of the component. This is used internally by the state container. * @returns {string} */ getStateKey():string; /** * Returns the reducer of the component. This is used internally by the state container. * @returns {Reducer} */ getReducer():Reducer<T>; /** * The state of the component */ state:T; } /** * Represents store configuration options */ export interface StoreCfg { /** * @type {boolean} * @description whether the store to track changes. */ trackChanges?:boolean; /** * @type {Array<Middleware>} * @description an array of middlewares to add to the store. */ middlewares?:IMiddleware[]; } export interface DispatchFn { <V,R>(dispatch:DispatchFn,getState:StateGetter,extra:V):R; <V>(dispatch:DispatchFn,getState:StateGetter):V; (action:Action,cb:()=>void):void; (action:Action):Promise<void>; } export type StateGetter = <T>(key:string)=>T; /** * A state container store */ export interface IStore { /** * Connects a component to the store. * @param {StatefulComponent<T>} el the component to connect to the store. * @returns {IStore} the store instance. */ connect<T,V>(el:StatefulComponent<T,V>):this; /** * Disconnects a component from the store. * @param {StatefulComponent<T>} el the component to disconnect. * @returns {IStore} the store instance. */ disconnect<T,V>(el:StatefulComponent<T,V>):this; /** * Set the state of a specific component within the state. * @param {string} key the component's key. * @param {T} val the updated state. * @returns {IStore} the store instance; */ setStateAt<T>(key:string,val:T):this; /** * Get the state of a specific component. * @param {string} key the component's key. * @returns {T} the state of the component. */ getStateAt<T>(key:string):T; /** * Dispatches an action within the store. * @param {Action} action the action to dispatch. * @returns {Promise<void>} if promises are supported by the browser. * The promise is resolved when the view is updated. Otherwise, returns `void`. * @throws {Error} if no action is provided */ dispatch:DispatchFn; } /** * Creates a state container instance with the provided configurations * @param {StoreCfg} cfg the store configurations. * @returns {IStore} */ export function createStore(cfg:StoreCfg):IStore; /** * Represents an action to be handled by a worker middleware. */ export interface WebSocketAction extends Action { websocket:"close"|"send"; websocketId?:string; } /** * A middleware to handle websocket communication. * @param {WebSocket} websocket the websocket to connect to. * @param {IStore} store the state container instance. * @returns {IMiddleware} the websocket middleware. */ export function WebSocketMiddleware (websocket:WebSocket,store:IStore):IMiddleware; /** * An action to be sent to a worker middleware * * @export * @interface WorkerAction * @extends {Action} */ export interface WorkerAction extends Action { /** * The worker identifier, if you're using the single worker middleware, * you'll just need to set this to any truthy value. */ workerId:string; /** * Set this to true to terminate the worker with the provided ID. * If no such worker is found, the action is ignored. */ terminate?:boolean; } /** * A worker registry interface. * The interface represents a contract for a registry to manage multiple workers. * @see {MultiWorkerMiddleware} */ export interface WorkerRegistry{ /** * Returns a worker with a given key (identifier) * @param {string} key the worker key * @returns {Worker} the requested worker * @throws {Error} if no worker with the provided key exists. */ get(key:string):Worker; /** * Registers a worker with a key and a file. * @param {string} key the key to reference the worker by. * @param {string|Worker} fileOrWorker either a file name to use with the worker * or a worker object. * @returns {WorkerRegistry} the current instance of the worker registry. */ register(key:string,fileOrWorker:string|Worker):WorkerRegistry; /** * Terminates a worker with a given key * @param {string} key the worker key. * @returns {WorkerRegistry} the current instance of the worker registry. */ terminate(key:string):WorkerRegistry; } /** * Creates a single worker middleware. * @param {Worker} worker the worker to use. * @param {IStore} store the store instance. * @returns {IMiddleware} */ export function WorkerMiddleware(worker:Worker,store:IStore):IMiddleware; /** * Creates a multi-worker middleware. * * @param {WorkerRegistry} registry the worker registry to use. * @param {IStore} store the state store instance * @returns {Middleware} a multi-worker middleware */ export function MultiWorkerMiddleware(registry:WorkerRegistry,store: IStore):IMiddleware; /** * Creates a basic implementation of a worker registry. * @returns {WorkerRegistry} */ export function createWorkerRegistry():WorkerRegistry; }