@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
@@ -0,0 +1,7 @@
1
+ declare global {
2
+ interface Error {
3
+ cause?: unknown;
4
+ }
5
+ }
6
+ export {};
7
+ //# sourceMappingURL=_dnt.polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CACF;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/esm/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import "./_dnt.polyfills.js";
2
+ export * from './lib/env/getEnv.js';
1
3
  export * from './lib/eventBus/eventBus.js';
2
4
  export * from './lib/exception/exception.js';
3
5
  export * from './lib/exception/forbiddenException.js';
@@ -6,6 +8,7 @@ export * from './lib/exception/invalidInputException.js';
6
8
  export * from './lib/exception/notFoundException.js';
7
9
  export * from './lib/exception/unauthorizedException.js';
8
10
  export * from './lib/log/logFormatter.js';
11
+ export * from './lib/log/logTruncator.js';
9
12
  export * from './lib/log/logger.js';
10
13
  export * from './lib/log/logLevel.js';
11
14
  export * from './lib/log/options.js';
@@ -14,5 +17,6 @@ export * from './lib/message/event.js';
14
17
  export * from './lib/message/message.js';
15
18
  export * from './lib/message/query.js';
16
19
  export * from './lib/message/router.js';
20
+ export * from './lib/retry/withRetry.js';
17
21
  export * from './lib/tracing/withSpan.js';
18
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC;AACzD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC;AACzD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
package/esm/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import "./_dnt.polyfills.js";
2
+ export * from './lib/env/getEnv.js';
1
3
  export * from './lib/eventBus/eventBus.js';
2
4
  export * from './lib/exception/exception.js';
3
5
  export * from './lib/exception/forbiddenException.js';
@@ -6,6 +8,7 @@ export * from './lib/exception/invalidInputException.js';
6
8
  export * from './lib/exception/notFoundException.js';
7
9
  export * from './lib/exception/unauthorizedException.js';
8
10
  export * from './lib/log/logFormatter.js';
11
+ export * from './lib/log/logTruncator.js';
9
12
  export * from './lib/log/logger.js';
10
13
  export * from './lib/log/logLevel.js';
11
14
  export * from './lib/log/options.js';
@@ -14,4 +17,5 @@ export * from './lib/message/event.js';
14
17
  export * from './lib/message/message.js';
15
18
  export * from './lib/message/query.js';
16
19
  export * from './lib/message/router.js';
20
+ export * from './lib/retry/withRetry.js';
17
21
  export * from './lib/tracing/withSpan.js';
@@ -0,0 +1,15 @@
1
+ type GetEnvInput = {
2
+ variables: string[];
3
+ };
4
+ /**
5
+ * Get environment variables from the process.env object.
6
+ * Throws an exception if any of the variables are not defined
7
+ * and logs the missing variable names.
8
+ *
9
+ * @param variables - The list of environment variables to get
10
+ * @returns {Record<string, string>} Object of the environment variables
11
+ * @throws {GenericException} Thrown if any of the requested variables are not defined
12
+ */
13
+ export declare const getEnv: ({ variables, }: GetEnvInput) => Record<string, string>;
14
+ export {};
15
+ //# sourceMappingURL=getEnv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getEnv.d.ts","sourceRoot":"","sources":["../../../src/lib/env/getEnv.ts"],"names":[],"mappings":"AAIA,KAAK,WAAW,GAAG;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,GAAI,gBAEpB,WAAW,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CA2BrC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import process from 'node:process';
2
+ import { GenericException } from '../exception/genericException.js';
3
+ import { getLogger } from '../log/logger.js';
4
+ /**
5
+ * Get environment variables from the process.env object.
6
+ * Throws an exception if any of the variables are not defined
7
+ * and logs the missing variable names.
8
+ *
9
+ * @param variables - The list of environment variables to get
10
+ * @returns {Record<string, string>} Object of the environment variables
11
+ * @throws {GenericException} Thrown if any of the requested variables are not defined
12
+ */
13
+ export const getEnv = ({ variables, }) => {
14
+ const envVars = {};
15
+ const missingEnvVars = [];
16
+ for (const variable of variables) {
17
+ if (!process.env[variable]) {
18
+ missingEnvVars.push(variable);
19
+ }
20
+ envVars[variable] = process.env[variable];
21
+ }
22
+ if (missingEnvVars.length > 0) {
23
+ getLogger().error({
24
+ category: 'Nimbus',
25
+ message: 'Undefined environment variables',
26
+ data: {
27
+ undefinedVariables: missingEnvVars,
28
+ },
29
+ });
30
+ throw new GenericException('Undefined environment variables', {
31
+ undefinedVariables: missingEnvVars,
32
+ });
33
+ }
34
+ return envVars;
35
+ };
@@ -240,7 +240,6 @@ export declare class NimbusEventBus {
240
240
  private _processEvent;
241
241
  private _recordDeliveryMetrics;
242
242
  private _handleFinalFailure;
243
- private _calculateRetryDelay;
244
243
  /**
245
244
  * Validate the size of the event and return the size in bytes.
246
245
  *
@@ -1 +1 @@
1
- {"version":3,"file":"eventBus.d.ts","sourceRoot":"","sources":["../../../src/lib/eventBus/eventBus.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AA0CjD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,KAAK,IAAI;IACpD;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD;;OAEG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;CACjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAyB;IAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;gBACS,OAAO,CAAC,EAAE,qBAAqB;IAU3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACI,QAAQ,CAAC,MAAM,SAAS,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAqD1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDG;IACI,cAAc,CAAC,MAAM,SAAS,KAAK,EAAE,EACxC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,OAAO,GACV,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,IAAI;IAqCrC,OAAO,CAAC,aAAa;IAmFrB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,mBAAmB;IAwC3B,OAAO,CAAC,oBAAoB;IAW5B;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;CAmB7B;AAOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,aAAa,GACtB,MAAM,MAAM,EACZ,UAAU,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAC9C,IAEF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,WAAW,GAAI,OAAM,MAAkB,KAAG,cAStD,CAAC"}
1
+ {"version":3,"file":"eventBus.d.ts","sourceRoot":"","sources":["../../../src/lib/eventBus/eventBus.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AA2CjD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,KAAK,IAAI;IACpD;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD;;OAEG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;CACjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAyB;IAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;gBACS,OAAO,CAAC,EAAE,qBAAqB;IAU3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACI,QAAQ,CAAC,MAAM,SAAS,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAqD1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDG;IACI,cAAc,CAAC,MAAM,SAAS,KAAK,EAAE,EACxC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,OAAO,GACV,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,IAAI;IAqCrC,OAAO,CAAC,aAAa;IA4ErB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,mBAAmB;IAwC3B;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;CAmB7B;AAOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,aAAa,GACtB,MAAM,MAAM,EACZ,UAAU,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAC9C,IAEF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,WAAW,GAAI,OAAM,MAAkB,KAAG,cAStD,CAAC"}
@@ -2,6 +2,7 @@ import { metrics, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';
2
2
  import EventEmitter from 'node:events';
3
3
  import { GenericException } from '../exception/genericException.js';
4
4
  import { getLogger } from '../log/logger.js';
5
+ import { withRetry } from '../retry/withRetry.js';
5
6
  const tracer = trace.getTracer('nimbus');
6
7
  const meter = metrics.getMeter('nimbus');
7
8
  const eventsPublishedCounter = meter.createCounter('eventbus_events_published_total', {
@@ -301,35 +302,38 @@ export class NimbusEventBus {
301
302
  }),
302
303
  },
303
304
  }, async (span) => {
304
- let attempt = 0;
305
- while (attempt <= maxRetries) {
306
- try {
305
+ try {
306
+ await withRetry(async () => {
307
307
  await handler(event);
308
- this._recordDeliveryMetrics(metricLabels, 'success', startTime);
309
- span.end();
310
- return;
311
- }
312
- catch (error) {
313
- attempt++;
314
- if (attempt > maxRetries) {
315
- this._handleFinalFailure({
316
- error,
317
- event,
318
- span,
319
- metricLabels,
320
- startTime,
321
- retryConfig: {
322
- maxRetries,
323
- baseDelay,
324
- maxDelay,
325
- },
308
+ }, {
309
+ maxRetries,
310
+ initialDelayMs: baseDelay,
311
+ maxDelayMs: maxDelay,
312
+ jitterFactor: useJitter ? 0.1 : 0,
313
+ onRetry: ({ attempt, delayMs }) => {
314
+ retryAttemptsCounter.add(1, metricLabels);
315
+ span.addEvent('retry', {
316
+ attempt,
317
+ delay_ms: delayMs,
326
318
  });
327
- }
328
- retryAttemptsCounter.add(1, metricLabels);
329
- const delayMs = this._calculateRetryDelay(attempt, baseDelay, maxDelay, useJitter);
330
- span.addEvent('retry', { attempt, delay_ms: delayMs });
331
- await new Promise((resolve) => setTimeout(resolve, delayMs));
332
- }
319
+ },
320
+ });
321
+ this._recordDeliveryMetrics(metricLabels, 'success', startTime);
322
+ span.end();
323
+ }
324
+ catch (error) {
325
+ this._handleFinalFailure({
326
+ error,
327
+ event,
328
+ span,
329
+ metricLabels,
330
+ startTime,
331
+ retryConfig: {
332
+ maxRetries,
333
+ baseDelay,
334
+ maxDelay,
335
+ },
336
+ });
333
337
  }
334
338
  });
335
339
  }
@@ -355,11 +359,6 @@ export class NimbusEventBus {
355
359
  }
356
360
  throw exception;
357
361
  }
358
- _calculateRetryDelay(attempt, baseDelay, maxDelay, useJitter) {
359
- const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
360
- const jitter = useJitter ? Math.random() * delay * 0.1 : 0;
361
- return delay + jitter;
362
- }
363
362
  /**
364
363
  * Validate the size of the event and return the size in bytes.
365
364
  *
@@ -5,6 +5,6 @@ export declare class Exception extends Error {
5
5
  details?: Record<string, unknown>;
6
6
  statusCode?: number;
7
7
  constructor(name: string, message: string, details?: Record<string, unknown>, statusCode?: number);
8
- fromError(error: Error): Exception;
8
+ fromError(error: Error): this;
9
9
  }
10
10
  //# sourceMappingURL=exception.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exception.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/exception.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAGvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,CAAC,EAAE,MAAM;IAmBhB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS;CAM5C"}
1
+ {"version":3,"file":"exception.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/exception.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAGvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,CAAC,EAAE,MAAM;IAmBhB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAMvC"}
@@ -13,6 +13,6 @@ export declare class InvalidInputException extends Exception {
13
13
  *
14
14
  * @returns {InvalidInputException} The InvalidInputException.
15
15
  */
16
- fromZodError(error: ZodError): InvalidInputException;
16
+ fromZodError(error: ZodError): this;
17
17
  }
18
18
  //# sourceMappingURL=invalidInputException.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"invalidInputException.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/invalidInputException.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACpC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAS/D;;;;;;;OAOG;IACI,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,qBAAqB;CAa9D"}
1
+ {"version":3,"file":"invalidInputException.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/invalidInputException.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACpC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAS/D;;;;;;;OAOG;IACI,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAa7C"}
@@ -0,0 +1,96 @@
1
+ import type { LogInput } from './logger.js';
2
+ /**
3
+ * Truncates a {@link LogInput} before it is turned into a log record.
4
+ *
5
+ * Use with {@link setupLogger} via the `truncator` option, or provide a custom
6
+ * implementation. The built-in factory is {@link createLogTruncator}.
7
+ */
8
+ export type LogTruncator = (logInput: LogInput) => LogInput;
9
+ /**
10
+ * Options for {@link createLogTruncator}.
11
+ *
12
+ * All fields are optional; omitted fields use the built-in defaults.
13
+ */
14
+ export type LogTruncatorOptions = {
15
+ /**
16
+ * Maximum serialized byte size of `data` after structural truncation.
17
+ * If still over budget (or not JSON-serializable), `data` is replaced
18
+ * with a size marker. Defaults to 16_384 (16 KB).
19
+ */
20
+ maxBytes?: number;
21
+ /**
22
+ * Maximum number of array items kept inside `data` (also applies when
23
+ * converting `Map` / `Set` to arrays). Defaults to 50.
24
+ */
25
+ maxArrayItems?: number;
26
+ /**
27
+ * Maximum number of own enumerable keys kept on plain objects inside
28
+ * `data`. Defaults to 50.
29
+ */
30
+ maxObjectKeys?: number;
31
+ /**
32
+ * Maximum object nesting depth inside `data`, and maximum depth when
33
+ * walking `error.cause` / aggregate error chains.
34
+ * Defaults to 8. Values below 1 are clamped to 1 so root `data` stays
35
+ * an object.
36
+ */
37
+ maxDepth?: number;
38
+ /**
39
+ * Maximum length of `category`.
40
+ * Defaults to 50.
41
+ */
42
+ maxCategoryLength?: number;
43
+ /**
44
+ * Maximum length of `message` and `error.message`.
45
+ * Defaults to 200.
46
+ */
47
+ maxMessageLength?: number;
48
+ /**
49
+ * Maximum length of `error.stack`.
50
+ * Defaults to 200.
51
+ */
52
+ maxStackLength?: number;
53
+ /**
54
+ * Maximum length of string values inside `data`.
55
+ * Defaults to 200.
56
+ */
57
+ maxDataStringLength?: number;
58
+ };
59
+ /**
60
+ * Creates a {@link LogTruncator} that truncates each {@link LogInput} field
61
+ * separately (except `correlationId`, which is left untouched).
62
+ *
63
+ * - `message` / `category`: string length caps
64
+ * - `data`: structural truncation (arrays, objects, strings, depth, circular
65
+ * refs, common JS types) plus a byte-size cliff that replaces oversized or
66
+ * unserializable payloads with a size marker
67
+ * - `error`: stays `Error`-shaped; truncates `message` / `stack`, copies
68
+ * enumerable custom fields, and walks `cause` / aggregate errors up to
69
+ * `maxDepth`
70
+ *
71
+ * @param options - Optional limits; omitted fields use built-in defaults.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * import { createLogTruncator, setupLogger } from '@nimbus-cqrs/core';
76
+ *
77
+ * setupLogger({
78
+ * truncator: createLogTruncator(),
79
+ * });
80
+ *
81
+ * setupLogger({
82
+ * truncator: createLogTruncator({
83
+ * maxBytes: 8_192,
84
+ * maxArrayItems: 50,
85
+ * maxObjectKeys: 50,
86
+ * maxDepth: 8,
87
+ * maxCategoryLength: 50,
88
+ * maxMessageLength: 100,
89
+ * maxStackLength: 200,
90
+ * maxDataStringLength: 200,
91
+ * }),
92
+ * });
93
+ * ```
94
+ */
95
+ export declare const createLogTruncator: (options?: LogTruncatorOptions) => LogTruncator;
96
+ //# sourceMappingURL=logTruncator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logTruncator.d.ts","sourceRoot":"","sources":["../../../src/lib/log/logTruncator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAsDF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,kBAAkB,GAC3B,UAAS,mBAAwB,KAClC,YA+TF,CAAC"}
@@ -0,0 +1,254 @@
1
+ const DEFAULT_MAX_BYTES = 16_384;
2
+ const DEFAULT_MAX_ARRAY_ITEMS = 50;
3
+ const DEFAULT_MAX_OBJECT_KEYS = 50;
4
+ const DEFAULT_MAX_DEPTH = 8;
5
+ const DEFAULT_MAX_CATEGORY_LENGTH = 50;
6
+ const DEFAULT_MAX_MESSAGE_LENGTH = 200;
7
+ const DEFAULT_MAX_STACK_LENGTH = 200;
8
+ const DEFAULT_MAX_DATA_STRING_LENGTH = 200;
9
+ const serializedByteSize = (value) => {
10
+ try {
11
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength;
12
+ }
13
+ catch {
14
+ return undefined;
15
+ }
16
+ };
17
+ const TRUNCATED_STRING_SUFFIX = ' [... __truncated]';
18
+ const truncateString = (value, maxLength) => {
19
+ if (value.length <= maxLength) {
20
+ return value;
21
+ }
22
+ return `${value.slice(0, maxLength)}${TRUNCATED_STRING_SUFFIX}`;
23
+ };
24
+ /**
25
+ * Creates a {@link LogTruncator} that truncates each {@link LogInput} field
26
+ * separately (except `correlationId`, which is left untouched).
27
+ *
28
+ * - `message` / `category`: string length caps
29
+ * - `data`: structural truncation (arrays, objects, strings, depth, circular
30
+ * refs, common JS types) plus a byte-size cliff that replaces oversized or
31
+ * unserializable payloads with a size marker
32
+ * - `error`: stays `Error`-shaped; truncates `message` / `stack`, copies
33
+ * enumerable custom fields, and walks `cause` / aggregate errors up to
34
+ * `maxDepth`
35
+ *
36
+ * @param options - Optional limits; omitted fields use built-in defaults.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { createLogTruncator, setupLogger } from '@nimbus-cqrs/core';
41
+ *
42
+ * setupLogger({
43
+ * truncator: createLogTruncator(),
44
+ * });
45
+ *
46
+ * setupLogger({
47
+ * truncator: createLogTruncator({
48
+ * maxBytes: 8_192,
49
+ * maxArrayItems: 50,
50
+ * maxObjectKeys: 50,
51
+ * maxDepth: 8,
52
+ * maxCategoryLength: 50,
53
+ * maxMessageLength: 100,
54
+ * maxStackLength: 200,
55
+ * maxDataStringLength: 200,
56
+ * }),
57
+ * });
58
+ * ```
59
+ */
60
+ export const createLogTruncator = (options = {}) => {
61
+ // Clamp so root `data` stays an object and string/array limits stay usable.
62
+ const maxBytes = Math.max(0, options.maxBytes ?? DEFAULT_MAX_BYTES);
63
+ const maxArrayItems = Math.max(0, options.maxArrayItems ?? DEFAULT_MAX_ARRAY_ITEMS);
64
+ const maxObjectKeys = Math.max(0, options.maxObjectKeys ?? DEFAULT_MAX_OBJECT_KEYS);
65
+ const maxDepth = Math.max(1, options.maxDepth ?? DEFAULT_MAX_DEPTH);
66
+ const maxCategoryLength = Math.max(0, options.maxCategoryLength ?? DEFAULT_MAX_CATEGORY_LENGTH);
67
+ const maxMessageLength = Math.max(0, options.maxMessageLength ?? DEFAULT_MAX_MESSAGE_LENGTH);
68
+ const maxStackLength = Math.max(0, options.maxStackLength ?? DEFAULT_MAX_STACK_LENGTH);
69
+ const maxDataStringLength = Math.max(0, options.maxDataStringLength ?? DEFAULT_MAX_DATA_STRING_LENGTH);
70
+ const truncateDataValue = (value, depth, seen) => {
71
+ if (typeof value === 'bigint') {
72
+ return truncateString(`${value}n`, maxDataStringLength);
73
+ }
74
+ if (value === null || typeof value !== 'object') {
75
+ if (typeof value === 'string' &&
76
+ value.length > maxDataStringLength) {
77
+ return truncateString(value, maxDataStringLength);
78
+ }
79
+ return value;
80
+ }
81
+ if (seen.has(value)) {
82
+ return '[Circular]';
83
+ }
84
+ if (depth >= maxDepth) {
85
+ return '[Max depth]';
86
+ }
87
+ seen.add(value);
88
+ try {
89
+ if (value instanceof Date) {
90
+ return truncateString(value.toISOString(), maxDataStringLength);
91
+ }
92
+ if (value instanceof RegExp) {
93
+ return truncateString(value.toString(), maxDataStringLength);
94
+ }
95
+ if (value instanceof ArrayBuffer) {
96
+ return {
97
+ __truncated: true,
98
+ reason: 'arrayBuffer',
99
+ byteLength: value.byteLength,
100
+ };
101
+ }
102
+ if (ArrayBuffer.isView(value)) {
103
+ return {
104
+ __truncated: true,
105
+ reason: 'typedArray',
106
+ type: value.constructor.name,
107
+ byteLength: value.byteLength,
108
+ };
109
+ }
110
+ if (value instanceof Error) {
111
+ return truncateErrorAsData(value, depth, seen);
112
+ }
113
+ if (value instanceof Map) {
114
+ return truncateDataValue(Array.from(value.entries()), depth + 1, seen);
115
+ }
116
+ if (value instanceof Set) {
117
+ return truncateDataValue(Array.from(value.values()), depth + 1, seen);
118
+ }
119
+ if (Array.isArray(value)) {
120
+ if (value.length > maxArrayItems) {
121
+ return [
122
+ ...value
123
+ .slice(0, maxArrayItems)
124
+ .map((item) => truncateDataValue(item, depth + 1, seen)),
125
+ {
126
+ __truncated: true,
127
+ omittedCount: value.length - maxArrayItems,
128
+ },
129
+ ];
130
+ }
131
+ return value.map((item) => truncateDataValue(item, depth + 1, seen));
132
+ }
133
+ const entries = Object.entries(value);
134
+ const limited = entries.length > maxObjectKeys
135
+ ? entries.slice(0, maxObjectKeys)
136
+ : entries;
137
+ const result = {};
138
+ for (const [key, entry] of limited) {
139
+ result[key] = truncateDataValue(entry, depth + 1, seen);
140
+ }
141
+ if (entries.length > maxObjectKeys) {
142
+ result.__truncated = true;
143
+ result.omittedKeyCount = entries.length - maxObjectKeys;
144
+ }
145
+ return result;
146
+ }
147
+ finally {
148
+ // Recursion stack: allow shared refs, still detect true cycles.
149
+ seen.delete(value);
150
+ }
151
+ };
152
+ const truncateErrorAsData = (error, depth, seen) => {
153
+ const result = {
154
+ name: error.name,
155
+ message: truncateString(error.message, maxMessageLength),
156
+ };
157
+ if (typeof error.stack === 'string') {
158
+ result.stack = truncateString(error.stack, maxStackLength);
159
+ }
160
+ for (const [key, entry] of Object.entries(error)) {
161
+ if (key === 'name' ||
162
+ key === 'message' ||
163
+ key === 'stack' ||
164
+ key === 'cause' ||
165
+ key === 'errors') {
166
+ continue;
167
+ }
168
+ result[key] = truncateDataValue(entry, depth + 1, seen);
169
+ }
170
+ if ('cause' in error && error.cause !== undefined) {
171
+ result.cause = truncateDataValue(error.cause, depth + 1, seen);
172
+ }
173
+ if (typeof AggregateError !== 'undefined' &&
174
+ error instanceof AggregateError) {
175
+ result.errors = truncateDataValue(error.errors, depth + 1, seen);
176
+ }
177
+ return result;
178
+ };
179
+ const truncateData = (data) => {
180
+ const truncated = truncateDataValue(data, 0, new WeakSet());
181
+ const byteSize = serializedByteSize(truncated);
182
+ if (byteSize !== undefined && byteSize <= maxBytes) {
183
+ return truncated;
184
+ }
185
+ return {
186
+ __truncated: true,
187
+ reason: byteSize === undefined ? 'unserializable' : 'size',
188
+ ...(byteSize !== undefined ? { serializedByteSize: byteSize } : {}),
189
+ maxBytes,
190
+ };
191
+ };
192
+ const copyCustomErrorFields = (source, target, depth) => {
193
+ for (const [key, entry] of Object.entries(source)) {
194
+ if (key === 'name' ||
195
+ key === 'message' ||
196
+ key === 'stack' ||
197
+ key === 'cause' ||
198
+ key === 'errors') {
199
+ continue;
200
+ }
201
+ target[key] =
202
+ entry instanceof Error
203
+ ? truncateError(entry, depth + 1)
204
+ : truncateDataValue(entry, depth + 1, new WeakSet());
205
+ }
206
+ };
207
+ const truncateError = (error, depth) => {
208
+ if (depth >= maxDepth) {
209
+ const maxDepthError = new Error('[Max depth]');
210
+ maxDepthError.name = error.name;
211
+ return maxDepthError;
212
+ }
213
+ const message = truncateString(error.message, maxMessageLength);
214
+ let truncated;
215
+ if (typeof AggregateError !== 'undefined' &&
216
+ error instanceof AggregateError) {
217
+ truncated = new AggregateError(error.errors.map((item) => item instanceof Error
218
+ ? truncateError(item, depth + 1)
219
+ : truncateDataValue(item, depth + 1, new WeakSet())), message);
220
+ }
221
+ else {
222
+ truncated = new Error(message);
223
+ }
224
+ truncated.name = error.name;
225
+ if (typeof error.stack === 'string') {
226
+ truncated.stack = truncateString(error.stack, maxStackLength);
227
+ }
228
+ if ('cause' in error && error.cause !== undefined) {
229
+ truncated.cause = error.cause instanceof Error
230
+ ? truncateError(error.cause, depth + 1)
231
+ : truncateDataValue(error.cause, depth + 1, new WeakSet());
232
+ }
233
+ copyCustomErrorFields(error, truncated, depth);
234
+ return truncated;
235
+ };
236
+ return (logInput) => {
237
+ const truncated = {
238
+ message: truncateString(logInput.message, maxMessageLength),
239
+ };
240
+ if (logInput.category !== undefined) {
241
+ truncated.category = truncateString(logInput.category, maxCategoryLength);
242
+ }
243
+ if (logInput.data !== undefined) {
244
+ truncated.data = truncateData(logInput.data);
245
+ }
246
+ if (logInput.error !== undefined) {
247
+ truncated.error = truncateError(logInput.error, 0);
248
+ }
249
+ if (logInput.correlationId !== undefined) {
250
+ truncated.correlationId = logInput.correlationId;
251
+ }
252
+ return truncated;
253
+ };
254
+ };