UNPKG

context

Version:

Lightweight context propagation for JavaScript and TypeScript. Create a scoped storage object, run code inside it, and read the active value anywhere down the call stack - without depending on React.

64 lines (62 loc) 1.73 kB
let vest_utils = require("vest-utils"); //#region src/context.ts const USEX_DEFAULT_ERROR_MESSAGE = "Not inside of a running context."; const EMPTY_CONTEXT = Symbol(); /** * Base context interface. */ function createContext(defaultContextValue) { let contextValue = EMPTY_CONTEXT; return { run, use, useX }; function use() { return isInsideContext() ? contextValue : defaultContextValue; } function useX(errorMessage) { (0, vest_utils.invariant)(isInsideContext(), (0, vest_utils.defaultTo)(errorMessage, USEX_DEFAULT_ERROR_MESSAGE)); return contextValue; } function run(value, cb) { const parentContext = isInsideContext() ? use() : EMPTY_CONTEXT; contextValue = value; const res = cb(); contextValue = parentContext; return res; } function isInsideContext() { return contextValue !== EMPTY_CONTEXT; } } /** * Cascading context - another implementation of context, that assumes the context value is an object. * When nesting context runs, the the values of the current layer merges with the layers above it. */ function createCascade(init) { const ctx = createContext(); return { bind, run, use: ctx.use, useX: ctx.useX }; function run(value, fn) { const parentContext = ctx.use(); const initResult = (0, vest_utils.dynamicValue)(init, value, parentContext) ?? value; const out = (0, vest_utils.assign)({}, parentContext ? parentContext : {}, initResult); return ctx.run(Object.freeze(out), fn); } function bind(value, fn) { return function(...runTimeArgs) { return run(value, function() { return fn(...runTimeArgs); }); }; } } //#endregion exports.createCascade = createCascade; exports.createContext = createContext; //# sourceMappingURL=context.cjs.map