@reproapp/node-sdk 0.0.26 → 0.0.27

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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.__reproTestHooks = exports.initRepro = exports.patchSendgridMail = exports.patchRedis = exports.patchAmqplib = exports.patchKafkaJs = exports.reproMongoosePlugin = exports.reproMiddleware = exports.__materializePendingTraceEventsForWorker = exports.isReproTracingEnabled = exports.initReproTracing = exports.disableReproTraceLogs = exports.enableReproTraceLogs = exports.setReproTraceLogsEnabled = exports.setDisabledTraceFiles = exports.setDisabledFunctionTypes = exports.setDisabledFunctionTraces = void 0;
3
+ exports.__reproTestHooks = exports.initRepro = exports.patchSendgridMail = exports.patchMongoDb = exports.patchRedis = exports.patchAmqplib = exports.patchKafkaJs = exports.reproMongoosePlugin = exports.reproMiddleware = exports.__materializePendingTraceEventsForWorker = exports.isReproTracingEnabled = exports.initReproTracing = exports.disableReproTraceLogs = exports.enableReproTraceLogs = exports.setReproTraceLogsEnabled = exports.setDisabledTraceFiles = exports.setDisabledFunctionTypes = exports.setDisabledFunctionTraces = void 0;
4
4
  const mongoose = require("mongoose");
5
5
  const async_hooks_1 = require("async_hooks");
6
6
  const crypto_1 = require("crypto");
@@ -819,6 +819,57 @@ function buildRequestCaptureManifestPayload(scope, traceBatchTotal, closedAtMs)
819
819
  }
820
820
  const als = new async_hooks_1.AsyncLocalStorage();
821
821
  const getCtx = () => als.getStore() || {};
822
+ function normalizeNativeMongoSuppressionOp(op) {
823
+ return String(op ?? '').trim();
824
+ }
825
+ function pushNativeMongoSuppression(collection, ops) {
826
+ const store = als.getStore();
827
+ if (!store)
828
+ return null;
829
+ const normalizedOps = Array.isArray(ops)
830
+ ? ops.map(normalizeNativeMongoSuppressionOp).filter(Boolean)
831
+ : [];
832
+ const token = {
833
+ collection: collection == null ? null : String(collection),
834
+ ops: normalizedOps.length ? new Set(normalizedOps) : undefined,
835
+ startedAt: Date.now(),
836
+ };
837
+ if (!Array.isArray(store.nativeMongoSuppressions)) {
838
+ store.nativeMongoSuppressions = [];
839
+ }
840
+ store.nativeMongoSuppressions.push(token);
841
+ return token;
842
+ }
843
+ function popNativeMongoSuppression(token) {
844
+ if (!token)
845
+ return;
846
+ const store = als.getStore();
847
+ const suppressions = store?.nativeMongoSuppressions;
848
+ if (!Array.isArray(suppressions) || suppressions.length === 0)
849
+ return;
850
+ const index = suppressions.indexOf(token);
851
+ if (index >= 0) {
852
+ suppressions.splice(index, 1);
853
+ }
854
+ }
855
+ function isNativeMongoSuppressed(collection, op) {
856
+ const suppressions = getCtx().nativeMongoSuppressions;
857
+ if (!Array.isArray(suppressions) || suppressions.length === 0)
858
+ return false;
859
+ const normalizedCollection = collection == null ? null : String(collection);
860
+ const normalizedOp = normalizeNativeMongoSuppressionOp(op);
861
+ const now = Date.now();
862
+ for (const token of suppressions) {
863
+ if (!token || now - token.startedAt > 60000)
864
+ continue;
865
+ if (token.collection && normalizedCollection && token.collection !== normalizedCollection)
866
+ continue;
867
+ if (token.ops && token.ops.size > 0 && !token.ops.has(normalizedOp))
868
+ continue;
869
+ return true;
870
+ }
871
+ return false;
872
+ }
822
873
  function currentClockSkewMs() {
823
874
  const store = als.getStore();
824
875
  const skew = store?.clockSkewMs;
@@ -4483,6 +4534,16 @@ exports.reproMiddleware = reproMiddleware;
4483
4534
  // - ONLY schema middleware (pre/post) for specific ops
4484
4535
  // - keeps your existing doc-diff hooks
4485
4536
  // ===================================================================
4537
+ function nativeMongoOpsForMongooseOp(op) {
4538
+ if (op === 'findByIdAndUpdate')
4539
+ return ['findOneAndUpdate'];
4540
+ if (op === 'findByIdAndDelete' || op === 'findByIdAndRemove' || op === 'findOneAndRemove') {
4541
+ return ['findOneAndDelete'];
4542
+ }
4543
+ if (op === 'findByIdAndReplace')
4544
+ return ['findOneAndReplace'];
4545
+ return [op];
4546
+ }
4486
4547
  function reproMongoosePlugin(cfg) {
4487
4548
  return function (schema) {
4488
4549
  // -------- pre/post save (unchanged) --------
@@ -4501,6 +4562,7 @@ function reproMongoosePlugin(cfg) {
4501
4562
  ? this.modifiedPaths()
4502
4563
  : [],
4503
4564
  };
4565
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_meta.collection, this.isNew ? ['insertOne'] : ['updateOne', 'replaceOne']);
4504
4566
  next();
4505
4567
  });
4506
4568
  schema.post('save', { document: true }, function () {
@@ -4534,6 +4596,11 @@ function reproMongoosePlugin(cfg) {
4534
4596
  t: alignTimestamp(meta.t0 ?? Date.now()),
4535
4597
  spanContext,
4536
4598
  });
4599
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4600
+ });
4601
+ schema.post('save', { document: true }, function (error, _doc, next) {
4602
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4603
+ next(error);
4537
4604
  });
4538
4605
  // -------- findOneAndUpdate capture (unchanged) --------
4539
4606
  schema.pre('findOneAndUpdate', function (next) {
@@ -4548,6 +4615,7 @@ function reproMongoosePlugin(cfg) {
4548
4615
  this.__repro_spanContext = captureSpanContextFromTracer(this);
4549
4616
  this.__repro_filter = filter;
4550
4617
  this.__repro_update = this.getUpdate?.() ?? this._update ?? undefined;
4618
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_collection, ['findOneAndUpdate']);
4551
4619
  }
4552
4620
  catch { }
4553
4621
  next();
@@ -4577,6 +4645,11 @@ function reproMongoosePlugin(cfg) {
4577
4645
  t: alignTimestamp(this.__repro_t0 ?? Date.now()),
4578
4646
  spanContext,
4579
4647
  });
4648
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4649
+ });
4650
+ schema.post('findOneAndUpdate', function (error, _res, next) {
4651
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4652
+ next(error);
4580
4653
  });
4581
4654
  // -------- deleteOne capture (unchanged) --------
4582
4655
  schema.pre('deleteOne', { document: false, query: true }, function (next) {
@@ -4589,6 +4662,7 @@ function reproMongoosePlugin(cfg) {
4589
4662
  this.__repro_collection = resolveCollectionOrWarn(this, 'query');
4590
4663
  this.__repro_filter = filter;
4591
4664
  this.__repro_spanContext = captureSpanContextFromTracer(this);
4665
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_collection, ['deleteOne']);
4592
4666
  }
4593
4667
  catch { }
4594
4668
  next();
@@ -4613,6 +4687,11 @@ function reproMongoosePlugin(cfg) {
4613
4687
  t: alignTimestamp(this.__repro_t0 ?? Date.now()),
4614
4688
  spanContext,
4615
4689
  });
4690
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4691
+ });
4692
+ schema.post('deleteOne', { document: false, query: true }, function (error, _res, next) {
4693
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4694
+ next(error);
4616
4695
  });
4617
4696
  // -------- NON-intrusive generic query telemetry via schema hooks -------
4618
4697
  const READ_OPS = [
@@ -4653,6 +4732,7 @@ function reproMongoosePlugin(cfg) {
4653
4732
  rawProjection,
4654
4733
  rawOptions,
4655
4734
  };
4735
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_qmeta.collection, nativeMongoOpsForMongooseOp(op));
4656
4736
  }
4657
4737
  catch {
4658
4738
  this.__repro_qmeta = {
@@ -4661,6 +4741,7 @@ function reproMongoosePlugin(cfg) {
4661
4741
  op,
4662
4742
  spanContext: captureSpanContextFromTracer(this),
4663
4743
  };
4744
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', nativeMongoOpsForMongooseOp(op));
4664
4745
  }
4665
4746
  next();
4666
4747
  });
@@ -4684,6 +4765,11 @@ function reproMongoosePlugin(cfg) {
4684
4765
  t: alignedNow(),
4685
4766
  spanContext,
4686
4767
  });
4768
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4769
+ });
4770
+ schema.post(op, function (error, _res, next) {
4771
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4772
+ next(error);
4687
4773
  });
4688
4774
  }
4689
4775
  READ_OPS.forEach(attachQueryHooks);
@@ -4698,6 +4784,7 @@ function reproMongoosePlugin(cfg) {
4698
4784
  rawDocs,
4699
4785
  spanContext: captureSpanContextFromTracer(this),
4700
4786
  };
4787
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_insert_meta.collection, ['insertMany']);
4701
4788
  }
4702
4789
  catch {
4703
4790
  this.__repro_insert_meta = {
@@ -4705,6 +4792,7 @@ function reproMongoosePlugin(cfg) {
4705
4792
  collection: 'unknown',
4706
4793
  spanContext: captureSpanContextFromTracer(this),
4707
4794
  };
4795
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', ['insertMany']);
4708
4796
  }
4709
4797
  next();
4710
4798
  });
@@ -4723,6 +4811,11 @@ function reproMongoosePlugin(cfg) {
4723
4811
  t: alignedNow(),
4724
4812
  spanContext,
4725
4813
  });
4814
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4815
+ });
4816
+ schema.post('insertMany', { document: false, query: false }, function (error, _res, next) {
4817
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4818
+ next(error);
4726
4819
  });
4727
4820
  schema.pre('bulkWrite', { document: false, query: false }, function (next, ops) {
4728
4821
  try {
@@ -4733,6 +4826,7 @@ function reproMongoosePlugin(cfg) {
4733
4826
  rawOps,
4734
4827
  spanContext: captureSpanContextFromTracer(this),
4735
4828
  };
4829
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_bulk_meta.collection, ['bulkWrite']);
4736
4830
  }
4737
4831
  catch {
4738
4832
  this.__repro_bulk_meta = {
@@ -4740,6 +4834,7 @@ function reproMongoosePlugin(cfg) {
4740
4834
  collection: 'unknown',
4741
4835
  spanContext: captureSpanContextFromTracer(this),
4742
4836
  };
4837
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', ['bulkWrite']);
4743
4838
  }
4744
4839
  next();
4745
4840
  });
@@ -4758,6 +4853,11 @@ function reproMongoosePlugin(cfg) {
4758
4853
  t: alignedNow(),
4759
4854
  spanContext,
4760
4855
  });
4856
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4857
+ });
4858
+ schema.post('bulkWrite', { document: false, query: false }, function (error, _res, next) {
4859
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4860
+ next(error);
4761
4861
  });
4762
4862
  // Aggregate middleware (non-intrusive)
4763
4863
  schema.pre('aggregate', function (next) {
@@ -4772,6 +4872,7 @@ function reproMongoosePlugin(cfg) {
4772
4872
  spanContext: captureSpanContextFromTracer(this),
4773
4873
  rawPipeline,
4774
4874
  };
4875
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression(this.__repro_aggmeta.collection, ['aggregate']);
4775
4876
  }
4776
4877
  catch {
4777
4878
  this.__repro_aggmeta = {
@@ -4780,6 +4881,7 @@ function reproMongoosePlugin(cfg) {
4780
4881
  pipeline: undefined,
4781
4882
  spanContext: captureSpanContextFromTracer(this),
4782
4883
  };
4884
+ this.__repro_native_mongo_suppression = pushNativeMongoSuppression('unknown', ['aggregate']);
4783
4885
  }
4784
4886
  next();
4785
4887
  });
@@ -4798,6 +4900,11 @@ function reproMongoosePlugin(cfg) {
4798
4900
  t: alignedNow(),
4799
4901
  spanContext,
4800
4902
  });
4903
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4904
+ });
4905
+ schema.post('aggregate', function (error, _res, next) {
4906
+ popNativeMongoSuppression(this.__repro_native_mongo_suppression);
4907
+ next(error);
4801
4908
  });
4802
4909
  };
4803
4910
  }
@@ -4823,10 +4930,24 @@ function summarizeQueryResult(op, res) {
4823
4930
  }
4824
4931
  return summary;
4825
4932
  }
4933
+ if (op === 'insertOne') {
4934
+ const summary = {
4935
+ insertedId: res?.insertedId ?? undefined,
4936
+ acknowledged: res?.acknowledged ?? undefined,
4937
+ };
4938
+ if (typeof resultPreview !== 'undefined')
4939
+ summary.result = resultPreview;
4940
+ return summary;
4941
+ }
4826
4942
  if (op === 'insertMany') {
4827
4943
  const summary = {};
4828
4944
  if (Array.isArray(res))
4829
4945
  summary.inserted = res.length;
4946
+ else {
4947
+ summary.inserted = res?.insertedCount ?? undefined;
4948
+ summary.insertedIds = res?.insertedIds ?? undefined;
4949
+ summary.acknowledged = res?.acknowledged ?? undefined;
4950
+ }
4830
4951
  if (typeof resultPreview !== 'undefined')
4831
4952
  summary.result = resultPreview;
4832
4953
  return summary;
@@ -7409,6 +7530,469 @@ function patchRedis(cfg) {
7409
7530
  }
7410
7531
  }
7411
7532
  exports.patchRedis = patchRedis;
7533
+ const mongoDbPatchConfigs = [];
7534
+ let mongoDbRequireHookInstalled = false;
7535
+ const MONGODB_PROMISE_OPS = [
7536
+ 'insertOne',
7537
+ 'insertMany',
7538
+ 'updateOne',
7539
+ 'updateMany',
7540
+ 'replaceOne',
7541
+ 'deleteOne',
7542
+ 'deleteMany',
7543
+ 'findOne',
7544
+ 'countDocuments',
7545
+ 'estimatedDocumentCount',
7546
+ 'distinct',
7547
+ 'bulkWrite',
7548
+ 'findOneAndUpdate',
7549
+ 'findOneAndDelete',
7550
+ 'findOneAndReplace',
7551
+ ];
7552
+ const MONGODB_CURSOR_OPS = ['find', 'aggregate'];
7553
+ const MONGODB_CURSOR_TERMINALS = ['toArray', 'next', 'forEach'];
7554
+ function resolveMongoDbRuntimeContext(cfg) {
7555
+ const ctx = getCtx();
7556
+ const fallback = cfg.resolveContext?.() ?? {};
7557
+ return {
7558
+ ctx,
7559
+ sid: ctx.sid ?? fallback.sid ?? null,
7560
+ aid: ctx.aid ?? fallback.aid ?? null,
7561
+ };
7562
+ }
7563
+ function resolveMongoCollectionName(collection) {
7564
+ const candidates = [
7565
+ collection?.collectionName,
7566
+ collection?.namespace?.collection,
7567
+ collection?.s?.namespace?.collection,
7568
+ collection?.s?.namespace?.collectionName,
7569
+ ];
7570
+ for (const candidate of candidates) {
7571
+ if (typeof candidate === 'string' && candidate.trim())
7572
+ return candidate;
7573
+ }
7574
+ const namespace = typeof collection?.namespace === 'string'
7575
+ ? collection.namespace
7576
+ : typeof collection?.s?.namespace === 'string'
7577
+ ? collection.s.namespace
7578
+ : typeof collection?.namespace?.toString === 'function'
7579
+ ? collection.namespace.toString()
7580
+ : typeof collection?.s?.namespace?.toString === 'function'
7581
+ ? collection.s.namespace.toString()
7582
+ : null;
7583
+ if (namespace && namespace.includes('.')) {
7584
+ return namespace.slice(namespace.indexOf('.') + 1) || namespace;
7585
+ }
7586
+ return namespace || 'unknown';
7587
+ }
7588
+ function resolveMongoDbName(collection) {
7589
+ const candidates = [
7590
+ collection?.dbName,
7591
+ collection?.db?.databaseName,
7592
+ collection?.s?.db?.databaseName,
7593
+ collection?.namespace?.db,
7594
+ collection?.s?.namespace?.db,
7595
+ ];
7596
+ for (const candidate of candidates) {
7597
+ if (typeof candidate === 'string' && candidate.trim())
7598
+ return candidate;
7599
+ }
7600
+ const namespace = typeof collection?.namespace === 'string'
7601
+ ? collection.namespace
7602
+ : typeof collection?.s?.namespace === 'string'
7603
+ ? collection.s.namespace
7604
+ : null;
7605
+ if (namespace && namespace.includes('.')) {
7606
+ return namespace.slice(0, namespace.indexOf('.')) || undefined;
7607
+ }
7608
+ return undefined;
7609
+ }
7610
+ function summarizeMongoSession(session) {
7611
+ if (!session || typeof session !== 'object')
7612
+ return session;
7613
+ let inTransaction = undefined;
7614
+ try {
7615
+ inTransaction = typeof session.inTransaction === 'function' ? session.inTransaction() : undefined;
7616
+ }
7617
+ catch { }
7618
+ return {
7619
+ __kind: 'mongodb_client_session',
7620
+ id: session.id ?? session.serverSession?.id ?? undefined,
7621
+ hasEnded: session.hasEnded ?? undefined,
7622
+ inTransaction,
7623
+ };
7624
+ }
7625
+ function normalizeMongoDriverOptions(options) {
7626
+ if (!options || typeof options !== 'object' || Array.isArray(options))
7627
+ return options;
7628
+ const normalized = {};
7629
+ for (const key of Object.keys(options)) {
7630
+ normalized[key] = key === 'session'
7631
+ ? summarizeMongoSession(options[key])
7632
+ : options[key];
7633
+ }
7634
+ return normalized;
7635
+ }
7636
+ function summarizeMongoError(error) {
7637
+ return {
7638
+ name: error?.name ?? undefined,
7639
+ message: error?.message ?? String(error),
7640
+ code: error?.code ?? undefined,
7641
+ codeName: error?.codeName ?? undefined,
7642
+ };
7643
+ }
7644
+ function extractMongoPkFromFilter(filter) {
7645
+ if (filter && typeof filter === 'object' && Object.prototype.hasOwnProperty.call(filter, '_id')) {
7646
+ return { _id: filter._id };
7647
+ }
7648
+ return undefined;
7649
+ }
7650
+ function extractMongoPkFromDoc(doc, result) {
7651
+ const id = doc && typeof doc === 'object' ? doc._id : undefined;
7652
+ const insertedId = result?.insertedId;
7653
+ if (id !== undefined)
7654
+ return { _id: id };
7655
+ if (insertedId !== undefined)
7656
+ return { _id: insertedId };
7657
+ return undefined;
7658
+ }
7659
+ function buildMongoQueryPayload(op, args, dbName) {
7660
+ const withDriver = (payload) => ({
7661
+ driver: 'mongodb',
7662
+ db: dbName,
7663
+ ...payload,
7664
+ });
7665
+ if (op === 'insertOne') {
7666
+ return withDriver({ doc: args[0], options: normalizeMongoDriverOptions(args[1]) });
7667
+ }
7668
+ if (op === 'insertMany') {
7669
+ return withDriver({ docs: args[0], options: normalizeMongoDriverOptions(args[1]) });
7670
+ }
7671
+ if (op === 'updateOne' || op === 'updateMany') {
7672
+ return withDriver({ filter: args[0], update: args[1], options: normalizeMongoDriverOptions(args[2]) });
7673
+ }
7674
+ if (op === 'replaceOne') {
7675
+ return withDriver({ filter: args[0], replacement: args[1], options: normalizeMongoDriverOptions(args[2]) });
7676
+ }
7677
+ if (op === 'deleteOne' || op === 'deleteMany') {
7678
+ return withDriver({ filter: args[0], options: normalizeMongoDriverOptions(args[1]) });
7679
+ }
7680
+ if (op === 'findOne' || op === 'find' || op === 'countDocuments') {
7681
+ return withDriver({ filter: args[0], options: normalizeMongoDriverOptions(args[1]) });
7682
+ }
7683
+ if (op === 'estimatedDocumentCount') {
7684
+ return withDriver({ options: normalizeMongoDriverOptions(args[0]) });
7685
+ }
7686
+ if (op === 'distinct') {
7687
+ return withDriver({ key: args[0], filter: args[1], options: normalizeMongoDriverOptions(args[2]) });
7688
+ }
7689
+ if (op === 'bulkWrite') {
7690
+ return withDriver({ ops: args[0], options: normalizeMongoDriverOptions(args[1]) });
7691
+ }
7692
+ if (op === 'findOneAndUpdate') {
7693
+ return withDriver({ filter: args[0], update: args[1], options: normalizeMongoDriverOptions(args[2]) });
7694
+ }
7695
+ if (op === 'findOneAndReplace') {
7696
+ return withDriver({ filter: args[0], replacement: args[1], options: normalizeMongoDriverOptions(args[2]) });
7697
+ }
7698
+ if (op === 'findOneAndDelete') {
7699
+ return withDriver({ filter: args[0], options: normalizeMongoDriverOptions(args[1]) });
7700
+ }
7701
+ if (op === 'aggregate') {
7702
+ return withDriver({ pipeline: args[0], options: normalizeMongoDriverOptions(args[1]) });
7703
+ }
7704
+ return withDriver({ args });
7705
+ }
7706
+ function buildMongoPk(op, args, result) {
7707
+ if (op === 'insertOne')
7708
+ return extractMongoPkFromDoc(args[0], result);
7709
+ if (op === 'updateOne' ||
7710
+ op === 'replaceOne' ||
7711
+ op === 'deleteOne' ||
7712
+ op === 'findOne' ||
7713
+ op === 'findOneAndUpdate' ||
7714
+ op === 'findOneAndDelete' ||
7715
+ op === 'findOneAndReplace') {
7716
+ return extractMongoPkFromFilter(args[0]);
7717
+ }
7718
+ return undefined;
7719
+ }
7720
+ function buildMongoAfter(op, args, result) {
7721
+ if (op === 'insertOne')
7722
+ return args[0] ?? null;
7723
+ if (op === 'insertMany')
7724
+ return args[0] ?? null;
7725
+ if (op === 'findOne' || op === 'findOneAndUpdate' || op === 'findOneAndDelete' || op === 'findOneAndReplace') {
7726
+ return result ?? null;
7727
+ }
7728
+ if (op === 'find' || op === 'aggregate') {
7729
+ return Array.isArray(result) ? result : null;
7730
+ }
7731
+ return null;
7732
+ }
7733
+ function findMongoCallbackIndex(args) {
7734
+ for (let i = args.length - 1; i >= 0; i -= 1) {
7735
+ if (typeof args[i] === 'function')
7736
+ return i;
7737
+ }
7738
+ return -1;
7739
+ }
7740
+ function patchMongoCursorInstance(cursor, meta) {
7741
+ if (!cursor || typeof cursor !== 'object')
7742
+ return cursor;
7743
+ if (cursor.__repro_mongodb_cursor_patched)
7744
+ return cursor;
7745
+ try {
7746
+ Object.defineProperty(cursor, '__repro_mongodb_cursor_patched', {
7747
+ value: true,
7748
+ configurable: true,
7749
+ });
7750
+ }
7751
+ catch {
7752
+ return cursor;
7753
+ }
7754
+ for (const methodName of MONGODB_CURSOR_TERMINALS) {
7755
+ const original = cursor[methodName];
7756
+ if (typeof original !== 'function')
7757
+ continue;
7758
+ cursor[methodName] = function reproPatchedMongoCursorTerminal(...callArgs) {
7759
+ const t0 = Date.now();
7760
+ let emitted = false;
7761
+ let forEachDocs = null;
7762
+ const emitSuccess = (value) => {
7763
+ if (emitted)
7764
+ return;
7765
+ emitted = true;
7766
+ const terminalQueryArgs = [...meta.args];
7767
+ const queryRaw = buildMongoQueryPayload(meta.op, terminalQueryArgs, meta.dbName);
7768
+ queryRaw.cursorMethod = methodName;
7769
+ emitDbQuery(meta.cfg, meta.sid, meta.aid ?? undefined, {
7770
+ type: 'mongo',
7771
+ collection: meta.collection,
7772
+ op: meta.op,
7773
+ pk: buildMongoPk(meta.op, meta.args, value),
7774
+ before: null,
7775
+ after: buildMongoAfter(meta.op, meta.args, forEachDocs ?? value),
7776
+ queryRaw,
7777
+ resultMetaRaw: forEachDocs ?? value,
7778
+ durMs: Date.now() - t0,
7779
+ t: alignedNow(),
7780
+ spanContext: meta.spanContext,
7781
+ });
7782
+ };
7783
+ const emitFailure = (error) => {
7784
+ if (emitted)
7785
+ return;
7786
+ emitted = true;
7787
+ const terminalQueryArgs = [...meta.args];
7788
+ const queryRaw = buildMongoQueryPayload(meta.op, terminalQueryArgs, meta.dbName);
7789
+ queryRaw.cursorMethod = methodName;
7790
+ emitDbQuery(meta.cfg, meta.sid, meta.aid ?? undefined, {
7791
+ type: 'mongo',
7792
+ collection: meta.collection,
7793
+ op: meta.op,
7794
+ queryRaw,
7795
+ error: summarizeMongoError(error),
7796
+ durMs: Date.now() - t0,
7797
+ t: alignedNow(),
7798
+ spanContext: meta.spanContext,
7799
+ });
7800
+ };
7801
+ const actualArgs = [...callArgs];
7802
+ if (methodName === 'forEach' && typeof actualArgs[0] === 'function') {
7803
+ forEachDocs = [];
7804
+ const originalIterator = actualArgs[0];
7805
+ actualArgs[0] = function reproMongoForEachIterator(doc, ...rest) {
7806
+ forEachDocs?.push(doc);
7807
+ return originalIterator.call(this, doc, ...rest);
7808
+ };
7809
+ }
7810
+ try {
7811
+ const value = original.apply(this, actualArgs);
7812
+ if (value && typeof value.then === 'function') {
7813
+ return value.then((resolved) => {
7814
+ emitSuccess(resolved);
7815
+ return resolved;
7816
+ }, (err) => {
7817
+ emitFailure(err);
7818
+ throw err;
7819
+ });
7820
+ }
7821
+ emitSuccess(value);
7822
+ return value;
7823
+ }
7824
+ catch (err) {
7825
+ emitFailure(err);
7826
+ throw err;
7827
+ }
7828
+ };
7829
+ }
7830
+ return cursor;
7831
+ }
7832
+ function patchMongoCollectionMethod(proto, op, cursorOp, cfg) {
7833
+ if (!proto)
7834
+ return;
7835
+ const marker = `__repro_mongodb_${op}_patched`;
7836
+ if (proto[marker])
7837
+ return;
7838
+ const original = proto[op];
7839
+ if (typeof original !== 'function')
7840
+ return;
7841
+ proto[marker] = true;
7842
+ proto[op] = function reproPatchedMongoCollectionMethod(...args) {
7843
+ const collection = resolveMongoCollectionName(this);
7844
+ if (isNativeMongoSuppressed(collection, op)) {
7845
+ return original.apply(this, args);
7846
+ }
7847
+ const { sid, aid } = resolveMongoDbRuntimeContext(cfg);
7848
+ if (!sid) {
7849
+ return original.apply(this, args);
7850
+ }
7851
+ const spanContext = captureSpanContextFromTracer(this);
7852
+ const t0 = Date.now();
7853
+ const dbName = resolveMongoDbName(this);
7854
+ const callbackIndex = cursorOp ? -1 : findMongoCallbackIndex(args);
7855
+ const actualArgs = callbackIndex >= 0 ? [...args] : args;
7856
+ let emitted = false;
7857
+ const emitSuccess = (result) => {
7858
+ if (emitted)
7859
+ return;
7860
+ emitted = true;
7861
+ emitDbQuery(cfg, sid, aid ?? undefined, {
7862
+ type: 'mongo',
7863
+ collection,
7864
+ op,
7865
+ pk: buildMongoPk(op, args, result),
7866
+ before: null,
7867
+ after: buildMongoAfter(op, args, result),
7868
+ queryRaw: buildMongoQueryPayload(op, args, dbName),
7869
+ resultMetaRaw: result,
7870
+ durMs: Date.now() - t0,
7871
+ t: alignedNow(),
7872
+ spanContext,
7873
+ });
7874
+ };
7875
+ const emitFailure = (error) => {
7876
+ if (emitted)
7877
+ return;
7878
+ emitted = true;
7879
+ emitDbQuery(cfg, sid, aid ?? undefined, {
7880
+ type: 'mongo',
7881
+ collection,
7882
+ op,
7883
+ queryRaw: buildMongoQueryPayload(op, args, dbName),
7884
+ error: summarizeMongoError(error),
7885
+ durMs: Date.now() - t0,
7886
+ t: alignedNow(),
7887
+ spanContext,
7888
+ });
7889
+ };
7890
+ if (callbackIndex >= 0) {
7891
+ const originalCallback = args[callbackIndex];
7892
+ actualArgs[callbackIndex] = function reproMongoCallback(err, result, ...rest) {
7893
+ if (err)
7894
+ emitFailure(err);
7895
+ else
7896
+ emitSuccess(result);
7897
+ return originalCallback.call(this, err, result, ...rest);
7898
+ };
7899
+ }
7900
+ try {
7901
+ const result = original.apply(this, actualArgs);
7902
+ if (cursorOp) {
7903
+ return patchMongoCursorInstance(result, {
7904
+ cfg,
7905
+ sid,
7906
+ aid,
7907
+ collection,
7908
+ dbName,
7909
+ op,
7910
+ args,
7911
+ spanContext,
7912
+ });
7913
+ }
7914
+ if (result && typeof result.then === 'function') {
7915
+ return result.then((value) => {
7916
+ emitSuccess(value);
7917
+ return value;
7918
+ }, (error) => {
7919
+ emitFailure(error);
7920
+ throw error;
7921
+ });
7922
+ }
7923
+ if (callbackIndex < 0) {
7924
+ emitSuccess(result);
7925
+ }
7926
+ return result;
7927
+ }
7928
+ catch (error) {
7929
+ emitFailure(error);
7930
+ throw error;
7931
+ }
7932
+ };
7933
+ }
7934
+ function patchMongoCollectionPrototype(proto, cfg) {
7935
+ if (!proto)
7936
+ return;
7937
+ for (const op of MONGODB_PROMISE_OPS) {
7938
+ patchMongoCollectionMethod(proto, op, false, cfg);
7939
+ }
7940
+ for (const op of MONGODB_CURSOR_OPS) {
7941
+ patchMongoCollectionMethod(proto, op, true, cfg);
7942
+ }
7943
+ }
7944
+ function patchMongoDbFromModuleExports(mongoModule, cfg) {
7945
+ if (!mongoModule)
7946
+ return;
7947
+ const constructors = new Set();
7948
+ const addCtor = (candidate) => {
7949
+ if (typeof candidate === 'function' && candidate.prototype) {
7950
+ constructors.add(candidate);
7951
+ }
7952
+ };
7953
+ addCtor(mongoModule?.Collection);
7954
+ addCtor(mongoModule?.default?.Collection);
7955
+ for (const ctor of constructors) {
7956
+ patchMongoCollectionPrototype(ctor.prototype, cfg);
7957
+ }
7958
+ }
7959
+ function installMongoDbRequireHook() {
7960
+ if (mongoDbRequireHookInstalled)
7961
+ return;
7962
+ mongoDbRequireHookInstalled = true;
7963
+ try {
7964
+ const rim = requireOptionalHostModule('require-in-the-middle');
7965
+ const Hook = rim?.Hook ?? rim;
7966
+ if (typeof Hook !== 'function')
7967
+ return;
7968
+ // eslint-disable-next-line no-new
7969
+ new Hook(['mongodb'], (exports) => {
7970
+ for (const cfg of mongoDbPatchConfigs) {
7971
+ patchMongoDbFromModuleExports(exports, cfg);
7972
+ }
7973
+ return exports;
7974
+ });
7975
+ }
7976
+ catch { }
7977
+ }
7978
+ function patchMongoDb(cfg) {
7979
+ mongoDbPatchConfigs.push(cfg);
7980
+ installMongoDbRequireHook();
7981
+ const mongoModules = new Set();
7982
+ const resolvedMongoModule = requireOptionalHostModule('mongodb');
7983
+ if (resolvedMongoModule) {
7984
+ mongoModules.add(resolvedMongoModule);
7985
+ }
7986
+ for (const loadedMongoModule of getLoadedModuleExportsByPackage('mongodb')) {
7987
+ mongoModules.add(loadedMongoModule);
7988
+ }
7989
+ if (!mongoModules.size)
7990
+ return;
7991
+ for (const mongoModule of mongoModules) {
7992
+ patchMongoDbFromModuleExports(mongoModule, cfg);
7993
+ }
7994
+ }
7995
+ exports.patchMongoDb = patchMongoDb;
7412
7996
  // ===================================================================
7413
7997
  // Auto init helpers
7414
7998
  // ===================================================================
@@ -7834,6 +8418,7 @@ async function initRepro(cfg) {
7834
8418
  patchKafkaJs(integrationCfg);
7835
8419
  patchAmqplib(integrationCfg);
7836
8420
  patchRedis(integrationCfg);
8421
+ patchMongoDb(integrationCfg);
7837
8422
  patchSendgridMail(integrationCfg);
7838
8423
  patchMongooseIntegration(reproAutoMiddlewareConfig);
7839
8424
  await initializeRuntimePrivacyPolicyAtStartup(reproAutoMiddlewareConfig);
@@ -7881,6 +8466,8 @@ exports.__reproTestHooks = {
7881
8466
  patchAmqplibConnectionForTest: patchAmqplibConnection,
7882
8467
  patchAmqplibChannelForTest: patchAmqplibChannel,
7883
8468
  wrapAmqplibConsumeHandlerForTest: wrapAmqplibConsumeHandler,
8469
+ patchMongoDbModuleForTest: patchMongoDbFromModuleExports,
8470
+ patchMongoCollectionPrototypeForTest: patchMongoCollectionPrototype,
7884
8471
  chunkTraceEventsForTransportForTest: chunkTraceEventsForTransport,
7885
8472
  estimateTraceBatchSerializedBytesForTest: estimateTraceBatchSerializedBytes,
7886
8473
  sanitizeTraceValueForPrivacyForTest: sanitizeTraceValueForPrivacy,