autotel 4.0.0 → 4.2.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 (232) hide show
  1. package/README.md +26 -1
  2. package/dist/auto.cjs +2 -2
  3. package/dist/auto.js +1 -1
  4. package/dist/correlation-id.cjs +1 -1
  5. package/dist/correlation-id.js +1 -1
  6. package/dist/decorators.cjs +1 -1
  7. package/dist/decorators.js +1 -1
  8. package/dist/{event-Dlqr4ZNL.cjs → event-BhHREDJk.cjs} +3 -3
  9. package/dist/{event-Dlqr4ZNL.cjs.map → event-BhHREDJk.cjs.map} +1 -1
  10. package/dist/{event-_58ryBjh.js → event-ByBTV9M2.js} +3 -3
  11. package/dist/{event-_58ryBjh.js.map → event-ByBTV9M2.js.map} +1 -1
  12. package/dist/event.cjs +1 -1
  13. package/dist/event.js +1 -1
  14. package/dist/{functional-BGkT8J-h.js → functional-DtI0u4vx.js} +19 -19
  15. package/dist/functional-DtI0u4vx.js.map +1 -0
  16. package/dist/{functional-C4CzoVrX.cjs → functional-zpzNLhky.cjs} +4 -4
  17. package/dist/{functional-C4CzoVrX.cjs.map → functional-zpzNLhky.cjs.map} +1 -1
  18. package/dist/functional.cjs +1 -1
  19. package/dist/functional.js +1 -1
  20. package/dist/http.cjs +1 -1
  21. package/dist/http.js +1 -1
  22. package/dist/index.cjs +5 -5
  23. package/dist/index.d.cts +1 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.js +5 -5
  26. package/dist/{init-DJQOdVlN.d.ts → init-B7u-DjxM.d.ts} +57 -2
  27. package/dist/init-B7u-DjxM.d.ts.map +1 -0
  28. package/dist/{init-DvapOXCc.cjs → init-BX7AmFRl.cjs} +40 -21
  29. package/dist/init-BX7AmFRl.cjs.map +1 -0
  30. package/dist/{init-Ch6t7MNI.js → init-D-jnNMix.js} +39 -20
  31. package/dist/init-D-jnNMix.js.map +1 -0
  32. package/dist/{init-CNp-ee80.d.cts → init-DSrRmVnz.d.cts} +57 -2
  33. package/dist/init-DSrRmVnz.d.cts.map +1 -0
  34. package/dist/instrumentation.cjs +1 -1
  35. package/dist/instrumentation.js +1 -1
  36. package/dist/logger-D3Ej3DII.js +446 -0
  37. package/dist/logger-D3Ej3DII.js.map +1 -0
  38. package/dist/logger-thMPLpOG.cjs +487 -0
  39. package/dist/logger-thMPLpOG.cjs.map +1 -0
  40. package/dist/logger.cjs +8 -236
  41. package/dist/logger.js +2 -204
  42. package/dist/messaging.cjs +1 -1
  43. package/dist/messaging.js +1 -1
  44. package/dist/semantic-helpers.cjs +1 -1
  45. package/dist/semantic-helpers.js +1 -1
  46. package/dist/{track-3HY4NGV-.cjs → track-D59FfpL0.cjs} +2 -2
  47. package/dist/{track-3HY4NGV-.cjs.map → track-D59FfpL0.cjs.map} +1 -1
  48. package/dist/{track-nsKVy-pj.js → track-wc0HafS_.js} +6 -6
  49. package/dist/track-wc0HafS_.js.map +1 -0
  50. package/dist/webhook.cjs +1 -1
  51. package/dist/webhook.js +1 -1
  52. package/dist/workflow-distributed.cjs +1 -1
  53. package/dist/workflow-distributed.js +1 -1
  54. package/dist/workflow.cjs +1 -1
  55. package/dist/workflow.js +1 -1
  56. package/dist/{yaml-config-B3dQ82GR.cjs → yaml-config-Ck2uB0Dp.cjs} +2 -1
  57. package/dist/yaml-config-Ck2uB0Dp.cjs.map +1 -0
  58. package/dist/yaml-config.cjs +1 -1
  59. package/dist/yaml-config.d.cts +7 -1
  60. package/dist/yaml-config.d.cts.map +1 -1
  61. package/dist/yaml-config.d.ts +7 -1
  62. package/dist/yaml-config.d.ts.map +1 -1
  63. package/dist/yaml-config.js +1 -0
  64. package/dist/yaml-config.js.map +1 -1
  65. package/package.json +1 -2
  66. package/skills/autotel-core/SKILL.md +2 -0
  67. package/skills/autotel-instrumentation/SKILL.md +25 -0
  68. package/skills/debug-missing-spans/SKILL.md +3 -1
  69. package/skills/migrate-to-autotel/SKILL.md +24 -23
  70. package/skills/review-otel-patterns/SKILL.md +5 -4
  71. package/dist/functional-BGkT8J-h.js.map +0 -1
  72. package/dist/init-CNp-ee80.d.cts.map +0 -1
  73. package/dist/init-Ch6t7MNI.js.map +0 -1
  74. package/dist/init-DJQOdVlN.d.ts.map +0 -1
  75. package/dist/init-DvapOXCc.cjs.map +0 -1
  76. package/dist/logger.cjs.map +0 -1
  77. package/dist/logger.js.map +0 -1
  78. package/dist/track-nsKVy-pj.js.map +0 -1
  79. package/dist/yaml-config-B3dQ82GR.cjs.map +0 -1
  80. package/src/attribute-redacting-processor.test.ts +0 -763
  81. package/src/attribute-redacting-processor.ts +0 -621
  82. package/src/attributes/attachers.ts +0 -161
  83. package/src/attributes/builders.ts +0 -529
  84. package/src/attributes/domains.ts +0 -42
  85. package/src/attributes/index.ts +0 -81
  86. package/src/attributes/registry.ts +0 -323
  87. package/src/attributes/types.ts +0 -211
  88. package/src/attributes/utils.ts +0 -64
  89. package/src/attributes/validators.ts +0 -266
  90. package/src/attributes.test.ts +0 -292
  91. package/src/auto.ts +0 -67
  92. package/src/autotel-logger.test.ts +0 -548
  93. package/src/autotel-logger.ts +0 -364
  94. package/src/baggage-span-processor.test.ts +0 -202
  95. package/src/baggage-span-processor.ts +0 -100
  96. package/src/business-baggage.test.ts +0 -500
  97. package/src/business-baggage.ts +0 -669
  98. package/src/circuit-breaker.test.ts +0 -341
  99. package/src/circuit-breaker.ts +0 -184
  100. package/src/config.test.ts +0 -94
  101. package/src/config.ts +0 -172
  102. package/src/correlated-events.test.ts +0 -151
  103. package/src/correlated-events.ts +0 -47
  104. package/src/correlation-id.test.ts +0 -163
  105. package/src/correlation-id.ts +0 -206
  106. package/src/db.test.ts +0 -252
  107. package/src/db.ts +0 -447
  108. package/src/decorators.test.ts +0 -153
  109. package/src/decorators.ts +0 -188
  110. package/src/define-event.test.ts +0 -41
  111. package/src/define-event.ts +0 -58
  112. package/src/devtools.ts +0 -60
  113. package/src/drain-pipeline.test.ts +0 -68
  114. package/src/drain-pipeline.ts +0 -199
  115. package/src/drain-toolkit.test.ts +0 -113
  116. package/src/drain-toolkit.ts +0 -129
  117. package/src/enricher-toolkit.test.ts +0 -67
  118. package/src/enricher-toolkit.ts +0 -79
  119. package/src/enrichers.test.ts +0 -150
  120. package/src/enrichers.ts +0 -145
  121. package/src/env-config.test.ts +0 -323
  122. package/src/env-config.ts +0 -309
  123. package/src/error-catalog.test.ts +0 -133
  124. package/src/error-catalog.ts +0 -262
  125. package/src/event-queue.test.ts +0 -864
  126. package/src/event-queue.ts +0 -699
  127. package/src/event-subscriber.ts +0 -262
  128. package/src/event-testing.ts +0 -197
  129. package/src/event.test.ts +0 -1104
  130. package/src/event.ts +0 -988
  131. package/src/events-config.ts +0 -235
  132. package/src/exporters.ts +0 -165
  133. package/src/filtering-span-processor.test.ts +0 -281
  134. package/src/filtering-span-processor.ts +0 -111
  135. package/src/flatten-attributes.test.ts +0 -76
  136. package/src/flatten-attributes.ts +0 -80
  137. package/src/functional.strict-types.typecheck.ts +0 -53
  138. package/src/functional.test.ts +0 -1464
  139. package/src/functional.ts +0 -2539
  140. package/src/functional.types.test.ts +0 -135
  141. package/src/hook.mjs +0 -15
  142. package/src/http.test.ts +0 -485
  143. package/src/http.ts +0 -424
  144. package/src/index.ts +0 -433
  145. package/src/init-auto-redactor.test.ts +0 -53
  146. package/src/init-redactor.test.ts +0 -8
  147. package/src/init.customization.test.ts +0 -594
  148. package/src/init.integrations.test.ts +0 -399
  149. package/src/init.openllmetry.test.ts +0 -194
  150. package/src/init.protocol.test.ts +0 -215
  151. package/src/init.ts +0 -2312
  152. package/src/instrumentation.test.ts +0 -108
  153. package/src/instrumentation.ts +0 -319
  154. package/src/logger.test.ts +0 -125
  155. package/src/logger.ts +0 -341
  156. package/src/messaging-adapters.test.ts +0 -595
  157. package/src/messaging-adapters.ts +0 -583
  158. package/src/messaging-testing.test.ts +0 -573
  159. package/src/messaging-testing.ts +0 -935
  160. package/src/messaging.test.ts +0 -1646
  161. package/src/messaging.ts +0 -2245
  162. package/src/metric-helpers.ts +0 -47
  163. package/src/metric-testing.ts +0 -197
  164. package/src/metric.ts +0 -446
  165. package/src/metrics.test.ts +0 -241
  166. package/src/node-require.ts +0 -123
  167. package/src/operation-context.ts +0 -93
  168. package/src/parse-error.test.ts +0 -73
  169. package/src/parse-error.ts +0 -112
  170. package/src/posthog-logs.test.ts +0 -115
  171. package/src/posthog-logs.ts +0 -77
  172. package/src/pretty-console-exporter.test.ts +0 -545
  173. package/src/pretty-console-exporter.ts +0 -413
  174. package/src/pretty-log-formatter.test.ts +0 -123
  175. package/src/pretty-log-formatter.ts +0 -210
  176. package/src/processors/canonical-log-line-processor.test.ts +0 -523
  177. package/src/processors/canonical-log-line-processor.ts +0 -396
  178. package/src/processors.ts +0 -152
  179. package/src/rate-limiter.test.ts +0 -199
  180. package/src/rate-limiter.ts +0 -98
  181. package/src/redact-values.test.ts +0 -90
  182. package/src/redact-values.ts +0 -34
  183. package/src/register.ts +0 -37
  184. package/src/request-logger.test.ts +0 -545
  185. package/src/request-logger.ts +0 -342
  186. package/src/sampling.test.ts +0 -1060
  187. package/src/sampling.ts +0 -737
  188. package/src/security-schema.test.ts +0 -45
  189. package/src/security-schema.ts +0 -107
  190. package/src/semantic-conventions.ts +0 -15
  191. package/src/semantic-helpers.test.ts +0 -226
  192. package/src/semantic-helpers.ts +0 -438
  193. package/src/shutdown.test.ts +0 -364
  194. package/src/shutdown.ts +0 -246
  195. package/src/span-name-normalizer.test.ts +0 -377
  196. package/src/span-name-normalizer.ts +0 -213
  197. package/src/stable-hash.ts +0 -27
  198. package/src/structured-error.test.ts +0 -191
  199. package/src/structured-error.ts +0 -157
  200. package/src/stub.integration.test.ts +0 -361
  201. package/src/tail-sampling-processor.test.ts +0 -230
  202. package/src/tail-sampling-processor.ts +0 -55
  203. package/src/test-span-collector.test.ts +0 -234
  204. package/src/test-span-collector.ts +0 -150
  205. package/src/testing.ts +0 -705
  206. package/src/trace-context.test.ts +0 -73
  207. package/src/trace-context.ts +0 -567
  208. package/src/trace-helpers.new.test.ts +0 -278
  209. package/src/trace-helpers.test.ts +0 -290
  210. package/src/trace-helpers.ts +0 -710
  211. package/src/trace-hybrid.test.ts +0 -42
  212. package/src/trace-hybrid.ts +0 -37
  213. package/src/tracer-provider.test.ts +0 -183
  214. package/src/tracer-provider.ts +0 -266
  215. package/src/track.test.ts +0 -154
  216. package/src/track.ts +0 -216
  217. package/src/validate.test.ts +0 -287
  218. package/src/validate.ts +0 -307
  219. package/src/validation-attributes.ts +0 -43
  220. package/src/validation.test.ts +0 -330
  221. package/src/validation.ts +0 -246
  222. package/src/variable-name-inference.test.ts +0 -178
  223. package/src/variable-name-inference.ts +0 -242
  224. package/src/webhook.test.ts +0 -649
  225. package/src/webhook.ts +0 -637
  226. package/src/workflow-distributed.test.ts +0 -786
  227. package/src/workflow-distributed.ts +0 -916
  228. package/src/workflow.async-safety.integration.test.ts +0 -345
  229. package/src/workflow.test.ts +0 -647
  230. package/src/workflow.ts +0 -810
  231. package/src/yaml-config.test.ts +0 -337
  232. package/src/yaml-config.ts +0 -342
@@ -1,241 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import { Metric, getMetrics, resetMetrics } from './metric';
3
- import { type ILogger } from './logger';
4
- import { init } from './init';
5
- import { configure } from './config';
6
-
7
- describe('Metrics', () => {
8
- let mockLogger: ILogger;
9
-
10
- beforeEach(() => {
11
- resetMetrics();
12
- init({ service: 'test-app' });
13
- configure({
14
- meterName: 'test',
15
- });
16
- mockLogger = {
17
- info: vi.fn(),
18
- warn: vi.fn(),
19
- error: vi.fn(),
20
- debug: vi.fn(),
21
- };
22
- });
23
-
24
- describe('trackEvent', () => {
25
- it('should track business events as metrics', () => {
26
- const metrics = new Metric('test-service', { logger: mockLogger });
27
-
28
- metrics.trackEvent('order.completed', {
29
- orderId: '123',
30
- amount: 99.99,
31
- });
32
-
33
- // Pino-native: (extra, message)
34
- expect(mockLogger.info).toHaveBeenCalledWith(
35
- {
36
- event: 'order.completed',
37
- attributes: { orderId: '123', amount: 99.99 },
38
- },
39
- 'Metric event tracked',
40
- );
41
- });
42
-
43
- it('should track events without attributes', () => {
44
- const metrics = new Metric('test-service', { logger: mockLogger });
45
-
46
- metrics.trackEvent('user.login');
47
-
48
- // Pino-native: (extra, message)
49
- expect(mockLogger.info).toHaveBeenCalledWith(
50
- {
51
- event: 'user.login',
52
- attributes: undefined,
53
- },
54
- 'Metric event tracked',
55
- );
56
- });
57
- });
58
-
59
- describe('trackFunnelStep', () => {
60
- it('should track funnel progression as metrics', () => {
61
- const metrics = new Metric('test-service', { logger: mockLogger });
62
-
63
- metrics.trackFunnelStep('checkout', 'started', { cartValue: 99.99 });
64
- metrics.trackFunnelStep('checkout', 'completed', { cartValue: 99.99 });
65
-
66
- expect(mockLogger.info).toHaveBeenCalledTimes(2);
67
- // Pino-native: (extra, message)
68
- expect(mockLogger.info).toHaveBeenCalledWith(
69
- {
70
- funnel: 'checkout',
71
- status: 'started',
72
- attributes: { cartValue: 99.99 },
73
- },
74
- 'Funnel step tracked',
75
- );
76
- });
77
-
78
- it('should track funnel abandonment', () => {
79
- const metrics = new Metric('test-service', { logger: mockLogger });
80
-
81
- metrics.trackFunnelStep('checkout', 'abandoned', { reason: 'timeout' });
82
-
83
- // Pino-native: (extra, message)
84
- expect(mockLogger.info).toHaveBeenCalledWith(
85
- {
86
- funnel: 'checkout',
87
- status: 'abandoned',
88
- attributes: { reason: 'timeout' },
89
- },
90
- 'Funnel step tracked',
91
- );
92
- });
93
- });
94
-
95
- describe('trackOutcome', () => {
96
- it('should track successful outcomes as metrics', () => {
97
- const metrics = new Metric('test-service', { logger: mockLogger });
98
-
99
- metrics.trackOutcome('payment.process', 'success', {
100
- amount: 99.99,
101
- });
102
-
103
- // Pino-native: (extra, message)
104
- expect(mockLogger.info).toHaveBeenCalledWith(
105
- {
106
- operation: 'payment.process',
107
- status: 'success',
108
- attributes: { amount: 99.99 },
109
- },
110
- 'Outcome tracked',
111
- );
112
- });
113
-
114
- it('should track failed outcomes', () => {
115
- const metrics = new Metric('test-service', { logger: mockLogger });
116
-
117
- metrics.trackOutcome('payment.process', 'failure', {
118
- error: 'insufficient_funds',
119
- });
120
-
121
- // Pino-native: (extra, message)
122
- expect(mockLogger.info).toHaveBeenCalledWith(
123
- {
124
- operation: 'payment.process',
125
- status: 'failure',
126
- attributes: { error: 'insufficient_funds' },
127
- },
128
- 'Outcome tracked',
129
- );
130
- });
131
-
132
- it('should track partial outcomes', () => {
133
- const metrics = new Metric('test-service', { logger: mockLogger });
134
-
135
- metrics.trackOutcome('batch.process', 'partial', {
136
- successCount: 8,
137
- failureCount: 2,
138
- });
139
-
140
- // Pino-native: (extra, message)
141
- expect(mockLogger.info).toHaveBeenCalledWith(
142
- {
143
- operation: 'batch.process',
144
- status: 'partial',
145
- attributes: { successCount: 8, failureCount: 2 },
146
- },
147
- 'Outcome tracked',
148
- );
149
- });
150
- });
151
-
152
- describe('trackValue', () => {
153
- it('should track revenue metrics', () => {
154
- const metrics = new Metric('test-service', { logger: mockLogger });
155
-
156
- metrics.trackValue('order.revenue', 149.99, {
157
- currency: 'USD',
158
- productCategory: 'electronics',
159
- });
160
-
161
- // Pino-native: (extra, message)
162
- expect(mockLogger.debug).toHaveBeenCalledWith(
163
- {
164
- metric: 'order.revenue',
165
- value: 149.99,
166
- attributes: { currency: 'USD', productCategory: 'electronics' },
167
- },
168
- 'Value metric tracked',
169
- );
170
- });
171
-
172
- it('should track processing time', () => {
173
- const metrics = new Metric('test-service', { logger: mockLogger });
174
-
175
- metrics.trackValue('application.processing_time', 2500, {
176
- unit: 'ms',
177
- });
178
-
179
- // Pino-native: (extra, message)
180
- expect(mockLogger.debug).toHaveBeenCalledWith(
181
- {
182
- metric: 'application.processing_time',
183
- value: 2500,
184
- attributes: { unit: 'ms' },
185
- },
186
- 'Value metric tracked',
187
- );
188
- });
189
- });
190
-
191
- describe('getMetrics', () => {
192
- it('should return singleton instance', () => {
193
- const metrics1 = getMetrics('test-service');
194
- const metrics2 = getMetrics('test-service');
195
-
196
- expect(metrics1).toBe(metrics2);
197
- });
198
-
199
- it('should return different instances for different services', () => {
200
- const metrics1 = getMetrics('service-1');
201
- const metrics2 = getMetrics('service-2');
202
-
203
- expect(metrics1).not.toBe(metrics2);
204
- });
205
-
206
- it('should reset instances', () => {
207
- const metrics1 = getMetrics('test-service');
208
- resetMetrics();
209
- const metrics2 = getMetrics('test-service');
210
-
211
- expect(metrics1).not.toBe(metrics2);
212
- });
213
- });
214
-
215
- describe('real-world usage example', () => {
216
- it('should track checkout flow', () => {
217
- const metrics = new Metric('checkout', { logger: mockLogger });
218
-
219
- // User starts checkout
220
- metrics.trackFunnelStep('checkout', 'started', { cartValue: 99.99 });
221
-
222
- // Order completed
223
- metrics.trackEvent('order.completed', {
224
- orderId: 'ord_123',
225
- amount: 99.99,
226
- });
227
- metrics.trackFunnelStep('checkout', 'completed', { cartValue: 99.99 });
228
-
229
- // Payment processed successfully
230
- metrics.trackOutcome('payment.process', 'success', {
231
- amount: 99.99,
232
- });
233
-
234
- // Track revenue
235
- metrics.trackValue('revenue', 99.99, { currency: 'USD' });
236
-
237
- expect(mockLogger.info).toHaveBeenCalledTimes(4);
238
- expect(mockLogger.debug).toHaveBeenCalledTimes(1);
239
- });
240
- });
241
- });
@@ -1,123 +0,0 @@
1
- /**
2
- * Cross-format require() helper for CJS and ESM compatibility
3
- *
4
- * Provides a synchronous `require()` function that works in both:
5
- * - CJS builds: Uses native `require`
6
- * - ESM builds: Uses `createRequire(import.meta.url)`
7
- *
8
- * This allows optional peer dependencies and dynamic module loading
9
- * to work synchronously in both module formats.
10
- */
11
-
12
- import { createRequire } from 'node:module';
13
-
14
- // `__filename` is provided by CJS and by esbuild's CJS output wrapper, but
15
- // is undefined under pure ESM. `import.meta.url` is provided by ESM. Pick
16
- // whichever is available so the helper works in:
17
- // - native CJS (autotel's published `.cjs`)
18
- // - native ESM (autotel's published `.js`)
19
- // - ESM-bundled-into-CJS by a downstream consumer (e.g. CDK's
20
- // `aws-lambda-nodejs` → esbuild with `format: cjs`). esbuild rewrites
21
- // `import.meta` to `{}` in this case, so `createRequire(import.meta.url)`
22
- // alone collapses to `createRequire(undefined)` and crashes at load.
23
- // `typeof __filename` does NOT throw when the identifier is undeclared, so
24
- // the ESM build evaluates the conditional safely.
25
- declare const __filename: string | undefined;
26
-
27
- // Build the Node `require` lazily on first use. Calling `createRequire`
28
- // eagerly at module load crashes in runtimes where neither `__filename` nor
29
- // `import.meta.url` resolves to a path — e.g. Cloudflare Workers / workerd,
30
- // where the bundle has no module path and `createRequire(undefined)` throws
31
- // synchronously at import. Deferring the call keeps merely importing this
32
- // module (and therefore anything that re-exports it, such as `track`)
33
- // side-effect-free; Node/CJS/ESM still get a real `require` on first call.
34
- let cachedRequire: NodeRequire | undefined;
35
-
36
- function getNodeRequire(): NodeRequire {
37
- if (cachedRequire) return cachedRequire;
38
- const base = typeof __filename === 'string' ? __filename : import.meta.url;
39
- if (!base) {
40
- // No module path in this runtime. Surface as a missing-module error so
41
- // optional lookups via `safeRequire()` degrade gracefully to `undefined`.
42
- throw Object.assign(
43
- new Error('node require() is unavailable in this runtime'),
44
- { code: 'MODULE_NOT_FOUND' },
45
- );
46
- }
47
- cachedRequire = createRequire(base);
48
- return cachedRequire;
49
- }
50
-
51
- /**
52
- * Synchronously require a module (works in both CJS and ESM)
53
- *
54
- * @param id - Module ID to require
55
- * @returns The required module
56
- * @throws Error if module cannot be loaded
57
- *
58
- * @example
59
- * ```typescript
60
- * import { safeRequire } from './node-require';
61
- *
62
- * const traceloop = safeRequire('@traceloop/node-server-sdk');
63
- * if (traceloop) {
64
- * traceloop.initialize({ ... });
65
- * }
66
- * ```
67
- */
68
- export function safeRequire<T = unknown>(id: string): T | undefined {
69
- try {
70
- return getNodeRequire()(id) as T;
71
- } catch (error) {
72
- if (error && (error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {
73
- // Optional dependency missing – return undefined
74
- return undefined;
75
- }
76
- // Any other error is a real bug: rethrow
77
- throw error;
78
- }
79
- }
80
-
81
- /**
82
- * Synchronously require a module (throws if not found)
83
- *
84
- * Use this when the module is required (not optional).
85
- *
86
- * @param id - Module ID to require
87
- * @returns The required module
88
- * @throws Error if module cannot be loaded
89
- *
90
- * @example
91
- * ```typescript
92
- * import { requireModule } from './node-require';
93
- *
94
- * const fs = requireModule<typeof import('node:fs')>('node:fs');
95
- * const content = fs.readFileSync('file.txt', 'utf8');
96
- * ```
97
- */
98
- export function requireModule<T = unknown>(id: string): T {
99
- return getNodeRequire()(id) as T;
100
- }
101
-
102
- /**
103
- * Direct access to the nodeRequire function (for advanced use cases).
104
- *
105
- * Lazily resolves the underlying Node `require` on first call, so importing
106
- * this binding never triggers `createRequire` in runtimes that lack a module
107
- * path (e.g. Cloudflare Workers).
108
- *
109
- * Only the call signature and `resolve` (including `resolve.paths`) are
110
- * forwarded. The live, mutable members of a real `require` — `.cache`,
111
- * `.main`, `.extensions` — are intentionally NOT exposed: a lazy wrapper
112
- * can't mirror that shared state without resolving eagerly, which would
113
- * reintroduce the workerd crash. Use `createRequire` directly if you need
114
- * them.
115
- */
116
- const nodeRequire = ((id: string) => getNodeRequire()(id)) as NodeRequire;
117
- const lazyResolve = ((id: string, options?: { paths?: string[] }) =>
118
- getNodeRequire().resolve(id, options)) as NodeRequire['resolve'];
119
- lazyResolve.paths = (request: string) =>
120
- getNodeRequire().resolve.paths(request);
121
- nodeRequire.resolve = lazyResolve;
122
-
123
- export { nodeRequire };
@@ -1,93 +0,0 @@
1
- /**
2
- * Operation context tracking using AsyncLocalStorage
3
- *
4
- * This module provides a way to track operation names across async boundaries
5
- * so they can be automatically captured in events events.
6
- *
7
- * We cannot read span attributes from OpenTelemetry's API (it's write-only),
8
- * so we maintain our own async context storage.
9
- */
10
-
11
- import { AsyncLocalStorage } from 'node:async_hooks';
12
-
13
- /**
14
- * Operation context that flows through async operations
15
- */
16
- export interface OperationContext {
17
- /**
18
- * The name of the current operation
19
- * This is set by trace() or span() and can be read by events
20
- */
21
- name: string;
22
- }
23
-
24
- /**
25
- * AsyncLocalStorage instance for tracking operation context
26
- */
27
- const operationStorage = new AsyncLocalStorage<OperationContext>();
28
-
29
- /**
30
- * Get the current operation context (if any)
31
- *
32
- * @returns The current operation context, or undefined if not in an operation
33
- *
34
- * @example
35
- * ```typescript
36
- * const ctx = getOperationContext();
37
- * if (ctx) {
38
- * console.log('Current operation:', ctx.name);
39
- * }
40
- * ```
41
- */
42
- export function getOperationContext(): OperationContext | undefined {
43
- return operationStorage.getStore();
44
- }
45
-
46
- /**
47
- * Run a function within an operation context
48
- *
49
- * This sets the operation name for the duration of the function execution,
50
- * including all async operations spawned from it.
51
- *
52
- * @param name - The operation name to set
53
- * @param fn - The function to execute within the context
54
- * @returns The result of the function
55
- *
56
- * @example
57
- * ```typescript
58
- * const result = await runInOperationContext('user.create', async () => {
59
- * // Any events.trackEvent() calls here will automatically capture
60
- * // 'operation.name': 'user.create'
61
- * await createUser();
62
- * return 'success';
63
- * });
64
- * ```
65
- */
66
- export function runInOperationContext<T>(name: string, fn: () => T): T {
67
- return operationStorage.run({ name }, fn);
68
- }
69
-
70
- /**
71
- * Update the operation name in the current context
72
- *
73
- * This is useful when you want to change the operation name within
74
- * an already-established context (e.g., when entering a nested span).
75
- *
76
- * @param name - The new operation name
77
- *
78
- * @example
79
- * ```typescript
80
- * runInOperationContext('parent.operation', () => {
81
- * // operation.name is 'parent.operation'
82
- *
83
- * updateOperationName('nested.operation');
84
- * // operation.name is now 'nested.operation'
85
- * });
86
- * ```
87
- */
88
- export function updateOperationName(name: string): void {
89
- const store = operationStorage.getStore();
90
- if (store) {
91
- store.name = name;
92
- }
93
- }
@@ -1,73 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { createStructuredError } from './structured-error';
3
- import { parseError } from './parse-error';
4
-
5
- describe('parseError', () => {
6
- it('parses structured errors with why/fix/link', () => {
7
- const err = createStructuredError({
8
- message: 'Payment failed',
9
- status: 402,
10
- why: 'Card declined',
11
- fix: 'Use another card',
12
- link: 'https://docs.example.com/payment-errors',
13
- code: 'PAYMENT_DECLINED',
14
- });
15
-
16
- const parsed = parseError(err);
17
- expect(parsed).toMatchObject({
18
- message: 'Payment failed',
19
- status: 402,
20
- why: 'Card declined',
21
- fix: 'Use another card',
22
- link: 'https://docs.example.com/payment-errors',
23
- code: 'PAYMENT_DECLINED',
24
- raw: err,
25
- });
26
- });
27
-
28
- it('parses fetch-like nested data payloads', () => {
29
- const fetchLikeError = {
30
- message: 'Request failed',
31
- statusCode: 409,
32
- data: {
33
- statusText: 'Conflict',
34
- data: {
35
- why: 'Order already exists',
36
- fix: 'Use idempotency key',
37
- link: 'https://docs.example.com/idempotency',
38
- code: 'ORDER_EXISTS',
39
- },
40
- },
41
- };
42
-
43
- const parsed = parseError(fetchLikeError);
44
- expect(parsed).toMatchObject({
45
- message: 'Conflict',
46
- status: 409,
47
- why: 'Order already exists',
48
- fix: 'Use idempotency key',
49
- link: 'https://docs.example.com/idempotency',
50
- code: 'ORDER_EXISTS',
51
- raw: fetchLikeError,
52
- });
53
- });
54
-
55
- it('preserves details from structured errors', () => {
56
- const err = createStructuredError({
57
- message: 'Export failed',
58
- status: 500,
59
- details: { retryable: true, provider: 'stripe' },
60
- });
61
-
62
- const parsed = parseError(err);
63
- expect(parsed.details).toEqual({ retryable: true, provider: 'stripe' });
64
- });
65
-
66
- it('falls back for unknown values', () => {
67
- expect(parseError('boom')).toMatchObject({
68
- message: 'boom',
69
- status: 500,
70
- raw: 'boom',
71
- });
72
- });
73
- });
@@ -1,112 +0,0 @@
1
- import type { StructuredError } from './structured-error';
2
-
3
- export interface ParsedError {
4
- message: string;
5
- status: number;
6
- why?: string;
7
- fix?: string;
8
- link?: string;
9
- code?: string | number;
10
- details?: Record<string, unknown>;
11
- raw: unknown;
12
- }
13
-
14
- type ErrorLike = {
15
- message?: unknown;
16
- status?: unknown;
17
- statusCode?: unknown;
18
- data?: unknown;
19
- code?: unknown;
20
- why?: unknown;
21
- fix?: unknown;
22
- link?: unknown;
23
- details?: unknown;
24
- };
25
-
26
- function toStatus(value: unknown): number | undefined {
27
- if (typeof value === 'number' && Number.isFinite(value)) return value;
28
- if (typeof value === 'string') {
29
- const n = Number(value);
30
- if (Number.isFinite(n)) return n;
31
- }
32
- return undefined;
33
- }
34
-
35
- function pickString(value: unknown): string | undefined {
36
- return typeof value === 'string' && value.length > 0 ? value : undefined;
37
- }
38
-
39
- function pickCode(value: unknown): string | number | undefined {
40
- if (typeof value === 'string' || typeof value === 'number') return value;
41
- return undefined;
42
- }
43
-
44
- function pickDetails(value: unknown): Record<string, unknown> | undefined {
45
- if (value && typeof value === 'object' && value.constructor === Object) {
46
- return value as Record<string, unknown>;
47
- }
48
- return undefined;
49
- }
50
-
51
- export function parseError(error: unknown): ParsedError {
52
- if (error instanceof Error) {
53
- const structured = error as StructuredError;
54
- return {
55
- message: error.message || 'An error occurred',
56
- status: toStatus(structured.status) ?? 500,
57
- why: pickString(structured.why),
58
- fix: pickString(structured.fix),
59
- link: pickString(structured.link),
60
- code: pickCode(structured.code),
61
- details: pickDetails(structured.details),
62
- raw: error,
63
- };
64
- }
65
-
66
- if (error && typeof error === 'object') {
67
- const err = error as ErrorLike;
68
- const data =
69
- err.data && typeof err.data === 'object'
70
- ? (err.data as Record<string, unknown>)
71
- : undefined;
72
- const nested =
73
- data?.data && typeof data.data === 'object'
74
- ? (data.data as Record<string, unknown>)
75
- : undefined;
76
- const payload = nested ?? data;
77
-
78
- const message =
79
- pickString(data?.statusText) ||
80
- pickString(data?.statusMessage) ||
81
- pickString(data?.message) ||
82
- pickString(payload?.statusText) ||
83
- pickString(payload?.statusMessage) ||
84
- pickString(payload?.message) ||
85
- pickString(err.message) ||
86
- 'An error occurred';
87
-
88
- const status =
89
- toStatus(payload?.status) ||
90
- toStatus(payload?.statusCode) ||
91
- toStatus(err.status) ||
92
- toStatus(err.statusCode) ||
93
- 500;
94
-
95
- return {
96
- message,
97
- status,
98
- why: pickString(payload?.why) || pickString(err.why),
99
- fix: pickString(payload?.fix) || pickString(err.fix),
100
- link: pickString(payload?.link) || pickString(err.link),
101
- code: pickCode(payload?.code) || pickCode(err.code),
102
- details: pickDetails(payload?.details) || pickDetails(err.details),
103
- raw: error,
104
- };
105
- }
106
-
107
- return {
108
- message: String(error),
109
- status: 500,
110
- raw: error,
111
- };
112
- }