strikejs-react
Version:
A state management framework for ReactJS applications.
719 lines (654 loc) • 24.2 kB
TypeScript
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;
}