@wooksjs/event-core 0.6.1 → 0.6.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 +94 -36
- package/dist/index.d.ts +59 -9
- package/dist/index.mjs +94 -36
- package/package.json +28 -28
package/dist/index.cjs
CHANGED
|
@@ -37,18 +37,27 @@ var ContextInjector = class {
|
|
|
37
37
|
const fn = typeof attributes === "function" ? attributes : cb;
|
|
38
38
|
return fn();
|
|
39
39
|
}
|
|
40
|
-
hook(
|
|
40
|
+
hook(_method, _name, _route) {}
|
|
41
41
|
};
|
|
42
42
|
let ci = new ContextInjector();
|
|
43
|
+
/** Returns the current global `ContextInjector` instance. */
|
|
43
44
|
function getContextInjector() {
|
|
44
45
|
return ci;
|
|
45
46
|
}
|
|
47
|
+
/** Replaces the global `ContextInjector` instance (e.g., to integrate with OpenTelemetry). */
|
|
46
48
|
function replaceContextInjector(newCi) {
|
|
47
49
|
ci = newCi;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
//#endregion
|
|
51
53
|
//#region packages/event-core/src/hook.ts
|
|
54
|
+
/**
|
|
55
|
+
* Attaches a getter/setter hook to a target object property via `Object.defineProperty`.
|
|
56
|
+
*
|
|
57
|
+
* @param target - The object to attach the hook to.
|
|
58
|
+
* @param opts - Getter and optional setter for the hooked property.
|
|
59
|
+
* @param name - Property name to hook (defaults to `'value'`).
|
|
60
|
+
*/
|
|
52
61
|
function attachHook(target, opts, name) {
|
|
53
62
|
Object.defineProperty(target, name || "value", {
|
|
54
63
|
get: opts.get,
|
|
@@ -59,14 +68,29 @@ function attachHook(target, opts, name) {
|
|
|
59
68
|
|
|
60
69
|
//#endregion
|
|
61
70
|
//#region packages/event-core/src/context.ts
|
|
71
|
+
const STORAGE_KEY = Symbol.for("wooks.asyncStorage");
|
|
72
|
+
const VERSION_KEY = Symbol.for("wooks.asyncStorage.version");
|
|
73
|
+
const CURRENT_VERSION = "0.6.2";
|
|
74
|
+
const _g = globalThis;
|
|
75
|
+
if (_g[STORAGE_KEY]) {
|
|
76
|
+
if (_g[VERSION_KEY] !== CURRENT_VERSION) console.warn(`[33m[wooks] Multiple versions of @wooksjs/event-core detected: existing v${_g[VERSION_KEY]}, current v${CURRENT_VERSION}. Reusing existing asyncStorage to avoid runtime errors.[0m`);
|
|
77
|
+
} else {
|
|
78
|
+
_g[STORAGE_KEY] = new node_async_hooks.AsyncLocalStorage();
|
|
79
|
+
_g[VERSION_KEY] = CURRENT_VERSION;
|
|
80
|
+
}
|
|
62
81
|
/**
|
|
63
82
|
* AsyncLocalStorage instance
|
|
64
83
|
*
|
|
65
84
|
* Use on your own risk only if you know what you're doing
|
|
66
85
|
*/
|
|
67
|
-
const asyncStorage =
|
|
86
|
+
const asyncStorage = _g[STORAGE_KEY];
|
|
87
|
+
/** Symbol key for caching store accessors directly on the context object */
|
|
88
|
+
const _storeCacheKey = Symbol("storeCache");
|
|
68
89
|
/**
|
|
69
|
-
*
|
|
90
|
+
* Creates a new async event context and returns a runner function to execute callbacks within it.
|
|
91
|
+
*
|
|
92
|
+
* @param data - Initial context store data including the event object and options.
|
|
93
|
+
* @returns A function that runs a callback within the created async context.
|
|
70
94
|
*/
|
|
71
95
|
function createAsyncEventContext(data) {
|
|
72
96
|
const newContext = { ...data };
|
|
@@ -76,7 +100,10 @@ function createAsyncEventContext(data) {
|
|
|
76
100
|
return (cb) => asyncStorage.run(newContext, () => ci$1.with("Event:start", { eventType: newContext.event.type }, cb));
|
|
77
101
|
}
|
|
78
102
|
/**
|
|
79
|
-
*
|
|
103
|
+
* Retrieves the current async event context and returns helpers for reading/writing the store.
|
|
104
|
+
*
|
|
105
|
+
* @param expectedTypes - Optional event type(s) to validate the context against.
|
|
106
|
+
* @throws If no event context exists or if the event type does not match.
|
|
80
107
|
*/
|
|
81
108
|
function useAsyncEventContext(expectedTypes) {
|
|
82
109
|
let cc = asyncStorage.getStore();
|
|
@@ -89,12 +116,10 @@ function useAsyncEventContext(expectedTypes) {
|
|
|
89
116
|
}
|
|
90
117
|
return _getCtxHelpers(cc);
|
|
91
118
|
}
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @param cc
|
|
95
|
-
* @returns
|
|
96
|
-
*/
|
|
97
119
|
function _getCtxHelpers(cc) {
|
|
120
|
+
const ccAny = cc;
|
|
121
|
+
if (!ccAny[_storeCacheKey]) ccAny[_storeCacheKey] = /* @__PURE__ */ new Map();
|
|
122
|
+
const _storeCache = ccAny[_storeCacheKey];
|
|
98
123
|
/**
|
|
99
124
|
* Hook to an event store property
|
|
100
125
|
*
|
|
@@ -102,6 +127,12 @@ function _getCtxHelpers(cc) {
|
|
|
102
127
|
* @returns a hook { value: <prop value>, hook: (key2: keyof <prop value>) => { value: <nested prop value> }, ... }
|
|
103
128
|
*/
|
|
104
129
|
function store(key) {
|
|
130
|
+
const cachedStore = _storeCache.get(key);
|
|
131
|
+
if (cachedStore) return cachedStore;
|
|
132
|
+
const getSection = () => cc[key];
|
|
133
|
+
const setSection = (v) => {
|
|
134
|
+
cc[key] = v;
|
|
135
|
+
};
|
|
105
136
|
const obj = {
|
|
106
137
|
value: null,
|
|
107
138
|
hook,
|
|
@@ -115,46 +146,54 @@ function _getCtxHelpers(cc) {
|
|
|
115
146
|
};
|
|
116
147
|
attachHook(obj, {
|
|
117
148
|
set: (v) => {
|
|
118
|
-
|
|
149
|
+
setSection(v);
|
|
119
150
|
},
|
|
120
|
-
get: () =>
|
|
151
|
+
get: () => getSection()
|
|
121
152
|
});
|
|
122
153
|
function init(key2, getter) {
|
|
123
154
|
if (hasNested(key2)) return getNested(key2);
|
|
124
155
|
return setNested(key2, getter());
|
|
125
156
|
}
|
|
126
157
|
function hook(key2) {
|
|
127
|
-
const
|
|
158
|
+
const hookObj = {
|
|
128
159
|
value: null,
|
|
129
160
|
isDefined: null
|
|
130
161
|
};
|
|
131
|
-
attachHook(
|
|
162
|
+
attachHook(hookObj, {
|
|
132
163
|
set: (v) => setNested(key2, v),
|
|
133
164
|
get: () => getNested(key2)
|
|
134
165
|
});
|
|
135
|
-
attachHook(
|
|
136
|
-
return
|
|
166
|
+
attachHook(hookObj, { get: () => hasNested(key2) }, "isDefined");
|
|
167
|
+
return hookObj;
|
|
137
168
|
}
|
|
138
169
|
function setNested(key2, v) {
|
|
139
|
-
|
|
140
|
-
|
|
170
|
+
let section = getSection();
|
|
171
|
+
if (section === void 0) {
|
|
172
|
+
section = {};
|
|
173
|
+
setSection(section);
|
|
174
|
+
}
|
|
175
|
+
section[key2] = v;
|
|
141
176
|
return v;
|
|
142
177
|
}
|
|
143
178
|
function delNested(key2) {
|
|
144
179
|
setNested(key2, void 0);
|
|
145
180
|
}
|
|
146
181
|
function getNested(key2) {
|
|
147
|
-
|
|
182
|
+
const section = getSection();
|
|
183
|
+
return section !== void 0 ? section[key2] : void 0;
|
|
148
184
|
}
|
|
149
185
|
function hasNested(key2) {
|
|
150
|
-
|
|
186
|
+
const section = getSection();
|
|
187
|
+
return section !== void 0 ? section[key2] !== void 0 : false;
|
|
151
188
|
}
|
|
152
189
|
function entries() {
|
|
153
|
-
|
|
190
|
+
const section = getSection();
|
|
191
|
+
return section ? Object.entries(section) : [];
|
|
154
192
|
}
|
|
155
193
|
function clear() {
|
|
156
|
-
|
|
194
|
+
setSection({});
|
|
157
195
|
}
|
|
196
|
+
_storeCache.set(key, obj);
|
|
158
197
|
return obj;
|
|
159
198
|
}
|
|
160
199
|
/**
|
|
@@ -165,26 +204,14 @@ function _getCtxHelpers(cc) {
|
|
|
165
204
|
function getCtx() {
|
|
166
205
|
return cc;
|
|
167
206
|
}
|
|
168
|
-
/**
|
|
169
|
-
* Get value of event store property
|
|
170
|
-
*
|
|
171
|
-
* @param key property name
|
|
172
|
-
* @returns value of property by name
|
|
173
|
-
*/
|
|
174
207
|
function get(key) {
|
|
175
|
-
return
|
|
208
|
+
return cc[key];
|
|
176
209
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Set value of event store property
|
|
179
|
-
*
|
|
180
|
-
* @param key property name
|
|
181
|
-
* @param v property value
|
|
182
|
-
*/
|
|
183
210
|
function set(key, v) {
|
|
184
|
-
|
|
211
|
+
cc[key] = v;
|
|
185
212
|
}
|
|
186
213
|
const hasParentCtx = () => !!cc.parentCtx;
|
|
187
|
-
|
|
214
|
+
const helpers = {
|
|
188
215
|
getCtx,
|
|
189
216
|
store,
|
|
190
217
|
getStore: get,
|
|
@@ -198,10 +225,20 @@ function _getCtxHelpers(cc) {
|
|
|
198
225
|
return _getCtxHelpers(cc.parentCtx);
|
|
199
226
|
}
|
|
200
227
|
};
|
|
228
|
+
return helpers;
|
|
201
229
|
}
|
|
202
230
|
|
|
203
231
|
//#endregion
|
|
204
232
|
//#region packages/event-core/src/composables/event-id.ts
|
|
233
|
+
/**
|
|
234
|
+
* Composable that provides a unique event ID for the current event context.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* const { getId } = useEventId()
|
|
239
|
+
* console.log(getId()) // '550e8400-e29b-41d4-a716-446655440000'
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
205
242
|
function useEventId() {
|
|
206
243
|
const { store } = useAsyncEventContext();
|
|
207
244
|
const { init } = store("event");
|
|
@@ -211,6 +248,7 @@ function useEventId() {
|
|
|
211
248
|
|
|
212
249
|
//#endregion
|
|
213
250
|
//#region packages/event-core/src/event-logger.ts
|
|
251
|
+
/** Logger scoped to a single event, automatically tagging messages with the event ID. */
|
|
214
252
|
var EventLogger = class extends __prostojs_logger.ProstoLogger {
|
|
215
253
|
constructor(eventId, opts) {
|
|
216
254
|
const _opts = opts || { level: 4 };
|
|
@@ -225,6 +263,16 @@ var EventLogger = class extends __prostojs_logger.ProstoLogger {
|
|
|
225
263
|
|
|
226
264
|
//#endregion
|
|
227
265
|
//#region packages/event-core/src/composables/event-logger.ts
|
|
266
|
+
/**
|
|
267
|
+
* Composable that provides a logger scoped to the current event context.
|
|
268
|
+
*
|
|
269
|
+
* @param topic - Optional topic name to create a sub-logger for.
|
|
270
|
+
* @example
|
|
271
|
+
* ```ts
|
|
272
|
+
* const logger = useEventLogger('my-handler')
|
|
273
|
+
* logger.log('processing request')
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
228
276
|
function useEventLogger(topic) {
|
|
229
277
|
const { getId } = useEventId();
|
|
230
278
|
const { store, getCtx } = useAsyncEventContext();
|
|
@@ -236,6 +284,16 @@ function useEventLogger(topic) {
|
|
|
236
284
|
|
|
237
285
|
//#endregion
|
|
238
286
|
//#region packages/event-core/src/composables/route-params.ts
|
|
287
|
+
/**
|
|
288
|
+
* Composable that provides access to route parameters from the current event context.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* const { get, params } = useRouteParams<{ id: string }>()
|
|
293
|
+
* console.log(get('id')) // '123'
|
|
294
|
+
* console.log(params) // { id: '123' }
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
239
297
|
function useRouteParams() {
|
|
240
298
|
const { store } = useAsyncEventContext();
|
|
241
299
|
const params = store("routeParams").value || {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,37 +1,71 @@
|
|
|
1
1
|
import { TConsoleBase, ProstoLogger, TProstoLoggerOptions } from '@prostojs/logger';
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Composable that provides a unique event ID for the current event context.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const { getId } = useEventId()
|
|
10
|
+
* console.log(getId()) // '550e8400-e29b-41d4-a716-446655440000'
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
4
13
|
declare function useEventId(): {
|
|
5
14
|
getId: () => string;
|
|
6
15
|
};
|
|
7
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Composable that provides a logger scoped to the current event context.
|
|
19
|
+
*
|
|
20
|
+
* @param topic - Optional topic name to create a sub-logger for.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const logger = useEventLogger('my-handler')
|
|
24
|
+
* logger.log('processing request')
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
8
27
|
declare function useEventLogger(topic?: string): TConsoleBase;
|
|
9
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Composable that provides access to route parameters from the current event context.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const { get, params } = useRouteParams<{ id: string }>()
|
|
35
|
+
* console.log(get('id')) // '123'
|
|
36
|
+
* console.log(params) // { id: '123' }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
10
39
|
declare function useRouteParams<T extends object = Record<string, string | string[]>>(): {
|
|
11
40
|
params: T;
|
|
12
41
|
get: <K extends keyof T>(name: K) => T[K];
|
|
13
42
|
};
|
|
14
43
|
|
|
44
|
+
/** Data shape passed through logger transports, carrying the event ID. */
|
|
15
45
|
interface TEventLoggerData {
|
|
16
46
|
eventId: string;
|
|
17
47
|
}
|
|
48
|
+
/** Logger scoped to a single event, automatically tagging messages with the event ID. */
|
|
18
49
|
declare class EventLogger extends ProstoLogger<TEventLoggerData> {
|
|
19
50
|
constructor(eventId: string, opts?: TEventOptions['eventLogger']);
|
|
20
51
|
}
|
|
21
52
|
|
|
53
|
+
/** Base event shape shared by all event types. */
|
|
22
54
|
interface TGenericEvent {
|
|
23
55
|
type: string;
|
|
24
56
|
logger?: EventLogger;
|
|
25
57
|
id?: string;
|
|
26
58
|
}
|
|
27
|
-
|
|
28
|
-
|
|
59
|
+
/** Empty record type used as a default generic parameter. */
|
|
60
|
+
type TEmpty = Record<string, never>;
|
|
29
61
|
|
|
62
|
+
/** Configuration options for event context creation. */
|
|
30
63
|
interface TEventOptions {
|
|
31
64
|
eventLogger?: {
|
|
32
65
|
topic?: string;
|
|
33
66
|
} & TProstoLoggerOptions<TEventLoggerData>;
|
|
34
67
|
}
|
|
68
|
+
/** Shape of the context store that holds event data, options, and route params. */
|
|
35
69
|
interface TGenericContextStore<CustomEventType = TEmpty> {
|
|
36
70
|
event: CustomEventType & TGenericEvent;
|
|
37
71
|
options: TEventOptions;
|
|
@@ -46,13 +80,20 @@ interface TGenericContextStore<CustomEventType = TEmpty> {
|
|
|
46
80
|
*/
|
|
47
81
|
declare const asyncStorage: AsyncLocalStorage<TGenericContextStore>;
|
|
48
82
|
/**
|
|
49
|
-
*
|
|
83
|
+
* Creates a new async event context and returns a runner function to execute callbacks within it.
|
|
84
|
+
*
|
|
85
|
+
* @param data - Initial context store data including the event object and options.
|
|
86
|
+
* @returns A function that runs a callback within the created async context.
|
|
50
87
|
*/
|
|
51
88
|
declare function createAsyncEventContext<S = TEmpty, EventTypeToCreate = TEmpty>(data: S & TGenericContextStore<EventTypeToCreate>): <T>(cb: (...a: any[]) => T) => T;
|
|
52
89
|
/**
|
|
53
|
-
*
|
|
90
|
+
* Retrieves the current async event context and returns helpers for reading/writing the store.
|
|
91
|
+
*
|
|
92
|
+
* @param expectedTypes - Optional event type(s) to validate the context against.
|
|
93
|
+
* @throws If no event context exists or if the event type does not match.
|
|
54
94
|
*/
|
|
55
95
|
declare function useAsyncEventContext<S = TEmpty, EventType = TEmpty>(expectedTypes?: string | string[]): TCtxHelpers<S & TGenericContextStore<EventType>>;
|
|
96
|
+
/** Helper methods returned by `useAsyncEventContext` for interacting with the context store. */
|
|
56
97
|
interface TCtxHelpers<T> {
|
|
57
98
|
getCtx: () => T;
|
|
58
99
|
store: <K extends keyof Required<T>>(key: K) => {
|
|
@@ -85,19 +126,28 @@ interface TCtxHelpers<T> {
|
|
|
85
126
|
declare class ContextInjector<N> {
|
|
86
127
|
with<T>(name: N, attributes: Record<string, string | number | boolean>, cb: TContextInjectorCallback<T>): T;
|
|
87
128
|
with<T>(name: N, cb: TContextInjectorCallback<T>): T;
|
|
88
|
-
hook(
|
|
129
|
+
hook(_method: string, _name: 'Handler:not_found' | 'Handler:routed', _route?: string): void;
|
|
89
130
|
}
|
|
90
131
|
type TContextInjectorCallback<T> = () => T;
|
|
132
|
+
/** Returns the current global `ContextInjector` instance. */
|
|
91
133
|
declare function getContextInjector<N = TContextInjectorHooks>(): ContextInjector<N>;
|
|
134
|
+
/** Replaces the global `ContextInjector` instance (e.g., to integrate with OpenTelemetry). */
|
|
92
135
|
declare function replaceContextInjector(newCi: ContextInjector<string>): void;
|
|
93
136
|
type TContextInjectorHooks = 'Event:start';
|
|
94
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Attaches a getter/setter hook to a target object property via `Object.defineProperty`.
|
|
140
|
+
*
|
|
141
|
+
* @param target - The object to attach the hook to.
|
|
142
|
+
* @param opts - Getter and optional setter for the hooked property.
|
|
143
|
+
* @param name - Property name to hook (defaults to `'value'`).
|
|
144
|
+
*/
|
|
95
145
|
declare function attachHook<V = unknown, T extends object | Function = object, P extends PropertyKey = 'value'>(target: T, opts: {
|
|
96
146
|
get: () => V | undefined;
|
|
97
147
|
set?: (value: V) => void;
|
|
98
148
|
}, name?: P): T & THook<V, P>;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
};
|
|
149
|
+
/** A record type representing a hooked property on an object. */
|
|
150
|
+
type THook<T = string, K extends PropertyKey = 'value'> = Record<K, T>;
|
|
102
151
|
|
|
103
|
-
export { ContextInjector, EventLogger,
|
|
152
|
+
export { ContextInjector, EventLogger, asyncStorage, attachHook, createAsyncEventContext, getContextInjector, replaceContextInjector, useAsyncEventContext, useEventId, useEventLogger, useRouteParams };
|
|
153
|
+
export type { TContextInjectorHooks, TCtxHelpers, TEmpty, TEventLoggerData, TEventOptions, TGenericContextStore, TGenericEvent, THook };
|
package/dist/index.mjs
CHANGED
|
@@ -14,18 +14,27 @@ var ContextInjector = class {
|
|
|
14
14
|
const fn = typeof attributes === "function" ? attributes : cb;
|
|
15
15
|
return fn();
|
|
16
16
|
}
|
|
17
|
-
hook(
|
|
17
|
+
hook(_method, _name, _route) {}
|
|
18
18
|
};
|
|
19
19
|
let ci = new ContextInjector();
|
|
20
|
+
/** Returns the current global `ContextInjector` instance. */
|
|
20
21
|
function getContextInjector() {
|
|
21
22
|
return ci;
|
|
22
23
|
}
|
|
24
|
+
/** Replaces the global `ContextInjector` instance (e.g., to integrate with OpenTelemetry). */
|
|
23
25
|
function replaceContextInjector(newCi) {
|
|
24
26
|
ci = newCi;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
//#endregion
|
|
28
30
|
//#region packages/event-core/src/hook.ts
|
|
31
|
+
/**
|
|
32
|
+
* Attaches a getter/setter hook to a target object property via `Object.defineProperty`.
|
|
33
|
+
*
|
|
34
|
+
* @param target - The object to attach the hook to.
|
|
35
|
+
* @param opts - Getter and optional setter for the hooked property.
|
|
36
|
+
* @param name - Property name to hook (defaults to `'value'`).
|
|
37
|
+
*/
|
|
29
38
|
function attachHook(target, opts, name) {
|
|
30
39
|
Object.defineProperty(target, name || "value", {
|
|
31
40
|
get: opts.get,
|
|
@@ -36,14 +45,29 @@ function attachHook(target, opts, name) {
|
|
|
36
45
|
|
|
37
46
|
//#endregion
|
|
38
47
|
//#region packages/event-core/src/context.ts
|
|
48
|
+
const STORAGE_KEY = Symbol.for("wooks.asyncStorage");
|
|
49
|
+
const VERSION_KEY = Symbol.for("wooks.asyncStorage.version");
|
|
50
|
+
const CURRENT_VERSION = "0.6.2";
|
|
51
|
+
const _g = globalThis;
|
|
52
|
+
if (_g[STORAGE_KEY]) {
|
|
53
|
+
if (_g[VERSION_KEY] !== CURRENT_VERSION) console.warn(`[33m[wooks] Multiple versions of @wooksjs/event-core detected: existing v${_g[VERSION_KEY]}, current v${CURRENT_VERSION}. Reusing existing asyncStorage to avoid runtime errors.[0m`);
|
|
54
|
+
} else {
|
|
55
|
+
_g[STORAGE_KEY] = new AsyncLocalStorage();
|
|
56
|
+
_g[VERSION_KEY] = CURRENT_VERSION;
|
|
57
|
+
}
|
|
39
58
|
/**
|
|
40
59
|
* AsyncLocalStorage instance
|
|
41
60
|
*
|
|
42
61
|
* Use on your own risk only if you know what you're doing
|
|
43
62
|
*/
|
|
44
|
-
const asyncStorage =
|
|
63
|
+
const asyncStorage = _g[STORAGE_KEY];
|
|
64
|
+
/** Symbol key for caching store accessors directly on the context object */
|
|
65
|
+
const _storeCacheKey = Symbol("storeCache");
|
|
45
66
|
/**
|
|
46
|
-
*
|
|
67
|
+
* Creates a new async event context and returns a runner function to execute callbacks within it.
|
|
68
|
+
*
|
|
69
|
+
* @param data - Initial context store data including the event object and options.
|
|
70
|
+
* @returns A function that runs a callback within the created async context.
|
|
47
71
|
*/
|
|
48
72
|
function createAsyncEventContext(data) {
|
|
49
73
|
const newContext = { ...data };
|
|
@@ -53,7 +77,10 @@ function createAsyncEventContext(data) {
|
|
|
53
77
|
return (cb) => asyncStorage.run(newContext, () => ci$1.with("Event:start", { eventType: newContext.event.type }, cb));
|
|
54
78
|
}
|
|
55
79
|
/**
|
|
56
|
-
*
|
|
80
|
+
* Retrieves the current async event context and returns helpers for reading/writing the store.
|
|
81
|
+
*
|
|
82
|
+
* @param expectedTypes - Optional event type(s) to validate the context against.
|
|
83
|
+
* @throws If no event context exists or if the event type does not match.
|
|
57
84
|
*/
|
|
58
85
|
function useAsyncEventContext(expectedTypes) {
|
|
59
86
|
let cc = asyncStorage.getStore();
|
|
@@ -66,12 +93,10 @@ function useAsyncEventContext(expectedTypes) {
|
|
|
66
93
|
}
|
|
67
94
|
return _getCtxHelpers(cc);
|
|
68
95
|
}
|
|
69
|
-
/**
|
|
70
|
-
*
|
|
71
|
-
* @param cc
|
|
72
|
-
* @returns
|
|
73
|
-
*/
|
|
74
96
|
function _getCtxHelpers(cc) {
|
|
97
|
+
const ccAny = cc;
|
|
98
|
+
if (!ccAny[_storeCacheKey]) ccAny[_storeCacheKey] = /* @__PURE__ */ new Map();
|
|
99
|
+
const _storeCache = ccAny[_storeCacheKey];
|
|
75
100
|
/**
|
|
76
101
|
* Hook to an event store property
|
|
77
102
|
*
|
|
@@ -79,6 +104,12 @@ function _getCtxHelpers(cc) {
|
|
|
79
104
|
* @returns a hook { value: <prop value>, hook: (key2: keyof <prop value>) => { value: <nested prop value> }, ... }
|
|
80
105
|
*/
|
|
81
106
|
function store(key) {
|
|
107
|
+
const cachedStore = _storeCache.get(key);
|
|
108
|
+
if (cachedStore) return cachedStore;
|
|
109
|
+
const getSection = () => cc[key];
|
|
110
|
+
const setSection = (v) => {
|
|
111
|
+
cc[key] = v;
|
|
112
|
+
};
|
|
82
113
|
const obj = {
|
|
83
114
|
value: null,
|
|
84
115
|
hook,
|
|
@@ -92,46 +123,54 @@ function _getCtxHelpers(cc) {
|
|
|
92
123
|
};
|
|
93
124
|
attachHook(obj, {
|
|
94
125
|
set: (v) => {
|
|
95
|
-
|
|
126
|
+
setSection(v);
|
|
96
127
|
},
|
|
97
|
-
get: () =>
|
|
128
|
+
get: () => getSection()
|
|
98
129
|
});
|
|
99
130
|
function init(key2, getter) {
|
|
100
131
|
if (hasNested(key2)) return getNested(key2);
|
|
101
132
|
return setNested(key2, getter());
|
|
102
133
|
}
|
|
103
134
|
function hook(key2) {
|
|
104
|
-
const
|
|
135
|
+
const hookObj = {
|
|
105
136
|
value: null,
|
|
106
137
|
isDefined: null
|
|
107
138
|
};
|
|
108
|
-
attachHook(
|
|
139
|
+
attachHook(hookObj, {
|
|
109
140
|
set: (v) => setNested(key2, v),
|
|
110
141
|
get: () => getNested(key2)
|
|
111
142
|
});
|
|
112
|
-
attachHook(
|
|
113
|
-
return
|
|
143
|
+
attachHook(hookObj, { get: () => hasNested(key2) }, "isDefined");
|
|
144
|
+
return hookObj;
|
|
114
145
|
}
|
|
115
146
|
function setNested(key2, v) {
|
|
116
|
-
|
|
117
|
-
|
|
147
|
+
let section = getSection();
|
|
148
|
+
if (section === void 0) {
|
|
149
|
+
section = {};
|
|
150
|
+
setSection(section);
|
|
151
|
+
}
|
|
152
|
+
section[key2] = v;
|
|
118
153
|
return v;
|
|
119
154
|
}
|
|
120
155
|
function delNested(key2) {
|
|
121
156
|
setNested(key2, void 0);
|
|
122
157
|
}
|
|
123
158
|
function getNested(key2) {
|
|
124
|
-
|
|
159
|
+
const section = getSection();
|
|
160
|
+
return section !== void 0 ? section[key2] : void 0;
|
|
125
161
|
}
|
|
126
162
|
function hasNested(key2) {
|
|
127
|
-
|
|
163
|
+
const section = getSection();
|
|
164
|
+
return section !== void 0 ? section[key2] !== void 0 : false;
|
|
128
165
|
}
|
|
129
166
|
function entries() {
|
|
130
|
-
|
|
167
|
+
const section = getSection();
|
|
168
|
+
return section ? Object.entries(section) : [];
|
|
131
169
|
}
|
|
132
170
|
function clear() {
|
|
133
|
-
|
|
171
|
+
setSection({});
|
|
134
172
|
}
|
|
173
|
+
_storeCache.set(key, obj);
|
|
135
174
|
return obj;
|
|
136
175
|
}
|
|
137
176
|
/**
|
|
@@ -142,26 +181,14 @@ function _getCtxHelpers(cc) {
|
|
|
142
181
|
function getCtx() {
|
|
143
182
|
return cc;
|
|
144
183
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Get value of event store property
|
|
147
|
-
*
|
|
148
|
-
* @param key property name
|
|
149
|
-
* @returns value of property by name
|
|
150
|
-
*/
|
|
151
184
|
function get(key) {
|
|
152
|
-
return
|
|
185
|
+
return cc[key];
|
|
153
186
|
}
|
|
154
|
-
/**
|
|
155
|
-
* Set value of event store property
|
|
156
|
-
*
|
|
157
|
-
* @param key property name
|
|
158
|
-
* @param v property value
|
|
159
|
-
*/
|
|
160
187
|
function set(key, v) {
|
|
161
|
-
|
|
188
|
+
cc[key] = v;
|
|
162
189
|
}
|
|
163
190
|
const hasParentCtx = () => !!cc.parentCtx;
|
|
164
|
-
|
|
191
|
+
const helpers = {
|
|
165
192
|
getCtx,
|
|
166
193
|
store,
|
|
167
194
|
getStore: get,
|
|
@@ -175,10 +202,20 @@ function _getCtxHelpers(cc) {
|
|
|
175
202
|
return _getCtxHelpers(cc.parentCtx);
|
|
176
203
|
}
|
|
177
204
|
};
|
|
205
|
+
return helpers;
|
|
178
206
|
}
|
|
179
207
|
|
|
180
208
|
//#endregion
|
|
181
209
|
//#region packages/event-core/src/composables/event-id.ts
|
|
210
|
+
/**
|
|
211
|
+
* Composable that provides a unique event ID for the current event context.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* const { getId } = useEventId()
|
|
216
|
+
* console.log(getId()) // '550e8400-e29b-41d4-a716-446655440000'
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
182
219
|
function useEventId() {
|
|
183
220
|
const { store } = useAsyncEventContext();
|
|
184
221
|
const { init } = store("event");
|
|
@@ -188,6 +225,7 @@ function useEventId() {
|
|
|
188
225
|
|
|
189
226
|
//#endregion
|
|
190
227
|
//#region packages/event-core/src/event-logger.ts
|
|
228
|
+
/** Logger scoped to a single event, automatically tagging messages with the event ID. */
|
|
191
229
|
var EventLogger = class extends ProstoLogger {
|
|
192
230
|
constructor(eventId, opts) {
|
|
193
231
|
const _opts = opts || { level: 4 };
|
|
@@ -202,6 +240,16 @@ var EventLogger = class extends ProstoLogger {
|
|
|
202
240
|
|
|
203
241
|
//#endregion
|
|
204
242
|
//#region packages/event-core/src/composables/event-logger.ts
|
|
243
|
+
/**
|
|
244
|
+
* Composable that provides a logger scoped to the current event context.
|
|
245
|
+
*
|
|
246
|
+
* @param topic - Optional topic name to create a sub-logger for.
|
|
247
|
+
* @example
|
|
248
|
+
* ```ts
|
|
249
|
+
* const logger = useEventLogger('my-handler')
|
|
250
|
+
* logger.log('processing request')
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
205
253
|
function useEventLogger(topic) {
|
|
206
254
|
const { getId } = useEventId();
|
|
207
255
|
const { store, getCtx } = useAsyncEventContext();
|
|
@@ -213,6 +261,16 @@ function useEventLogger(topic) {
|
|
|
213
261
|
|
|
214
262
|
//#endregion
|
|
215
263
|
//#region packages/event-core/src/composables/route-params.ts
|
|
264
|
+
/**
|
|
265
|
+
* Composable that provides access to route parameters from the current event context.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* const { get, params } = useRouteParams<{ id: string }>()
|
|
270
|
+
* console.log(get('id')) // '123'
|
|
271
|
+
* console.log(params) // { id: '123' }
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
216
274
|
function useRouteParams() {
|
|
217
275
|
const { store } = useAsyncEventContext();
|
|
218
276
|
const params = store("routeParams").value || {};
|
package/package.json
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/event-core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "@wooksjs/event-core",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
"keywords": [
|
|
6
|
+
"api",
|
|
7
|
+
"app",
|
|
8
|
+
"composables",
|
|
9
|
+
"framework",
|
|
10
|
+
"http",
|
|
11
|
+
"prostojs",
|
|
12
|
+
"rest",
|
|
13
|
+
"restful",
|
|
14
|
+
"web",
|
|
15
|
+
"wooks"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-core#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/wooksjs/wooksjs/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Artem Maltsev",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/wooksjs/wooksjs.git",
|
|
26
|
+
"directory": "packages/event-core"
|
|
27
|
+
},
|
|
8
28
|
"files": [
|
|
9
29
|
"dist"
|
|
10
30
|
],
|
|
31
|
+
"main": "dist/index.cjs",
|
|
32
|
+
"module": "dist/index.mjs",
|
|
33
|
+
"types": "dist/index.d.ts",
|
|
11
34
|
"exports": {
|
|
12
35
|
"./package.json": "./package.json",
|
|
13
36
|
".": {
|
|
@@ -16,34 +39,11 @@
|
|
|
16
39
|
"import": "./dist/index.mjs"
|
|
17
40
|
}
|
|
18
41
|
},
|
|
19
|
-
"repository": {
|
|
20
|
-
"type": "git",
|
|
21
|
-
"url": "git+https://github.com/wooksjs/wooksjs.git",
|
|
22
|
-
"directory": "packages/event-core"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"http",
|
|
26
|
-
"wooks",
|
|
27
|
-
"composables",
|
|
28
|
-
"web",
|
|
29
|
-
"framework",
|
|
30
|
-
"app",
|
|
31
|
-
"api",
|
|
32
|
-
"rest",
|
|
33
|
-
"restful",
|
|
34
|
-
"prostojs"
|
|
35
|
-
],
|
|
36
|
-
"author": "Artem Maltsev",
|
|
37
|
-
"license": "MIT",
|
|
38
|
-
"bugs": {
|
|
39
|
-
"url": "https://github.com/wooksjs/wooksjs/issues"
|
|
40
|
-
},
|
|
41
42
|
"dependencies": {
|
|
42
43
|
"@prostojs/logger": "^0.4.3"
|
|
43
44
|
},
|
|
44
|
-
"homepage": "https://github.com/wooksjs/wooksjs/tree/main/packages/event-core#readme",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"typescript": "^5.
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
47
|
"vitest": "^3.2.4"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|