@reproapp/node-sdk 0.0.26 → 0.0.28

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