@pristine-ts/common 2.0.4 → 2.0.5

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 (120) hide show
  1. package/dist/lib/cjs/contexts/event-context.js.map +1 -1
  2. package/dist/lib/cjs/decorators/traced.decorator.js +38 -2
  3. package/dist/lib/cjs/decorators/traced.decorator.js.map +1 -1
  4. package/dist/lib/cjs/errors/bad-request.error.js +15 -0
  5. package/dist/lib/cjs/errors/bad-request.error.js.map +1 -0
  6. package/dist/lib/cjs/errors/config.error.js +20 -0
  7. package/dist/lib/cjs/errors/config.error.js.map +1 -0
  8. package/dist/lib/cjs/errors/conflict.error.js +15 -0
  9. package/dist/lib/cjs/errors/conflict.error.js.map +1 -0
  10. package/dist/lib/cjs/errors/errors.js +14 -1
  11. package/dist/lib/cjs/errors/errors.js.map +1 -1
  12. package/dist/lib/cjs/errors/exit-code.enum.js +50 -0
  13. package/dist/lib/cjs/errors/exit-code.enum.js.map +1 -0
  14. package/dist/lib/cjs/errors/forbidden.error.js +15 -0
  15. package/dist/lib/cjs/errors/forbidden.error.js.map +1 -0
  16. package/dist/lib/cjs/errors/internal.error.js +19 -0
  17. package/dist/lib/cjs/errors/internal.error.js.map +1 -0
  18. package/dist/lib/cjs/errors/not-found.error.js +15 -0
  19. package/dist/lib/cjs/errors/not-found.error.js.map +1 -0
  20. package/dist/lib/cjs/errors/pristine-error-code.enum.js +37 -0
  21. package/dist/lib/cjs/errors/pristine-error-code.enum.js.map +1 -0
  22. package/dist/lib/cjs/errors/pristine-error-kind.enum.js +29 -0
  23. package/dist/lib/cjs/errors/pristine-error-kind.enum.js.map +1 -0
  24. package/dist/lib/cjs/errors/pristine-error-options.interface.js +3 -0
  25. package/dist/lib/cjs/errors/pristine-error-options.interface.js.map +1 -0
  26. package/dist/lib/cjs/errors/pristine.error.js +109 -0
  27. package/dist/lib/cjs/errors/pristine.error.js.map +1 -0
  28. package/dist/lib/cjs/errors/unauthorized.error.js +15 -0
  29. package/dist/lib/cjs/errors/unauthorized.error.js.map +1 -0
  30. package/dist/lib/cjs/errors/usage.error.js +18 -0
  31. package/dist/lib/cjs/errors/usage.error.js.map +1 -0
  32. package/dist/lib/cjs/errors/validation.error.js +15 -0
  33. package/dist/lib/cjs/errors/validation.error.js.map +1 -0
  34. package/dist/lib/cjs/managers/event-context.manager.js +9 -0
  35. package/dist/lib/cjs/managers/event-context.manager.js.map +1 -1
  36. package/dist/lib/cjs/models/models.js +1 -0
  37. package/dist/lib/cjs/models/models.js.map +1 -1
  38. package/dist/lib/cjs/models/span-lifecycle-owner.interface.js +3 -0
  39. package/dist/lib/cjs/models/span-lifecycle-owner.interface.js.map +1 -0
  40. package/dist/lib/cjs/models/span.model.js.map +1 -1
  41. package/dist/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  42. package/dist/lib/cjs/utils/utils.js +0 -1
  43. package/dist/lib/cjs/utils/utils.js.map +1 -1
  44. package/dist/lib/esm/contexts/event-context.js.map +1 -1
  45. package/dist/lib/esm/decorators/traced.decorator.js +38 -2
  46. package/dist/lib/esm/decorators/traced.decorator.js.map +1 -1
  47. package/dist/lib/esm/errors/bad-request.error.js +11 -0
  48. package/dist/lib/esm/errors/bad-request.error.js.map +1 -0
  49. package/dist/lib/esm/errors/config.error.js +16 -0
  50. package/dist/lib/esm/errors/config.error.js.map +1 -0
  51. package/dist/lib/esm/errors/conflict.error.js +11 -0
  52. package/dist/lib/esm/errors/conflict.error.js.map +1 -0
  53. package/dist/lib/esm/errors/errors.js +14 -1
  54. package/dist/lib/esm/errors/errors.js.map +1 -1
  55. package/dist/lib/esm/errors/exit-code.enum.js +47 -0
  56. package/dist/lib/esm/errors/exit-code.enum.js.map +1 -0
  57. package/dist/lib/esm/errors/forbidden.error.js +11 -0
  58. package/dist/lib/esm/errors/forbidden.error.js.map +1 -0
  59. package/dist/lib/esm/errors/internal.error.js +15 -0
  60. package/dist/lib/esm/errors/internal.error.js.map +1 -0
  61. package/dist/lib/esm/errors/not-found.error.js +11 -0
  62. package/dist/lib/esm/errors/not-found.error.js.map +1 -0
  63. package/dist/lib/esm/errors/pristine-error-code.enum.js +34 -0
  64. package/dist/lib/esm/errors/pristine-error-code.enum.js.map +1 -0
  65. package/dist/lib/esm/errors/pristine-error-kind.enum.js +26 -0
  66. package/dist/lib/esm/errors/pristine-error-kind.enum.js.map +1 -0
  67. package/dist/lib/esm/errors/pristine-error-options.interface.js +2 -0
  68. package/dist/lib/esm/errors/pristine-error-options.interface.js.map +1 -0
  69. package/dist/lib/esm/errors/pristine.error.js +105 -0
  70. package/dist/lib/esm/errors/pristine.error.js.map +1 -0
  71. package/dist/lib/esm/errors/unauthorized.error.js +11 -0
  72. package/dist/lib/esm/errors/unauthorized.error.js.map +1 -0
  73. package/dist/lib/esm/errors/usage.error.js +14 -0
  74. package/dist/lib/esm/errors/usage.error.js.map +1 -0
  75. package/dist/lib/esm/errors/validation.error.js +11 -0
  76. package/dist/lib/esm/errors/validation.error.js.map +1 -0
  77. package/dist/lib/esm/managers/event-context.manager.js +9 -0
  78. package/dist/lib/esm/managers/event-context.manager.js.map +1 -1
  79. package/dist/lib/esm/models/models.js +1 -0
  80. package/dist/lib/esm/models/models.js.map +1 -1
  81. package/dist/lib/esm/models/span-lifecycle-owner.interface.js +2 -0
  82. package/dist/lib/esm/models/span-lifecycle-owner.interface.js.map +1 -0
  83. package/dist/lib/esm/models/span.model.js.map +1 -1
  84. package/dist/lib/esm/tsconfig.tsbuildinfo +1 -1
  85. package/dist/lib/esm/utils/utils.js +0 -1
  86. package/dist/lib/esm/utils/utils.js.map +1 -1
  87. package/dist/types/contexts/event-context.d.ts +11 -3
  88. package/dist/types/errors/bad-request.error.d.ts +8 -0
  89. package/dist/types/errors/config.error.d.ts +13 -0
  90. package/dist/types/errors/conflict.error.d.ts +8 -0
  91. package/dist/types/errors/errors.d.ts +14 -1
  92. package/dist/types/errors/exit-code.enum.d.ts +45 -0
  93. package/dist/types/errors/forbidden.error.d.ts +8 -0
  94. package/dist/types/errors/internal.error.d.ts +12 -0
  95. package/dist/types/errors/not-found.error.d.ts +8 -0
  96. package/dist/types/errors/pristine-error-code.enum.d.ts +32 -0
  97. package/dist/types/errors/pristine-error-kind.enum.d.ts +24 -0
  98. package/dist/types/errors/pristine-error-options.interface.d.ts +59 -0
  99. package/dist/types/errors/pristine.error.d.ts +78 -0
  100. package/dist/types/errors/unauthorized.error.d.ts +8 -0
  101. package/dist/types/errors/usage.error.d.ts +11 -0
  102. package/dist/types/errors/validation.error.d.ts +8 -0
  103. package/dist/types/interfaces/module.interface.d.ts +26 -0
  104. package/dist/types/interfaces/tracing-manager.interface.d.ts +3 -3
  105. package/dist/types/managers/event-context.manager.d.ts +4 -0
  106. package/dist/types/models/models.d.ts +1 -0
  107. package/dist/types/models/span-lifecycle-owner.interface.d.ts +11 -0
  108. package/dist/types/models/span.model.d.ts +2 -10
  109. package/dist/types/utils/utils.d.ts +0 -1
  110. package/package.json +2 -2
  111. package/dist/lib/cjs/errors/loggable.error.js +0 -19
  112. package/dist/lib/cjs/errors/loggable.error.js.map +0 -1
  113. package/dist/lib/cjs/utils/span-runner.js +0 -117
  114. package/dist/lib/cjs/utils/span-runner.js.map +0 -1
  115. package/dist/lib/esm/errors/loggable.error.js +0 -15
  116. package/dist/lib/esm/errors/loggable.error.js.map +0 -1
  117. package/dist/lib/esm/utils/span-runner.js +0 -113
  118. package/dist/lib/esm/utils/span-runner.js.map +0 -1
  119. package/dist/types/errors/loggable.error.d.ts +0 -8
  120. package/dist/types/utils/span-runner.d.ts +0 -55
@@ -0,0 +1,8 @@
1
+ import { PristineError } from "./pristine.error";
2
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
3
+ type StandardOptions = Omit<PristineErrorOptions, "httpStatus" | "exitCode" | "kind">;
4
+ /** 403. Caller is authenticated but lacks permission. CLI exit `ExitCode.NoPermission` (77). */
5
+ export declare class ForbiddenError extends PristineError {
6
+ constructor(message?: string, options?: StandardOptions);
7
+ }
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import { PristineError } from "./pristine.error";
2
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
3
+ type StandardOptions = Omit<PristineErrorOptions, "httpStatus" | "exitCode" | "kind">;
4
+ /**
5
+ * Catch-all for framework/system bugs that shouldn't be exposed verbatim. 500.
6
+ * CLI exit `ExitCode.Software` (70). `SystemError` triggers message sanitization in
7
+ * production mode.
8
+ */
9
+ export declare class InternalError extends PristineError {
10
+ constructor(message?: string, options?: StandardOptions);
11
+ }
12
+ export {};
@@ -0,0 +1,8 @@
1
+ import { PristineError } from "./pristine.error";
2
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
3
+ type StandardOptions = Omit<PristineErrorOptions, "httpStatus" | "exitCode" | "kind">;
4
+ /** 404. Resource doesn't exist. CLI exit `ExitCode.Error` (1). */
5
+ export declare class NotFoundError extends PristineError {
6
+ constructor(message: string, options?: StandardOptions);
7
+ }
8
+ export {};
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Standard error-code catalog used across the framework. Each value is a `SCREAMING_SNAKE_CASE`
3
+ * slug surfaced in the HTTP response body (`{"code": ...}`) and on CLI stderr (`✗ CODE: ...`).
4
+ *
5
+ * **Use the enum members for framework-standard cases.** Consumers can add their own
6
+ * domain-specific codes by passing a plain string — `PristineErrorOptions.code` is typed
7
+ * `PristineErrorCode | string` so both the enum and free-form strings get autocomplete-
8
+ * friendly type checking.
9
+ *
10
+ * ```ts
11
+ * throw new PristineError("Token expired", {
12
+ * code: "TOKEN_EXPIRED", // consumer-defined code
13
+ * httpStatus: 401,
14
+ * });
15
+ *
16
+ * throw new PristineError("Item missing", {
17
+ * code: PristineErrorCode.NotFound, // framework-standard code
18
+ * httpStatus: 404,
19
+ * });
20
+ * ```
21
+ */
22
+ export declare enum PristineErrorCode {
23
+ BadRequest = "BAD_REQUEST",
24
+ Unauthorized = "UNAUTHORIZED",
25
+ Forbidden = "FORBIDDEN",
26
+ NotFound = "NOT_FOUND",
27
+ Conflict = "CONFLICT",
28
+ ValidationFailed = "VALIDATION_FAILED",
29
+ ConfigError = "CONFIG_ERROR",
30
+ UsageError = "USAGE_ERROR",
31
+ InternalError = "INTERNAL_ERROR"
32
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Categorizes a `PristineError` by who caused it. Replaces the older `expected: boolean`
3
+ * field, whose meaning ("expected by whom?") wasn't self-explanatory.
4
+ *
5
+ * The kind drives how the channel reporters render the error in production mode:
6
+ *
7
+ * - `UserError`: caller did something wrong. Message is safe to expose verbatim;
8
+ * structured details surface as-is. HTTP responses use the carried `httpStatus`
9
+ * (typically 4xx). CLI stderr shows the message and details.
10
+ *
11
+ * - `SystemError`: framework or downstream bug — not the caller's fault. In production
12
+ * mode the message is replaced with a generic "Internal Server Error" / "Internal Error"
13
+ * so internal details never leak to clients. Stack and cause chain are still logged
14
+ * internally via the LogHandler for operators. In development mode (`PRISTINE_ENV=dev`)
15
+ * the full message surfaces.
16
+ *
17
+ * Default is `UserError` — most thrown errors in framework and application code are caller-
18
+ * induced. `PristineError.from(unknown)` marks raw `Error` and non-Error throws as
19
+ * `SystemError` since they didn't opt into the typed contract.
20
+ */
21
+ export declare enum PristineErrorKind {
22
+ UserError = "user-error",
23
+ SystemError = "system-error"
24
+ }
@@ -0,0 +1,59 @@
1
+ import { ExitCode } from "./exit-code.enum";
2
+ import { PristineErrorCode } from "./pristine-error-code.enum";
3
+ import { PristineErrorKind } from "./pristine-error-kind.enum";
4
+ /**
5
+ * Options carried by every `PristineError`. All fields optional — defaults give a sensible
6
+ * "user error with 500 / exit 1" shape when none are set.
7
+ */
8
+ export interface PristineErrorOptions {
9
+ /**
10
+ * Stable slug for the error category. Surfaces in HTTP response bodies and CLI stderr;
11
+ * safe to use as the join key for i18n, log queries, and alerting rules.
12
+ *
13
+ * Accepts the framework's `PristineErrorCode` enum for standard categories, or any
14
+ * `SCREAMING_SNAKE_CASE` string for domain-specific codes (`"TOKEN_EXPIRED"`,
15
+ * `"STRIPE_CARD_DECLINED"`). The enum is the catalog of well-known codes; strings are
16
+ * the extensibility hatch.
17
+ *
18
+ * Defaults to `PristineErrorCode.InternalError` at render time when absent.
19
+ */
20
+ code?: PristineErrorCode | string;
21
+ /**
22
+ * HTTP status when this error reaches the HTTP boundary. Omit when the error has no
23
+ * natural HTTP semantics (e.g. a CLI-only `ConfigError`) — the responder will fall back
24
+ * to 500.
25
+ */
26
+ httpStatus?: number;
27
+ /**
28
+ * Process exit code when this error reaches the CLI boundary. Accepts the framework's
29
+ * `ExitCode` enum (sysexits.h-aligned) or any raw number for custom codes. Omit to fall
30
+ * back to `ExitCode.Error` (1) for user errors and `ExitCode.Software` (70) for system
31
+ * errors.
32
+ */
33
+ exitCode?: ExitCode | number;
34
+ /**
35
+ * Underlying error this one wraps. Uses the standard `Error.cause` slot (Node 16.9+),
36
+ * so any tooling that knows the standard cause chain works automatically. Walked by
37
+ * `PristineError.from` to preserve the original error type when normalizing.
38
+ */
39
+ cause?: Error;
40
+ /**
41
+ * Structured fields safe to surface in the response body / stderr. Per-error-class
42
+ * schema — e.g. a `NotFoundError` may carry `{ resource, id }`. Surfaced to users
43
+ * only when `kind === UserError` (the default) or `mode === development`.
44
+ */
45
+ details?: Record<string, unknown>;
46
+ /**
47
+ * Categorizes the error by who caused it. Drives how the message is rendered in
48
+ * production mode:
49
+ *
50
+ * - `UserError` (default): caller did something wrong. Message surfaced verbatim;
51
+ * details exposed; production responses include both.
52
+ *
53
+ * - `SystemError`: framework/system bug, not the caller's fault. Production responses
54
+ * replace the message with a generic "Internal Server Error" / "Internal Error" and
55
+ * omit details + stack. The raw error is still logged via the LogHandler for
56
+ * operators. `PristineError.from` marks unknown throws as `SystemError`.
57
+ */
58
+ kind?: PristineErrorKind;
59
+ }
@@ -0,0 +1,78 @@
1
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
2
+ /**
3
+ * Single error base for the entire framework. Replaces the old `LoggableError` +
4
+ * `HttpError` + ad-hoc subclass hierarchy.
5
+ *
6
+ * **What it gives you**:
7
+ * - A structured `options` bag (`code`, `httpStatus`, `exitCode`, `details`, `cause`,
8
+ * `kind`) read by both the HTTP and CLI channel reporters.
9
+ * - Automatic `error.name = ClassName` for subclasses.
10
+ * - Automatic prototype-chain fix via `new.target.prototype` — subclasses never need to
11
+ * repeat the `Object.setPrototypeOf(this, FooError.prototype)` incantation, AND
12
+ * `instanceof` works correctly for direct/standard-library/custom subclasses at any
13
+ * depth (verified by spec).
14
+ * - Standard `Error.cause` propagation (Node 16.9+ native).
15
+ *
16
+ * **Subclass form** when a named class makes `instanceof` checks read better:
17
+ *
18
+ * ```ts
19
+ * export class TokenExpiredError extends UnauthorizedError {
20
+ * constructor(tokenId: string) {
21
+ * super("The token has expired", {
22
+ * code: "TOKEN_EXPIRED",
23
+ * details: { tokenId },
24
+ * });
25
+ * }
26
+ * }
27
+ * // ...
28
+ * try { ... }
29
+ * catch (e) { if (e instanceof TokenExpiredError) ... } // works.
30
+ * ```
31
+ *
32
+ * **Direct form** when the call site self-documents:
33
+ *
34
+ * ```ts
35
+ * throw new PristineError(`User '${id}' not found`, {
36
+ * code: PristineErrorCode.NotFound,
37
+ * httpStatus: 404,
38
+ * details: { resource: "User", id },
39
+ * });
40
+ * ```
41
+ *
42
+ * **Re-throw with enrichment** when catching, adding context, and re-throwing. Use the
43
+ * standard `cause` chain rather than mutating the original — this preserves the original
44
+ * error's identity for tooling that walks `error.cause`:
45
+ *
46
+ * ```ts
47
+ * try { await dispatcher.dispatch(event); }
48
+ * catch (cause) {
49
+ * throw new PristineError("Event dispatch failed", {
50
+ * code: "EVENT_DISPATCH_FAILED",
51
+ * kind: PristineErrorKind.SystemError,
52
+ * cause,
53
+ * details: { eventId: event.id },
54
+ * });
55
+ * }
56
+ * ```
57
+ */
58
+ export declare class PristineError extends Error {
59
+ readonly options: PristineErrorOptions;
60
+ constructor(message: string, options?: PristineErrorOptions);
61
+ /**
62
+ * Normalizes any thrown value into a `PristineError`. The chokepoint that every channel
63
+ * reporter funnels through before rendering, so the reporters never need to handle
64
+ * unknown shapes.
65
+ *
66
+ * - `PristineError` instances pass through unchanged.
67
+ * - `Error` instances are wrapped with `kind: SystemError` and propagated as `cause` —
68
+ * the wrapper preserves the original message and stack for `mode === Development`
69
+ * rendering.
70
+ * - Anything else (strings, numbers, `throw {someObject}`) is coerced via `String(...)`
71
+ * into a message with `kind: SystemError`.
72
+ *
73
+ * The standard `Error.cause` chain is preserved: if the input has a `cause`, it stays
74
+ * on the wrapper (which itself has the input as its cause), so a debugger walking
75
+ * `error.cause.cause.cause` sees the full history.
76
+ */
77
+ static from(error: unknown): PristineError;
78
+ }
@@ -0,0 +1,8 @@
1
+ import { PristineError } from "./pristine.error";
2
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
3
+ type StandardOptions = Omit<PristineErrorOptions, "httpStatus" | "exitCode" | "kind">;
4
+ /** 401. Caller is not authenticated. CLI exit `ExitCode.NoPermission` (77). */
5
+ export declare class UnauthorizedError extends PristineError {
6
+ constructor(message?: string, options?: StandardOptions);
7
+ }
8
+ export {};
@@ -0,0 +1,11 @@
1
+ import { PristineError } from "./pristine.error";
2
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
3
+ type StandardOptions = Omit<PristineErrorOptions, "httpStatus" | "exitCode" | "kind">;
4
+ /**
5
+ * CLI-only — bad command-line usage (wrong flag, missing required arg, unknown command).
6
+ * No `httpStatus`. CLI exit `ExitCode.Usage` (64).
7
+ */
8
+ export declare class UsageError extends PristineError {
9
+ constructor(message: string, options?: StandardOptions);
10
+ }
11
+ export {};
@@ -0,0 +1,8 @@
1
+ import { PristineError } from "./pristine.error";
2
+ import { PristineErrorOptions } from "./pristine-error-options.interface";
3
+ type StandardOptions = Omit<PristineErrorOptions, "httpStatus" | "exitCode" | "kind">;
4
+ /** 422. Input parsed but failed semantic validation. CLI exit `ExitCode.DataError` (65). */
5
+ export declare class ValidationError extends PristineError {
6
+ constructor(message: string, options?: StandardOptions);
7
+ }
8
+ export {};
@@ -25,6 +25,32 @@ export interface ModuleInterface {
25
25
  * for the module.
26
26
  */
27
27
  configurationDefinitions?: ConfigurationDefinition[];
28
+ /**
29
+ * Default values this module wants applied to configuration keys — typically keys owned
30
+ * by **other** modules. Use it when a context-providing module (e.g. `CliModule`) has an
31
+ * opinion about how a dependency-module's keys should be configured by default.
32
+ *
33
+ * Precedence in the resolution chain:
34
+ * 1. Explicit overrides passed to `kernel.start()` — beats this.
35
+ * 2. `pristine.config.ts:config` block — beats this.
36
+ * 3. **`configDefaults`** (this field).
37
+ * 4. The owning `configurationDefinition.defaultResolvers` chain — loses to this.
38
+ * 5. The owning `configurationDefinition.defaultValue` — loses to this.
39
+ *
40
+ * Not to be confused with `configurationDefinition.defaultValue`: that's the
41
+ * owning-module's hard fallback when nothing else fires; `configDefaults` is a
42
+ * different module expressing a preferred value above the resolver chain.
43
+ *
44
+ * Validation:
45
+ * - **Unknown key** (not declared by any module's `configurationDefinitions` in the
46
+ * graph) → kernel throws at boot, naming the source module + key.
47
+ * - **Two modules disagree** on the same key's `configDefaults` → kernel throws at
48
+ * registration time, naming both module keynames.
49
+ *
50
+ * Keys are configuration parameter names (e.g. `"pristine.logging.consoleLoggerOutputMode"`),
51
+ * not arbitrary strings.
52
+ */
53
+ configDefaults?: Record<string, unknown>;
28
54
  /**
29
55
  * This function lets you run code on the module initialization. Be careful the tags and the router are not created yet.
30
56
  * @param container
@@ -4,9 +4,9 @@ import { Trace } from "../models/trace.model";
4
4
  * This interface specifies what a tracing manager should implement.
5
5
  *
6
6
  * Lives in `@pristine-ts/common` so any package can declare a `TracingManagerInterface`
7
- * dependency or use the `@traced` decorator / `spanRunner` helper without taking a
8
- * direct dep on `@pristine-ts/telemetry`. The concrete implementation
9
- * (`TracingManager`, plus the tracers that consume traces) still lives in telemetry.
7
+ * dependency or use the `@traced` decorator without taking a direct dep on
8
+ * `@pristine-ts/telemetry`. The concrete implementation (`TracingManager`, plus the
9
+ * tracers that consume traces) still lives in telemetry.
10
10
  */
11
11
  export interface TracingManagerInterface {
12
12
  /**
@@ -1,5 +1,6 @@
1
1
  import { DependencyContainer } from "tsyringe";
2
2
  import { EventContext } from "../contexts/event-context";
3
+ import { TracingManagerInterface } from "../interfaces/tracing-manager.interface";
3
4
  /**
4
5
  * Owns the `AsyncLocalStorage` instance that propagates the active `EventContext`
5
6
  * across `await` boundaries, `Promise.all`, `setImmediate`, and the rest of Node's
@@ -40,6 +41,8 @@ export declare class EventContextManager {
40
41
  traceId(): string | undefined;
41
42
  /** Convenience: the per-event DI child container, or `undefined`. */
42
43
  container(): DependencyContainer | undefined;
44
+ /** Convenience: the `TracingManager` that owns this event's trace, or `undefined`. */
45
+ tracingManager(): TracingManagerInterface | undefined;
43
46
  /**
44
47
  * Returns a wrapped version of `fn` that restores the current context on call. Use
45
48
  * when you need to spawn work that escapes the natural async chain (e.g. a callback
@@ -54,5 +57,6 @@ export declare class EventContextManager {
54
57
  static eventId(): string | undefined;
55
58
  static traceId(): string | undefined;
56
59
  static container(): DependencyContainer | undefined;
60
+ static tracingManager(): TracingManagerInterface | undefined;
57
61
  static bind<F extends (...args: any[]) => any>(fn: F): F;
58
62
  }
@@ -1,5 +1,6 @@
1
1
  export * from "./request";
2
2
  export * from "./response";
3
3
  export * from "./span-event.model";
4
+ export * from "./span-lifecycle-owner.interface";
4
5
  export * from "./span.model";
5
6
  export * from "./trace.model";
@@ -0,0 +1,11 @@
1
+ import { Span } from "./span.model";
2
+ /**
3
+ * Minimal structural type for the back-reference a `Span` keeps to whatever lifecycle
4
+ * owner created it. Lets `span.end()` delegate without importing the full
5
+ * `TracingManagerInterface` (which is registered through DI under the
6
+ * `"TracingManagerInterface"` token). Telemetry's `TracingManagerInterface` satisfies
7
+ * this shape by having a compatible `endSpan` method.
8
+ */
9
+ export interface SpanLifecycleOwnerInterface {
10
+ endSpan(span: Span): void;
11
+ }
@@ -1,14 +1,6 @@
1
- import { Trace } from "./trace.model";
2
1
  import { SpanEvent } from "./span-event.model";
3
- /**
4
- * Minimal structural type for the back-reference Span keeps to whatever lifecycle owner
5
- * created it. Lets `span.end()` delegate without importing the full TracingManagerInterface
6
- * (which lives in @pristine-ts/telemetry). Telemetry's TracingManagerInterface satisfies
7
- * this shape by having a compatible `endSpan` method.
8
- */
9
- export interface SpanLifecycleOwnerInterface {
10
- endSpan(span: Span): void;
11
- }
2
+ import { SpanLifecycleOwnerInterface } from "./span-lifecycle-owner.interface";
3
+ import { Trace } from "./trace.model";
12
4
  /**
13
5
  * This model represents a span.
14
6
  */
@@ -1,4 +1,3 @@
1
1
  export * from "./date.util";
2
2
  export * from "./enum.util";
3
3
  export * from "./metadata.util";
4
- export * from "./span-runner";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pristine-ts/common",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "",
5
5
  "module": "dist/lib/esm/common.module.js",
6
6
  "main": "dist/lib/cjs/common.module.js",
@@ -63,5 +63,5 @@
63
63
  "src/*.{js,ts}"
64
64
  ]
65
65
  },
66
- "gitHead": "f376d34e13c1b17b7764c0b47708148e4e51390b"
66
+ "gitHead": "9a960b330ee1961bb9a6151ce50257c4d8ccd48d"
67
67
  }
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LoggableError = void 0;
4
- /**
5
- * This Error represents a LoggableError
6
- */
7
- class LoggableError extends Error {
8
- constructor(message, extra) {
9
- super(message);
10
- this.message = message;
11
- this.extra = extra;
12
- // Set the prototype explicitly.
13
- // As specified in the documentation in TypeScript
14
- // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
15
- Object.setPrototypeOf(this, LoggableError.prototype);
16
- }
17
- }
18
- exports.LoggableError = LoggableError;
19
- //# sourceMappingURL=loggable.error.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loggable.error.js","sourceRoot":"","sources":["../../../../src/errors/loggable.error.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,aAAc,SAAQ,KAAK;IACtC,YAA4B,OAAe,EAAW,KAAW;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAC;QADW,YAAO,GAAP,OAAO,CAAQ;QAAW,UAAK,GAAL,KAAK,CAAM;QAG/D,gCAAgC;QAChC,kDAAkD;QAClD,gIAAgI;QAChI,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;CACF;AATD,sCASC"}
@@ -1,117 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.spanRunner = exports.SpanRunner = void 0;
13
- const event_context_manager_1 = require("../managers/event-context.manager");
14
- /**
15
- * Runs a function inside a span that is automatically ended when the function returns
16
- * or throws.
17
- *
18
- * Two call shapes are supported:
19
- *
20
- * **Explicit form** (`runWithSpan(tracingManager, name, fn)`) — pass the manager you've
21
- * already injected. Works anywhere, including outside an event context. Use this when
22
- * you have a `TracingManager` reference in hand:
23
- *
24
- * ```ts
25
- * return spanRunner.runWithSpan(this.tracingManager, "payment.charge",
26
- * () => this.client.charge(amount));
27
- * ```
28
- *
29
- * **ALS form** (`runWithSpan(name, fn)`) — auto-resolves the `TracingManager` from the
30
- * active `EventContext`'s container. Concise; works when called from anywhere inside
31
- * a Pristine event (controller, service, etc.) without needing the manager threaded
32
- * through:
33
- *
34
- * ```ts
35
- * return spanRunner.runWithSpan("payment.charge", () => this.client.charge(amount));
36
- * ```
37
- *
38
- * If the ALS form is used outside any `EventContext` (e.g. a unit test that doesn't
39
- * boot a kernel), no span is created and `fn` runs unchanged — same no-throw contract
40
- * as the rest of the tracing layer.
41
- *
42
- * On thrown errors: the error's name/message is attached to the span's context (visible
43
- * in the rendered tree/JSON output) and then re-thrown. The span is ended either way.
44
- *
45
- * Stateless — instantiate once and reuse, or use the exported singleton `spanRunner`.
46
- */
47
- class SpanRunner {
48
- runWithSpan(tracingManagerOrSpanKeyname, spanKeynameOrFn, fnOrOptions, maybeOptions) {
49
- return __awaiter(this, void 0, void 0, function* () {
50
- // Disambiguate by the first argument's shape. A string means "ALS form"; an object
51
- // with `startSpan` means the explicit-manager form.
52
- let tracingManager;
53
- let spanKeyname;
54
- let fn;
55
- let options;
56
- if (typeof tracingManagerOrSpanKeyname === "string") {
57
- spanKeyname = tracingManagerOrSpanKeyname;
58
- fn = spanKeynameOrFn;
59
- options = fnOrOptions;
60
- // ── container.resolve, justified ──────────────────────────────────────────────
61
- // This is one of the documented "legitimate exception" cases (see CLAUDE.md):
62
- // SpanRunner is a stateless utility class with static-ish methods invoked from
63
- // free functions / decorators that have no constructor to inject through. The
64
- // ALS-form overload exists precisely so callers don't have to thread a
65
- // TracingManager reference everywhere. If there's no active event context (e.g. a
66
- // unit test calling this directly), the lookup is skipped and the function runs
67
- // without a span — tracing must never throw or change semantics.
68
- const container = event_context_manager_1.EventContextManager.container();
69
- if (container !== undefined) {
70
- try {
71
- tracingManager = container.resolve("TracingManagerInterface");
72
- }
73
- catch (_a) {
74
- tracingManager = undefined;
75
- }
76
- }
77
- }
78
- else {
79
- tracingManager = tracingManagerOrSpanKeyname;
80
- spanKeyname = spanKeynameOrFn;
81
- fn = fnOrOptions;
82
- options = maybeOptions;
83
- }
84
- if (tracingManager === undefined) {
85
- // No manager available: ALS form called outside any event context, or no
86
- // TracingManager registered in the container. Run the function unchanged so
87
- // callers get the same behavior they'd see without `runWithSpan` wrapping at all.
88
- return yield fn();
89
- }
90
- const span = tracingManager.startSpan(spanKeyname, options === null || options === void 0 ? void 0 : options.parentKeyname, options === null || options === void 0 ? void 0 : options.parentId, options === null || options === void 0 ? void 0 : options.context);
91
- try {
92
- return yield fn();
93
- }
94
- catch (error) {
95
- // Annotate the span with error info so it surfaces in the rendered output without
96
- // forcing the caller to remember to add it themselves. Span.context is string-typed
97
- // by design (cheap to serialize), so we coerce.
98
- if (error instanceof Error) {
99
- span.context = Object.assign(Object.assign({}, span.context), { error: "true", errorName: error.name, errorMessage: error.message });
100
- }
101
- else {
102
- span.context = Object.assign(Object.assign({}, span.context), { error: "true", errorName: "non-error-throw", errorMessage: String(error) });
103
- }
104
- throw error;
105
- }
106
- finally {
107
- span.end();
108
- }
109
- });
110
- }
111
- }
112
- exports.SpanRunner = SpanRunner;
113
- /**
114
- * Default singleton. Stateless so sharing is safe.
115
- */
116
- exports.spanRunner = new SpanRunner();
117
- //# sourceMappingURL=span-runner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"span-runner.js","sourceRoot":"","sources":["../../../../src/utils/span-runner.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6EAAsE;AAetE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAa,UAAU;IAcf,WAAW,CACf,2BAA6D,EAC7D,eAAgD,EAChD,WAAwD,EACxD,YAAgC;;YAEhC,mFAAmF;YACnF,oDAAoD;YACpD,IAAI,cAAmD,CAAC;YACxD,IAAI,WAAmB,CAAC;YACxB,IAAI,EAAwB,CAAC;YAC7B,IAAI,OAAsC,CAAC;YAE3C,IAAI,OAAO,2BAA2B,KAAK,QAAQ,EAAE,CAAC;gBACpD,WAAW,GAAG,2BAA2B,CAAC;gBAC1C,EAAE,GAAG,eAAuC,CAAC;gBAC7C,OAAO,GAAG,WAA4C,CAAC;gBACvD,iFAAiF;gBACjF,8EAA8E;gBAC9E,+EAA+E;gBAC/E,8EAA8E;gBAC9E,uEAAuE;gBACvE,kFAAkF;gBAClF,gFAAgF;gBAChF,iEAAiE;gBACjE,MAAM,SAAS,GAAG,2CAAmB,CAAC,SAAS,EAAE,CAAC;gBAClD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;oBAC5B,IAAI,CAAC;wBACH,cAAc,GAAG,SAAS,CAAC,OAAO,CAA0B,yBAAyB,CAAC,CAAC;oBACzF,CAAC;oBAAC,WAAM,CAAC;wBACP,cAAc,GAAG,SAAS,CAAC;oBAC7B,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,cAAc,GAAG,2BAA2B,CAAC;gBAC7C,WAAW,GAAG,eAAyB,CAAC;gBACxC,EAAE,GAAG,WAAmC,CAAC;gBACzC,OAAO,GAAG,YAAY,CAAC;YACzB,CAAC;YAED,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACjC,yEAAyE;gBACzE,4EAA4E;gBAC5E,kFAAkF;gBAClF,OAAO,MAAM,EAAE,EAAE,CAAC;YACpB,CAAC;YAED,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CACnC,WAAW,EACX,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa,EACtB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,EACjB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CACjB,CAAC;YAEF,IAAI,CAAC;gBACH,OAAO,MAAM,EAAE,EAAE,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,kFAAkF;gBAClF,oFAAoF;gBACpF,gDAAgD;gBAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;oBAC3B,IAAI,CAAC,OAAO,mCACP,IAAI,CAAC,OAAO,KACf,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,KAAK,CAAC,IAAI,EACrB,YAAY,EAAE,KAAK,CAAC,OAAO,GAC5B,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,OAAO,mCACP,IAAI,CAAC,OAAO,KACf,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,iBAAiB,EAC5B,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,GAC5B,CAAC;gBACJ,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,CAAC;QACH,CAAC;KAAA;CACF;AA9FD,gCA8FC;AAED;;GAEG;AACU,QAAA,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC"}
@@ -1,15 +0,0 @@
1
- /**
2
- * This Error represents a LoggableError
3
- */
4
- export class LoggableError extends Error {
5
- constructor(message, extra) {
6
- super(message);
7
- this.message = message;
8
- this.extra = extra;
9
- // Set the prototype explicitly.
10
- // As specified in the documentation in TypeScript
11
- // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
12
- Object.setPrototypeOf(this, LoggableError.prototype);
13
- }
14
- }
15
- //# sourceMappingURL=loggable.error.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loggable.error.js","sourceRoot":"","sources":["../../../../src/errors/loggable.error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAA4B,OAAe,EAAW,KAAW;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAC;QADW,YAAO,GAAP,OAAO,CAAQ;QAAW,UAAK,GAAL,KAAK,CAAM;QAG/D,gCAAgC;QAChC,kDAAkD;QAClD,gIAAgI;QAChI,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;CACF"}