Comparing version 0.3.3 to 0.4.0
import { IActionDefinition } from "./types"; | ||
/** | ||
* Defines a new Action type for typesafe action handling. | ||
* | ||
* @param type the Action type string being defined | ||
*/ | ||
export declare function defineAction<T = undefined>(type: string): IActionDefinition<T>; |
@@ -0,1 +1,6 @@ | ||
/** | ||
* Defines a new Action type for typesafe action handling. | ||
* | ||
* @param type the Action type string being defined | ||
*/ | ||
export function defineAction(type) { | ||
@@ -2,0 +7,0 @@ const definition = ((payload) => ({ type, payload })); |
import { IAction, IActionType, IEmitter } from "./types"; | ||
export declare function on<T>(emitter: IEmitter, type: IActionType<T>, cb: (t: T) => void): void; | ||
export declare function off<T>(emitter: IEmitter, type: IActionType<T>, cb: (t: T) => void): void; | ||
export declare function once<T>(emitter: IEmitter, type: IActionType<T>, cb: (t: T) => void): { | ||
cancel: () => void; | ||
}; | ||
/** | ||
* Equivalent to `emitter.on()`, exported as an Effect for consistency. | ||
* | ||
* @param emitter the emitter to hook into | ||
* @param type the action type to listen on | ||
* @param cb a callback called whenever the action is emitted | ||
*/ | ||
export declare function on<T>(emitter: IEmitter, type: IActionType<T>, cb: (t: T) => void): () => void; | ||
/** | ||
* Listens for `emitter.on()`, invokes the callback exactly once, and then unlistens. | ||
* Returns a handle which, when called, cancels this effect. | ||
* | ||
* @param emitter the emitter to hook into | ||
* @param type the action type to listen on | ||
* @param cb a callback called exactly once when the next action is emitted | ||
*/ | ||
export declare function once<T>(emitter: IEmitter, type: IActionType<T>, cb: (t: T) => void): () => void; | ||
/** | ||
* Returns a promise whose resolved value will be the next action of the given type | ||
* emitted on the emitter. If the `maxWait` parameter is specified, then at most | ||
* `maxWait` milliseconds will be waited before returning the default value `null`. | ||
* | ||
* @param emitter emitter to hook into | ||
* @param type the action type to listen on | ||
*/ | ||
export declare function take<T>(emitter: IEmitter, type: IActionType<T>): Promise<T>; | ||
/** | ||
* Returns a promise whose resolved value will be the next action of the given type | ||
* emitted on the emitter. If the `maxWait` parameter is specified, then at most | ||
* `maxWait` milliseconds will be waited before returning the default value `null`. | ||
* | ||
* @param emitter emitter to hook into | ||
* @param type the action type to listen on | ||
* @param maxWait the maximum time, in millis, to wait for the given action type | ||
*/ | ||
export declare function take<T>(emitter: IEmitter, type: IActionType<T>, maxWait: number): Promise<T | null>; | ||
/** | ||
* | ||
* Equivalent to `emitter.put()`, exported as an Effect for consistency. | ||
* | ||
* @param emitter the emitter to use | ||
* @param action the action to emit | ||
*/ | ||
export declare function put(emitter: IEmitter, action: IAction): void; |
@@ -0,18 +1,29 @@ | ||
/** | ||
* Equivalent to `emitter.on()`, exported as an Effect for consistency. | ||
* | ||
* @param emitter the emitter to hook into | ||
* @param type the action type to listen on | ||
* @param cb a callback called whenever the action is emitted | ||
*/ | ||
export function on(emitter, type, cb) { | ||
return emitter.on(type, cb); | ||
} | ||
export function off(emitter, type, cb) { | ||
return emitter.off(type, cb); | ||
} | ||
/** | ||
* Listens for `emitter.on()`, invokes the callback exactly once, and then unlistens. | ||
* Returns a handle which, when called, cancels this effect. | ||
* | ||
* @param emitter the emitter to hook into | ||
* @param type the action type to listen on | ||
* @param cb a callback called exactly once when the next action is emitted | ||
*/ | ||
export function once(emitter, type, cb) { | ||
const handler = (value) => { | ||
emitter.off(type, handler); | ||
const destroy = emitter.on(type, (value) => { | ||
destroy(); | ||
cb(value); | ||
}; | ||
emitter.on(type, handler); | ||
return { cancel: () => emitter.off(type, handler) }; | ||
}); | ||
return destroy; | ||
} | ||
export function take(emitter, type, maxWait) { | ||
return new Promise((resolve) => { | ||
const o = once(emitter, type, (value) => { | ||
const unsubscribe = once(emitter, type, (value) => { | ||
if (handle !== 0) { | ||
@@ -23,7 +34,14 @@ clearTimeout(handle); | ||
}); | ||
const handle = maxWait !== undefined ? setTimeout(o.cancel, maxWait) : 0; | ||
const handle = maxWait !== undefined ? setTimeout(unsubscribe, maxWait) : 0; | ||
}); | ||
} | ||
/** | ||
* | ||
* Equivalent to `emitter.put()`, exported as an Effect for consistency. | ||
* | ||
* @param emitter the emitter to use | ||
* @param action the action to emit | ||
*/ | ||
export function put(emitter, action) { | ||
emitter.put(action); | ||
} |
@@ -5,6 +5,5 @@ import { IAction, IActionType, IEmitter } from "./types"; | ||
private end; | ||
put({ type, payload }: IAction): void; | ||
on<T>(type: IActionType<T>, handler: (payload: T) => void): void; | ||
off<T>(type: IActionType<T>, handler: (payload: T) => void): void; | ||
put(action: IAction): void; | ||
on<T>(type: IActionType<T>, handler: (payload: T) => void): () => void; | ||
private drain; | ||
} |
@@ -7,4 +7,4 @@ import { Chain } from "./utils/Chain"; | ||
} | ||
put({ type, payload }) { | ||
const next = { type, payload, next: null }; | ||
put(action) { | ||
const next = { type: action.type, payload: action.payload, next: null }; | ||
if (this.end !== null) { | ||
@@ -25,8 +25,5 @@ this.end = this.end.next = next; | ||
chain.add(handler); | ||
} | ||
off(type, handler) { | ||
const chain = this.chains.get(type); | ||
if (chain !== undefined) { | ||
return () => { | ||
chain.remove(handler); | ||
} | ||
}; | ||
} | ||
@@ -33,0 +30,0 @@ drain() { |
export { defineAction } from "./defineAction"; | ||
export { off, on, once, put, take } from "./effects"; | ||
export { on, once, put, take } from "./effects"; | ||
export { Emitter } from "./Emitter"; | ||
export { Store } from "./Store"; | ||
export { IAction, IActionDefinition, IActionType, IEmitter, IStore } from "./types"; |
export { defineAction } from "./defineAction"; | ||
export { off, on, once, put, take } from "./effects"; | ||
export { on, once, put, take } from "./effects"; | ||
export { Emitter } from "./Emitter"; | ||
export { Store } from "./Store"; |
@@ -6,2 +6,8 @@ import { IAction, IStore } from "./types"; | ||
private chain; | ||
/** | ||
* Constructs a Store with the given initial state and dispatch function. | ||
* | ||
* @param state initial state | ||
* @param dispatch function called whenever a React component emits an Action using `dispatch()` | ||
*/ | ||
constructor(state: S, dispatch: (action: IAction) => void); | ||
@@ -8,0 +14,0 @@ getState(): S; |
import { Chain } from "./utils/Chain"; | ||
import { defer } from "./utils/defer"; | ||
export class Store { | ||
/** | ||
* Constructs a Store with the given initial state and dispatch function. | ||
* | ||
* @param state initial state | ||
* @param dispatch function called whenever a React component emits an Action using `dispatch()` | ||
*/ | ||
constructor(state, dispatch) { | ||
@@ -5,0 +11,0 @@ this.state = state; |
@@ -0,8 +1,41 @@ | ||
/** | ||
* Variant of the standard Flux Standard Action type used by Tinysaga. | ||
* When an Action is given to an Emitter, the handlers of the given `type` | ||
* will be called with the action's `payload`. | ||
* | ||
* For constructing Actions to use with Tinysaga, prefer using ActionDefinitions | ||
* created with `defineAction()`. | ||
*/ | ||
export interface IAction { | ||
/** | ||
* Type of the action, like "ReloadUsers" | ||
*/ | ||
type: string; | ||
payload: unknown; | ||
/** | ||
* The payload associated with this action. | ||
*/ | ||
payload: any; | ||
} | ||
/** | ||
* This class is a typesafe wrapper for creating Actions. Using `defineAction()`, consumers can | ||
* create typesafe paylods by invoking the definition as a function. | ||
* | ||
* ``` | ||
* const LoadUser = defineAction<{ id: string }>("LoadUser"); | ||
* // the following line is typesafe | ||
* dispatch(LoadUser({ id: "4" })); | ||
* ``` | ||
*/ | ||
export declare type IActionDefinition<T> = { | ||
/** | ||
* The Action type string, used for registering handlers via Emitter.on() | ||
*/ | ||
TYPE: IActionType<T>; | ||
/** | ||
* Convenience TypeScript type for higher order type arithmetic | ||
*/ | ||
__payload: T; | ||
/** | ||
* Constructs an instance of this Action using the definition's `type` and this `payload` | ||
*/ | ||
(payload: T): { | ||
@@ -21,13 +54,70 @@ type: string; | ||
}; | ||
/** | ||
* An event bus in Tinysaga which accepts `{ type, payload }` Actions | ||
* and invokes all listeners of the given `type` with the `payload`. | ||
* | ||
* Note: The Tinysaga emitter operates as a _strict_ event queue, which means | ||
* emitting Actions from a previous listener being called will *enqueue the action for | ||
* later processing*, rather than allowing reentrant action loop processing. | ||
* | ||
* This design choice was made specifically to avoid two different listeners seeing the same | ||
* events in different orders. If your workflow requires reentrant event processing, consider rewriting your code | ||
* to not rely on the special ordering or managing your own eventing structure for those needs. | ||
* | ||
* For constructing an emitter, use the Emitter class. | ||
*/ | ||
export interface IEmitter { | ||
/** | ||
* Emits a new Action onto this emitter. If the emitter is already notifying listeners | ||
* of a previous Action, this followup `action` will be added to a queue for later processing. | ||
* | ||
* @param action the action to emit | ||
*/ | ||
put(action: IAction): void; | ||
on<T>(type: IActionType<T>, handler: (payload: T) => void): void; | ||
off<T>(type: IActionType<T>, handler: (payload: T) => void): void; | ||
/** | ||
* Listens for Actions of a given Type to enter the emitter, invoking the given callback | ||
* with the Action's payload. Returns a cleanup function that, when called, will stop | ||
* notifying the handler of further Actions, similar to Store.subscribe() in Redux. | ||
* | ||
* @param type | ||
* @param handler | ||
*/ | ||
on<T>(type: IActionType<T>, handler: (payload: T) => void): () => void; | ||
} | ||
/** | ||
* A Store type included with Tinysaga. This Store can be handed directly to React-Redux | ||
* and will completely replace the Redux needs of some applications. | ||
* | ||
* For constructing a store, use the Store class. | ||
*/ | ||
export interface IStore<S> { | ||
/** | ||
* Ths state of the store. Applications should feel free to reference this value directly, | ||
* rather than using getState(). | ||
*/ | ||
readonly state: S; | ||
/** | ||
* The state of the store as a getter function, required for React-Redux integration. | ||
*/ | ||
getState(): S; | ||
/** | ||
* Directly sets the new state of the store. If this state reference is different from the old one, | ||
* listeners will be notified on the next tick. If you'd like to notify listeners sooner (e.g. to | ||
* _synchronously_ repaint your UI), use store.flush() immediately after store.setState(). | ||
*/ | ||
setState(nextState: S): void; | ||
/** | ||
* Subscribes to changes from this store, required for React-Redux integrations. Applications | ||
* should generally not need to subscribe() to the Store, preferring instead to handle | ||
* update logic as part of their Emitter handler logic. | ||
* | ||
* @param cb | ||
*/ | ||
subscribe(cb: () => void): () => void; | ||
/** | ||
* Flushes any pending listener notifications synchronously, rather than waiting until the next tick. | ||
* The default behavior to wait a tick is to prevent multiple synchronous repaints to the same Redux tree, | ||
* e.g. if two different handlers for an Action both wrote to the same Store. | ||
*/ | ||
flush(): void; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defineAction = void 0; | ||
/** | ||
* Defines a new Action type for typesafe action handling. | ||
* | ||
* @param type the Action type string being defined | ||
*/ | ||
function defineAction(type) { | ||
@@ -5,0 +10,0 @@ const definition = ((payload) => ({ type, payload })); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.put = exports.take = exports.once = exports.off = exports.on = void 0; | ||
exports.put = exports.take = exports.once = exports.on = void 0; | ||
/** | ||
* Equivalent to `emitter.on()`, exported as an Effect for consistency. | ||
* | ||
* @param emitter the emitter to hook into | ||
* @param type the action type to listen on | ||
* @param cb a callback called whenever the action is emitted | ||
*/ | ||
function on(emitter, type, cb) { | ||
@@ -8,13 +15,16 @@ return emitter.on(type, cb); | ||
exports.on = on; | ||
function off(emitter, type, cb) { | ||
return emitter.off(type, cb); | ||
} | ||
exports.off = off; | ||
/** | ||
* Listens for `emitter.on()`, invokes the callback exactly once, and then unlistens. | ||
* Returns a handle which, when called, cancels this effect. | ||
* | ||
* @param emitter the emitter to hook into | ||
* @param type the action type to listen on | ||
* @param cb a callback called exactly once when the next action is emitted | ||
*/ | ||
function once(emitter, type, cb) { | ||
const handler = (value) => { | ||
emitter.off(type, handler); | ||
const destroy = emitter.on(type, (value) => { | ||
destroy(); | ||
cb(value); | ||
}; | ||
emitter.on(type, handler); | ||
return { cancel: () => emitter.off(type, handler) }; | ||
}); | ||
return destroy; | ||
} | ||
@@ -24,3 +34,3 @@ exports.once = once; | ||
return new Promise((resolve) => { | ||
const o = once(emitter, type, (value) => { | ||
const unsubscribe = once(emitter, type, (value) => { | ||
if (handle !== 0) { | ||
@@ -31,6 +41,13 @@ clearTimeout(handle); | ||
}); | ||
const handle = maxWait !== undefined ? setTimeout(o.cancel, maxWait) : 0; | ||
const handle = maxWait !== undefined ? setTimeout(unsubscribe, maxWait) : 0; | ||
}); | ||
} | ||
exports.take = take; | ||
/** | ||
* | ||
* Equivalent to `emitter.put()`, exported as an Effect for consistency. | ||
* | ||
* @param emitter the emitter to use | ||
* @param action the action to emit | ||
*/ | ||
function put(emitter, action) { | ||
@@ -37,0 +54,0 @@ emitter.put(action); |
@@ -10,4 +10,4 @@ "use strict"; | ||
} | ||
put({ type, payload }) { | ||
const next = { type, payload, next: null }; | ||
put(action) { | ||
const next = { type: action.type, payload: action.payload, next: null }; | ||
if (this.end !== null) { | ||
@@ -28,8 +28,5 @@ this.end = this.end.next = next; | ||
chain.add(handler); | ||
} | ||
off(type, handler) { | ||
const chain = this.chains.get(type); | ||
if (chain !== undefined) { | ||
return () => { | ||
chain.remove(handler); | ||
} | ||
}; | ||
} | ||
@@ -36,0 +33,0 @@ drain() { |
@@ -6,3 +6,2 @@ "use strict"; | ||
var effects_1 = require("./effects"); | ||
Object.defineProperty(exports, "off", { enumerable: true, get: function () { return effects_1.off; } }); | ||
Object.defineProperty(exports, "on", { enumerable: true, get: function () { return effects_1.on; } }); | ||
@@ -9,0 +8,0 @@ Object.defineProperty(exports, "once", { enumerable: true, get: function () { return effects_1.once; } }); |
@@ -7,2 +7,8 @@ "use strict"; | ||
class Store { | ||
/** | ||
* Constructs a Store with the given initial state and dispatch function. | ||
* | ||
* @param state initial state | ||
* @param dispatch function called whenever a React component emits an Action using `dispatch()` | ||
*/ | ||
constructor(state, dispatch) { | ||
@@ -9,0 +15,0 @@ this.state = state; |
{ | ||
"name": "tinysaga", | ||
"version": "0.3.3", | ||
"version": "0.4.0", | ||
"main": "lib/index.js", | ||
@@ -5,0 +5,0 @@ "module": "esm/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27032
695