//#region src/types.d.ts declare const atomSymbol: unique symbol; declare const flowSymbol: unique symbol; declare const tagSymbol: unique symbol; declare const taggedSymbol: unique symbol; declare const controllerDepSymbol: unique symbol; declare const presetSymbol: unique symbol; declare const controllerSymbol: unique symbol; declare const tagExecutorSymbol: unique symbol; declare const typedSymbol: unique symbol; declare const resourceSymbol: unique symbol; declare const attributeSymbol: unique symbol; declare const attributedSymbol: unique symbol; declare class ParseError extends Error { readonly phase: "tag" | "flow-input"; readonly label: string; readonly cause: unknown; readonly name = "ParseError"; constructor(message: string, phase: "tag" | "flow-input", label: string, cause: unknown); } declare class FlowFault extends Error { readonly name = "FlowFault"; readonly fault: unknown; readonly flow: string; constructor(fault: unknown, flow: string | undefined); } type MaybePromise = T | Promise; type AtomState = 'idle' | 'resolving' | 'resolved' | 'failed'; declare namespace Lite { interface Scope { readonly ready: Promise; readonly tags: readonly Tagged[]; resolve(atom: Atom): Promise; controller(atom: Atom): Controller; controller(atom: Atom, options: { resolve: true; }): Promise>; controller(atom: Atom, options?: ControllerOptions): Controller | Promise>; release(atom: Atom): Promise; dispose(): Promise; flush(): Promise; run(options: ExecFlowOptions & { deps?: never; fn?: never; params?: never; }): Promise; run(options: ExecOptions): Promise>; run, const Args extends unknown[], Result>(options: ExecDepsOptions): Promise>; runStream(options: ExecFlowOptions): FlowStream; createContext(options?: CreateContextOptions): ExecutionContext; on(event: AtomState, atom: Atom, listener: (...args: Args) => void, ...params: Args): () => void; changes(atom: Atom): AsyncIterable; changes(atom: Atom, options: ChangesOptions): AsyncIterable>; changes(handle: SelectHandle): AsyncIterable; resolveStream(atom: Atom | AsyncIterator>): AsyncIterable; drain(atom: Atom | AsyncIterator>, options?: DrainOptions): Promise; select(atom: Atom, selector: (value: T) => S, options?: SelectOptions): SelectHandle; } interface CreateContextOptions { tags?: TagInput; parent?: ExecutionContext; signal?: AbortSignal; } interface ScopeOptions { extensions?: Extension[]; tags?: TagInput; presets?: Preset[]; gc?: GCOptions; } interface GCOptions { /** Enable automatic garbage collection. Default: true */ enabled?: boolean; /** Grace period before releasing (ms). Default: 3000 */ graceMs?: number; } interface Atom { readonly [atomSymbol]: true; readonly factory: AtomFactory>; readonly deps?: Record; readonly tags?: Tagged[]; readonly keepAlive?: boolean; } interface Flow { readonly [flowSymbol]: true; readonly name?: string; readonly parse?: (raw: unknown) => MaybePromise; readonly factory: FlowFactory, Yield>; readonly deps?: Record; readonly tags?: Tagged[]; /** Phantom marker carrying the flow's declared fault type; never assigned at runtime. */ readonly faultType?: Fault; readonly yieldType?: Yield; } interface FlowRunOptions { name?: string; tags?: TagInput; signal?: AbortSignal; } interface FlowControllerOptions extends FlowRunOptions { key?: string; } type FlowExecOptions = FlowRunOptions & (([NoInfer] extends [void | undefined | null] ? { input?: undefined | null; rawInput?: never; } : { input: NoInfer; rawInput?: never; }) | { rawInput: unknown; input?: never; }); type FlowExecArgs = [Input] extends [void | undefined | null] ? [] | [options: FlowExecOptions] : [options: FlowExecOptions]; type FlowPrepareOptions = FlowExecOptions & { key?: string; }; type FlowPrepareArgs = [Input] extends [void | undefined | null] ? [] | [options: FlowPrepareOptions] : [options: FlowPrepareOptions]; interface FlowInvocation { readonly flow: Flow; readonly options: FlowPrepareOptions & { tags?: Tagged[]; }; readonly key: string | undefined; readonly ready: Promise; exec(): Promise; execStream(): FlowStream; } interface FlowHandle { readonly flow: Flow; exec(...args: FlowExecArgs): Promise; execStream(...args: FlowExecArgs): FlowStream; prepare(...args: FlowPrepareArgs): FlowInvocation; } interface Resource = Record> { readonly [resourceSymbol]: true; readonly name?: string; readonly deps?: D; readonly tags?: Tagged[]; readonly ownership?: ResourceOwnership; readonly factory: ResourceFactory; } type ResourceOwnership = "boundary" | "current"; interface ContextTagWatchOptions { /** Emit the current local family synchronously while registering. */ initial?: boolean; } /** Typed tag-family storage owned by one execution context. */ interface ContextTags { /** * Replace every local family present in the input, preserving family value order. * @throws After committing when a watcher fails, or when reentrant writes do not settle. * A write that does not settle stops delivery, so watchers may not observe the committed values. */ set(input: TagInput): void; /** Get the first local value without applying the tag default. */ get(tag: Tag): T | undefined; /** Get a copy of all local values without applying the tag default. */ getMany(tag: Tag): readonly T[]; /** Get the first value from the nearest context without applying the tag default. */ seek(tag: Tag): T | undefined; /** Get copies of all values from the current context through its parents. */ seekMany(tag: Tag): readonly T[]; /** Check whether the local context stores the tag family. */ has(tag: Tag): boolean; /** * Delete the local tag family, returning true when it existed. * @throws After committing when a watcher fails. */ delete(tag: Tag): boolean; /** * Watch one local tag family. Each listener receives its own value snapshot. Listeners * present when delivery starts run once, even when another listener removes them. Each call * owns its own subscription, so the same function may be watched more than once. * * @throws When the context is closed, or when initial delivery fails. A failed initial * delivery rolls the registration back, including when the failure comes from another * watcher reached by the initial listener's own writes. */ watch(tag: Tag, listener: (values: readonly T[]) => void, options?: ContextTagWatchOptions): () => void; } /** * Context-local raw data storage. Tag helpers remain as compatibility shims; * execution contexts should use `ctx.tags`. During the 6.x migration, raw operations * using a tag symbol preserve the old bridge to a family that already exists. Such a * write uses the same watcher and failure rules as `ctx.tags.set`. */ interface ContextData { /** Get value by key */ get(key: string | symbol): unknown; /** Set value by key */ set(key: string | symbol, value: unknown): void; /** Check if key exists */ has(key: string | symbol): boolean; /** Delete value by key, returns true if existed */ delete(key: string | symbol): boolean; /** * Remove all stored values. * * @throws After committing when a watcher of a removed tag family fails. */ clear(): void; /** * Look up value by key, traversing parent chain if not found locally. * Returns first match or undefined. */ seek(key: string | symbol): unknown; /** * Look up tag value, traversing parent chain if not found locally. * Returns first match or undefined (ignores tag defaults). * * @deprecated Move raw `tag.key` writes to `ctx.tags`, then use `ctx.tags.seek(tag)`. */ seekTag(tag: Tag): T | undefined; /** * Check if key exists locally or in parent chain. */ seekHas(key: string | symbol): boolean; /** * Get value by tag, returns undefined if not stored. * * @deprecated Move raw `tag.key` writes to `ctx.tags`, then use `ctx.tags.get(tag)`. */ getTag(tag: Tag): T | undefined; /** * Set value by tag. * * @deprecated Use `ctx.tags.set(tag(value))` on execution contexts. */ setTag(tag: Tag, value: T): void; /** * Check if tag has stored value. * * @deprecated Move raw `tag.key` writes to `ctx.tags`, then use `ctx.tags.has(tag)`. */ hasTag(tag: Tag): boolean; /** * Delete value by tag, returns true if existed. * * @deprecated Use `ctx.tags.delete(tag)` on execution contexts. */ deleteTag(tag: Tag): boolean; /** * Get existing value or initialize with tag's default. * Stores and returns the value. * * @deprecated Check `ctx.tags.has(tag)` and store `tag.defaultValue` with `ctx.tags.set` when absent. */ getOrSetTag(tag: Tag): T; /** * Get existing value or initialize with provided value. * Stores and returns the value. * * @deprecated Use `ctx.tags.has(tag)` with `ctx.tags.set(tag(value))` on execution contexts. */ getOrSetTag(tag: Tag, value: T): T; /** * Get existing value or initialize with provided value. * Required for tags without defaults. * * @deprecated Use `ctx.tags.has(tag)` with `ctx.tags.set(tag(value))` on execution contexts. */ getOrSetTag(tag: Tag, value: T): T; } interface ResolveContext { cleanup(fn: (...args: Args) => MaybePromise, ...params: Args): void; invalidate(): void; /** * Release the atom generation that created this context. * * During that generation's cleanup this settles without joining its own * release. After replacement it cannot release the newer generation. */ release(): Promise; readonly scope: Scope; readonly data: ContextData; } type CloseResult = { ok: true; } | { ok: false; error: unknown; readonly aborted?: true; }; type FlowStream = AsyncIterable & { readonly result: Promise; }; interface ExecutionContext { readonly input: unknown; readonly name: string | undefined; readonly scope: Scope; readonly parent: ExecutionContext | undefined; readonly signal: AbortSignal; readonly data: ContextData; readonly tags: ContextTags; resolve(target: Atom): Promise; resolve(target: Resource): Promise; release(resource: Resource): Promise; controller(resource: Resource): ResourceController; exec(options: ExecFlowOptions): Promise; exec(options: ExecOptions): Promise>; exec, const Args extends unknown[], Result>(options: ExecDepsOptions): Promise>; execStream(options: ExecFlowOptions): FlowStream; /** * Executes a streaming child with inherited context data without joining its eventual settlement. * Abandonment aborts and closes the child while late yields and settlement are ignored. */ execDetachedStream(options: ExecFlowOptions): FlowStream; changes(atom: Atom): AsyncIterable; changes(atom: Atom, options: ChangesOptions): AsyncIterable>; changes(handle: SelectHandle): AsyncIterable; resolveStream(atom: Atom | AsyncIterator>): AsyncIterable; onClose(fn: (result: CloseResult, ...args: Args) => MaybePromise, ...params: Args): () => void; close(result?: CloseResult): Promise; /** Throws a `FlowFault` carrying `fault`, tagged with the executing flow's name. */ fail(fault: Fault): never; } interface ResourceContext extends ExecutionContext { cleanup(fn: (...args: Args) => MaybePromise, ...params: Args): void; } type ExecFlowOptions = { flow: Flow; name?: string; tags?: TagInput; signal?: AbortSignal; } & (([NoInfer] extends [void | undefined | null] ? { input?: undefined | null; rawInput?: never; } : { input: NoInfer; rawInput?: never; }) | { rawInput: unknown; input?: never; }); type ExecDepsOptions, Args extends unknown[], Result> = { name: string; deps: D; fn: (deps: InferDeps, ...args: Args) => Result; params: Args; tags?: TagInput; signal?: AbortSignal; flow?: never; } & (Extract, AsyncIterable | { next: (...args: never[]) => unknown; }> extends never ? unknown : never); type ExecOptions = { name: string; deps?: never; fn: (...args: Args) => Result; params: Args; tags?: TagInput; signal?: AbortSignal; flow?: never; } & (Extract, AsyncIterable | { next: (...args: never[]) => unknown; }> extends never ? unknown : never); type ControllerEvent = 'resolving' | 'resolved' | '*'; type ResourceControllerEvent = AtomState | '*'; /** * Reactive handle for observing and controlling atom state. */ interface Controller { readonly [controllerSymbol]: true; /** Current lifecycle state */ readonly state: AtomState; /** * Get current value synchronously. * @throws If atom is idle, failed, or in `'resolving'` state without a * prior value (first resolution not yet complete) * @returns Current value; during re-resolution returns the previous * (stale) value */ get(): T; /** Trigger resolution if not already resolved */ resolve(): Promise; /** Run cleanups and remove from cache */ release(): Promise; /** Schedule re-resolution (runs factory) */ invalidate(): void; /** * Replace the stored value without running the factory or cleanups. * Emits `'resolved'` only. Use `invalidate()` when the previous value's * resources must be released. * @throws If atom is idle or failed */ set(value: T): void; /** * Transform the stored value using a function without running the factory * or cleanups. Equivalent to `set(fn(get()))` but queued atomically. * Emits `'resolved'` only. Use `invalidate()` when the previous value's * resources must be released. * @throws If atom is idle or failed */ update(fn: (prev: T) => T): void; /** Subscribe to state changes */ on(event: ControllerEvent, listener: (...args: Args) => void, ...params: Args): () => void; } /** * Execution-context handle for observing and controlling a resource. */ interface ResourceController { /** Current lifecycle state visible from this execution context */ readonly state: AtomState; /** * Get current value synchronously. * @throws If resource is idle, resolving without a value, or failed */ get(): T; /** Trigger resolution if not already resolved */ resolve(): Promise; /** Owner-local release/reset */ release(): Promise; /** Subscribe to resource state changes visible from this execution context */ on(event: ResourceControllerEvent, listener: (...args: Args) => void, ...params: Args): () => void; } interface SelectOptions { eq?: (prev: S, next: S) => boolean; } interface SelectHandle { get(): S; subscribe(listener: (...args: Args) => void, ...params: Args): () => void; dispose(): void; } interface ChangesOptions { states: true; } interface DrainOptions { take?: number; } type AtomChange = { readonly state: "resolving"; } | { readonly state: "resolved"; readonly value: T; } | { readonly state: "failed"; readonly error: Error; }; interface Tag { readonly [tagSymbol]: true; readonly key: symbol; readonly label: string; readonly serializable: Serializable; readonly defaultValue: HasDefault extends true ? T : undefined; readonly hasDefault: HasDefault; readonly parse?: (raw: unknown) => T; eq(a: T, b: T): boolean; (value: T, options?: TaggedOptions): Tagged; same(a: Tagged, b: Tagged): boolean; get(source: TagSource): T; find(source: TagSource): HasDefault extends true ? T : T | undefined; collect(source: TagSource): T[]; atoms(): Atom[]; } interface Tagged { readonly [taggedSymbol]: true; readonly key: symbol; readonly value: T; readonly tag: Tag; readonly attributes?: readonly Attributed[]; } /** * Declaration-layer membership key: discriminates carriers of the same tag. * Attributes never enter a scope or an execution context. A carrier's bindings * of one attribute form its membership set, read with `has` and `collect`. * `select` marks whether application picking polices facts of this attribute * (default true); consumer-owned attributes declare `select: false`. */ interface Attribute { readonly [attributeSymbol]: true; readonly key: symbol; readonly label: string; readonly select: boolean; eq(a: T, b: T): boolean; (value: T): Attributed; has(source: AttributeSource, value: T): boolean; collect(source: AttributeSource): T[]; } /** Presence-only attribute for markers; never participates in application picking. */ interface Flag { readonly [attributeSymbol]: true; readonly key: symbol; readonly label: string; readonly select: false; (): Attributed; has(source: AttributeSource): boolean; } interface Attributed { readonly [attributedSymbol]: true; readonly key: symbol; readonly value: T; readonly attribute: Attribute; } type AttributeInput = Attributed | readonly AttributeInput[]; type AttributeSource = AttributeInput | { attributes?: AttributeInput; }; /** Creation options for one tagged value; the value itself stays untouched. */ interface TaggedOptions { attributes?: AttributeInput; } type TagInput = Tagged | readonly TagInput[]; type TagSource = TagInput | { tags?: TagInput; }; interface TagExecutor { readonly [tagExecutorSymbol]: true; readonly tag: Tag; readonly mode: "required" | "optional" | "all"; } interface AtomControllerDep { readonly [controllerDepSymbol]: true; readonly atom: Atom; readonly resource?: undefined; readonly resolve?: boolean; readonly watch?: boolean; readonly eq?: (a: any, b: any) => boolean; } interface ResourceControllerDep { readonly [controllerDepSymbol]: true; readonly atom?: undefined; readonly resource: Resource; readonly resolve?: boolean; readonly watch?: boolean; readonly eq?: (a: any, b: any) => boolean; } interface FlowControllerDep { readonly [controllerDepSymbol]: true; readonly atom?: undefined; readonly resource?: undefined; readonly flow: Flow; readonly name?: string; readonly tags?: Tagged[]; readonly key?: string; } type ControllerDep = AtomControllerDep | ResourceControllerDep | FlowControllerDep; type WatchControllerDep = AtomControllerDep & { readonly resolve: true; readonly watch: true; }; type NonWatchControllerDep = AtomControllerDep & { readonly watch?: never; readonly eq?: never; }; type NonWatchResourceControllerDep = ResourceControllerDep & { readonly watch?: never; readonly eq?: never; }; type WatchResourceControllerDep = ResourceControllerDep & { readonly resolve: true; readonly watch: true; }; interface ControllerOptions { resolve?: boolean; } type ControllerDepOptions = { resolve: true; watch: true; eq: (a: T, b: T) => boolean; } | { resolve: true; watch: true; eq?: never; } | { resolve: true; watch?: never; eq?: never; } | { resolve?: never; watch?: never; eq?: never; }; type ResourceControllerDepOptions = { resolve: true; watch: true; eq: (a: any, b: any) => boolean; } | { resolve: true; watch: true; eq?: never; } | { resolve: true; watch?: never; eq?: never; } | { resolve?: never; watch?: never; eq?: never; }; interface Typed { readonly [typedSymbol]: true; } type PresetTarget = Atom | Flow | Resource; type PresetValue = T | Atom | Flow | Resource | ((ctx: ExecutionContext & { readonly input: I; }) => MaybePromise | AsyncGenerator) | ((ctx: ResourceContext) => MaybePromise); interface Preset { readonly [presetSymbol]: true; readonly target: PresetTarget; readonly value: PresetValue; } /** * Discriminated context for `wrapResolve`. * * - `"atom"` — scope-level singleton. Cached after first resolve. * - `"resource"` — execution-context-owned. Fresh factory per owner miss, * with the owner selected by the resource ownership mode. */ type ResolveEvent = { readonly kind: "atom"; readonly target: Atom; readonly scope: Scope; readonly ctx: ResolveContext; } | { readonly kind: "resource"; readonly target: Resource; readonly ctx: ResourceContext; }; interface Extension { readonly name: string; init?(scope: Scope): MaybePromise; /** * Observes every execution-context creation: scope-created roots, * per-exec children, prepared-flow lifetimes, and detached streams. * Runs after context tags are seeded, before any user code receives * the context. Must be synchronous — a returned promise fails the * creation. If it throws, the error reaches the creator and the * context closes with it, notifying extensions already attached; * that closing settles inside the owning lifetime (the parent * context's close, or scope disposal for scope-created roots). */ initContext?(ctx: ExecutionContext): void; /** * Observes the context's close outcome. Runs after user `onClose` * cleanups (LIFO) and before context-owned resource teardown, so it * sees the requested outcome, not resource-teardown failures. Skipped * when this extension's own `initContext` threw for the context. */ disposeContext?(ctx: ExecutionContext, result: CloseResult): MaybePromise; /** * Wraps dependency resolution. Dispatch by `event.kind`: * * - `"atom"` — `event.scope`, `event.ctx`, `event.target: Atom`. Cached in scope. * - `"resource"` — `event.ctx`, `event.target: Resource`. Seek-up in * execution hierarchy, factory(ctx, deps) on miss. */ wrapResolve?(next: () => Promise, event: ResolveEvent): Promise; wrapExec?(next: () => Promise, target: ExecTarget, ctx: ExecutionContext): Promise; dispose?(scope: Scope): MaybePromise; } type JsonValue = string | number | boolean | null | readonly JsonValue[] | { readonly [key: string]: JsonValue; }; type Dependency = Atom | Flow | ControllerDep | TagExecutor | Resource; type AtomDependency = Atom | AtomControllerDep | TagExecutor; type ExecutionDependency = Atom | Flow | FlowControllerDep | NonWatchControllerDep | NonWatchResourceControllerDep | TagExecutor | Resource>; type ResourceDependency = Atom | Flow | FlowControllerDep | NonWatchControllerDep | ResourceControllerDep | TagExecutor | Resource>; type Projected = V extends readonly (infer E)[] ? Projected[] : V extends Flow ? FlowHandle : V; type InferDep = D extends Atom ? T : D extends Flow ? FlowHandle : D extends FlowControllerDep ? FlowHandle : D extends AtomControllerDep ? Controller : D extends ResourceControllerDep ? ResourceController : D extends TagExecutor ? Projected : D extends Resource ? T : never; type InferDeps = { [K in keyof D]: InferDep; }; type AtomFactory> = keyof D extends never ? (ctx: ResolveContext) => MaybePromise : (ctx: ResolveContext, deps: InferDeps) => MaybePromise; type FlowFactory, Yield = never> = keyof D extends never ? (ctx: ExecutionContext & { readonly input: Input; }) => MaybePromise | AsyncGenerator : (ctx: ExecutionContext & { readonly input: Input; }, deps: InferDeps) => MaybePromise | AsyncGenerator; type ResourceFactory> = keyof D extends never ? (ctx: ResourceContext) => MaybePromise : (ctx: ResourceContext, deps: InferDeps) => MaybePromise; /** * Any atom regardless of value type. * Useful for APIs that don't need the value type. */ type AnyAtom = Atom; /** * Any flow regardless of input/output types. * Useful for APIs that don't need the type parameters. */ type AnyFlow = Flow; /** * Any controller regardless of value type. */ type AnyController = Controller; /** * Any resource regardless of value type. */ type AnyResource = Resource; /** Target observed by the execution extension pipeline. */ type ExecTarget = Flow | ExecTargetFn; /** Inline operation identity observed by the execution extension pipeline. */ type ExecTargetFn = (...args: any[]) => unknown; /** * Utility types for type extraction and manipulation. * @example * type Config = Lite.Utils.AtomValue * type Result = Lite.Utils.FlowOutput */ namespace Utils { /** * Extract value type from an Atom. * @example * type Config = Lite.Utils.AtomValue // string */ type AtomValue = A extends Atom ? T : never; /** * Extract output type from a Flow. * @example * type Result = Lite.Utils.FlowOutput // ProcessResult */ type FlowOutput = F extends Flow ? O : never; /** * Extract input type from a Flow. * @example * type Input = Lite.Utils.FlowInput // ProcessRequest */ type FlowInput = F extends Flow ? I : never; /** * Extract the declared fault union from a Flow. * @example * type Faults = Lite.Utils.FaultsOf // "conflict" | "not-found" */ type FaultsOf = F extends Flow ? Fault : never; /** * Extract value type from a Tag. * @example * type UserId = Lite.Utils.TagValue // string */ type TagValue = T extends Tag ? V : never; /** * Extract the deps record from an Atom or Flow declared with `AtomType`. * `atom()` erases `D`, so `DepsOf` on a plain `atom()` call returns the * index-typed `Record | undefined`. * @example * type RepoAtom = Lite.Utils.AtomType; cache: Lite.Atom }> * type RepoDeps = Lite.Utils.DepsOf // { db: Lite.Atom; cache: Lite.Atom } */ type DepsOf = T extends Atom ? T['deps'] : T extends Flow ? T['deps'] : never; /** * Flatten complex intersection types for better IDE display. */ type Simplify = { [K in keyof T]: T[K]; } & {}; /** * Create an atom type with inferred value. * Useful for declaring atom types without defining the atom. */ type AtomType = Record> = Atom & { readonly deps: D; }; /** * Create a flow type with inferred input/output. * Useful for declaring flow types without defining the flow. */ type FlowType = Record, Fault = never> = Flow & { readonly deps: D; }; /** * Extract value type from a Controller. * @example * type Value = Lite.Utils.ControllerValue // string */ type ControllerValue = C extends Controller ? T : never; } } //#endregion //#region src/tag.d.ts interface TagBaseOptions { label: string; attributes?: Lite.AttributeInput; parse?: (raw: unknown) => T; eq?: (a: T, b: T) => boolean; } type JsonField = T extends Lite.JsonValue ? T : JsonShape; type JsonShapeMember = [T] extends [(...args: never[]) => unknown] ? never : [T] extends [abstract new (...args: never[]) => unknown] ? never : [T] extends [readonly unknown[]] ? { readonly [K in keyof T]: JsonField; } : [T] extends [object] ? Extract extends never ? keyof T extends never ? never : { readonly [K in keyof T]: JsonField; } : never : [T] extends [Lite.JsonValue] ? T : never; type JsonShape = T extends unknown ? JsonShapeMember : never; type JsonObjectFields = { readonly [K in keyof T]: T[K] & Lite.JsonValue; }; type SerializableOption = [T] extends [JsonShape] ? true : [T] extends [(...args: never[]) => unknown] ? never : [T] extends [abstract new (...args: never[]) => unknown] ? never : [T] extends [readonly unknown[]] ? never : [T] extends [object] ? Extract extends never ? keyof T extends never ? never : [T] extends [JsonObjectFields] ? true : never : never : never; type DefaultOptions = boolean extends HasDefault ? { default?: T; } : HasDefault extends true ? { default: T; } : { default?: never; }; type SerializableGate = [SerializableOption] extends [never] ? never : unknown; type SerializableOptions = boolean extends Serializable ? { serializable?: boolean; } : Serializable extends true ? { serializable: true; } & SerializableGate : { serializable?: false; }; type TagOptions = TagBaseOptions & DefaultOptions & SerializableOptions; type SerializableWithoutDefault = TagBaseOptions & { default?: never; serializable: true; } & SerializableGate; type SerializableWithDefault = TagBaseOptions & { default: T; serializable: true; } & SerializableGate; type LocalWithoutDefault = TagBaseOptions & { default?: never; serializable?: false; }; type LocalWithDefault = TagBaseOptions & { default: T; serializable?: false; }; /** * Returns all tags that have been created. * * Uses WeakRef internally so tags can be garbage collected when no longer referenced. * Stale references are cleaned up lazily on each call (not between calls). * * @returns Array of all live Tag instances. Returns `Tag[]` because * the registry cannot preserve individual tag type parameters at runtime. * * Performance: O(n) where n = total tags created. For typical usage (< 100 tags), * this is negligible. Cleanup happens during query, not continuously. * * @example * ```typescript * const allTags = getAllTags() * for (const t of allTags) { * console.log(t.label, t.atoms().length) * } * ``` */ declare function getAllTags(): Lite.Tag[]; /** * Creates a metadata tag for attaching and retrieving typed values from Atoms and Flows. * * @param options - Configuration object with label and optional default value * @returns A Tag instance that can create tagged values and query them from sources * * @example * ```typescript * const name = tag({ label: "name" }) * const greeting = atom({ * factory: (ctx) => "value", * tags: name("greeting") * }) * ``` */ declare function tag(options: SerializableWithoutDefault): Lite.Tag; declare function tag(options: SerializableWithDefault): Lite.Tag; declare function tag(options: SerializableWithoutDefault): Lite.Tag; declare function tag(options: SerializableWithDefault): Lite.Tag; declare function tag(options: TagOptions): Lite.Tag; declare function tag(options: LocalWithoutDefault): Lite.Tag; declare function tag(options: LocalWithDefault): Lite.Tag; declare function tag(options: TagOptions): Lite.Tag; /** Asserts that a value contains only strict JSON data. */ declare function assertSerializable(value: unknown): asserts value is Lite.JsonValue; /** * Type guard to check if a value is a Tag. * * @param value - The value to check * @returns True if the value is a Tag, false otherwise * * @example * ```typescript * if (isTag(value)) { * const tagged = value("myValue") * } * ``` */ declare function isTag(value: unknown): value is Lite.Tag; /** * Type guard to check if a value is a Tagged value. * * @param value - The value to check * @returns True if the value is a Tagged value, false otherwise * * @example * ```typescript * if (isTagged(value)) { * console.log(value.key, value.value) * } * ``` */ declare function isTagged(value: unknown): value is Lite.Tagged; /** * Tag execution helpers for declaring how tags should be resolved from dependency sources. */ declare const tags: { /** * Creates a required tag executor that throws if the tag is not found. * * @param tag - The tag to execute * @returns A tag executor that requires the tag to be present * * @example * ```typescript * const greeting = atom({ * deps: { name: tags.required(name) }, * factory: (ctx, { name }) => `Hello ${name}` * }) * ``` */ required(tag: Lite.Tag): Lite.TagExecutor; /** * Creates an optional tag executor that returns undefined if the tag is not found. * * @param tag - The tag to execute * @returns A tag executor that allows the tag to be absent * * @example * ```typescript * const greeting = atom({ * deps: { name: tags.optional(name) }, * factory: (ctx, { name }) => name ?? "Anonymous" * }) * ``` */ optional(tag: Lite.Tag): Lite.TagExecutor; /** * Creates a tag executor that collects all values for the given tag. * * @param tag - The tag to execute * @returns A tag executor that returns an array of all matching tag values * * @example * ```typescript * const roster = atom({ * deps: { names: tags.all(name) }, * factory: (ctx, { names }) => names.join(", ") * }) * ``` */ all(tag: Lite.Tag): Lite.TagExecutor; }; /** * Type guard to check if a value is a TagExecutor. * * @param value - The value to check * @returns True if the value is a TagExecutor, false otherwise * * @example * ```typescript * if (isTagExecutor(value)) { * console.log(value.mode, value.tag) * } * ``` */ declare function isTagExecutor(value: unknown): value is Lite.TagExecutor; //#endregion //#region src/atom.d.ts /** * Creates a long-lived dependency that can be resolved and reused within a scope. * * @param config - Configuration object containing factory function, optional dependencies, and tags * @returns An Atom instance that can be resolved to produce a value of type T * * @example * ```typescript * const db = atom({ * factory: async (ctx) => { * const pool = await createDatabase() * ctx.cleanup((pool) => pool.end(), pool) * return pool * } * }) * ``` */ declare function atom(config: { deps?: undefined; factory: (ctx: Lite.ResolveContext) => MaybePromise; tags?: Lite.TagInput; keepAlive?: boolean; }): Lite.Atom; declare function atom>(config: { deps: D; factory: (ctx: Lite.ResolveContext, deps: Lite.InferDeps) => MaybePromise; tags?: Lite.TagInput; keepAlive?: boolean; }): Lite.Atom; /** * Type guard to check if a value is an Atom. * * @param value - The value to check * @returns True if the value is an Atom, false otherwise * * @example * ```typescript * if (isAtom(value)) { * await scope.resolve(value) * } * ``` */ declare function isAtom(value: unknown): value is Lite.Atom; /** * Wraps an Atom or Resource to receive a controller instead of the resolved value. * Atom controllers provide value mutation and invalidation. Resource controllers * provide execution-scoped observation plus resolve/release only. * * @param atom - The Atom or Resource to wrap * @param options - Optional configuration: * - `resolve: true` — auto-resolves the dep before the parent factory runs; `config.get()` is safe. * - `watch: true` — requires `resolve: true`; atom deps re-run the parent atom factory when * the dep resolves to a new value. Resource deps release the dependent resource on value * change and re-resolve lazily on the next access. Flow deps do not support watch. * - `eq` — custom equality function `(a: T, b: T) => boolean`; only used with `watch: true`. * @returns A ControllerDep that resolves to a Controller for the Atom or Resource * * @example * ```typescript * // resolve only * const server = atom({ * deps: { config: controller(config, { resolve: true }) }, * factory: (ctx, { config }) => { * const s = createServer(config.get().port) * ctx.cleanup((server) => server.close(), s) * return s * }, * }) * * // watch: re-runs parent when dep value changes * const profile = atom({ * deps: { token: controller(token, { resolve: true, watch: true }) }, * factory: (_, { token }) => ({ id: `user-${token.get().jwt}` }), * }) * * // watch with custom equality * const derived = atom({ * deps: { src: controller(src, { resolve: true, watch: true, eq: (a, b) => a.name === b.name }) }, * factory: (_, { src }) => src.get().name, * }) * ``` */ declare function controller(atom: Lite.Atom): Lite.NonWatchControllerDep; declare function controller(atom: Lite.Atom, options: { resolve: true; watch: true; eq: (a: T, b: T) => boolean; }): Lite.WatchControllerDep; declare function controller(atom: Lite.Atom, options: { resolve: true; watch: true; eq?: never; }): Lite.WatchControllerDep; declare function controller(atom: Lite.Atom, options: { resolve: true; watch?: never; eq?: never; }): Lite.NonWatchControllerDep; declare function controller(atom: Lite.Atom, options: { resolve?: never; watch?: never; eq?: never; }): Lite.NonWatchControllerDep; declare function controller(resource: Lite.Resource): Lite.NonWatchResourceControllerDep; declare function controller(resource: Lite.Resource, options: { resolve: true; watch?: never; eq?: never; }): Lite.NonWatchResourceControllerDep; declare function controller(resource: Lite.Resource, options: { resolve: true; watch: true; eq: (a: T, b: T) => boolean; }): Lite.WatchResourceControllerDep; declare function controller(resource: Lite.Resource, options: { resolve: true; watch: true; eq?: never; }): Lite.WatchResourceControllerDep; declare function controller(resource: Lite.Resource, options: { resolve?: never; watch?: never; eq?: never; }): Lite.NonWatchResourceControllerDep; declare function controller(flow: Lite.Flow): Lite.FlowControllerDep; declare function controller(flow: Lite.Flow, options: Lite.FlowControllerOptions): Lite.FlowControllerDep; /** * Type guard to check if a value is a ControllerDep wrapper. * * @param value - The value to check * @returns True if the value is a ControllerDep wrapper, false otherwise * * @example * ```typescript * if (isControllerDep(dep)) { * if (dep.atom) { * const ctrl = scope.controller(dep.atom) * } * } * ``` */ declare function isControllerDep(value: unknown): value is Lite.ControllerDep; //#endregion //#region src/flow.d.ts /** * Type marker for flow input without runtime parsing. * Use this when you want typed input but don't need validation. * * @example * ```typescript * const shout = flow({ * parse: typed<{ name: string }>(), * factory: (ctx) => { * return ctx.input.name.toUpperCase() * } * }) * ``` */ declare function typed(): Lite.Typed; /** * Creates a short-lived execution unit that processes input and produces output. * * @param config - Configuration object containing factory function, optional dependencies, and tags * @returns A Flow instance that can be executed within an execution context * * @example * ```typescript * const processUser = flow({ * parse: typed(), * factory: async (ctx) => { * const userId = ctx.input * return await fetchUser(userId) * } * }) * ``` */ declare function flow(config: { name?: string; parse?: undefined; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext) => never; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse?: undefined; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext, deps: Lite.InferDeps) => never; tags?: Lite.TagInput; }): Lite.Flow; declare function flow(config: { name?: string; parse?: undefined; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext) => AsyncGenerator; tags?: Lite.TagInput; }): Lite.Flow; declare function flow(config: { name?: string; parse: (raw: unknown) => MaybePromise; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }) => AsyncGenerator; tags?: Lite.TagInput; }): Lite.Flow; declare function flow(config: { name?: string; parse: Lite.Typed; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }) => AsyncGenerator; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse?: undefined; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext, deps: Lite.InferDeps) => AsyncGenerator; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse: (raw: unknown) => MaybePromise; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }, deps: Lite.InferDeps) => AsyncGenerator; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse: Lite.Typed; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }, deps: Lite.InferDeps) => AsyncGenerator; tags?: Lite.TagInput; }): Lite.Flow; declare function flow(config: { name?: string; parse?: undefined; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext) => MaybePromise; tags?: Lite.TagInput; }): Lite.Flow; declare function flow(config: { name?: string; parse: (raw: unknown) => MaybePromise; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }) => MaybePromise; tags?: Lite.TagInput; }): Lite.Flow; declare function flow(config: { name?: string; parse: Lite.Typed; deps?: undefined; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }) => MaybePromise; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse?: undefined; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext, deps: Lite.InferDeps) => MaybePromise; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse: (raw: unknown) => MaybePromise; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }, deps: Lite.InferDeps) => MaybePromise; tags?: Lite.TagInput; }): Lite.Flow; declare function flow, Fault = never>(config: { name?: string; parse: Lite.Typed; deps: D; faults?: Lite.Typed; factory: (ctx: Lite.ExecutionContext & { readonly input: NoInfer; }, deps: Lite.InferDeps) => MaybePromise; tags?: Lite.TagInput; }): Lite.Flow; /** * Type guard to check if a value is a Flow. * * @param value - The value to check * @returns True if the value is a Flow, false otherwise * * @example * ```typescript * if (isFlow(value)) { * await ctx.exec({ flow: value, input: data }) * } * ``` */ declare function isFlow(value: unknown): value is Lite.Flow; /** * Type guard narrowing an unknown error to the fault type declared by `flow`. * * Honesty note: the runtime check can only verify `error instanceof FlowFault` * and that `error.flow` matches the flow's name. It trusts the flow-name match * as a proxy for flow identity — it does not (cannot) verify that `error` was * actually thrown by this exact `flow` instance. * * @example * ```typescript * const pairPayment = flow({ * faults: typed<{ kind: "conflict"; id: string }>(), * factory: (ctx) => ctx.fail({ kind: "conflict", id: "p1" }), * }) * * async function run(ctx: Lite.ExecutionContext) { * try { * await ctx.exec({ flow: pairPayment }) * } catch (error) { * if (isFault(pairPayment, error)) { * // error.fault is typed as the fault union declared on pairPayment * } * } * } * ``` */ declare function isFault(flow: Lite.Flow, error: unknown): error is FlowFault & { fault: F; }; //#endregion //#region src/attribute.d.ts declare function normalizeAttributes(input: Lite.AttributeInput | undefined): Lite.Attributed[]; /** * Declares a membership key that discriminates carriers of the same tag. Attributes * never enter a scope or an execution context; they attach to tagged values through * the `attributes` creation option and to declarations, and are read as membership: * `has(carrier, value)` and `collect(carrier)`. `select: false` keeps facts of this * attribute out of application picking; such attributes belong to their consumers. * * @example * ```typescript * const server = attribute({ label: "pumped.server", select: false }) * server.has(route({ method: "GET", path: "/health" }, { attributes: [server("admin")] }), "admin") // true * ``` */ declare function attribute(options: { label: string; eq?: (a: T, b: T) => boolean; select?: boolean; }): Lite.Attribute; /** * Declares a presence-only attribute for markers. * * @example * ```typescript * const internal = flag({ label: "acme.internal" }) * internal.has(route({ method: "GET", path: "/debug" }, { attributes: [internal()] })) // true * ``` */ declare function flag(options: { label: string; }): Lite.Flag; declare function isAttribute(value: unknown): value is Lite.Attribute; declare function isAttributed(value: unknown): value is Lite.Attributed; //#endregion //#region src/preset.d.ts type ResourcePresetValue = (T extends ((...args: any[]) => any) ? never : T) | Lite.Resource | ((ctx: Lite.ResourceContext) => MaybePromise); /** * Creates a preset that overrides an Atom's factory within a scope. * * @param target - The Atom to preset * @param value - The preset value (can be a direct value or another Atom) * @returns A Preset instance to be used in scope configuration * * @example * ```typescript * const scope = createScope({ * presets: [preset(db, mockDatabase)] * }) * ``` */ declare function preset(target: Lite.Atom, value: T | Lite.Atom): Lite.Preset; /** * Creates a preset that overrides a Flow's execution within a scope. * * @param target - The Flow to preset * @param value - The replacement (another Flow or a function that receives ctx with parsed input) * @returns A Preset instance to be used in scope configuration * * @example * ```typescript * // Replace with another flow * const scopeA = createScope({ * presets: [preset(process, processStub)] * }) * * // Replace with a function (deps are NOT resolved) * const scopeB = createScope({ * presets: [preset(process, (ctx) => ({ result: ctx.input }))] * }) * ``` */ declare function preset(target: Lite.Flow, value: Lite.Flow | ((ctx: Lite.ExecutionContext & { readonly input: Input; }) => MaybePromise | AsyncGenerator)): Lite.Preset; /** * Creates a preset that overrides a Resource within an execution context. * * @param target - The Resource to preset * @param value - Direct value, replacement Resource, or function that receives the execution context * @returns A Preset instance to be used in scope configuration */ declare function preset(target: Lite.Resource, value: ResourcePresetValue): Lite.Preset; /** * Type guard to check if a value is a Preset. * * @param value - The value to check * @returns True if the value is a Preset, false otherwise * * @example * ```typescript * if (isPreset(value)) { * console.log(value.target, value.value) * } * ``` */ declare function isPreset(value: unknown): value is Lite.Preset; //#endregion //#region src/resource.d.ts /** * Creates an execution-context-owned dependency. * Boundary-owned resources create on the nearest execution boundary. Current-owned resources * create on the current execution boundary while `ctx.exec()` children can reuse them. * * @param config - Configuration object containing factory function and optional dependencies * @returns A Resource instance that can be declared as a dependency in flows and other resources * * @example * ```typescript * const requestId = tag({ label: "request.id" }) * * const requestLogger = resource({ * deps: { requestId: tags.required(requestId), logService }, * factory: (ctx, { requestId, logService }) => { * const logger = logService.child({ requestId }) * ctx.cleanup((logger) => logger.flush(), logger) * return logger * } * }) * ``` */ declare function resource(config: { name?: string; tags?: Lite.TagInput; ownership?: Lite.ResourceOwnership; deps?: undefined; factory: (ctx: Lite.ResourceContext) => MaybePromise; }): Lite.Resource; declare function resource>(config: { name?: string; tags?: Lite.TagInput; ownership?: Lite.ResourceOwnership; deps: D; factory: (ctx: Lite.ResourceContext, deps: Lite.InferDeps) => MaybePromise; }): Lite.Resource; /** * Type guard to check if a value is a Resource. * * @param value - The value to check * @returns True if the value is a Resource, false otherwise * * @example * ```typescript * if (isResource(value)) { * // value is Lite.Resource * } * ``` */ declare function isResource(value: unknown): value is Lite.Resource; //#endregion //#region src/streaming.d.ts declare function isStreamingExec(target: Lite.ExecTarget, ctx?: Lite.ExecutionContext): boolean; //#endregion //#region src/scope.d.ts declare function shallowEqual(a: unknown, b: unknown): boolean; /** * Registers or restores controller-read observers used by integrations that * need to track `controller.get()` access. */ declare function setControllerReadHook(fn: ((ctrl: Lite.Controller) => void) | null): void; /** * Creates a DI container that manages Atom resolution, caching, and lifecycle. * * The scope is returned synchronously, with a `ready` promise that resolves * when all extensions have been initialized. Resolution methods automatically * wait for `ready` before proceeding. * * @param options - Optional configuration for extensions, presets, and tags * @returns A Scope instance with a `ready` promise for extension initialization * * @example * ```typescript * const scope = createScope({ * extensions: [logging], * presets: [preset(db, testDb)] * }) * * // Option 1: resolve() waits for ready internally * const pool = await scope.resolve(db) * * // Option 2: explicit wait * await scope.ready * const conn = await scope.resolve(db) * ``` */ declare function createScope(options?: Lite.ScopeOptions): Lite.Scope; //#endregion //#region src/tracker.d.ts declare function registerInTracker(target: any): void; declare function startArrayTracking(tracker: { deps: any[]; len: number; }): { deps: any[]; len: number; } | null; declare function stopArrayTracking(prev: { deps: any[]; len: number; } | null): void; declare function startTracking(set: Set): Set | null; declare function stopTracking(prev: Set | null): void; //#endregion //#region src/index.d.ts /** Current package version. */ declare const VERSION: string; //#endregion export { type AtomState, FlowFault, type Lite, ParseError, VERSION, assertSerializable, atom, atomSymbol, attribute, attributeSymbol, attributedSymbol, controller, controllerDepSymbol, controllerSymbol, createScope, flag, flow, flowSymbol, getAllTags, isAtom, isAttribute, isAttributed, isControllerDep, isFault, isFlow, isPreset, isResource, isStreamingExec, isTag, isTagExecutor, isTagged, normalizeAttributes, preset, presetSymbol, registerInTracker, resource, resourceSymbol, setControllerReadHook, shallowEqual, startArrayTracking, startTracking, stopArrayTracking, stopTracking, tag, tagExecutorSymbol, tagSymbol, taggedSymbol, tags, typed, typedSymbol };