@andrew_l/context
Version:
Like composition api but for Node.
152 lines (145 loc) • 4.34 kB
text/typescript
import { AnyFunction } from '@andrew_l/toolkit';
/**
* Wrapper around `provide/inject` function to simple usage.
*
* @param providerName - The name(s) of the providing the context.
*
* There are situations where context can come from multiple scopes. In such cases, you might need to give an array of names to provide your context, instead of just a single string.
*
* @param contextName The description for injection key symbol.
*
* @example
* const [injectTraceId, provideTraceId] = createContext<string>('withContext');
*
* // this function will returns the same trace if for execution context
* export const useTraceId = () => {
* let traceId = injectTraceId(null);
*
* if (!traceId) {
* traceId = uuidv4();
* provideTraceId(traceId);
* }
*
* return traceId;
* };
*
* @group Main
*/
declare function createContext<ContextValue>(providerName: string | string[], contextName?: string): readonly [<T extends ContextValue | null | undefined = ContextValue>(fallback?: T | (() => T)) => T extends null ? ContextValue | null : ContextValue, (contextValue: ContextValue) => ContextValue];
/**
* The callback will be invoked when the associated context completes.
*
* @example
* const fn = withContext(() => {
* onScopeDispose(() => {
* console.log(2);
* });
*
* console.log(1);
* });
*
* fn();
*
* console.log(3);
*
* // 1
* // 2
* // 3
*
* @group Main
*/
declare function onScopeDispose(fn: () => void): void;
type ProvideKey = symbol | string | number | object;
type ProvideValue<T = unknown> = T | undefined;
type InjectionKey = symbol | string | number | object;
/**
* To provide data to a descendants
* @param enterWith Enter into injection context (Experimental)
* @group Main
*/
declare function provide(key: ProvideKey, value: any, enterWith?: boolean): void;
/**
* Inject previously provided data
* @group Main
*/
declare function inject<T = any>(key: ProvideKey, defaultValue?: T | (() => T)): ProvideValue<T>;
/**
* Returns true if `inject()` can be used without warning about being called in the wrong place.
* @group Main
*/
declare function hasInjectionContext(): boolean;
declare class Scope {
detached: boolean;
/**
* @internal
*/
id: number;
/**
* @internal
*/
providers: Map<any, any>;
/**
* @internal
*/
parent: Scope | null;
/**
* @internal
*/
cleanups: (() => void)[];
/**
* @internal
*/
private _activeRuns;
constructor(detached?: boolean);
run<T>(fn: () => T): T;
stop(): void;
get active(): boolean;
}
/**
* @group Main
*/
declare function getCurrentScope(): Scope | null;
/**
* Creates a function within the injection context and returns its result. Providers/injections are only accessible within the callback function.
* @param isolated Do not inject parent providers into this context (Default: `false`)
*
* @example
* const main = withContext(() => {
* provide('user', { id: 1, name: 'Andrew' });
* doCoolStaff();
* });
*
* const doCoolStaff = () => {
* const user = inject('user');
* console.log(user); // { id: 1, name: 'Andrew' }
* };
*
* main();
*
* @group Main
*/
declare function withContext<T extends AnyFunction>(fn: T, detached?: boolean): T;
/**
* Runs a function within the injection context and returns its result. Providers/injections are only accessible inside the callback function.
* @param isolated Do not inject parent providers into this context (Default: `false`)
* @group Main
*/
declare function runWithContext<T = any>(fn: () => T, isolated?: boolean): T;
/**
* Binds the current context to the provided function. Useful for creating callbacks with the current context, such as `setTimeout` or `EventEmitter` handlers.
* @example
* const main = withContext(() => {
* provide("user", { id: 1, name: "Andrew" });
*
* setInterval(bindContext(() => {
* const user = inject("user");
* console.log(user); // { id: 1, name: 'Andrew' }
* }));
* });
*
* main();
*
* @group Main
*/
declare function bindContext<T>(fn: () => T): () => T;
export { type InjectionKey, type ProvideKey, type ProvideValue, bindContext, createContext, getCurrentScope, hasInjectionContext, inject, onScopeDispose, provide, runWithContext, withContext };