@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.
Files changed (328) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -0
  3. package/bin/softprobe +15 -0
  4. package/dist/api/baggage.d.ts +13 -0
  5. package/dist/api/baggage.d.ts.map +1 -0
  6. package/dist/api/baggage.js +32 -0
  7. package/dist/api/baggage.js.map +1 -0
  8. package/dist/api/compare.d.ts +16 -0
  9. package/dist/api/compare.d.ts.map +1 -0
  10. package/dist/api/compare.js +77 -0
  11. package/dist/api/compare.js.map +1 -0
  12. package/dist/api.d.ts +63 -0
  13. package/dist/api.d.ts.map +1 -0
  14. package/dist/api.js +104 -0
  15. package/dist/api.js.map +1 -0
  16. package/dist/bindings/http-span.d.ts +6 -0
  17. package/dist/bindings/http-span.d.ts.map +1 -0
  18. package/dist/bindings/http-span.js +11 -0
  19. package/dist/bindings/http-span.js.map +1 -0
  20. package/dist/bindings/postgres-span.d.ts +6 -0
  21. package/dist/bindings/postgres-span.d.ts.map +1 -0
  22. package/dist/bindings/postgres-span.js +11 -0
  23. package/dist/bindings/postgres-span.js.map +1 -0
  24. package/dist/bindings/redis-span.d.ts +6 -0
  25. package/dist/bindings/redis-span.d.ts.map +1 -0
  26. package/dist/bindings/redis-span.js +11 -0
  27. package/dist/bindings/redis-span.js.map +1 -0
  28. package/dist/bindings/test-span.d.ts +6 -0
  29. package/dist/bindings/test-span.d.ts.map +1 -0
  30. package/dist/bindings/test-span.js +9 -0
  31. package/dist/bindings/test-span.js.map +1 -0
  32. package/dist/bootstrap/otel/framework-mutator.d.ts +20 -0
  33. package/dist/bootstrap/otel/framework-mutator.d.ts.map +1 -0
  34. package/dist/bootstrap/otel/framework-mutator.js +144 -0
  35. package/dist/bootstrap/otel/framework-mutator.js.map +1 -0
  36. package/dist/bootstrap/otel/inject.d.ts +17 -0
  37. package/dist/bootstrap/otel/inject.d.ts.map +1 -0
  38. package/dist/bootstrap/otel/inject.js +28 -0
  39. package/dist/bootstrap/otel/inject.js.map +1 -0
  40. package/dist/bootstrap/otel/mutator.d.ts +17 -0
  41. package/dist/bootstrap/otel/mutator.d.ts.map +1 -0
  42. package/dist/bootstrap/otel/mutator.js +51 -0
  43. package/dist/bootstrap/otel/mutator.js.map +1 -0
  44. package/dist/capture/express.d.ts +6 -0
  45. package/dist/capture/express.d.ts.map +1 -0
  46. package/dist/capture/express.js +11 -0
  47. package/dist/capture/express.js.map +1 -0
  48. package/dist/capture/fastify.d.ts +5 -0
  49. package/dist/capture/fastify.d.ts.map +1 -0
  50. package/dist/capture/fastify.js +9 -0
  51. package/dist/capture/fastify.js.map +1 -0
  52. package/dist/capture/framework-mutator.d.ts +20 -0
  53. package/dist/capture/framework-mutator.d.ts.map +1 -0
  54. package/dist/capture/framework-mutator.js +144 -0
  55. package/dist/capture/framework-mutator.js.map +1 -0
  56. package/dist/capture/http-inbound.d.ts +28 -0
  57. package/dist/capture/http-inbound.d.ts.map +1 -0
  58. package/dist/capture/http-inbound.js +40 -0
  59. package/dist/capture/http-inbound.js.map +1 -0
  60. package/dist/capture/inject.d.ts +17 -0
  61. package/dist/capture/inject.d.ts.map +1 -0
  62. package/dist/capture/inject.js +28 -0
  63. package/dist/capture/inject.js.map +1 -0
  64. package/dist/capture/mutator.d.ts +17 -0
  65. package/dist/capture/mutator.d.ts.map +1 -0
  66. package/dist/capture/mutator.js +51 -0
  67. package/dist/capture/mutator.js.map +1 -0
  68. package/dist/capture/postgres.d.ts +6 -0
  69. package/dist/capture/postgres.d.ts.map +1 -0
  70. package/dist/capture/postgres.js +11 -0
  71. package/dist/capture/postgres.js.map +1 -0
  72. package/dist/capture/redis.d.ts +5 -0
  73. package/dist/capture/redis.d.ts.map +1 -0
  74. package/dist/capture/redis.js +10 -0
  75. package/dist/capture/redis.js.map +1 -0
  76. package/dist/capture/store-accessor.d.ts +11 -0
  77. package/dist/capture/store-accessor.d.ts.map +1 -0
  78. package/dist/capture/store-accessor.js +19 -0
  79. package/dist/capture/store-accessor.js.map +1 -0
  80. package/dist/capture/stream-tap.d.ts +5 -0
  81. package/dist/capture/stream-tap.d.ts.map +1 -0
  82. package/dist/capture/stream-tap.js +9 -0
  83. package/dist/capture/stream-tap.js.map +1 -0
  84. package/dist/cli/diff-reporter.d.ts +26 -0
  85. package/dist/cli/diff-reporter.d.ts.map +1 -0
  86. package/dist/cli/diff-reporter.js +163 -0
  87. package/dist/cli/diff-reporter.js.map +1 -0
  88. package/dist/cli/diff.d.ts +18 -0
  89. package/dist/cli/diff.d.ts.map +1 -0
  90. package/dist/cli/diff.js +105 -0
  91. package/dist/cli/diff.js.map +1 -0
  92. package/dist/cli.d.ts +7 -0
  93. package/dist/cli.d.ts.map +1 -0
  94. package/dist/cli.js +84 -0
  95. package/dist/cli.js.map +1 -0
  96. package/dist/config/config-manager.d.ts +20 -0
  97. package/dist/config/config-manager.d.ts.map +1 -0
  98. package/dist/config/config-manager.js +46 -0
  99. package/dist/config/config-manager.js.map +1 -0
  100. package/dist/context.d.ts +98 -0
  101. package/dist/context.d.ts.map +1 -0
  102. package/dist/context.js +198 -0
  103. package/dist/context.js.map +1 -0
  104. package/dist/core/bindings/http-span.d.ts +39 -0
  105. package/dist/core/bindings/http-span.d.ts.map +1 -0
  106. package/dist/core/bindings/http-span.js +55 -0
  107. package/dist/core/bindings/http-span.js.map +1 -0
  108. package/dist/core/bindings/index.d.ts +12 -0
  109. package/dist/core/bindings/index.d.ts.map +1 -0
  110. package/dist/core/bindings/index.js +21 -0
  111. package/dist/core/bindings/index.js.map +1 -0
  112. package/dist/core/bindings/postgres-span.d.ts +41 -0
  113. package/dist/core/bindings/postgres-span.d.ts.map +1 -0
  114. package/dist/core/bindings/postgres-span.js +57 -0
  115. package/dist/core/bindings/postgres-span.js.map +1 -0
  116. package/dist/core/bindings/redis-span.d.ts +40 -0
  117. package/dist/core/bindings/redis-span.d.ts.map +1 -0
  118. package/dist/core/bindings/redis-span.js +65 -0
  119. package/dist/core/bindings/redis-span.js.map +1 -0
  120. package/dist/core/bindings/test-span.d.ts +15 -0
  121. package/dist/core/bindings/test-span.d.ts.map +1 -0
  122. package/dist/core/bindings/test-span.js +24 -0
  123. package/dist/core/bindings/test-span.js.map +1 -0
  124. package/dist/core/cassette/capture-store-accessor.d.ts +11 -0
  125. package/dist/core/cassette/capture-store-accessor.d.ts.map +1 -0
  126. package/dist/core/cassette/capture-store-accessor.js +19 -0
  127. package/dist/core/cassette/capture-store-accessor.js.map +1 -0
  128. package/dist/core/cassette/context-request-storage.d.ts +14 -0
  129. package/dist/core/cassette/context-request-storage.d.ts.map +1 -0
  130. package/dist/core/cassette/context-request-storage.js +24 -0
  131. package/dist/core/cassette/context-request-storage.js.map +1 -0
  132. package/dist/core/cassette/index.d.ts +8 -0
  133. package/dist/core/cassette/index.d.ts.map +1 -0
  134. package/dist/core/cassette/index.js +16 -0
  135. package/dist/core/cassette/index.js.map +1 -0
  136. package/dist/core/cassette/ndjson-cassette.d.ts +22 -0
  137. package/dist/core/cassette/ndjson-cassette.d.ts.map +1 -0
  138. package/dist/core/cassette/ndjson-cassette.js +56 -0
  139. package/dist/core/cassette/ndjson-cassette.js.map +1 -0
  140. package/dist/core/cassette/request-storage.d.ts +16 -0
  141. package/dist/core/cassette/request-storage.d.ts.map +1 -0
  142. package/dist/core/cassette/request-storage.js +22 -0
  143. package/dist/core/cassette/request-storage.js.map +1 -0
  144. package/dist/core/context/index.d.ts +5 -0
  145. package/dist/core/context/index.d.ts.map +1 -0
  146. package/dist/core/context/index.js +9 -0
  147. package/dist/core/context/index.js.map +1 -0
  148. package/dist/core/contracts/index.d.ts +5 -0
  149. package/dist/core/contracts/index.d.ts.map +1 -0
  150. package/dist/core/contracts/index.js +3 -0
  151. package/dist/core/contracts/index.js.map +1 -0
  152. package/dist/core/identifier.d.ts +20 -0
  153. package/dist/core/identifier.d.ts.map +1 -0
  154. package/dist/core/identifier.js +31 -0
  155. package/dist/core/identifier.js.map +1 -0
  156. package/dist/core/index.d.ts +11 -0
  157. package/dist/core/index.d.ts.map +1 -0
  158. package/dist/core/index.js +27 -0
  159. package/dist/core/index.js.map +1 -0
  160. package/dist/core/matcher/extract-key.d.ts +41 -0
  161. package/dist/core/matcher/extract-key.d.ts.map +1 -0
  162. package/dist/core/matcher/extract-key.js +80 -0
  163. package/dist/core/matcher/extract-key.js.map +1 -0
  164. package/dist/core/matcher/index.d.ts +9 -0
  165. package/dist/core/matcher/index.d.ts.map +1 -0
  166. package/dist/core/matcher/index.js +24 -0
  167. package/dist/core/matcher/index.js.map +1 -0
  168. package/dist/core/matcher/matcher.d.ts +25 -0
  169. package/dist/core/matcher/matcher.d.ts.map +1 -0
  170. package/dist/core/matcher/matcher.js +83 -0
  171. package/dist/core/matcher/matcher.js.map +1 -0
  172. package/dist/core/matcher/softprobe-matcher.d.ts +41 -0
  173. package/dist/core/matcher/softprobe-matcher.d.ts.map +1 -0
  174. package/dist/core/matcher/softprobe-matcher.js +92 -0
  175. package/dist/core/matcher/softprobe-matcher.js.map +1 -0
  176. package/dist/core/matcher/store-accessor.d.ts +14 -0
  177. package/dist/core/matcher/store-accessor.d.ts.map +1 -0
  178. package/dist/core/matcher/store-accessor.js +25 -0
  179. package/dist/core/matcher/store-accessor.js.map +1 -0
  180. package/dist/core/matcher/topology.d.ts +37 -0
  181. package/dist/core/matcher/topology.d.ts.map +1 -0
  182. package/dist/core/matcher/topology.js +72 -0
  183. package/dist/core/matcher/topology.js.map +1 -0
  184. package/dist/core/runtime/architecture-guard.d.ts +9 -0
  185. package/dist/core/runtime/architecture-guard.d.ts.map +1 -0
  186. package/dist/core/runtime/architecture-guard.js +131 -0
  187. package/dist/core/runtime/architecture-guard.js.map +1 -0
  188. package/dist/core/runtime/index.d.ts +6 -0
  189. package/dist/core/runtime/index.d.ts.map +1 -0
  190. package/dist/core/runtime/index.js +11 -0
  191. package/dist/core/runtime/index.js.map +1 -0
  192. package/dist/identifier.d.ts +5 -0
  193. package/dist/identifier.d.ts.map +1 -0
  194. package/dist/identifier.js +11 -0
  195. package/dist/identifier.js.map +1 -0
  196. package/dist/index.d.ts +5 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/index.js +21 -0
  199. package/dist/index.js.map +1 -0
  200. package/dist/init.d.ts +21 -0
  201. package/dist/init.d.ts.map +1 -0
  202. package/dist/init.js +51 -0
  203. package/dist/init.js.map +1 -0
  204. package/dist/instrumentations/common/http/context-headers.d.ts +9 -0
  205. package/dist/instrumentations/common/http/context-headers.d.ts.map +1 -0
  206. package/dist/instrumentations/common/http/context-headers.js +16 -0
  207. package/dist/instrumentations/common/http/context-headers.js.map +1 -0
  208. package/dist/instrumentations/common/http/inbound-capture.d.ts +17 -0
  209. package/dist/instrumentations/common/http/inbound-capture.d.ts.map +1 -0
  210. package/dist/instrumentations/common/http/inbound-capture.js +41 -0
  211. package/dist/instrumentations/common/http/inbound-capture.js.map +1 -0
  212. package/dist/instrumentations/common/http/inbound-record.d.ts +28 -0
  213. package/dist/instrumentations/common/http/inbound-record.d.ts.map +1 -0
  214. package/dist/instrumentations/common/http/inbound-record.js +40 -0
  215. package/dist/instrumentations/common/http/inbound-record.js.map +1 -0
  216. package/dist/instrumentations/common/http/span-adapter.d.ts +6 -0
  217. package/dist/instrumentations/common/http/span-adapter.d.ts.map +1 -0
  218. package/dist/instrumentations/common/http/span-adapter.js +12 -0
  219. package/dist/instrumentations/common/http/span-adapter.js.map +1 -0
  220. package/dist/instrumentations/common/http/stream-tap.d.ts +28 -0
  221. package/dist/instrumentations/common/http/stream-tap.d.ts.map +1 -0
  222. package/dist/instrumentations/common/http/stream-tap.js +61 -0
  223. package/dist/instrumentations/common/http/stream-tap.js.map +1 -0
  224. package/dist/instrumentations/express/capture.d.ts +26 -0
  225. package/dist/instrumentations/express/capture.d.ts.map +1 -0
  226. package/dist/instrumentations/express/capture.js +80 -0
  227. package/dist/instrumentations/express/capture.js.map +1 -0
  228. package/dist/instrumentations/express/index.d.ts +7 -0
  229. package/dist/instrumentations/express/index.d.ts.map +1 -0
  230. package/dist/instrumentations/express/index.js +15 -0
  231. package/dist/instrumentations/express/index.js.map +1 -0
  232. package/dist/instrumentations/express/replay.d.ts +10 -0
  233. package/dist/instrumentations/express/replay.d.ts.map +1 -0
  234. package/dist/instrumentations/express/replay.js +16 -0
  235. package/dist/instrumentations/express/replay.js.map +1 -0
  236. package/dist/instrumentations/fastify/capture.d.ts +13 -0
  237. package/dist/instrumentations/fastify/capture.d.ts.map +1 -0
  238. package/dist/instrumentations/fastify/capture.js +65 -0
  239. package/dist/instrumentations/fastify/capture.js.map +1 -0
  240. package/dist/instrumentations/fastify/index.d.ts +7 -0
  241. package/dist/instrumentations/fastify/index.d.ts.map +1 -0
  242. package/dist/instrumentations/fastify/index.js +13 -0
  243. package/dist/instrumentations/fastify/index.js.map +1 -0
  244. package/dist/instrumentations/fastify/replay.d.ts +13 -0
  245. package/dist/instrumentations/fastify/replay.d.ts.map +1 -0
  246. package/dist/instrumentations/fastify/replay.js +24 -0
  247. package/dist/instrumentations/fastify/replay.js.map +1 -0
  248. package/dist/instrumentations/fetch/index.d.ts +5 -0
  249. package/dist/instrumentations/fetch/index.d.ts.map +1 -0
  250. package/dist/instrumentations/fetch/index.js +10 -0
  251. package/dist/instrumentations/fetch/index.js.map +1 -0
  252. package/dist/instrumentations/fetch/replay.d.ts +19 -0
  253. package/dist/instrumentations/fetch/replay.d.ts.map +1 -0
  254. package/dist/instrumentations/fetch/replay.js +259 -0
  255. package/dist/instrumentations/fetch/replay.js.map +1 -0
  256. package/dist/instrumentations/postgres/capture.d.ts +46 -0
  257. package/dist/instrumentations/postgres/capture.d.ts.map +1 -0
  258. package/dist/instrumentations/postgres/capture.js +68 -0
  259. package/dist/instrumentations/postgres/capture.js.map +1 -0
  260. package/dist/instrumentations/postgres/index.d.ts +6 -0
  261. package/dist/instrumentations/postgres/index.d.ts.map +1 -0
  262. package/dist/instrumentations/postgres/index.js +14 -0
  263. package/dist/instrumentations/postgres/index.js.map +1 -0
  264. package/dist/instrumentations/postgres/replay.d.ts +20 -0
  265. package/dist/instrumentations/postgres/replay.d.ts.map +1 -0
  266. package/dist/instrumentations/postgres/replay.js +163 -0
  267. package/dist/instrumentations/postgres/replay.js.map +1 -0
  268. package/dist/instrumentations/redis/capture.d.ts +20 -0
  269. package/dist/instrumentations/redis/capture.d.ts.map +1 -0
  270. package/dist/instrumentations/redis/capture.js +61 -0
  271. package/dist/instrumentations/redis/capture.js.map +1 -0
  272. package/dist/instrumentations/redis/index.d.ts +6 -0
  273. package/dist/instrumentations/redis/index.d.ts.map +1 -0
  274. package/dist/instrumentations/redis/index.js +13 -0
  275. package/dist/instrumentations/redis/index.js.map +1 -0
  276. package/dist/instrumentations/redis/replay.d.ts +24 -0
  277. package/dist/instrumentations/redis/replay.d.ts.map +1 -0
  278. package/dist/instrumentations/redis/replay.js +173 -0
  279. package/dist/instrumentations/redis/replay.js.map +1 -0
  280. package/dist/replay/express.d.ts +5 -0
  281. package/dist/replay/express.d.ts.map +1 -0
  282. package/dist/replay/express.js +9 -0
  283. package/dist/replay/express.js.map +1 -0
  284. package/dist/replay/extract-key.d.ts +41 -0
  285. package/dist/replay/extract-key.d.ts.map +1 -0
  286. package/dist/replay/extract-key.js +80 -0
  287. package/dist/replay/extract-key.js.map +1 -0
  288. package/dist/replay/fastify.d.ts +5 -0
  289. package/dist/replay/fastify.d.ts.map +1 -0
  290. package/dist/replay/fastify.js +9 -0
  291. package/dist/replay/fastify.js.map +1 -0
  292. package/dist/replay/http.d.ts +5 -0
  293. package/dist/replay/http.d.ts.map +1 -0
  294. package/dist/replay/http.js +10 -0
  295. package/dist/replay/http.js.map +1 -0
  296. package/dist/replay/matcher.d.ts +25 -0
  297. package/dist/replay/matcher.d.ts.map +1 -0
  298. package/dist/replay/matcher.js +83 -0
  299. package/dist/replay/matcher.js.map +1 -0
  300. package/dist/replay/postgres.d.ts +5 -0
  301. package/dist/replay/postgres.d.ts.map +1 -0
  302. package/dist/replay/postgres.js +10 -0
  303. package/dist/replay/postgres.js.map +1 -0
  304. package/dist/replay/redis.d.ts +5 -0
  305. package/dist/replay/redis.d.ts.map +1 -0
  306. package/dist/replay/redis.js +10 -0
  307. package/dist/replay/redis.js.map +1 -0
  308. package/dist/replay/softprobe-matcher.d.ts +41 -0
  309. package/dist/replay/softprobe-matcher.d.ts.map +1 -0
  310. package/dist/replay/softprobe-matcher.js +92 -0
  311. package/dist/replay/softprobe-matcher.js.map +1 -0
  312. package/dist/replay/store-accessor.d.ts +14 -0
  313. package/dist/replay/store-accessor.d.ts.map +1 -0
  314. package/dist/replay/store-accessor.js +26 -0
  315. package/dist/replay/store-accessor.js.map +1 -0
  316. package/dist/replay/topology.d.ts +37 -0
  317. package/dist/replay/topology.d.ts.map +1 -0
  318. package/dist/replay/topology.js +72 -0
  319. package/dist/replay/topology.js.map +1 -0
  320. package/dist/store/cassette-store.d.ts +36 -0
  321. package/dist/store/cassette-store.d.ts.map +1 -0
  322. package/dist/store/cassette-store.js +66 -0
  323. package/dist/store/cassette-store.js.map +1 -0
  324. package/dist/types/schema.d.ts +114 -0
  325. package/dist/types/schema.d.ts.map +1 -0
  326. package/dist/types/schema.js +13 -0
  327. package/dist/types/schema.js.map +1 -0
  328. package/package.json +88 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../../src/instrumentations/redis/capture.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,eAAO,MAAM,0BAA0B,2CAA2C,CAAC;AAUnF;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAqCrE"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /**
3
+ * Capture hook for Redis. Pairs with replay/redis.ts (same protocol & identifier).
4
+ * Design §3.1, §5.3: responseHook contract must match @opentelemetry/instrumentation-redis-4.
5
+ * Design §10.5: when capture store is set, writes outbound record with responsePayload.
6
+ *
7
+ * Actual contract (from types.d.ts):
8
+ * responseHook(span: Span, cmdName: string, cmdArgs: Array<string|Buffer>, response: unknown): void
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.REDIS_INSTRUMENTATION_NAME = void 0;
12
+ exports.buildRedisResponseHook = buildRedisResponseHook;
13
+ const identifier_1 = require("../../core/identifier");
14
+ const context_1 = require("../../context");
15
+ exports.REDIS_INSTRUMENTATION_NAME = '@opentelemetry/instrumentation-redis-4';
16
+ /**
17
+ * Builds the responseHook for Redis instrumentation.
18
+ * Sets softprobe.protocol: 'redis', identifier (command + args), and
19
+ * request/response on spans per design §3.1.
20
+ * When a capture store is set, writes an outbound SoftprobeCassetteRecord (Task 10.5.1).
21
+ *
22
+ * The instrumentation calls: responseHook(span, cmdName, cmdArgs, response).
23
+ * We declare the return type loosely so it can be stored via injectHook.
24
+ */
25
+ function buildRedisResponseHook() {
26
+ return (span, cmdName, cmdArgs, response) => {
27
+ const s = span;
28
+ const cmd = (cmdName != null ? String(cmdName) : 'UNKNOWN').toUpperCase();
29
+ const args = Array.isArray(cmdArgs)
30
+ ? cmdArgs.map((a) => (a != null ? String(a) : ''))
31
+ : [];
32
+ const identifier = (0, identifier_1.redisIdentifier)(cmd, args);
33
+ s.setAttribute?.('softprobe.protocol', 'redis');
34
+ s.setAttribute?.('softprobe.identifier', identifier);
35
+ if (args.length > 0) {
36
+ s.setAttribute?.('softprobe.request.body', JSON.stringify(args));
37
+ }
38
+ if (typeof response !== 'undefined') {
39
+ s.setAttribute?.('softprobe.response.body', JSON.stringify(response));
40
+ }
41
+ const ctx = s.spanContext?.() ?? { traceId: '', spanId: '' };
42
+ const record = {
43
+ version: '4.1',
44
+ traceId: ctx.traceId,
45
+ spanId: ctx.spanId,
46
+ parentSpanId: s.parentSpanId,
47
+ spanName: s.name,
48
+ timestamp: new Date().toISOString(),
49
+ type: 'outbound',
50
+ protocol: 'redis',
51
+ identifier,
52
+ responsePayload: response,
53
+ };
54
+ const cassette = context_1.SoftprobeContext.getCassette();
55
+ if (context_1.SoftprobeContext.getMode() === 'CAPTURE' && cassette) {
56
+ const tid = context_1.SoftprobeContext.getTraceId();
57
+ void cassette.saveRecord(tid ? { ...record, traceId: tid } : record).catch(() => { });
58
+ }
59
+ };
60
+ }
61
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../src/instrumentations/redis/capture.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAyBH,wDAqCC;AA3DD,sDAAwD;AACxD,2CAAiD;AAEpC,QAAA,0BAA0B,GAAG,wCAAwC,CAAC;AAUnF;;;;;;;;GAQG;AACH,SAAgB,sBAAsB;IACpC,OAAO,CAAC,IAAa,EAAE,OAAgB,EAAE,OAAgB,EAAE,QAAiB,EAAE,EAAE;QAC9E,MAAM,CAAC,GAAG,IAA0E,CAAC;QACrF,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1E,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YACjC,CAAC,CAAE,OAA+B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3E,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,UAAU,GAAG,IAAA,4BAAe,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAE9C,CAAC,CAAC,YAAY,EAAE,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC,CAAC,YAAY,EAAE,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,CAAC,CAAC,YAAY,EAAE,CAAC,wBAAwB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACpC,CAAC,CAAC,YAAY,EAAE,CAAC,yBAAyB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC7D,MAAM,MAAM,GAA4B;YACtC,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,QAAQ,EAAE,CAAC,CAAC,IAAI;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,OAAO;YACjB,UAAU;YACV,eAAe,EAAE,QAAQ;SAC1B,CAAC;QACF,MAAM,QAAQ,GAAG,0BAAgB,CAAC,WAAW,EAAE,CAAC;QAChD,IAAI,0BAAgB,CAAC,OAAO,EAAE,KAAK,SAAS,IAAI,QAAQ,EAAE,CAAC;YACzD,MAAM,GAAG,GAAG,0BAAgB,CAAC,UAAU,EAAE,CAAC;YAC1C,KAAK,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvF,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Redis instrumentation package entry point.
3
+ */
4
+ export { REDIS_INSTRUMENTATION_NAME, buildRedisResponseHook } from './capture';
5
+ export { applyRedisReplay, setupRedisReplay } from './replay';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/instrumentations/redis/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupRedisReplay = exports.applyRedisReplay = exports.buildRedisResponseHook = exports.REDIS_INSTRUMENTATION_NAME = void 0;
4
+ /**
5
+ * Redis instrumentation package entry point.
6
+ */
7
+ var capture_1 = require("./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
+ var replay_1 = require("./replay");
11
+ Object.defineProperty(exports, "applyRedisReplay", { enumerable: true, get: function () { return replay_1.applyRedisReplay; } });
12
+ Object.defineProperty(exports, "setupRedisReplay", { enumerable: true, get: function () { return replay_1.setupRedisReplay; } });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/instrumentations/redis/index.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,qCAA+E;AAAtE,qHAAA,0BAA0B,OAAA;AAAE,iHAAA,sBAAsB,OAAA;AAC3D,mCAA8D;AAArD,0GAAA,gBAAgB,OAAA;AAAE,0GAAA,gBAAgB,OAAA"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Redis replay: patches Redis client so that under replay context commands are
3
+ * resolved by matcher actions (no live network). Pairs with capture Task 4.5;
4
+ * identifier = command + args per design §3.1, §6.3.
5
+ *
6
+ * We wrap the commander's attachCommands so that the executor passed to each
7
+ * command (get, set, etc.) is our wrapper; the client captures that executor in
8
+ * a closure when the module loads, so we must patch before the client loads.
9
+ */
10
+ /**
11
+ * Sets up Redis replay by wrapping the commander's attachCommands so the
12
+ * executor used by get/set/etc. is our wrapper (matcher-aware). Must run
13
+ * before the redis client module is loaded so the closure captures our wrapper.
14
+ */
15
+ export declare function setupRedisReplay(): void;
16
+ /**
17
+ * Wraps createClient so every new client gets connect/quit no-ops as instance own-properties.
18
+ * Using instance-level patching (not prototype) makes it immune to OTel re-patching the redis
19
+ * module at sdk.start(), which creates new Commander prototype objects that would bypass a
20
+ * prototype-level patch applied before sdk.start().
21
+ * Idempotent. Exported so init can call it from a require hook (Task 16.3.1).
22
+ */
23
+ export declare function applyRedisReplay(redis: Record<string, unknown>): void;
24
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../../src/instrumentations/redis/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmBH;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CA+HvC;AAgCD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAgBrE"}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ /**
3
+ * Redis replay: patches Redis client so that under replay context commands are
4
+ * resolved by matcher actions (no live network). Pairs with capture Task 4.5;
5
+ * identifier = command + args per design §3.1, §6.3.
6
+ *
7
+ * We wrap the commander's attachCommands so that the executor passed to each
8
+ * command (get, set, etc.) is our wrapper; the client captures that executor in
9
+ * a closure when the module loads, so we must patch before the client loads.
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.setupRedisReplay = setupRedisReplay;
16
+ exports.applyRedisReplay = applyRedisReplay;
17
+ const api_1 = require("@opentelemetry/api");
18
+ const shimmer_1 = __importDefault(require("shimmer"));
19
+ const redis_span_1 = require("../../core/bindings/redis-span");
20
+ const context_1 = require("../../context");
21
+ /**
22
+ * Builds the same identifier string as the Redis capture hook (capture/redis.ts):
23
+ * command name (uppercase) plus args joined by space.
24
+ */
25
+ function buildIdentifier(redisArgs) {
26
+ if (!Array.isArray(redisArgs) || redisArgs.length === 0)
27
+ return '';
28
+ const cmd = (redisArgs[0] != null ? String(redisArgs[0]) : 'UNKNOWN').toUpperCase();
29
+ const rest = redisArgs.slice(1).map((a) => (a != null ? String(a) : ''));
30
+ return [cmd, ...rest].join(' ').trim();
31
+ }
32
+ /**
33
+ * Sets up Redis replay by wrapping the commander's attachCommands so the
34
+ * executor used by get/set/etc. is our wrapper (matcher-aware). Must run
35
+ * before the redis client module is loaded so the closure captures our wrapper.
36
+ */
37
+ function setupRedisReplay() {
38
+ const commanderModule = require('@redis/client/dist/lib/commander');
39
+ const { transformCommandArguments, transformCommandReply } = commanderModule;
40
+ if (!transformCommandArguments || !transformCommandReply)
41
+ return;
42
+ shimmer_1.default.wrap(commanderModule, 'attachCommands', (originalAttachCommands) => (config) => {
43
+ const cfg = config;
44
+ const originalExecutor = cfg.executor;
45
+ const wrappedConfig = {
46
+ ...cfg,
47
+ executor: function patchedExecutor(command, args, _name) {
48
+ const matcher = context_1.SoftprobeContext.active().matcher;
49
+ const mode = context_1.SoftprobeContext.getMode();
50
+ const strictReplay = context_1.SoftprobeContext.getStrictReplay();
51
+ if (mode === 'REPLAY' && !matcher && strictReplay) {
52
+ return Promise.reject(new Error('Softprobe replay: no match for redis command'));
53
+ }
54
+ const { args: redisArgs } = transformCommandArguments(command, args);
55
+ const cmd = (redisArgs[0] != null ? String(redisArgs[0]) : 'UNKNOWN').toUpperCase();
56
+ if (mode === 'REPLAY' && (cmd === 'QUIT' || cmd === 'DISCONNECT')) {
57
+ return Promise.resolve('OK');
58
+ }
59
+ if (!matcher) {
60
+ return originalExecutor.call(this, command, args, _name);
61
+ }
62
+ const cmdArgs = redisArgs.slice(1).map((a) => (a != null ? String(a) : ''));
63
+ redis_span_1.RedisSpan.tagCommand(cmd, cmdArgs, api_1.trace.getActiveSpan() ?? undefined);
64
+ const identifier = buildIdentifier(redisArgs);
65
+ let payload;
66
+ const softprobeMatcher = matcher;
67
+ if (typeof softprobeMatcher.match === 'function') {
68
+ const r = softprobeMatcher.match?.({
69
+ attributes: {
70
+ 'softprobe.protocol': 'redis',
71
+ 'softprobe.identifier': identifier,
72
+ 'softprobe.redis.cmd': cmd,
73
+ 'softprobe.request.body': JSON.stringify(redisArgs),
74
+ },
75
+ });
76
+ if (r.action === 'MOCK') {
77
+ payload = r.payload;
78
+ }
79
+ else if (r.action === 'PASSTHROUGH') {
80
+ return originalExecutor.call(this, command, args, _name);
81
+ }
82
+ else if (strictReplay) {
83
+ return Promise.reject(new Error('Softprobe replay: no match for redis command'));
84
+ }
85
+ else {
86
+ // CONTINUE + DEV: passthrough (design §9.3)
87
+ return originalExecutor.call(this, command, args, _name);
88
+ }
89
+ }
90
+ else {
91
+ try {
92
+ payload = matcher.findMatch({
93
+ protocol: 'redis',
94
+ identifier,
95
+ requestBody: redisArgs,
96
+ });
97
+ }
98
+ catch (err) {
99
+ if (strictReplay) {
100
+ return Promise.reject(new Error('Softprobe replay: no match for redis command'));
101
+ }
102
+ // CONTINUE + DEV: passthrough (design §9.3)
103
+ return originalExecutor.call(this, command, args, _name);
104
+ }
105
+ }
106
+ if (typeof payload === 'undefined') {
107
+ if (strictReplay) {
108
+ return Promise.reject(new Error('Softprobe replay: no match for redis command'));
109
+ }
110
+ // CONTINUE + DEV: passthrough (design §9.3)
111
+ return originalExecutor.call(this, command, args, _name);
112
+ }
113
+ const preserved = redisArgs?.preserve;
114
+ return Promise.resolve(transformCommandReply(command, payload, preserved));
115
+ },
116
+ };
117
+ return originalAttachCommands(wrappedConfig);
118
+ });
119
+ // Ensure client module loads after our patch so attachCommands uses our wrapper
120
+ try {
121
+ const redis = require('redis');
122
+ applyRedisReplay(redis);
123
+ }
124
+ catch {
125
+ // redis optional; tests will require it
126
+ }
127
+ }
128
+ /**
129
+ * Wraps connect/quit/QUIT on a single Redis client instance as own properties.
130
+ * Own-property wrappers shadow the prototype and survive any prototype-chain reshuffling
131
+ * caused by OTel's module re-patching at sdk.start().
132
+ */
133
+ function applyInstanceNoops(client) {
134
+ if (typeof client.connect === 'function') {
135
+ const orig = client.connect;
136
+ client.connect = function (...args) {
137
+ if (context_1.SoftprobeContext.getMode() === 'REPLAY')
138
+ return Promise.resolve();
139
+ return orig.apply(this, args);
140
+ };
141
+ }
142
+ const noopQuitFn = (orig) => function (...args) {
143
+ if (context_1.SoftprobeContext.getMode() === 'REPLAY')
144
+ return Promise.resolve('OK');
145
+ return orig.apply(this, args);
146
+ };
147
+ if (typeof client.quit === 'function')
148
+ client.quit = noopQuitFn(client.quit);
149
+ if (typeof client.QUIT === 'function')
150
+ client.QUIT = noopQuitFn(client.QUIT);
151
+ }
152
+ const SOFTPROBE_CREATE_CLIENT_WRAPPED = '__softprobeCreateClientWrapped';
153
+ /**
154
+ * Wraps createClient so every new client gets connect/quit no-ops as instance own-properties.
155
+ * Using instance-level patching (not prototype) makes it immune to OTel re-patching the redis
156
+ * module at sdk.start(), which creates new Commander prototype objects that would bypass a
157
+ * prototype-level patch applied before sdk.start().
158
+ * Idempotent. Exported so init can call it from a require hook (Task 16.3.1).
159
+ */
160
+ function applyRedisReplay(redis) {
161
+ const target = redis.createClient != null ? redis : redis.default;
162
+ if (!target)
163
+ return;
164
+ if (target.createClient?.[SOFTPROBE_CREATE_CLIENT_WRAPPED])
165
+ return;
166
+ shimmer_1.default.wrap(target, 'createClient', (original) => function (...args) {
167
+ const client = original.apply(this, args);
168
+ applyInstanceNoops(client);
169
+ return client;
170
+ });
171
+ target.createClient[SOFTPROBE_CREATE_CLIENT_WRAPPED] = true;
172
+ }
173
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../../src/instrumentations/redis/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Legacy compatibility re-export for Express replay instrumentation.
3
+ */
4
+ export { activateReplayForContext } from '../instrumentations/express/replay';
5
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/replay/express.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.activateReplayForContext = void 0;
4
+ /**
5
+ * Legacy compatibility re-export for Express replay instrumentation.
6
+ */
7
+ var replay_1 = require("../instrumentations/express/replay");
8
+ Object.defineProperty(exports, "activateReplayForContext", { enumerable: true, get: function () { return replay_1.activateReplayForContext; } });
9
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/replay/express.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,6DAA8E;AAArE,kHAAA,wBAAwB,OAAA"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Key extraction and candidate filtering for default matcher (design §7.3).
3
+ * Derives { protocol, identifier } from a span; filters outbound records by key.
4
+ */
5
+ import type { MatcherFn, SoftprobeCassetteRecord } from '../types/schema';
6
+ /** Key used for flat matching: protocol + identifier. */
7
+ export type SpanKey = {
8
+ protocol: 'postgres' | 'redis' | 'http';
9
+ identifier: string;
10
+ };
11
+ /** Span-like with readable attributes (OTel Span or test span). */
12
+ type ReadableSpan = {
13
+ attributes?: Record<string, unknown>;
14
+ } | undefined;
15
+ /**
16
+ * Extracts matching key from a span using PostgresSpan, RedisSpan, and HttpSpan.
17
+ * Returns the first non-null fromSpan result as { protocol, identifier }; unknown span yields null.
18
+ */
19
+ export declare function extractKeyFromSpan(span: ReadableSpan): SpanKey | null;
20
+ /**
21
+ * Returns only outbound records whose protocol and identifier match the key.
22
+ */
23
+ export declare function filterOutboundCandidates(records: SoftprobeCassetteRecord[], key: SpanKey): SoftprobeCassetteRecord[];
24
+ /**
25
+ * Per-key call sequence for default matcher: tracks the next candidate index
26
+ * per (protocol, identifier). getAndIncrement returns the current index and advances.
27
+ */
28
+ export declare class CallSeq {
29
+ private next;
30
+ /**
31
+ * Returns the current index for this key and increments for the next call.
32
+ */
33
+ getAndIncrement(key: SpanKey): number;
34
+ }
35
+ /**
36
+ * Returns a MatcherFn that uses extractKeyFromSpan, filterOutboundCandidates,
37
+ * and CallSeq to pick an outbound record and return MOCK with its responsePayload.
38
+ */
39
+ export declare function createDefaultMatcher(): MatcherFn;
40
+ export {};
41
+ //# sourceMappingURL=extract-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-key.d.ts","sourceRoot":"","sources":["../../src/replay/extract-key.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAEV,SAAS,EACT,uBAAuB,EACxB,MAAM,iBAAiB,CAAC;AAKzB,yDAAyD;AACzD,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,mEAAmE;AACnE,KAAK,YAAY,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,SAAS,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,GAAG,IAAI,CAWrE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,EAAE,EAClC,GAAG,EAAE,OAAO,GACX,uBAAuB,EAAE,CAO3B;AAMD;;;GAGG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,IAAI,CAA6B;IAEzC;;OAEG;IACH,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;CAMtC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,SAAS,CAYhD"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Key extraction and candidate filtering for default matcher (design §7.3).
4
+ * Derives { protocol, identifier } from a span; filters outbound records by key.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CallSeq = void 0;
8
+ exports.extractKeyFromSpan = extractKeyFromSpan;
9
+ exports.filterOutboundCandidates = filterOutboundCandidates;
10
+ exports.createDefaultMatcher = createDefaultMatcher;
11
+ const postgres_span_1 = require("../core/bindings/postgres-span");
12
+ const redis_span_1 = require("../core/bindings/redis-span");
13
+ const http_span_1 = require("../core/bindings/http-span");
14
+ /**
15
+ * Extracts matching key from a span using PostgresSpan, RedisSpan, and HttpSpan.
16
+ * Returns the first non-null fromSpan result as { protocol, identifier }; unknown span yields null.
17
+ */
18
+ function extractKeyFromSpan(span) {
19
+ const pg = postgres_span_1.PostgresSpan.fromSpan(span);
20
+ if (pg)
21
+ return { protocol: 'postgres', identifier: pg.identifier };
22
+ const redis = redis_span_1.RedisSpan.fromSpan(span);
23
+ if (redis)
24
+ return { protocol: 'redis', identifier: redis.identifier };
25
+ const http = http_span_1.HttpSpan.fromSpan(span);
26
+ if (http)
27
+ return { protocol: 'http', identifier: http.identifier };
28
+ return null;
29
+ }
30
+ /**
31
+ * Returns only outbound records whose protocol and identifier match the key.
32
+ */
33
+ function filterOutboundCandidates(records, key) {
34
+ return records.filter((r) => r.type === 'outbound' &&
35
+ r.protocol === key.protocol &&
36
+ r.identifier === key.identifier);
37
+ }
38
+ function seqKey(key) {
39
+ return `${key.protocol}::${key.identifier}`;
40
+ }
41
+ /**
42
+ * Per-key call sequence for default matcher: tracks the next candidate index
43
+ * per (protocol, identifier). getAndIncrement returns the current index and advances.
44
+ */
45
+ class CallSeq {
46
+ constructor() {
47
+ this.next = new Map();
48
+ }
49
+ /**
50
+ * Returns the current index for this key and increments for the next call.
51
+ */
52
+ getAndIncrement(key) {
53
+ const k = seqKey(key);
54
+ const idx = this.next.get(k) ?? 0;
55
+ this.next.set(k, idx + 1);
56
+ return idx;
57
+ }
58
+ }
59
+ exports.CallSeq = CallSeq;
60
+ /**
61
+ * Returns a MatcherFn that uses extractKeyFromSpan, filterOutboundCandidates,
62
+ * and CallSeq to pick an outbound record and return MOCK with its responsePayload.
63
+ */
64
+ function createDefaultMatcher() {
65
+ const callSeq = new CallSeq();
66
+ return (span, records) => {
67
+ const key = extractKeyFromSpan(span);
68
+ if (!key)
69
+ return { action: 'CONTINUE' };
70
+ const candidates = filterOutboundCandidates(records, key);
71
+ if (candidates.length === 0)
72
+ return { action: 'CONTINUE' };
73
+ const idx = callSeq.getAndIncrement(key);
74
+ if (idx >= candidates.length)
75
+ return { action: 'CONTINUE' };
76
+ const record = candidates[idx];
77
+ return { action: 'MOCK', payload: record?.responsePayload, traceId: record?.traceId };
78
+ };
79
+ }
80
+ //# sourceMappingURL=extract-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-key.js","sourceRoot":"","sources":["../../src/replay/extract-key.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAwBH,gDAWC;AAKD,4DAUC;AA4BD,oDAYC;AAnFD,kEAA8D;AAC9D,4DAAwD;AACxD,0DAAsD;AAWtD;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,IAAkB;IACnD,MAAM,EAAE,GAAG,4BAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,EAAE;QAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC;IAEnE,MAAM,KAAK,GAAG,sBAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,KAAK;QAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;IAEtE,MAAM,IAAI,GAAG,oBAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IAEnE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAgB,wBAAwB,CACtC,OAAkC,EAClC,GAAY;IAEZ,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,KAAK,UAAU;QACrB,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ;QAC3B,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,UAAU,CAClC,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,GAAY;IAC1B,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAa,OAAO;IAApB;QACU,SAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAW3C,CAAC;IATC;;OAEG;IACH,eAAe,CAAC,GAAY;QAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAZD,0BAYC;AAED;;;GAGG;AACH,SAAgB,oBAAoB;IAClC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,OAAO,EAAiB,EAAE;QACtC,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAoB,CAAC,CAAC;QACrD,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC1D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACxF,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Legacy compatibility re-export for Fastify replay instrumentation.
3
+ */
4
+ export { softprobeFastifyReplayPreHandler } from '../instrumentations/fastify/replay';
5
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/replay/fastify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.softprobeFastifyReplayPreHandler = void 0;
4
+ /**
5
+ * Legacy compatibility re-export for Fastify replay instrumentation.
6
+ */
7
+ var replay_1 = require("../instrumentations/fastify/replay");
8
+ Object.defineProperty(exports, "softprobeFastifyReplayPreHandler", { enumerable: true, get: function () { return replay_1.softprobeFastifyReplayPreHandler; } });
9
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/replay/fastify.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,6DAAsF;AAA7E,0HAAA,gCAAgC,OAAA"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Legacy compatibility re-export for HTTP/fetch replay instrumentation.
3
+ */
4
+ export { handleHttpReplayRequest, setupHttpReplayInterceptor } from '../instrumentations/fetch/replay';
5
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/replay/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupHttpReplayInterceptor = exports.handleHttpReplayRequest = void 0;
4
+ /**
5
+ * Legacy compatibility re-export for HTTP/fetch replay instrumentation.
6
+ */
7
+ var replay_1 = require("../instrumentations/fetch/replay");
8
+ Object.defineProperty(exports, "handleHttpReplayRequest", { enumerable: true, get: function () { return replay_1.handleHttpReplayRequest; } });
9
+ Object.defineProperty(exports, "setupHttpReplayInterceptor", { enumerable: true, get: function () { return replay_1.setupHttpReplayInterceptor; } });
10
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/replay/http.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,2DAAuG;AAA9F,iHAAA,uBAAuB,OAAA;AAAE,oHAAA,0BAA0B,OAAA"}
@@ -0,0 +1,25 @@
1
+ import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
2
+ import type { MatchRequest, CustomMatcherFn } from '../types/schema';
3
+ export declare class SemanticMatcher {
4
+ private readonly recordedSpans;
5
+ /** Tracks call count per (protocol, identifier, liveParentName) for sequential N+1 resolution. */
6
+ private readonly callSequenceMap;
7
+ /** User-registered matchers evaluated before the default tree-matching algorithm. */
8
+ private readonly customMatchers;
9
+ constructor(recordedSpans: ReadableSpan[]);
10
+ /**
11
+ * Registers a custom matcher. Custom matchers are run before the default tree-matching logic.
12
+ * - MOCK: return the given payload (no tree matching, no network).
13
+ * - CONTINUE: fall through to tree matching; the call is still replayed from the recording.
14
+ * - PASSTHROUGH: request live network for this call; in strict mode throws (not allowed).
15
+ */
16
+ addMatcher(fn: CustomMatcherFn): void;
17
+ /**
18
+ * Finds a recorded span that matches the live request by protocol and identifier,
19
+ * and optionally by lineage: the recorded span's parent name matches the current
20
+ * active OpenTelemetry span's name (semantic tree matching).
21
+ * Custom matchers are evaluated first; if any returns MOCK, that payload is returned; if any returns PASSTHROUGH, throws.
22
+ */
23
+ findMatch(request: MatchRequest): unknown;
24
+ }
25
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/replay/matcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAQrE,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAC/C,kGAAkG;IAClG,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAC7D,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;gBAE5C,aAAa,EAAE,YAAY,EAAE;IAIzC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI;IAIrC;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;CA0D1C"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SemanticMatcher = void 0;
4
+ const api_1 = require("@opentelemetry/api");
5
+ const RESPONSE_BODY_KEY = 'softprobe.response.body';
6
+ const PROTOCOL_KEY = 'softprobe.protocol';
7
+ const IDENTIFIER_KEY = 'softprobe.identifier';
8
+ // This is obsolete, we should use the new matcher instead
9
+ // Deprecated: use SoftprobeMatcher instead
10
+ class SemanticMatcher {
11
+ constructor(recordedSpans) {
12
+ /** Tracks call count per (protocol, identifier, liveParentName) for sequential N+1 resolution. */
13
+ this.callSequenceMap = new Map();
14
+ /** User-registered matchers evaluated before the default tree-matching algorithm. */
15
+ this.customMatchers = [];
16
+ this.recordedSpans = recordedSpans;
17
+ }
18
+ /**
19
+ * Registers a custom matcher. Custom matchers are run before the default tree-matching logic.
20
+ * - MOCK: return the given payload (no tree matching, no network).
21
+ * - CONTINUE: fall through to tree matching; the call is still replayed from the recording.
22
+ * - PASSTHROUGH: request live network for this call; in strict mode throws (not allowed).
23
+ */
24
+ addMatcher(fn) {
25
+ this.customMatchers.push(fn);
26
+ }
27
+ /**
28
+ * Finds a recorded span that matches the live request by protocol and identifier,
29
+ * and optionally by lineage: the recorded span's parent name matches the current
30
+ * active OpenTelemetry span's name (semantic tree matching).
31
+ * Custom matchers are evaluated first; if any returns MOCK, that payload is returned; if any returns PASSTHROUGH, throws.
32
+ */
33
+ findMatch(request) {
34
+ for (const matcher of this.customMatchers) {
35
+ const result = matcher(request, this.recordedSpans);
36
+ if (result.action === 'MOCK')
37
+ return result.payload;
38
+ if (result.action === 'PASSTHROUGH') {
39
+ throw new Error('[Softprobe] Network Passthrough not allowed in strict mode');
40
+ }
41
+ }
42
+ const candidates = this.recordedSpans.filter((span) => span.attributes[PROTOCOL_KEY] === request.protocol &&
43
+ span.attributes[IDENTIFIER_KEY] === request.identifier);
44
+ if (candidates.length === 0) {
45
+ throw new Error(`[Softprobe] No recorded traces found for ${request.protocol}: ${request.identifier}`);
46
+ }
47
+ const liveSpan = api_1.trace.getActiveSpan();
48
+ const liveParentName = liveSpan && typeof liveSpan.name === 'string'
49
+ ? liveSpan.name
50
+ : 'root';
51
+ const lineageMatches = candidates.filter((candidate) => {
52
+ const parentSpanId = candidate.parentSpanId;
53
+ if (parentSpanId == null)
54
+ return liveParentName === 'root';
55
+ const candidateParent = this.recordedSpans.find((s) => s.spanContext().spanId === parentSpanId);
56
+ return candidateParent != null && candidateParent.name === liveParentName;
57
+ });
58
+ let matched;
59
+ if (lineageMatches.length > 0) {
60
+ const sequenceKey = `${request.protocol}-${request.identifier}-${liveParentName}`;
61
+ const currentCount = this.callSequenceMap.get(sequenceKey) ?? 0;
62
+ // Wrap-around: if call count exceeds number of lineage matches, reuse the first match
63
+ matched = lineageMatches[currentCount] ?? lineageMatches[0];
64
+ this.callSequenceMap.set(sequenceKey, currentCount + 1);
65
+ }
66
+ else {
67
+ // Flat match: no lineage context, so we do not update callSequenceMap; always return first candidate.
68
+ matched = candidates[0];
69
+ }
70
+ const raw = matched.attributes[RESPONSE_BODY_KEY];
71
+ if (typeof raw !== 'string') {
72
+ throw new Error('[Softprobe] Missing or invalid softprobe.response.body on matched span');
73
+ }
74
+ try {
75
+ return JSON.parse(raw);
76
+ }
77
+ catch {
78
+ throw new Error('[Softprobe] Invalid or non-JSON softprobe.response.body on matched span');
79
+ }
80
+ }
81
+ }
82
+ exports.SemanticMatcher = SemanticMatcher;
83
+ //# sourceMappingURL=matcher.js.map