better-call 0.0.0-experimental.01ff4b77
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.
- package/LICENSE +21 -0
- package/README.md +265 -0
- package/dist/capability.cjs +417 -0
- package/dist/capability.cjs.map +1 -0
- package/dist/capability.d.cts +189 -0
- package/dist/capability.d.mts +189 -0
- package/dist/capability.mjs +401 -0
- package/dist/capability.mjs.map +1 -0
- package/dist/error.cjs +76 -0
- package/dist/error.cjs.map +1 -0
- package/dist/error.d.cts +51 -0
- package/dist/error.d.mts +51 -0
- package/dist/error.mjs +72 -0
- package/dist/error.mjs.map +1 -0
- package/dist/fn.cjs +350 -0
- package/dist/fn.cjs.map +1 -0
- package/dist/fn.d.cts +378 -0
- package/dist/fn.d.mts +378 -0
- package/dist/fn.mjs +350 -0
- package/dist/fn.mjs.map +1 -0
- package/dist/index.cjs +43 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +50 -0
- package/dist/index.d.mts +50 -0
- package/dist/index.mjs +24 -0
- package/dist/index.mjs.map +1 -0
- package/dist/module.cjs +176 -0
- package/dist/module.cjs.map +1 -0
- package/dist/module.d.cts +283 -0
- package/dist/module.d.mts +283 -0
- package/dist/module.mjs +166 -0
- package/dist/module.mjs.map +1 -0
- package/dist/plugins/db.cjs +24 -0
- package/dist/plugins/db.cjs.map +1 -0
- package/dist/plugins/db.d.cts +18 -0
- package/dist/plugins/db.d.mts +18 -0
- package/dist/plugins/db.mjs +19 -0
- package/dist/plugins/db.mjs.map +1 -0
- package/dist/plugins/http/attrs.cjs +91 -0
- package/dist/plugins/http/attrs.cjs.map +1 -0
- package/dist/plugins/http/attrs.d.cts +26 -0
- package/dist/plugins/http/attrs.d.mts +26 -0
- package/dist/plugins/http/attrs.mjs +87 -0
- package/dist/plugins/http/attrs.mjs.map +1 -0
- package/dist/plugins/http/cookie.cjs +117 -0
- package/dist/plugins/http/cookie.cjs.map +1 -0
- package/dist/plugins/http/cookie.d.cts +637 -0
- package/dist/plugins/http/cookie.d.mts +637 -0
- package/dist/plugins/http/cookie.mjs +113 -0
- package/dist/plugins/http/cookie.mjs.map +1 -0
- package/dist/plugins/http/error.cjs +39 -0
- package/dist/plugins/http/error.cjs.map +1 -0
- package/dist/plugins/http/error.d.cts +38 -0
- package/dist/plugins/http/error.d.mts +38 -0
- package/dist/plugins/http/error.mjs +35 -0
- package/dist/plugins/http/error.mjs.map +1 -0
- package/dist/plugins/http/handle.cjs +73 -0
- package/dist/plugins/http/handle.cjs.map +1 -0
- package/dist/plugins/http/handle.d.cts +955 -0
- package/dist/plugins/http/handle.d.mts +955 -0
- package/dist/plugins/http/handle.mjs +72 -0
- package/dist/plugins/http/handle.mjs.map +1 -0
- package/dist/plugins/http/redirect.cjs +82 -0
- package/dist/plugins/http/redirect.cjs.map +1 -0
- package/dist/plugins/http/redirect.d.cts +67 -0
- package/dist/plugins/http/redirect.d.mts +67 -0
- package/dist/plugins/http/redirect.mjs +79 -0
- package/dist/plugins/http/redirect.mjs.map +1 -0
- package/dist/plugins/http/request.cjs +63 -0
- package/dist/plugins/http/request.cjs.map +1 -0
- package/dist/plugins/http/request.d.cts +142 -0
- package/dist/plugins/http/request.d.mts +142 -0
- package/dist/plugins/http/request.mjs +61 -0
- package/dist/plugins/http/request.mjs.map +1 -0
- package/dist/plugins/http/response.cjs +13 -0
- package/dist/plugins/http/response.cjs.map +1 -0
- package/dist/plugins/http/response.d.cts +18 -0
- package/dist/plugins/http/response.d.mts +18 -0
- package/dist/plugins/http/response.mjs +13 -0
- package/dist/plugins/http/response.mjs.map +1 -0
- package/dist/plugins/http.cjs +64 -0
- package/dist/plugins/http.cjs.map +1 -0
- package/dist/plugins/http.d.cts +945 -0
- package/dist/plugins/http.d.mts +945 -0
- package/dist/plugins/http.mjs +37 -0
- package/dist/plugins/http.mjs.map +1 -0
- package/dist/plugins/read-only.cjs +19 -0
- package/dist/plugins/read-only.cjs.map +1 -0
- package/dist/plugins/read-only.d.cts +17 -0
- package/dist/plugins/read-only.d.mts +17 -0
- package/dist/plugins/read-only.mjs +19 -0
- package/dist/plugins/read-only.mjs.map +1 -0
- package/dist/schema.cjs +245 -0
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.cts +411 -0
- package/dist/schema.d.mts +411 -0
- package/dist/schema.mjs +235 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/scope.d.cts +31 -0
- package/dist/scope.d.mts +31 -0
- package/dist/storage.cjs +308 -0
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.d.cts +220 -0
- package/dist/storage.d.mts +220 -0
- package/dist/storage.mjs +302 -0
- package/dist/storage.mjs.map +1 -0
- package/dist/types.d.cts +8 -0
- package/dist/types.d.mts +8 -0
- package/dist/var.cjs +186 -0
- package/dist/var.cjs.map +1 -0
- package/dist/var.d.cts +46 -0
- package/dist/var.d.mts +46 -0
- package/dist/var.mjs +177 -0
- package/dist/var.mjs.map +1 -0
- package/package.json +114 -0
package/dist/fn.d.mts
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { FnError } from "./error.mjs";
|
|
2
|
+
import { LiteralString, Prettify } from "./types.mjs";
|
|
3
|
+
import { InferArgs, InferInput, OutputSchemaOf, TypeDefination, vTypes } from "./schema.mjs";
|
|
4
|
+
import { ResolvedVars, ScopeOf, VarName, VarScope } from "./scope.mjs";
|
|
5
|
+
import { ApplyOns, InputVarExtra, InputVarExtraOut, Module, ModuleFns, OnEntry, TargetMatches, VarGetContext, VarSetContext, WithDerived } from "./module.mjs";
|
|
6
|
+
import { VarDefination } from "./var.mjs";
|
|
7
|
+
//#region src/fn.d.ts
|
|
8
|
+
type ParentContext = Record<string, any>;
|
|
9
|
+
/**
|
|
10
|
+
* `{}` assignable to `A`, and `A` is not an open index signature
|
|
11
|
+
* (`Record<string, …>` / `v.object()` with no shape). Those accept any
|
|
12
|
+
* object, so omitting the arg is not the same as sending one.
|
|
13
|
+
*/
|
|
14
|
+
type EmptyExtendsArgs<A> = Record<never, never> extends A ? string extends keyof A ? false : true : false;
|
|
15
|
+
/**
|
|
16
|
+
* Callers may omit a non-tuple input when the schema is optional or
|
|
17
|
+
* defaulted, or every field is already optional to send.
|
|
18
|
+
*/
|
|
19
|
+
type InputOmittable<A, I> = I extends {
|
|
20
|
+
$var: true;
|
|
21
|
+
schema?: infer S;
|
|
22
|
+
} ? InputOmittable<A, NonNullable<S>> : I extends TypeDefination<any, any, infer D> ? [D] extends [never] ? EmptyExtendsArgs<A> : true : EmptyExtendsArgs<A>;
|
|
23
|
+
/** The call shape: a TUPLE input spreads - one parameter per position,
|
|
24
|
+
* the parent context last. No input, or an omittable one, takes
|
|
25
|
+
* `(input?, parent?)`; required inputs stay required. */
|
|
26
|
+
type CallArgs<A, I> = I extends readonly unknown[] ? A extends readonly unknown[] ? [...A] | [...A, ParentContext] : never : [A] extends [void] ? [input?: undefined, parent?: ParentContext] : InputOmittable<A, I> extends true ? [input?: A, parent?: ParentContext] : [input: A, parent?: ParentContext];
|
|
27
|
+
/** The union of a fn's DECLARED errors, as thrown values. */
|
|
28
|
+
type FnErrorsOf<Er> = { [T in keyof Er & string]: FnError<T, InferInput<Er[T]>>; }[keyof Er & string];
|
|
29
|
+
/** The declared-error union of a fn - for typing catch sites. */
|
|
30
|
+
type FnErrors<F> = F extends FnDefination<any, any, any, any, any, infer Er> ? FnErrorsOf<Er> : never;
|
|
31
|
+
/** Non-distributive `never` guard first: a naked `R extends Promise`
|
|
32
|
+
* distributes over `never` into `never`, and `[never] extends [Promise<_>]`
|
|
33
|
+
* is also true (bottom type). Always-throwing bodies need a sync result. */
|
|
34
|
+
type TryResult<R, Er> = [R] extends [never] ? {
|
|
35
|
+
ok: true;
|
|
36
|
+
value: never;
|
|
37
|
+
} | {
|
|
38
|
+
ok: false;
|
|
39
|
+
error: FnErrorsOf<Er>;
|
|
40
|
+
} : R extends Promise<infer V> ? Promise<{
|
|
41
|
+
ok: true;
|
|
42
|
+
value: V;
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
error: FnErrorsOf<Er>;
|
|
46
|
+
}> : {
|
|
47
|
+
ok: true;
|
|
48
|
+
value: R;
|
|
49
|
+
} | {
|
|
50
|
+
ok: false;
|
|
51
|
+
error: FnErrorsOf<Er>;
|
|
52
|
+
};
|
|
53
|
+
/** No declared errors - the default error channel. */
|
|
54
|
+
type NoErrors = Record<never, never>;
|
|
55
|
+
/** The `use` half of `.with`: fn overrides by name, recursing into
|
|
56
|
+
* GROUPS so a nested binding can be overridden too. A var alias takes a
|
|
57
|
+
* SEED for the var it points at. */
|
|
58
|
+
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]>; };
|
|
59
|
+
/** The context `.with` accepts: any var of the fn's WHOLE chain scope
|
|
60
|
+
* (the builder's `use` included, not just the fn's own), plus any `use`
|
|
61
|
+
* fn as an override - and nothing else. Kept as PLAIN mapped types: with
|
|
62
|
+
* `RV`/`U` unknown both halves collapse to `{}`, which keeps every
|
|
63
|
+
* `extends FnDefination<any, ...>` structural check passing.
|
|
64
|
+
*
|
|
65
|
+
* Prefer {@link WithSeed} for values stored on {@link FnDefination} - it
|
|
66
|
+
* is what `v.fn` returns, and stays declaration-emit safe. */
|
|
67
|
+
type WithContext<RV, U> = { [K in keyof RV]?: RV[K]; } & WithFns<U>;
|
|
68
|
+
/** Storage (or the FnEntries slice of one): `$models` plus callable
|
|
69
|
+
* `$adapter`. Nested under a module as `{ db }`, it must not flow into
|
|
70
|
+
* `.with` seeds - model schemas alone blow past declaration serialize
|
|
71
|
+
* limits. ModuleFns keeps collections; WithSeed still drops storage. */
|
|
72
|
+
type StorageLike = {
|
|
73
|
+
$models: object;
|
|
74
|
+
$adapter: (...args: never[]) => unknown;
|
|
75
|
+
};
|
|
76
|
+
/** Flatten `use` members to `.with` overrides: bound call signatures, var
|
|
77
|
+
* alias values, nested groups. Storage is dropped (mount-only). */
|
|
78
|
+
type WithFnsSeed<U> = { [K in keyof U as U[K] extends StorageLike ? never : K]?: U[K] extends FnDefination<any, any, any, any, any, any> ? BoundFn<U[K]> : U[K] extends VarDefination<any, infer T, any, any> ? T : WithFnsSeed<U[K]>; };
|
|
79
|
+
/**
|
|
80
|
+
* Flat `.with` seed map stored on exported fns. Evaluating ScopeOf /
|
|
81
|
+
* ModuleFns here (instead of embedding those wrappers as type arguments)
|
|
82
|
+
* keeps declaration emit small: `.d.ts` shows leaf var shapes and bound
|
|
83
|
+
* call signatures, not `ScopeOf<ResolvedVars<entire module graph>>`.
|
|
84
|
+
*/
|
|
85
|
+
type WithSeed<RV, U> = Prettify<{ [K in keyof RV]?: RV[K]; } & WithFnsSeed<U>>;
|
|
86
|
+
/** What `v.fn` / `e.fn` returns: contract params plus a flat {@link WithSeed}
|
|
87
|
+
* for `.with`, never the raw ScopeOf / ModuleFns graph. */
|
|
88
|
+
type PublicFn<A, R, K extends string, I, P extends readonly string[], Er, RV, U, O = unknown> = FnDefination<A, R, K, I, P, Er, WithSeed<RV, U>, O>;
|
|
89
|
+
/** What `.with` returns: the same callable, context baked in. */
|
|
90
|
+
interface BoundCall<A, R, I, Er> {
|
|
91
|
+
(...args: CallArgs<A, I>): R;
|
|
92
|
+
try(...args: CallArgs<A, I>): TryResult<R, Er>;
|
|
93
|
+
}
|
|
94
|
+
interface FnDefination<A, R, K extends string = string, I = unknown, P extends readonly string[] = readonly string[], Er = NoErrors,
|
|
95
|
+
/** `.with` seed map ({@link WithSeed}). Defaults keep structural
|
|
96
|
+
* `extends FnDefination<any, ...>` checks passing. */
|
|
97
|
+
W = unknown, O = unknown> {
|
|
98
|
+
(...args: CallArgs<A, I>): R;
|
|
99
|
+
/**
|
|
100
|
+
* Call with DECLARED errors caught as a value: `{ ok: true, value }`
|
|
101
|
+
* or `{ ok: false, error }`, narrowed by `error.tag`. Only tagged,
|
|
102
|
+
* expected errors become results - defects and contract violations
|
|
103
|
+
* still throw, exactly as they should.
|
|
104
|
+
*/
|
|
105
|
+
try(...args: CallArgs<A, I>): TryResult<R, Er>;
|
|
106
|
+
/**
|
|
107
|
+
* Call with a HAND-BUILT context. Keys naming a var SEED that var in a
|
|
108
|
+
* fresh scope; keys naming a `use` fn OVERRIDE that binding for the
|
|
109
|
+
* whole subtree below. Both are typed from the fn's chain - what the
|
|
110
|
+
* BUILDER mounted counts, so `signOut.with({ user })` type-checks even
|
|
111
|
+
* though `signOut` itself never says `use: [user]`. A parent passed to
|
|
112
|
+
* the bound call is FORKED: its vars are copied in, never written back.
|
|
113
|
+
*/
|
|
114
|
+
with(context: W): BoundCall<A, R, I, Er>;
|
|
115
|
+
/** Brand, so a plugin module can be scanned for its fns. */
|
|
116
|
+
readonly $fn: true;
|
|
117
|
+
/** The name interceptors target - literal, so `ApplyOn` can match it. */
|
|
118
|
+
readonly key: K;
|
|
119
|
+
/** The declared contract, retained AS WRITTEN for runtime
|
|
120
|
+
* introspection (tool cards, docs renderers): the raw input/output
|
|
121
|
+
* schemas, error tag map, and required vars. Optional so structural
|
|
122
|
+
* `extends FnDefination` checks keep passing for hand-built fns. */
|
|
123
|
+
readonly $schema?: {
|
|
124
|
+
input?: unknown;
|
|
125
|
+
output?: unknown;
|
|
126
|
+
errors?: Record<string, unknown>;
|
|
127
|
+
requires?: readonly string[];
|
|
128
|
+
/** Declared idempotence - same args, same result, safe to repeat. */
|
|
129
|
+
idempotent?: boolean;
|
|
130
|
+
};
|
|
131
|
+
/** Vars this fn promises to set when ITS OWN body runs - the literal
|
|
132
|
+
* list, readable by graph tooling at both type and runtime level. */
|
|
133
|
+
readonly provides: P;
|
|
134
|
+
/** Phantom: the raw declared input, so extensions of the vars it
|
|
135
|
+
* references can widen used-fn call sites. Never set at runtime. */
|
|
136
|
+
readonly $input?: I;
|
|
137
|
+
/** Phantom: the raw declared output, the counterpart of `$input` - the
|
|
138
|
+
* schema as written, for type-level introspection. Never set at runtime. */
|
|
139
|
+
readonly $output?: O;
|
|
140
|
+
/** Phantom: declared error tags -> payload schemas. */
|
|
141
|
+
readonly $errors?: Er;
|
|
142
|
+
}
|
|
143
|
+
type ArgsOf<I> = I extends readonly unknown[] ? { -readonly [K in keyof I]: InferArgs<I[K]>; } : unknown extends I ? void : InferArgs<I>;
|
|
144
|
+
/**
|
|
145
|
+
* Call args of a declaring fn: the declared input, plus whatever mounted
|
|
146
|
+
* `v.extend` / same-name shadows add for vars that input references.
|
|
147
|
+
* Mirrors {@link ApplyOn} so `input: user` + `use: [userWithEmail]` types
|
|
148
|
+
* the door the same way a used call site would.
|
|
149
|
+
*/
|
|
150
|
+
type WidenedArgs<I, ExtPL> = unknown extends InputVarExtra<ExtPL, I> ? ArgsOf<I> : Prettify<([ArgsOf<I>] extends [void] ? unknown : ArgsOf<I>) & InputVarExtra<ExtPL, I>>;
|
|
151
|
+
type OptionType<I, O, P, Q, PL, RO extends boolean = boolean, Er = any> = {
|
|
152
|
+
/**
|
|
153
|
+
* The fn's DECLARED failures: tag -> payload schema. The THIRD
|
|
154
|
+
* contract door - input validates on entry, output on exit, errors at
|
|
155
|
+
* `throw c.error(tag, data)`. Once declared, any UNTAGGED throw
|
|
156
|
+
* escaping the body is a defect and comes out as `UnexpectedError` -
|
|
157
|
+
* callers can tell a domain refusal from a bug without string
|
|
158
|
+
* matching.
|
|
159
|
+
*/
|
|
160
|
+
errors?: Er;
|
|
161
|
+
/**
|
|
162
|
+
* A readonly fn cannot write vars - not in its handler, not in
|
|
163
|
+
* anything it calls, not from interceptors mounted on it. Enforced at
|
|
164
|
+
* the type level (vars readonly on `c`, declared writers uncallable)
|
|
165
|
+
* and at runtime (the whole subtree's store locks).
|
|
166
|
+
*/
|
|
167
|
+
readonly?: RO;
|
|
168
|
+
/**
|
|
169
|
+
* Declared idempotence: calling with the same args always produces the
|
|
170
|
+
* same result and repeating the call is harmless - a read, a lookup, a
|
|
171
|
+
* pure computation. Part of the retained contract (`$schema`), so
|
|
172
|
+
* hosts may DEDUPE calls: the script engine serves repeated
|
|
173
|
+
* same-args calls to an idempotent fn from one dispatch per session.
|
|
174
|
+
* Note this is a different promise than `readonly` (writes no vars) -
|
|
175
|
+
* an fn can be readonly and still hit a non-idempotent API.
|
|
176
|
+
*/
|
|
177
|
+
idempotent?: boolean;
|
|
178
|
+
input?: I;
|
|
179
|
+
/**
|
|
180
|
+
* The fn's return contract. A bare schema is BOTH the signature and
|
|
181
|
+
* the exit check; the wrapper `{ def?, validation? }` splits them -
|
|
182
|
+
* `{ def }` documents the return (tool cards, handler typing) without
|
|
183
|
+
* runtime validation, `validation` is the schema the exit check runs
|
|
184
|
+
* (defaults to none in the wrapper form).
|
|
185
|
+
*/
|
|
186
|
+
output?: O;
|
|
187
|
+
/** Vars this fn guarantees to set. Checked on exit. */
|
|
188
|
+
provides?: P;
|
|
189
|
+
/** Vars that must already be set. Checked on entry, before the body. */
|
|
190
|
+
requires?: Q;
|
|
191
|
+
/**
|
|
192
|
+
* Module namespaces to pull in. Their vars come into scope, their fns
|
|
193
|
+
* land directly on `c` already bound to this context (a plain-record
|
|
194
|
+
* member nests as a NAMESPACE: `c.cookies.setCookie`), and their `on`
|
|
195
|
+
* entries stay active for everything below.
|
|
196
|
+
*/
|
|
197
|
+
use?: PL;
|
|
198
|
+
};
|
|
199
|
+
/** A used fn, with the parent context already applied. A tuple-input fn
|
|
200
|
+
* keeps its positional signature. Omittable inputs match {@link CallArgs}. */
|
|
201
|
+
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 : InputOmittable<A, I> extends true ? (input?: A) => R : (input: A) => R : never;
|
|
202
|
+
/** Keys of a usable map whose member is a VAR alias. */
|
|
203
|
+
type UseVarKeys<U> = { [K in keyof U]: U[K] extends VarDefination<any, any, any, any> ? K : never; }[keyof U];
|
|
204
|
+
/**
|
|
205
|
+
* VarDefination surface keys. ModuleFns intersects a merge var with
|
|
206
|
+
* same-key namespace helpers (`VarDef & { createUser }`); stripping these
|
|
207
|
+
* leaves the helper group for {@link UseApi}.
|
|
208
|
+
*/
|
|
209
|
+
type VarSurfaceKeys = "$var" | "name" | "default" | "schema" | "type" | "$source" | "$attrs" | "$merge" | "customize";
|
|
210
|
+
type MergeHelpersOnVar<V> = Omit<V, VarSurfaceKeys>;
|
|
211
|
+
/** Bound helpers intersected onto a merge var in ModuleFns, if any. */
|
|
212
|
+
type UseApiMergeExtras<V> = V extends {
|
|
213
|
+
$merge: true;
|
|
214
|
+
} ? [keyof MergeHelpersOnVar<V>] extends [never] ? never : UseApi<MergeHelpersOnVar<V>> : never;
|
|
215
|
+
/**
|
|
216
|
+
* A var alias' surface: the var's VALUE, plus same-key namespace helpers
|
|
217
|
+
* when the var is `merge: true` (mirrors {@link collectMergeSeeds} /
|
|
218
|
+
* {@link viewMergeVar}).
|
|
219
|
+
*/
|
|
220
|
+
type UseVarValue<V> = V extends VarDefination<any, infer T, any, any> ? UseApiMergeExtras<V> extends (infer H) ? [H] extends [never] ? T : Prettify<T & H> : T : never;
|
|
221
|
+
/**
|
|
222
|
+
* Fold merge-var helpers from the usable map `U` onto scope values keyed
|
|
223
|
+
* by DECLARED name (so `c.vt_merge_db.byTag` types when the export key
|
|
224
|
+
* was `db`).
|
|
225
|
+
*/
|
|
226
|
+
type MergeIntoScope<RV, U> = { [K in keyof RV]: HelpersForDeclaredName<K & string, U> extends (infer H) ? [H] extends [never] ? RV[K] : Prettify<RV[K] & H> : RV[K]; };
|
|
227
|
+
type HelpersForDeclaredName<N extends string, U> = { [K in keyof U]: U[K] extends VarDefination<N, any, any, any> ? UseApiMergeExtras<U[K]> : never; }[keyof U];
|
|
228
|
+
type UseApi<U> = Prettify<{ [K in Exclude<keyof U, UseVarKeys<U>>]: U[K] extends FnDefination<any, any, any, any, any, any> ? BoundFn<U[K]> : U[K] extends StorageLike ? U[K] : UseApi<U[K]>; } & { [K in UseVarKeys<U>]: UseVarValue<U[K]>; }>;
|
|
229
|
+
/** Used fns inside a readonly fn: declared writers become uncallable,
|
|
230
|
+
* with the reason on hover instead of a generic type error; var aliases
|
|
231
|
+
* become readonly properties. */
|
|
232
|
+
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` : U[K] extends StorageLike ? U[K] : ReadUseApi<U[K]>; } & { readonly [K in UseVarKeys<U>]: UseVarValue<U[K]>; }>;
|
|
233
|
+
type Context<I, RV, Required, U = unknown, FnApi = Fn, RO extends boolean = false, Errs = NoErrors,
|
|
234
|
+
/** Modules that widen var-bound input (this fn's `use` + builder chain). */
|
|
235
|
+
ExtPL = unknown> = {
|
|
236
|
+
input: unknown extends InputVarExtraOut<ExtPL, I> ? InferInput<I> : Prettify<InferInput<I> & InputVarExtraOut<ExtPL, I>>;
|
|
237
|
+
/**
|
|
238
|
+
* Mint a DECLARED error - tag-checked, payload validated at creation:
|
|
239
|
+
* `throw c.error("invalid_credentials", { attempts: 3 })`. Only tags
|
|
240
|
+
* from this fn's `errors` exist; the payload validates like input.
|
|
241
|
+
*/
|
|
242
|
+
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]>>;
|
|
243
|
+
/** Define fns from inside: this fn's scope and key carry over, so
|
|
244
|
+
* anything built here is typed exactly like a chained builder. */
|
|
245
|
+
fn: FnApi;
|
|
246
|
+
/** The schema constructors (string, number, object, ...). */
|
|
247
|
+
types: typeof vTypes;
|
|
248
|
+
} & /** Every var in scope, directly on `c`: read `c.session`, write by
|
|
249
|
+
* plain assignment (`c.session = {...}`). Every var is a readonly
|
|
250
|
+
* property on a readonly fn. Merge vars also expose same-key helpers
|
|
251
|
+
* folded from `U` (declared-name access). */ VarScope<MergeIntoScope<RV, U>, Required, RO> &
|
|
252
|
+
/** Fns from `use`, directly on `c` and already threaded with this
|
|
253
|
+
* context: `c.createUser({...})`. */
|
|
254
|
+
(RO extends true ? ReadUseApi<U> : UseApi<U>);
|
|
255
|
+
type InferReturn<O> = unknown extends O ? unknown : InferInput<OutputSchemaOf<O>>;
|
|
256
|
+
interface Fn<Base = unknown, BaseFns = unknown, BasePL extends readonly Module[] = [], Prefix extends string = ""> {
|
|
257
|
+
/**
|
|
258
|
+
* The builder FN is a schema too: `create: v.fn` (never called) declares
|
|
259
|
+
* "any function" - typed `(...args: any[]) => any`, runtime checks only
|
|
260
|
+
* `typeof value === "function"`.
|
|
261
|
+
*/
|
|
262
|
+
readonly $fnSchema: {
|
|
263
|
+
input?: unknown;
|
|
264
|
+
output?: unknown;
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* "A fn with THIS signature", as a schema: `create: v.fn.type({ input,
|
|
268
|
+
* output })` types the field as that fn and validates what a signature
|
|
269
|
+
* CAN be validated for - the value is a function, and a plain closure
|
|
270
|
+
* gets the declared input checked at its door on every call.
|
|
271
|
+
*
|
|
272
|
+
* `optional` / `default` work like on `v.string()` etc., so a prop in
|
|
273
|
+
* `v.object({...})` can be a fn type and still omittable.
|
|
274
|
+
*
|
|
275
|
+
* This exists apart from a handler-less `v.fn({ input, output })` for
|
|
276
|
+
* INLINE use: `v.fn`'s handler overloads return a callable, which makes
|
|
277
|
+
* TypeScript defer any inline `v.fn(...)` call inside another generic
|
|
278
|
+
* call's arguments (higher-order inference) - the enclosing `v.object`/
|
|
279
|
+
* `v.var` then loses its shape inference entirely. `v.fn.type` returns a
|
|
280
|
+
* plain carrier, so it composes inline anywhere.
|
|
281
|
+
*/
|
|
282
|
+
readonly type: <I = unknown, O = unknown, D = never, Opt extends boolean = false>(signature?: {
|
|
283
|
+
input?: I;
|
|
284
|
+
output?: O;
|
|
285
|
+
default?: D;
|
|
286
|
+
optional?: Opt;
|
|
287
|
+
}) => {
|
|
288
|
+
readonly $fnSchema: {
|
|
289
|
+
input?: I;
|
|
290
|
+
output?: O;
|
|
291
|
+
};
|
|
292
|
+
} & ([Opt] extends [true] ? {
|
|
293
|
+
readonly optional: true;
|
|
294
|
+
} : unknown) & ([D] extends [never] ? unknown : {
|
|
295
|
+
readonly default: D;
|
|
296
|
+
});
|
|
297
|
+
<R>(fn: (ctx: Context<unknown, ScopeOf<[], Base, BasePL>, never, BaseFns, Fn<Base, BaseFns, BasePL, Prefix>>) => R): PublicFn<void, R, Prefix extends "" ? string : Prefix, unknown, readonly string[], NoErrors, ScopeOf<[], Base, BasePL>, BaseFns>;
|
|
298
|
+
<K extends LiteralString, R>(key: K, fn: (ctx: Context<unknown, ScopeOf<[], Base, BasePL>, never, BaseFns, Fn<Base, BaseFns, BasePL, `${Prefix}${K}`>>) => R): PublicFn<void, R, `${Prefix}${K}`, unknown, readonly string[], NoErrors, ScopeOf<[], Base, BasePL>, BaseFns>;
|
|
299
|
+
<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, readonly [...BasePL, ...PL]>) => R): PublicFn<WidenedArgs<I, readonly [...BasePL, ...PL]>, R, Prefix extends "" ? string : Prefix, I, P, Er, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, O>;
|
|
300
|
+
<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, readonly [...BasePL, ...PL]>) => R): PublicFn<WidenedArgs<I, readonly [...BasePL, ...PL]>, R, `${Prefix}${K}`, I, P, Er, ScopeOf<PL, Base, readonly [...BasePL, ...PL]>, ApplyOns<ModuleFns<PL>, PL> & BaseFns, O>;
|
|
301
|
+
<K extends LiteralString>(key: K): Instance<Base, BaseFns, BasePL, `${Prefix}${K}`>;
|
|
302
|
+
<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>;
|
|
303
|
+
<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>;
|
|
304
|
+
}
|
|
305
|
+
/** Every target worth suggesting on a builder's `on`: the mounted fns'
|
|
306
|
+
* keys (prefix-stripped, so they are valid RELATIVE targets), the scope's
|
|
307
|
+
* var-write events by name, and the two wildcards. Arbitrary strings stay
|
|
308
|
+
* legal - these only feed completion. */
|
|
309
|
+
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.*" | "*";
|
|
310
|
+
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];
|
|
311
|
+
type VarNameOfT<T extends string> = T extends `var.${"set" | "get"}.${infer N}` ? N extends `${string}*${string}` ? string : N : string;
|
|
312
|
+
/** The scope's value for a var-event target - `unknown` when inexact. */
|
|
313
|
+
type VarValueOfT<T extends string, Base> = VarNameOfT<T> extends keyof ScopeOf<[], Base> ? ScopeOf<[], Base>[VarNameOfT<T>] : unknown;
|
|
314
|
+
/** The fns among `Fns` whose key the (already prefixed) target hits. */
|
|
315
|
+
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];
|
|
316
|
+
/** The intercepted input: the matched fn's (a union under wildcards),
|
|
317
|
+
* or an open record when the target names nothing the builder knows. */
|
|
318
|
+
type MatchedInput<F> = [F] extends [never] ? Record<string, any> : F extends FnDefination<any, any, any, infer I, any, any> ? InferInput<I> : never;
|
|
319
|
+
/** What `next()` resolves to: the matched fn's own result. */
|
|
320
|
+
type MatchedResult<F> = [F] extends [never] ? any : F extends FnDefination<any, infer R, any, any, any, any> ? Awaited<R> : never;
|
|
321
|
+
/** What a builder-scoped `on` handler sees: vars and `use` fns directly
|
|
322
|
+
* on `c` from the builder, `input` from the TARGET fn when known. */
|
|
323
|
+
type OnContext<Base, BaseFns, F, Ext = unknown> = {
|
|
324
|
+
input: MatchedInput<F> & (unknown extends Ext ? unknown : InferInput<Ext>);
|
|
325
|
+
types: typeof vTypes;
|
|
326
|
+
fn: unknown;
|
|
327
|
+
} & VarScope<ScopeOf<[], Base>, never> & UseApi<BaseFns>;
|
|
328
|
+
/** `v.on`, scoped: string targets get the builder's key prefix; the
|
|
329
|
+
* handler's `c` and `next()` are typed against the matched target fn. */
|
|
330
|
+
interface InstanceOn<Base, BaseFns, Prefix extends string> {
|
|
331
|
+
/** A fn REFERENCE targets its own key - never prefixed, fully typed
|
|
332
|
+
* from the fn itself plus the builder's scope. */
|
|
333
|
+
<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"]>;
|
|
334
|
+
/** Var-write events: never prefixed (vars are global), and `value`
|
|
335
|
+
* is typed from the builder's scope when the target is exact. */
|
|
336
|
+
<T extends `var.set.${keyof ScopeOf<[], Base> & string}` | "var.set.*" | `var.set.${string}`>(target: T, handler: (c: VarSetContext<VarNameOfT<T>> & {
|
|
337
|
+
value: VarValueOfT<T, Base>;
|
|
338
|
+
}, next: () => void) => void): OnEntry<T>;
|
|
339
|
+
/** Var-read events: `next()` yields the stored value and the handler's
|
|
340
|
+
* return becomes the read result - typed from the scope when exact. */
|
|
341
|
+
<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>;
|
|
342
|
+
(target: RegExp, handler: (c: OnContext<Base, BaseFns, never>, next: () => Promise<any>) => any): OnEntry<string>;
|
|
343
|
+
<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}`>;
|
|
344
|
+
<const Ext>(target: RegExp, extend: {
|
|
345
|
+
input: Ext;
|
|
346
|
+
}, handler: (c: OnContext<Base, BaseFns, never, Ext>, next: () => Promise<any>) => any): OnEntry<string, Ext>;
|
|
347
|
+
<N extends OnTargetSuggest<Base, BaseFns, Prefix> | LiteralString, const Ext>(target: N, extend: {
|
|
348
|
+
input: Ext;
|
|
349
|
+
}, handler: (c: OnContext<Base, BaseFns, MatchedFn<BaseFns, `${Prefix}${N}`>, Ext>, next: () => Promise<MatchedResult<MatchedFn<BaseFns, `${Prefix}${N}`>>>) => any): OnEntry<`${Prefix}${N}`, Ext>;
|
|
350
|
+
}
|
|
351
|
+
type Instance<Base, BaseFns, PL extends readonly Module[] = [], Prefix extends string = "", I = unknown, O = unknown> = {
|
|
352
|
+
/** Same as `v.fn`, with this builder's key prefix and options baked in. */
|
|
353
|
+
fn: Fn<Base, BaseFns, PL, Prefix>;
|
|
354
|
+
/**
|
|
355
|
+
* A handler-less builder doubles as an input SCHEMA: used as `input`
|
|
356
|
+
* (or an input field) it declares "a FN from `input` to `output`" -
|
|
357
|
+
* the value crossing is the fn itself. Carries the declared schemas
|
|
358
|
+
* for inference here and validation at runtime (see `isFnSchema`).
|
|
359
|
+
*/
|
|
360
|
+
readonly $fnSchema: {
|
|
361
|
+
input?: I;
|
|
362
|
+
output?: O;
|
|
363
|
+
};
|
|
364
|
+
/** Same as `v.on`, with the prefix on string targets and the handler
|
|
365
|
+
* typed against the matched target fn. */
|
|
366
|
+
on: InstanceOn<Base, BaseFns, Prefix>;
|
|
367
|
+
/**
|
|
368
|
+
* The context a handler on this builder receives - a TYPE carrier for
|
|
369
|
+
* `typeof f.ctx` (helper signatures, plugin contracts). Every handler
|
|
370
|
+
* context on this builder is assignable to it: `input` and `fn` are
|
|
371
|
+
* loosened since they vary per fn. A real context only exists per
|
|
372
|
+
* invocation, so this is `undefined` at runtime.
|
|
373
|
+
*/
|
|
374
|
+
readonly ctx: Context<unknown, ScopeOf<[], Base, PL>, never, BaseFns, unknown>;
|
|
375
|
+
};
|
|
376
|
+
//#endregion
|
|
377
|
+
export { ArgsOf, BoundCall, Context, Fn, FnDefination, FnErrors, FnErrorsOf, InferReturn, Instance, InstanceOn, OptionType, ParentContext, UseApi, WidenedArgs, WithContext, WithSeed };
|
|
378
|
+
//# sourceMappingURL=fn.d.mts.map
|