@nimbus-cqrs/core 2.0.0-beta.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.
Files changed (79) hide show
  1. package/LICENSE +85 -0
  2. package/README.md +56 -0
  3. package/esm/_dnt.shims.d.ts +2 -0
  4. package/esm/_dnt.shims.d.ts.map +1 -0
  5. package/esm/_dnt.shims.js +57 -0
  6. package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.d.ts +700 -0
  7. package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.d.ts.map +1 -0
  8. package/esm/deps/jsr.io/@std/fmt/1.0.10/colors.js +903 -0
  9. package/esm/deps/jsr.io/@std/ulid/1.0.0/_util.d.ts +14 -0
  10. package/esm/deps/jsr.io/@std/ulid/1.0.0/_util.d.ts.map +1 -0
  11. package/esm/deps/jsr.io/@std/ulid/1.0.0/_util.js +65 -0
  12. package/esm/deps/jsr.io/@std/ulid/1.0.0/decode_time.d.ts +20 -0
  13. package/esm/deps/jsr.io/@std/ulid/1.0.0/decode_time.d.ts.map +1 -0
  14. package/esm/deps/jsr.io/@std/ulid/1.0.0/decode_time.js +43 -0
  15. package/esm/deps/jsr.io/@std/ulid/1.0.0/mod.d.ts +44 -0
  16. package/esm/deps/jsr.io/@std/ulid/1.0.0/mod.d.ts.map +1 -0
  17. package/esm/deps/jsr.io/@std/ulid/1.0.0/mod.js +47 -0
  18. package/esm/deps/jsr.io/@std/ulid/1.0.0/monotonic_ulid.d.ts +44 -0
  19. package/esm/deps/jsr.io/@std/ulid/1.0.0/monotonic_ulid.d.ts.map +1 -0
  20. package/esm/deps/jsr.io/@std/ulid/1.0.0/monotonic_ulid.js +51 -0
  21. package/esm/deps/jsr.io/@std/ulid/1.0.0/ulid.d.ts +31 -0
  22. package/esm/deps/jsr.io/@std/ulid/1.0.0/ulid.d.ts.map +1 -0
  23. package/esm/deps/jsr.io/@std/ulid/1.0.0/ulid.js +37 -0
  24. package/esm/index.d.ts +18 -0
  25. package/esm/index.d.ts.map +1 -0
  26. package/esm/index.js +17 -0
  27. package/esm/lib/eventBus/eventBus.d.ts +329 -0
  28. package/esm/lib/eventBus/eventBus.d.ts.map +1 -0
  29. package/esm/lib/eventBus/eventBus.js +473 -0
  30. package/esm/lib/exception/exception.d.ts +10 -0
  31. package/esm/lib/exception/exception.d.ts.map +1 -0
  32. package/esm/lib/exception/exception.js +26 -0
  33. package/esm/lib/exception/forbiddenException.d.ts +8 -0
  34. package/esm/lib/exception/forbiddenException.d.ts.map +1 -0
  35. package/esm/lib/exception/forbiddenException.js +9 -0
  36. package/esm/lib/exception/genericException.d.ts +8 -0
  37. package/esm/lib/exception/genericException.d.ts.map +1 -0
  38. package/esm/lib/exception/genericException.js +9 -0
  39. package/esm/lib/exception/invalidInputException.d.ts +18 -0
  40. package/esm/lib/exception/invalidInputException.d.ts.map +1 -0
  41. package/esm/lib/exception/invalidInputException.js +28 -0
  42. package/esm/lib/exception/notFoundException.d.ts +8 -0
  43. package/esm/lib/exception/notFoundException.d.ts.map +1 -0
  44. package/esm/lib/exception/notFoundException.js +9 -0
  45. package/esm/lib/exception/unauthorizedException.d.ts +8 -0
  46. package/esm/lib/exception/unauthorizedException.d.ts.map +1 -0
  47. package/esm/lib/exception/unauthorizedException.js +9 -0
  48. package/esm/lib/log/logFormatter.d.ts +26 -0
  49. package/esm/lib/log/logFormatter.d.ts.map +1 -0
  50. package/esm/lib/log/logFormatter.js +59 -0
  51. package/esm/lib/log/logLevel.d.ts +24 -0
  52. package/esm/lib/log/logLevel.d.ts.map +1 -0
  53. package/esm/lib/log/logLevel.js +27 -0
  54. package/esm/lib/log/logger.d.ts +377 -0
  55. package/esm/lib/log/logger.d.ts.map +1 -0
  56. package/esm/lib/log/logger.js +394 -0
  57. package/esm/lib/log/options.d.ts +34 -0
  58. package/esm/lib/log/options.d.ts.map +1 -0
  59. package/esm/lib/log/options.js +9 -0
  60. package/esm/lib/message/command.d.ts +100 -0
  61. package/esm/lib/message/command.d.ts.map +1 -0
  62. package/esm/lib/message/command.js +47 -0
  63. package/esm/lib/message/event.d.ts +103 -0
  64. package/esm/lib/message/event.d.ts.map +1 -0
  65. package/esm/lib/message/event.js +47 -0
  66. package/esm/lib/message/message.d.ts +18 -0
  67. package/esm/lib/message/message.d.ts.map +1 -0
  68. package/esm/lib/message/message.js +1 -0
  69. package/esm/lib/message/query.d.ts +95 -0
  70. package/esm/lib/message/query.d.ts.map +1 -0
  71. package/esm/lib/message/query.js +45 -0
  72. package/esm/lib/message/router.d.ts +233 -0
  73. package/esm/lib/message/router.d.ts.map +1 -0
  74. package/esm/lib/message/router.js +304 -0
  75. package/esm/lib/tracing/withSpan.d.ts +67 -0
  76. package/esm/lib/tracing/withSpan.d.ts.map +1 -0
  77. package/esm/lib/tracing/withSpan.js +87 -0
  78. package/esm/package.json +3 -0
  79. package/package.json +33 -0
@@ -0,0 +1,304 @@
1
+ import { metrics, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';
2
+ import { InvalidInputException } from '../exception/invalidInputException.js';
3
+ import { NotFoundException } from '../exception/notFoundException.js';
4
+ import { getLogger } from '../log/logger.js';
5
+ const tracer = trace.getTracer('nimbus');
6
+ const meter = metrics.getMeter('nimbus');
7
+ const messagesRoutedCounter = meter.createCounter('router_messages_routed_total', {
8
+ description: 'Total number of messages routed',
9
+ });
10
+ const routingDuration = meter.createHistogram('router_routing_duration_seconds', {
11
+ description: 'Duration of message routing in seconds',
12
+ unit: 's',
13
+ });
14
+ /**
15
+ * The MessageRouter routes messages to their handlers based on the type value of the message.
16
+ *
17
+ * Messages are validated against their registered Zod schemas before being passed to handlers.
18
+ * All routing operations are instrumented with OpenTelemetry tracing and metrics for observability.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { createCommand, MessageRouter } from '@nimbus/core';
23
+ *
24
+ * const messageRouter = new MessageRouter({
25
+ * name: 'api',
26
+ * logInput: (input) => {
27
+ * console.log('Received message:', input.type);
28
+ * },
29
+ * logOutput: (output) => {
30
+ * console.log('Handler result:', output);
31
+ * },
32
+ * });
33
+ *
34
+ * // Register command handler
35
+ * messageRouter.register(
36
+ * 'at.overlap.nimbus.create-order',
37
+ * createOrderHandler,
38
+ * createOrderCommandSchema,
39
+ * );
40
+ *
41
+ * // Register query handler
42
+ * messageRouter.register(
43
+ * 'at.overlap.nimbus.get-order',
44
+ * getOrderHandler,
45
+ * getOrderQuerySchema,
46
+ * );
47
+ *
48
+ * // Route a command
49
+ * const command = createCommand({
50
+ * type: 'at.overlap.nimbus.create-order',
51
+ * source: 'https://api.example.com',
52
+ * data: { customerId: '123', items: ['item-1', 'item-2'] },
53
+ * });
54
+ *
55
+ * const result = await messageRouter.route(command);
56
+ * ```
57
+ */
58
+ export class MessageRouter {
59
+ _handlers;
60
+ _name;
61
+ _logInput;
62
+ _logOutput;
63
+ constructor(options) {
64
+ this._handlers = new Map();
65
+ this._name = options?.name ?? 'default';
66
+ this._logInput = options?.logInput;
67
+ this._logOutput = options?.logOutput;
68
+ }
69
+ /**
70
+ * Register a handler for a specific message type.
71
+ *
72
+ * @param messageType - The message type as defined in the CloudEvents specification
73
+ * (e.g., 'at.overlap.nimbus.create-order').
74
+ * @param handler - The async handler function that processes the message and returns a result.
75
+ * @param schema - The Zod schema to validate the incoming message before passing to the handler.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * import { commandSchema, type Command, getRouter } from '@nimbus/core';
80
+ * import { z } from 'zod';
81
+ *
82
+ * // Define the command type and schema
83
+ * const CREATE_ORDER_TYPE = 'at.overlap.nimbus.create-order';
84
+ *
85
+ * const createOrderSchema = commandSchema.extend({
86
+ * type: z.literal(CREATE_ORDER_TYPE),
87
+ * data: z.object({
88
+ * customerId: z.string(),
89
+ * items: z.array(z.string()),
90
+ * }),
91
+ * });
92
+ * type CreateOrderCommand = z.infer<typeof createOrderSchema>;
93
+ *
94
+ * // Define the handler
95
+ * const createOrderHandler = async (command: CreateOrderCommand) => {
96
+ * // Process the command and return the result
97
+ * return { orderId: '12345', status: 'created' };
98
+ * };
99
+ *
100
+ * // Register the handler
101
+ * const router = getRouter('default');
102
+ * router.register(CREATE_ORDER_TYPE, createOrderHandler, createOrderSchema);
103
+ * ```
104
+ */
105
+ register(messageType, handler, schema) {
106
+ this._handlers.set(messageType, {
107
+ handler,
108
+ schema,
109
+ });
110
+ getLogger().debug({
111
+ category: 'Nimbus',
112
+ message: `Registered handler for: ${messageType}`,
113
+ });
114
+ }
115
+ /**
116
+ * Route a message to its handler.
117
+ *
118
+ * The message is validated against the registered schema before being passed to the handler.
119
+ * The routing operation is instrumented with OpenTelemetry tracing and metrics.
120
+ *
121
+ * @param input - The CloudEvents-compliant message to route (command, query, or event).
122
+ * @returns The result from the handler.
123
+ *
124
+ * @throws {NotFoundException} If no handler is registered for the message type.
125
+ * @throws {InvalidInputException} If the message has no type attribute or fails schema validation.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * import { createCommand, getRouter } from '@nimbus/core';
130
+ *
131
+ * const router = getRouter('default');
132
+ *
133
+ * // Create a command with all CloudEvents properties
134
+ * const command = createCommand({
135
+ * type: 'at.overlap.nimbus.create-order',
136
+ * source: 'https://api.example.com',
137
+ * correlationid: '550e8400-e29b-41d4-a716-446655440000',
138
+ * data: {
139
+ * customerId: '123',
140
+ * items: ['item-1', 'item-2'],
141
+ * },
142
+ * datacontenttype: 'application/json',
143
+ * });
144
+ *
145
+ * // Route the command to its registered handler
146
+ * const result = await router.route(command);
147
+ * console.log('Order created:', result);
148
+ * ```
149
+ */
150
+ async route(input) {
151
+ const startTime = performance.now();
152
+ const messageType = input?.type ?? 'unknown';
153
+ return await tracer.startActiveSpan('router.route', {
154
+ kind: SpanKind.INTERNAL,
155
+ attributes: {
156
+ 'messaging.system': 'nimbusRouter',
157
+ 'messaging.router_name': this._name,
158
+ 'messaging.operation': 'route',
159
+ 'messaging.destination': messageType,
160
+ ...(input?.correlationid && {
161
+ correlation_id: input.correlationid,
162
+ }),
163
+ },
164
+ }, async (span) => {
165
+ try {
166
+ if (this._logInput) {
167
+ this._logInput(input);
168
+ }
169
+ if (!input?.type) {
170
+ throw new InvalidInputException('The provided input has no type attribute');
171
+ }
172
+ const registration = this._handlers.get(input.type);
173
+ if (!registration) {
174
+ throw new NotFoundException('Message handler not found', {
175
+ reason: `Could not find a handler for message type: "${input.type}"`,
176
+ });
177
+ }
178
+ const { handler, schema } = registration;
179
+ const validationResult = schema.safeParse(input);
180
+ if (!validationResult.success) {
181
+ throw new InvalidInputException('The provided input is invalid').fromZodError(validationResult.error);
182
+ }
183
+ const result = await handler(validationResult.data);
184
+ if (this._logOutput) {
185
+ this._logOutput(result);
186
+ }
187
+ messagesRoutedCounter.add(1, {
188
+ router_name: this._name,
189
+ message_type: input.type,
190
+ status: 'success',
191
+ });
192
+ routingDuration.record((performance.now() - startTime) / 1000, { router_name: this._name, message_type: input.type });
193
+ return result;
194
+ }
195
+ catch (error) {
196
+ messagesRoutedCounter.add(1, {
197
+ router_name: this._name,
198
+ message_type: messageType,
199
+ status: 'error',
200
+ });
201
+ routingDuration.record((performance.now() - startTime) / 1000, { router_name: this._name, message_type: messageType });
202
+ span.setStatus({
203
+ code: SpanStatusCode.ERROR,
204
+ message: error instanceof Error
205
+ ? error.message
206
+ : 'Unknown error',
207
+ });
208
+ span.recordException(error instanceof Error
209
+ ? error
210
+ : new Error('Unknown error'));
211
+ throw error;
212
+ }
213
+ finally {
214
+ span.end();
215
+ }
216
+ });
217
+ }
218
+ }
219
+ /**
220
+ * Registry to store named MessageRouter instances.
221
+ */
222
+ const routerRegistry = new Map();
223
+ /**
224
+ * Setup a named MessageRouter instance and register it for later retrieval.
225
+ *
226
+ * Use this function to configure a MessageRouter with specific options at application
227
+ * startup, then retrieve it later using {@link getRouter}.
228
+ *
229
+ * @param name - The unique name for this MessageRouter instance.
230
+ * @param options - Optional configuration options for the MessageRouter.
231
+ * @param options.logInput - Optional callback invoked when a message is received for routing.
232
+ * @param options.logOutput - Optional callback invoked after a message has been successfully handled.
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * import { getLogger, setupRouter } from '@nimbus/core';
237
+ *
238
+ * // At application startup, configure the router with all options
239
+ * setupRouter('default', {
240
+ * logInput: (input) => {
241
+ * getLogger().debug({
242
+ * category: 'Router',
243
+ * message: 'Received message',
244
+ * data: { type: input.type, correlationId: input.correlationid },
245
+ * correlationId: input.correlationid,
246
+ * });
247
+ * },
248
+ * logOutput: (output) => {
249
+ * getLogger().debug({
250
+ * category: 'Router',
251
+ * message: 'Handler completed',
252
+ * data: { output },
253
+ * });
254
+ * },
255
+ * });
256
+ * ```
257
+ */
258
+ export const setupRouter = (name, options) => {
259
+ routerRegistry.set(name, new MessageRouter({ ...options, name }));
260
+ };
261
+ /**
262
+ * Get a named MessageRouter instance.
263
+ *
264
+ * If a MessageRouter with the given name has been configured via {@link setupRouter},
265
+ * that instance is returned. Otherwise, a new MessageRouter with default options is created
266
+ * and registered.
267
+ *
268
+ * @param name - The name of the MessageRouter instance to retrieve. Defaults to 'default'.
269
+ * @returns The MessageRouter instance.
270
+ *
271
+ * @example
272
+ * ```ts
273
+ * import { createCommand, getRouter } from '@nimbus/core';
274
+ *
275
+ * // Get the router configured earlier with setupRouter
276
+ * const router = getRouter('default');
277
+ *
278
+ * // Register handlers
279
+ * router.register(
280
+ * 'at.overlap.nimbus.create-order',
281
+ * createOrderHandler,
282
+ * createOrderSchema,
283
+ * );
284
+ *
285
+ * // Route a message
286
+ * const command = createCommand({
287
+ * type: 'at.overlap.nimbus.create-order',
288
+ * source: 'https://api.example.com',
289
+ * correlationid: '550e8400-e29b-41d4-a716-446655440000',
290
+ * data: { customerId: '123', items: ['item-1'] },
291
+ * datacontenttype: 'application/json',
292
+ * });
293
+ *
294
+ * const result = await router.route(command);
295
+ * ```
296
+ */
297
+ export const getRouter = (name = 'default') => {
298
+ let router = routerRegistry.get(name);
299
+ if (!router) {
300
+ router = new MessageRouter({ name });
301
+ routerRegistry.set(name, router);
302
+ }
303
+ return router;
304
+ };
@@ -0,0 +1,67 @@
1
+ import { type Attributes, type Span, SpanKind } from '@opentelemetry/api';
2
+ /**
3
+ * Options for configuring a span created by withSpan.
4
+ */
5
+ export type WithSpanOptions = {
6
+ /**
7
+ * The name of the span. This will be displayed in your tracing UI.
8
+ */
9
+ name: string;
10
+ /**
11
+ * The name of the tracer. Defaults to "nimbus".
12
+ */
13
+ tracerName?: string;
14
+ /**
15
+ * The kind of span. Defaults to SpanKind.INTERNAL.
16
+ */
17
+ kind?: SpanKind;
18
+ /**
19
+ * Initial attributes to set on the span.
20
+ */
21
+ attributes?: Attributes;
22
+ };
23
+ /**
24
+ * Higher-order function that wraps a function with OpenTelemetry tracing.
25
+ *
26
+ * Creates a child span within the current trace context. The span automatically:
27
+ * - Inherits the parent span from the active context
28
+ * - Records the function's execution time
29
+ * - Sets error status and records exceptions on failure
30
+ * - Ends when the function completes (success or failure)
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { withSpan } from '@nimbus/core';
35
+ *
36
+ * const fetchUser = withSpan(
37
+ * {
38
+ * name: 'fetchUser',
39
+ * attributes: {
40
+ * 'user.source': 'database'
41
+ * }
42
+ * },
43
+ * async (userId: string) => {
44
+ * return await db.users.findById(userId);
45
+ * }
46
+ * );
47
+ *
48
+ * const user = await fetchUser('123');
49
+ * ```
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const processOrder = withSpan(
54
+ * { name: 'processOrder' },
55
+ * async (orderId: string, span: Span) => {
56
+ * const order = await db.orders.findById(orderId);
57
+ *
58
+ * span.setAttribute('order.total', order.total);
59
+ * span.setAttribute('order.items', order.items.length);
60
+ *
61
+ * return await processPayment(order);
62
+ * }
63
+ * );
64
+ * ```
65
+ */
66
+ export declare const withSpan: <TArgs extends unknown[], TReturn>(options: WithSpanOptions, fn: (...args: [...TArgs, Span]) => TReturn) => (...args: TArgs) => TReturn;
67
+ //# sourceMappingURL=withSpan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withSpan.d.ts","sourceRoot":"","sources":["../../../src/lib/tracing/withSpan.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,UAAU,EAEf,KAAK,IAAI,EACT,QAAQ,EAGX,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC1B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,SAAS,OAAO,EAAE,EAAE,OAAO,EACrD,SAAS,eAAe,EACxB,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,KAAK,OAAO,KAC3C,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAkDtB,CAAC"}
@@ -0,0 +1,87 @@
1
+ import { context, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
2
+ /**
3
+ * Higher-order function that wraps a function with OpenTelemetry tracing.
4
+ *
5
+ * Creates a child span within the current trace context. The span automatically:
6
+ * - Inherits the parent span from the active context
7
+ * - Records the function's execution time
8
+ * - Sets error status and records exceptions on failure
9
+ * - Ends when the function completes (success or failure)
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { withSpan } from '@nimbus/core';
14
+ *
15
+ * const fetchUser = withSpan(
16
+ * {
17
+ * name: 'fetchUser',
18
+ * attributes: {
19
+ * 'user.source': 'database'
20
+ * }
21
+ * },
22
+ * async (userId: string) => {
23
+ * return await db.users.findById(userId);
24
+ * }
25
+ * );
26
+ *
27
+ * const user = await fetchUser('123');
28
+ * ```
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const processOrder = withSpan(
33
+ * { name: 'processOrder' },
34
+ * async (orderId: string, span: Span) => {
35
+ * const order = await db.orders.findById(orderId);
36
+ *
37
+ * span.setAttribute('order.total', order.total);
38
+ * span.setAttribute('order.items', order.items.length);
39
+ *
40
+ * return await processPayment(order);
41
+ * }
42
+ * );
43
+ * ```
44
+ */
45
+ export const withSpan = (options, fn) => {
46
+ const tracerName = options.tracerName ?? 'nimbus';
47
+ const tracer = trace.getTracer(tracerName);
48
+ return (...args) => {
49
+ const parentContext = context.active();
50
+ return tracer.startActiveSpan(options.name, {
51
+ kind: options.kind ?? SpanKind.INTERNAL,
52
+ attributes: options.attributes,
53
+ }, parentContext, (span) => {
54
+ try {
55
+ const result = fn(...args, span);
56
+ // Handle promises
57
+ if (result instanceof Promise) {
58
+ return result
59
+ .then((value) => {
60
+ span.end();
61
+ return value;
62
+ })
63
+ .catch((err) => {
64
+ span.setStatus({
65
+ code: SpanStatusCode.ERROR,
66
+ message: err.message,
67
+ });
68
+ span.recordException(err);
69
+ span.end();
70
+ throw err;
71
+ });
72
+ }
73
+ span.end();
74
+ return result;
75
+ }
76
+ catch (err) {
77
+ span.setStatus({
78
+ code: SpanStatusCode.ERROR,
79
+ message: err.message,
80
+ });
81
+ span.recordException(err);
82
+ span.end();
83
+ throw err;
84
+ }
85
+ });
86
+ };
87
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@nimbus-cqrs/core",
3
+ "version": "2.0.0-beta.0",
4
+ "description": "Core building blocks of the Nimbus CQRS framework.",
5
+ "author": "Daniel Gördes <d.goerdes@overlap.at> (https://overlap.at)",
6
+ "homepage": "https://nimbus.overlap.at",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/overlap-dev/Nimbus"
10
+ },
11
+ "license": "Apache-2.0",
12
+ "bugs": {
13
+ "url": "https://github.com/overlap-dev/Nimbus/issues"
14
+ },
15
+ "module": "./esm/index.js",
16
+ "exports": {
17
+ ".": {
18
+ "import": "./esm/index.js"
19
+ }
20
+ },
21
+ "scripts": {},
22
+ "engines": {
23
+ "node": ">=20"
24
+ },
25
+ "dependencies": {
26
+ "@opentelemetry/api": "^1.9.1",
27
+ "zod": "^4.3.6"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0"
31
+ },
32
+ "_generatedBy": "dnt@dev"
33
+ }