@wooksjs/event-core 0.6.5 → 0.7.0
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 +34 -4
- package/dist/index.cjs +440 -221
- package/dist/index.d.ts +386 -107
- package/dist/index.mjs +422 -211
- package/package.json +11 -13
- package/scripts/setup-skills.js +78 -0
- package/skills/wooksjs-event-core/.gitkeep +0 -0
- package/skills/wooksjs-event-core/SKILL.md +50 -0
- package/skills/wooksjs-event-core/composables.md +200 -0
- package/skills/wooksjs-event-core/context.md +270 -0
- package/skills/wooksjs-event-core/core.md +91 -0
- package/skills/wooksjs-event-core/primitives.md +213 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,153 +1,432 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Logger interface used throughout Wooks. Passed via `EventContextOptions`
|
|
3
|
+
* and accessed with `useLogger()`. Compatible with `@prostojs/logger` and
|
|
4
|
+
* most standard loggers.
|
|
5
|
+
*/
|
|
6
|
+
interface Logger {
|
|
7
|
+
info(msg: string, ...args: unknown[]): void;
|
|
8
|
+
warn(msg: string, ...args: unknown[]): void;
|
|
9
|
+
error(msg: string, ...args: unknown[]): void;
|
|
10
|
+
debug(msg: string, ...args: unknown[]): void;
|
|
11
|
+
/** Creates a child logger with a topic prefix (optional). */
|
|
12
|
+
topic?: (name?: string) => Logger;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A typed, writable context slot. Created with `key<T>(name)`.
|
|
16
|
+
* Use `ctx.set(k, value)` to store and `ctx.get(k)` to retrieve.
|
|
17
|
+
*/
|
|
18
|
+
interface Key<T> {
|
|
19
|
+
readonly _id: number;
|
|
20
|
+
readonly _name: string;
|
|
21
|
+
/** @internal Type brand — not used at runtime. */
|
|
22
|
+
readonly _T?: T;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A lazily-computed, read-only context slot. Created with `cached<T>(fn)`.
|
|
26
|
+
* The factory runs once per context on first `ctx.get()` call; the result is cached.
|
|
27
|
+
*/
|
|
28
|
+
interface Cached<T> {
|
|
29
|
+
readonly _id: number;
|
|
30
|
+
readonly _name: string;
|
|
31
|
+
readonly _fn: (ctx: EventContext) => T;
|
|
32
|
+
/** @internal Type brand — not used at runtime. */
|
|
33
|
+
readonly _T?: T;
|
|
34
|
+
}
|
|
35
|
+
/** Union type for any context slot — either a writable `Key` or a computed `Cached`. */
|
|
36
|
+
type Accessor<T> = Key<T> | Cached<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Type-level marker used in `defineEventKind` schemas. Each `slot<T>()`
|
|
39
|
+
* becomes a typed `Key<T>` on the resulting `EventKind`. No runtime behavior.
|
|
40
|
+
*/
|
|
41
|
+
interface SlotMarker<T> {
|
|
42
|
+
/** @internal Type brand — not used at runtime. */
|
|
43
|
+
readonly _T?: T;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Declares the shape of an event type — its name and typed seed slots.
|
|
47
|
+
* Created with `defineEventKind(name, schema)`.
|
|
48
|
+
*
|
|
49
|
+
* Use `kind.keys.<prop>` to access typed context keys for each slot.
|
|
50
|
+
*/
|
|
51
|
+
interface EventKind<S extends Record<string, SlotMarker<any>>> {
|
|
52
|
+
/** Unique event kind name (e.g. `'http'`, `'cli'`). */
|
|
53
|
+
readonly name: string;
|
|
54
|
+
/** Typed context keys for each slot in the schema. */
|
|
55
|
+
readonly keys: {
|
|
56
|
+
[K in keyof S]: S[K] extends SlotMarker<infer V> ? Key<V> : never;
|
|
57
|
+
};
|
|
58
|
+
/** @internal Pre-computed entries for fast `seed()`. */
|
|
59
|
+
readonly _entries: Array<[string, Key<unknown>]>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extracts the seed values type for an `EventKind`. This is the object
|
|
63
|
+
* shape passed to `ctx.seed(kind, seeds)` or `createEventContext(opts, kind, seeds, fn)`.
|
|
64
|
+
*/
|
|
65
|
+
type EventKindSeeds<K> = K extends EventKind<infer S> ? {
|
|
66
|
+
[P in keyof S]: S[P] extends SlotMarker<infer V> ? V : never;
|
|
67
|
+
} : never;
|
|
3
68
|
|
|
69
|
+
/** Options for creating an {@link EventContext}. */
|
|
70
|
+
interface EventContextOptions {
|
|
71
|
+
/** Logger instance available to all composables via `useLogger()`. */
|
|
72
|
+
logger: Logger;
|
|
73
|
+
/** Optional parent context. Enables transparent read-through and scoped writes. */
|
|
74
|
+
parent?: EventContext;
|
|
75
|
+
}
|
|
4
76
|
/**
|
|
5
|
-
*
|
|
77
|
+
* Per-event container for typed slots, propagated via `AsyncLocalStorage`.
|
|
78
|
+
* Composables read and write data through `get`/`set` using typed `Key` or `Cached` accessors.
|
|
79
|
+
*
|
|
80
|
+
* Supports a parent chain: when a slot is not found locally, `get()` traverses
|
|
81
|
+
* parent contexts. `set()` writes to the nearest context that already holds the slot,
|
|
82
|
+
* or locally if the slot is new.
|
|
83
|
+
*
|
|
84
|
+
* Typically created by adapters (HTTP, CLI, etc.) — application code
|
|
85
|
+
* interacts with it indirectly through composables.
|
|
6
86
|
*
|
|
7
87
|
* @example
|
|
8
88
|
* ```ts
|
|
9
|
-
* const {
|
|
10
|
-
*
|
|
89
|
+
* const ctx = new EventContext({ logger })
|
|
90
|
+
* ctx.set(userIdKey, '123')
|
|
91
|
+
* ctx.get(userIdKey) // '123'
|
|
11
92
|
* ```
|
|
12
93
|
*/
|
|
13
|
-
declare
|
|
14
|
-
|
|
15
|
-
|
|
94
|
+
declare class EventContext {
|
|
95
|
+
/** Logger instance for this event. */
|
|
96
|
+
readonly logger: Logger;
|
|
97
|
+
/** Parent context for read-through and scoped writes. */
|
|
98
|
+
readonly parent?: EventContext;
|
|
99
|
+
private slots;
|
|
100
|
+
constructor(options: EventContextOptions);
|
|
101
|
+
/**
|
|
102
|
+
* Reads a value from a typed slot.
|
|
103
|
+
* - For `Key<T>`: returns the previously `set` value, checking parent chain if not found locally.
|
|
104
|
+
* - For `Cached<T>`: returns a cached result from this context or any parent. If not found
|
|
105
|
+
* anywhere, runs the factory on first access, caches locally, and returns the result.
|
|
106
|
+
* Throws on circular dependencies. Errors are cached and re-thrown on subsequent access.
|
|
107
|
+
*/
|
|
108
|
+
get<T>(accessor: Key<T> | Cached<T>): T;
|
|
109
|
+
/**
|
|
110
|
+
* Writes a value to a typed slot. If the slot already exists somewhere in the
|
|
111
|
+
* parent chain, the value is written there. Otherwise, it is written locally.
|
|
112
|
+
*/
|
|
113
|
+
set<T>(key: Key<T> | Cached<T>, value: T): void;
|
|
114
|
+
/**
|
|
115
|
+
* Returns `true` if the slot has been set or computed in this context or any parent.
|
|
116
|
+
*/
|
|
117
|
+
has(accessor: Accessor<any>): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Reads a value from a typed slot in this context only, ignoring parents.
|
|
120
|
+
* Same semantics as `get()` but without parent chain traversal.
|
|
121
|
+
*/
|
|
122
|
+
getOwn<T>(accessor: Key<T> | Cached<T>): T;
|
|
123
|
+
/**
|
|
124
|
+
* Writes a value to a typed slot in this context only, ignoring parents.
|
|
125
|
+
*/
|
|
126
|
+
setOwn<T>(key: Key<T> | Cached<T>, value: T): void;
|
|
127
|
+
/**
|
|
128
|
+
* Returns `true` if the slot has been set or computed in this context only.
|
|
129
|
+
*/
|
|
130
|
+
hasOwn(accessor: Accessor<any>): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Seeds an event kind's slots into this context. Sets the event type key
|
|
133
|
+
* and populates all slots declared in the kind's schema.
|
|
134
|
+
*
|
|
135
|
+
* @param kind - The event kind (from `defineEventKind`)
|
|
136
|
+
* @param seeds - Values for each slot in the kind's schema
|
|
137
|
+
* @param fn - Optional callback to run after seeding (returned value is forwarded)
|
|
138
|
+
*/
|
|
139
|
+
seed<S extends Record<string, any>>(kind: EventKind<S>, seeds: EventKindSeeds<EventKind<S>>): void;
|
|
140
|
+
seed<S extends Record<string, any>, R>(kind: EventKind<S>, seeds: EventKindSeeds<EventKind<S>>, fn: () => R): R;
|
|
141
|
+
/** Walk the parent chain looking for a set slot. Returns `undefined` if not found. */
|
|
142
|
+
private _findSlot;
|
|
143
|
+
/** Set value in the first context in the chain that has this slot. Returns true if found. */
|
|
144
|
+
private _setIfExists;
|
|
145
|
+
}
|
|
16
146
|
|
|
17
147
|
/**
|
|
18
|
-
*
|
|
148
|
+
* Creates a typed, writable context slot. Use `ctx.set(k, value)` to store
|
|
149
|
+
* and `ctx.get(k)` to retrieve. Throws if read before being set.
|
|
150
|
+
*
|
|
151
|
+
* @param name - Debug label (shown in error messages, not used for lookup)
|
|
19
152
|
*
|
|
20
|
-
* @param topic - Optional topic name to create a sub-logger for.
|
|
21
153
|
* @example
|
|
22
154
|
* ```ts
|
|
23
|
-
* const
|
|
24
|
-
*
|
|
155
|
+
* const userIdKey = key<string>('userId')
|
|
156
|
+
* ctx.set(userIdKey, '123')
|
|
157
|
+
* ctx.get(userIdKey) // '123'
|
|
25
158
|
* ```
|
|
26
159
|
*/
|
|
27
|
-
declare function
|
|
28
|
-
|
|
160
|
+
declare function key<T>(name: string): Key<T>;
|
|
29
161
|
/**
|
|
30
|
-
*
|
|
162
|
+
* Creates a lazily-computed, read-only context slot. The factory runs once
|
|
163
|
+
* per `EventContext` on first `ctx.get(slot)` call; the result is cached
|
|
164
|
+
* for the context lifetime. Errors are also cached and re-thrown.
|
|
165
|
+
*
|
|
166
|
+
* @param fn - Factory receiving the current `EventContext`, returning the value to cache
|
|
31
167
|
*
|
|
32
168
|
* @example
|
|
33
169
|
* ```ts
|
|
34
|
-
* const
|
|
35
|
-
*
|
|
36
|
-
*
|
|
170
|
+
* const parsedUrl = cached((ctx) => new URL(ctx.get(rawUrlKey)))
|
|
171
|
+
* // first call computes, subsequent calls return cached result
|
|
172
|
+
* ctx.get(parsedUrl)
|
|
37
173
|
* ```
|
|
38
174
|
*/
|
|
39
|
-
declare function
|
|
40
|
-
params: T;
|
|
41
|
-
get: <K extends keyof T>(name: K) => T[K];
|
|
42
|
-
};
|
|
175
|
+
declare function cached<T>(fn: (ctx: EventContext) => T): Cached<T>;
|
|
43
176
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Creates a parameterized cached computation. Maintains a `Map<K, V>` per
|
|
179
|
+
* event context — one cached result per unique key argument.
|
|
180
|
+
*
|
|
181
|
+
* @param fn - Factory receiving the lookup key and `EventContext`, returning the value to cache
|
|
182
|
+
* @returns A function `(key: K, ctx?: EventContext) => V` that computes on first call per key
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* const parseCookie = cachedBy((name: string, ctx) => {
|
|
187
|
+
* const raw = ctx.get(cookieHeaderKey)
|
|
188
|
+
* return parseSingleCookie(raw, name)
|
|
189
|
+
* })
|
|
190
|
+
*
|
|
191
|
+
* parseCookie('session') // computed and cached for 'session'
|
|
192
|
+
* parseCookie('theme') // computed and cached for 'theme'
|
|
193
|
+
* parseCookie('session') // returns cached result
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
declare function cachedBy<K, V>(fn: (key: K, ctx: EventContext) => V): (key: K, ctx?: EventContext) => V;
|
|
61
197
|
|
|
62
|
-
/** Configuration options for event context creation. */
|
|
63
|
-
interface TEventOptions {
|
|
64
|
-
eventLogger?: {
|
|
65
|
-
topic?: string;
|
|
66
|
-
} & TProstoLoggerOptions<TEventLoggerData>;
|
|
67
|
-
}
|
|
68
|
-
/** Shape of the context store that holds event data, options, and route params. */
|
|
69
|
-
interface TGenericContextStore<CustomEventType = TEmpty> {
|
|
70
|
-
event: CustomEventType & TGenericEvent;
|
|
71
|
-
options: TEventOptions;
|
|
72
|
-
parentCtx?: TGenericContextStore;
|
|
73
|
-
routeParams?: Record<string, string | string[]>;
|
|
74
|
-
_ended?: boolean;
|
|
75
|
-
}
|
|
76
198
|
/**
|
|
77
|
-
*
|
|
199
|
+
* Type-level marker used inside `defineEventKind` schemas. Each `slot<T>()`
|
|
200
|
+
* becomes a typed `Key<T>` on the resulting `EventKind`. Has no runtime behavior.
|
|
78
201
|
*
|
|
79
|
-
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* const httpKind = defineEventKind('http', {
|
|
205
|
+
* req: slot<IncomingMessage>(),
|
|
206
|
+
* response: slot<HttpResponse>(),
|
|
207
|
+
* })
|
|
208
|
+
* ```
|
|
80
209
|
*/
|
|
81
|
-
declare
|
|
210
|
+
declare function slot<T>(): SlotMarker<T>;
|
|
82
211
|
/**
|
|
83
|
-
*
|
|
212
|
+
* Declares a named event kind with typed seed slots. The returned object
|
|
213
|
+
* contains `keys` — typed accessors for reading seed values from context —
|
|
214
|
+
* and is passed to `ctx.seed(kind, seeds)` or `createEventContext()`.
|
|
215
|
+
*
|
|
216
|
+
* @param name - Unique event kind name (e.g. `'http'`, `'cli'`, `'workflow'`)
|
|
217
|
+
* @param schema - Object mapping slot names to `slot<T>()` markers
|
|
218
|
+
* @returns An `EventKind` with typed `keys` for context access
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* const httpKind = defineEventKind('http', {
|
|
223
|
+
* req: slot<IncomingMessage>(),
|
|
224
|
+
* response: slot<HttpResponse>(),
|
|
225
|
+
* })
|
|
84
226
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
227
|
+
* // Access typed seed values:
|
|
228
|
+
* const req = ctx.get(httpKind.keys.req) // IncomingMessage
|
|
229
|
+
* ```
|
|
87
230
|
*/
|
|
88
|
-
declare function
|
|
231
|
+
declare function defineEventKind<S extends Record<string, SlotMarker<any>>>(name: string, schema: S): EventKind<S>;
|
|
232
|
+
|
|
89
233
|
/**
|
|
90
|
-
*
|
|
234
|
+
* Creates a composable with per-event caching. The factory runs once per
|
|
235
|
+
* `EventContext`; subsequent calls within the same event return the cached result.
|
|
236
|
+
*
|
|
237
|
+
* This is the recommended way to build composables in Wooks. All built-in
|
|
238
|
+
* composables (`useRequest`, `useResponse`, `useCookies`, etc.) are created with `defineWook`.
|
|
91
239
|
*
|
|
92
|
-
* @param
|
|
93
|
-
* @
|
|
240
|
+
* @param factory - Receives the `EventContext` and returns the composable's public API
|
|
241
|
+
* @returns A composable function `(ctx?: EventContext) => T`
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* export const useCurrentUser = defineWook((ctx) => {
|
|
246
|
+
* const { basicCredentials } = useAuthorization(ctx)
|
|
247
|
+
* const username = basicCredentials()?.username
|
|
248
|
+
* return {
|
|
249
|
+
* username,
|
|
250
|
+
* profile: async () => username ? await db.findUser(username) : null,
|
|
251
|
+
* }
|
|
252
|
+
* })
|
|
253
|
+
*
|
|
254
|
+
* // In a handler — factory runs once, cached for the request:
|
|
255
|
+
* const { username, profile } = useCurrentUser()
|
|
256
|
+
* ```
|
|
94
257
|
*/
|
|
95
|
-
declare function
|
|
96
|
-
/** Helper methods returned by `useAsyncEventContext` for interacting with the context store. */
|
|
97
|
-
interface TCtxHelpers<T> {
|
|
98
|
-
getCtx: () => T;
|
|
99
|
-
store: <K extends keyof Required<T>>(key: K) => {
|
|
100
|
-
value: T[K];
|
|
101
|
-
hook: <K2 extends keyof Required<T>[K]>(key2: K2) => {
|
|
102
|
-
value: Required<T>[K][K2];
|
|
103
|
-
isDefined: boolean;
|
|
104
|
-
};
|
|
105
|
-
init: <K2 extends keyof Required<T>[K]>(key2: K2, getter: () => Required<Required<T>[K]>[K2]) => Required<Required<T>[K]>[K2];
|
|
106
|
-
set: <K2 extends keyof Required<T>[K]>(key2: K2, v: Required<T[K]>[K2]) => Required<T[K]>[K2];
|
|
107
|
-
get: <K2 extends keyof Required<T>[K]>(key2: K2) => Required<T>[K][K2] | undefined;
|
|
108
|
-
has: <K2 extends keyof Required<T>[K]>(key2: K2) => boolean;
|
|
109
|
-
del: <K2 extends keyof Required<T>[K]>(key2: K2) => void;
|
|
110
|
-
entries: () => Array<[string, unknown]>;
|
|
111
|
-
clear: () => void;
|
|
112
|
-
};
|
|
113
|
-
getStore: <K extends keyof T>(key: K) => T[K];
|
|
114
|
-
setStore: <K extends keyof T>(key: K, v: T[K]) => void;
|
|
115
|
-
setParentCtx: (parentCtx: unknown) => void;
|
|
116
|
-
hasParentCtx: () => boolean;
|
|
117
|
-
getParentCtx: <T2 = T>() => TCtxHelpers<T2>;
|
|
118
|
-
}
|
|
258
|
+
declare function defineWook<T>(factory: (ctx: EventContext) => T): (ctx?: EventContext) => T;
|
|
119
259
|
|
|
120
260
|
/**
|
|
121
|
-
*
|
|
261
|
+
* No-op base class for observability integration. Subclass and override
|
|
262
|
+
* `with()` / `hook()` to add tracing, metrics, or logging around event
|
|
263
|
+
* lifecycle points.
|
|
122
264
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
265
|
+
* The default implementation simply calls the callback with no overhead.
|
|
266
|
+
* Replace via `replaceContextInjector()` to enable instrumentation.
|
|
125
267
|
*/
|
|
126
268
|
declare class ContextInjector<N> {
|
|
127
|
-
|
|
128
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Wraps a callback with optional named attributes for observability.
|
|
271
|
+
* Default implementation just calls `cb()` — override for tracing.
|
|
272
|
+
*/
|
|
273
|
+
with<T>(name: N, attributes: Record<string, string | number | boolean>, cb: () => T): T;
|
|
274
|
+
with<T>(name: N, cb: () => T): T;
|
|
275
|
+
/**
|
|
276
|
+
* Hook called by adapters at specific lifecycle points (e.g., after route lookup).
|
|
277
|
+
* Default implementation is a no-op — override for observability.
|
|
278
|
+
*/
|
|
129
279
|
hook(_method: string, _name: 'Handler:not_found' | 'Handler:routed', _route?: string): void;
|
|
130
280
|
}
|
|
131
|
-
|
|
132
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Returns the current `ContextInjector` instance (default: no-op).
|
|
283
|
+
* Used internally by adapters to wrap lifecycle events.
|
|
284
|
+
*/
|
|
133
285
|
declare function getContextInjector<N = TContextInjectorHooks>(): ContextInjector<N>;
|
|
134
|
-
/**
|
|
286
|
+
/**
|
|
287
|
+
* Replaces the global `ContextInjector` with a custom implementation.
|
|
288
|
+
* Use this to integrate OpenTelemetry or other observability tools.
|
|
289
|
+
*
|
|
290
|
+
* @param newCi - Custom `ContextInjector` subclass instance
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```ts
|
|
294
|
+
* class OtelInjector extends ContextInjector<string> {
|
|
295
|
+
* with<T>(name: string, attrs: Record<string, any>, cb: () => T): T {
|
|
296
|
+
* return tracer.startActiveSpan(name, (span) => {
|
|
297
|
+
* span.setAttributes(attrs)
|
|
298
|
+
* try { return cb() } finally { span.end() }
|
|
299
|
+
* })
|
|
300
|
+
* }
|
|
301
|
+
* }
|
|
302
|
+
* replaceContextInjector(new OtelInjector())
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
135
305
|
declare function replaceContextInjector(newCi: ContextInjector<string>): void;
|
|
306
|
+
/** Built-in hook names used by the framework. */
|
|
136
307
|
type TContextInjectorHooks = 'Event:start';
|
|
137
308
|
|
|
309
|
+
/** Context key for route parameters. Set by adapters after route matching. */
|
|
310
|
+
declare const routeParamsKey: Key<Record<string, string | string[]>>;
|
|
311
|
+
/** Context key for the event type name (e.g. `'http'`, `'cli'`). Set by `ctx.seed()`. */
|
|
312
|
+
declare const eventTypeKey: Key<string>;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Returns the route parameters for the current event. Works with HTTP
|
|
316
|
+
* routes, CLI commands, workflow steps — any adapter that sets `routeParamsKey`.
|
|
317
|
+
*
|
|
318
|
+
* @param ctx - Optional explicit context (defaults to `current()`)
|
|
319
|
+
* @returns Object with `params` (the full params record) and `get(name)` for typed access
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```ts
|
|
323
|
+
* app.get('/users/:id', () => {
|
|
324
|
+
* const { params, get } = useRouteParams<{ id: string }>()
|
|
325
|
+
* console.log(get('id')) // typed as string
|
|
326
|
+
* })
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
declare function useRouteParams<T extends Record<string, string | string[]> = Record<string, string | string[]>>(ctx?: EventContext): {
|
|
330
|
+
params: T;
|
|
331
|
+
get: <K extends keyof T>(name: K) => T[K];
|
|
332
|
+
};
|
|
333
|
+
/**
|
|
334
|
+
* Provides a unique, per-event identifier. The ID is a random UUID, generated
|
|
335
|
+
* lazily on first `getId()` call and cached for the event lifetime.
|
|
336
|
+
*
|
|
337
|
+
* @param ctx - Optional explicit context (defaults to `current()`)
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```ts
|
|
341
|
+
* const { getId } = useEventId()
|
|
342
|
+
* logger.info(`Request ${getId()}`)
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
declare function useEventId(ctx?: EventContext): {
|
|
346
|
+
getId: () => string;
|
|
347
|
+
};
|
|
348
|
+
|
|
138
349
|
/**
|
|
139
|
-
*
|
|
350
|
+
* Runs a callback with the given `EventContext` as the active context.
|
|
351
|
+
* All composables and `current()` calls inside `fn` will resolve to `ctx`.
|
|
352
|
+
*
|
|
353
|
+
* @param ctx - The event context to make active
|
|
354
|
+
* @param fn - Callback to execute within the context scope
|
|
355
|
+
* @returns The return value of `fn`
|
|
140
356
|
*
|
|
141
|
-
* @
|
|
142
|
-
*
|
|
143
|
-
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```ts
|
|
359
|
+
* const ctx = new EventContext({ logger })
|
|
360
|
+
* run(ctx, () => {
|
|
361
|
+
* // current() returns ctx here
|
|
362
|
+
* const logger = useLogger()
|
|
363
|
+
* })
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
declare function run<R>(ctx: EventContext, fn: () => R): R;
|
|
367
|
+
/**
|
|
368
|
+
* Returns the active `EventContext` for the current async scope.
|
|
369
|
+
* Throws if called outside an event context (e.g., at module level).
|
|
370
|
+
*
|
|
371
|
+
* All composables use this internally. Prefer composables over direct `current()` access.
|
|
372
|
+
*
|
|
373
|
+
* @throws Error if no active event context exists
|
|
374
|
+
*/
|
|
375
|
+
declare function current(): EventContext;
|
|
376
|
+
/**
|
|
377
|
+
* Returns the active `EventContext`, or `undefined` if none is active.
|
|
378
|
+
* Use this when context availability is uncertain (e.g., in code that may
|
|
379
|
+
* run both inside and outside an event handler).
|
|
380
|
+
*/
|
|
381
|
+
declare function tryGetCurrent(): EventContext | undefined;
|
|
382
|
+
/**
|
|
383
|
+
* Returns the logger for the current event context.
|
|
384
|
+
*
|
|
385
|
+
* @param ctx - Optional explicit context (defaults to `current()`)
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```ts
|
|
389
|
+
* const logger = useLogger()
|
|
390
|
+
* logger.info('Processing request')
|
|
391
|
+
* ```
|
|
392
|
+
*/
|
|
393
|
+
declare function useLogger(ctx?: EventContext): Logger;
|
|
394
|
+
/**
|
|
395
|
+
* Creates a new `EventContext`, makes it the active context via
|
|
396
|
+
* `AsyncLocalStorage`, and runs `fn` inside it.
|
|
397
|
+
*
|
|
398
|
+
* @param options - Context options (must include `logger`)
|
|
399
|
+
* @param fn - Callback to execute within the new context
|
|
400
|
+
* @returns The return value of `fn`
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* createEventContext({ logger }, () => {
|
|
405
|
+
* // composables work here
|
|
406
|
+
* })
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
declare function createEventContext<R>(options: EventContextOptions, fn: () => R): R;
|
|
410
|
+
/**
|
|
411
|
+
* Creates a new `EventContext` with an event kind, seeds the kind's slots,
|
|
412
|
+
* and runs `fn` inside the context.
|
|
413
|
+
*
|
|
414
|
+
* @param options - Context options (must include `logger`)
|
|
415
|
+
* @param kind - Event kind (from `defineEventKind`)
|
|
416
|
+
* @param seeds - Seed values for the event kind's slots
|
|
417
|
+
* @param fn - Callback to execute within the new context
|
|
418
|
+
* @returns The return value of `fn`
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```ts
|
|
422
|
+
* const httpKind = defineEventKind('http', { req: slot<IncomingMessage>() })
|
|
423
|
+
*
|
|
424
|
+
* createEventContext({ logger }, httpKind, { req: incomingMessage }, () => {
|
|
425
|
+
* const req = current().get(httpKind.keys.req)
|
|
426
|
+
* })
|
|
427
|
+
* ```
|
|
144
428
|
*/
|
|
145
|
-
declare function
|
|
146
|
-
get: () => V | undefined;
|
|
147
|
-
set?: (value: V) => void;
|
|
148
|
-
}, name?: P): T & THook<V, P>;
|
|
149
|
-
/** A record type representing a hooked property on an object. */
|
|
150
|
-
type THook<T = string, K extends PropertyKey = 'value'> = Record<K, T>;
|
|
429
|
+
declare function createEventContext<S extends Record<string, any>, R>(options: EventContextOptions, kind: EventKind<S>, seeds: EventKindSeeds<EventKind<S>>, fn: () => R): R;
|
|
151
430
|
|
|
152
|
-
export { ContextInjector,
|
|
153
|
-
export type {
|
|
431
|
+
export { ContextInjector, EventContext, cached, cachedBy, createEventContext, current, defineEventKind, defineWook, eventTypeKey, getContextInjector, key, replaceContextInjector, routeParamsKey, run, slot, tryGetCurrent, useEventId, useLogger, useRouteParams };
|
|
432
|
+
export type { Accessor, Cached, EventContextOptions, EventKind, EventKindSeeds, Key, Logger, SlotMarker, TContextInjectorHooks };
|