@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,394 @@
1
+ import { blue, bold, red, yellow } from '../../deps/jsr.io/@std/fmt/1.0.10/colors.js';
2
+ import { numericLogLevel } from './logLevel.js';
3
+ import { defaultLogOptions } from './options.js';
4
+ /**
5
+ * The Logger provides structured logging with configurable log levels, formatters, and console colors.
6
+ *
7
+ * The Logger is a singleton that should be configured once at application startup using
8
+ * {@link setupLogger}, then accessed throughout the application using {@link getLogger}.
9
+ *
10
+ * Log levels in order of severity: debug < info < warn < error < critical.
11
+ * Messages below the configured log level are silently ignored.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import {
16
+ * getLogger,
17
+ * jsonLogFormatter,
18
+ * parseLogLevel,
19
+ * prettyLogFormatter,
20
+ * setupLogger,
21
+ * } from '@nimbus/core';
22
+ *
23
+ * // Configure the logger at application startup
24
+ * setupLogger({
25
+ * logLevel: parseLogLevel(process.env.LOG_LEVEL),
26
+ * formatter: process.env.NODE_ENV === 'production'
27
+ * ? jsonLogFormatter
28
+ * : prettyLogFormatter,
29
+ * useConsoleColors: process.env.NODE_ENV !== 'production',
30
+ * });
31
+ *
32
+ * // Use the logger throughout your application
33
+ * const logger = getLogger();
34
+ *
35
+ * logger.info({
36
+ * message: 'Application started',
37
+ * category: 'App',
38
+ * data: { port: 3000, environment: 'production' },
39
+ * });
40
+ *
41
+ * logger.error({
42
+ * message: 'Failed to connect to database',
43
+ * category: 'Database',
44
+ * error: new Error('Connection timeout'),
45
+ * correlationId: '550e8400-e29b-41d4-a716-446655440000',
46
+ * });
47
+ * ```
48
+ */
49
+ export class Logger {
50
+ static _instance;
51
+ _logLevel;
52
+ _formatter;
53
+ _useConsoleColors;
54
+ constructor(options) {
55
+ this._logLevel = options.logLevel ?? defaultLogOptions.logLevel;
56
+ this._formatter = options.formatter ?? defaultLogOptions.formatter;
57
+ this._useConsoleColors = options.useConsoleColors ??
58
+ defaultLogOptions.useConsoleColors;
59
+ }
60
+ /**
61
+ * Configure the Logger.
62
+ *
63
+ * @param {LogOptions} options - The options for the Logger
64
+ * @param {LogLevel} options.logLevel - The log level to use for the Logger
65
+ * @param {LogFormatter} options.formatter - The formatter to use for the Logger
66
+ */
67
+ static configure(options) {
68
+ Logger._instance = new Logger(options);
69
+ }
70
+ /**
71
+ * Get the Logger instance.
72
+ *
73
+ * @returns {Logger} The Logger instance
74
+ */
75
+ static getInstance() {
76
+ if (!Logger._instance) {
77
+ Logger._instance = new Logger(defaultLogOptions);
78
+ }
79
+ return Logger._instance;
80
+ }
81
+ /**
82
+ * Log a message at the debug level.
83
+ *
84
+ * @param {LogInput} logInput - The log input
85
+ * @param {string} logInput.message - The message
86
+ * @param {string} logInput.category - An optional category
87
+ * @param {string} logInput.correlationId - An optional correlation ID
88
+ * @param {Record<string, unknown>} logInput.data - An optional data object
89
+ * @param {Error | Exception} logInput.error - An optional error
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { getLogger } from "@nimbus/core";
94
+ *
95
+ * getLogger().debug({
96
+ * message: 'Hello World!',
97
+ * category: 'MyCategory',
98
+ * correlationId: '1234567890',
99
+ * data: {
100
+ * foo: 'bar',
101
+ * },
102
+ * error: new Error('Something went wrong!'),
103
+ * });
104
+ * ```
105
+ */
106
+ debug(logInput) {
107
+ if (numericLogLevel['debug'] >= numericLogLevel[this._logLevel]) {
108
+ this._log(logInput, 'debug', console.debug);
109
+ }
110
+ }
111
+ /**
112
+ * Log a message at the info level.
113
+ *
114
+ * @param {LogInput} logInput - The log input
115
+ * @param {string} logInput.message - The message
116
+ * @param {string} logInput.category - An optional category
117
+ * @param {string} logInput.correlationId - An optional correlation ID
118
+ * @param {Record<string, unknown>} logInput.data - An optional data object
119
+ * @param {Error | Exception} logInput.error - An optional error
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * import { getLogger } from "@nimbus/core";
124
+ *
125
+ * getLogger().info({
126
+ * message: 'Hello World!',
127
+ * category: 'MyCategory',
128
+ * correlationId: '1234567890',
129
+ * data: {
130
+ * foo: 'bar',
131
+ * },
132
+ * error: new Error('Something went wrong!'),
133
+ * });
134
+ * ```
135
+ */
136
+ info(logInput) {
137
+ if (numericLogLevel['info'] >= numericLogLevel[this._logLevel]) {
138
+ this._log(logInput, 'info', console.info);
139
+ }
140
+ }
141
+ /**
142
+ * Log a message at the warn level.
143
+ *
144
+ * @param {LogInput} logInput - The log input
145
+ * @param {string} logInput.message - The message
146
+ * @param {string} logInput.category - An optional category
147
+ * @param {string} logInput.correlationId - An optional correlation ID
148
+ * @param {Record<string, unknown>} logInput.data - An optional data object
149
+ * @param {Error | Exception} logInput.error - An optional error
150
+ *
151
+ * @example
152
+ * ```ts
153
+ * import { getLogger } from "@nimbus/core";
154
+ *
155
+ * getLogger().warn({
156
+ * message: 'Hello World!',
157
+ * category: 'MyCategory',
158
+ * correlationId: '1234567890',
159
+ * data: {
160
+ * foo: 'bar',
161
+ * },
162
+ * error: new Error('Something went wrong!'),
163
+ * });
164
+ * ```
165
+ */
166
+ warn(logInput) {
167
+ if (numericLogLevel['warn'] >= numericLogLevel[this._logLevel]) {
168
+ this._log(logInput, 'warn', console.warn);
169
+ }
170
+ }
171
+ /**
172
+ * Log a message at the error level.
173
+ *
174
+ * @param {LogInput} logInput - The log input
175
+ * @param {string} logInput.message - The message
176
+ * @param {string} logInput.category - An optional category
177
+ * @param {string} logInput.correlationId - An optional correlation ID
178
+ * @param {Record<string, unknown>} logInput.data - An optional data object
179
+ * @param {Error | Exception} logInput.error - An optional error
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * import { getLogger } from "@nimbus/core";
184
+ *
185
+ * getLogger().error({
186
+ * message: 'Hello World!',
187
+ * category: 'MyCategory',
188
+ * correlationId: '1234567890',
189
+ * data: {
190
+ * foo: 'bar',
191
+ * },
192
+ * error: new Error('Something went wrong!'),
193
+ * });
194
+ * ```
195
+ */
196
+ error(logInput) {
197
+ if (numericLogLevel['error'] >= numericLogLevel[this._logLevel]) {
198
+ this._log(logInput, 'error', console.error);
199
+ }
200
+ }
201
+ /**
202
+ * Log a message at the critical level.
203
+ *
204
+ * @param {LogInput} logInput - The log input
205
+ * @param {string} logInput.message - The message
206
+ * @param {string} logInput.category - An optional category
207
+ * @param {string} logInput.correlationId - An optional correlation ID
208
+ * @param {Record<string, unknown>} logInput.data - An optional data object
209
+ * @param {Error | Exception} logInput.error - An optional error
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * import { getLogger } from "@nimbus/core";
214
+ *
215
+ * getLogger().critical({
216
+ * message: 'Hello World!',
217
+ * category: 'MyCategory',
218
+ * correlationId: '1234567890',
219
+ * data: {
220
+ * foo: 'bar',
221
+ * },
222
+ * error: new Error('Something went wrong!'),
223
+ * });
224
+ * ```
225
+ */
226
+ critical(logInput) {
227
+ if (numericLogLevel['critical'] >= numericLogLevel[this._logLevel]) {
228
+ this._log(logInput, 'critical', console.error);
229
+ }
230
+ }
231
+ /**
232
+ * Produce a log record.
233
+ *
234
+ * @param {LogInput} logInput - The log input
235
+ * @param {LogLevel} level - The log level
236
+ *
237
+ * @returns {LogRecord} The log record
238
+ */
239
+ _produceLogRecord(logInput, level) {
240
+ return {
241
+ timestamp: new Date(),
242
+ level,
243
+ category: logInput.category ?? 'Default',
244
+ message: logInput.message,
245
+ ...(logInput.data && { data: logInput.data }),
246
+ ...(logInput.error && { error: logInput.error }),
247
+ ...(logInput.correlationId &&
248
+ { correlationId: logInput.correlationId }),
249
+ };
250
+ }
251
+ /**
252
+ * Format a log record.
253
+ *
254
+ * @param {LogRecord} logRecord - The log record
255
+ *
256
+ * @returns {string} The formatted log record
257
+ */
258
+ _formatLogRecord(logRecord) {
259
+ return this._formatter(logRecord);
260
+ }
261
+ /**
262
+ * Colorize a string.
263
+ *
264
+ * @param {string} string - The string to colorize
265
+ * @param {LogLevel} logLevel - The log level to determine the color
266
+ *
267
+ * @returns {string} The colorized string
268
+ */
269
+ _colorizeString(string, logLevel) {
270
+ switch (logLevel) {
271
+ case 'info':
272
+ string = blue(string);
273
+ break;
274
+ case 'warn':
275
+ string = yellow(string);
276
+ break;
277
+ case 'error':
278
+ string = red(string);
279
+ break;
280
+ case 'critical':
281
+ string = bold(red(string));
282
+ break;
283
+ default:
284
+ break;
285
+ }
286
+ return string;
287
+ }
288
+ /**
289
+ * Log a message.
290
+ *
291
+ * @param {LogInput} logInput - The log input
292
+ * @param {LogLevel} logLevel - The log level
293
+ * @param {Function} logFunction - The log function
294
+ */
295
+ _log(logInput, logLevel, logFunction) {
296
+ const logRecord = this._produceLogRecord(logInput, logLevel);
297
+ const formattedLogRecord = this._formatLogRecord(logRecord);
298
+ if (Array.isArray(formattedLogRecord)) {
299
+ if (this._useConsoleColors) {
300
+ const coloredLogs = formattedLogRecord.map((log) => this._colorizeString(log, logLevel));
301
+ logFunction(...coloredLogs);
302
+ }
303
+ else {
304
+ logFunction(...formattedLogRecord);
305
+ }
306
+ }
307
+ else if (this._useConsoleColors) {
308
+ logFunction(this._colorizeString(formattedLogRecord, logLevel));
309
+ }
310
+ else {
311
+ logFunction(formattedLogRecord);
312
+ }
313
+ }
314
+ }
315
+ /**
316
+ * Configure the Logger.
317
+ *
318
+ * @param {LogOptions} options - The options for the Logger
319
+ *
320
+ * @example
321
+ * ```ts
322
+ * import {
323
+ * jsonLogFormatter,
324
+ * parseLogLevel,
325
+ * prettyLogFormatter,
326
+ * setupLogger,
327
+ * } from "@nimbus/core";
328
+ *
329
+ * setupLogger({
330
+ * logLevel: parseLogLevel(process.env.LOG_LEVEL),
331
+ * formatter:
332
+ * process.env.NODE_ENV === "development"
333
+ * ? prettyLogFormatter
334
+ * : jsonLogFormatter,
335
+ * useConsoleColors: process.env.NODE_ENV === "development",
336
+ * });
337
+ * ```
338
+ */
339
+ export const setupLogger = (options) => {
340
+ Logger.configure(options);
341
+ };
342
+ /**
343
+ * Get the Logger instance.
344
+ *
345
+ * Returns the singleton Logger instance. If the logger has not been configured
346
+ * via {@link setupLogger}, a default logger with silent log level is returned.
347
+ *
348
+ * @returns The Logger instance.
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * import { getLogger } from '@nimbus/core';
353
+ *
354
+ * const logger = getLogger();
355
+ *
356
+ * // Log at different levels with all available options
357
+ * logger.debug({
358
+ * message: 'Processing request',
359
+ * category: 'API',
360
+ * data: { method: 'POST', path: '/orders' },
361
+ * correlationId: '550e8400-e29b-41d4-a716-446655440000',
362
+ * });
363
+ *
364
+ * logger.info({
365
+ * message: 'Order created successfully',
366
+ * category: 'Orders',
367
+ * data: { orderId: '12345', customerId: '67890' },
368
+ * correlationId: '550e8400-e29b-41d4-a716-446655440000',
369
+ * });
370
+ *
371
+ * logger.warn({
372
+ * message: 'Rate limit approaching',
373
+ * category: 'API',
374
+ * data: { currentRate: 95, maxRate: 100 },
375
+ * });
376
+ *
377
+ * logger.error({
378
+ * message: 'Failed to process payment',
379
+ * category: 'Payments',
380
+ * data: { orderId: '12345' },
381
+ * error: new Error('Payment gateway timeout'),
382
+ * correlationId: '550e8400-e29b-41d4-a716-446655440000',
383
+ * });
384
+ *
385
+ * logger.critical({
386
+ * message: 'Database connection lost',
387
+ * category: 'Database',
388
+ * error: new Error('Connection refused'),
389
+ * });
390
+ * ```
391
+ */
392
+ export const getLogger = () => {
393
+ return Logger.getInstance();
394
+ };
@@ -0,0 +1,34 @@
1
+ import { type LogFormatter } from './logFormatter.js';
2
+ import type { LogLevel } from './logLevel.js';
3
+ /**
4
+ * Configuration options for the Logger.
5
+ *
6
+ * Use these options with {@link setupLogger} to configure the logger at application startup.
7
+ */
8
+ export type LogOptions = {
9
+ /**
10
+ * The minimum log level to output. Messages below this level are silently ignored.
11
+ * Levels in order of severity: debug < info < warn < error < critical.
12
+ * Defaults to 'silent' (no logs output).
13
+ */
14
+ logLevel?: LogLevel;
15
+ /**
16
+ * The formatter function used to convert LogRecord objects into output strings.
17
+ * Use `jsonLogFormatter` for structured JSON output (recommended for production),
18
+ * or `prettyLogFormatter` for human-readable output (recommended for development).
19
+ * Defaults to `jsonLogFormatter`.
20
+ */
21
+ formatter?: LogFormatter;
22
+ /**
23
+ * Whether to apply ANSI color codes to the console output based on log level.
24
+ * Set to true for colored output in development terminals.
25
+ * Set to false for production or when outputting to log aggregation systems.
26
+ * Defaults to false.
27
+ */
28
+ useConsoleColors?: boolean;
29
+ };
30
+ /**
31
+ * The default log options.
32
+ */
33
+ export declare const defaultLogOptions: Required<LogOptions>;
34
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/log/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,UAAU,CAIlD,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { jsonLogFormatter } from './logFormatter.js';
2
+ /**
3
+ * The default log options.
4
+ */
5
+ export const defaultLogOptions = {
6
+ logLevel: 'silent',
7
+ formatter: jsonLogFormatter,
8
+ useConsoleColors: false,
9
+ };
@@ -0,0 +1,100 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * A command is a message that is sent to tell the system
4
+ * to perform an action. Typically commands come in via an API
5
+ * like HTTP POST requests, gRPC calls, or similar inbound traffic.
6
+ *
7
+ * Nimbus sticks to the CloudEvents specifications for all messages
8
+ * to make it easier to work with these messages across multiple systems.
9
+ *
10
+ * @see https://cloudevents.io/ for more information.
11
+ *
12
+ * @property {string} specversion - The version of the CloudEvents specification which the event uses.
13
+ * @property {string} id - A globally unique identifier of the event.
14
+ * @property {string} correlationid - A globally unique identifier that indicates a correlation to previous and subsequent messages.
15
+ * @property {string} time - The time when the command was created.
16
+ * @property {string} source - A URI reference that identifies the system that is constructing the command.
17
+ * @property {string} type - The type must follow the CloudEvents naming convention, which uses a reversed domain name as a namespace, followed by a domain-specific name.
18
+ * @property {string} subject - An identifier for an object or entity the command is about (optional).
19
+ * @property {TData} data - The actual data, containing the specific business payload.
20
+ * @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
21
+ * @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
22
+ *
23
+ * @template TData - The type of the data.
24
+ *
25
+ * @example
26
+ * const submitOrderCommand: Command<SubmitOrderPayload> = {
27
+ * specversion: '1.0',
28
+ * id: '123',
29
+ * correlationid: '456',
30
+ * time: '2025-01-01T00:00:00Z',
31
+ * source: 'https://nimbus.overlap.at',
32
+ * type: 'at.overlap.nimbus.submit-order',
33
+ * data: {
34
+ * customerId: '666',
35
+ * cartId: '123',
36
+ * },
37
+ * datacontenttype: 'application/json',
38
+ * };
39
+ */
40
+ export type Command<TData = unknown> = {
41
+ specversion: '1.0';
42
+ id: string;
43
+ correlationid: string;
44
+ time: string;
45
+ source: string;
46
+ type: string;
47
+ subject?: string;
48
+ data: TData;
49
+ datacontenttype?: string;
50
+ dataschema?: string;
51
+ };
52
+ /**
53
+ * Type alias for the command data field schema.
54
+ */
55
+ type CommandDataSchema = z.ZodUnion<[
56
+ z.ZodRecord<z.ZodString, z.ZodUnknown>,
57
+ z.ZodString,
58
+ z.ZodNumber,
59
+ z.ZodArray<z.ZodUnknown>,
60
+ z.ZodBoolean
61
+ ]>;
62
+ /**
63
+ * Type alias for the command schema shape.
64
+ */
65
+ export type CommandSchemaType = z.ZodObject<{
66
+ specversion: z.ZodLiteral<'1.0'>;
67
+ id: z.ZodString;
68
+ correlationid: z.ZodString;
69
+ time: z.ZodISODateTime;
70
+ source: z.ZodString;
71
+ type: z.ZodString;
72
+ subject: z.ZodOptional<z.ZodString>;
73
+ data: CommandDataSchema;
74
+ datacontenttype: z.ZodOptional<z.ZodString>;
75
+ dataschema: z.ZodOptional<z.ZodURL>;
76
+ }>;
77
+ /**
78
+ * The Zod schema matching the Command type.
79
+ *
80
+ * Zod is the default for validating incomming messages.
81
+ *
82
+ * We do not infer the Command type from this schema because of
83
+ * slow type issues see https://jsr.io/docs/about-slow-types for more details.
84
+ */
85
+ export declare const commandSchema: CommandSchemaType;
86
+ /**
87
+ * Input for creating a command.
88
+ *
89
+ * When a specific command type is provided via the generic parameter,
90
+ * the input is validated against that type. This means fields like
91
+ * `type` and `data` must match the narrower types of `TCommand`.
92
+ */
93
+ export type CreateCommandInput<TCommand extends Command = Command> = Partial<Pick<TCommand, 'id' | 'correlationid' | 'time' | 'subject' | 'datacontenttype' | 'dataschema'>> & Pick<TCommand, 'type' | 'source' | 'data'>;
94
+ /**
95
+ * Creates a command based on input data with the convenience
96
+ * to skip properties and use the defaults for the rest.
97
+ */
98
+ export declare const createCommand: <TCommand extends Command>(input: CreateCommandInput<TCommand>) => TCommand;
99
+ export {};
100
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/lib/message/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAAI;IACnC,WAAW,EAAE,KAAK,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,iBAAiB,GAAG,CAAC,CAAC,QAAQ,CAC/B;IACI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;IACtC,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACxB,CAAC,CAAC,UAAU;CACf,CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC;IACvB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,EAAE,iBAAiB,CAAC;IACxB,eAAe,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,iBAiB1B,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,OAAO,GAAG,OAAO,IAC3D,OAAO,CACL,IAAI,CACA,QAAQ,EACN,IAAI,GACJ,eAAe,GACf,MAAM,GACN,SAAS,GACT,iBAAiB,GACjB,YAAY,CACjB,CACJ,GACC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,OAAO,EAClD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,KACpC,QAeF,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
2
+ import { z } from 'zod';
3
+ /**
4
+ * The Zod schema matching the Command type.
5
+ *
6
+ * Zod is the default for validating incomming messages.
7
+ *
8
+ * We do not infer the Command type from this schema because of
9
+ * slow type issues see https://jsr.io/docs/about-slow-types for more details.
10
+ */
11
+ export const commandSchema = z.object({
12
+ specversion: z.literal('1.0'),
13
+ id: z.string(),
14
+ correlationid: z.string(),
15
+ time: z.iso.datetime(),
16
+ source: z.string(),
17
+ type: z.string(),
18
+ subject: z.string().optional(),
19
+ data: z.union([
20
+ z.record(z.string(), z.unknown()),
21
+ z.string(),
22
+ z.number(),
23
+ z.array(z.unknown()),
24
+ z.boolean(),
25
+ ]),
26
+ datacontenttype: z.string().optional(),
27
+ dataschema: z.url().optional(),
28
+ });
29
+ /**
30
+ * Creates a command based on input data with the convenience
31
+ * to skip properties and use the defaults for the rest.
32
+ */
33
+ export const createCommand = (input) => {
34
+ const command = {
35
+ specversion: '1.0',
36
+ id: input.id ?? ulid(),
37
+ correlationid: input.correlationid ?? ulid(),
38
+ time: input.time ?? new Date().toISOString(),
39
+ source: input.source,
40
+ type: input.type,
41
+ ...(input.subject && { subject: input.subject }),
42
+ data: input.data,
43
+ datacontenttype: input.datacontenttype ?? 'application/json',
44
+ ...(input.dataschema && { dataschema: input.dataschema }),
45
+ };
46
+ return command;
47
+ };
@@ -0,0 +1,103 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * An event is a message that is emitted by the system to notify
4
+ * subscribers that something has happened. Typically events are
5
+ * the result of a command that was executed before.
6
+ *
7
+ * Nimbus sticks to the CloudEvents specifications for all messages
8
+ * to make it easier to work with these messages across multiple systems.
9
+ *
10
+ * @see https://cloudevents.io/ for more information.
11
+ *
12
+ * @property {string} specversion - The version of the CloudEvents specification which the event uses.
13
+ * @property {string} id - A globally unique identifier of the event.
14
+ * @property {string} correlationid - A globally unique identifier that indicates a correlation to previous and subsequent messages to this event.
15
+ * @property {string} time - The time when the event was created.
16
+ * @property {string} source - A URI reference that identifies the system that is constructing the event.
17
+ * @property {string} type - The type must follow the CloudEvents naming convention, which uses a reversed domain name as a namespace, followed by a domain-specific name.
18
+ * @property {string} subject - An identifier for an object or entity the event is about (optional).
19
+ * @property {TData} data - The actual data, containing the specific business payload.
20
+ * @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
21
+ * @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
22
+ *
23
+ * @template TData - The type of the data.
24
+ *
25
+ * @example
26
+ * const orderSubmittedEvent: Event<Order> = {
27
+ * specversion: '1.0',
28
+ * id: '123',
29
+ * correlationid: '456',
30
+ * time: '2025-01-01T00:00:00Z',
31
+ * source: 'https://nimbus.overlap.at',
32
+ * type: 'at.overlap.nimbus.submit-order',
33
+ * subject: '/orders/42',
34
+ * data: {
35
+ * orderId: '42',
36
+ * customerId: '666',
37
+ * cartId: '123',
38
+ * status: 'submitted',
39
+ * },
40
+ * datacontenttype: 'application/json',
41
+ * };
42
+ */
43
+ export type Event<TData = unknown> = {
44
+ specversion: '1.0';
45
+ id: string;
46
+ correlationid: string;
47
+ time: string;
48
+ source: string;
49
+ type: string;
50
+ subject: string;
51
+ data: TData;
52
+ datacontenttype?: string;
53
+ dataschema?: string;
54
+ };
55
+ /**
56
+ * Type alias for the event data field schema.
57
+ */
58
+ type EventDataSchema = z.ZodUnion<[
59
+ z.ZodRecord<z.ZodString, z.ZodUnknown>,
60
+ z.ZodString,
61
+ z.ZodNumber,
62
+ z.ZodArray<z.ZodUnknown>,
63
+ z.ZodBoolean
64
+ ]>;
65
+ /**
66
+ * Type alias for the event schema shape.
67
+ */
68
+ export type EventSchemaType = z.ZodObject<{
69
+ specversion: z.ZodLiteral<'1.0'>;
70
+ id: z.ZodString;
71
+ correlationid: z.ZodString;
72
+ time: z.ZodISODateTime;
73
+ source: z.ZodString;
74
+ type: z.ZodString;
75
+ subject: z.ZodString;
76
+ data: EventDataSchema;
77
+ datacontenttype: z.ZodOptional<z.ZodString>;
78
+ dataschema: z.ZodOptional<z.ZodURL>;
79
+ }>;
80
+ /**
81
+ * The Zod schema matching the Event type.
82
+ *
83
+ * Zod is the default for validating incoming messages.
84
+ *
85
+ * We do not infer the Event type from this schema because of
86
+ * slow type issues see https://jsr.io/docs/about-slow-types for more details.
87
+ */
88
+ export declare const eventSchema: EventSchemaType;
89
+ /**
90
+ * Input for creating an event.
91
+ *
92
+ * When a specific event type is provided via the generic parameter,
93
+ * the input is validated against that type. This means fields like
94
+ * `type` and `data` must match the narrower types of `TEvent`.
95
+ */
96
+ export type CreateEventInput<TEvent extends Event = Event> = Partial<Pick<TEvent, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TEvent, 'type' | 'source' | 'subject' | 'data'>;
97
+ /**
98
+ * Creates an event based on input data with the convenience
99
+ * to skip properties and use the defaults for the rest.
100
+ */
101
+ export declare const createEvent: <TEvent extends Event>(input: CreateEventInput<TEvent>) => TEvent;
102
+ export {};
103
+ //# sourceMappingURL=event.d.ts.map