@wooksjs/event-core 0.7.1 → 0.7.3
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/dist/index.cjs
CHANGED
|
@@ -251,9 +251,9 @@ var ContextInjector = class {
|
|
|
251
251
|
*/
|
|
252
252
|
hook(_method, _name, _route) {}
|
|
253
253
|
};
|
|
254
|
-
let ci =
|
|
254
|
+
let ci = null;
|
|
255
255
|
/**
|
|
256
|
-
* Returns the current `ContextInjector` instance
|
|
256
|
+
* Returns the current `ContextInjector` instance, or `null` if none has been installed.
|
|
257
257
|
* Used internally by adapters to wrap lifecycle events.
|
|
258
258
|
*/
|
|
259
259
|
function getContextInjector() {
|
|
@@ -281,12 +281,19 @@ function getContextInjector() {
|
|
|
281
281
|
function replaceContextInjector(newCi) {
|
|
282
282
|
ci = newCi;
|
|
283
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Resets the global `ContextInjector` back to `null` (no-op default).
|
|
286
|
+
* Useful for tests or when disabling instrumentation.
|
|
287
|
+
*/
|
|
288
|
+
function resetContextInjector() {
|
|
289
|
+
ci = null;
|
|
290
|
+
}
|
|
284
291
|
|
|
285
292
|
//#endregion
|
|
286
293
|
//#region packages/event-core/src/storage.ts
|
|
287
294
|
const STORAGE_KEY = Symbol.for("wooks.core.asyncStorage");
|
|
288
295
|
const VERSION_KEY = Symbol.for("wooks.core.asyncStorage.version");
|
|
289
|
-
const CURRENT_VERSION = "0.7.
|
|
296
|
+
const CURRENT_VERSION = "0.7.2";
|
|
290
297
|
const _g = globalThis;
|
|
291
298
|
if (_g[STORAGE_KEY]) {
|
|
292
299
|
if (_g[VERSION_KEY] !== CURRENT_VERSION) throw new Error(`[wooks] Incompatible versions of @wooksjs/event-core detected: existing v${_g[VERSION_KEY]}, loading v${CURRENT_VERSION}. All packages must use the same @wooksjs/event-core version.`);
|
|
@@ -355,7 +362,8 @@ function createEventContext(options, kindOrFn, seedsOrUndefined, maybeFn) {
|
|
|
355
362
|
if (typeof kindOrFn === "function") return run(ctx, kindOrFn);
|
|
356
363
|
return run(ctx, () => {
|
|
357
364
|
ctx.seed(kindOrFn, seedsOrUndefined);
|
|
358
|
-
|
|
365
|
+
const ci$1 = getContextInjector();
|
|
366
|
+
return ci$1 ? ci$1.with("Event:start", { eventType: kindOrFn.name }, maybeFn) : maybeFn();
|
|
359
367
|
});
|
|
360
368
|
}
|
|
361
369
|
|
|
@@ -530,6 +538,7 @@ exports.eventTypeKey = eventTypeKey;
|
|
|
530
538
|
exports.getContextInjector = getContextInjector;
|
|
531
539
|
exports.key = key;
|
|
532
540
|
exports.replaceContextInjector = replaceContextInjector;
|
|
541
|
+
exports.resetContextInjector = resetContextInjector;
|
|
533
542
|
exports.routeParamsKey = routeParamsKey;
|
|
534
543
|
exports.run = run;
|
|
535
544
|
exports.slot = slot;
|
package/dist/index.d.ts
CHANGED
|
@@ -279,10 +279,10 @@ declare class ContextInjector<N> {
|
|
|
279
279
|
hook(_method: string, _name: 'Handler:not_found' | 'Handler:routed', _route?: string): void;
|
|
280
280
|
}
|
|
281
281
|
/**
|
|
282
|
-
* Returns the current `ContextInjector` instance
|
|
282
|
+
* Returns the current `ContextInjector` instance, or `null` if none has been installed.
|
|
283
283
|
* Used internally by adapters to wrap lifecycle events.
|
|
284
284
|
*/
|
|
285
|
-
declare function getContextInjector<N = TContextInjectorHooks>(): ContextInjector<N
|
|
285
|
+
declare function getContextInjector<N = TContextInjectorHooks>(): ContextInjector<N> | null;
|
|
286
286
|
/**
|
|
287
287
|
* Replaces the global `ContextInjector` with a custom implementation.
|
|
288
288
|
* Use this to integrate OpenTelemetry or other observability tools.
|
|
@@ -303,6 +303,11 @@ declare function getContextInjector<N = TContextInjectorHooks>(): ContextInjecto
|
|
|
303
303
|
* ```
|
|
304
304
|
*/
|
|
305
305
|
declare function replaceContextInjector(newCi: ContextInjector<string>): void;
|
|
306
|
+
/**
|
|
307
|
+
* Resets the global `ContextInjector` back to `null` (no-op default).
|
|
308
|
+
* Useful for tests or when disabling instrumentation.
|
|
309
|
+
*/
|
|
310
|
+
declare function resetContextInjector(): void;
|
|
306
311
|
/** Built-in hook names used by the framework. */
|
|
307
312
|
type TContextInjectorHooks = 'Event:start';
|
|
308
313
|
|
|
@@ -399,6 +404,9 @@ declare function useLogger(ctx?: EventContext): Logger;
|
|
|
399
404
|
* @param fn - Callback to execute within the new context
|
|
400
405
|
* @returns The return value of `fn`
|
|
401
406
|
*
|
|
407
|
+
* The kindless overload is a convenience for tests that need a context scope
|
|
408
|
+
* without declaring an event kind. Production code should always provide a kind.
|
|
409
|
+
*
|
|
402
410
|
* @example
|
|
403
411
|
* ```ts
|
|
404
412
|
* createEventContext({ logger }, () => {
|
|
@@ -428,5 +436,5 @@ declare function createEventContext<R>(options: EventContextOptions, fn: () => R
|
|
|
428
436
|
*/
|
|
429
437
|
declare function createEventContext<S extends Record<string, any>, R>(options: EventContextOptions, kind: EventKind<S>, seeds: EventKindSeeds<EventKind<S>>, fn: () => R): R;
|
|
430
438
|
|
|
431
|
-
export { ContextInjector, EventContext, cached, cachedBy, createEventContext, current, defineEventKind, defineWook, eventTypeKey, getContextInjector, key, replaceContextInjector, routeParamsKey, run, slot, tryGetCurrent, useEventId, useLogger, useRouteParams };
|
|
439
|
+
export { ContextInjector, EventContext, cached, cachedBy, createEventContext, current, defineEventKind, defineWook, eventTypeKey, getContextInjector, key, replaceContextInjector, resetContextInjector, routeParamsKey, run, slot, tryGetCurrent, useEventId, useLogger, useRouteParams };
|
|
432
440
|
export type { Accessor, Cached, EventContextOptions, EventKind, EventKindSeeds, Key, Logger, SlotMarker, TContextInjectorHooks };
|
package/dist/index.mjs
CHANGED
|
@@ -228,9 +228,9 @@ var ContextInjector = class {
|
|
|
228
228
|
*/
|
|
229
229
|
hook(_method, _name, _route) {}
|
|
230
230
|
};
|
|
231
|
-
let ci =
|
|
231
|
+
let ci = null;
|
|
232
232
|
/**
|
|
233
|
-
* Returns the current `ContextInjector` instance
|
|
233
|
+
* Returns the current `ContextInjector` instance, or `null` if none has been installed.
|
|
234
234
|
* Used internally by adapters to wrap lifecycle events.
|
|
235
235
|
*/
|
|
236
236
|
function getContextInjector() {
|
|
@@ -258,12 +258,19 @@ function getContextInjector() {
|
|
|
258
258
|
function replaceContextInjector(newCi) {
|
|
259
259
|
ci = newCi;
|
|
260
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Resets the global `ContextInjector` back to `null` (no-op default).
|
|
263
|
+
* Useful for tests or when disabling instrumentation.
|
|
264
|
+
*/
|
|
265
|
+
function resetContextInjector() {
|
|
266
|
+
ci = null;
|
|
267
|
+
}
|
|
261
268
|
|
|
262
269
|
//#endregion
|
|
263
270
|
//#region packages/event-core/src/storage.ts
|
|
264
271
|
const STORAGE_KEY = Symbol.for("wooks.core.asyncStorage");
|
|
265
272
|
const VERSION_KEY = Symbol.for("wooks.core.asyncStorage.version");
|
|
266
|
-
const CURRENT_VERSION = "0.7.
|
|
273
|
+
const CURRENT_VERSION = "0.7.2";
|
|
267
274
|
const _g = globalThis;
|
|
268
275
|
if (_g[STORAGE_KEY]) {
|
|
269
276
|
if (_g[VERSION_KEY] !== CURRENT_VERSION) throw new Error(`[wooks] Incompatible versions of @wooksjs/event-core detected: existing v${_g[VERSION_KEY]}, loading v${CURRENT_VERSION}. All packages must use the same @wooksjs/event-core version.`);
|
|
@@ -332,7 +339,8 @@ function createEventContext(options, kindOrFn, seedsOrUndefined, maybeFn) {
|
|
|
332
339
|
if (typeof kindOrFn === "function") return run(ctx, kindOrFn);
|
|
333
340
|
return run(ctx, () => {
|
|
334
341
|
ctx.seed(kindOrFn, seedsOrUndefined);
|
|
335
|
-
|
|
342
|
+
const ci$1 = getContextInjector();
|
|
343
|
+
return ci$1 ? ci$1.with("Event:start", { eventType: kindOrFn.name }, maybeFn) : maybeFn();
|
|
336
344
|
});
|
|
337
345
|
}
|
|
338
346
|
|
|
@@ -495,4 +503,4 @@ function useEventId(ctx) {
|
|
|
495
503
|
}
|
|
496
504
|
|
|
497
505
|
//#endregion
|
|
498
|
-
export { ContextInjector, EventContext, cached, cachedBy, createEventContext, current, defineEventKind, defineWook, eventTypeKey, getContextInjector, key, replaceContextInjector, routeParamsKey, run, slot, tryGetCurrent, useEventId, useLogger, useRouteParams };
|
|
506
|
+
export { ContextInjector, EventContext, cached, cachedBy, createEventContext, current, defineEventKind, defineWook, eventTypeKey, getContextInjector, key, replaceContextInjector, resetContextInjector, routeParamsKey, run, slot, tryGetCurrent, useEventId, useLogger, useRouteParams };
|
package/package.json
CHANGED
|
@@ -175,39 +175,52 @@ This prevents subtle bugs from multiple context stores.
|
|
|
175
175
|
|
|
176
176
|
### Pattern: Custom adapter
|
|
177
177
|
|
|
178
|
-
Build an adapter that creates contexts and runs handlers
|
|
178
|
+
Build an adapter that creates contexts and runs handlers. Each adapter exports a **context factory** that hardcodes the kind and delegates to `createEventContext`:
|
|
179
179
|
|
|
180
180
|
```ts
|
|
181
|
-
import {
|
|
181
|
+
import { createEventContext, defineEventKind, slot } from '@wooksjs/event-core'
|
|
182
|
+
import type { EventContextOptions, EventKindSeeds } from '@wooksjs/event-core'
|
|
182
183
|
|
|
183
184
|
const myKind = defineEventKind('my-event', {
|
|
184
185
|
data: slot<unknown>(),
|
|
185
186
|
})
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
// Context factory — same signature as createEventContext, minus the kind
|
|
189
|
+
export function createMyEventContext<R>(
|
|
190
|
+
options: EventContextOptions,
|
|
191
|
+
seeds: EventKindSeeds<typeof myKind>,
|
|
192
|
+
fn: () => R,
|
|
193
|
+
): R {
|
|
194
|
+
return createEventContext(options, myKind, seeds, fn)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Usage in the adapter
|
|
198
|
+
function handleEvent(data: unknown, handler: () => unknown) {
|
|
199
|
+
return createMyEventContext({ logger: console }, { data }, handler)
|
|
191
200
|
}
|
|
192
201
|
```
|
|
193
202
|
|
|
203
|
+
All built-in adapters follow this pattern: `createHttpContext`, `createCliContext`, `createWsConnectionContext`, `createWsMessageContext`, `createWfContext`, `resumeWfContext`.
|
|
204
|
+
|
|
194
205
|
### Pattern: Child contexts with parent links
|
|
195
206
|
|
|
196
|
-
Instead of attaching multiple kinds to a single context, create child contexts
|
|
207
|
+
Instead of attaching multiple kinds to a single context, create child contexts by passing `parent` in the options. Each child sees its own data plus everything in the parent chain:
|
|
197
208
|
|
|
198
209
|
```ts
|
|
199
210
|
createEventContext({ logger }, httpKind, httpSeeds, () => {
|
|
200
211
|
const parentCtx = current()
|
|
201
212
|
|
|
202
|
-
// Create a child context
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
// Create a child context linked to the HTTP parent
|
|
214
|
+
createEventContext(
|
|
215
|
+
{ logger, parent: parentCtx },
|
|
216
|
+
workflowKind,
|
|
217
|
+
{ triggerId: 'deploy-42', payload },
|
|
218
|
+
() => {
|
|
219
|
+
// Both HTTP and workflow composables work
|
|
220
|
+
const { method } = useRequest() // found via parent chain
|
|
221
|
+
const { triggerId } = useWorkflow() // found locally
|
|
222
|
+
},
|
|
223
|
+
)
|
|
211
224
|
})
|
|
212
225
|
```
|
|
213
226
|
|
|
@@ -234,10 +247,10 @@ const log = ctx.logger
|
|
|
234
247
|
|
|
235
248
|
## ContextInjector (observability)
|
|
236
249
|
|
|
237
|
-
`ContextInjector` is a hook point for observability tools (OpenTelemetry, etc.).
|
|
250
|
+
`ContextInjector` is a hook point for observability tools (OpenTelemetry, etc.). No injector is installed by default — `getContextInjector()` returns `null`, so all adapters run with zero overhead until one is installed.
|
|
238
251
|
|
|
239
252
|
```ts
|
|
240
|
-
import { ContextInjector, replaceContextInjector } from '@wooksjs/event-core'
|
|
253
|
+
import { ContextInjector, replaceContextInjector, resetContextInjector } from '@wooksjs/event-core'
|
|
241
254
|
|
|
242
255
|
class OtelInjector extends ContextInjector<string> {
|
|
243
256
|
with<T>(name: string, attributes: Record<string, any>, cb: () => T): T {
|
|
@@ -246,9 +259,14 @@ class OtelInjector extends ContextInjector<string> {
|
|
|
246
259
|
}
|
|
247
260
|
|
|
248
261
|
replaceContextInjector(new OtelInjector())
|
|
262
|
+
|
|
263
|
+
// To disable instrumentation later:
|
|
264
|
+
resetContextInjector()
|
|
249
265
|
```
|
|
250
266
|
|
|
251
|
-
The injector's `with()` method wraps `createEventContext` callbacks
|
|
267
|
+
The injector's `with()` method wraps `createEventContext` callbacks. All adapters (HTTP, CLI, WS, WF) route through `createEventContext`, so installing an injector automatically instruments every event type.
|
|
268
|
+
|
|
269
|
+
Adapter callbacks **return their result** (sync value or Promise), so `with()` can track async handler completion for span lifecycle. A `TracingInjector` can detect thenable returns and attach `.then()/.catch()` to end spans when the handler settles — no separate `onEnd()` hook needed.
|
|
252
270
|
|
|
253
271
|
## Best Practices
|
|
254
272
|
|
|
@@ -62,9 +62,10 @@ Every event (HTTP request, CLI invocation, workflow step) gets its own `EventCon
|
|
|
62
62
|
| `useEventId(ctx?)` | composable | Lazy UUID per event |
|
|
63
63
|
| `routeParamsKey` | key | Standard key for route params |
|
|
64
64
|
| `eventTypeKey` | key | Standard key for event type name |
|
|
65
|
-
| `ContextInjector` | class | Observability hook point (OpenTelemetry etc.)
|
|
66
|
-
| `getContextInjector()` | function | Get current injector
|
|
67
|
-
| `replaceContextInjector(ci)` | function |
|
|
65
|
+
| `ContextInjector` | class | Observability hook point (OpenTelemetry etc.). Defaults to `null` — zero overhead until installed. |
|
|
66
|
+
| `getContextInjector()` | function | Get current injector (returns `null` when none installed) |
|
|
67
|
+
| `replaceContextInjector(ci)` | function | Install a custom injector (e.g. with OTel spans) |
|
|
68
|
+
| `resetContextInjector()` | function | Reset injector back to `null` (disables instrumentation) |
|
|
68
69
|
|
|
69
70
|
## Types
|
|
70
71
|
|