@softprobe/softprobe-js 2.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.
- package/LICENSE +21 -0
- package/README.md +202 -0
- package/bin/softprobe +15 -0
- package/dist/api/baggage.d.ts +13 -0
- package/dist/api/baggage.d.ts.map +1 -0
- package/dist/api/baggage.js +32 -0
- package/dist/api/baggage.js.map +1 -0
- package/dist/api/compare.d.ts +16 -0
- package/dist/api/compare.d.ts.map +1 -0
- package/dist/api/compare.js +77 -0
- package/dist/api/compare.js.map +1 -0
- package/dist/api.d.ts +63 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +104 -0
- package/dist/api.js.map +1 -0
- package/dist/bindings/http-span.d.ts +6 -0
- package/dist/bindings/http-span.d.ts.map +1 -0
- package/dist/bindings/http-span.js +11 -0
- package/dist/bindings/http-span.js.map +1 -0
- package/dist/bindings/postgres-span.d.ts +6 -0
- package/dist/bindings/postgres-span.d.ts.map +1 -0
- package/dist/bindings/postgres-span.js +11 -0
- package/dist/bindings/postgres-span.js.map +1 -0
- package/dist/bindings/redis-span.d.ts +6 -0
- package/dist/bindings/redis-span.d.ts.map +1 -0
- package/dist/bindings/redis-span.js +11 -0
- package/dist/bindings/redis-span.js.map +1 -0
- package/dist/bindings/test-span.d.ts +6 -0
- package/dist/bindings/test-span.d.ts.map +1 -0
- package/dist/bindings/test-span.js +9 -0
- package/dist/bindings/test-span.js.map +1 -0
- package/dist/bootstrap/otel/framework-mutator.d.ts +20 -0
- package/dist/bootstrap/otel/framework-mutator.d.ts.map +1 -0
- package/dist/bootstrap/otel/framework-mutator.js +144 -0
- package/dist/bootstrap/otel/framework-mutator.js.map +1 -0
- package/dist/bootstrap/otel/inject.d.ts +17 -0
- package/dist/bootstrap/otel/inject.d.ts.map +1 -0
- package/dist/bootstrap/otel/inject.js +28 -0
- package/dist/bootstrap/otel/inject.js.map +1 -0
- package/dist/bootstrap/otel/mutator.d.ts +17 -0
- package/dist/bootstrap/otel/mutator.d.ts.map +1 -0
- package/dist/bootstrap/otel/mutator.js +51 -0
- package/dist/bootstrap/otel/mutator.js.map +1 -0
- package/dist/capture/express.d.ts +6 -0
- package/dist/capture/express.d.ts.map +1 -0
- package/dist/capture/express.js +11 -0
- package/dist/capture/express.js.map +1 -0
- package/dist/capture/fastify.d.ts +5 -0
- package/dist/capture/fastify.d.ts.map +1 -0
- package/dist/capture/fastify.js +9 -0
- package/dist/capture/fastify.js.map +1 -0
- package/dist/capture/framework-mutator.d.ts +20 -0
- package/dist/capture/framework-mutator.d.ts.map +1 -0
- package/dist/capture/framework-mutator.js +144 -0
- package/dist/capture/framework-mutator.js.map +1 -0
- package/dist/capture/http-inbound.d.ts +28 -0
- package/dist/capture/http-inbound.d.ts.map +1 -0
- package/dist/capture/http-inbound.js +40 -0
- package/dist/capture/http-inbound.js.map +1 -0
- package/dist/capture/inject.d.ts +17 -0
- package/dist/capture/inject.d.ts.map +1 -0
- package/dist/capture/inject.js +28 -0
- package/dist/capture/inject.js.map +1 -0
- package/dist/capture/mutator.d.ts +17 -0
- package/dist/capture/mutator.d.ts.map +1 -0
- package/dist/capture/mutator.js +51 -0
- package/dist/capture/mutator.js.map +1 -0
- package/dist/capture/postgres.d.ts +6 -0
- package/dist/capture/postgres.d.ts.map +1 -0
- package/dist/capture/postgres.js +11 -0
- package/dist/capture/postgres.js.map +1 -0
- package/dist/capture/redis.d.ts +5 -0
- package/dist/capture/redis.d.ts.map +1 -0
- package/dist/capture/redis.js +10 -0
- package/dist/capture/redis.js.map +1 -0
- package/dist/capture/store-accessor.d.ts +11 -0
- package/dist/capture/store-accessor.d.ts.map +1 -0
- package/dist/capture/store-accessor.js +19 -0
- package/dist/capture/store-accessor.js.map +1 -0
- package/dist/capture/stream-tap.d.ts +5 -0
- package/dist/capture/stream-tap.d.ts.map +1 -0
- package/dist/capture/stream-tap.js +9 -0
- package/dist/capture/stream-tap.js.map +1 -0
- package/dist/cli/diff-reporter.d.ts +26 -0
- package/dist/cli/diff-reporter.d.ts.map +1 -0
- package/dist/cli/diff-reporter.js +163 -0
- package/dist/cli/diff-reporter.js.map +1 -0
- package/dist/cli/diff.d.ts +18 -0
- package/dist/cli/diff.d.ts.map +1 -0
- package/dist/cli/diff.js +105 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +84 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/config-manager.d.ts +20 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +46 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/context.d.ts +98 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +198 -0
- package/dist/context.js.map +1 -0
- package/dist/core/bindings/http-span.d.ts +39 -0
- package/dist/core/bindings/http-span.d.ts.map +1 -0
- package/dist/core/bindings/http-span.js +55 -0
- package/dist/core/bindings/http-span.js.map +1 -0
- package/dist/core/bindings/index.d.ts +12 -0
- package/dist/core/bindings/index.d.ts.map +1 -0
- package/dist/core/bindings/index.js +21 -0
- package/dist/core/bindings/index.js.map +1 -0
- package/dist/core/bindings/postgres-span.d.ts +41 -0
- package/dist/core/bindings/postgres-span.d.ts.map +1 -0
- package/dist/core/bindings/postgres-span.js +57 -0
- package/dist/core/bindings/postgres-span.js.map +1 -0
- package/dist/core/bindings/redis-span.d.ts +40 -0
- package/dist/core/bindings/redis-span.d.ts.map +1 -0
- package/dist/core/bindings/redis-span.js +65 -0
- package/dist/core/bindings/redis-span.js.map +1 -0
- package/dist/core/bindings/test-span.d.ts +15 -0
- package/dist/core/bindings/test-span.d.ts.map +1 -0
- package/dist/core/bindings/test-span.js +24 -0
- package/dist/core/bindings/test-span.js.map +1 -0
- package/dist/core/cassette/capture-store-accessor.d.ts +11 -0
- package/dist/core/cassette/capture-store-accessor.d.ts.map +1 -0
- package/dist/core/cassette/capture-store-accessor.js +19 -0
- package/dist/core/cassette/capture-store-accessor.js.map +1 -0
- package/dist/core/cassette/context-request-storage.d.ts +14 -0
- package/dist/core/cassette/context-request-storage.d.ts.map +1 -0
- package/dist/core/cassette/context-request-storage.js +24 -0
- package/dist/core/cassette/context-request-storage.js.map +1 -0
- package/dist/core/cassette/index.d.ts +8 -0
- package/dist/core/cassette/index.d.ts.map +1 -0
- package/dist/core/cassette/index.js +16 -0
- package/dist/core/cassette/index.js.map +1 -0
- package/dist/core/cassette/ndjson-cassette.d.ts +22 -0
- package/dist/core/cassette/ndjson-cassette.d.ts.map +1 -0
- package/dist/core/cassette/ndjson-cassette.js +56 -0
- package/dist/core/cassette/ndjson-cassette.js.map +1 -0
- package/dist/core/cassette/request-storage.d.ts +16 -0
- package/dist/core/cassette/request-storage.d.ts.map +1 -0
- package/dist/core/cassette/request-storage.js +22 -0
- package/dist/core/cassette/request-storage.js.map +1 -0
- package/dist/core/context/index.d.ts +5 -0
- package/dist/core/context/index.d.ts.map +1 -0
- package/dist/core/context/index.js +9 -0
- package/dist/core/context/index.js.map +1 -0
- package/dist/core/contracts/index.d.ts +5 -0
- package/dist/core/contracts/index.d.ts.map +1 -0
- package/dist/core/contracts/index.js +3 -0
- package/dist/core/contracts/index.js.map +1 -0
- package/dist/core/identifier.d.ts +20 -0
- package/dist/core/identifier.d.ts.map +1 -0
- package/dist/core/identifier.js +31 -0
- package/dist/core/identifier.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +27 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/matcher/extract-key.d.ts +41 -0
- package/dist/core/matcher/extract-key.d.ts.map +1 -0
- package/dist/core/matcher/extract-key.js +80 -0
- package/dist/core/matcher/extract-key.js.map +1 -0
- package/dist/core/matcher/index.d.ts +9 -0
- package/dist/core/matcher/index.d.ts.map +1 -0
- package/dist/core/matcher/index.js +24 -0
- package/dist/core/matcher/index.js.map +1 -0
- package/dist/core/matcher/matcher.d.ts +25 -0
- package/dist/core/matcher/matcher.d.ts.map +1 -0
- package/dist/core/matcher/matcher.js +83 -0
- package/dist/core/matcher/matcher.js.map +1 -0
- package/dist/core/matcher/softprobe-matcher.d.ts +41 -0
- package/dist/core/matcher/softprobe-matcher.d.ts.map +1 -0
- package/dist/core/matcher/softprobe-matcher.js +92 -0
- package/dist/core/matcher/softprobe-matcher.js.map +1 -0
- package/dist/core/matcher/store-accessor.d.ts +14 -0
- package/dist/core/matcher/store-accessor.d.ts.map +1 -0
- package/dist/core/matcher/store-accessor.js +25 -0
- package/dist/core/matcher/store-accessor.js.map +1 -0
- package/dist/core/matcher/topology.d.ts +37 -0
- package/dist/core/matcher/topology.d.ts.map +1 -0
- package/dist/core/matcher/topology.js +72 -0
- package/dist/core/matcher/topology.js.map +1 -0
- package/dist/core/runtime/architecture-guard.d.ts +9 -0
- package/dist/core/runtime/architecture-guard.d.ts.map +1 -0
- package/dist/core/runtime/architecture-guard.js +131 -0
- package/dist/core/runtime/architecture-guard.js.map +1 -0
- package/dist/core/runtime/index.d.ts +6 -0
- package/dist/core/runtime/index.d.ts.map +1 -0
- package/dist/core/runtime/index.js +11 -0
- package/dist/core/runtime/index.js.map +1 -0
- package/dist/identifier.d.ts +5 -0
- package/dist/identifier.d.ts.map +1 -0
- package/dist/identifier.js +11 -0
- package/dist/identifier.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +21 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +51 -0
- package/dist/init.js.map +1 -0
- package/dist/instrumentations/common/http/context-headers.d.ts +9 -0
- package/dist/instrumentations/common/http/context-headers.d.ts.map +1 -0
- package/dist/instrumentations/common/http/context-headers.js +16 -0
- package/dist/instrumentations/common/http/context-headers.js.map +1 -0
- package/dist/instrumentations/common/http/inbound-capture.d.ts +17 -0
- package/dist/instrumentations/common/http/inbound-capture.d.ts.map +1 -0
- package/dist/instrumentations/common/http/inbound-capture.js +41 -0
- package/dist/instrumentations/common/http/inbound-capture.js.map +1 -0
- package/dist/instrumentations/common/http/inbound-record.d.ts +28 -0
- package/dist/instrumentations/common/http/inbound-record.d.ts.map +1 -0
- package/dist/instrumentations/common/http/inbound-record.js +40 -0
- package/dist/instrumentations/common/http/inbound-record.js.map +1 -0
- package/dist/instrumentations/common/http/span-adapter.d.ts +6 -0
- package/dist/instrumentations/common/http/span-adapter.d.ts.map +1 -0
- package/dist/instrumentations/common/http/span-adapter.js +12 -0
- package/dist/instrumentations/common/http/span-adapter.js.map +1 -0
- package/dist/instrumentations/common/http/stream-tap.d.ts +28 -0
- package/dist/instrumentations/common/http/stream-tap.d.ts.map +1 -0
- package/dist/instrumentations/common/http/stream-tap.js +61 -0
- package/dist/instrumentations/common/http/stream-tap.js.map +1 -0
- package/dist/instrumentations/express/capture.d.ts +26 -0
- package/dist/instrumentations/express/capture.d.ts.map +1 -0
- package/dist/instrumentations/express/capture.js +80 -0
- package/dist/instrumentations/express/capture.js.map +1 -0
- package/dist/instrumentations/express/index.d.ts +7 -0
- package/dist/instrumentations/express/index.d.ts.map +1 -0
- package/dist/instrumentations/express/index.js +15 -0
- package/dist/instrumentations/express/index.js.map +1 -0
- package/dist/instrumentations/express/replay.d.ts +10 -0
- package/dist/instrumentations/express/replay.d.ts.map +1 -0
- package/dist/instrumentations/express/replay.js +16 -0
- package/dist/instrumentations/express/replay.js.map +1 -0
- package/dist/instrumentations/fastify/capture.d.ts +13 -0
- package/dist/instrumentations/fastify/capture.d.ts.map +1 -0
- package/dist/instrumentations/fastify/capture.js +65 -0
- package/dist/instrumentations/fastify/capture.js.map +1 -0
- package/dist/instrumentations/fastify/index.d.ts +7 -0
- package/dist/instrumentations/fastify/index.d.ts.map +1 -0
- package/dist/instrumentations/fastify/index.js +13 -0
- package/dist/instrumentations/fastify/index.js.map +1 -0
- package/dist/instrumentations/fastify/replay.d.ts +13 -0
- package/dist/instrumentations/fastify/replay.d.ts.map +1 -0
- package/dist/instrumentations/fastify/replay.js +24 -0
- package/dist/instrumentations/fastify/replay.js.map +1 -0
- package/dist/instrumentations/fetch/index.d.ts +5 -0
- package/dist/instrumentations/fetch/index.d.ts.map +1 -0
- package/dist/instrumentations/fetch/index.js +10 -0
- package/dist/instrumentations/fetch/index.js.map +1 -0
- package/dist/instrumentations/fetch/replay.d.ts +19 -0
- package/dist/instrumentations/fetch/replay.d.ts.map +1 -0
- package/dist/instrumentations/fetch/replay.js +259 -0
- package/dist/instrumentations/fetch/replay.js.map +1 -0
- package/dist/instrumentations/postgres/capture.d.ts +46 -0
- package/dist/instrumentations/postgres/capture.d.ts.map +1 -0
- package/dist/instrumentations/postgres/capture.js +68 -0
- package/dist/instrumentations/postgres/capture.js.map +1 -0
- package/dist/instrumentations/postgres/index.d.ts +6 -0
- package/dist/instrumentations/postgres/index.d.ts.map +1 -0
- package/dist/instrumentations/postgres/index.js +14 -0
- package/dist/instrumentations/postgres/index.js.map +1 -0
- package/dist/instrumentations/postgres/replay.d.ts +20 -0
- package/dist/instrumentations/postgres/replay.d.ts.map +1 -0
- package/dist/instrumentations/postgres/replay.js +163 -0
- package/dist/instrumentations/postgres/replay.js.map +1 -0
- package/dist/instrumentations/redis/capture.d.ts +20 -0
- package/dist/instrumentations/redis/capture.d.ts.map +1 -0
- package/dist/instrumentations/redis/capture.js +61 -0
- package/dist/instrumentations/redis/capture.js.map +1 -0
- package/dist/instrumentations/redis/index.d.ts +6 -0
- package/dist/instrumentations/redis/index.d.ts.map +1 -0
- package/dist/instrumentations/redis/index.js +13 -0
- package/dist/instrumentations/redis/index.js.map +1 -0
- package/dist/instrumentations/redis/replay.d.ts +24 -0
- package/dist/instrumentations/redis/replay.d.ts.map +1 -0
- package/dist/instrumentations/redis/replay.js +173 -0
- package/dist/instrumentations/redis/replay.js.map +1 -0
- package/dist/replay/express.d.ts +5 -0
- package/dist/replay/express.d.ts.map +1 -0
- package/dist/replay/express.js +9 -0
- package/dist/replay/express.js.map +1 -0
- package/dist/replay/extract-key.d.ts +41 -0
- package/dist/replay/extract-key.d.ts.map +1 -0
- package/dist/replay/extract-key.js +80 -0
- package/dist/replay/extract-key.js.map +1 -0
- package/dist/replay/fastify.d.ts +5 -0
- package/dist/replay/fastify.d.ts.map +1 -0
- package/dist/replay/fastify.js +9 -0
- package/dist/replay/fastify.js.map +1 -0
- package/dist/replay/http.d.ts +5 -0
- package/dist/replay/http.d.ts.map +1 -0
- package/dist/replay/http.js +10 -0
- package/dist/replay/http.js.map +1 -0
- package/dist/replay/matcher.d.ts +25 -0
- package/dist/replay/matcher.d.ts.map +1 -0
- package/dist/replay/matcher.js +83 -0
- package/dist/replay/matcher.js.map +1 -0
- package/dist/replay/postgres.d.ts +5 -0
- package/dist/replay/postgres.d.ts.map +1 -0
- package/dist/replay/postgres.js +10 -0
- package/dist/replay/postgres.js.map +1 -0
- package/dist/replay/redis.d.ts +5 -0
- package/dist/replay/redis.d.ts.map +1 -0
- package/dist/replay/redis.js +10 -0
- package/dist/replay/redis.js.map +1 -0
- package/dist/replay/softprobe-matcher.d.ts +41 -0
- package/dist/replay/softprobe-matcher.d.ts.map +1 -0
- package/dist/replay/softprobe-matcher.js +92 -0
- package/dist/replay/softprobe-matcher.js.map +1 -0
- package/dist/replay/store-accessor.d.ts +14 -0
- package/dist/replay/store-accessor.d.ts.map +1 -0
- package/dist/replay/store-accessor.js +26 -0
- package/dist/replay/store-accessor.js.map +1 -0
- package/dist/replay/topology.d.ts +37 -0
- package/dist/replay/topology.d.ts.map +1 -0
- package/dist/replay/topology.js +72 -0
- package/dist/replay/topology.js.map +1 -0
- package/dist/store/cassette-store.d.ts +36 -0
- package/dist/store/cassette-store.d.ts.map +1 -0
- package/dist/store/cassette-store.js +66 -0
- package/dist/store/cassette-store.js.map +1 -0
- package/dist/types/schema.d.ts +114 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +13 -0
- package/dist/types/schema.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP inbound capture: write one NDJSON record per inbound request/response.
|
|
4
|
+
* Design §10.4: Inbound HTTP — request body + response status/body.
|
|
5
|
+
* Single record embeds both requestPayload and responsePayload when available.
|
|
6
|
+
* Task 14.3.1: requestPayload.body is populated from req.body when Express
|
|
7
|
+
* middleware is placed after body-parser (via queueInboundResponse.requestBody).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.writeInboundHttpRecord = writeInboundHttpRecord;
|
|
11
|
+
const identifier_1 = require("../identifier");
|
|
12
|
+
/**
|
|
13
|
+
* Writes one inbound HTTP cassette record. Include requestBody for request capture,
|
|
14
|
+
* and statusCode/responseBody when the response is available (same record).
|
|
15
|
+
*/
|
|
16
|
+
function writeInboundHttpRecord(store, options) {
|
|
17
|
+
const { traceId, spanId, parentSpanId, spanName, method, url, requestBody, statusCode, responseBody, } = options;
|
|
18
|
+
const record = {
|
|
19
|
+
version: '4.1',
|
|
20
|
+
traceId,
|
|
21
|
+
spanId,
|
|
22
|
+
parentSpanId,
|
|
23
|
+
spanName,
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
type: 'inbound',
|
|
26
|
+
protocol: 'http',
|
|
27
|
+
identifier: (0, identifier_1.httpIdentifier)(method, url),
|
|
28
|
+
};
|
|
29
|
+
if (requestBody !== undefined) {
|
|
30
|
+
record.requestPayload = { body: requestBody };
|
|
31
|
+
}
|
|
32
|
+
if (statusCode !== undefined) {
|
|
33
|
+
record.responsePayload = {
|
|
34
|
+
statusCode,
|
|
35
|
+
body: responseBody,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
store.saveRecord(record);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=http-inbound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-inbound.js","sourceRoot":"","sources":["../../src/capture/http-inbound.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAyBH,wDAuCC;AA5DD,8CAA+C;AAiB/C;;;GAGG;AACH,SAAgB,sBAAsB,CACpC,KAAoB,EACpB,OAAgC;IAEhC,MAAM,EACJ,OAAO,EACP,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,GAAG,EACH,WAAW,EACX,UAAU,EACV,YAAY,GACb,GAAG,OAAO,CAAC;IAEZ,MAAM,MAAM,GAA4B;QACtC,OAAO,EAAE,KAAK;QACd,OAAO;QACP,MAAM;QACN,YAAY;QACZ,QAAQ;QACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,IAAA,2BAAc,EAAC,MAAM,EAAE,GAAG,CAAC;KACxC,CAAC;IAEF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,cAAc,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAChD,CAAC;IACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,CAAC,eAAe,GAAG;YACvB,UAAU;YACV,IAAI,EAAE,YAAY;SACnB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers to inject hooks into the instrumentation config array
|
|
3
|
+
* returned by getNodeAutoInstrumentations. Used by mutator to apply each protocol's hook.
|
|
4
|
+
* Design §5.3: keeps injection logic DRY across capture/postgres, undici, redis.
|
|
5
|
+
*/
|
|
6
|
+
export type InstrumentationEntry = {
|
|
7
|
+
instrumentationName?: string;
|
|
8
|
+
[hookName: string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Finds the entry in the config array whose instrumentationName matches, and sets
|
|
12
|
+
* the named hook property. Mutates the array in place and returns it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function injectHook(result: unknown[], instrumentationName: string, hookName: string, hookFn: (...args: unknown[]) => void): unknown[];
|
|
15
|
+
/** Convenience wrapper: injects a responseHook. */
|
|
16
|
+
export declare function injectResponseHook(result: unknown[], instrumentationName: string, responseHook: (span: unknown, result: unknown) => void): unknown[];
|
|
17
|
+
//# sourceMappingURL=inject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject.d.ts","sourceRoot":"","sources":["../../src/capture/inject.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,OAAO,EAAE,EACjB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GACnC,OAAO,EAAE,CASX;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,EAAE,EACjB,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,GACrD,OAAO,EAAE,CAEX"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared helpers to inject hooks into the instrumentation config array
|
|
4
|
+
* returned by getNodeAutoInstrumentations. Used by mutator to apply each protocol's hook.
|
|
5
|
+
* Design §5.3: keeps injection logic DRY across capture/postgres, undici, redis.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.injectHook = injectHook;
|
|
9
|
+
exports.injectResponseHook = injectResponseHook;
|
|
10
|
+
/**
|
|
11
|
+
* Finds the entry in the config array whose instrumentationName matches, and sets
|
|
12
|
+
* the named hook property. Mutates the array in place and returns it.
|
|
13
|
+
*/
|
|
14
|
+
function injectHook(result, instrumentationName, hookName, hookFn) {
|
|
15
|
+
for (const item of result) {
|
|
16
|
+
const entry = item;
|
|
17
|
+
if (entry.instrumentationName === instrumentationName) {
|
|
18
|
+
entry[hookName] = hookFn;
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
/** Convenience wrapper: injects a responseHook. */
|
|
25
|
+
function injectResponseHook(result, instrumentationName, responseHook) {
|
|
26
|
+
return injectHook(result, instrumentationName, 'responseHook', responseHook);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=inject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject.js","sourceRoot":"","sources":["../../src/capture/inject.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAWH,gCAcC;AAGD,gDAMC;AA3BD;;;GAGG;AACH,SAAgB,UAAU,CACxB,MAAiB,EACjB,mBAA2B,EAC3B,QAAgB,EAChB,MAAoC;IAEpC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,IAA4B,CAAC;QAC3C,IAAI,KAAK,CAAC,mBAAmB,KAAK,mBAAmB,EAAE,CAAC;YACtD,KAAK,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YACzB,MAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mDAAmD;AACnD,SAAgB,kBAAkB,CAChC,MAAiB,EACjB,mBAA2B,EAC3B,YAAsD;IAEtD,OAAO,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-instrumentation mutator: wraps getNodeAutoInstrumentations to inject
|
|
3
|
+
* Softprobe responseHooks per protocol (postgres, redis). HTTP capture/replay
|
|
4
|
+
* is done solely via the MSW interceptor (replay/http.ts), not undici instrumentation.
|
|
5
|
+
* Design §5.2, §5.3.
|
|
6
|
+
*/
|
|
7
|
+
/** Module-like object that exposes getNodeAutoInstrumentations (for real use or tests). */
|
|
8
|
+
export interface AutoInstrumentationsModule {
|
|
9
|
+
getNodeAutoInstrumentations: (options?: unknown) => unknown[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Wraps getNodeAutoInstrumentations so that the returned config includes our
|
|
13
|
+
* custom responseHook for each protocol. Pass a module object to mutate (e.g. for tests);
|
|
14
|
+
* if omitted, the real @opentelemetry/auto-instrumentations-node module is used.
|
|
15
|
+
*/
|
|
16
|
+
export declare function applyAutoInstrumentationMutator(target?: AutoInstrumentationsModule): void;
|
|
17
|
+
//# sourceMappingURL=mutator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutator.d.ts","sourceRoot":"","sources":["../../src/capture/mutator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,2FAA2F;AAC3F,MAAM,WAAW,0BAA0B;IACzC,2BAA2B,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,EAAE,CAAC;CAC/D;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,CAAC,EAAE,0BAA0B,GAClC,IAAI,CAuCN"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auto-instrumentation mutator: wraps getNodeAutoInstrumentations to inject
|
|
4
|
+
* Softprobe responseHooks per protocol (postgres, redis). HTTP capture/replay
|
|
5
|
+
* is done solely via the MSW interceptor (replay/http.ts), not undici instrumentation.
|
|
6
|
+
* Design §5.2, §5.3.
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.applyAutoInstrumentationMutator = applyAutoInstrumentationMutator;
|
|
13
|
+
const shimmer_1 = __importDefault(require("shimmer"));
|
|
14
|
+
const inject_1 = require("./inject");
|
|
15
|
+
const capture_1 = require("../instrumentations/postgres/capture");
|
|
16
|
+
const capture_2 = require("../instrumentations/redis/capture");
|
|
17
|
+
/**
|
|
18
|
+
* Wraps getNodeAutoInstrumentations so that the returned config includes our
|
|
19
|
+
* custom responseHook for each protocol. Pass a module object to mutate (e.g. for tests);
|
|
20
|
+
* if omitted, the real @opentelemetry/auto-instrumentations-node module is used.
|
|
21
|
+
*/
|
|
22
|
+
function applyAutoInstrumentationMutator(target) {
|
|
23
|
+
const moduleExport = target ?? require('@opentelemetry/auto-instrumentations-node');
|
|
24
|
+
shimmer_1.default.wrap(moduleExport, 'getNodeAutoInstrumentations', ((original) => {
|
|
25
|
+
return function wrappedGetNodeAutoInstrumentations(options) {
|
|
26
|
+
// Real getNodeAutoInstrumentations(inputConfigs) creates instances from config;
|
|
27
|
+
// merge our responseHooks into the input so instances get them (E2E).
|
|
28
|
+
const input = options != null && typeof options === 'object' && !Array.isArray(options)
|
|
29
|
+
? options
|
|
30
|
+
: {};
|
|
31
|
+
const merged = { ...input };
|
|
32
|
+
merged[capture_1.PG_INSTRUMENTATION_NAME] = {
|
|
33
|
+
...(input[capture_1.PG_INSTRUMENTATION_NAME] ?? {}),
|
|
34
|
+
requestHook: (0, capture_1.buildPostgresRequestHook)(),
|
|
35
|
+
responseHook: (0, capture_1.buildPostgresResponseHook)(),
|
|
36
|
+
};
|
|
37
|
+
merged[capture_2.REDIS_INSTRUMENTATION_NAME] = {
|
|
38
|
+
...(input[capture_2.REDIS_INSTRUMENTATION_NAME] ?? {}),
|
|
39
|
+
responseHook: (0, capture_2.buildRedisResponseHook)(),
|
|
40
|
+
};
|
|
41
|
+
const result = original.call(this, merged);
|
|
42
|
+
// Also mutate return value for mocks that return config-like entries (unit tests).
|
|
43
|
+
const arr = Array.isArray(result) ? result : [];
|
|
44
|
+
(0, inject_1.injectHook)(arr, capture_1.PG_INSTRUMENTATION_NAME, 'requestHook', (0, capture_1.buildPostgresRequestHook)());
|
|
45
|
+
(0, inject_1.injectResponseHook)(arr, capture_1.PG_INSTRUMENTATION_NAME, (0, capture_1.buildPostgresResponseHook)());
|
|
46
|
+
(0, inject_1.injectResponseHook)(arr, capture_2.REDIS_INSTRUMENTATION_NAME, (0, capture_2.buildRedisResponseHook)());
|
|
47
|
+
return arr;
|
|
48
|
+
};
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=mutator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutator.js","sourceRoot":"","sources":["../../src/capture/mutator.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;AAwBH,0EAyCC;AA/DD,sDAA8B;AAC9B,qCAA0D;AAC1D,kEAI8C;AAC9C,+DAG2C;AAO3C;;;;GAIG;AACH,SAAgB,+BAA+B,CAC7C,MAAmC;IAEnC,MAAM,YAAY,GAChB,MAAM,IAAI,OAAO,CAAC,2CAA2C,CAAC,CAAC;IAEjE,iBAAO,CAAC,IAAI,CACV,YAAY,EACZ,6BAA6B,EAC7B,CAAC,CAAC,QAA0C,EAAE,EAAE;QAC9C,OAAO,SAAS,kCAAkC,CAEhD,OAAiB;YAEjB,gFAAgF;YAChF,sEAAsE;YACtE,MAAM,KAAK,GACT,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBACvE,CAAC,CAAE,OAAmC;gBACtC,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,MAAM,GAA4B,EAAE,GAAG,KAAK,EAAE,CAAC;YACrD,MAAM,CAAC,iCAAuB,CAAC,GAAG;gBAChC,GAAG,CAAE,KAAK,CAAC,iCAAuB,CAAY,IAAI,EAAE,CAAC;gBACrD,WAAW,EAAE,IAAA,kCAAwB,GAAE;gBACvC,YAAY,EAAE,IAAA,mCAAyB,GAAE;aAC1C,CAAC;YACF,MAAM,CAAC,oCAA0B,CAAC,GAAG;gBACnC,GAAG,CAAE,KAAK,CAAC,oCAA0B,CAAY,IAAI,EAAE,CAAC;gBACxD,YAAY,EAAE,IAAA,gCAAsB,GAAE;aACvC,CAAC;YAEF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,mFAAmF;YACnF,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,IAAA,mBAAU,EAAC,GAAG,EAAE,iCAAuB,EAAE,aAAa,EAAE,IAAA,kCAAwB,GAAE,CAAC,CAAC;YACpF,IAAA,2BAAkB,EAAC,GAAG,EAAE,iCAAuB,EAAE,IAAA,mCAAyB,GAAE,CAAC,CAAC;YAC9E,IAAA,2BAAkB,EAAC,GAAG,EAAE,oCAA0B,EAAE,IAAA,gCAAsB,GAAE,CAAC,CAAC;YAC9E,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;IACJ,CAAC,CAAmF,CACrF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy compatibility re-export for Postgres capture instrumentation.
|
|
3
|
+
*/
|
|
4
|
+
export { PG_INSTRUMENTATION_NAME, buildPostgresRequestHook, buildPostgresResponseHook, } from '../instrumentations/postgres/capture';
|
|
5
|
+
export type { PgQueryInfo, PgResultInfo } from '../instrumentations/postgres/capture';
|
|
6
|
+
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/capture/postgres.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPostgresResponseHook = exports.buildPostgresRequestHook = exports.PG_INSTRUMENTATION_NAME = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Legacy compatibility re-export for Postgres capture instrumentation.
|
|
6
|
+
*/
|
|
7
|
+
var capture_1 = require("../instrumentations/postgres/capture");
|
|
8
|
+
Object.defineProperty(exports, "PG_INSTRUMENTATION_NAME", { enumerable: true, get: function () { return capture_1.PG_INSTRUMENTATION_NAME; } });
|
|
9
|
+
Object.defineProperty(exports, "buildPostgresRequestHook", { enumerable: true, get: function () { return capture_1.buildPostgresRequestHook; } });
|
|
10
|
+
Object.defineProperty(exports, "buildPostgresResponseHook", { enumerable: true, get: function () { return capture_1.buildPostgresResponseHook; } });
|
|
11
|
+
//# sourceMappingURL=postgres.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/capture/postgres.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,gEAI8C;AAH5C,kHAAA,uBAAuB,OAAA;AACvB,mHAAA,wBAAwB,OAAA;AACxB,oHAAA,yBAAyB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/capture/redis.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildRedisResponseHook = exports.REDIS_INSTRUMENTATION_NAME = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Legacy compatibility re-export for Redis capture instrumentation.
|
|
6
|
+
*/
|
|
7
|
+
var capture_1 = require("../instrumentations/redis/capture");
|
|
8
|
+
Object.defineProperty(exports, "REDIS_INSTRUMENTATION_NAME", { enumerable: true, get: function () { return capture_1.REDIS_INSTRUMENTATION_NAME; } });
|
|
9
|
+
Object.defineProperty(exports, "buildRedisResponseHook", { enumerable: true, get: function () { return capture_1.buildRedisResponseHook; } });
|
|
10
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/capture/redis.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,6DAAuG;AAA9F,qHAAA,0BAA0B,OAAA;AAAE,iHAAA,sBAAsB,OAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture-mode cassette store accessor. Allows hooks to write NDJSON records
|
|
3
|
+
* without coupling them to init. Design §10: payloads written via single-threaded queue.
|
|
4
|
+
* HTTP outbound capture is done solely via the MSW interceptor (replay/http.ts).
|
|
5
|
+
*/
|
|
6
|
+
import type { CassetteStore } from '../store/cassette-store';
|
|
7
|
+
/** Returns the current capture cassette store, if set (e.g. by init in capture mode). */
|
|
8
|
+
export declare function getCaptureStore(): CassetteStore | undefined;
|
|
9
|
+
/** Sets the capture cassette store (used by init or tests). */
|
|
10
|
+
export declare function setCaptureStore(store: CassetteStore | undefined): void;
|
|
11
|
+
//# sourceMappingURL=store-accessor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-accessor.d.ts","sourceRoot":"","sources":["../../src/capture/store-accessor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAI7D,yFAAyF;AACzF,wBAAgB,eAAe,IAAI,aAAa,GAAG,SAAS,CAE3D;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAEtE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Capture-mode cassette store accessor. Allows hooks to write NDJSON records
|
|
4
|
+
* without coupling them to init. Design §10: payloads written via single-threaded queue.
|
|
5
|
+
* HTTP outbound capture is done solely via the MSW interceptor (replay/http.ts).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.getCaptureStore = getCaptureStore;
|
|
9
|
+
exports.setCaptureStore = setCaptureStore;
|
|
10
|
+
let captureStore;
|
|
11
|
+
/** Returns the current capture cassette store, if set (e.g. by init in capture mode). */
|
|
12
|
+
function getCaptureStore() {
|
|
13
|
+
return captureStore;
|
|
14
|
+
}
|
|
15
|
+
/** Sets the capture cassette store (used by init or tests). */
|
|
16
|
+
function setCaptureStore(store) {
|
|
17
|
+
captureStore = store;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=store-accessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-accessor.js","sourceRoot":"","sources":["../../src/capture/store-accessor.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAOH,0CAEC;AAGD,0CAEC;AAVD,IAAI,YAAuC,CAAC;AAE5C,yFAAyF;AACzF,SAAgB,eAAe;IAC7B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,+DAA+D;AAC/D,SAAgB,eAAe,CAAC,KAAgC;IAC9D,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-tap.d.ts","sourceRoot":"","sources":["../../src/capture/stream-tap.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAC9B,MAAM,4CAA4C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tapReadableStream = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Legacy compatibility re-export for HTTP stream tap helper.
|
|
6
|
+
*/
|
|
7
|
+
var stream_tap_1 = require("../instrumentations/common/http/stream-tap");
|
|
8
|
+
Object.defineProperty(exports, "tapReadableStream", { enumerable: true, get: function () { return stream_tap_1.tapReadableStream; } });
|
|
9
|
+
//# sourceMappingURL=stream-tap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-tap.js","sourceRoot":"","sources":["../../src/capture/stream-tap.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,yEAIoD;AAHlD,+GAAA,iBAAiB,OAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff reporter: compares recorded response (from cassette) vs live response (from server).
|
|
3
|
+
* Used by `softprobe diff`. On match returns true; on mismatch prints a colored diff
|
|
4
|
+
* (status and body) to stderr and returns false. So the CLI can show PASS/FAIL and
|
|
5
|
+
* on failure show what differed.
|
|
6
|
+
*/
|
|
7
|
+
/** Recorded response from cassette inbound responsePayload. */
|
|
8
|
+
export type RecordedResponse = {
|
|
9
|
+
statusCode?: number;
|
|
10
|
+
body?: unknown;
|
|
11
|
+
};
|
|
12
|
+
/** Live response from fetch. */
|
|
13
|
+
export type LiveResponse = {
|
|
14
|
+
status: number;
|
|
15
|
+
body: unknown;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Compares recorded vs live response. If they differ, prints a colored diff to stderr.
|
|
19
|
+
* @param opts.ignoreBodyPaths - JSON paths to omit from body before comparing (e.g. ["http.headers"] for upstream variance).
|
|
20
|
+
* @returns true when recorded and live match, false when they differ.
|
|
21
|
+
*/
|
|
22
|
+
export declare function reportDiff(recorded: RecordedResponse, live: LiveResponse, opts?: {
|
|
23
|
+
write?: (s: string) => void;
|
|
24
|
+
ignoreBodyPaths?: string[];
|
|
25
|
+
}): boolean;
|
|
26
|
+
//# sourceMappingURL=diff-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-reporter.d.ts","sourceRoot":"","sources":["../../src/cli/diff-reporter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,+DAA+D;AAC/D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,gCAAgC;AAChC,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAqCF;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GACrE,OAAO,CAqCT"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Diff reporter: compares recorded response (from cassette) vs live response (from server).
|
|
4
|
+
* Used by `softprobe diff`. On match returns true; on mismatch prints a colored diff
|
|
5
|
+
* (status and body) to stderr and returns false. So the CLI can show PASS/FAIL and
|
|
6
|
+
* on failure show what differed.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.reportDiff = reportDiff;
|
|
10
|
+
const RED = '\x1b[31m';
|
|
11
|
+
const GREEN = '\x1b[32m';
|
|
12
|
+
const RESET = '\x1b[0m';
|
|
13
|
+
const DIM = '\x1b[2m';
|
|
14
|
+
/**
|
|
15
|
+
* Parses response body as JSON when possible; otherwise returns raw string.
|
|
16
|
+
*/
|
|
17
|
+
function parseBody(raw) {
|
|
18
|
+
const trimmed = raw.trim();
|
|
19
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return raw;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return raw;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Removes a path (e.g. "http.headers") from a nested object for comparison.
|
|
31
|
+
*/
|
|
32
|
+
function omitPath(obj, path) {
|
|
33
|
+
if (obj === null || typeof obj !== 'object')
|
|
34
|
+
return obj;
|
|
35
|
+
const parts = path.split('.');
|
|
36
|
+
const key = parts[0];
|
|
37
|
+
if (parts.length === 1) {
|
|
38
|
+
const o = { ...obj };
|
|
39
|
+
delete o[key];
|
|
40
|
+
return o;
|
|
41
|
+
}
|
|
42
|
+
const rest = parts.slice(1).join('.');
|
|
43
|
+
const o = obj;
|
|
44
|
+
if (!(key in o))
|
|
45
|
+
return obj;
|
|
46
|
+
const sub = omitPath(o[key], rest);
|
|
47
|
+
if (sub === o[key])
|
|
48
|
+
return obj;
|
|
49
|
+
return { ...o, [key]: sub };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Compares recorded vs live response. If they differ, prints a colored diff to stderr.
|
|
53
|
+
* @param opts.ignoreBodyPaths - JSON paths to omit from body before comparing (e.g. ["http.headers"] for upstream variance).
|
|
54
|
+
* @returns true when recorded and live match, false when they differ.
|
|
55
|
+
*/
|
|
56
|
+
function reportDiff(recorded, live, opts = {}) {
|
|
57
|
+
const write = opts.write ?? ((s) => process.stderr.write(s));
|
|
58
|
+
const recStatus = recorded.statusCode;
|
|
59
|
+
let recBody = typeof recorded.body === 'string' ? parseBody(recorded.body) : recorded.body;
|
|
60
|
+
let liveBody = typeof live.body === 'string' ? parseBody(live.body) : live.body;
|
|
61
|
+
for (const p of opts.ignoreBodyPaths ?? []) {
|
|
62
|
+
recBody = omitPath(recBody, p);
|
|
63
|
+
liveBody = omitPath(liveBody, p);
|
|
64
|
+
}
|
|
65
|
+
const statusMatch = recStatus === undefined || recStatus === live.status;
|
|
66
|
+
const bodyMatch = deepEqual(recBody, liveBody);
|
|
67
|
+
if (statusMatch && bodyMatch)
|
|
68
|
+
return true;
|
|
69
|
+
write('softprobe diff: FAIL — response differs from recording\n\n');
|
|
70
|
+
if (!statusMatch) {
|
|
71
|
+
write(`${DIM}status:${RESET}\n`);
|
|
72
|
+
if (recStatus !== undefined) {
|
|
73
|
+
write(` ${GREEN}recorded: ${recStatus}${RESET}\n`);
|
|
74
|
+
}
|
|
75
|
+
write(` ${RED}live: ${live.status}${RESET}\n\n`);
|
|
76
|
+
}
|
|
77
|
+
if (!bodyMatch) {
|
|
78
|
+
const diffs = collectDiffs(recBody, liveBody, '');
|
|
79
|
+
write(`${DIM}body (only differences):${RESET}\n`);
|
|
80
|
+
for (const { path, recorded: r, live: l } of diffs) {
|
|
81
|
+
write(` ${DIM}${path}:${RESET}\n`);
|
|
82
|
+
write(` ${GREEN}recorded: ${formatValue(r)}${RESET}\n`);
|
|
83
|
+
write(` ${RED}live: ${formatValue(l)}${RESET}\n`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
/** Collect paths where recorded and live differ; only report leaf differences. */
|
|
89
|
+
function collectDiffs(recorded, live, path) {
|
|
90
|
+
if (recorded === live)
|
|
91
|
+
return [];
|
|
92
|
+
if (recorded === null || live === null || typeof recorded !== 'object' || typeof live !== 'object') {
|
|
93
|
+
return [{ path: path || '(root)', recorded, live }];
|
|
94
|
+
}
|
|
95
|
+
const rec = recorded;
|
|
96
|
+
const liv = live;
|
|
97
|
+
const keys = new Set([...Object.keys(rec), ...Object.keys(liv)]);
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const k of [...keys].sort()) {
|
|
100
|
+
const p = path ? `${path}.${k}` : k;
|
|
101
|
+
const rv = rec[k];
|
|
102
|
+
const lv = liv[k];
|
|
103
|
+
if (rv === lv)
|
|
104
|
+
continue;
|
|
105
|
+
if (Array.isArray(rv) && Array.isArray(lv)) {
|
|
106
|
+
if (!deepEqual(rv, lv))
|
|
107
|
+
out.push({ path: p, recorded: rv, live: lv });
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (rv !== null &&
|
|
111
|
+
lv !== null &&
|
|
112
|
+
typeof rv === 'object' &&
|
|
113
|
+
typeof lv === 'object' &&
|
|
114
|
+
!Array.isArray(rv) &&
|
|
115
|
+
!Array.isArray(lv)) {
|
|
116
|
+
out.push(...collectDiffs(rv, lv, p));
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
out.push({ path: p, recorded: rv, live: lv });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
function formatValue(value) {
|
|
125
|
+
if (value === undefined)
|
|
126
|
+
return 'undefined';
|
|
127
|
+
if (typeof value === 'string' && value.length > 80)
|
|
128
|
+
return JSON.stringify(value.slice(0, 77) + '...');
|
|
129
|
+
try {
|
|
130
|
+
const s = JSON.stringify(value);
|
|
131
|
+
return s.length > 80 ? s.slice(0, 77) + '...' : s;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return String(value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function formatJson(value) {
|
|
138
|
+
if (value === undefined)
|
|
139
|
+
return 'undefined';
|
|
140
|
+
try {
|
|
141
|
+
return JSON.stringify(value);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return String(value);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function deepEqual(a, b) {
|
|
148
|
+
if (a === b)
|
|
149
|
+
return true;
|
|
150
|
+
if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
154
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
155
|
+
}
|
|
156
|
+
const keysA = Object.keys(a).sort();
|
|
157
|
+
const keysB = Object.keys(b).sort();
|
|
158
|
+
if (keysA.length !== keysB.length || keysA.some((k, i) => k !== keysB[i])) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
return keysA.every((k) => deepEqual(a[k], b[k]));
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=diff-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-reporter.js","sourceRoot":"","sources":["../../src/cli/diff-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task 21.2.1: softprobe diff CLI — load cassette inbound, send request with coordination headers.
|
|
3
|
+
* Design §3.1: CLI injects x-softprobe-mode and x-softprobe-trace-id (and traceparent).
|
|
4
|
+
* The target server must have cassetteDirectory set so it resolves the cassette as {cassetteDirectory}/{traceId}.ndjson.
|
|
5
|
+
* Sends W3C Traceparent so the server's OTel context uses the same trace id as the cassette.
|
|
6
|
+
* Task 13.10: Load via Cassette (getOrCreateCassette) only; no loadNdjson.
|
|
7
|
+
*/
|
|
8
|
+
import type { SoftprobeCassetteRecord } from '../types/schema';
|
|
9
|
+
export type RunDiffResult = {
|
|
10
|
+
response: Response;
|
|
11
|
+
inbound: SoftprobeCassetteRecord;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Loads cassette, finds inbound record, sends request to target with coordination headers.
|
|
15
|
+
* Returns the fetch Response and the inbound record so caller can compare recorded vs live.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runDiff(file: string, target: string): Promise<RunDiffResult>;
|
|
18
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/cli/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAqB/D,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAErF;;;GAGG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAsClF"}
|
package/dist/cli/diff.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Task 21.2.1: softprobe diff CLI — load cassette inbound, send request with coordination headers.
|
|
4
|
+
* Design §3.1: CLI injects x-softprobe-mode and x-softprobe-trace-id (and traceparent).
|
|
5
|
+
* The target server must have cassetteDirectory set so it resolves the cassette as {cassetteDirectory}/{traceId}.ndjson.
|
|
6
|
+
* Sends W3C Traceparent so the server's OTel context uses the same trace id as the cassette.
|
|
7
|
+
* Task 13.10: Load via Cassette (getOrCreateCassette) only; no loadNdjson.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
+
};
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.runDiff = runDiff;
|
|
47
|
+
const path_1 = __importDefault(require("path"));
|
|
48
|
+
const context_1 = require("../context");
|
|
49
|
+
/** Builds W3C Traceparent header (version-traceId-spanId-flags) so the server uses the cassette trace. */
|
|
50
|
+
function traceparentFromInbound(inbound) {
|
|
51
|
+
const traceId = (inbound.traceId ?? '').padEnd(32, '0').slice(0, 32).toLowerCase();
|
|
52
|
+
const spanId = (inbound.spanId ?? '0000000000000000').padEnd(16, '0').slice(0, 16).toLowerCase();
|
|
53
|
+
return `00-${traceId}-${spanId}-01`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parses HTTP identifier "METHOD url" into { method, url }.
|
|
57
|
+
*/
|
|
58
|
+
function parseHttpIdentifier(identifier) {
|
|
59
|
+
const idx = identifier.indexOf(' ');
|
|
60
|
+
if (idx < 0)
|
|
61
|
+
return { method: 'GET', url: identifier };
|
|
62
|
+
return {
|
|
63
|
+
method: identifier.slice(0, idx),
|
|
64
|
+
url: identifier.slice(idx + 1),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Loads cassette, finds inbound record, sends request to target with coordination headers.
|
|
69
|
+
* Returns the fetch Response and the inbound record so caller can compare recorded vs live.
|
|
70
|
+
*/
|
|
71
|
+
async function runDiff(file, target) {
|
|
72
|
+
const cassettePath = path_1.default.resolve(process.cwd(), file);
|
|
73
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
74
|
+
if (!fs.existsSync(cassettePath)) {
|
|
75
|
+
throw new Error(`Cassette file not found: ${cassettePath}. Run the diff from the repository root, e.g. bin/softprobe diff examples/basic-app/softprobe-cassettes.ndjson http://localhost:3000`);
|
|
76
|
+
}
|
|
77
|
+
const dir = path_1.default.dirname(cassettePath);
|
|
78
|
+
const traceId = path_1.default.basename(cassettePath, '.ndjson');
|
|
79
|
+
const records = await context_1.SoftprobeContext.getOrCreateCassette(dir, traceId).loadTrace();
|
|
80
|
+
const inbound = records.find((r) => r.type === 'inbound');
|
|
81
|
+
if (!inbound)
|
|
82
|
+
throw new Error("Cassette missing 'inbound' record.");
|
|
83
|
+
const { method, url } = parseHttpIdentifier(inbound.identifier);
|
|
84
|
+
const requestUrl = `${target.replace(/\/$/, '')}${url.startsWith('/') ? url : '/' + url}`;
|
|
85
|
+
const requestPayload = inbound.requestPayload;
|
|
86
|
+
const body = requestPayload?.body !== undefined
|
|
87
|
+
? (typeof requestPayload.body === 'string'
|
|
88
|
+
? requestPayload.body
|
|
89
|
+
: JSON.stringify(requestPayload.body))
|
|
90
|
+
: undefined;
|
|
91
|
+
const headers = {
|
|
92
|
+
'x-softprobe-mode': 'REPLAY',
|
|
93
|
+
'x-softprobe-trace-id': inbound.traceId ?? '',
|
|
94
|
+
traceparent: traceparentFromInbound(inbound),
|
|
95
|
+
};
|
|
96
|
+
if (body)
|
|
97
|
+
headers['Content-Type'] = 'application/json';
|
|
98
|
+
const response = await fetch(requestUrl, {
|
|
99
|
+
method,
|
|
100
|
+
headers,
|
|
101
|
+
body,
|
|
102
|
+
});
|
|
103
|
+
return { response, inbound };
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=diff.js.map
|