apcore-js 0.19.0 → 0.20.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 (186) hide show
  1. package/README.md +110 -9
  2. package/dist/acl.d.ts +18 -0
  3. package/dist/acl.d.ts.map +1 -1
  4. package/dist/acl.js +54 -17
  5. package/dist/acl.js.map +1 -1
  6. package/dist/async-task.d.ts +70 -16
  7. package/dist/async-task.d.ts.map +1 -1
  8. package/dist/async-task.js +212 -72
  9. package/dist/async-task.js.map +1 -1
  10. package/dist/builtin-steps.d.ts +16 -5
  11. package/dist/builtin-steps.d.ts.map +1 -1
  12. package/dist/builtin-steps.js +45 -28
  13. package/dist/builtin-steps.js.map +1 -1
  14. package/dist/config.d.ts +38 -0
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +163 -33
  17. package/dist/config.js.map +1 -1
  18. package/dist/context.d.ts.map +1 -1
  19. package/dist/context.js +12 -1
  20. package/dist/context.js.map +1 -1
  21. package/dist/errors.d.ts +32 -10
  22. package/dist/errors.d.ts.map +1 -1
  23. package/dist/errors.js +55 -16
  24. package/dist/errors.js.map +1 -1
  25. package/dist/events/circuit-breaker.d.ts +45 -0
  26. package/dist/events/circuit-breaker.d.ts.map +1 -0
  27. package/dist/events/circuit-breaker.js +115 -0
  28. package/dist/events/circuit-breaker.js.map +1 -0
  29. package/dist/events/emitter.d.ts +22 -1
  30. package/dist/events/emitter.d.ts.map +1 -1
  31. package/dist/events/emitter.js +66 -2
  32. package/dist/events/emitter.js.map +1 -1
  33. package/dist/events/index.d.ts +4 -2
  34. package/dist/events/index.d.ts.map +1 -1
  35. package/dist/events/index.js +3 -2
  36. package/dist/events/index.js.map +1 -1
  37. package/dist/events/subscribers.d.ts +33 -1
  38. package/dist/events/subscribers.d.ts.map +1 -1
  39. package/dist/events/subscribers.js +124 -1
  40. package/dist/events/subscribers.js.map +1 -1
  41. package/dist/executor.d.ts +10 -2
  42. package/dist/executor.d.ts.map +1 -1
  43. package/dist/executor.js +134 -51
  44. package/dist/executor.js.map +1 -1
  45. package/dist/generated/version.d.ts +1 -1
  46. package/dist/generated/version.js +1 -1
  47. package/dist/index.d.ts +35 -25
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +23 -17
  50. package/dist/index.js.map +1 -1
  51. package/dist/middleware/base.d.ts +25 -3
  52. package/dist/middleware/base.d.ts.map +1 -1
  53. package/dist/middleware/base.js +24 -0
  54. package/dist/middleware/base.js.map +1 -1
  55. package/dist/middleware/circuit-breaker.d.ts +54 -0
  56. package/dist/middleware/circuit-breaker.d.ts.map +1 -0
  57. package/dist/middleware/circuit-breaker.js +168 -0
  58. package/dist/middleware/circuit-breaker.js.map +1 -0
  59. package/dist/middleware/context-namespace.d.ts +30 -0
  60. package/dist/middleware/context-namespace.d.ts.map +1 -0
  61. package/dist/middleware/context-namespace.js +38 -0
  62. package/dist/middleware/context-namespace.js.map +1 -0
  63. package/dist/middleware/index.d.ts +7 -1
  64. package/dist/middleware/index.d.ts.map +1 -1
  65. package/dist/middleware/index.js +4 -1
  66. package/dist/middleware/index.js.map +1 -1
  67. package/dist/middleware/manager.d.ts +11 -4
  68. package/dist/middleware/manager.d.ts.map +1 -1
  69. package/dist/middleware/manager.js +25 -9
  70. package/dist/middleware/manager.js.map +1 -1
  71. package/dist/middleware/platform-notify.d.ts +8 -4
  72. package/dist/middleware/platform-notify.d.ts.map +1 -1
  73. package/dist/middleware/platform-notify.js +11 -7
  74. package/dist/middleware/platform-notify.js.map +1 -1
  75. package/dist/middleware/tracing.d.ts +50 -0
  76. package/dist/middleware/tracing.d.ts.map +1 -0
  77. package/dist/middleware/tracing.js +89 -0
  78. package/dist/middleware/tracing.js.map +1 -0
  79. package/dist/observability/batch-span-processor.d.ts +48 -0
  80. package/dist/observability/batch-span-processor.d.ts.map +1 -0
  81. package/dist/observability/batch-span-processor.js +89 -0
  82. package/dist/observability/batch-span-processor.js.map +1 -0
  83. package/dist/observability/context-logger.d.ts +54 -1
  84. package/dist/observability/context-logger.d.ts.map +1 -1
  85. package/dist/observability/context-logger.js +270 -6
  86. package/dist/observability/context-logger.js.map +1 -1
  87. package/dist/observability/error-history.d.ts +36 -7
  88. package/dist/observability/error-history.d.ts.map +1 -1
  89. package/dist/observability/error-history.js +169 -50
  90. package/dist/observability/error-history.js.map +1 -1
  91. package/dist/observability/index.d.ts +16 -5
  92. package/dist/observability/index.d.ts.map +1 -1
  93. package/dist/observability/index.js +8 -3
  94. package/dist/observability/index.js.map +1 -1
  95. package/dist/observability/metrics.d.ts +14 -1
  96. package/dist/observability/metrics.d.ts.map +1 -1
  97. package/dist/observability/metrics.js +23 -2
  98. package/dist/observability/metrics.js.map +1 -1
  99. package/dist/observability/prometheus-exporter.d.ts +37 -0
  100. package/dist/observability/prometheus-exporter.d.ts.map +1 -0
  101. package/dist/observability/prometheus-exporter.js +135 -0
  102. package/dist/observability/prometheus-exporter.js.map +1 -0
  103. package/dist/observability/storage.d.ts +43 -0
  104. package/dist/observability/storage.d.ts.map +1 -0
  105. package/dist/observability/storage.js +58 -0
  106. package/dist/observability/storage.js.map +1 -0
  107. package/dist/observability/store.d.ts +29 -0
  108. package/dist/observability/store.d.ts.map +1 -0
  109. package/dist/observability/store.js +36 -0
  110. package/dist/observability/store.js.map +1 -0
  111. package/dist/observability/usage-exporter.d.ts +58 -0
  112. package/dist/observability/usage-exporter.d.ts.map +1 -0
  113. package/dist/observability/usage-exporter.js +86 -0
  114. package/dist/observability/usage-exporter.js.map +1 -0
  115. package/dist/observability/usage.d.ts +18 -1
  116. package/dist/observability/usage.d.ts.map +1 -1
  117. package/dist/observability/usage.js +25 -3
  118. package/dist/observability/usage.js.map +1 -1
  119. package/dist/pipeline-config.d.ts +11 -0
  120. package/dist/pipeline-config.d.ts.map +1 -1
  121. package/dist/pipeline-config.js +36 -10
  122. package/dist/pipeline-config.js.map +1 -1
  123. package/dist/pipeline.d.ts +123 -2
  124. package/dist/pipeline.d.ts.map +1 -1
  125. package/dist/pipeline.js +249 -50
  126. package/dist/pipeline.js.map +1 -1
  127. package/dist/registry/index.d.ts +2 -0
  128. package/dist/registry/index.d.ts.map +1 -1
  129. package/dist/registry/index.js +1 -0
  130. package/dist/registry/index.js.map +1 -1
  131. package/dist/registry/multi-class.d.ts +57 -0
  132. package/dist/registry/multi-class.d.ts.map +1 -0
  133. package/dist/registry/multi-class.js +120 -0
  134. package/dist/registry/multi-class.js.map +1 -0
  135. package/dist/registry/registry.d.ts +91 -3
  136. package/dist/registry/registry.d.ts.map +1 -1
  137. package/dist/registry/registry.js +181 -11
  138. package/dist/registry/registry.js.map +1 -1
  139. package/dist/schema/constants.d.ts +9 -0
  140. package/dist/schema/constants.d.ts.map +1 -0
  141. package/dist/schema/constants.js +9 -0
  142. package/dist/schema/constants.js.map +1 -0
  143. package/dist/schema/index.d.ts +1 -1
  144. package/dist/schema/index.d.ts.map +1 -1
  145. package/dist/schema/index.js +1 -1
  146. package/dist/schema/index.js.map +1 -1
  147. package/dist/schema/loader.d.ts +27 -3
  148. package/dist/schema/loader.d.ts.map +1 -1
  149. package/dist/schema/loader.js +137 -32
  150. package/dist/schema/loader.js.map +1 -1
  151. package/dist/schema/types.d.ts +4 -0
  152. package/dist/schema/types.d.ts.map +1 -1
  153. package/dist/schema/types.js.map +1 -1
  154. package/dist/schema/validator.d.ts +9 -0
  155. package/dist/schema/validator.d.ts.map +1 -1
  156. package/dist/schema/validator.js +153 -4
  157. package/dist/schema/validator.js.map +1 -1
  158. package/dist/sys-modules/audit.d.ts +50 -0
  159. package/dist/sys-modules/audit.d.ts.map +1 -0
  160. package/dist/sys-modules/audit.js +89 -0
  161. package/dist/sys-modules/audit.js.map +1 -0
  162. package/dist/sys-modules/control.d.ts +32 -4
  163. package/dist/sys-modules/control.d.ts.map +1 -1
  164. package/dist/sys-modules/control.js +196 -25
  165. package/dist/sys-modules/control.js.map +1 -1
  166. package/dist/sys-modules/index.d.ts +7 -2
  167. package/dist/sys-modules/index.d.ts.map +1 -1
  168. package/dist/sys-modules/index.js +3 -1
  169. package/dist/sys-modules/index.js.map +1 -1
  170. package/dist/sys-modules/overrides.d.ts +58 -0
  171. package/dist/sys-modules/overrides.d.ts.map +1 -0
  172. package/dist/sys-modules/overrides.js +106 -0
  173. package/dist/sys-modules/overrides.js.map +1 -0
  174. package/dist/sys-modules/registration.d.ts +17 -12
  175. package/dist/sys-modules/registration.d.ts.map +1 -1
  176. package/dist/sys-modules/registration.js +115 -23
  177. package/dist/sys-modules/registration.js.map +1 -1
  178. package/dist/sys-modules/toggle.d.ts +7 -2
  179. package/dist/sys-modules/toggle.d.ts.map +1 -1
  180. package/dist/sys-modules/toggle.js +61 -5
  181. package/dist/sys-modules/toggle.js.map +1 -1
  182. package/dist/trace-context.d.ts +47 -9
  183. package/dist/trace-context.d.ts.map +1 -1
  184. package/dist/trace-context.js +139 -16
  185. package/dist/trace-context.js.map +1 -1
  186. package/package.json +1 -1
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Context namespace utilities for apcore middleware hardening (Issue #42).
3
+ *
4
+ * Namespace rules:
5
+ * - _apcore.* — reserved for framework use only
6
+ * - ext.* — reserved for user extensions
7
+ * - All other keys are allowed (legacy compatibility)
8
+ */
9
+ export type ContextKeyWriter = 'framework' | 'user';
10
+ export interface ContextKeyValidation {
11
+ readonly valid: boolean;
12
+ readonly warning: boolean;
13
+ }
14
+ /**
15
+ * Validate whether a context key write is allowed for the given writer role.
16
+ *
17
+ * Rules (PROTOCOL_SPEC §Middleware Architecture Hardening §1.1):
18
+ * - User middleware MUST NOT write `_apcore.*` keys.
19
+ * - Framework MUST NOT write `ext.*` keys.
20
+ */
21
+ export declare function validateContextKey(writer: ContextKeyWriter, key: string): ContextKeyValidation;
22
+ /**
23
+ * Detect whether a function is an async function at call time using
24
+ * `handler.constructor.name === 'AsyncFunction'`.
25
+ *
26
+ * This is the TypeScript-safe equivalent of Python's `inspect.iscoroutinefunction`.
27
+ * Do NOT use `handler() instanceof Promise` — that calls the function and is too late.
28
+ */
29
+ export declare function isAsyncHandler(handler: Function): boolean;
30
+ //# sourceMappingURL=context-namespace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-namespace.d.ts","sourceRoot":"","sources":["../../src/middleware/context-namespace.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAKD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,gBAAgB,EACxB,GAAG,EAAE,MAAM,GACV,oBAAoB,CAQtB;AAED;;;;;;GAMG;AAEH,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAEzD"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Context namespace utilities for apcore middleware hardening (Issue #42).
3
+ *
4
+ * Namespace rules:
5
+ * - _apcore.* — reserved for framework use only
6
+ * - ext.* — reserved for user extensions
7
+ * - All other keys are allowed (legacy compatibility)
8
+ */
9
+ const APCORE_NS_PREFIX = '_apcore.';
10
+ const EXT_NS_PREFIX = 'ext.';
11
+ /**
12
+ * Validate whether a context key write is allowed for the given writer role.
13
+ *
14
+ * Rules (PROTOCOL_SPEC §Middleware Architecture Hardening §1.1):
15
+ * - User middleware MUST NOT write `_apcore.*` keys.
16
+ * - Framework MUST NOT write `ext.*` keys.
17
+ */
18
+ export function validateContextKey(writer, key) {
19
+ if (writer === 'user' && key.startsWith(APCORE_NS_PREFIX)) {
20
+ return { valid: false, warning: true };
21
+ }
22
+ if (writer === 'framework' && key.startsWith(EXT_NS_PREFIX)) {
23
+ return { valid: false, warning: true };
24
+ }
25
+ return { valid: true, warning: false };
26
+ }
27
+ /**
28
+ * Detect whether a function is an async function at call time using
29
+ * `handler.constructor.name === 'AsyncFunction'`.
30
+ *
31
+ * This is the TypeScript-safe equivalent of Python's `inspect.iscoroutinefunction`.
32
+ * Do NOT use `handler() instanceof Promise` — that calls the function and is too late.
33
+ */
34
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
35
+ export function isAsyncHandler(handler) {
36
+ return handler.constructor.name === 'AsyncFunction';
37
+ }
38
+ //# sourceMappingURL=context-namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-namespace.js","sourceRoot":"","sources":["../../src/middleware/context-namespace.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,MAAM,gBAAgB,GAAG,UAAU,CAAC;AACpC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAwB,EACxB,GAAW;IAEX,IAAI,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IACD,IAAI,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,sEAAsE;AACtE,MAAM,UAAU,cAAc,CAAC,OAAiB;IAC9C,OAAO,OAAO,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe,CAAC;AACtD,CAAC"}
@@ -1,4 +1,4 @@
1
- export { Middleware } from './base.js';
1
+ export { Middleware, RetrySignal } from './base.js';
2
2
  export { MiddlewareManager, MiddlewareChainError } from './manager.js';
3
3
  export { BeforeMiddleware, AfterMiddleware } from './adapters.js';
4
4
  export type { BeforeCallback, AfterCallback } from './adapters.js';
@@ -8,4 +8,10 @@ export { RetryHintMiddleware, RetryMiddleware, CTX_RETRY_COUNT_PREFIX, CTX_RETRY
8
8
  export type { RetryConfig } from './retry.js';
9
9
  export { ErrorHistoryMiddleware } from './error-history.js';
10
10
  export { PlatformNotifyMiddleware } from './platform-notify.js';
11
+ export { CircuitBreakerMiddleware, CircuitState as MiddlewareCircuitState, CTX_CIRCUIT_STATE, } from './circuit-breaker.js';
12
+ export type { CircuitBreakerOptions } from './circuit-breaker.js';
13
+ export { TracingMiddleware, CTX_TRACING_SPAN_ID } from './tracing.js';
14
+ export type { OtelTracer, OtelSpan, TracingMiddlewareOptions } from './tracing.js';
15
+ export { validateContextKey, isAsyncHandler } from './context-namespace.js';
16
+ export type { ContextKeyWriter, ContextKeyValidation } from './context-namespace.js';
11
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAClH,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAClH,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EACL,wBAAwB,EACxB,YAAY,IAAI,sBAAsB,EACtC,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1,8 +1,11 @@
1
- export { Middleware } from './base.js';
1
+ export { Middleware, RetrySignal } from './base.js';
2
2
  export { MiddlewareManager, MiddlewareChainError } from './manager.js';
3
3
  export { BeforeMiddleware, AfterMiddleware } from './adapters.js';
4
4
  export { LoggingMiddleware } from './logging.js';
5
5
  export { RetryHintMiddleware, RetryMiddleware, CTX_RETRY_COUNT_PREFIX, CTX_RETRY_DELAY_PREFIX } from './retry.js';
6
6
  export { ErrorHistoryMiddleware } from './error-history.js';
7
7
  export { PlatformNotifyMiddleware } from './platform-notify.js';
8
+ export { CircuitBreakerMiddleware, CircuitState as MiddlewareCircuitState, CTX_CIRCUIT_STATE, } from './circuit-breaker.js';
9
+ export { TracingMiddleware, CTX_TRACING_SPAN_ID } from './tracing.js';
10
+ export { validateContextKey, isAsyncHandler } from './context-namespace.js';
8
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAElH,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAElH,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EACL,wBAAwB,EACxB,YAAY,IAAI,sBAAsB,EACtC,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import type { Context } from '../context.js';
5
5
  import { ModuleError } from '../errors.js';
6
- import { Middleware } from './base.js';
6
+ import { Middleware, RetrySignal } from './base.js';
7
7
  export declare class MiddlewareChainError extends ModuleError {
8
8
  static readonly DEFAULT_RETRYABLE: boolean | null;
9
9
  readonly original: Error;
@@ -15,8 +15,15 @@ export declare class MiddlewareManager {
15
15
  add(middleware: Middleware): void;
16
16
  remove(middleware: Middleware): boolean;
17
17
  snapshot(): Middleware[];
18
- executeBefore(moduleId: string, inputs: Record<string, unknown>, context: Context): [Record<string, unknown>, Middleware[]];
19
- executeAfter(moduleId: string, inputs: Record<string, unknown>, output: Record<string, unknown>, context: Context): Record<string, unknown>;
20
- executeOnError(moduleId: string, inputs: Record<string, unknown>, error: Error, context: Context, executedMiddlewares: Middleware[]): Record<string, unknown> | null;
18
+ /**
19
+ * Run all `before` hooks in priority-descending order, awaiting any Promise
20
+ * a middleware returns.
21
+ *
22
+ * Always-async (sync finding A-D-403) — matches apcore-rust's design and
23
+ * removes the silent-Promise-into-currentInputs trap.
24
+ */
25
+ executeBefore(moduleId: string, inputs: Record<string, unknown>, context: Context): Promise<[Record<string, unknown>, Middleware[]]>;
26
+ executeAfter(moduleId: string, inputs: Record<string, unknown>, output: Record<string, unknown>, context: Context): Promise<Record<string, unknown>>;
27
+ executeOnError(moduleId: string, inputs: Record<string, unknown>, error: Error, context: Context, executedMiddlewares: Middleware[]): Promise<Record<string, unknown> | RetrySignal | null>;
21
28
  }
22
29
  //# sourceMappingURL=manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,gBAAyB,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAS;IAEnE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzB,QAAQ,CAAC,mBAAmB,EAAE,UAAU,EAAE,CAAC;gBAE/B,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE;CAM/D;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,YAAY,CAAoB;IAExC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAcjC,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO;IAUvC,QAAQ,IAAI,UAAU,EAAE;IAIxB,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IAoB1C,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAe1B,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAE,UAAU,EAAE,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAclC"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEpD,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,gBAAyB,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAS;IAEnE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzB,QAAQ,CAAC,mBAAmB,EAAE,UAAU,EAAE,CAAC;gBAE/B,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE;CAM/D;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,YAAY,CAAoB;IAExC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAcjC,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO;IAUvC,QAAQ,IAAI,UAAU,EAAE;IAIxB;;;;;;OAMG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAoB7C,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAe7B,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAE,UAAU,EAAE,GAChC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,IAAI,CAAC;CAwBzD"}
@@ -2,6 +2,7 @@
2
2
  * MiddlewareManager -- onion model execution engine for the middleware pipeline.
3
3
  */
4
4
  import { ModuleError } from '../errors.js';
5
+ import { RetrySignal } from './base.js';
5
6
  export class MiddlewareChainError extends ModuleError {
6
7
  static DEFAULT_RETRYABLE = false;
7
8
  original;
@@ -40,15 +41,22 @@ export class MiddlewareManager {
40
41
  snapshot() {
41
42
  return [...this._middlewares];
42
43
  }
43
- executeBefore(moduleId, inputs, context) {
44
+ /**
45
+ * Run all `before` hooks in priority-descending order, awaiting any Promise
46
+ * a middleware returns.
47
+ *
48
+ * Always-async (sync finding A-D-403) — matches apcore-rust's design and
49
+ * removes the silent-Promise-into-currentInputs trap.
50
+ */
51
+ async executeBefore(moduleId, inputs, context) {
44
52
  let currentInputs = inputs;
45
53
  const executedMiddlewares = [];
46
54
  const middlewares = this.snapshot();
47
55
  for (const mw of middlewares) {
48
56
  executedMiddlewares.push(mw);
49
57
  try {
50
- const result = mw.before(moduleId, currentInputs, context);
51
- if (result !== null) {
58
+ const result = await mw.before(moduleId, currentInputs, context);
59
+ if (result !== null && result !== undefined) {
52
60
  currentInputs = result;
53
61
  }
54
62
  }
@@ -58,23 +66,31 @@ export class MiddlewareManager {
58
66
  }
59
67
  return [currentInputs, executedMiddlewares];
60
68
  }
61
- executeAfter(moduleId, inputs, output, context) {
69
+ async executeAfter(moduleId, inputs, output, context) {
62
70
  let currentOutput = output;
63
71
  const middlewares = this.snapshot();
64
72
  // Fail-fast: propagate the first error immediately (matches Python/Rust behaviour).
65
73
  for (let i = middlewares.length - 1; i >= 0; i--) {
66
- const result = middlewares[i].after(moduleId, inputs, currentOutput, context);
67
- if (result !== null) {
74
+ const result = await middlewares[i].after(moduleId, inputs, currentOutput, context);
75
+ if (result !== null && result !== undefined) {
68
76
  currentOutput = result;
69
77
  }
70
78
  }
71
79
  return currentOutput;
72
80
  }
73
- executeOnError(moduleId, inputs, error, context, executedMiddlewares) {
81
+ async executeOnError(moduleId, inputs, error, context, executedMiddlewares) {
74
82
  for (let i = executedMiddlewares.length - 1; i >= 0; i--) {
75
83
  try {
76
- const result = executedMiddlewares[i].onError(moduleId, inputs, error, context);
77
- if (result !== null) {
84
+ const result = await executedMiddlewares[i].onError(moduleId, inputs, error, context);
85
+ // Strict recovery type check (sync finding A-D-404):
86
+ // only a non-null object or a RetrySignal counts as recovery.
87
+ // `undefined` (typical of arrow functions without a return) does NOT trigger recovery.
88
+ if (result !== null
89
+ && result !== undefined
90
+ && (result instanceof RetrySignal || (typeof result === 'object'))) {
91
+ // RetrySignal short-circuits and propagates up to the executor's
92
+ // call() loop, which re-runs the pipeline with new inputs.
93
+ // Plain objects become the recovery output. (sync finding A-D-017)
78
94
  return result;
79
95
  }
80
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,14 @@
2
2
  * PlatformNotifyMiddleware -- threshold sensor with hysteresis.
3
3
  *
4
4
  * Monitors error rates and latency, emits threshold events with hysteresis.
5
- * Emits error_threshold_exceeded when a module's error rate crosses the
6
- * configured threshold, latency_threshold_exceeded when p99 latency
7
- * exceeds the limit, and apcore.health.recovered when a previously alerted
8
- * module recovers below threshold * 0.5.
5
+ * Emits apcore.health.error_threshold_exceeded when a module's error rate
6
+ * crosses the configured threshold, apcore.health.latency_threshold_exceeded
7
+ * when p99 latency exceeds the limit, and apcore.health.recovered when a
8
+ * previously alerted module recovers below threshold * 0.5.
9
+ *
10
+ * During the deprecation window legacy aliases (`error_threshold_exceeded`,
11
+ * `latency_threshold_exceeded`) are emitted alongside the canonical names
12
+ * with `deprecated: true` in the payload (Issue #36).
9
13
  */
10
14
  import type { Context } from '../context.js';
11
15
  import type { EventEmitter } from '../events/emitter.js';
@@ -1 +1 @@
1
- {"version":3,"file":"platform-notify.d.ts","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,qBAAa,wBAAyB,SAAQ,UAAU;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAC5D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;gBAG9D,YAAY,EAAE,YAAY,EAC1B,gBAAgB,GAAE,gBAAgB,GAAG,IAAW,EAChD,kBAAkB,GAAE,MAAY,EAChC,qBAAqB,GAAE,MAAa;IAS7B,KAAK,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMxB,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IASjC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,mBAAmB;CAe5B"}
1
+ {"version":3,"file":"platform-notify.d.ts","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,qBAAa,wBAAyB,SAAQ,UAAU;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAC5D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;gBAG9D,YAAY,EAAE,YAAY,EAC1B,gBAAgB,GAAE,gBAAgB,GAAG,IAAW,EAChD,kBAAkB,GAAE,MAAY,EAChC,qBAAqB,GAAE,MAAa;IAS7B,KAAK,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMxB,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IASjC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,sBAAsB;IAmB9B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,mBAAmB;CAe5B"}
@@ -2,12 +2,16 @@
2
2
  * PlatformNotifyMiddleware -- threshold sensor with hysteresis.
3
3
  *
4
4
  * Monitors error rates and latency, emits threshold events with hysteresis.
5
- * Emits error_threshold_exceeded when a module's error rate crosses the
6
- * configured threshold, latency_threshold_exceeded when p99 latency
7
- * exceeds the limit, and apcore.health.recovered when a previously alerted
8
- * module recovers below threshold * 0.5.
5
+ * Emits apcore.health.error_threshold_exceeded when a module's error rate
6
+ * crosses the configured threshold, apcore.health.latency_threshold_exceeded
7
+ * when p99 latency exceeds the limit, and apcore.health.recovered when a
8
+ * previously alerted module recovers below threshold * 0.5.
9
+ *
10
+ * During the deprecation window legacy aliases (`error_threshold_exceeded`,
11
+ * `latency_threshold_exceeded`) are emitted alongside the canonical names
12
+ * with `deprecated: true` in the payload (Issue #36).
9
13
  */
10
- import { createEvent } from '../events/emitter.js';
14
+ import { createEvent, emitWithLegacy } from '../events/emitter.js';
11
15
  import { computeModuleErrorRate, estimateP99FromHistogram } from '../observability/metrics-utils.js';
12
16
  import { Middleware } from './base.js';
13
17
  export class PlatformNotifyMiddleware extends Middleware {
@@ -53,7 +57,7 @@ export class PlatformNotifyMiddleware extends Middleware {
53
57
  const errorRate = this._computeErrorRate(moduleId);
54
58
  const alerted = this._getAlerted(moduleId);
55
59
  if (errorRate >= this._errorRateThreshold && !alerted.has('error_rate')) {
56
- this._emitter.emit(createEvent('error_threshold_exceeded', moduleId, 'error', { error_rate: errorRate, threshold: this._errorRateThreshold }));
60
+ emitWithLegacy(this._emitter, 'apcore.health.error_threshold_exceeded', 'error_threshold_exceeded', moduleId, 'error', { error_rate: errorRate, threshold: this._errorRateThreshold });
57
61
  alerted.add('error_rate');
58
62
  }
59
63
  }
@@ -65,7 +69,7 @@ export class PlatformNotifyMiddleware extends Middleware {
65
69
  return;
66
70
  const p99Ms = this._estimateP99Ms(moduleId);
67
71
  if (p99Ms >= this._latencyP99ThresholdMs) {
68
- this._emitter.emit(createEvent('latency_threshold_exceeded', moduleId, 'warn', { p99_latency_ms: p99Ms, threshold: this._latencyP99ThresholdMs }));
72
+ emitWithLegacy(this._emitter, 'apcore.health.latency_threshold_exceeded', 'latency_threshold_exceeded', moduleId, 'warn', { p99_latency_ms: p99Ms, threshold: this._latencyP99ThresholdMs });
69
73
  alerted.add('latency');
70
74
  }
71
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"platform-notify.js","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform-notify.js","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * TracingMiddleware — OpenTelemetry-compatible span lifecycle management (Issue #42).
3
+ *
4
+ * Behaviour:
5
+ * - before(): creates a span named after the module_id, sets apcore.* attributes,
6
+ * and stores the span_id in context.data["_apcore.mw.tracing.span_id"].
7
+ * - after(): ends the span with status OK.
8
+ * - onError(): ends the span with status ERROR.
9
+ * - If @opentelemetry/api is not installed (and no tracer is injected), all methods
10
+ * are silent no-ops.
11
+ */
12
+ import type { Context } from '../context.js';
13
+ import { Middleware } from './base.js';
14
+ export declare const CTX_TRACING_SPAN_ID = "_apcore.mw.tracing.span_id";
15
+ export interface OtelSpan {
16
+ spanContext(): {
17
+ spanId: string;
18
+ };
19
+ setAttribute(key: string, value: string): void;
20
+ setStatus(status: {
21
+ code: number;
22
+ message?: string;
23
+ }): void;
24
+ end(): void;
25
+ }
26
+ export interface OtelTracer {
27
+ startSpan(name: string, options?: Record<string, unknown>): OtelSpan;
28
+ }
29
+ export interface TracingMiddlewareOptions {
30
+ /** OTel service name used when initialising the default tracer. Default: 'apcore' */
31
+ serviceName?: string;
32
+ /**
33
+ * Inject a custom tracer (primarily for testing).
34
+ * When provided this takes precedence over auto-detected OTel.
35
+ * Pass `null` to force no-op mode even if OTel is installed.
36
+ */
37
+ tracer?: OtelTracer | null;
38
+ /** Middleware priority (0–1000). Default: 800 */
39
+ priority?: number;
40
+ }
41
+ export declare class TracingMiddleware extends Middleware {
42
+ private readonly _tracer;
43
+ constructor(options?: TracingMiddlewareOptions);
44
+ /** Type-safe accessor for the active span stored by before(). */
45
+ private _activeSpan;
46
+ before(moduleId: string, _inputs: Record<string, unknown>, context: Context): Record<string, unknown> | null;
47
+ after(_moduleId: string, _inputs: Record<string, unknown>, _output: Record<string, unknown>, context: Context): Record<string, unknown> | null;
48
+ onError(_moduleId: string, _inputs: Record<string, unknown>, error: Error, context: Context): Record<string, unknown> | null;
49
+ }
50
+ //# sourceMappingURL=tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/middleware/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAUhE,MAAM,WAAW,QAAQ;IACvB,WAAW,IAAI;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,GAAG,IAAI,IAAI,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC;CACtE;AAaD,MAAM,WAAW,wBAAwB;IACvC,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;gBAEhC,OAAO,GAAE,wBAA6B;IAWlD,iEAAiE;IACjE,OAAO,CAAC,WAAW;IAUV,MAAM,CACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAkBxB,KAAK,CACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IASxB,OAAO,CACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAQlC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * TracingMiddleware — OpenTelemetry-compatible span lifecycle management (Issue #42).
3
+ *
4
+ * Behaviour:
5
+ * - before(): creates a span named after the module_id, sets apcore.* attributes,
6
+ * and stores the span_id in context.data["_apcore.mw.tracing.span_id"].
7
+ * - after(): ends the span with status OK.
8
+ * - onError(): ends the span with status ERROR.
9
+ * - If @opentelemetry/api is not installed (and no tracer is injected), all methods
10
+ * are silent no-ops.
11
+ */
12
+ import { createRequire } from 'node:module';
13
+ import { Middleware } from './base.js';
14
+ export const CTX_TRACING_SPAN_ID = '_apcore.mw.tracing.span_id';
15
+ // Internal key — stores the live Span object for retrieval in after()/onError().
16
+ // Not part of the public spec; not serialised; prefixed with _ to signal internal use.
17
+ const CTX_TRACING_SPAN = '_apcore.mw.tracing._active_span';
18
+ // OTel SpanStatusCode values (from @opentelemetry/api):
19
+ // UNSET = 0, OK = 1, ERROR = 2
20
+ const SPAN_STATUS_OK = 1;
21
+ const SPAN_STATUS_ERROR = 2;
22
+ // Attempt to load @opentelemetry/api synchronously via Node.js require.
23
+ // If the package is absent, _defaultTrace remains null and TracingMiddleware
24
+ // silently becomes a no-op unless a tracer is explicitly injected.
25
+ const _nodeRequire = createRequire(import.meta.url);
26
+ let _defaultTrace = null;
27
+ try {
28
+ _defaultTrace = _nodeRequire('@opentelemetry/api').trace;
29
+ }
30
+ catch {
31
+ _defaultTrace = null;
32
+ }
33
+ export class TracingMiddleware extends Middleware {
34
+ _tracer;
35
+ constructor(options = {}) {
36
+ super(options.priority ?? 800);
37
+ if ('tracer' in options) {
38
+ this._tracer = options.tracer ?? null;
39
+ }
40
+ else {
41
+ const name = options.serviceName ?? 'apcore';
42
+ this._tracer = _defaultTrace ? _defaultTrace.getTracer(name) : null;
43
+ }
44
+ }
45
+ /** Type-safe accessor for the active span stored by before(). */
46
+ _activeSpan(context) {
47
+ const val = context.data[CTX_TRACING_SPAN];
48
+ if (val == null)
49
+ return null;
50
+ // Minimal shape check: any valid OtelSpan must expose an `end` method.
51
+ if (typeof val === 'object' && typeof val.end === 'function') {
52
+ return val;
53
+ }
54
+ return null;
55
+ }
56
+ before(moduleId, _inputs, context) {
57
+ if (!this._tracer)
58
+ return null;
59
+ try {
60
+ const span = this._tracer.startSpan(moduleId);
61
+ span.setAttribute('apcore.trace_id', context.traceId);
62
+ span.setAttribute('apcore.caller_id', context.callerId ?? '');
63
+ span.setAttribute('apcore.module_id', moduleId);
64
+ context.data[CTX_TRACING_SPAN_ID] = span.spanContext().spanId;
65
+ context.data[CTX_TRACING_SPAN] = span;
66
+ }
67
+ catch (err) {
68
+ console.warn(`[apcore:middleware] TracingMiddleware: span creation failed for '${moduleId}':`, err);
69
+ }
70
+ return null;
71
+ }
72
+ after(_moduleId, _inputs, _output, context) {
73
+ const span = this._activeSpan(context);
74
+ if (span) {
75
+ span.setStatus({ code: SPAN_STATUS_OK });
76
+ span.end();
77
+ }
78
+ return null;
79
+ }
80
+ onError(_moduleId, _inputs, error, context) {
81
+ const span = this._activeSpan(context);
82
+ if (span) {
83
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: String(error) });
84
+ span.end();
85
+ }
86
+ return null;
87
+ }
88
+ }
89
+ //# sourceMappingURL=tracing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../src/middleware/tracing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Span processors: SimpleSpanProcessor (synchronous) and BatchSpanProcessor (async, non-blocking).
3
+ */
4
+ import type { Span, SpanExporter } from './tracing.js';
5
+ export interface SpanProcessor {
6
+ onSpan(span: Span): void;
7
+ shutdown(): Promise<void>;
8
+ }
9
+ /** Synchronous processor — exports each span immediately. For development and testing. */
10
+ export declare class SimpleSpanProcessor implements SpanProcessor {
11
+ private readonly _exporter;
12
+ constructor(options: {
13
+ exporter: SpanExporter;
14
+ });
15
+ onSpan(span: Span): void;
16
+ shutdown(): Promise<void>;
17
+ }
18
+ export interface BatchSpanProcessorOptions {
19
+ exporter: SpanExporter;
20
+ maxQueueSize?: number;
21
+ scheduleDelayMs?: number;
22
+ maxExportBatchSize?: number;
23
+ exportTimeoutMs?: number;
24
+ }
25
+ /**
26
+ * Non-blocking batch processor — buffers spans and exports in background.
27
+ *
28
+ * When the queue is full, new spans are dropped and spansDropped is incremented.
29
+ * On shutdown, remaining spans are flushed within exportTimeoutMs.
30
+ */
31
+ export declare class BatchSpanProcessor implements SpanProcessor {
32
+ private readonly _exporter;
33
+ private readonly _maxQueueSize;
34
+ private readonly _scheduleDelayMs;
35
+ private readonly _maxExportBatchSize;
36
+ private readonly _exportTimeoutMs;
37
+ private _queue;
38
+ private _spansDropped;
39
+ private _timer;
40
+ constructor(options: BatchSpanProcessorOptions);
41
+ get queueSize(): number;
42
+ get spansDropped(): number;
43
+ onSpan(span: Span): void;
44
+ shutdown(): Promise<void>;
45
+ private _startTimer;
46
+ private _flush;
47
+ }
48
+ //# sourceMappingURL=batch-span-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-span-processor.d.ts","sourceRoot":"","sources":["../../src/observability/batch-span-processor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,0FAA0F;AAC1F,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,OAAO,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAA;KAAE;IAI/C,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIlB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,YAAY,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA+C;gBAEjD,OAAO,EAAE,yBAAyB;IAS9C,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAQlB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB/B,OAAO,CAAC,WAAW;YAUL,MAAM;CAQrB"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Span processors: SimpleSpanProcessor (synchronous) and BatchSpanProcessor (async, non-blocking).
3
+ */
4
+ /** Synchronous processor — exports each span immediately. For development and testing. */
5
+ export class SimpleSpanProcessor {
6
+ _exporter;
7
+ constructor(options) {
8
+ this._exporter = options.exporter;
9
+ }
10
+ onSpan(span) {
11
+ this._exporter.export(span);
12
+ }
13
+ async shutdown() { }
14
+ }
15
+ /**
16
+ * Non-blocking batch processor — buffers spans and exports in background.
17
+ *
18
+ * When the queue is full, new spans are dropped and spansDropped is incremented.
19
+ * On shutdown, remaining spans are flushed within exportTimeoutMs.
20
+ */
21
+ export class BatchSpanProcessor {
22
+ _exporter;
23
+ _maxQueueSize;
24
+ _scheduleDelayMs;
25
+ _maxExportBatchSize;
26
+ _exportTimeoutMs;
27
+ _queue = [];
28
+ _spansDropped = 0;
29
+ _timer = null;
30
+ constructor(options) {
31
+ this._exporter = options.exporter;
32
+ this._maxQueueSize = options.maxQueueSize ?? 2048;
33
+ this._scheduleDelayMs = options.scheduleDelayMs ?? 5000;
34
+ this._maxExportBatchSize = options.maxExportBatchSize ?? 512;
35
+ this._exportTimeoutMs = options.exportTimeoutMs ?? 30000;
36
+ this._startTimer();
37
+ }
38
+ get queueSize() {
39
+ return this._queue.length;
40
+ }
41
+ get spansDropped() {
42
+ return this._spansDropped;
43
+ }
44
+ onSpan(span) {
45
+ if (this._queue.length >= this._maxQueueSize) {
46
+ this._spansDropped++;
47
+ return;
48
+ }
49
+ this._queue.push(span);
50
+ }
51
+ async shutdown() {
52
+ if (this._timer !== null) {
53
+ clearInterval(this._timer);
54
+ this._timer = null;
55
+ }
56
+ let timeoutId = null;
57
+ const timeoutPromise = new Promise((_, reject) => {
58
+ timeoutId = setTimeout(() => reject(new Error('Export timeout')), this._exportTimeoutMs);
59
+ });
60
+ try {
61
+ await Promise.race([this._flush(), timeoutPromise]);
62
+ }
63
+ catch {
64
+ this._queue = [];
65
+ }
66
+ finally {
67
+ if (timeoutId !== null)
68
+ clearTimeout(timeoutId);
69
+ }
70
+ }
71
+ _startTimer() {
72
+ this._timer = setInterval(() => {
73
+ void this._flush();
74
+ }, this._scheduleDelayMs);
75
+ // Prevent the timer from keeping the Node.js event loop alive in tests
76
+ if (typeof this._timer.unref === 'function') {
77
+ this._timer.unref();
78
+ }
79
+ }
80
+ async _flush() {
81
+ while (this._queue.length > 0) {
82
+ const batch = this._queue.splice(0, this._maxExportBatchSize);
83
+ for (const span of batch) {
84
+ this._exporter.export(span);
85
+ }
86
+ }
87
+ }
88
+ }
89
+ //# sourceMappingURL=batch-span-processor.js.map