@reproapp/node-sdk 0.0.30 → 0.0.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reproapp/node-sdk",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "description": "Repro Nest SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,7 +12,7 @@
12
12
  "build": "tsc -p tsconfig.json",
13
13
  "dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
14
14
  "prepublishOnly": "npm run build",
15
- "test": "npm run build && node test/unawaited.test.js && node test/integration-unawaited.js && node test/request-flush-timing.test.js && node test/request-capture-background.test.js && node test/init-auto-http-server.test.js && node test/client-performance-regression.test.js && node test/request-manifest-priority.test.js && node test/runtime-no-double-invoke.test.js && node test/express-trace-http-args.test.js && node test/trace-batch-size.test.js && node test/sdk-background-priority.test.js && node test/ingest-queue-retention.test.js && node test/ingest-high-priority-retention.test.js && node test/ingest-critical-retention.test.js && node test/ingest-critical-retry-retention.test.js && node test/ingest-timeout.test.js && node -r ./tracer/register test/promise-map.test.js && node test/disable-subtree.test.js && node test/circular-capture.test.js && node test/wrap-plugin-arrow-args.test.js && node test/wrap-plugin-super-call.test.js && node test/function-arg-identity.test.js && node test/privacy-runtime-policy.test.js && node test/runtime-privacy-materialization.test.js && node test/kafka-runtime-privacy-policy.test.js && node test/amqplib-integration.test.js && node test/mongodb-integration.test.js",
15
+ "test": "npm run build && node test/unawaited.test.js && node test/integration-unawaited.js && node test/request-flush-timing.test.js && node test/request-capture-background.test.js && node test/init-auto-http-server.test.js && node test/client-performance-regression.test.js && node test/request-manifest-priority.test.js && node test/runtime-no-double-invoke.test.js && node test/express-trace-http-args.test.js && node test/trace-batch-size.test.js && node test/sdk-background-priority.test.js && node test/ingest-queue-retention.test.js && node test/ingest-high-priority-retention.test.js && node test/ingest-critical-retention.test.js && node test/ingest-critical-retry-retention.test.js && node test/ingest-timeout.test.js && node -r ./tracer/register test/promise-map.test.js && node test/disable-subtree.test.js && node test/circular-capture.test.js && node test/wrap-plugin-arrow-args.test.js && node test/wrap-plugin-super-call.test.js && node test/function-arg-identity.test.js && node test/privacy-runtime-policy.test.js && node test/runtime-privacy-materialization.test.js && node test/kafka-runtime-privacy-policy.test.js && node test/amqplib-integration.test.js && node test/mongodb-integration.test.js && node test/mongodb-esm-import-hook.test.js && node test/mongodb-suppression-cleanup.test.js",
16
16
  "test:containers": "npm run build && node test/runtime-no-double-invoke.testcontainers.test.js && node test/wrap-plugin-super-call.testcontainers.test.js && node test/function-arg-identity.testcontainers.test.js"
17
17
  },
18
18
  "peerDependencies": {
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import { AsyncLocalStorage } from 'async_hooks';
5
5
  import { randomUUID } from 'crypto';
6
6
  import { createRequire } from 'module';
7
7
  import { join } from 'path';
8
+ import { pathToFileURL } from 'url';
8
9
  import {
9
10
  configureIngestQueueDrain,
10
11
  enqueueIngestEntries,
@@ -1162,6 +1163,7 @@ type NativeMongoSuppression = {
1162
1163
  collection?: string | null;
1163
1164
  ops?: Set<string>;
1164
1165
  startedAt: number;
1166
+ ownerStore?: Ctx;
1165
1167
  };
1166
1168
 
1167
1169
  type RequestCaptureScopeState = {
@@ -1235,6 +1237,7 @@ function pushNativeMongoSuppression(collection: any, ops?: string[] | readonly s
1235
1237
  collection: collection == null ? null : String(collection),
1236
1238
  ops: normalizedOps.length ? new Set(normalizedOps) : undefined,
1237
1239
  startedAt: Date.now(),
1240
+ ownerStore: store,
1238
1241
  };
1239
1242
  if (!Array.isArray(store.nativeMongoSuppressions)) {
1240
1243
  store.nativeMongoSuppressions = [];
@@ -1245,12 +1248,22 @@ function pushNativeMongoSuppression(collection: any, ops?: string[] | readonly s
1245
1248
 
1246
1249
  function popNativeMongoSuppression(token: NativeMongoSuppression | null | undefined): void {
1247
1250
  if (!token) return;
1248
- const store = als.getStore();
1251
+ const store = token.ownerStore ?? als.getStore();
1249
1252
  const suppressions = store?.nativeMongoSuppressions;
1250
- if (!Array.isArray(suppressions) || suppressions.length === 0) return;
1251
- const index = suppressions.indexOf(token);
1252
- if (index >= 0) {
1253
- suppressions.splice(index, 1);
1253
+ if (Array.isArray(suppressions) && suppressions.length > 0) {
1254
+ const index = suppressions.indexOf(token);
1255
+ if (index >= 0) {
1256
+ suppressions.splice(index, 1);
1257
+ }
1258
+ }
1259
+ token.ownerStore = undefined;
1260
+ }
1261
+
1262
+ function releaseNativeMongoSuppression(target: any): void {
1263
+ const token = target?.__repro_native_mongo_suppression;
1264
+ popNativeMongoSuppression(token);
1265
+ try { delete target.__repro_native_mongo_suppression; } catch {
1266
+ try { target.__repro_native_mongo_suppression = undefined; } catch {}
1254
1267
  }
1255
1268
  }
1256
1269
 
@@ -1260,8 +1273,12 @@ function isNativeMongoSuppressed(collection: any, op: string): boolean {
1260
1273
  const normalizedCollection = collection == null ? null : String(collection);
1261
1274
  const normalizedOp = normalizeNativeMongoSuppressionOp(op);
1262
1275
  const now = Date.now();
1263
- for (const token of suppressions) {
1264
- if (!token || now - token.startedAt > 60000) continue;
1276
+ for (let i = suppressions.length - 1; i >= 0; i -= 1) {
1277
+ const token = suppressions[i];
1278
+ if (!token || now - token.startedAt > 60000) {
1279
+ suppressions.splice(i, 1);
1280
+ continue;
1281
+ }
1265
1282
  if (token.collection && normalizedCollection && token.collection !== normalizedCollection) continue;
1266
1283
  if (token.ops && token.ops.size > 0 && !token.ops.has(normalizedOp)) continue;
1267
1284
  return true;
@@ -5571,41 +5588,44 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5571
5588
  });
5572
5589
 
5573
5590
  schema.post('save', { document: true }, function () {
5574
- const { sid, aid } = getCtx();
5575
- if (!sid || !aid) return;
5576
- if ((this as any).$isSubdocument) return;
5577
-
5578
- const meta = (this as any).__repro_meta || {};
5579
- const before = null;
5580
- const after = this;
5581
- const collection = meta.collection || resolveCollectionOrWarn(this, 'doc');
5582
- const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5583
- if (!shouldCaptureDbSpan(spanContext)) return;
5584
- const modifiedPaths = Array.isArray(meta.modifiedPaths) ? meta.modifiedPaths : [];
5585
-
5586
- const query = meta.wasNew
5587
- ? { op: 'insertOne', doc: after }
5588
- : {
5589
- filter: { _id: this._id },
5590
- update: buildModifiedPathUpdate(this, modifiedPaths),
5591
- options: { upsert: false },
5592
- };
5591
+ try {
5592
+ const { sid, aid } = getCtx();
5593
+ if (!sid || !aid) return;
5594
+ if ((this as any).$isSubdocument) return;
5593
5595
 
5594
- emitDbQuery(cfg, sid, aid ?? undefined, {
5595
- collection,
5596
- pk: { _id: (this as any)._id },
5597
- before,
5598
- after,
5599
- op: meta.wasNew ? 'insert' : 'update',
5600
- query,
5601
- t: alignTimestamp(meta.t0 ?? Date.now()),
5602
- spanContext,
5603
- });
5604
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5596
+ const meta = (this as any).__repro_meta || {};
5597
+ const before = null;
5598
+ const after = this;
5599
+ const collection = meta.collection || resolveCollectionOrWarn(this, 'doc');
5600
+ const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5601
+ if (!shouldCaptureDbSpan(spanContext)) return;
5602
+ const modifiedPaths = Array.isArray(meta.modifiedPaths) ? meta.modifiedPaths : [];
5603
+
5604
+ const query = meta.wasNew
5605
+ ? { op: 'insertOne', doc: after }
5606
+ : {
5607
+ filter: { _id: this._id },
5608
+ update: buildModifiedPathUpdate(this, modifiedPaths),
5609
+ options: { upsert: false },
5610
+ };
5611
+
5612
+ emitDbQuery(cfg, sid, aid ?? undefined, {
5613
+ collection,
5614
+ pk: { _id: (this as any)._id },
5615
+ before,
5616
+ after,
5617
+ op: meta.wasNew ? 'insert' : 'update',
5618
+ query,
5619
+ t: alignTimestamp(meta.t0 ?? Date.now()),
5620
+ spanContext,
5621
+ });
5622
+ } finally {
5623
+ releaseNativeMongoSuppression(this);
5624
+ }
5605
5625
  });
5606
5626
 
5607
5627
  schema.post('save', { document: true }, function (error: any, _doc: any, next: Function) {
5608
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5628
+ releaseNativeMongoSuppression(this);
5609
5629
  next(error);
5610
5630
  });
5611
5631
 
@@ -5630,35 +5650,38 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5630
5650
  });
5631
5651
 
5632
5652
  schema.post<Query<any, any>>('findOneAndUpdate', function (res: any) {
5633
- const { sid, aid } = getCtx();
5634
- if (!sid || !aid) return;
5653
+ try {
5654
+ const { sid, aid } = getCtx();
5655
+ if (!sid || !aid) return;
5635
5656
 
5636
- const before = null;
5637
- const after = res ?? null;
5638
- const collection = (this as any).__repro_collection || resolveCollectionOrWarn(this, 'query');
5639
- const spanContext = (this as any).__repro_spanContext || captureSpanContextFromTracer(this);
5640
- if (!shouldCaptureDbSpan(spanContext)) return;
5641
- const filter = (this as any).__repro_filter;
5642
- const pk = after?._id ?? (filter && typeof filter === 'object' ? (filter as any)._id : undefined);
5657
+ const before = null;
5658
+ const after = res ?? null;
5659
+ const collection = (this as any).__repro_collection || resolveCollectionOrWarn(this, 'query');
5660
+ const spanContext = (this as any).__repro_spanContext || captureSpanContextFromTracer(this);
5661
+ if (!shouldCaptureDbSpan(spanContext)) return;
5662
+ const filter = (this as any).__repro_filter;
5663
+ const pk = after?._id ?? (filter && typeof filter === 'object' ? (filter as any)._id : undefined);
5643
5664
 
5644
- emitDbQuery(cfg, sid, aid ?? undefined, {
5645
- collection,
5646
- pk: { _id: pk },
5647
- before,
5648
- after,
5649
- op: 'update',
5650
- queryRaw: {
5651
- filter,
5652
- update: (this as any).__repro_update,
5653
- },
5654
- t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
5655
- spanContext,
5656
- });
5657
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5665
+ emitDbQuery(cfg, sid, aid ?? undefined, {
5666
+ collection,
5667
+ pk: { _id: pk },
5668
+ before,
5669
+ after,
5670
+ op: 'update',
5671
+ queryRaw: {
5672
+ filter,
5673
+ update: (this as any).__repro_update,
5674
+ },
5675
+ t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
5676
+ spanContext,
5677
+ });
5678
+ } finally {
5679
+ releaseNativeMongoSuppression(this);
5680
+ }
5658
5681
  });
5659
5682
 
5660
5683
  schema.post<Query<any, any>>('findOneAndUpdate', function (this: any, error: any, _res: any, next: Function) {
5661
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5684
+ releaseNativeMongoSuppression(this);
5662
5685
  next(error);
5663
5686
  } as any);
5664
5687
 
@@ -5680,27 +5703,30 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5680
5703
  });
5681
5704
 
5682
5705
  schema.post<Query<any, any>>('deleteOne', { document: false, query: true }, function () {
5683
- const { sid, aid } = getCtx(); if (!sid || !aid) return;
5684
- const before = null;
5685
- const collection = (this as any).__repro_collection || resolveCollectionOrWarn(this, 'query');
5686
- const filter = (this as any).__repro_filter ?? undefined;
5687
- const spanContext = (this as any).__repro_spanContext || captureSpanContextFromTracer(this);
5688
- if (!shouldCaptureDbSpan(spanContext)) return;
5689
- emitDbQuery(cfg, sid, aid ?? undefined, {
5690
- collection,
5691
- pk: filter && typeof filter === 'object' && '_id' in filter ? { _id: (filter as any)._id } : undefined,
5692
- before,
5693
- after: null,
5694
- op: 'delete',
5695
- queryRaw: { filter },
5696
- t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
5697
- spanContext,
5698
- });
5699
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5706
+ try {
5707
+ const { sid, aid } = getCtx(); if (!sid || !aid) return;
5708
+ const before = null;
5709
+ const collection = (this as any).__repro_collection || resolveCollectionOrWarn(this, 'query');
5710
+ const filter = (this as any).__repro_filter ?? undefined;
5711
+ const spanContext = (this as any).__repro_spanContext || captureSpanContextFromTracer(this);
5712
+ if (!shouldCaptureDbSpan(spanContext)) return;
5713
+ emitDbQuery(cfg, sid, aid ?? undefined, {
5714
+ collection,
5715
+ pk: filter && typeof filter === 'object' && '_id' in filter ? { _id: (filter as any)._id } : undefined,
5716
+ before,
5717
+ after: null,
5718
+ op: 'delete',
5719
+ queryRaw: { filter },
5720
+ t: alignTimestamp((this as any).__repro_t0 ?? Date.now()),
5721
+ spanContext,
5722
+ });
5723
+ } finally {
5724
+ releaseNativeMongoSuppression(this);
5725
+ }
5700
5726
  });
5701
5727
 
5702
5728
  schema.post<Query<any, any>>('deleteOne', { document: false, query: true }, function (this: any, error: any, _res: any, next: Function) {
5703
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5729
+ releaseNativeMongoSuppression(this);
5704
5730
  next(error);
5705
5731
  } as any);
5706
5732
 
@@ -5765,31 +5791,34 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5765
5791
  });
5766
5792
 
5767
5793
  schema.post(op as any, function (this: any, res: any) {
5768
- const { sid, aid } = getCtx();
5769
- if (!sid) return;
5794
+ try {
5795
+ const { sid, aid } = getCtx();
5796
+ if (!sid) return;
5770
5797
 
5771
- const meta = (this as any).__repro_qmeta || { t0: Date.now(), collection: 'unknown', op };
5772
- const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5798
+ const meta = (this as any).__repro_qmeta || { t0: Date.now(), collection: 'unknown', op };
5799
+ const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5773
5800
 
5774
- emitDbQuery(cfg, sid, aid, {
5775
- collection: meta.collection,
5776
- op,
5777
- queryRaw: {
5778
- filter: meta.rawFilter,
5779
- update: meta.rawUpdate,
5780
- projection: meta.rawProjection,
5781
- options: meta.rawOptions,
5782
- },
5783
- resultMetaRaw: res,
5784
- durMs: Date.now() - meta.t0,
5785
- t: alignedNow(),
5786
- spanContext,
5787
- });
5788
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5801
+ emitDbQuery(cfg, sid, aid, {
5802
+ collection: meta.collection,
5803
+ op,
5804
+ queryRaw: {
5805
+ filter: meta.rawFilter,
5806
+ update: meta.rawUpdate,
5807
+ projection: meta.rawProjection,
5808
+ options: meta.rawOptions,
5809
+ },
5810
+ resultMetaRaw: res,
5811
+ durMs: Date.now() - meta.t0,
5812
+ t: alignedNow(),
5813
+ spanContext,
5814
+ });
5815
+ } finally {
5816
+ releaseNativeMongoSuppression(this);
5817
+ }
5789
5818
  });
5790
5819
 
5791
5820
  schema.post(op as any, function (this: any, error: any, _res: any, next: Function) {
5792
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5821
+ releaseNativeMongoSuppression(this);
5793
5822
  next(error);
5794
5823
  } as any);
5795
5824
  }
@@ -5823,25 +5852,28 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5823
5852
  } as any);
5824
5853
 
5825
5854
  schema.post<any>('insertMany' as any, { document: false, query: false } as any, function (this: any, docs: any[]) {
5826
- const { sid, aid } = getCtx();
5827
- if (!sid) return;
5828
- const meta = (this as any).__repro_insert_meta || { t0: Date.now(), collection: 'unknown' };
5829
- const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5830
-
5831
- emitDbQuery(cfg, sid, aid ?? undefined, {
5832
- collection: meta.collection,
5833
- op: 'insertMany',
5834
- queryRaw: { docs: meta.rawDocs ?? undefined },
5835
- resultMetaRaw: docs,
5836
- durMs: Date.now() - meta.t0,
5837
- t: alignedNow(),
5838
- spanContext,
5839
- });
5840
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5855
+ try {
5856
+ const { sid, aid } = getCtx();
5857
+ if (!sid) return;
5858
+ const meta = (this as any).__repro_insert_meta || { t0: Date.now(), collection: 'unknown' };
5859
+ const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5860
+
5861
+ emitDbQuery(cfg, sid, aid ?? undefined, {
5862
+ collection: meta.collection,
5863
+ op: 'insertMany',
5864
+ queryRaw: { docs: meta.rawDocs ?? undefined },
5865
+ resultMetaRaw: docs,
5866
+ durMs: Date.now() - meta.t0,
5867
+ t: alignedNow(),
5868
+ spanContext,
5869
+ });
5870
+ } finally {
5871
+ releaseNativeMongoSuppression(this);
5872
+ }
5841
5873
  } as any);
5842
5874
 
5843
5875
  schema.post<any>('insertMany' as any, { document: false, query: false } as any, function (this: any, error: any, _res: any, next: Function) {
5844
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5876
+ releaseNativeMongoSuppression(this);
5845
5877
  next(error);
5846
5878
  } as any);
5847
5879
 
@@ -5870,25 +5902,28 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5870
5902
  } as any);
5871
5903
 
5872
5904
  schema.post<any>('bulkWrite' as any, { document: false, query: false } as any, function (this: any, res: any) {
5873
- const { sid, aid } = getCtx();
5874
- if (!sid) return;
5875
- const meta = (this as any).__repro_bulk_meta || { t0: Date.now(), collection: 'unknown' };
5876
- const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5877
-
5878
- emitDbQuery(cfg, sid, aid, {
5879
- collection: meta.collection,
5880
- op: 'bulkWrite',
5881
- queryRaw: { ops: meta.rawOps ?? undefined },
5882
- resultMetaRaw: res,
5883
- durMs: Date.now() - meta.t0,
5884
- t: alignedNow(),
5885
- spanContext,
5886
- });
5887
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5905
+ try {
5906
+ const { sid, aid } = getCtx();
5907
+ if (!sid) return;
5908
+ const meta = (this as any).__repro_bulk_meta || { t0: Date.now(), collection: 'unknown' };
5909
+ const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5910
+
5911
+ emitDbQuery(cfg, sid, aid, {
5912
+ collection: meta.collection,
5913
+ op: 'bulkWrite',
5914
+ queryRaw: { ops: meta.rawOps ?? undefined },
5915
+ resultMetaRaw: res,
5916
+ durMs: Date.now() - meta.t0,
5917
+ t: alignedNow(),
5918
+ spanContext,
5919
+ });
5920
+ } finally {
5921
+ releaseNativeMongoSuppression(this);
5922
+ }
5888
5923
  } as any);
5889
5924
 
5890
5925
  schema.post<any>('bulkWrite' as any, { document: false, query: false } as any, function (this: any, error: any, _res: any, next: Function) {
5891
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5926
+ releaseNativeMongoSuppression(this);
5892
5927
  next(error);
5893
5928
  } as any);
5894
5929
 
@@ -5923,26 +5958,29 @@ export function reproMongoosePlugin(cfg: ReproMiddlewareConfig) {
5923
5958
  });
5924
5959
 
5925
5960
  schema.post('aggregate', function (this: any, res: any[]) {
5926
- const { sid, aid } = getCtx();
5927
- if (!sid) return;
5961
+ try {
5962
+ const { sid, aid } = getCtx();
5963
+ if (!sid) return;
5928
5964
 
5929
- const meta = (this as any).__repro_aggmeta || { t0: Date.now(), collection: 'unknown' };
5930
- const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5965
+ const meta = (this as any).__repro_aggmeta || { t0: Date.now(), collection: 'unknown' };
5966
+ const spanContext = meta.spanContext || captureSpanContextFromTracer(this);
5931
5967
 
5932
- emitDbQuery(cfg, sid, aid, {
5933
- collection: meta.collection,
5934
- op: 'aggregate',
5935
- queryRaw: { pipeline: meta.rawPipeline },
5936
- resultMetaRaw: res,
5937
- durMs: Date.now() - meta.t0,
5938
- t: alignedNow(),
5939
- spanContext,
5940
- });
5941
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5968
+ emitDbQuery(cfg, sid, aid, {
5969
+ collection: meta.collection,
5970
+ op: 'aggregate',
5971
+ queryRaw: { pipeline: meta.rawPipeline },
5972
+ resultMetaRaw: res,
5973
+ durMs: Date.now() - meta.t0,
5974
+ t: alignedNow(),
5975
+ spanContext,
5976
+ });
5977
+ } finally {
5978
+ releaseNativeMongoSuppression(this);
5979
+ }
5942
5980
  });
5943
5981
 
5944
5982
  schema.post('aggregate', function (this: any, error: any, _res: any, next: Function) {
5945
- popNativeMongoSuppression((this as any).__repro_native_mongo_suppression);
5983
+ releaseNativeMongoSuppression(this);
5946
5984
  next(error);
5947
5985
  } as any);
5948
5986
  };
@@ -8810,6 +8848,8 @@ export type MongoDbPatchConfig = ReproMiddlewareConfig & {
8810
8848
 
8811
8849
  const mongoDbPatchConfigs: MongoDbPatchConfig[] = [];
8812
8850
  let mongoDbRequireHookInstalled = false;
8851
+ let mongoDbImportHookInstalled = false;
8852
+ let mongoDbImportHookReady: Promise<void> | null = null;
8813
8853
 
8814
8854
  const MONGODB_PROMISE_OPS = [
8815
8855
  'insertOne',
@@ -8832,6 +8872,12 @@ const MONGODB_PROMISE_OPS = [
8832
8872
  const MONGODB_CURSOR_OPS = ['find', 'aggregate'] as const;
8833
8873
  const MONGODB_CURSOR_TERMINALS = ['toArray', 'next', 'forEach'] as const;
8834
8874
 
8875
+ function registerMongoDbPatchConfig(cfg: MongoDbPatchConfig): void {
8876
+ if (!mongoDbPatchConfigs.includes(cfg)) {
8877
+ mongoDbPatchConfigs.push(cfg);
8878
+ }
8879
+ }
8880
+
8835
8881
  function resolveMongoDbRuntimeContext(cfg: MongoDbPatchConfig) {
8836
8882
  const ctx = getCtx();
8837
8883
  const fallback = cfg.resolveContext?.() ?? {};
@@ -8842,6 +8888,18 @@ function resolveMongoDbRuntimeContext(cfg: MongoDbPatchConfig) {
8842
8888
  };
8843
8889
  }
8844
8890
 
8891
+ function resolveMongoDbCaptureContext(): { cfg: MongoDbPatchConfig; sid: string; aid: string | null } | null {
8892
+ for (let i = mongoDbPatchConfigs.length - 1; i >= 0; i -= 1) {
8893
+ const cfg = mongoDbPatchConfigs[i];
8894
+ if (!cfg) continue;
8895
+ const { sid, aid } = resolveMongoDbRuntimeContext(cfg);
8896
+ if (sid) {
8897
+ return { cfg, sid, aid };
8898
+ }
8899
+ }
8900
+ return null;
8901
+ }
8902
+
8845
8903
  function resolveMongoCollectionName(collection: any): string {
8846
8904
  const candidates = [
8847
8905
  collection?.collectionName,
@@ -9142,10 +9200,11 @@ function patchMongoCollectionMethod(proto: any, op: string, cursorOp: boolean, c
9142
9200
  return original.apply(this, args);
9143
9201
  }
9144
9202
 
9145
- const { sid, aid } = resolveMongoDbRuntimeContext(cfg);
9146
- if (!sid) {
9203
+ const captureContext = resolveMongoDbCaptureContext();
9204
+ if (!captureContext) {
9147
9205
  return original.apply(this, args);
9148
9206
  }
9207
+ const { cfg: activeCfg, sid, aid } = captureContext;
9149
9208
 
9150
9209
  const spanContext = captureSpanContextFromTracer(this);
9151
9210
  const t0 = Date.now();
@@ -9157,7 +9216,7 @@ function patchMongoCollectionMethod(proto: any, op: string, cursorOp: boolean, c
9157
9216
  const emitSuccess = (result: any) => {
9158
9217
  if (emitted) return;
9159
9218
  emitted = true;
9160
- emitDbQuery(cfg, sid, aid ?? undefined, {
9219
+ emitDbQuery(activeCfg, sid, aid ?? undefined, {
9161
9220
  type: 'mongo',
9162
9221
  collection,
9163
9222
  op,
@@ -9174,7 +9233,7 @@ function patchMongoCollectionMethod(proto: any, op: string, cursorOp: boolean, c
9174
9233
  const emitFailure = (error: any) => {
9175
9234
  if (emitted) return;
9176
9235
  emitted = true;
9177
- emitDbQuery(cfg, sid, aid ?? undefined, {
9236
+ emitDbQuery(activeCfg, sid, aid ?? undefined, {
9178
9237
  type: 'mongo',
9179
9238
  collection,
9180
9239
  op,
@@ -9199,7 +9258,7 @@ function patchMongoCollectionMethod(proto: any, op: string, cursorOp: boolean, c
9199
9258
  const result = original.apply(this, actualArgs);
9200
9259
  if (cursorOp) {
9201
9260
  return patchMongoCursorInstance(result, {
9202
- cfg,
9261
+ cfg: activeCfg,
9203
9262
  sid,
9204
9263
  aid,
9205
9264
  collection,
@@ -9283,6 +9342,7 @@ function patchMongoClientPrototype(proto: any, cfg: MongoDbPatchConfig): void {
9283
9342
  }
9284
9343
 
9285
9344
  function patchMongoDbFromModuleExports(mongoModule: any, cfg: MongoDbPatchConfig): void {
9345
+ registerMongoDbPatchConfig(cfg);
9286
9346
  if (!mongoModule) return;
9287
9347
  const constructors = new Set<any>();
9288
9348
  const addCtor = (candidate: any) => {
@@ -9343,9 +9403,50 @@ function installMongoDbRequireHook(): void {
9343
9403
  } catch {}
9344
9404
  }
9345
9405
 
9406
+ function installMongoDbImportHook(): Promise<void> {
9407
+ if (mongoDbImportHookInstalled) return mongoDbImportHookReady ?? Promise.resolve();
9408
+ mongoDbImportHookInstalled = true;
9409
+
9410
+ mongoDbImportHookReady = (async () => {
9411
+ try {
9412
+ const nodeModule = requireOptionalHostModule('node:module') ?? requireOptionalHostModule('module');
9413
+ if (typeof nodeModule?.register !== 'function') return;
9414
+
9415
+ const iitm = requireOptionalHostModule('import-in-the-middle');
9416
+ const Hook = iitm?.Hook ?? iitm;
9417
+ if (typeof Hook !== 'function') return;
9418
+
9419
+ let waitForAllMessagesAcknowledged: undefined | (() => Promise<void>);
9420
+ let registerOptions: any = { data: { include: ['mongodb'] } };
9421
+ if (typeof iitm?.createAddHookMessageChannel === 'function') {
9422
+ const channel = iitm.createAddHookMessageChannel();
9423
+ registerOptions = channel.registerOptions;
9424
+ waitForAllMessagesAcknowledged = channel.waitForAllMessagesAcknowledged;
9425
+ }
9426
+
9427
+ nodeModule.register('import-in-the-middle/hook.mjs', pathToFileURL(__filename), registerOptions);
9428
+
9429
+ // eslint-disable-next-line no-new
9430
+ new Hook(['mongodb'], (exports: any) => {
9431
+ for (const cfg of mongoDbPatchConfigs) {
9432
+ patchMongoDbFromModuleExports(exports, cfg);
9433
+ }
9434
+ return exports;
9435
+ });
9436
+
9437
+ if (waitForAllMessagesAcknowledged) {
9438
+ await waitForAllMessagesAcknowledged();
9439
+ }
9440
+ } catch {}
9441
+ })();
9442
+
9443
+ return mongoDbImportHookReady;
9444
+ }
9445
+
9346
9446
  export function patchMongoDb(cfg: MongoDbPatchConfig): void {
9347
- mongoDbPatchConfigs.push(cfg);
9447
+ registerMongoDbPatchConfig(cfg);
9348
9448
  installMongoDbRequireHook();
9449
+ void installMongoDbImportHook();
9349
9450
 
9350
9451
  const mongoModules = new Set<any>();
9351
9452
  for (const loadedMongoModule of getLoadedModuleExportsByPackage('mongodb')) {
@@ -9867,6 +9968,7 @@ export async function initRepro(cfg: ReproInitConfig): Promise<void> {
9867
9968
  patchAmqplib(integrationCfg);
9868
9969
  patchRedis(integrationCfg);
9869
9970
  patchMongoDb(integrationCfg);
9971
+ await installMongoDbImportHook();
9870
9972
  patchSendgridMail(integrationCfg);
9871
9973
  patchMongooseIntegration(reproAutoMiddlewareConfig);
9872
9974
 
@@ -9901,6 +10003,16 @@ export const __reproTestHooks = {
9901
10003
  lastClientActivityAt = 0;
9902
10004
  sdkBackgroundQuietUntil = 0;
9903
10005
  },
10006
+ runWithRequestContextForTest<T>(ctx: Partial<Ctx>, fn: () => T): T {
10007
+ return als.run({
10008
+ ...ctx,
10009
+ excludedSpanIds: ctx.excludedSpanIds ?? new Set<string>(),
10010
+ }, fn);
10011
+ },
10012
+ getNativeMongoSuppressionCountForTest(): number {
10013
+ const suppressions = getCtx().nativeMongoSuppressions;
10014
+ return Array.isArray(suppressions) ? suppressions.length : 0;
10015
+ },
9904
10016
  getRuntimePrivacyPolicyForTest(cfg: ReproMiddlewareConfig): NormalizedRuntimePrivacyPolicy | null {
9905
10017
  return getRuntimePrivacyState(cfg).policy;
9906
10018
  },