@nimbus-cqrs/core 2.1.2 → 2.3.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 (40) hide show
  1. package/esm/_dnt.polyfills.d.ts +7 -0
  2. package/esm/_dnt.polyfills.d.ts.map +1 -0
  3. package/esm/_dnt.polyfills.js +1 -0
  4. package/esm/index.d.ts +4 -0
  5. package/esm/index.d.ts.map +1 -1
  6. package/esm/index.js +4 -0
  7. package/esm/lib/env/getEnv.d.ts +15 -0
  8. package/esm/lib/env/getEnv.d.ts.map +1 -0
  9. package/esm/lib/env/getEnv.js +35 -0
  10. package/esm/lib/eventBus/eventBus.d.ts +0 -1
  11. package/esm/lib/eventBus/eventBus.d.ts.map +1 -1
  12. package/esm/lib/eventBus/eventBus.js +31 -32
  13. package/esm/lib/exception/exception.d.ts +1 -1
  14. package/esm/lib/exception/exception.d.ts.map +1 -1
  15. package/esm/lib/exception/invalidInputException.d.ts +1 -1
  16. package/esm/lib/exception/invalidInputException.d.ts.map +1 -1
  17. package/esm/lib/log/logTruncator.d.ts +96 -0
  18. package/esm/lib/log/logTruncator.d.ts.map +1 -0
  19. package/esm/lib/log/logTruncator.js +254 -0
  20. package/esm/lib/log/logger.d.ts +20 -0
  21. package/esm/lib/log/logger.d.ts.map +1 -1
  22. package/esm/lib/log/logger.js +28 -1
  23. package/esm/lib/log/options.d.ts +13 -1
  24. package/esm/lib/log/options.d.ts.map +1 -1
  25. package/esm/lib/message/command.d.ts +11 -1
  26. package/esm/lib/message/command.d.ts.map +1 -1
  27. package/esm/lib/message/command.js +17 -10
  28. package/esm/lib/message/event.d.ts +11 -1
  29. package/esm/lib/message/event.d.ts.map +1 -1
  30. package/esm/lib/message/event.js +17 -10
  31. package/esm/lib/message/message.d.ts +14 -0
  32. package/esm/lib/message/message.d.ts.map +1 -1
  33. package/esm/lib/message/message.js +47 -1
  34. package/esm/lib/message/query.d.ts +11 -1
  35. package/esm/lib/message/query.d.ts.map +1 -1
  36. package/esm/lib/message/query.js +16 -9
  37. package/esm/lib/retry/withRetry.d.ts +175 -0
  38. package/esm/lib/retry/withRetry.d.ts.map +1 -0
  39. package/esm/lib/retry/withRetry.js +207 -0
  40. package/package.json +2 -2
@@ -32,6 +32,12 @@ export type LogInput = {
32
32
  * Useful for tracking a request through multiple services or handlers.
33
33
  */
34
34
  correlationId?: string;
35
+ /**
36
+ * When `true`, skips the configured truncator for this log call.
37
+ * Useful for intentionally logging full payloads. Defaults to `false`.
38
+ * This flag is not included in the emitted log record.
39
+ */
40
+ skipTruncation?: boolean;
35
41
  };
36
42
  /**
37
43
  * A full log record with the log input and additional metadata attached.
@@ -80,6 +86,7 @@ export type LogRecord = {
80
86
  * @example
81
87
  * ```ts
82
88
  * import {
89
+ * createLogTruncator,
83
90
  * getLogger,
84
91
  * jsonLogFormatter,
85
92
  * parseLogLevel,
@@ -94,6 +101,7 @@ export type LogRecord = {
94
101
  * ? jsonLogFormatter
95
102
  * : prettyLogFormatter,
96
103
  * useConsoleColors: process.env.NODE_ENV !== 'production',
104
+ * truncator: createLogTruncator(),
97
105
  * });
98
106
  *
99
107
  * // Use the logger throughout your application
@@ -118,6 +126,7 @@ export declare class Logger {
118
126
  private readonly _logLevel;
119
127
  private readonly _formatter;
120
128
  private readonly _useConsoleColors;
129
+ private readonly _truncator?;
121
130
  constructor(options: LogOptions);
122
131
  /**
123
132
  * Configure the Logger.
@@ -125,6 +134,7 @@ export declare class Logger {
125
134
  * @param {LogOptions} options - The options for the Logger
126
135
  * @param {LogLevel} options.logLevel - The log level to use for the Logger
127
136
  * @param {LogFormatter} options.formatter - The formatter to use for the Logger
137
+ * @param {LogTruncator} options.truncator - Optional truncator for log inputs
128
138
  */
129
139
  static configure(options: LogOptions): void;
130
140
  /**
@@ -289,6 +299,14 @@ export declare class Logger {
289
299
  * @returns {string} The colorized string
290
300
  */
291
301
  private _colorizeString;
302
+ /**
303
+ * Apply the configured truncator, failing open if it throws.
304
+ *
305
+ * @param {LogInput} logInput - The original log input
306
+ *
307
+ * @returns {LogInput} The truncated log input, or the original on failure
308
+ */
309
+ private _applyTruncator;
292
310
  /**
293
311
  * Log a message.
294
312
  *
@@ -306,6 +324,7 @@ export declare class Logger {
306
324
  * @example
307
325
  * ```ts
308
326
  * import {
327
+ * createLogTruncator,
309
328
  * jsonLogFormatter,
310
329
  * parseLogLevel,
311
330
  * prettyLogFormatter,
@@ -319,6 +338,7 @@ export declare class Logger {
319
338
  * ? prettyLogFormatter
320
339
  * : jsonLogFormatter,
321
340
  * useConsoleColors: process.env.NODE_ENV === "development",
341
+ * truncator: createLogTruncator(),
322
342
  * });
323
343
  * ```
324
344
  */
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/lib/log/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,KAAK,QAAQ,EAAmB,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAElE;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG;IACnB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IACpB;;OAEG;IACH,SAAS,EAAE,IAAI,CAAC;IAChB;;OAEG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBAAa,MAAM;IACf,OAAO,CAAC,MAAM,CAAC,SAAS,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;gBAEhC,OAAO,EAAE,UAAU;IAO/B;;;;;;OAMG;WACW,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAIlD;;;;OAIG;WACW,WAAW,IAAI,MAAM;IAQnC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMtC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMrC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMrC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMtC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMzC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAwBvB;;;;;;OAMG;IACH,OAAO,CAAC,IAAI;CAwBf;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,UAAU,KAAG,IAEjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,SAAS,QAAO,MAE5B,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/lib/log/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,KAAK,QAAQ,EAAmB,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAGlE;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG;IACnB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IACpB;;OAEG;IACH,SAAS,EAAE,IAAI,CAAC;IAChB;;OAEG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,MAAM;IACf,OAAO,CAAC,MAAM,CAAC,SAAS,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAe;gBAE/B,OAAO,EAAE,UAAU;IAQ/B;;;;;;;OAOG;WACW,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAIlD;;;;OAIG;WACW,WAAW,IAAI,MAAM;IAQnC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMtC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMrC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMrC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMtC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMzC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAwBvB;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;;OAMG;IACH,OAAO,CAAC,IAAI;CAyBf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,UAAU,KAAG,IAEjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,SAAS,QAAO,MAE5B,CAAC"}
@@ -13,6 +13,7 @@ import { defaultLogOptions } from './options.js';
13
13
  * @example
14
14
  * ```ts
15
15
  * import {
16
+ * createLogTruncator,
16
17
  * getLogger,
17
18
  * jsonLogFormatter,
18
19
  * parseLogLevel,
@@ -27,6 +28,7 @@ import { defaultLogOptions } from './options.js';
27
28
  * ? jsonLogFormatter
28
29
  * : prettyLogFormatter,
29
30
  * useConsoleColors: process.env.NODE_ENV !== 'production',
31
+ * truncator: createLogTruncator(),
30
32
  * });
31
33
  *
32
34
  * // Use the logger throughout your application
@@ -51,11 +53,13 @@ export class Logger {
51
53
  _logLevel;
52
54
  _formatter;
53
55
  _useConsoleColors;
56
+ _truncator;
54
57
  constructor(options) {
55
58
  this._logLevel = options.logLevel ?? defaultLogOptions.logLevel;
56
59
  this._formatter = options.formatter ?? defaultLogOptions.formatter;
57
60
  this._useConsoleColors = options.useConsoleColors ??
58
61
  defaultLogOptions.useConsoleColors;
62
+ this._truncator = options.truncator ?? defaultLogOptions.truncator;
59
63
  }
60
64
  /**
61
65
  * Configure the Logger.
@@ -63,6 +67,7 @@ export class Logger {
63
67
  * @param {LogOptions} options - The options for the Logger
64
68
  * @param {LogLevel} options.logLevel - The log level to use for the Logger
65
69
  * @param {LogFormatter} options.formatter - The formatter to use for the Logger
70
+ * @param {LogTruncator} options.truncator - Optional truncator for log inputs
66
71
  */
67
72
  static configure(options) {
68
73
  Logger._instance = new Logger(options);
@@ -285,6 +290,25 @@ export class Logger {
285
290
  }
286
291
  return string;
287
292
  }
293
+ /**
294
+ * Apply the configured truncator, failing open if it throws.
295
+ *
296
+ * @param {LogInput} logInput - The original log input
297
+ *
298
+ * @returns {LogInput} The truncated log input, or the original on failure
299
+ */
300
+ _applyTruncator(logInput) {
301
+ if (!this._truncator || logInput.skipTruncation) {
302
+ return logInput;
303
+ }
304
+ try {
305
+ return this._truncator(logInput);
306
+ }
307
+ catch (error) {
308
+ console.warn('Log truncator failed; logging original input.', error);
309
+ return logInput;
310
+ }
311
+ }
288
312
  /**
289
313
  * Log a message.
290
314
  *
@@ -293,7 +317,8 @@ export class Logger {
293
317
  * @param {Function} logFunction - The log function
294
318
  */
295
319
  _log(logInput, logLevel, logFunction) {
296
- const logRecord = this._produceLogRecord(logInput, logLevel);
320
+ const truncatedInput = this._applyTruncator(logInput);
321
+ const logRecord = this._produceLogRecord(truncatedInput, logLevel);
297
322
  const formattedLogRecord = this._formatLogRecord(logRecord);
298
323
  if (Array.isArray(formattedLogRecord)) {
299
324
  if (this._useConsoleColors) {
@@ -320,6 +345,7 @@ export class Logger {
320
345
  * @example
321
346
  * ```ts
322
347
  * import {
348
+ * createLogTruncator,
323
349
  * jsonLogFormatter,
324
350
  * parseLogLevel,
325
351
  * prettyLogFormatter,
@@ -333,6 +359,7 @@ export class Logger {
333
359
  * ? prettyLogFormatter
334
360
  * : jsonLogFormatter,
335
361
  * useConsoleColors: process.env.NODE_ENV === "development",
362
+ * truncator: createLogTruncator(),
336
363
  * });
337
364
  * ```
338
365
  */
@@ -1,5 +1,6 @@
1
1
  import { type LogFormatter } from './logFormatter.js';
2
2
  import type { LogLevel } from './logLevel.js';
3
+ import type { LogTruncator } from './logTruncator.js';
3
4
  /**
4
5
  * Configuration options for the Logger.
5
6
  *
@@ -26,9 +27,20 @@ export type LogOptions = {
26
27
  * Defaults to false.
27
28
  */
28
29
  useConsoleColors?: boolean;
30
+ /**
31
+ * Optional truncator applied to each {@link LogInput} before formatting.
32
+ * Use {@link createLogTruncator} for the built-in implementation, or supply a custom one.
33
+ * Defaults to undefined (no truncation).
34
+ */
35
+ truncator?: LogTruncator;
29
36
  };
30
37
  /**
31
38
  * The default log options.
32
39
  */
33
- export declare const defaultLogOptions: Required<LogOptions>;
40
+ export declare const defaultLogOptions: {
41
+ logLevel: LogLevel;
42
+ formatter: LogFormatter;
43
+ useConsoleColors: boolean;
44
+ truncator?: LogTruncator;
45
+ };
34
46
  //# sourceMappingURL=options.d.ts.map
@@ -1 +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"}
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;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;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;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,YAAY,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,YAAY,CAAC;CAK5B,CAAC"}
@@ -20,6 +20,12 @@ import { z } from 'zod';
20
20
  * @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
21
21
  * @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
22
22
  *
23
+ * Commands may include additional CloudEvents extension attributes such as
24
+ * `metadata` or `authcontext`. Define them on a command-specific schema via
25
+ * {@link commandSchema.extend} or as an intersection type.
26
+ *
27
+ * @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
28
+ *
23
29
  * @template TData - The type of the data.
24
30
  *
25
31
  * @example
@@ -49,6 +55,10 @@ export type Command<TData = unknown> = {
49
55
  datacontenttype?: string;
50
56
  dataschema?: string;
51
57
  };
58
+ /**
59
+ * Known command properties handled by {@link createCommand}.
60
+ */
61
+ type CommandKnownProperty = 'specversion' | 'id' | 'correlationid' | 'time' | 'source' | 'type' | 'subject' | 'data' | 'datacontenttype' | 'dataschema';
52
62
  /**
53
63
  * Type alias for the command data field schema.
54
64
  */
@@ -90,7 +100,7 @@ export declare const commandSchema: CommandSchemaType;
90
100
  * the input is validated against that type. This means fields like
91
101
  * `type` and `data` must match the narrower types of `TCommand`.
92
102
  */
93
- export type CreateCommandInput<TCommand extends Command = Command> = Partial<Pick<TCommand, 'id' | 'correlationid' | 'time' | 'subject' | 'datacontenttype' | 'dataschema'>> & Pick<TCommand, 'type' | 'source' | 'data'>;
103
+ export type CreateCommandInput<TCommand extends Command = Command> = Partial<Pick<TCommand, 'id' | 'correlationid' | 'time' | 'subject' | 'datacontenttype' | 'dataschema'>> & Pick<TCommand, 'type' | 'source' | 'data'> & Partial<Omit<TCommand, CommandKnownProperty>>;
94
104
  /**
95
105
  * Creates a command based on input data with the convenience
96
106
  * to skip properties and use the defaults for the rest.
@@ -1 +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"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/lib/message/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;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,oBAAoB,GACnB,aAAa,GACb,IAAI,GACJ,eAAe,GACf,MAAM,GACN,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAEnB;;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,iBAiBL,CAAC;AAExB;;;;;;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,GAC1C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,OAAO,EAClD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,KACpC,QAuCF,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
2
2
  import { z } from 'zod';
3
+ import { warnOnInvalidExtensionAttributeNames } from './message.js';
3
4
  /**
4
5
  * The Zod schema matching the Command type.
5
6
  *
@@ -8,7 +9,7 @@ import { z } from 'zod';
8
9
  * We do not infer the Command type from this schema because of
9
10
  * slow type issues see https://jsr.io/docs/about-slow-types for more details.
10
11
  */
11
- export const commandSchema = z.object({
12
+ export const commandSchema = z.looseObject({
12
13
  specversion: z.literal('1.0'),
13
14
  id: z.string(),
14
15
  correlationid: z.string(),
@@ -31,17 +32,23 @@ export const commandSchema = z.object({
31
32
  * to skip properties and use the defaults for the rest.
32
33
  */
33
34
  export const createCommand = (input) => {
35
+ const { id, correlationid, time, source, type, subject, data, datacontenttype, dataschema, ...extensions } = input;
36
+ const correlationIdWithFallback = correlationid ?? ulid();
37
+ if (Object.keys(extensions).length > 0) {
38
+ warnOnInvalidExtensionAttributeNames(extensions, correlationIdWithFallback, createCommand);
39
+ }
34
40
  const command = {
35
41
  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 }),
42
+ id: id ?? ulid(),
43
+ correlationid: correlationIdWithFallback,
44
+ time: time ?? new Date().toISOString(),
45
+ source,
46
+ type,
47
+ ...(subject && { subject }),
48
+ data,
49
+ datacontenttype: datacontenttype ?? 'application/json',
50
+ ...(dataschema && { dataschema }),
51
+ ...extensions,
45
52
  };
46
53
  return command;
47
54
  };
@@ -20,6 +20,12 @@ import { z } from 'zod';
20
20
  * @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
21
21
  * @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
22
22
  *
23
+ * Events may include additional CloudEvents extension attributes such as
24
+ * `metadata` or `authcontext`. Define them on an event-specific schema via
25
+ * {@link eventSchema.extend} or as an intersection type.
26
+ *
27
+ * @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
28
+ *
23
29
  * @template TData - The type of the data.
24
30
  *
25
31
  * @example
@@ -52,6 +58,10 @@ export type Event<TData = unknown> = {
52
58
  datacontenttype?: string;
53
59
  dataschema?: string;
54
60
  };
61
+ /**
62
+ * Known event properties handled by {@link createEvent}.
63
+ */
64
+ type EventKnownProperty = 'specversion' | 'id' | 'correlationid' | 'time' | 'source' | 'type' | 'subject' | 'data' | 'datacontenttype' | 'dataschema';
55
65
  /**
56
66
  * Type alias for the event data field schema.
57
67
  */
@@ -93,7 +103,7 @@ export declare const eventSchema: EventSchemaType;
93
103
  * the input is validated against that type. This means fields like
94
104
  * `type` and `data` must match the narrower types of `TEvent`.
95
105
  */
96
- export type CreateEventInput<TEvent extends Event = Event> = Partial<Pick<TEvent, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TEvent, 'type' | 'source' | 'subject' | 'data'>;
106
+ export type CreateEventInput<TEvent extends Event = Event> = Partial<Pick<TEvent, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TEvent, 'type' | 'source' | 'subject' | 'data'> & Partial<Omit<TEvent, EventKnownProperty>>;
97
107
  /**
98
108
  * Creates an event based on input data with the convenience
99
109
  * to skip properties and use the defaults for the rest.
@@ -1 +1 @@
1
- {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/lib/message/event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,OAAO,IAAI;IACjC,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,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,QAAQ,CAC7B;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,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC;IACtC,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,SAAS,CAAC;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,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,WAAW,EAAE,eAiBxB,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK,IACnD,OAAO,CACL,IAAI,CACA,MAAM,EACN,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,iBAAiB,GAAG,YAAY,CACrE,CACJ,GACC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAK,EAC5C,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAChC,MAeF,CAAC"}
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/lib/message/event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,OAAO,IAAI;IACjC,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,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,kBAAkB,GACjB,aAAa,GACb,IAAI,GACJ,eAAe,GACf,MAAM,GACN,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAEnB;;GAEG;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,QAAQ,CAC7B;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,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC;IACtC,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,SAAS,CAAC;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,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,WAAW,EAAE,eAiBL,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK,IACnD,OAAO,CACL,IAAI,CACA,MAAM,EACN,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,iBAAiB,GAAG,YAAY,CACrE,CACJ,GACC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,GACpD,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAK,EAC5C,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAChC,MAuCF,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
2
2
  import { z } from 'zod';
3
+ import { warnOnInvalidExtensionAttributeNames } from './message.js';
3
4
  /**
4
5
  * The Zod schema matching the Event type.
5
6
  *
@@ -8,7 +9,7 @@ import { z } from 'zod';
8
9
  * We do not infer the Event type from this schema because of
9
10
  * slow type issues see https://jsr.io/docs/about-slow-types for more details.
10
11
  */
11
- export const eventSchema = z.object({
12
+ export const eventSchema = z.looseObject({
12
13
  specversion: z.literal('1.0'),
13
14
  id: z.string(),
14
15
  correlationid: z.string(),
@@ -31,17 +32,23 @@ export const eventSchema = z.object({
31
32
  * to skip properties and use the defaults for the rest.
32
33
  */
33
34
  export const createEvent = (input) => {
35
+ const { id, correlationid, time, source, type, subject, data, datacontenttype, dataschema, ...extensions } = input;
36
+ const correlationIdWithFallback = correlationid ?? ulid();
37
+ if (Object.keys(extensions).length > 0) {
38
+ warnOnInvalidExtensionAttributeNames(extensions, correlationIdWithFallback, createEvent);
39
+ }
34
40
  const event = {
35
41
  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
- subject: input.subject,
42
- data: input.data,
43
- datacontenttype: input.datacontenttype ?? 'application/json',
44
- ...(input.dataschema && { dataschema: input.dataschema }),
42
+ id: id ?? ulid(),
43
+ correlationid: correlationIdWithFallback,
44
+ time: time ?? new Date().toISOString(),
45
+ source,
46
+ type,
47
+ subject,
48
+ data,
49
+ datacontenttype: datacontenttype ?? 'application/json',
50
+ ...(dataschema && { dataschema }),
51
+ ...extensions,
45
52
  };
46
53
  return event;
47
54
  };
@@ -15,4 +15,18 @@ import type { Query } from './query.js';
15
15
  * @template TData - The type of the data.
16
16
  */
17
17
  export type Message<TData = unknown> = Command<TData> | Event<TData> | Query<TData>;
18
+ /**
19
+ * Validates CloudEvents extension attribute names and logs a warning when invalid.
20
+ *
21
+ * Called by {@link createCommand}, {@link createEvent}, and {@link createQuery}
22
+ * to check extension attributes against the CloudEvents naming rules. Invalid
23
+ * names are logged with a stack trace anchored at the caller function.
24
+ *
25
+ * @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
26
+ *
27
+ * @param {Record<string, unknown>} extensions - Extension attributes to validate, excluding known CloudEvents context attributes.
28
+ * @param {string | undefined} correlationId - Optional correlation ID included in the warning log for tracing.
29
+ * @param {(...args: never[]) => unknown} stackTraceAnchor - Function used to anchor the warning stack trace at the message factory caller (for example {@link createCommand}).
30
+ */
31
+ export declare const warnOnInvalidExtensionAttributeNames: (extensions: Record<string, unknown>, correlationId: string | undefined, stackTraceAnchor: (...args: never[]) => unknown) => void;
18
32
  //# sourceMappingURL=message.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/lib/message/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAC7B,OAAO,CAAC,KAAK,CAAC,GACd,KAAK,CAAC,KAAK,CAAC,GACZ,KAAK,CAAC,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/lib/message/message.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAC7B,OAAO,CAAC,KAAK,CAAC,GACd,KAAK,CAAC,KAAK,CAAC,GACZ,KAAK,CAAC,KAAK,CAAC,CAAC;AAsCnB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oCAAoC,GAC7C,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,eAAe,MAAM,GAAG,SAAS,EACjC,kBAAkB,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,KAChD,IAkBF,CAAC"}
@@ -1 +1,47 @@
1
- export {};
1
+ import { getLogger } from '../log/logger.js';
2
+ /**
3
+ * CloudEvents extension context attribute names must consist of lowercase
4
+ * ASCII letters or digits.
5
+ *
6
+ * @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
7
+ */
8
+ const getInvalidExtensionAttributeNames = (extensions) => {
9
+ const EXTENSION_ATTRIBUTE_NAME_PATTERN = /^[a-z0-9]+$/;
10
+ return Object.keys(extensions).filter((name) => !EXTENSION_ATTRIBUTE_NAME_PATTERN.test(name));
11
+ };
12
+ /**
13
+ * Create an error object to capture the stack trace for better debugging.
14
+ */
15
+ const createInvalidExtensionAttributeNamesError = (invalidNames, stackTraceAnchor) => {
16
+ const error = new Error(`Invalid CloudEvents extension attribute names: ${invalidNames.join(', ')}`);
17
+ if (typeof Error.captureStackTrace === 'function') {
18
+ Error.captureStackTrace(error, stackTraceAnchor);
19
+ }
20
+ return error;
21
+ };
22
+ /**
23
+ * Validates CloudEvents extension attribute names and logs a warning when invalid.
24
+ *
25
+ * Called by {@link createCommand}, {@link createEvent}, and {@link createQuery}
26
+ * to check extension attributes against the CloudEvents naming rules. Invalid
27
+ * names are logged with a stack trace anchored at the caller function.
28
+ *
29
+ * @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
30
+ *
31
+ * @param {Record<string, unknown>} extensions - Extension attributes to validate, excluding known CloudEvents context attributes.
32
+ * @param {string | undefined} correlationId - Optional correlation ID included in the warning log for tracing.
33
+ * @param {(...args: never[]) => unknown} stackTraceAnchor - Function used to anchor the warning stack trace at the message factory caller (for example {@link createCommand}).
34
+ */
35
+ export const warnOnInvalidExtensionAttributeNames = (extensions, correlationId, stackTraceAnchor) => {
36
+ const invalidNames = getInvalidExtensionAttributeNames(extensions);
37
+ if (invalidNames.length === 0) {
38
+ return;
39
+ }
40
+ getLogger().warn({
41
+ category: 'Nimbus',
42
+ message: 'Extension attribute names must use lowercase ASCII letters or digits only per CloudEvents specification.',
43
+ data: { invalidAttributeNames: invalidNames },
44
+ error: createInvalidExtensionAttributeNamesError(invalidNames, stackTraceAnchor),
45
+ ...(correlationId && { correlationId }),
46
+ });
47
+ };
@@ -18,6 +18,12 @@ import { z } from 'zod';
18
18
  * @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
19
19
  * @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
20
20
  *
21
+ * Queries may include additional CloudEvents extension attributes such as
22
+ * `metadata` or `authcontext`. Define them on a query-specific schema via
23
+ * {@link querySchema.extend} or as an intersection type.
24
+ *
25
+ * @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
26
+ *
21
27
  * @template TData - The type of the data.
22
28
  *
23
29
  * @example
@@ -45,6 +51,10 @@ export type Query<TData = unknown> = {
45
51
  datacontenttype?: string;
46
52
  dataschema?: string;
47
53
  };
54
+ /**
55
+ * Known query properties handled by {@link createQuery}.
56
+ */
57
+ type QueryKnownProperty = 'specversion' | 'id' | 'correlationid' | 'time' | 'source' | 'type' | 'data' | 'datacontenttype' | 'dataschema';
48
58
  /**
49
59
  * Type alias for the query data field schema.
50
60
  */
@@ -85,7 +95,7 @@ export declare const querySchema: QuerySchemaType;
85
95
  * the input is validated against that type. This means fields like
86
96
  * `type` and `data` must match the narrower types of `TQuery`.
87
97
  */
88
- export type CreateQueryInput<TQuery extends Query = Query> = Partial<Pick<TQuery, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TQuery, 'type' | 'source' | 'data'>;
98
+ export type CreateQueryInput<TQuery extends Query = Query> = Partial<Pick<TQuery, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TQuery, 'type' | 'source' | 'data'> & Partial<Omit<TQuery, QueryKnownProperty>>;
89
99
  /**
90
100
  * Creates a query based on input data with the convenience
91
101
  * to skip properties and use the defaults for the rest.
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/lib/message/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,OAAO,IAAI;IACjC,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,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,QAAQ,CAC7B;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,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC;IACtC,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,IAAI,EAAE,eAAe,CAAC;IACtB,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,WAAW,EAAE,eAgBxB,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK,IACnD,OAAO,CACL,IAAI,CACA,MAAM,EACN,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,iBAAiB,GAAG,YAAY,CACrE,CACJ,GACC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAK,EAC5C,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAChC,MAcF,CAAC"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/lib/message/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,OAAO,IAAI;IACjC,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,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,kBAAkB,GACjB,aAAa,GACb,IAAI,GACJ,eAAe,GACf,MAAM,GACN,QAAQ,GACR,MAAM,GACN,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAEnB;;GAEG;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,QAAQ,CAC7B;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,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC;IACtC,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,IAAI,EAAE,eAAe,CAAC;IACtB,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,WAAW,EAAE,eAgBL,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK,IACnD,OAAO,CACL,IAAI,CACA,MAAM,EACN,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,iBAAiB,GAAG,YAAY,CACrE,CACJ,GACC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAK,EAC5C,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAChC,MAqCF,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
2
2
  import { z } from 'zod';
3
+ import { warnOnInvalidExtensionAttributeNames } from './message.js';
3
4
  /**
4
5
  * The Zod schema matching the Query type.
5
6
  *
@@ -8,7 +9,7 @@ import { z } from 'zod';
8
9
  * We do not infer the Query type from this schema because of
9
10
  * slow type issues see https://jsr.io/docs/about-slow-types for more details.
10
11
  */
11
- export const querySchema = z.object({
12
+ export const querySchema = z.looseObject({
12
13
  specversion: z.literal('1.0'),
13
14
  id: z.string(),
14
15
  correlationid: z.string(),
@@ -30,16 +31,22 @@ export const querySchema = z.object({
30
31
  * to skip properties and use the defaults for the rest.
31
32
  */
32
33
  export const createQuery = (input) => {
34
+ const { id, correlationid, time, source, type, data, datacontenttype, dataschema, ...extensions } = input;
35
+ const correlationIdWithFallback = correlationid ?? ulid();
36
+ if (Object.keys(extensions).length > 0) {
37
+ warnOnInvalidExtensionAttributeNames(extensions, correlationIdWithFallback, createQuery);
38
+ }
33
39
  const query = {
34
40
  specversion: '1.0',
35
- id: input.id ?? ulid(),
36
- correlationid: input.correlationid ?? ulid(),
37
- time: input.time ?? new Date().toISOString(),
38
- source: input.source,
39
- type: input.type,
40
- data: input.data,
41
- datacontenttype: input.datacontenttype ?? 'application/json',
42
- ...(input.dataschema && { dataschema: input.dataschema }),
41
+ id: id ?? ulid(),
42
+ correlationid: correlationIdWithFallback,
43
+ time: time ?? new Date().toISOString(),
44
+ source,
45
+ type,
46
+ data,
47
+ datacontenttype: datacontenttype ?? 'application/json',
48
+ ...(dataschema && { dataschema }),
49
+ ...extensions,
43
50
  };
44
51
  return query;
45
52
  };