@runtime-digital-twin/sdk 1.0.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 (56) hide show
  1. package/README.md +214 -0
  2. package/dist/constants.d.ts +11 -0
  3. package/dist/constants.d.ts.map +1 -0
  4. package/dist/constants.js +13 -0
  5. package/dist/db-wrapper.d.ts +258 -0
  6. package/dist/db-wrapper.d.ts.map +1 -0
  7. package/dist/db-wrapper.js +636 -0
  8. package/dist/event-envelope.d.ts +35 -0
  9. package/dist/event-envelope.d.ts.map +1 -0
  10. package/dist/event-envelope.js +101 -0
  11. package/dist/fastify-plugin.d.ts +29 -0
  12. package/dist/fastify-plugin.d.ts.map +1 -0
  13. package/dist/fastify-plugin.js +243 -0
  14. package/dist/http-sentinels.d.ts +39 -0
  15. package/dist/http-sentinels.d.ts.map +1 -0
  16. package/dist/http-sentinels.js +169 -0
  17. package/dist/http-wrapper.d.ts +25 -0
  18. package/dist/http-wrapper.d.ts.map +1 -0
  19. package/dist/http-wrapper.js +477 -0
  20. package/dist/index.d.ts +19 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +93 -0
  23. package/dist/invariants.d.ts +58 -0
  24. package/dist/invariants.d.ts.map +1 -0
  25. package/dist/invariants.js +192 -0
  26. package/dist/multi-service-edge-builder.d.ts +80 -0
  27. package/dist/multi-service-edge-builder.d.ts.map +1 -0
  28. package/dist/multi-service-edge-builder.js +107 -0
  29. package/dist/outbound-matcher.d.ts +192 -0
  30. package/dist/outbound-matcher.d.ts.map +1 -0
  31. package/dist/outbound-matcher.js +457 -0
  32. package/dist/peer-service-resolver.d.ts +22 -0
  33. package/dist/peer-service-resolver.d.ts.map +1 -0
  34. package/dist/peer-service-resolver.js +85 -0
  35. package/dist/redaction.d.ts +111 -0
  36. package/dist/redaction.d.ts.map +1 -0
  37. package/dist/redaction.js +487 -0
  38. package/dist/replay-logger.d.ts +438 -0
  39. package/dist/replay-logger.d.ts.map +1 -0
  40. package/dist/replay-logger.js +434 -0
  41. package/dist/root-cause-analyzer.d.ts +45 -0
  42. package/dist/root-cause-analyzer.d.ts.map +1 -0
  43. package/dist/root-cause-analyzer.js +606 -0
  44. package/dist/shape-digest-utils.d.ts +45 -0
  45. package/dist/shape-digest-utils.d.ts.map +1 -0
  46. package/dist/shape-digest-utils.js +154 -0
  47. package/dist/trace-bundle-writer.d.ts +52 -0
  48. package/dist/trace-bundle-writer.d.ts.map +1 -0
  49. package/dist/trace-bundle-writer.js +267 -0
  50. package/dist/trace-loader.d.ts +69 -0
  51. package/dist/trace-loader.d.ts.map +1 -0
  52. package/dist/trace-loader.js +146 -0
  53. package/dist/trace-uploader.d.ts +25 -0
  54. package/dist/trace-uploader.d.ts.map +1 -0
  55. package/dist/trace-uploader.js +132 -0
  56. package/package.json +63 -0
@@ -0,0 +1,477 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setTraceContext = setTraceContext;
4
+ exports.getTraceContext = getTraceContext;
5
+ exports.wrapFetch = wrapFetch;
6
+ const trace_bundle_writer_1 = require("./trace-bundle-writer");
7
+ const async_hooks_1 = require("async_hooks");
8
+ const peer_service_resolver_1 = require("./peer-service-resolver");
9
+ const shape_digest_utils_1 = require("./shape-digest-utils");
10
+ const http_sentinels_1 = require("./http-sentinels");
11
+ // Use AsyncLocalStorage for request-scoped trace context
12
+ const traceContextStorage = new async_hooks_1.AsyncLocalStorage();
13
+ /**
14
+ * Set the current trace context (called by Fastify plugin)
15
+ * Note: This uses enterWith which sets the context for the current async execution
16
+ */
17
+ function setTraceContext(bundle, spanId) {
18
+ if (bundle && spanId) {
19
+ traceContextStorage.enterWith({ bundle, spanId });
20
+ }
21
+ else {
22
+ // For clearing, we can't use enterWith with null, so we'll check in getTraceContext
23
+ // In practice, the context will be naturally cleared when the async context ends
24
+ }
25
+ }
26
+ /**
27
+ * Get the current trace context
28
+ */
29
+ function getTraceContext() {
30
+ const context = traceContextStorage.getStore();
31
+ if (!context) {
32
+ return { bundle: null, spanId: null };
33
+ }
34
+ return { bundle: context.bundle, spanId: context.spanId };
35
+ }
36
+ /**
37
+ * Wrap fetch/undici to capture outbound HTTP calls
38
+ */
39
+ function wrapFetch(originalFetch) {
40
+ return async function wrappedFetch(input, init) {
41
+ const { bundle, spanId } = getTraceContext();
42
+ const mode = process.env.RDT_MODE;
43
+ const mockBase = process.env.RDT_MOCK_BASE;
44
+ // L2-5: SUBGRAPH mode - route calls based on service boundaries
45
+ // In replay mode, check if call is leaving subgraph
46
+ if (mode === 'replay' && mockBase) {
47
+ const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
48
+ const urlObj = new URL(url);
49
+ // L2-5: Check if this call is leaving the subgraph
50
+ const subgraphServicesJson = process.env.RDT_SUBGRAPH_SERVICES;
51
+ const stubServicesJson = process.env.RDT_STUB_SERVICES;
52
+ let shouldRouteToMock = true; // Default: route to mock server
53
+ if (subgraphServicesJson) {
54
+ try {
55
+ const subgraphServices = JSON.parse(subgraphServicesJson);
56
+ const stubServices = stubServicesJson ? JSON.parse(stubServicesJson) : [];
57
+ // Resolve peer service from hostname
58
+ const hostname = urlObj.hostname;
59
+ const { peerService } = (0, peer_service_resolver_1.resolvePeerService)(hostname);
60
+ // L2-5: Route logic:
61
+ // - If peerService is in subgraphServices → route to actual service (not implemented yet, route to mock for now)
62
+ // - If peerService is in stubServices → route to mock server (stub)
63
+ // - If peerService is NOT in subgraphServices → route to mock server (stub)
64
+ // - If peerService is null → route to mock server (stub)
65
+ if (peerService) {
66
+ if (subgraphServices.includes(peerService)) {
67
+ // Call is to a service in subgraph - should route to actual service
68
+ // TODO: Implement actual service routing (requires service discovery/URL mapping)
69
+ // For now, route to mock server as fallback
70
+ shouldRouteToMock = true;
71
+ }
72
+ else if (stubServices.includes(peerService)) {
73
+ // Call is to a stubbed service - route to mock server
74
+ shouldRouteToMock = true;
75
+ }
76
+ else {
77
+ // Call is to a service outside subgraph - route to mock server (stub)
78
+ shouldRouteToMock = true;
79
+ }
80
+ }
81
+ else {
82
+ // Cannot resolve peer service - route to mock server (safe default)
83
+ shouldRouteToMock = true;
84
+ }
85
+ }
86
+ catch (error) {
87
+ // Failed to parse subgraph config - fall back to routing all to mock
88
+ console.warn(`[SDK] Failed to parse SUBGRAPH config: ${error}`);
89
+ shouldRouteToMock = true;
90
+ }
91
+ }
92
+ // Route to mock server but keep path+query for matching
93
+ // The mock server will match based on method + path+query + body hash
94
+ const mockUrl = `${mockBase}${urlObj.pathname}${urlObj.search}`;
95
+ // Make request to mock server
96
+ try {
97
+ const response = await originalFetch(mockUrl, init);
98
+ // L2-5: Check if mock server returned 502 (no match) - FAIL LOUDLY
99
+ if (response.status === 502) {
100
+ let errorBody = {};
101
+ try {
102
+ errorBody = await response.json();
103
+ }
104
+ catch {
105
+ // Ignore JSON parse errors
106
+ }
107
+ // L2-5: Typed error for missing stub
108
+ const errorMessage = `[Replay] Outbound HTTP call not found in trace (missing stub): ${url}\n` +
109
+ `Computed match key: ${errorBody.computedKey || 'unknown'}\n` +
110
+ `This call was not recorded in the trace bundle.\n` +
111
+ `In SUBGRAPH mode, calls leaving the subgraph must have recorded stubs.`;
112
+ throw new Error(errorMessage);
113
+ }
114
+ return response;
115
+ }
116
+ catch (error) {
117
+ // Block unknown network calls - fail loudly
118
+ if (error.message.includes('[Replay]')) {
119
+ throw error; // Re-throw our custom error
120
+ }
121
+ throw new Error(`[Replay] Outbound HTTP call blocked: ${url}\n` +
122
+ `Mock server base: ${mockBase}\n` +
123
+ `Original error: ${error.message}`);
124
+ }
125
+ }
126
+ // Record mode: capture and make real request
127
+ if (!bundle || !spanId) {
128
+ // No trace context - in replay mode this should not happen
129
+ if (mode === 'replay') {
130
+ throw new Error('[Replay] Outbound HTTP call made without trace context');
131
+ }
132
+ return originalFetch(input, init);
133
+ }
134
+ const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
135
+ const method = init?.method || 'GET';
136
+ const headers = init?.headers ? init.headers : {};
137
+ const body = init?.body || null;
138
+ const requestSpanId = (0, trace_bundle_writer_1.generateSpanId)();
139
+ const startTime = Date.now();
140
+ // Extract peer service and hostname
141
+ let hostname = null;
142
+ try {
143
+ const urlObj = new URL(url);
144
+ hostname = urlObj.hostname;
145
+ }
146
+ catch {
147
+ // URL parsing failed, try to extract hostname manually
148
+ const hostMatch = url.match(/^https?:\/\/([^\/]+)/);
149
+ if (hostMatch) {
150
+ hostname = hostMatch[1];
151
+ }
152
+ }
153
+ const { peerService, peerHost } = hostname ? (0, peer_service_resolver_1.resolvePeerService)(hostname) : { peerService: null, peerHost: null };
154
+ const urlTemplate = (0, peer_service_resolver_1.extractUrlTemplate)(url);
155
+ // Process request body
156
+ let requestBody = null;
157
+ if (body) {
158
+ if (typeof body === 'string') {
159
+ requestBody = body;
160
+ }
161
+ else if (Buffer.isBuffer(body)) {
162
+ requestBody = body;
163
+ }
164
+ else if (body instanceof FormData || body instanceof URLSearchParams) {
165
+ // For FormData/URLSearchParams, we'll skip body capture for P0
166
+ requestBody = null;
167
+ }
168
+ else {
169
+ requestBody = JSON.stringify(body);
170
+ }
171
+ }
172
+ const { bodyHash: requestBodyHash, bodyBlob: requestBodyBlob } = await (0, trace_bundle_writer_1.processBody)(requestBody, bundle.writeBlob);
173
+ // Filter headers
174
+ const filteredHeaders = (0, trace_bundle_writer_1.filterHeaders)(headers);
175
+ // Inject trace context propagation headers
176
+ const propagationHeaders = {};
177
+ if (bundle.traceId) {
178
+ propagationHeaders['x-wraith-trace-id'] = bundle.traceId;
179
+ }
180
+ propagationHeaders['x-wraith-parent-span-id'] = requestSpanId;
181
+ // Merge propagation headers with existing headers
182
+ // Note: Headers object might be Headers instance, Record, or array of tuples
183
+ let mergedHeaders;
184
+ if (init?.headers instanceof Headers) {
185
+ const headers = new Headers(init.headers);
186
+ Object.entries(propagationHeaders).forEach(([key, value]) => {
187
+ headers.set(key, value);
188
+ });
189
+ mergedHeaders = headers;
190
+ }
191
+ else if (Array.isArray(init?.headers)) {
192
+ mergedHeaders = [
193
+ ...init.headers,
194
+ ...Object.entries(propagationHeaders),
195
+ ];
196
+ }
197
+ else {
198
+ mergedHeaders = {
199
+ ...(init?.headers || {}),
200
+ ...propagationHeaders,
201
+ };
202
+ }
203
+ // Create new init object with merged headers
204
+ const enhancedInit = {
205
+ ...init,
206
+ headers: mergedHeaders,
207
+ };
208
+ try {
209
+ // Make the actual HTTP request with propagation headers
210
+ const response = await originalFetch(input, enhancedInit);
211
+ const endTime = Date.now();
212
+ const durationMs = endTime - startTime;
213
+ // Debug logging
214
+ if (process.env.DEBUG_HTTP_WRAPPER) {
215
+ console.log('[HTTP_WRAPPER] Response received:', {
216
+ status: response.status,
217
+ headersType: response.headers?.constructor?.name,
218
+ hasForEach: typeof response.headers?.forEach === 'function',
219
+ });
220
+ }
221
+ // Read response body (clone response so we can read it without consuming the original)
222
+ let responseClone;
223
+ try {
224
+ responseClone = response.clone();
225
+ }
226
+ catch (error) {
227
+ if (process.env.DEBUG_HTTP_WRAPPER) {
228
+ console.error('[HTTP_WRAPPER] Failed to clone response:', error);
229
+ }
230
+ throw error;
231
+ }
232
+ let responseBody = null;
233
+ let responseBodyForDigest = null;
234
+ try {
235
+ const contentType = response.headers.get('content-type') || '';
236
+ if (process.env.DEBUG_HTTP_WRAPPER) {
237
+ console.log('[HTTP_WRAPPER] Content-Type:', contentType);
238
+ }
239
+ if (contentType.includes('application/json') || contentType.includes('text/')) {
240
+ responseBody = await responseClone.text();
241
+ responseBodyForDigest = responseBody;
242
+ if (process.env.DEBUG_HTTP_WRAPPER) {
243
+ console.log('[HTTP_WRAPPER] Response body read, length:', responseBody?.length);
244
+ }
245
+ }
246
+ else {
247
+ // For shape digest, try to read body even if content-type isn't explicitly JSON/text
248
+ // This allows us to compute digests for JSON responses with missing/wrong content-type
249
+ try {
250
+ responseBodyForDigest = await responseClone.text();
251
+ // Try to parse as JSON - if it fails, we'll skip digest computation
252
+ try {
253
+ JSON.parse(responseBodyForDigest);
254
+ // If parse succeeds, use it for digest
255
+ }
256
+ catch {
257
+ // Not JSON, don't use for digest
258
+ responseBodyForDigest = null;
259
+ }
260
+ }
261
+ catch {
262
+ // Failed to read, skip
263
+ }
264
+ }
265
+ }
266
+ catch (error) {
267
+ if (process.env.DEBUG_HTTP_WRAPPER) {
268
+ console.error('[HTTP_WRAPPER] Failed to read response body:', error);
269
+ }
270
+ // Failed to read response body, continue without it
271
+ }
272
+ const { bodyHash: responseBodyHash, bodyBlob: responseBodyBlob } = await (0, trace_bundle_writer_1.processBody)(responseBody, bundle.writeBlob);
273
+ // Filter response headers
274
+ const responseHeaders = {};
275
+ try {
276
+ response.headers.forEach((value, key) => {
277
+ responseHeaders[key] = value;
278
+ });
279
+ if (process.env.DEBUG_HTTP_WRAPPER) {
280
+ console.log('[HTTP_WRAPPER] Response headers processed:', Object.keys(responseHeaders));
281
+ }
282
+ }
283
+ catch (error) {
284
+ if (process.env.DEBUG_HTTP_WRAPPER) {
285
+ console.error('[HTTP_WRAPPER] Failed to process response headers:', error);
286
+ console.error('[HTTP_WRAPPER] Headers object:', {
287
+ type: typeof response.headers,
288
+ constructor: response.headers?.constructor?.name,
289
+ hasForEach: typeof response.headers?.forEach === 'function',
290
+ keys: response.headers ? Object.keys(response.headers) : 'null',
291
+ });
292
+ }
293
+ // Try to extract headers manually if forEach fails
294
+ if (response.headers && typeof response.headers === 'object') {
295
+ try {
296
+ for (const [key, value] of Object.entries(response.headers)) {
297
+ responseHeaders[key] = String(value);
298
+ }
299
+ }
300
+ catch (e) {
301
+ // Ignore
302
+ }
303
+ }
304
+ }
305
+ const filteredResponseHeaders = (0, trace_bundle_writer_1.filterHeaders)(responseHeaders);
306
+ // Compute shape digests (async, non-blocking)
307
+ const mode = (0, shape_digest_utils_1.getShapeDigestMode)();
308
+ const sampleRate = (0, shape_digest_utils_1.getShapeDigestSampleRate)();
309
+ const requestContentType = (0, shape_digest_utils_1.getContentType)(headers);
310
+ const responseContentType = (0, shape_digest_utils_1.getContentType)(response.headers);
311
+ if (process.env.DEBUG_HTTP_WRAPPER) {
312
+ console.log('[HTTP_WRAPPER] Content types:', {
313
+ request: requestContentType,
314
+ response: responseContentType,
315
+ mode,
316
+ sampleRate,
317
+ });
318
+ }
319
+ const statusCode = response.status;
320
+ const hasError = statusCode >= 400;
321
+ let requestShapeDigest = null;
322
+ let responseShapeDigest = null;
323
+ try {
324
+ [requestShapeDigest, responseShapeDigest] = await Promise.all([
325
+ (0, shape_digest_utils_1.computeBodyShapeDigest)(requestBody, requestContentType, {
326
+ mode,
327
+ sampleRate,
328
+ statusCode,
329
+ hasError,
330
+ }),
331
+ (0, shape_digest_utils_1.computeBodyShapeDigest)(responseBodyForDigest || responseBody, responseContentType, {
332
+ mode,
333
+ sampleRate,
334
+ statusCode,
335
+ hasError,
336
+ }),
337
+ ]);
338
+ if (process.env.DEBUG_HTTP_WRAPPER) {
339
+ console.log('[HTTP_WRAPPER] Shape digests computed:', {
340
+ request: !!requestShapeDigest,
341
+ response: !!responseShapeDigest,
342
+ responseKind: responseShapeDigest?.kind,
343
+ responseNullPaths: responseShapeDigest?.nullPaths?.length,
344
+ });
345
+ }
346
+ }
347
+ catch (error) {
348
+ if (process.env.DEBUG_HTTP_WRAPPER) {
349
+ console.error('[HTTP_WRAPPER] Failed to compute shape digests:', error);
350
+ }
351
+ // Continue without digests
352
+ }
353
+ const requestSizeBytes = (0, shape_digest_utils_1.getBodySizeBytes)(requestBody);
354
+ const responseSizeBytes = (0, shape_digest_utils_1.getBodySizeBytes)(responseBody);
355
+ if (process.env.DEBUG_HTTP_WRAPPER) {
356
+ console.log('[HTTP_WRAPPER] Body sizes:', {
357
+ request: requestSizeBytes,
358
+ response: responseSizeBytes,
359
+ });
360
+ }
361
+ // Check response sentinels (automatic contract checking)
362
+ // This emits state.invariant events for contract violations
363
+ try {
364
+ await (0, http_sentinels_1.checkResponseSentinels)(responseShapeDigest, statusCode, responseBodyForDigest || responseBody, requestSpanId, // Use requestSpanId so sentinel is attached to outbound call
365
+ spanId // parentSpanId
366
+ );
367
+ if (process.env.DEBUG_HTTP_WRAPPER) {
368
+ console.log('[HTTP_WRAPPER] Sentinels checked');
369
+ }
370
+ }
371
+ catch (error) {
372
+ if (process.env.DEBUG_HTTP_WRAPPER) {
373
+ console.error('[HTTP_WRAPPER] Failed to check sentinels:', error);
374
+ }
375
+ // Continue without sentinels
376
+ }
377
+ // Write http.request.outbound event (after completion with statusCode and durationMs)
378
+ const outboundEvent = {
379
+ type: 'http.request.outbound',
380
+ timestamp: startTime, // Use start time for request timestamp
381
+ spanId: requestSpanId,
382
+ parentSpanId: spanId,
383
+ method,
384
+ url,
385
+ headers: filteredHeaders,
386
+ bodyHash: requestBodyHash,
387
+ bodyBlob: requestBodyBlob,
388
+ peerService,
389
+ peerHost,
390
+ urlTemplate,
391
+ statusCode: response.status,
392
+ durationMs,
393
+ ...(requestShapeDigest && { requestShapeDigest }),
394
+ ...(requestContentType && { requestContentType }),
395
+ ...(requestSizeBytes !== undefined && { requestSizeBytes }),
396
+ ...(responseShapeDigest && { responseShapeDigest }),
397
+ ...(responseContentType && { responseContentType }),
398
+ ...(responseSizeBytes !== undefined && { responseSizeBytes }),
399
+ };
400
+ if (process.env.DEBUG_HTTP_WRAPPER) {
401
+ console.log('[HTTP_WRAPPER] Writing outbound event with fields:', {
402
+ statusCode: outboundEvent.statusCode,
403
+ responseContentType: outboundEvent.responseContentType,
404
+ responseSizeBytes: outboundEvent.responseSizeBytes,
405
+ hasResponseShapeDigest: !!outboundEvent.responseShapeDigest,
406
+ hasRequestShapeDigest: !!outboundEvent.requestShapeDigest,
407
+ });
408
+ }
409
+ await bundle.writeEvent(outboundEvent);
410
+ // Write http.response.outbound event
411
+ await bundle.writeEvent({
412
+ type: 'http.response.outbound',
413
+ timestamp: endTime,
414
+ spanId: requestSpanId,
415
+ parentSpanId: spanId,
416
+ statusCode: response.status,
417
+ headers: filteredResponseHeaders,
418
+ bodyHash: responseBodyHash,
419
+ bodyBlob: responseBodyBlob,
420
+ durationMs,
421
+ });
422
+ return response;
423
+ }
424
+ catch (error) {
425
+ if (process.env.DEBUG_HTTP_WRAPPER) {
426
+ console.error('[HTTP_WRAPPER] Error in fetch wrapper:', error);
427
+ console.error('[HTTP_WRAPPER] Error stack:', error.stack);
428
+ }
429
+ const endTime = Date.now();
430
+ const durationMs = endTime - startTime;
431
+ // Compute shape digest for request (errors always include digest)
432
+ const mode = (0, shape_digest_utils_1.getShapeDigestMode)();
433
+ const sampleRate = (0, shape_digest_utils_1.getShapeDigestSampleRate)();
434
+ const requestContentType = (0, shape_digest_utils_1.getContentType)(headers);
435
+ const requestShapeDigest = await (0, shape_digest_utils_1.computeBodyShapeDigest)(requestBody, requestContentType, {
436
+ mode,
437
+ sampleRate,
438
+ statusCode: null,
439
+ hasError: true, // Always compute for errors
440
+ });
441
+ const requestSizeBytes = (0, shape_digest_utils_1.getBodySizeBytes)(requestBody);
442
+ // Write http.request.outbound event (after error with durationMs, null statusCode)
443
+ await bundle.writeEvent({
444
+ type: 'http.request.outbound',
445
+ timestamp: startTime, // Use start time for request timestamp
446
+ spanId: requestSpanId,
447
+ parentSpanId: spanId,
448
+ method,
449
+ url,
450
+ headers: filteredHeaders,
451
+ bodyHash: requestBodyHash,
452
+ bodyBlob: requestBodyBlob,
453
+ peerService,
454
+ peerHost,
455
+ urlTemplate,
456
+ statusCode: null, // Error - no status code
457
+ durationMs,
458
+ ...(requestShapeDigest && { requestShapeDigest }),
459
+ ...(requestContentType && { requestContentType }),
460
+ ...(requestSizeBytes !== undefined && { requestSizeBytes }),
461
+ });
462
+ // Write error event
463
+ await bundle.writeEvent({
464
+ type: 'error',
465
+ timestamp: endTime,
466
+ spanId: requestSpanId,
467
+ parentSpanId: spanId,
468
+ error: {
469
+ name: error.name || 'Error',
470
+ message: error.message || String(error),
471
+ stack: error.stack || undefined,
472
+ },
473
+ });
474
+ throw error;
475
+ }
476
+ };
477
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Runtime Digital Twin SDK
3
+ *
4
+ * In-process instrumentation for capturing runtime behavior.
5
+ */
6
+ export { CURRENT_TRACE_FORMAT_VERSION } from "./constants";
7
+ export { createTrace, processBody, filterHeaders, generateSpanId, type CreateTraceOptions, type TraceBundle, } from "./trace-bundle-writer";
8
+ export { loadTraceMeta, validateTraceStructure, formatTraceLoadFailure, type TraceLoadFailure, type TraceMetadata, type TraceVersionWarning, type TraceLoadResult, } from "./trace-loader";
9
+ export { fastifyTracing, type FastifyTracingOptions } from "./fastify-plugin";
10
+ export { wrapFetch, setTraceContext, getTraceContext } from "./http-wrapper";
11
+ export { OutboundMatcher, normalizeUrl, normalizeHeaders, computeBodyHash, computeMatchSignature, compareOutboundCalls, parseRecordedOutboundCalls, formatOutboundMismatch, formatUnexpectedOutboundCall, formatMissingOutboundCall, formatOutboundCallFailure, type ReplayMode, type OutboundRequestMismatch, type UnexpectedOutboundCall, type MissingOutboundCall, type OutboundCallFailure, type OutboundDivergence, type RecordedOutboundCall, type OutboundCallSignature, } from "./outbound-matcher";
12
+ export { DbQueryMatcher, wrapDbClient, createWrappedDbClient, normalizeSql, computeParamsHash, extractOperation, compareDbQueries, parseRecordedDbQueries, formatDbQueryMismatch, formatUnexpectedDbQuery, formatMissingDbQuery, formatBlockedDbAccess, formatDbQueryFailure, type DbReplayMode, type DbQueryMismatch, type UnexpectedDbQuery, type MissingDbQuery, type BlockedDbAccess, type DbQueryFailure, type DbQueryDivergence, type RecordedDbQuery, type DbQuerySignature, type DbClient, type WrappedDbClient, type WrapDbClientOptions, type CreateWrappedDbClientOptions, } from "./db-wrapper";
13
+ export { ReplayLogger, getReplayLogger, resetReplayLogger, createReplayLogger, type ReplayLogFormat, type ReplayLogLevel, type ReplayEventCategory, type ReplayEventBase, type ReplayEvent, type ReplayLoggerConfig, type HttpOutboundMatchEvent, type HttpOutboundReturnEvent, type HttpOutboundMismatchEvent, type HttpOutboundUnexpectedEvent, type HttpOutboundMissingEvent, type HttpOutboundBlockedEvent, type DbQueryMatchEvent, type DbQueryReturnEvent, type DbQueryMismatchEvent, type DbQueryUnexpectedEvent, type DbQueryMissingEvent, type DbQueryBlockedEvent, type TraceLoadEvent, type TraceLoadWarningEvent, type TraceLoadErrorEvent, type ReplayStartEvent, type ReplayCompleteEvent, type ReplayErrorEvent, type ReplayDivergenceEvent, } from "./replay-logger";
14
+ export { buildEdges, buildEdgesForTrace, type TraceEvent, type ServiceEdge, } from "./multi-service-edge-builder";
15
+ export { analyzeMultiServiceRootCause, type RootCauseAnalysis, } from "./root-cause-analyzer";
16
+ export { redactHeaders, redactBody, redactBodyObject, redactBodyPatterns, redactQueryParams, redactUrl, loadRedactionConfig, setRedactionConfig, getRedactionConfig, resetRedactionConfig, computeRedactionHash, createRedactedValue, shouldRedactHeader, shouldRedactQueryParam, containsSensitivePatterns, SENSITIVE_HEADERS, SENSITIVE_QUERY_PARAMS, SENSITIVE_BODY_FIELDS, type RedactionRule, type RedactionRuleType, type RedactionConfig, } from "./redaction";
17
+ export { emitInvariant, assertNonNull, assertHasKeys, assertInRange, type InvariantDetails, type EmitInvariantOptions, } from "./invariants";
18
+ export { uploadTrace, type TraceUploadOptions, type TraceUploadResult, } from "./trace-uploader";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * Runtime Digital Twin SDK
4
+ *
5
+ * In-process instrumentation for capturing runtime behavior.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.loadRedactionConfig = exports.redactUrl = exports.redactQueryParams = exports.redactBodyPatterns = exports.redactBodyObject = exports.redactBody = exports.redactHeaders = exports.analyzeMultiServiceRootCause = exports.buildEdgesForTrace = exports.buildEdges = exports.createReplayLogger = exports.resetReplayLogger = exports.getReplayLogger = exports.ReplayLogger = exports.formatDbQueryFailure = exports.formatBlockedDbAccess = exports.formatMissingDbQuery = exports.formatUnexpectedDbQuery = exports.formatDbQueryMismatch = exports.parseRecordedDbQueries = exports.compareDbQueries = exports.extractOperation = exports.computeParamsHash = exports.normalizeSql = exports.createWrappedDbClient = exports.wrapDbClient = exports.DbQueryMatcher = exports.formatOutboundCallFailure = exports.formatMissingOutboundCall = exports.formatUnexpectedOutboundCall = exports.formatOutboundMismatch = exports.parseRecordedOutboundCalls = exports.compareOutboundCalls = exports.computeMatchSignature = exports.computeBodyHash = exports.normalizeHeaders = exports.normalizeUrl = exports.OutboundMatcher = exports.getTraceContext = exports.setTraceContext = exports.wrapFetch = exports.fastifyTracing = exports.formatTraceLoadFailure = exports.validateTraceStructure = exports.loadTraceMeta = exports.generateSpanId = exports.filterHeaders = exports.processBody = exports.createTrace = exports.CURRENT_TRACE_FORMAT_VERSION = void 0;
9
+ exports.uploadTrace = exports.assertInRange = exports.assertHasKeys = exports.assertNonNull = exports.emitInvariant = exports.SENSITIVE_BODY_FIELDS = exports.SENSITIVE_QUERY_PARAMS = exports.SENSITIVE_HEADERS = exports.containsSensitivePatterns = exports.shouldRedactQueryParam = exports.shouldRedactHeader = exports.createRedactedValue = exports.computeRedactionHash = exports.resetRedactionConfig = exports.getRedactionConfig = exports.setRedactionConfig = void 0;
10
+ var constants_1 = require("./constants");
11
+ Object.defineProperty(exports, "CURRENT_TRACE_FORMAT_VERSION", { enumerable: true, get: function () { return constants_1.CURRENT_TRACE_FORMAT_VERSION; } });
12
+ var trace_bundle_writer_1 = require("./trace-bundle-writer");
13
+ Object.defineProperty(exports, "createTrace", { enumerable: true, get: function () { return trace_bundle_writer_1.createTrace; } });
14
+ Object.defineProperty(exports, "processBody", { enumerable: true, get: function () { return trace_bundle_writer_1.processBody; } });
15
+ Object.defineProperty(exports, "filterHeaders", { enumerable: true, get: function () { return trace_bundle_writer_1.filterHeaders; } });
16
+ Object.defineProperty(exports, "generateSpanId", { enumerable: true, get: function () { return trace_bundle_writer_1.generateSpanId; } });
17
+ var trace_loader_1 = require("./trace-loader");
18
+ Object.defineProperty(exports, "loadTraceMeta", { enumerable: true, get: function () { return trace_loader_1.loadTraceMeta; } });
19
+ Object.defineProperty(exports, "validateTraceStructure", { enumerable: true, get: function () { return trace_loader_1.validateTraceStructure; } });
20
+ Object.defineProperty(exports, "formatTraceLoadFailure", { enumerable: true, get: function () { return trace_loader_1.formatTraceLoadFailure; } });
21
+ var fastify_plugin_1 = require("./fastify-plugin");
22
+ Object.defineProperty(exports, "fastifyTracing", { enumerable: true, get: function () { return fastify_plugin_1.fastifyTracing; } });
23
+ var http_wrapper_1 = require("./http-wrapper");
24
+ Object.defineProperty(exports, "wrapFetch", { enumerable: true, get: function () { return http_wrapper_1.wrapFetch; } });
25
+ Object.defineProperty(exports, "setTraceContext", { enumerable: true, get: function () { return http_wrapper_1.setTraceContext; } });
26
+ Object.defineProperty(exports, "getTraceContext", { enumerable: true, get: function () { return http_wrapper_1.getTraceContext; } });
27
+ var outbound_matcher_1 = require("./outbound-matcher");
28
+ Object.defineProperty(exports, "OutboundMatcher", { enumerable: true, get: function () { return outbound_matcher_1.OutboundMatcher; } });
29
+ Object.defineProperty(exports, "normalizeUrl", { enumerable: true, get: function () { return outbound_matcher_1.normalizeUrl; } });
30
+ Object.defineProperty(exports, "normalizeHeaders", { enumerable: true, get: function () { return outbound_matcher_1.normalizeHeaders; } });
31
+ Object.defineProperty(exports, "computeBodyHash", { enumerable: true, get: function () { return outbound_matcher_1.computeBodyHash; } });
32
+ Object.defineProperty(exports, "computeMatchSignature", { enumerable: true, get: function () { return outbound_matcher_1.computeMatchSignature; } });
33
+ Object.defineProperty(exports, "compareOutboundCalls", { enumerable: true, get: function () { return outbound_matcher_1.compareOutboundCalls; } });
34
+ Object.defineProperty(exports, "parseRecordedOutboundCalls", { enumerable: true, get: function () { return outbound_matcher_1.parseRecordedOutboundCalls; } });
35
+ Object.defineProperty(exports, "formatOutboundMismatch", { enumerable: true, get: function () { return outbound_matcher_1.formatOutboundMismatch; } });
36
+ Object.defineProperty(exports, "formatUnexpectedOutboundCall", { enumerable: true, get: function () { return outbound_matcher_1.formatUnexpectedOutboundCall; } });
37
+ Object.defineProperty(exports, "formatMissingOutboundCall", { enumerable: true, get: function () { return outbound_matcher_1.formatMissingOutboundCall; } });
38
+ Object.defineProperty(exports, "formatOutboundCallFailure", { enumerable: true, get: function () { return outbound_matcher_1.formatOutboundCallFailure; } });
39
+ var db_wrapper_1 = require("./db-wrapper");
40
+ Object.defineProperty(exports, "DbQueryMatcher", { enumerable: true, get: function () { return db_wrapper_1.DbQueryMatcher; } });
41
+ Object.defineProperty(exports, "wrapDbClient", { enumerable: true, get: function () { return db_wrapper_1.wrapDbClient; } });
42
+ Object.defineProperty(exports, "createWrappedDbClient", { enumerable: true, get: function () { return db_wrapper_1.createWrappedDbClient; } });
43
+ Object.defineProperty(exports, "normalizeSql", { enumerable: true, get: function () { return db_wrapper_1.normalizeSql; } });
44
+ Object.defineProperty(exports, "computeParamsHash", { enumerable: true, get: function () { return db_wrapper_1.computeParamsHash; } });
45
+ Object.defineProperty(exports, "extractOperation", { enumerable: true, get: function () { return db_wrapper_1.extractOperation; } });
46
+ Object.defineProperty(exports, "compareDbQueries", { enumerable: true, get: function () { return db_wrapper_1.compareDbQueries; } });
47
+ Object.defineProperty(exports, "parseRecordedDbQueries", { enumerable: true, get: function () { return db_wrapper_1.parseRecordedDbQueries; } });
48
+ Object.defineProperty(exports, "formatDbQueryMismatch", { enumerable: true, get: function () { return db_wrapper_1.formatDbQueryMismatch; } });
49
+ Object.defineProperty(exports, "formatUnexpectedDbQuery", { enumerable: true, get: function () { return db_wrapper_1.formatUnexpectedDbQuery; } });
50
+ Object.defineProperty(exports, "formatMissingDbQuery", { enumerable: true, get: function () { return db_wrapper_1.formatMissingDbQuery; } });
51
+ Object.defineProperty(exports, "formatBlockedDbAccess", { enumerable: true, get: function () { return db_wrapper_1.formatBlockedDbAccess; } });
52
+ Object.defineProperty(exports, "formatDbQueryFailure", { enumerable: true, get: function () { return db_wrapper_1.formatDbQueryFailure; } });
53
+ var replay_logger_1 = require("./replay-logger");
54
+ Object.defineProperty(exports, "ReplayLogger", { enumerable: true, get: function () { return replay_logger_1.ReplayLogger; } });
55
+ Object.defineProperty(exports, "getReplayLogger", { enumerable: true, get: function () { return replay_logger_1.getReplayLogger; } });
56
+ Object.defineProperty(exports, "resetReplayLogger", { enumerable: true, get: function () { return replay_logger_1.resetReplayLogger; } });
57
+ Object.defineProperty(exports, "createReplayLogger", { enumerable: true, get: function () { return replay_logger_1.createReplayLogger; } });
58
+ // Multi-service edge builder
59
+ var multi_service_edge_builder_1 = require("./multi-service-edge-builder");
60
+ Object.defineProperty(exports, "buildEdges", { enumerable: true, get: function () { return multi_service_edge_builder_1.buildEdges; } });
61
+ Object.defineProperty(exports, "buildEdgesForTrace", { enumerable: true, get: function () { return multi_service_edge_builder_1.buildEdgesForTrace; } });
62
+ // Root cause analyzer
63
+ var root_cause_analyzer_1 = require("./root-cause-analyzer");
64
+ Object.defineProperty(exports, "analyzeMultiServiceRootCause", { enumerable: true, get: function () { return root_cause_analyzer_1.analyzeMultiServiceRootCause; } });
65
+ // Redaction module
66
+ var redaction_1 = require("./redaction");
67
+ Object.defineProperty(exports, "redactHeaders", { enumerable: true, get: function () { return redaction_1.redactHeaders; } });
68
+ Object.defineProperty(exports, "redactBody", { enumerable: true, get: function () { return redaction_1.redactBody; } });
69
+ Object.defineProperty(exports, "redactBodyObject", { enumerable: true, get: function () { return redaction_1.redactBodyObject; } });
70
+ Object.defineProperty(exports, "redactBodyPatterns", { enumerable: true, get: function () { return redaction_1.redactBodyPatterns; } });
71
+ Object.defineProperty(exports, "redactQueryParams", { enumerable: true, get: function () { return redaction_1.redactQueryParams; } });
72
+ Object.defineProperty(exports, "redactUrl", { enumerable: true, get: function () { return redaction_1.redactUrl; } });
73
+ Object.defineProperty(exports, "loadRedactionConfig", { enumerable: true, get: function () { return redaction_1.loadRedactionConfig; } });
74
+ Object.defineProperty(exports, "setRedactionConfig", { enumerable: true, get: function () { return redaction_1.setRedactionConfig; } });
75
+ Object.defineProperty(exports, "getRedactionConfig", { enumerable: true, get: function () { return redaction_1.getRedactionConfig; } });
76
+ Object.defineProperty(exports, "resetRedactionConfig", { enumerable: true, get: function () { return redaction_1.resetRedactionConfig; } });
77
+ Object.defineProperty(exports, "computeRedactionHash", { enumerable: true, get: function () { return redaction_1.computeRedactionHash; } });
78
+ Object.defineProperty(exports, "createRedactedValue", { enumerable: true, get: function () { return redaction_1.createRedactedValue; } });
79
+ Object.defineProperty(exports, "shouldRedactHeader", { enumerable: true, get: function () { return redaction_1.shouldRedactHeader; } });
80
+ Object.defineProperty(exports, "shouldRedactQueryParam", { enumerable: true, get: function () { return redaction_1.shouldRedactQueryParam; } });
81
+ Object.defineProperty(exports, "containsSensitivePatterns", { enumerable: true, get: function () { return redaction_1.containsSensitivePatterns; } });
82
+ Object.defineProperty(exports, "SENSITIVE_HEADERS", { enumerable: true, get: function () { return redaction_1.SENSITIVE_HEADERS; } });
83
+ Object.defineProperty(exports, "SENSITIVE_QUERY_PARAMS", { enumerable: true, get: function () { return redaction_1.SENSITIVE_QUERY_PARAMS; } });
84
+ Object.defineProperty(exports, "SENSITIVE_BODY_FIELDS", { enumerable: true, get: function () { return redaction_1.SENSITIVE_BODY_FIELDS; } });
85
+ // Invariant checking
86
+ var invariants_1 = require("./invariants");
87
+ Object.defineProperty(exports, "emitInvariant", { enumerable: true, get: function () { return invariants_1.emitInvariant; } });
88
+ Object.defineProperty(exports, "assertNonNull", { enumerable: true, get: function () { return invariants_1.assertNonNull; } });
89
+ Object.defineProperty(exports, "assertHasKeys", { enumerable: true, get: function () { return invariants_1.assertHasKeys; } });
90
+ Object.defineProperty(exports, "assertInRange", { enumerable: true, get: function () { return invariants_1.assertInRange; } });
91
+ // Trace upload
92
+ var trace_uploader_1 = require("./trace-uploader");
93
+ Object.defineProperty(exports, "uploadTrace", { enumerable: true, get: function () { return trace_uploader_1.uploadTrace; } });