better-call 0.0.0-experimental.7f728d4b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +254 -0
  3. package/dist/error.cjs +67 -0
  4. package/dist/error.cjs.map +1 -0
  5. package/dist/error.d.cts +46 -0
  6. package/dist/error.d.mts +46 -0
  7. package/dist/error.mjs +64 -0
  8. package/dist/error.mjs.map +1 -0
  9. package/dist/fn.cjs +335 -0
  10. package/dist/fn.cjs.map +1 -0
  11. package/dist/fn.d.cts +286 -0
  12. package/dist/fn.d.mts +286 -0
  13. package/dist/fn.mjs +335 -0
  14. package/dist/fn.mjs.map +1 -0
  15. package/dist/index.cjs +37 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +46 -0
  18. package/dist/index.d.mts +46 -0
  19. package/dist/index.mjs +24 -0
  20. package/dist/index.mjs.map +1 -0
  21. package/dist/module.cjs +111 -0
  22. package/dist/module.cjs.map +1 -0
  23. package/dist/module.d.cts +249 -0
  24. package/dist/module.d.mts +249 -0
  25. package/dist/module.mjs +102 -0
  26. package/dist/module.mjs.map +1 -0
  27. package/dist/plugins/http.cjs +185 -0
  28. package/dist/plugins/http.cjs.map +1 -0
  29. package/dist/plugins/http.d.cts +2155 -0
  30. package/dist/plugins/http.d.mts +2155 -0
  31. package/dist/plugins/http.mjs +175 -0
  32. package/dist/plugins/http.mjs.map +1 -0
  33. package/dist/schema.cjs +166 -0
  34. package/dist/schema.cjs.map +1 -0
  35. package/dist/schema.d.cts +201 -0
  36. package/dist/schema.d.mts +201 -0
  37. package/dist/schema.mjs +159 -0
  38. package/dist/schema.mjs.map +1 -0
  39. package/dist/scope.d.cts +18 -0
  40. package/dist/scope.d.mts +18 -0
  41. package/dist/storage.cjs +256 -0
  42. package/dist/storage.cjs.map +1 -0
  43. package/dist/storage.d.cts +195 -0
  44. package/dist/storage.d.mts +195 -0
  45. package/dist/storage.mjs +253 -0
  46. package/dist/storage.mjs.map +1 -0
  47. package/dist/types.d.cts +8 -0
  48. package/dist/types.d.mts +8 -0
  49. package/dist/var.cjs +162 -0
  50. package/dist/var.cjs.map +1 -0
  51. package/dist/var.d.cts +36 -0
  52. package/dist/var.d.mts +36 -0
  53. package/dist/var.mjs +154 -0
  54. package/dist/var.mjs.map +1 -0
  55. package/package.json +70 -0
package/dist/fn.d.cts ADDED
@@ -0,0 +1,286 @@
1
+ import { FnError } from "./error.cjs";
2
+ import { LiteralString, Prettify } from "./types.cjs";
3
+ import { InferArgs, InferInput, OutputSchemaOf, vTypes } from "./schema.cjs";
4
+ import { VarDefination } from "./var.cjs";
5
+ import { ApplyOns, Module, ModuleFns, OnEntry, TargetMatches, VarGetContext, VarSetContext, WithDerived } from "./module.cjs";
6
+ import { ResolvedVars, ScopeOf, VarName, VarScope } from "./scope.cjs";
7
+ //#region src/fn.d.ts
8
+ type ParentContext = Record<string, any>;
9
+ /** The call shape: a TUPLE input spreads - one parameter per position,
10
+ * the parent context last. Everything else takes (input?, parent?). */
11
+ type CallArgs<A, I> = I extends readonly unknown[] ? A extends readonly unknown[] ? [...A] | [...A, ParentContext] : never : [A] extends [void] ? [input?: undefined, parent?: ParentContext] : [input: A, parent?: ParentContext];
12
+ /** The union of a fn's DECLARED errors, as thrown values. */
13
+ type FnErrorsOf<Er> = { [T in keyof Er & string]: FnError<T, InferInput<Er[T]>>; }[keyof Er & string];
14
+ /** The declared-error union of a fn - for typing catch sites. */
15
+ type FnErrors<F> = F extends FnDefination<any, any, any, any, any, infer Er> ? FnErrorsOf<Er> : never;
16
+ type TryResult<R, Er> = R extends Promise<infer V> ? Promise<{
17
+ ok: true;
18
+ value: V;
19
+ } | {
20
+ ok: false;
21
+ error: FnErrorsOf<Er>;
22
+ }> : {
23
+ ok: true;
24
+ value: R;
25
+ } | {
26
+ ok: false;
27
+ error: FnErrorsOf<Er>;
28
+ };
29
+ /** No declared errors - the default error channel. */
30
+ type NoErrors = Record<never, never>;
31
+ /** The `use` half of `.with`: fn overrides by name, recursing into
32
+ * GROUPS so a nested binding can be overridden too. A var alias takes a
33
+ * SEED for the var it points at. */
34
+ type WithFns<U> = { [K in keyof U]?: U[K] extends FnDefination<any, any, any, any, any, any> ? BoundFn<U[K]> : U[K] extends VarDefination<any, infer T, any, any> ? T : WithFns<U[K]>; };
35
+ /** The context `.with` accepts: any var of the fn's WHOLE chain scope
36
+ * (the builder's `use` included, not just the fn's own), plus any `use`
37
+ * fn as an override - and nothing else. Kept as PLAIN mapped types: with
38
+ * `RV`/`U` unknown both halves collapse to `{}`, which keeps every
39
+ * `extends FnDefination<any, ...>` structural check passing. */
40
+ type WithContext<RV, U> = { [K in keyof RV]?: RV[K]; } & WithFns<U>;
41
+ /** What `.with` returns: the same callable, context baked in. */
42
+ interface BoundCall<A, R, I, Er> {
43
+ (...args: CallArgs<A, I>): R;
44
+ try(...args: CallArgs<A, I>): TryResult<R, Er>;
45
+ }
46
+ interface FnDefination<A, R, K extends string = string, I = unknown, P extends readonly string[] = readonly string[], Er = NoErrors, RV = unknown, U = unknown, O = unknown> {
47
+ (...args: CallArgs<A, I>): R;
48
+ /**
49
+ * Call with DECLARED errors caught as a value: `{ ok: true, value }`
50
+ * or `{ ok: false, error }`, narrowed by `error.tag`. Only tagged,
51
+ * expected errors become results - defects and contract violations
52
+ * still throw, exactly as they should.
53
+ */
54
+ try(...args: CallArgs<A, I>): TryResult<R, Er>;
55
+ /**
56
+ * Call with a HAND-BUILT context. Keys naming a var SEED that var in a
57
+ * fresh scope; keys naming a `use` fn OVERRIDE that binding for the
58
+ * whole subtree below. Both are typed from the fn's chain - what the
59
+ * BUILDER mounted counts, so `signOut.with({ user })` type-checks even
60
+ * though `signOut` itself never says `use: [user]`. A parent passed to
61
+ * the bound call is FORKED: its vars are copied in, never written back.
62
+ */
63
+ with(context: WithContext<RV, U>): BoundCall<A, R, I, Er>;
64
+ /** Brand, so a plugin module can be scanned for its fns. */
65
+ readonly $fn: true;
66
+ /** The name interceptors target - literal, so `ApplyOn` can match it. */
67
+ readonly key: K;
68
+ /** The declared contract, retained AS WRITTEN for runtime
69
+ * introspection (tool cards, docs renderers): the raw input/output
70
+ * schemas, error tag map, and required vars. Optional so structural
71
+ * `extends FnDefination` checks keep passing for hand-built fns. */
72
+ readonly $schema?: {
73
+ input?: unknown;
74
+ output?: unknown;
75
+ errors?: Record<string, unknown>;
76
+ requires?: readonly string[];
77
+ /** Declared idempotence - same args, same result, safe to repeat. */
78
+ idempotent?: boolean;
79
+ };
80
+ /** Vars this fn promises to set when ITS OWN body runs - the literal
81
+ * list, readable by graph tooling at both type and runtime level. */
82
+ readonly provides: P;
83
+ /** Phantom: the raw declared input, so extensions of the vars it
84
+ * references can widen used-fn call sites. Never set at runtime. */
85
+ readonly $input?: I;
86
+ /** Phantom: the raw declared output, the counterpart of `$input` - the
87
+ * schema as written, for type-level introspection. Never set at runtime. */
88
+ readonly $output?: O;
89
+ /** Phantom: declared error tags -> payload schemas. */
90
+ readonly $errors?: Er;
91
+ }
92
+ type ArgsOf<I> = I extends readonly unknown[] ? { -readonly [K in keyof I]: InferArgs<I[K]>; } : unknown extends I ? void : InferArgs<I>;
93
+ type OptionType<I, O, P, Q, PL, RO extends boolean = boolean, Er = any> = {
94
+ /**
95
+ * The fn's DECLARED failures: tag -> payload schema. The THIRD
96
+ * contract door - input validates on entry, output on exit, errors at
97
+ * `throw c.error(tag, data)`. Once declared, any UNTAGGED throw
98
+ * escaping the body is a defect and comes out as `UnexpectedError` -
99
+ * callers can tell a domain refusal from a bug without string
100
+ * matching.
101
+ */
102
+ errors?: Er;
103
+ /**
104
+ * A readonly fn cannot write vars - not in its handler, not in
105
+ * anything it calls, not from interceptors mounted on it. Enforced at
106
+ * the type level (vars readonly on `c`, declared writers uncallable)
107
+ * and at runtime (the whole subtree's store locks).
108
+ */
109
+ readonly?: RO;
110
+ /**
111
+ * Declared idempotence: calling with the same args always produces the
112
+ * same result and repeating the call is harmless - a read, a lookup, a
113
+ * pure computation. Part of the retained contract (`$schema`), so
114
+ * hosts may DEDUPE calls: the script engine serves repeated
115
+ * same-args calls to an idempotent fn from one dispatch per session.
116
+ * Note this is a different promise than `readonly` (writes no vars) -
117
+ * an fn can be readonly and still hit a non-idempotent API.
118
+ */
119
+ idempotent?: boolean;
120
+ input?: I;
121
+ /**
122
+ * The fn's return contract. A bare schema is BOTH the signature and
123
+ * the exit check; the wrapper `{ def?, validation? }` splits them -
124
+ * `{ def }` documents the return (tool cards, handler typing) without
125
+ * runtime validation, `validation` is the schema the exit check runs
126
+ * (defaults to none in the wrapper form).
127
+ */
128
+ output?: O;
129
+ /** Vars this fn guarantees to set. Checked on exit. */
130
+ provides?: P;
131
+ /** Vars that must already be set. Checked on entry, before the body. */
132
+ requires?: Q;
133
+ /**
134
+ * Module namespaces to pull in. Their vars come into scope, their fns
135
+ * land directly on `c` already bound to this context (a plain-record
136
+ * member nests as a NAMESPACE: `c.cookies.setCookie`), and their `on`
137
+ * entries stay active for everything below.
138
+ */
139
+ use?: PL;
140
+ };
141
+ /** A used fn, with the parent context already applied. A tuple-input fn
142
+ * keeps its positional signature. */
143
+ type BoundFn<F> = F extends FnDefination<infer A, infer R, string, infer I, any, any> ? I extends readonly unknown[] ? A extends readonly unknown[] ? (...args: [...A]) => R : never : [A] extends [void] ? () => R : (input: A) => R : never;
144
+ /** Keys of a usable map whose member is a VAR alias. */
145
+ type UseVarKeys<U> = { [K in keyof U]: U[K] extends VarDefination<any, any, any, any> ? K : never; }[keyof U];
146
+ /** A var alias' surface: the var's VALUE, read and written in place. */
147
+ type UseVarValue<V> = V extends VarDefination<any, infer T, any, any> ? T : never;
148
+ type UseApi<U> = Prettify<{ [K in Exclude<keyof U, UseVarKeys<U>>]: U[K] extends FnDefination<any, any, any, any, any, any> ? BoundFn<U[K]> : UseApi<U[K]>; } & { [K in UseVarKeys<U>]: UseVarValue<U[K]>; }>;
149
+ /** Used fns inside a readonly fn: declared writers become uncallable,
150
+ * with the reason on hover instead of a generic type error; var aliases
151
+ * become readonly properties. */
152
+ type ReadUseApi<U> = Prettify<{ [K in Exclude<keyof U, UseVarKeys<U>>]: U[K] extends FnDefination<any, any, any, any, infer P, any> ? P extends readonly [] ? BoundFn<U[K]> : `writes "${P[number] & string}" - not callable from a readonly fn` : ReadUseApi<U[K]>; } & { readonly [K in UseVarKeys<U>]: UseVarValue<U[K]>; }>;
153
+ type Context<I, RV, Required, U = unknown, FnApi = Fn, RO extends boolean = false, Errs = NoErrors> = {
154
+ input: InferInput<I>;
155
+ /**
156
+ * Mint a DECLARED error - tag-checked, payload validated at creation:
157
+ * `throw c.error("invalid_credentials", { attempts: 3 })`. Only tags
158
+ * from this fn's `errors` exist; the payload validates like input.
159
+ */
160
+ error: <T extends keyof Errs & string>(tag: T, ...data: Record<never, never> extends InferArgs<Errs[T]> ? [data?: InferArgs<Errs[T]>] : [data: InferArgs<Errs[T]>]) => FnError<T, InferInput<Errs[T]>>;
161
+ /** Define fns from inside: this fn's scope and key carry over, so
162
+ * anything built here is typed exactly like a chained builder. */
163
+ fn: FnApi;
164
+ /** The schema constructors (string, number, object, ...). */
165
+ types: typeof vTypes;
166
+ } & /** Every var in scope, directly on `c`: read `c.session`, write by
167
+ * plain assignment (`c.session = {...}`). Every var is a readonly
168
+ * property on a readonly fn. */ VarScope<RV, Required, RO> &
169
+ /** Fns from `use`, directly on `c` and already threaded with this
170
+ * context: `c.createUser({...})`. */
171
+ (RO extends true ? ReadUseApi<U> : UseApi<U>);
172
+ type InferReturn<O> = unknown extends O ? unknown : InferInput<OutputSchemaOf<O>>;
173
+ interface Fn<Base = unknown, BaseFns = unknown, BasePL extends readonly Module[] = [], Prefix extends string = ""> {
174
+ /**
175
+ * The builder FN is a schema too: `create: v.fn` (never called) declares
176
+ * "any function" - typed `(...args: any[]) => any`, runtime checks only
177
+ * `typeof value === "function"`.
178
+ */
179
+ readonly $fnSchema: {
180
+ input?: unknown;
181
+ output?: unknown;
182
+ };
183
+ /**
184
+ * "A fn with THIS signature", as a schema: `create: v.fn.type({ input,
185
+ * output })` types the field as that fn and validates what a signature
186
+ * CAN be validated for - the value is a function, and a plain closure
187
+ * gets the declared input checked at its door on every call.
188
+ *
189
+ * This exists apart from a handler-less `v.fn({ input, output })` for
190
+ * INLINE use: `v.fn`'s handler overloads return a callable, which makes
191
+ * TypeScript defer any inline `v.fn(...)` call inside another generic
192
+ * call's arguments (higher-order inference) - the enclosing `v.object`/
193
+ * `v.var` then loses its shape inference entirely. `v.fn.type` returns a
194
+ * plain carrier, so it composes inline anywhere.
195
+ */
196
+ readonly type: <I = unknown, O = unknown>(signature?: {
197
+ input?: I;
198
+ output?: O;
199
+ }) => {
200
+ readonly $fnSchema: {
201
+ input?: I;
202
+ output?: O;
203
+ };
204
+ };
205
+ <R>(fn: (ctx: Context<unknown, ScopeOf<[], Base, BasePL>, never, BaseFns, Fn<Base, BaseFns, BasePL, Prefix>>) => R): FnDefination<void, R, Prefix extends "" ? string : Prefix, unknown, readonly string[], NoErrors, ScopeOf<[], Base, BasePL>, BaseFns>;
206
+ <K extends LiteralString, R>(key: K, fn: (ctx: Context<unknown, ScopeOf<[], Base, BasePL>, never, BaseFns, Fn<Base, BaseFns, BasePL, `${Prefix}${K}`>>) => R): FnDefination<void, R, `${Prefix}${K}`, unknown, readonly string[], NoErrors, ScopeOf<[], Base, BasePL>, BaseFns>;
207
+ <const I, O, R extends InferReturn<O> | Promise<InferReturn<O>>, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], RO extends boolean = false, Er extends Record<string, unknown> = NoErrors>(options: OptionType<I, O, P, Q, PL, RO, Er>, fn: (ctx: Context<I, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, WithDerived<PL, BasePL, Q[number]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, Fn<Base & ResolvedVars<PL>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, readonly [...BasePL, ...PL], Prefix>, RO, Er>) => R): FnDefination<ArgsOf<I>, R, Prefix extends "" ? string : Prefix, I, P, Er, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, O>;
208
+ <K extends LiteralString, const I, O, R extends InferReturn<O> | Promise<InferReturn<O>>, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], RO extends boolean = false, Er extends Record<string, unknown> = NoErrors>(key: K, options: OptionType<I, O, P, Q, PL, RO, Er>, fn: (ctx: Context<I, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, WithDerived<PL, BasePL, Q[number]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, Fn<Base & ResolvedVars<PL>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, readonly [...BasePL, ...PL], `${Prefix}${K}`>, RO, Er>) => R): FnDefination<ArgsOf<I>, R, `${Prefix}${K}`, I, P, Er, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, O>;
209
+ <K extends LiteralString>(key: K): Instance<Base, BaseFns, BasePL, `${Prefix}${K}`>;
210
+ <I, O, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly []>(options: OptionType<I, O, P, Q, PL>): Instance<Base & ResolvedVars<PL>, BaseFns & ApplyOns<ModuleFns<PL>, PL>, readonly [...BasePL, ...PL], Prefix, I, O>;
211
+ <K extends LiteralString, I, O, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly []>(key: K, options: OptionType<I, O, P, Q, PL>): Instance<Base & ResolvedVars<PL>, BaseFns & ApplyOns<ModuleFns<PL>, PL>, readonly [...BasePL, ...PL], `${Prefix}${K}`, I, O>;
212
+ }
213
+ /** Every target worth suggesting on a builder's `on`: the mounted fns'
214
+ * keys (prefix-stripped, so they are valid RELATIVE targets), the scope's
215
+ * var-write events by name, and the two wildcards. Arbitrary strings stay
216
+ * legal - these only feed completion. */
217
+ type OnTargetSuggest<Base, BaseFns, Prefix extends string> = FnTargetSuggest<BaseFns, Prefix> | `var.set.${keyof ScopeOf<[], Base> & string}` | "var.set.*" | `var.get.${keyof ScopeOf<[], Base> & string}` | "var.get.*" | "*";
218
+ type FnTargetSuggest<Fns, Prefix extends string> = { [K in keyof Fns]: Fns[K] extends FnDefination<any, any, infer FK, any, any, any> ? FK extends `${Prefix}${infer Rest}` ? Rest : never : never; }[keyof Fns];
219
+ type VarNameOfT<T extends string> = T extends `var.${"set" | "get"}.${infer N}` ? N extends `${string}*${string}` ? string : N : string;
220
+ /** The scope's value for a var-event target - `unknown` when inexact. */
221
+ type VarValueOfT<T extends string, Base> = VarNameOfT<T> extends keyof ScopeOf<[], Base> ? ScopeOf<[], Base>[VarNameOfT<T>] : unknown;
222
+ /** The fns among `Fns` whose key the (already prefixed) target hits. */
223
+ type MatchedFn<Fns, T extends string> = { [K in keyof Fns]: Fns[K] extends FnDefination<any, any, infer FK, any, any, any> ? TargetMatches<T, FK & string> extends true ? Fns[K] : never : never; }[keyof Fns];
224
+ /** The intercepted input: the matched fn's (a union under wildcards),
225
+ * or an open record when the target names nothing the builder knows. */
226
+ type MatchedInput<F> = [F] extends [never] ? Record<string, any> : F extends FnDefination<any, any, any, infer I, any, any> ? InferInput<I> : never;
227
+ /** What `next()` resolves to: the matched fn's own result. */
228
+ type MatchedResult<F> = [F] extends [never] ? any : F extends FnDefination<any, infer R, any, any, any, any> ? Awaited<R> : never;
229
+ /** What a builder-scoped `on` handler sees: vars and `use` fns directly
230
+ * on `c` from the builder, `input` from the TARGET fn when known. */
231
+ type OnContext<Base, BaseFns, F, Ext = unknown> = {
232
+ input: MatchedInput<F> & (unknown extends Ext ? unknown : InferInput<Ext>);
233
+ types: typeof vTypes;
234
+ fn: unknown;
235
+ } & VarScope<ScopeOf<[], Base>, never> & UseApi<BaseFns>;
236
+ /** `v.on`, scoped: string targets get the builder's key prefix; the
237
+ * handler's `c` and `next()` are typed against the matched target fn. */
238
+ interface InstanceOn<Base, BaseFns, Prefix extends string> {
239
+ /** A fn REFERENCE targets its own key - never prefixed, fully typed
240
+ * from the fn itself plus the builder's scope. */
241
+ <F extends FnDefination<any, any, string, any, any, any>>(target: F, handler: (c: OnContext<Base, BaseFns, F>, next: () => Promise<MatchedResult<F>>) => any): OnEntry<F["key"]>;
242
+ /** Var-write events: never prefixed (vars are global), and `value`
243
+ * is typed from the builder's scope when the target is exact. */
244
+ <T extends `var.set.${keyof ScopeOf<[], Base> & string}` | "var.set.*" | `var.set.${string}`>(target: T, handler: (c: VarSetContext<VarNameOfT<T>> & {
245
+ value: VarValueOfT<T, Base>;
246
+ }, next: () => void) => void): OnEntry<T>;
247
+ /** Var-read events: `next()` yields the stored value and the handler's
248
+ * return becomes the read result - typed from the scope when exact. */
249
+ <T extends `var.get.${keyof ScopeOf<[], Base> & string}` | "var.get.*" | `var.get.${string}`>(target: T, handler: (c: VarGetContext<VarNameOfT<T>>, next: () => VarValueOfT<T, Base>) => VarValueOfT<T, Base>): OnEntry<T>;
250
+ (target: RegExp, handler: (c: OnContext<Base, BaseFns, never>, next: () => Promise<any>) => any): OnEntry<string>;
251
+ <N extends OnTargetSuggest<Base, BaseFns, Prefix> | LiteralString>(target: N, handler: (c: OnContext<Base, BaseFns, MatchedFn<BaseFns, `${Prefix}${N}`>>, next: () => Promise<MatchedResult<MatchedFn<BaseFns, `${Prefix}${N}`>>>) => any): OnEntry<`${Prefix}${N}`>;
252
+ <const Ext>(target: RegExp, extend: {
253
+ input: Ext;
254
+ }, handler: (c: OnContext<Base, BaseFns, never, Ext>, next: () => Promise<any>) => any): OnEntry<string, Ext>;
255
+ <N extends OnTargetSuggest<Base, BaseFns, Prefix> | LiteralString, const Ext>(target: N, extend: {
256
+ input: Ext;
257
+ }, handler: (c: OnContext<Base, BaseFns, MatchedFn<BaseFns, `${Prefix}${N}`>, Ext>, next: () => Promise<MatchedResult<MatchedFn<BaseFns, `${Prefix}${N}`>>>) => any): OnEntry<`${Prefix}${N}`, Ext>;
258
+ }
259
+ type Instance<Base, BaseFns, PL extends readonly Module[] = [], Prefix extends string = "", I = unknown, O = unknown> = {
260
+ /** Same as `v.fn`, with this builder's key prefix and options baked in. */
261
+ fn: Fn<Base, BaseFns, PL, Prefix>;
262
+ /**
263
+ * A handler-less builder doubles as an input SCHEMA: used as `input`
264
+ * (or an input field) it declares "a FN from `input` to `output`" -
265
+ * the value crossing is the fn itself. Carries the declared schemas
266
+ * for inference here and validation at runtime (see `isFnSchema`).
267
+ */
268
+ readonly $fnSchema: {
269
+ input?: I;
270
+ output?: O;
271
+ };
272
+ /** Same as `v.on`, with the prefix on string targets and the handler
273
+ * typed against the matched target fn. */
274
+ on: InstanceOn<Base, BaseFns, Prefix>;
275
+ /**
276
+ * The context a handler on this builder receives - a TYPE carrier for
277
+ * `typeof f.ctx` (helper signatures, plugin contracts). Every handler
278
+ * context on this builder is assignable to it: `input` and `fn` are
279
+ * loosened since they vary per fn. A real context only exists per
280
+ * invocation, so this is `undefined` at runtime.
281
+ */
282
+ readonly ctx: Context<unknown, ScopeOf<[], Base, PL>, never, BaseFns, unknown>;
283
+ };
284
+ //#endregion
285
+ export { ArgsOf, BoundCall, Context, Fn, FnDefination, FnErrors, FnErrorsOf, InferReturn, Instance, InstanceOn, OptionType, ParentContext, UseApi, WithContext };
286
+ //# sourceMappingURL=fn.d.cts.map
package/dist/fn.d.mts ADDED
@@ -0,0 +1,286 @@
1
+ import { FnError } from "./error.mjs";
2
+ import { LiteralString, Prettify } from "./types.mjs";
3
+ import { InferArgs, InferInput, OutputSchemaOf, vTypes } from "./schema.mjs";
4
+ import { VarDefination } from "./var.mjs";
5
+ import { ApplyOns, Module, ModuleFns, OnEntry, TargetMatches, VarGetContext, VarSetContext, WithDerived } from "./module.mjs";
6
+ import { ResolvedVars, ScopeOf, VarName, VarScope } from "./scope.mjs";
7
+ //#region src/fn.d.ts
8
+ type ParentContext = Record<string, any>;
9
+ /** The call shape: a TUPLE input spreads - one parameter per position,
10
+ * the parent context last. Everything else takes (input?, parent?). */
11
+ type CallArgs<A, I> = I extends readonly unknown[] ? A extends readonly unknown[] ? [...A] | [...A, ParentContext] : never : [A] extends [void] ? [input?: undefined, parent?: ParentContext] : [input: A, parent?: ParentContext];
12
+ /** The union of a fn's DECLARED errors, as thrown values. */
13
+ type FnErrorsOf<Er> = { [T in keyof Er & string]: FnError<T, InferInput<Er[T]>>; }[keyof Er & string];
14
+ /** The declared-error union of a fn - for typing catch sites. */
15
+ type FnErrors<F> = F extends FnDefination<any, any, any, any, any, infer Er> ? FnErrorsOf<Er> : never;
16
+ type TryResult<R, Er> = R extends Promise<infer V> ? Promise<{
17
+ ok: true;
18
+ value: V;
19
+ } | {
20
+ ok: false;
21
+ error: FnErrorsOf<Er>;
22
+ }> : {
23
+ ok: true;
24
+ value: R;
25
+ } | {
26
+ ok: false;
27
+ error: FnErrorsOf<Er>;
28
+ };
29
+ /** No declared errors - the default error channel. */
30
+ type NoErrors = Record<never, never>;
31
+ /** The `use` half of `.with`: fn overrides by name, recursing into
32
+ * GROUPS so a nested binding can be overridden too. A var alias takes a
33
+ * SEED for the var it points at. */
34
+ type WithFns<U> = { [K in keyof U]?: U[K] extends FnDefination<any, any, any, any, any, any> ? BoundFn<U[K]> : U[K] extends VarDefination<any, infer T, any, any> ? T : WithFns<U[K]>; };
35
+ /** The context `.with` accepts: any var of the fn's WHOLE chain scope
36
+ * (the builder's `use` included, not just the fn's own), plus any `use`
37
+ * fn as an override - and nothing else. Kept as PLAIN mapped types: with
38
+ * `RV`/`U` unknown both halves collapse to `{}`, which keeps every
39
+ * `extends FnDefination<any, ...>` structural check passing. */
40
+ type WithContext<RV, U> = { [K in keyof RV]?: RV[K]; } & WithFns<U>;
41
+ /** What `.with` returns: the same callable, context baked in. */
42
+ interface BoundCall<A, R, I, Er> {
43
+ (...args: CallArgs<A, I>): R;
44
+ try(...args: CallArgs<A, I>): TryResult<R, Er>;
45
+ }
46
+ interface FnDefination<A, R, K extends string = string, I = unknown, P extends readonly string[] = readonly string[], Er = NoErrors, RV = unknown, U = unknown, O = unknown> {
47
+ (...args: CallArgs<A, I>): R;
48
+ /**
49
+ * Call with DECLARED errors caught as a value: `{ ok: true, value }`
50
+ * or `{ ok: false, error }`, narrowed by `error.tag`. Only tagged,
51
+ * expected errors become results - defects and contract violations
52
+ * still throw, exactly as they should.
53
+ */
54
+ try(...args: CallArgs<A, I>): TryResult<R, Er>;
55
+ /**
56
+ * Call with a HAND-BUILT context. Keys naming a var SEED that var in a
57
+ * fresh scope; keys naming a `use` fn OVERRIDE that binding for the
58
+ * whole subtree below. Both are typed from the fn's chain - what the
59
+ * BUILDER mounted counts, so `signOut.with({ user })` type-checks even
60
+ * though `signOut` itself never says `use: [user]`. A parent passed to
61
+ * the bound call is FORKED: its vars are copied in, never written back.
62
+ */
63
+ with(context: WithContext<RV, U>): BoundCall<A, R, I, Er>;
64
+ /** Brand, so a plugin module can be scanned for its fns. */
65
+ readonly $fn: true;
66
+ /** The name interceptors target - literal, so `ApplyOn` can match it. */
67
+ readonly key: K;
68
+ /** The declared contract, retained AS WRITTEN for runtime
69
+ * introspection (tool cards, docs renderers): the raw input/output
70
+ * schemas, error tag map, and required vars. Optional so structural
71
+ * `extends FnDefination` checks keep passing for hand-built fns. */
72
+ readonly $schema?: {
73
+ input?: unknown;
74
+ output?: unknown;
75
+ errors?: Record<string, unknown>;
76
+ requires?: readonly string[];
77
+ /** Declared idempotence - same args, same result, safe to repeat. */
78
+ idempotent?: boolean;
79
+ };
80
+ /** Vars this fn promises to set when ITS OWN body runs - the literal
81
+ * list, readable by graph tooling at both type and runtime level. */
82
+ readonly provides: P;
83
+ /** Phantom: the raw declared input, so extensions of the vars it
84
+ * references can widen used-fn call sites. Never set at runtime. */
85
+ readonly $input?: I;
86
+ /** Phantom: the raw declared output, the counterpart of `$input` - the
87
+ * schema as written, for type-level introspection. Never set at runtime. */
88
+ readonly $output?: O;
89
+ /** Phantom: declared error tags -> payload schemas. */
90
+ readonly $errors?: Er;
91
+ }
92
+ type ArgsOf<I> = I extends readonly unknown[] ? { -readonly [K in keyof I]: InferArgs<I[K]>; } : unknown extends I ? void : InferArgs<I>;
93
+ type OptionType<I, O, P, Q, PL, RO extends boolean = boolean, Er = any> = {
94
+ /**
95
+ * The fn's DECLARED failures: tag -> payload schema. The THIRD
96
+ * contract door - input validates on entry, output on exit, errors at
97
+ * `throw c.error(tag, data)`. Once declared, any UNTAGGED throw
98
+ * escaping the body is a defect and comes out as `UnexpectedError` -
99
+ * callers can tell a domain refusal from a bug without string
100
+ * matching.
101
+ */
102
+ errors?: Er;
103
+ /**
104
+ * A readonly fn cannot write vars - not in its handler, not in
105
+ * anything it calls, not from interceptors mounted on it. Enforced at
106
+ * the type level (vars readonly on `c`, declared writers uncallable)
107
+ * and at runtime (the whole subtree's store locks).
108
+ */
109
+ readonly?: RO;
110
+ /**
111
+ * Declared idempotence: calling with the same args always produces the
112
+ * same result and repeating the call is harmless - a read, a lookup, a
113
+ * pure computation. Part of the retained contract (`$schema`), so
114
+ * hosts may DEDUPE calls: the script engine serves repeated
115
+ * same-args calls to an idempotent fn from one dispatch per session.
116
+ * Note this is a different promise than `readonly` (writes no vars) -
117
+ * an fn can be readonly and still hit a non-idempotent API.
118
+ */
119
+ idempotent?: boolean;
120
+ input?: I;
121
+ /**
122
+ * The fn's return contract. A bare schema is BOTH the signature and
123
+ * the exit check; the wrapper `{ def?, validation? }` splits them -
124
+ * `{ def }` documents the return (tool cards, handler typing) without
125
+ * runtime validation, `validation` is the schema the exit check runs
126
+ * (defaults to none in the wrapper form).
127
+ */
128
+ output?: O;
129
+ /** Vars this fn guarantees to set. Checked on exit. */
130
+ provides?: P;
131
+ /** Vars that must already be set. Checked on entry, before the body. */
132
+ requires?: Q;
133
+ /**
134
+ * Module namespaces to pull in. Their vars come into scope, their fns
135
+ * land directly on `c` already bound to this context (a plain-record
136
+ * member nests as a NAMESPACE: `c.cookies.setCookie`), and their `on`
137
+ * entries stay active for everything below.
138
+ */
139
+ use?: PL;
140
+ };
141
+ /** A used fn, with the parent context already applied. A tuple-input fn
142
+ * keeps its positional signature. */
143
+ type BoundFn<F> = F extends FnDefination<infer A, infer R, string, infer I, any, any> ? I extends readonly unknown[] ? A extends readonly unknown[] ? (...args: [...A]) => R : never : [A] extends [void] ? () => R : (input: A) => R : never;
144
+ /** Keys of a usable map whose member is a VAR alias. */
145
+ type UseVarKeys<U> = { [K in keyof U]: U[K] extends VarDefination<any, any, any, any> ? K : never; }[keyof U];
146
+ /** A var alias' surface: the var's VALUE, read and written in place. */
147
+ type UseVarValue<V> = V extends VarDefination<any, infer T, any, any> ? T : never;
148
+ type UseApi<U> = Prettify<{ [K in Exclude<keyof U, UseVarKeys<U>>]: U[K] extends FnDefination<any, any, any, any, any, any> ? BoundFn<U[K]> : UseApi<U[K]>; } & { [K in UseVarKeys<U>]: UseVarValue<U[K]>; }>;
149
+ /** Used fns inside a readonly fn: declared writers become uncallable,
150
+ * with the reason on hover instead of a generic type error; var aliases
151
+ * become readonly properties. */
152
+ type ReadUseApi<U> = Prettify<{ [K in Exclude<keyof U, UseVarKeys<U>>]: U[K] extends FnDefination<any, any, any, any, infer P, any> ? P extends readonly [] ? BoundFn<U[K]> : `writes "${P[number] & string}" - not callable from a readonly fn` : ReadUseApi<U[K]>; } & { readonly [K in UseVarKeys<U>]: UseVarValue<U[K]>; }>;
153
+ type Context<I, RV, Required, U = unknown, FnApi = Fn, RO extends boolean = false, Errs = NoErrors> = {
154
+ input: InferInput<I>;
155
+ /**
156
+ * Mint a DECLARED error - tag-checked, payload validated at creation:
157
+ * `throw c.error("invalid_credentials", { attempts: 3 })`. Only tags
158
+ * from this fn's `errors` exist; the payload validates like input.
159
+ */
160
+ error: <T extends keyof Errs & string>(tag: T, ...data: Record<never, never> extends InferArgs<Errs[T]> ? [data?: InferArgs<Errs[T]>] : [data: InferArgs<Errs[T]>]) => FnError<T, InferInput<Errs[T]>>;
161
+ /** Define fns from inside: this fn's scope and key carry over, so
162
+ * anything built here is typed exactly like a chained builder. */
163
+ fn: FnApi;
164
+ /** The schema constructors (string, number, object, ...). */
165
+ types: typeof vTypes;
166
+ } & /** Every var in scope, directly on `c`: read `c.session`, write by
167
+ * plain assignment (`c.session = {...}`). Every var is a readonly
168
+ * property on a readonly fn. */ VarScope<RV, Required, RO> &
169
+ /** Fns from `use`, directly on `c` and already threaded with this
170
+ * context: `c.createUser({...})`. */
171
+ (RO extends true ? ReadUseApi<U> : UseApi<U>);
172
+ type InferReturn<O> = unknown extends O ? unknown : InferInput<OutputSchemaOf<O>>;
173
+ interface Fn<Base = unknown, BaseFns = unknown, BasePL extends readonly Module[] = [], Prefix extends string = ""> {
174
+ /**
175
+ * The builder FN is a schema too: `create: v.fn` (never called) declares
176
+ * "any function" - typed `(...args: any[]) => any`, runtime checks only
177
+ * `typeof value === "function"`.
178
+ */
179
+ readonly $fnSchema: {
180
+ input?: unknown;
181
+ output?: unknown;
182
+ };
183
+ /**
184
+ * "A fn with THIS signature", as a schema: `create: v.fn.type({ input,
185
+ * output })` types the field as that fn and validates what a signature
186
+ * CAN be validated for - the value is a function, and a plain closure
187
+ * gets the declared input checked at its door on every call.
188
+ *
189
+ * This exists apart from a handler-less `v.fn({ input, output })` for
190
+ * INLINE use: `v.fn`'s handler overloads return a callable, which makes
191
+ * TypeScript defer any inline `v.fn(...)` call inside another generic
192
+ * call's arguments (higher-order inference) - the enclosing `v.object`/
193
+ * `v.var` then loses its shape inference entirely. `v.fn.type` returns a
194
+ * plain carrier, so it composes inline anywhere.
195
+ */
196
+ readonly type: <I = unknown, O = unknown>(signature?: {
197
+ input?: I;
198
+ output?: O;
199
+ }) => {
200
+ readonly $fnSchema: {
201
+ input?: I;
202
+ output?: O;
203
+ };
204
+ };
205
+ <R>(fn: (ctx: Context<unknown, ScopeOf<[], Base, BasePL>, never, BaseFns, Fn<Base, BaseFns, BasePL, Prefix>>) => R): FnDefination<void, R, Prefix extends "" ? string : Prefix, unknown, readonly string[], NoErrors, ScopeOf<[], Base, BasePL>, BaseFns>;
206
+ <K extends LiteralString, R>(key: K, fn: (ctx: Context<unknown, ScopeOf<[], Base, BasePL>, never, BaseFns, Fn<Base, BaseFns, BasePL, `${Prefix}${K}`>>) => R): FnDefination<void, R, `${Prefix}${K}`, unknown, readonly string[], NoErrors, ScopeOf<[], Base, BasePL>, BaseFns>;
207
+ <const I, O, R extends InferReturn<O> | Promise<InferReturn<O>>, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], RO extends boolean = false, Er extends Record<string, unknown> = NoErrors>(options: OptionType<I, O, P, Q, PL, RO, Er>, fn: (ctx: Context<I, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, WithDerived<PL, BasePL, Q[number]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, Fn<Base & ResolvedVars<PL>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, readonly [...BasePL, ...PL], Prefix>, RO, Er>) => R): FnDefination<ArgsOf<I>, R, Prefix extends "" ? string : Prefix, I, P, Er, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, O>;
208
+ <K extends LiteralString, const I, O, R extends InferReturn<O> | Promise<InferReturn<O>>, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], RO extends boolean = false, Er extends Record<string, unknown> = NoErrors>(key: K, options: OptionType<I, O, P, Q, PL, RO, Er>, fn: (ctx: Context<I, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, WithDerived<PL, BasePL, Q[number]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, Fn<Base & ResolvedVars<PL>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, readonly [...BasePL, ...PL], `${Prefix}${K}`>, RO, Er>) => R): FnDefination<ArgsOf<I>, R, `${Prefix}${K}`, I, P, Er, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, O>;
209
+ <K extends LiteralString>(key: K): Instance<Base, BaseFns, BasePL, `${Prefix}${K}`>;
210
+ <I, O, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly []>(options: OptionType<I, O, P, Q, PL>): Instance<Base & ResolvedVars<PL>, BaseFns & ApplyOns<ModuleFns<PL>, PL>, readonly [...BasePL, ...PL], Prefix, I, O>;
211
+ <K extends LiteralString, I, O, const PL extends readonly Module[] = [], const P extends readonly VarName<ScopeOf<PL, Base>>[] = readonly [], const Q extends readonly VarName<ScopeOf<PL, Base>>[] = readonly []>(key: K, options: OptionType<I, O, P, Q, PL>): Instance<Base & ResolvedVars<PL>, BaseFns & ApplyOns<ModuleFns<PL>, PL>, readonly [...BasePL, ...PL], `${Prefix}${K}`, I, O>;
212
+ }
213
+ /** Every target worth suggesting on a builder's `on`: the mounted fns'
214
+ * keys (prefix-stripped, so they are valid RELATIVE targets), the scope's
215
+ * var-write events by name, and the two wildcards. Arbitrary strings stay
216
+ * legal - these only feed completion. */
217
+ type OnTargetSuggest<Base, BaseFns, Prefix extends string> = FnTargetSuggest<BaseFns, Prefix> | `var.set.${keyof ScopeOf<[], Base> & string}` | "var.set.*" | `var.get.${keyof ScopeOf<[], Base> & string}` | "var.get.*" | "*";
218
+ type FnTargetSuggest<Fns, Prefix extends string> = { [K in keyof Fns]: Fns[K] extends FnDefination<any, any, infer FK, any, any, any> ? FK extends `${Prefix}${infer Rest}` ? Rest : never : never; }[keyof Fns];
219
+ type VarNameOfT<T extends string> = T extends `var.${"set" | "get"}.${infer N}` ? N extends `${string}*${string}` ? string : N : string;
220
+ /** The scope's value for a var-event target - `unknown` when inexact. */
221
+ type VarValueOfT<T extends string, Base> = VarNameOfT<T> extends keyof ScopeOf<[], Base> ? ScopeOf<[], Base>[VarNameOfT<T>] : unknown;
222
+ /** The fns among `Fns` whose key the (already prefixed) target hits. */
223
+ type MatchedFn<Fns, T extends string> = { [K in keyof Fns]: Fns[K] extends FnDefination<any, any, infer FK, any, any, any> ? TargetMatches<T, FK & string> extends true ? Fns[K] : never : never; }[keyof Fns];
224
+ /** The intercepted input: the matched fn's (a union under wildcards),
225
+ * or an open record when the target names nothing the builder knows. */
226
+ type MatchedInput<F> = [F] extends [never] ? Record<string, any> : F extends FnDefination<any, any, any, infer I, any, any> ? InferInput<I> : never;
227
+ /** What `next()` resolves to: the matched fn's own result. */
228
+ type MatchedResult<F> = [F] extends [never] ? any : F extends FnDefination<any, infer R, any, any, any, any> ? Awaited<R> : never;
229
+ /** What a builder-scoped `on` handler sees: vars and `use` fns directly
230
+ * on `c` from the builder, `input` from the TARGET fn when known. */
231
+ type OnContext<Base, BaseFns, F, Ext = unknown> = {
232
+ input: MatchedInput<F> & (unknown extends Ext ? unknown : InferInput<Ext>);
233
+ types: typeof vTypes;
234
+ fn: unknown;
235
+ } & VarScope<ScopeOf<[], Base>, never> & UseApi<BaseFns>;
236
+ /** `v.on`, scoped: string targets get the builder's key prefix; the
237
+ * handler's `c` and `next()` are typed against the matched target fn. */
238
+ interface InstanceOn<Base, BaseFns, Prefix extends string> {
239
+ /** A fn REFERENCE targets its own key - never prefixed, fully typed
240
+ * from the fn itself plus the builder's scope. */
241
+ <F extends FnDefination<any, any, string, any, any, any>>(target: F, handler: (c: OnContext<Base, BaseFns, F>, next: () => Promise<MatchedResult<F>>) => any): OnEntry<F["key"]>;
242
+ /** Var-write events: never prefixed (vars are global), and `value`
243
+ * is typed from the builder's scope when the target is exact. */
244
+ <T extends `var.set.${keyof ScopeOf<[], Base> & string}` | "var.set.*" | `var.set.${string}`>(target: T, handler: (c: VarSetContext<VarNameOfT<T>> & {
245
+ value: VarValueOfT<T, Base>;
246
+ }, next: () => void) => void): OnEntry<T>;
247
+ /** Var-read events: `next()` yields the stored value and the handler's
248
+ * return becomes the read result - typed from the scope when exact. */
249
+ <T extends `var.get.${keyof ScopeOf<[], Base> & string}` | "var.get.*" | `var.get.${string}`>(target: T, handler: (c: VarGetContext<VarNameOfT<T>>, next: () => VarValueOfT<T, Base>) => VarValueOfT<T, Base>): OnEntry<T>;
250
+ (target: RegExp, handler: (c: OnContext<Base, BaseFns, never>, next: () => Promise<any>) => any): OnEntry<string>;
251
+ <N extends OnTargetSuggest<Base, BaseFns, Prefix> | LiteralString>(target: N, handler: (c: OnContext<Base, BaseFns, MatchedFn<BaseFns, `${Prefix}${N}`>>, next: () => Promise<MatchedResult<MatchedFn<BaseFns, `${Prefix}${N}`>>>) => any): OnEntry<`${Prefix}${N}`>;
252
+ <const Ext>(target: RegExp, extend: {
253
+ input: Ext;
254
+ }, handler: (c: OnContext<Base, BaseFns, never, Ext>, next: () => Promise<any>) => any): OnEntry<string, Ext>;
255
+ <N extends OnTargetSuggest<Base, BaseFns, Prefix> | LiteralString, const Ext>(target: N, extend: {
256
+ input: Ext;
257
+ }, handler: (c: OnContext<Base, BaseFns, MatchedFn<BaseFns, `${Prefix}${N}`>, Ext>, next: () => Promise<MatchedResult<MatchedFn<BaseFns, `${Prefix}${N}`>>>) => any): OnEntry<`${Prefix}${N}`, Ext>;
258
+ }
259
+ type Instance<Base, BaseFns, PL extends readonly Module[] = [], Prefix extends string = "", I = unknown, O = unknown> = {
260
+ /** Same as `v.fn`, with this builder's key prefix and options baked in. */
261
+ fn: Fn<Base, BaseFns, PL, Prefix>;
262
+ /**
263
+ * A handler-less builder doubles as an input SCHEMA: used as `input`
264
+ * (or an input field) it declares "a FN from `input` to `output`" -
265
+ * the value crossing is the fn itself. Carries the declared schemas
266
+ * for inference here and validation at runtime (see `isFnSchema`).
267
+ */
268
+ readonly $fnSchema: {
269
+ input?: I;
270
+ output?: O;
271
+ };
272
+ /** Same as `v.on`, with the prefix on string targets and the handler
273
+ * typed against the matched target fn. */
274
+ on: InstanceOn<Base, BaseFns, Prefix>;
275
+ /**
276
+ * The context a handler on this builder receives - a TYPE carrier for
277
+ * `typeof f.ctx` (helper signatures, plugin contracts). Every handler
278
+ * context on this builder is assignable to it: `input` and `fn` are
279
+ * loosened since they vary per fn. A real context only exists per
280
+ * invocation, so this is `undefined` at runtime.
281
+ */
282
+ readonly ctx: Context<unknown, ScopeOf<[], Base, PL>, never, BaseFns, unknown>;
283
+ };
284
+ //#endregion
285
+ export { ArgsOf, BoundCall, Context, Fn, FnDefination, FnErrors, FnErrorsOf, InferReturn, Instance, InstanceOn, OptionType, ParentContext, UseApi, WithContext };
286
+ //# sourceMappingURL=fn.d.mts.map