@nwire/handler 0.8.0 → 0.9.1
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/README.md +183 -68
- package/dist/define-error.d.ts +33 -27
- package/dist/define-error.d.ts.map +1 -1
- package/dist/define-error.js +27 -19
- package/dist/define-error.js.map +1 -1
- package/dist/define-handler.d.ts +146 -107
- package/dist/define-handler.d.ts.map +1 -1
- package/dist/define-handler.js +139 -83
- package/dist/define-handler.js.map +1 -1
- package/dist/define-middleware.js +4 -3
- package/dist/define-middleware.js.map +1 -1
- package/dist/handler-index.d.ts +17 -22
- package/dist/handler-index.d.ts.map +1 -1
- package/dist/handler-index.js +16 -21
- package/dist/handler-index.js.map +1 -1
- package/package.json +4 -7
package/dist/define-handler.d.ts
CHANGED
|
@@ -3,166 +3,205 @@
|
|
|
3
3
|
*
|
|
4
4
|
* const GetStation = defineHandler("GetStation", {
|
|
5
5
|
* input: z.object({ stationId: z.string() }),
|
|
6
|
+
* handler: async ({ input }) => loadStation(input.stationId),
|
|
6
7
|
* returns: Station,
|
|
7
|
-
*
|
|
8
|
+
* errors: [NotFound],
|
|
8
9
|
* });
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* GetStation({ stationId: "abc" }) // mint a prepared op
|
|
12
|
+
* await GetStation({ stationId: "abc" }).run() // run it
|
|
13
|
+
* await GetStation.run({ input, signal }) // low-level hook surface
|
|
14
|
+
* GetStation.use(myMiddleware) // attach a hook chain step
|
|
15
|
+
* GetStation.on(observer) // attach a listener
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
+
* The handler IS a `Hook` from `@nwire/hooks`. `.use()` attaches chain steps;
|
|
18
|
+
* `.on()` attaches parallel listeners; `.run()` executes. The user's handler
|
|
19
|
+
* function is the innermost chain step — registered at construction with
|
|
20
|
+
* `Number.MIN_SAFE_INTEGER` priority so every `.use(...)` wraps around it.
|
|
17
21
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
+
* **Ctx is generic.** The handler's ctx is `BaseHookCtx & { input } & TExtras`
|
|
23
|
+
* where `TExtras` is inferred from the handler's param annotation, or pinned
|
|
24
|
+
* once via `defineHandlerWith<TExtras>()` at the app boundary. Whatever you
|
|
25
|
+
* pass to `.run(ctx)` is what reaches the handler body, fully typed. No
|
|
26
|
+
* declaration merging on ctx — composition by value.
|
|
22
27
|
*
|
|
23
|
-
* `meta` + `settings`
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* to an existing `ActionDefinition`. That signature stays inside `@nwire/forge`
|
|
28
|
-
* because it depends on the action machinery. The standalone version lives
|
|
29
|
-
* here because every transport needs it without the forge surface.
|
|
28
|
+
* `meta` + `settings` ARE globally augmentable open interfaces. Those are
|
|
29
|
+
* declarative per-handler tags (policy, retry, persona, SLO) that plugins
|
|
30
|
+
* must discover across every handler — different role from ctx, different
|
|
31
|
+
* mechanism by design.
|
|
30
32
|
*/
|
|
31
33
|
import type { z } from "zod";
|
|
32
34
|
import type { ZodTypeAny } from "@nwire/messages";
|
|
33
|
-
import type
|
|
34
|
-
import { type Logger } from "@nwire/logger";
|
|
35
|
+
import { type BaseHookCtx, type ChainFn, type ListenerFn, type RunOptions, type RunResult, type UseOptions, type OnOptions, type TapFn } from "@nwire/hooks";
|
|
35
36
|
import type { ErrorDefinition } from "./define-error.js";
|
|
36
37
|
import type { ResponseSpec, ListResponseSpec } from "./response.js";
|
|
37
38
|
import type { ResourceDefinition } from "./define-resource.js";
|
|
38
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Empty bags — plugins extend via TS declaration merging.
|
|
41
|
+
*
|
|
42
|
+
* declare module "@nwire/handler" {
|
|
43
|
+
* interface HandlerSettings { retry?: { attempts: number } }
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* These hold *declarative config* (RBAC policies, retry strategies,
|
|
47
|
+
* SLO budgets, persona tags) — NOT runtime ctx. Different role, different
|
|
48
|
+
* mechanism: ctx is per-invocation runtime data composed by value;
|
|
49
|
+
* meta/settings are per-handler design-time tags plugins discover globally.
|
|
50
|
+
*/
|
|
39
51
|
export interface HandlerMeta {
|
|
40
|
-
readonly tags?: readonly string[];
|
|
41
|
-
readonly description?: string;
|
|
42
|
-
readonly version?: number;
|
|
43
|
-
readonly deprecated?: boolean;
|
|
44
|
-
readonly successor?: string;
|
|
45
52
|
}
|
|
46
53
|
export interface HandlerSettings {
|
|
47
|
-
readonly retry?: {
|
|
48
|
-
attempts: number;
|
|
49
|
-
backoff?: "linear" | "exponential";
|
|
50
|
-
};
|
|
51
|
-
readonly timeout?: number;
|
|
52
|
-
readonly cache?: {
|
|
53
|
-
ttl: number;
|
|
54
|
-
};
|
|
55
|
-
readonly idempotency?: (input: unknown) => string;
|
|
56
54
|
}
|
|
55
|
+
/** Resolve a zod schema (or `undefined`) to the parsed input type. */
|
|
56
|
+
export type InferInput<S extends ZodTypeAny | undefined> = S extends ZodTypeAny ? z.output<S> : undefined;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* The base ctx every handler receives — hooks' `BaseHookCtx` (`signal` + typed
|
|
59
|
+
* `set`) plus the parsed `input`. Apps extend with their own `TExtras` via
|
|
60
|
+
* the `Ctx<TInput, TExtras>` alias below.
|
|
61
61
|
*/
|
|
62
|
-
export interface
|
|
63
|
-
|
|
64
|
-
readonly input: TInput;
|
|
65
|
-
/** Look up a dependency by name. Most handlers destructure instead. */
|
|
66
|
-
resolve<T = unknown>(name: string): T;
|
|
67
|
-
/** Per-execution container scope. */
|
|
68
|
-
readonly container: Container;
|
|
69
|
-
/** Logger scoped to this execution (correlation/causation already attached). */
|
|
70
|
-
readonly logger: Logger;
|
|
71
|
-
/** Free-form bag for transport-specific extras (raw request, MCP progress, …). */
|
|
72
|
-
readonly transport?: Record<string, unknown>;
|
|
62
|
+
export interface HandlerBaseCtx<TInput> extends BaseHookCtx {
|
|
63
|
+
input: TInput;
|
|
73
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Sugar for declaring a handler's ctx shape:
|
|
67
|
+
*
|
|
68
|
+
* handler: async ({ input, cradle, user }: Ctx<MyInput, { cradle: Cradle; user: User }>) => …
|
|
69
|
+
*/
|
|
70
|
+
export type Ctx<TInput, TExtras extends object = object> = HandlerBaseCtx<TInput> & TExtras;
|
|
74
71
|
/**
|
|
75
72
|
* `returns` may be a single resource, a single response spec, or an array
|
|
76
73
|
* of response specs (e.g. `[created(Station), accepted(StationHandle)]`).
|
|
77
74
|
*/
|
|
78
75
|
export type HandlerReturnsSpec = ResourceDefinition | ResponseSpec | ListResponseSpec<ResourceDefinition> | ReadonlyArray<ResponseSpec | ListResponseSpec<ResourceDefinition>>;
|
|
79
|
-
|
|
80
|
-
* Policy: a tag (`"admin"`), a list of tags (`["admin", "operator"]`), or
|
|
81
|
-
* a tuple of `[action, subject]` for RBAC-style policies. Adapters
|
|
82
|
-
* interpret the value per their authorization model.
|
|
83
|
-
*/
|
|
84
|
-
export type HandlerPolicy = string | readonly string[] | readonly [string, string];
|
|
85
|
-
export interface HandlerConfig<TInputSchema extends ZodTypeAny | undefined = ZodTypeAny | undefined, TOutput = unknown> {
|
|
76
|
+
export interface HandlerConfig<TInputSchema extends ZodTypeAny | undefined = undefined, TOutput = unknown, TExtras extends object = object> {
|
|
86
77
|
/** Input schema. Optional for zero-arg handlers (health checks, listings without filters). */
|
|
87
78
|
readonly input?: TInputSchema;
|
|
88
|
-
/** The implementation. Receives the typed input +
|
|
89
|
-
readonly handler: (ctx:
|
|
79
|
+
/** The implementation. Receives the typed input + ctx fields contributed upstream. */
|
|
80
|
+
readonly handler: (ctx: Ctx<InferInput<TInputSchema>, TExtras>) => TOutput | Promise<TOutput>;
|
|
90
81
|
/** Documented response shape(s). Drives OpenAPI + runtime body validation. */
|
|
91
82
|
readonly returns?: HandlerReturnsSpec;
|
|
92
83
|
/** Declared error values this handler may throw. */
|
|
93
84
|
readonly errors?: readonly ErrorDefinition[];
|
|
94
|
-
/**
|
|
95
|
-
readonly emits?: readonly unknown[];
|
|
96
|
-
/** One-line intent. Surfaces in OpenAPI/MCP descriptions. */
|
|
85
|
+
/** One-line intent. Surfaces in OpenAPI / MCP / Studio. */
|
|
97
86
|
readonly summary?: string;
|
|
98
|
-
/**
|
|
99
|
-
readonly
|
|
100
|
-
/**
|
|
87
|
+
/** Multi-line prose. Surfaces in OpenAPI / MCP / Studio. */
|
|
88
|
+
readonly description?: string;
|
|
89
|
+
/** Open bag — plugins contribute fields via declaration merging. */
|
|
101
90
|
readonly meta?: HandlerMeta;
|
|
102
|
-
/**
|
|
91
|
+
/** Open bag — plugins contribute fields via declaration merging. */
|
|
103
92
|
readonly settings?: HandlerSettings;
|
|
104
93
|
}
|
|
105
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Hook ctx that flows through the chain when a handler runs. Extends the
|
|
96
|
+
* consumer's `TExtras` so middleware that wrote to ctx (or used `.set()`)
|
|
97
|
+
* is visible to subsequent steps + listeners.
|
|
98
|
+
*/
|
|
99
|
+
export type HandlerRunCtx<TInput = unknown, TOutput = unknown, TExtras extends object = object> = Ctx<TInput, TExtras> & {
|
|
100
|
+
result?: TOutput;
|
|
101
|
+
};
|
|
102
|
+
/** Options passed to `PreparedOp.run()` — the high-level callable form. */
|
|
103
|
+
export interface PreparedOpRunOptions<TExtras extends object = object> {
|
|
104
|
+
readonly signal?: AbortSignal;
|
|
105
|
+
/**
|
|
106
|
+
* Extras to populate on ctx before the handler body runs. Required when
|
|
107
|
+
* `TExtras` declares fields the runtime must supply (`cradle`, `user`, …).
|
|
108
|
+
* Optional `{}` for handlers that declared no extras.
|
|
109
|
+
*/
|
|
110
|
+
readonly ctx?: TExtras;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The value returned by calling a handler as a factory: `Handler(input)`.
|
|
114
|
+
* Holds the validated input and exposes `.run(opts?)` to execute.
|
|
115
|
+
*/
|
|
116
|
+
export interface PreparedOp<TInput = unknown, TOutput = unknown, TExtras extends object = object> {
|
|
117
|
+
readonly input: TInput;
|
|
118
|
+
run(opts?: PreparedOpRunOptions<TExtras>): Promise<TOutput>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The handler definition. Composes a `Hook<HandlerRunCtx>` for the chain
|
|
122
|
+
* surface (`.use` / `.on` / `.off` / `.run` / `.runDetailed` / `.tap`) and
|
|
123
|
+
* is callable as a factory that mints a `PreparedOp`.
|
|
124
|
+
*/
|
|
125
|
+
export interface HandlerDefinition<TInputSchema extends ZodTypeAny | undefined = undefined, TOutput = unknown, TExtras extends object = object> {
|
|
106
126
|
readonly $kind: "handler";
|
|
107
127
|
readonly name: string;
|
|
108
|
-
readonly config: HandlerConfig<TInputSchema, TOutput>;
|
|
128
|
+
readonly config: HandlerConfig<TInputSchema, TOutput, TExtras>;
|
|
129
|
+
(input: TInputSchema extends ZodTypeAny ? z.input<TInputSchema> : void): PreparedOp<InferInput<TInputSchema>, TOutput, TExtras>;
|
|
130
|
+
/** Hook chain attach — runs sequentially, can short-circuit. */
|
|
131
|
+
use(fn: ChainFn<HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>>, opts?: UseOptions): HandlerDefinition<TInputSchema, TOutput, TExtras>;
|
|
132
|
+
/** Listener attach — observes the final ctx, cannot mutate. */
|
|
133
|
+
on(fn: ListenerFn<HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>>, opts?: OnOptions): HandlerDefinition<TInputSchema, TOutput, TExtras>;
|
|
134
|
+
/** Detach a previously attached `.use()` or `.on()` fn. */
|
|
135
|
+
off(fn: ChainFn<HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>> | ListenerFn<HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>>): HandlerDefinition<TInputSchema, TOutput, TExtras>;
|
|
109
136
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
137
|
+
* Run the chain + listeners. The caller supplies the ctx — `input` +
|
|
138
|
+
* `signal` are filled in automatically; everything in `TExtras` must
|
|
139
|
+
* be present on the ctx object.
|
|
112
140
|
*/
|
|
113
|
-
run(ctx:
|
|
141
|
+
run(ctx: HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>, opts?: RunOptions): Promise<HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>>;
|
|
142
|
+
/** Same as `.run()` but returns the full observation trace. */
|
|
143
|
+
runDetailed(ctx: HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>, opts?: RunOptions): Promise<RunResult<HandlerRunCtx<InferInput<TInputSchema>, TOutput, TExtras>>>;
|
|
144
|
+
/** Subscribe to per-step observations. */
|
|
145
|
+
tap(observer: TapFn): () => void;
|
|
146
|
+
/** Step counts on the underlying hook. */
|
|
147
|
+
stepCounts(): {
|
|
148
|
+
readonly chain: number;
|
|
149
|
+
readonly listeners: number;
|
|
150
|
+
};
|
|
114
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* `HandlerLike` — what `interface-builder.wire()` accepts.
|
|
154
|
+
*
|
|
155
|
+
* - a full `HandlerDefinition` (typed, hookable, has metadata) — the canonical path.
|
|
156
|
+
* - a bare async function (one-liners, health checks, escape hatch).
|
|
157
|
+
*/
|
|
158
|
+
export type HandlerLike<TInput = unknown, TOutput = unknown> = HandlerDefinition<ZodTypeAny | undefined, TOutput, object> | ((input: TInput) => Promise<TOutput> | TOutput);
|
|
115
159
|
/**
|
|
116
160
|
* Define a handler — the operation primitive.
|
|
117
161
|
*
|
|
118
162
|
* const ListTodos = defineHandler("listTodos", {
|
|
119
163
|
* input: z.object({ status: z.string().optional() }),
|
|
120
|
-
* handler: async ({ input
|
|
121
|
-
* const db = resolve<DB>("db");
|
|
122
|
-
* return db.todos.findMany(input);
|
|
123
|
-
* },
|
|
164
|
+
* handler: async ({ input }) => todos.findMany(input),
|
|
124
165
|
* });
|
|
125
166
|
*
|
|
126
167
|
* // Direct invocation:
|
|
127
|
-
* const
|
|
168
|
+
* const result = await ListTodos({ status: "open" }).run();
|
|
128
169
|
*
|
|
129
|
-
* //
|
|
130
|
-
*
|
|
170
|
+
* // Hook composition:
|
|
171
|
+
* ListTodos.use(withTimeout(5000));
|
|
172
|
+
* ListTodos.on(record => otel.span(...));
|
|
131
173
|
*
|
|
132
|
-
* //
|
|
133
|
-
*
|
|
134
|
-
*/
|
|
135
|
-
export declare function defineHandler<TInputSchema extends ZodTypeAny | undefined, TOutput>(name: string, config: HandlerConfig<TInputSchema, TOutput>): HandlerDefinition<TInputSchema, TOutput>;
|
|
136
|
-
/** Type narrow. */
|
|
137
|
-
export declare function isHandlerDefinition(x: unknown): x is HandlerDefinition;
|
|
138
|
-
/**
|
|
139
|
-
* Options for `execute()` — transport-agnostic. Adapters can pass a
|
|
140
|
-
* container so the handler can `resolve()` its deps; if omitted, a
|
|
141
|
-
* minimal stub container is supplied that throws on resolve.
|
|
174
|
+
* // Low-level hook surface (transports use this):
|
|
175
|
+
* await ListTodos.run({ input: { status: "open" }, signal });
|
|
142
176
|
*/
|
|
143
|
-
export
|
|
144
|
-
readonly container?: Container;
|
|
145
|
-
readonly logger?: Logger;
|
|
146
|
-
readonly transport?: Record<string, unknown>;
|
|
147
|
-
}
|
|
177
|
+
export declare function defineHandler<TInputSchema extends ZodTypeAny | undefined, TOutput, TExtras extends object = object>(name: string, config: HandlerConfig<TInputSchema, TOutput, TExtras>): HandlerDefinition<TInputSchema, TOutput, TExtras>;
|
|
148
178
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* handler context, runs the handler, and returns its result.
|
|
179
|
+
* App-boundary sugar — pin `TExtras` once so every handler in the app reads
|
|
180
|
+
* `ctx` as the bound shape without per-call annotations.
|
|
152
181
|
*
|
|
153
|
-
*
|
|
182
|
+
* // app/action.ts
|
|
183
|
+
* type AppExtras = { cradle: AppCradle; user: User };
|
|
184
|
+
* export const action = defineHandlerWith<AppExtras>();
|
|
154
185
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
186
|
+
* // every handler file:
|
|
187
|
+
* import { action } from "@/action";
|
|
188
|
+
* const PlaceOrder = action("placeOrder", {
|
|
189
|
+
* input: z.object({ id: z.string() }),
|
|
190
|
+
* handler: async ({ input, cradle, user }) => … // fully typed, no annotation
|
|
191
|
+
* });
|
|
192
|
+
*
|
|
193
|
+
* // every transport / .run() call:
|
|
194
|
+
* PlaceOrder.run({ input, signal, cradle, user });
|
|
164
195
|
*/
|
|
165
|
-
export
|
|
166
|
-
/**
|
|
196
|
+
export declare function defineHandlerWith<TExtras extends object>(): <TInputSchema extends ZodTypeAny | undefined, TOutput>(name: string, config: HandlerConfig<TInputSchema, TOutput, TExtras>) => HandlerDefinition<TInputSchema, TOutput, TExtras>;
|
|
197
|
+
/** Type narrow. */
|
|
198
|
+
export declare function isHandlerDefinition(x: unknown): x is HandlerDefinition;
|
|
199
|
+
/** Extract the input type of a handler's schema (post-parse). */
|
|
200
|
+
export type HandlerInput<H> = H extends HandlerDefinition<infer S, unknown, object> ? InferInput<S> : never;
|
|
201
|
+
/** Extract the output type of a handler. */
|
|
202
|
+
export type HandlerOutput<H> = H extends HandlerDefinition<ZodTypeAny | undefined, infer O, object> ? O : never;
|
|
203
|
+
/** Extract the extras (TExtras) a handler requires on ctx. */
|
|
204
|
+
export type HandlerExtras<H> = H extends HandlerDefinition<ZodTypeAny | undefined, unknown, infer E> ? E : never;
|
|
205
|
+
/** Re-export from the response builders for ergonomics. */
|
|
167
206
|
export type { ResponseInstance } from "./response.js";
|
|
168
207
|
//# sourceMappingURL=define-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-handler.d.ts","sourceRoot":"","sources":["../src/define-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"define-handler.d.ts","sourceRoot":"","sources":["../src/define-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/define-handler.js
CHANGED
|
@@ -3,114 +3,170 @@
|
|
|
3
3
|
*
|
|
4
4
|
* const GetStation = defineHandler("GetStation", {
|
|
5
5
|
* input: z.object({ stationId: z.string() }),
|
|
6
|
+
* handler: async ({ input }) => loadStation(input.stationId),
|
|
6
7
|
* returns: Station,
|
|
7
|
-
*
|
|
8
|
+
* errors: [NotFound],
|
|
8
9
|
* });
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* GetStation({ stationId: "abc" }) // mint a prepared op
|
|
12
|
+
* await GetStation({ stationId: "abc" }).run() // run it
|
|
13
|
+
* await GetStation.run({ input, signal }) // low-level hook surface
|
|
14
|
+
* GetStation.use(myMiddleware) // attach a hook chain step
|
|
15
|
+
* GetStation.on(observer) // attach a listener
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
+
* The handler IS a `Hook` from `@nwire/hooks`. `.use()` attaches chain steps;
|
|
18
|
+
* `.on()` attaches parallel listeners; `.run()` executes. The user's handler
|
|
19
|
+
* function is the innermost chain step — registered at construction with
|
|
20
|
+
* `Number.MIN_SAFE_INTEGER` priority so every `.use(...)` wraps around it.
|
|
17
21
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
+
* **Ctx is generic.** The handler's ctx is `BaseHookCtx & { input } & TExtras`
|
|
23
|
+
* where `TExtras` is inferred from the handler's param annotation, or pinned
|
|
24
|
+
* once via `defineHandlerWith<TExtras>()` at the app boundary. Whatever you
|
|
25
|
+
* pass to `.run(ctx)` is what reaches the handler body, fully typed. No
|
|
26
|
+
* declaration merging on ctx — composition by value.
|
|
22
27
|
*
|
|
23
|
-
* `meta` + `settings`
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
* `meta` + `settings` ARE globally augmentable open interfaces. Those are
|
|
29
|
+
* declarative per-handler tags (policy, retry, persona, SLO) that plugins
|
|
30
|
+
* must discover across every handler — different role from ctx, different
|
|
31
|
+
* mechanism by design.
|
|
32
|
+
*/
|
|
33
|
+
import { hook, } from "@nwire/hooks";
|
|
34
|
+
/**
|
|
35
|
+
* Tag for the terminal chain step that calls the user's handler function.
|
|
36
|
+
* Registered with `Number.MIN_SAFE_INTEGER` priority so every `.use()` from
|
|
37
|
+
* the consumer wraps around it (higher priority = runs first / outermost).
|
|
30
38
|
*/
|
|
31
|
-
|
|
39
|
+
const TERMINAL_STEP_NAME = "@nwire/handler/terminal";
|
|
32
40
|
/**
|
|
33
41
|
* Define a handler — the operation primitive.
|
|
34
42
|
*
|
|
35
43
|
* const ListTodos = defineHandler("listTodos", {
|
|
36
44
|
* input: z.object({ status: z.string().optional() }),
|
|
37
|
-
* handler: async ({ input
|
|
38
|
-
* const db = resolve<DB>("db");
|
|
39
|
-
* return db.todos.findMany(input);
|
|
40
|
-
* },
|
|
45
|
+
* handler: async ({ input }) => todos.findMany(input),
|
|
41
46
|
* });
|
|
42
47
|
*
|
|
43
48
|
* // Direct invocation:
|
|
44
|
-
* const
|
|
49
|
+
* const result = await ListTodos({ status: "open" }).run();
|
|
45
50
|
*
|
|
46
|
-
* //
|
|
47
|
-
*
|
|
51
|
+
* // Hook composition:
|
|
52
|
+
* ListTodos.use(withTimeout(5000));
|
|
53
|
+
* ListTodos.on(record => otel.span(...));
|
|
48
54
|
*
|
|
49
|
-
* //
|
|
50
|
-
*
|
|
55
|
+
* // Low-level hook surface (transports use this):
|
|
56
|
+
* await ListTodos.run({ input: { status: "open" }, signal });
|
|
51
57
|
*/
|
|
52
58
|
export function defineHandler(name, config) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
const h = hook(name);
|
|
60
|
+
// Innermost step — runs the user's handler after every `.use()` has had
|
|
61
|
+
// its chance to wrap. Validation happens here (parse against config.input)
|
|
62
|
+
// so middleware that mutates ctx.input does so BEFORE validation. The
|
|
63
|
+
// chain ctx is forwarded so middleware-contributed fields (TExtras —
|
|
64
|
+
// cradle, user, tenant, logger, …) flow through.
|
|
65
|
+
h.use(async (ctx, next) => {
|
|
66
|
+
ctx.signal?.throwIfAborted();
|
|
67
|
+
const parsed = config.input ? config.input.parse(ctx.input) : ctx.input;
|
|
68
|
+
ctx.input = parsed;
|
|
69
|
+
const result = await config.handler(ctx);
|
|
70
|
+
ctx.result = result;
|
|
71
|
+
await next();
|
|
72
|
+
}, {
|
|
73
|
+
name: TERMINAL_STEP_NAME,
|
|
74
|
+
priority: Number.MIN_SAFE_INTEGER,
|
|
75
|
+
});
|
|
76
|
+
// The factory is a callable function. `Object.defineProperty` attaches the
|
|
77
|
+
// metadata + delegated hook methods + the `$kind` discriminator.
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
const factory = (input) => {
|
|
80
|
+
const prepared = {
|
|
81
|
+
input: input,
|
|
82
|
+
async run(opts) {
|
|
83
|
+
const ctx = {
|
|
84
|
+
input,
|
|
85
|
+
...(opts?.ctx ?? {}),
|
|
86
|
+
};
|
|
87
|
+
const out = await h.run(ctx, { signal: opts?.signal });
|
|
88
|
+
return out.result;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
return prepared;
|
|
60
92
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
Object.defineProperties(factory, {
|
|
94
|
+
$kind: { value: "handler", enumerable: true },
|
|
95
|
+
name: { value: name, enumerable: true, configurable: true },
|
|
96
|
+
config: { value: config, enumerable: true },
|
|
97
|
+
toString: { value: () => name, enumerable: false },
|
|
98
|
+
$hook: { value: h, enumerable: false, configurable: true },
|
|
99
|
+
use: {
|
|
100
|
+
value: function use(fn, opts) {
|
|
101
|
+
h.use(fn, opts);
|
|
102
|
+
return factory;
|
|
103
|
+
},
|
|
104
|
+
enumerable: false,
|
|
105
|
+
},
|
|
106
|
+
on: {
|
|
107
|
+
value: function on(fn, opts) {
|
|
108
|
+
h.on(fn, opts);
|
|
109
|
+
return factory;
|
|
110
|
+
},
|
|
111
|
+
enumerable: false,
|
|
112
|
+
},
|
|
113
|
+
off: {
|
|
114
|
+
value: function off(fn) {
|
|
115
|
+
h.off(fn);
|
|
116
|
+
return factory;
|
|
117
|
+
},
|
|
118
|
+
enumerable: false,
|
|
119
|
+
},
|
|
120
|
+
run: {
|
|
121
|
+
value: function run(ctx, opts) {
|
|
122
|
+
return h.run(ctx, opts);
|
|
123
|
+
},
|
|
124
|
+
enumerable: false,
|
|
125
|
+
},
|
|
126
|
+
runDetailed: {
|
|
127
|
+
value: function runDetailed(ctx, opts) {
|
|
128
|
+
return h.runDetailed(ctx, opts);
|
|
129
|
+
},
|
|
130
|
+
enumerable: false,
|
|
131
|
+
},
|
|
132
|
+
tap: {
|
|
133
|
+
value: function tap(observer) {
|
|
134
|
+
return h.tap(observer);
|
|
135
|
+
},
|
|
136
|
+
enumerable: false,
|
|
137
|
+
},
|
|
138
|
+
stepCounts: {
|
|
139
|
+
value: function stepCounts() {
|
|
140
|
+
return h.stepCounts();
|
|
141
|
+
},
|
|
142
|
+
enumerable: false,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
return factory;
|
|
65
146
|
}
|
|
66
147
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
148
|
+
* App-boundary sugar — pin `TExtras` once so every handler in the app reads
|
|
149
|
+
* `ctx` as the bound shape without per-call annotations.
|
|
150
|
+
*
|
|
151
|
+
* // app/action.ts
|
|
152
|
+
* type AppExtras = { cradle: AppCradle; user: User };
|
|
153
|
+
* export const action = defineHandlerWith<AppExtras>();
|
|
70
154
|
*
|
|
71
|
-
*
|
|
155
|
+
* // every handler file:
|
|
156
|
+
* import { action } from "@/action";
|
|
157
|
+
* const PlaceOrder = action("placeOrder", {
|
|
158
|
+
* input: z.object({ id: z.string() }),
|
|
159
|
+
* handler: async ({ input, cradle, user }) => … // fully typed, no annotation
|
|
160
|
+
* });
|
|
72
161
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* `execute()` directly to bypass transport machinery.
|
|
162
|
+
* // every transport / .run() call:
|
|
163
|
+
* PlaceOrder.run({ input, signal, cradle, user });
|
|
76
164
|
*/
|
|
77
|
-
export
|
|
78
|
-
|
|
79
|
-
input, options = {}) {
|
|
80
|
-
const schema = handler.config.input;
|
|
81
|
-
const parsed = schema ? schema.parse(input) : input;
|
|
82
|
-
const container = options.container ?? minimalContainer();
|
|
83
|
-
const logger = options.logger ?? minimalLogger();
|
|
84
|
-
const ctx = {
|
|
85
|
-
input: parsed,
|
|
86
|
-
container,
|
|
87
|
-
resolve: (name) => container.resolve(name),
|
|
88
|
-
logger,
|
|
89
|
-
transport: options.transport,
|
|
90
|
-
};
|
|
91
|
-
return handler.run(ctx);
|
|
92
|
-
}
|
|
93
|
-
/** Minimal stub container — every resolve throws. Used when no container supplied. */
|
|
94
|
-
function minimalContainer() {
|
|
95
|
-
const stub = {
|
|
96
|
-
resolve(name) {
|
|
97
|
-
throw new Error(`execute(): no container provided — cannot resolve "${name}". ` +
|
|
98
|
-
`Pass options.container or use a transport that wires one.`);
|
|
99
|
-
},
|
|
100
|
-
register() {
|
|
101
|
-
throw new Error("execute(): minimal container is read-only");
|
|
102
|
-
},
|
|
103
|
-
createScope() {
|
|
104
|
-
return minimalContainer();
|
|
105
|
-
},
|
|
106
|
-
has() {
|
|
107
|
-
return false;
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
return stub;
|
|
165
|
+
export function defineHandlerWith() {
|
|
166
|
+
return (name, config) => defineHandler(name, config);
|
|
111
167
|
}
|
|
112
|
-
/**
|
|
113
|
-
function
|
|
114
|
-
return
|
|
168
|
+
/** Type narrow. */
|
|
169
|
+
export function isHandlerDefinition(x) {
|
|
170
|
+
return typeof x === "function" && x.$kind === "handler";
|
|
115
171
|
}
|
|
116
172
|
//# sourceMappingURL=define-handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-handler.js","sourceRoot":"","sources":["../src/define-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"define-handler.js","sourceRoot":"","sources":["../src/define-handler.ts"],"names":[],"mappings":"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"}
|