@reproapp/node-sdk 0.0.35 → 0.0.37

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
@@ -330,7 +330,7 @@ let disabledFunctionTraceRules = computeDisabledFunctionTraceRules();
330
330
  let disabledFunctionTypePatterns = [];
331
331
  let disabledTraceFilePatterns = [];
332
332
  let __TRACE_LOG_PREF = null;
333
- let __FULL_VALUE_CAPTURE_ENABLED = false;
333
+ let __FULL_VALUE_CAPTURE_ENABLED = true;
334
334
  function setInterceptorTracingEnabled(enabled) {
335
335
  const next = !!enabled;
336
336
  if (interceptorTracingEnabled === next)
@@ -581,9 +581,9 @@ function defaultTracerInitOpts() {
581
581
  /** Call this from the client app to enable tracing. Safe to call multiple times. */
582
582
  function initReproTracing(opts) {
583
583
  const options = opts ?? {};
584
- if (hasOwn(options, 'fullValueCapture')) {
585
- __FULL_VALUE_CAPTURE_ENABLED = options.fullValueCapture === true;
586
- }
584
+ __FULL_VALUE_CAPTURE_ENABLED = hasOwn(options, 'fullValueCapture')
585
+ ? options.fullValueCapture === true
586
+ : true;
587
587
  if (hasOwn(options, 'traceInterceptors')) {
588
588
  setInterceptorTracingEnabled(!!options.traceInterceptors);
589
589
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reproapp/node-sdk",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "Repro Nest SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -604,7 +604,7 @@ let disabledFunctionTraceRules: DisableFunctionTraceConfig[] = computeDisabledFu
604
604
  let disabledFunctionTypePatterns: Array<string | number | RegExp> = [];
605
605
  let disabledTraceFilePatterns: Array<string | number | RegExp> = [];
606
606
  let __TRACE_LOG_PREF: boolean | null = null;
607
- let __FULL_VALUE_CAPTURE_ENABLED = false;
607
+ let __FULL_VALUE_CAPTURE_ENABLED = true;
608
608
 
609
609
  function setInterceptorTracingEnabled(enabled: boolean) {
610
610
  const next = !!enabled;
@@ -929,9 +929,9 @@ function defaultTracerInitOpts(): TracerInitOpts {
929
929
  export function initReproTracing(opts?: ReproTracingInitOptions) {
930
930
  const options = opts ?? {};
931
931
 
932
- if (hasOwn(options, 'fullValueCapture')) {
933
- __FULL_VALUE_CAPTURE_ENABLED = options.fullValueCapture === true;
934
- }
932
+ __FULL_VALUE_CAPTURE_ENABLED = hasOwn(options, 'fullValueCapture')
933
+ ? options.fullValueCapture === true
934
+ : true;
935
935
 
936
936
  if (hasOwn(options, 'traceInterceptors')) {
937
937
  setInterceptorTracingEnabled(!!options.traceInterceptors);
@@ -170,10 +170,28 @@ async function main() {
170
170
  event?.returnValue,
171
171
  );
172
172
  assert(largeReturnExit, JSON.stringify(traceEvents));
173
- assert.deepEqual(
174
- largeReturnExit.returnValue,
175
- { __kind: 'omitted', reason: 'inline-size-limit' },
173
+ assert(
174
+ Buffer.byteLength(JSON.stringify(largeReturnExit.returnValue), 'utf8') <= 2048,
175
+ JSON.stringify(largeReturnExit.returnValue),
176
176
  );
177
+ assert.equal(
178
+ largeReturnExit.returnValueCapture?.status,
179
+ 'stored',
180
+ JSON.stringify(largeReturnExit),
181
+ );
182
+ assert(
183
+ typeof largeReturnExit.returnValueCapture?.valueId === 'string' &&
184
+ largeReturnExit.returnValueCapture.valueId.length > 0,
185
+ JSON.stringify(largeReturnExit),
186
+ );
187
+ const traceValues = eventsOf(capturedBodies, 'trace_batch')
188
+ .flatMap((event) => Array.isArray(event?.payload?.traceValues) ? event.payload.traceValues : []);
189
+ const capturedReturnValue = traceValues.find((entry) =>
190
+ entry?.id === largeReturnExit.returnValueCapture.valueId &&
191
+ entry?.target === 'trace.returnValue'
192
+ );
193
+ assert(capturedReturnValue, JSON.stringify(traceValues));
194
+ assert.equal(capturedReturnValue.value?.rows?.length, 400, JSON.stringify(capturedReturnValue));
177
195
 
178
196
  console.log('client performance regression guards OK');
179
197
  } finally {
@@ -332,6 +332,151 @@ async function testMongoClientDbCollectionChainIsPatchedWithoutCollectionExport(
332
332
  });
333
333
  }
334
334
 
335
+ async function testClientScreenNativeMongoInsertOneShapeIsCaptured() {
336
+ await withCapturedFetch(async (capturedBodies) => {
337
+ __reproTestHooks.resetSdkBackgroundQueuesForTest();
338
+ const sessionId = 'S_client_screen_native_insert';
339
+ const actionId = 'A_client_screen_native_insert';
340
+ const cfg = {
341
+ ...makeConfig(sessionId, actionId),
342
+ privacy: { environment: 'dev', captureRaw: true },
343
+ };
344
+
345
+ class FakeCollection {
346
+ constructor(dbName, collectionName) {
347
+ this.dbName = dbName;
348
+ this.collectionName = collectionName;
349
+ }
350
+
351
+ async insertOne(doc, options) {
352
+ assert.strictEqual(options.session.id, 'screen-transaction-session-1');
353
+ doc._id = doc._id ?? 'subject-screen-1';
354
+ return { acknowledged: true, insertedId: doc._id };
355
+ }
356
+ }
357
+
358
+ class FakeDb {
359
+ constructor(dbName) {
360
+ this.databaseName = dbName;
361
+ }
362
+
363
+ collection(collectionName) {
364
+ return new FakeCollection(this.databaseName, collectionName);
365
+ }
366
+ }
367
+
368
+ class FakeMongoClient {
369
+ db(dbName) {
370
+ return new FakeDb(dbName);
371
+ }
372
+ }
373
+
374
+ __reproTestHooks.patchMongoDbModuleForTest({
375
+ MongoClient: FakeMongoClient,
376
+ Db: FakeDb,
377
+ }, cfg);
378
+
379
+ const dbClient = new FakeMongoClient();
380
+ const connectionDictionary = {
381
+ pulmovant: {
382
+ db: {
383
+ databaseName: 'dev-configure-pulmovant',
384
+ },
385
+ },
386
+ };
387
+ const collectionNames = {
388
+ SUBJECTS: 'subjects',
389
+ };
390
+ const completeVisitTypeLimitChecks = async () => null;
391
+
392
+ async function screen(req, newSubjectRecord, openUserTransaction) {
393
+ newSubjectRecord.lastUserTransactionId = openUserTransaction._id;
394
+
395
+ const dbName = connectionDictionary[req.query.tenantId].db.databaseName;
396
+ const subjectsCollection = await dbClient.db(dbName).collection(collectionNames.SUBJECTS);
397
+
398
+ const checkResult = await completeVisitTypeLimitChecks();
399
+ if (checkResult) return { success: false, message: checkResult };
400
+
401
+ const subjectSaveResult = await subjectsCollection.insertOne(newSubjectRecord, {
402
+ session: req.mongoSession,
403
+ });
404
+
405
+ if (!subjectSaveResult.acknowledged) {
406
+ throw new Error('Error creating subject');
407
+ }
408
+
409
+ return { success: true, insertedId: subjectSaveResult.insertedId };
410
+ }
411
+
412
+ const newSubjectRecord = {
413
+ activityLog: {
414
+ createdBy: '678a70921acd637a6de91c1f',
415
+ createdByUserName: "Pat O'Brien",
416
+ createdOn: '2026-06-22 10:14:13.151000000',
417
+ },
418
+ demographics: [
419
+ { key: 'age', type: 'Number', value: '35' },
420
+ { key: 'dateOfBirth', type: 'String', value: '1990' },
421
+ { key: 'gender', type: 'String', value: 'Female' },
422
+ ],
423
+ protocolId: '69e77c77ab541cfac917b36b',
424
+ site: {
425
+ id: '69f0c10256a07ef2204a6ef6',
426
+ number: '1001',
427
+ },
428
+ status: 'Active',
429
+ subjectFlags: {
430
+ isRescreen: false,
431
+ },
432
+ subjectNumber: '10013060',
433
+ subjectStatus: 'Screened',
434
+ subjectStatusOption: 'Screened',
435
+ };
436
+
437
+ await runCapturedRequest(cfg, sessionId, actionId, async () => {
438
+ const result = await screen(
439
+ {
440
+ query: { tenantId: 'pulmovant' },
441
+ mongoSession: {
442
+ id: 'screen-transaction-session-1',
443
+ hasEnded: false,
444
+ inTransaction: () => true,
445
+ },
446
+ },
447
+ newSubjectRecord,
448
+ { _id: '6a390af395744083f43fd484' },
449
+ );
450
+ assert.deepStrictEqual(result, {
451
+ success: true,
452
+ insertedId: 'subject-screen-1',
453
+ });
454
+ });
455
+
456
+ await waitFor(() => dbChanges(flattenEvents(capturedBodies)).length === 1);
457
+ await waitFor(() => requestCaptureManifests(flattenEvents(capturedBodies)).length === 1);
458
+ await drainSdk();
459
+
460
+ const [change] = dbChanges(flattenEvents(capturedBodies));
461
+ const [manifest] = requestCaptureManifests(flattenEvents(capturedBodies));
462
+ assert.strictEqual(change.type, 'mongo');
463
+ assert.strictEqual(change.collection, 'subjects');
464
+ assert.strictEqual(change.op, 'insertOne');
465
+ assert.strictEqual(change.pk._id, 'subject-screen-1');
466
+ assert.strictEqual(change.query.driver, 'mongodb');
467
+ assert.strictEqual(change.query.db, 'dev-configure-pulmovant');
468
+ assert.strictEqual(change.query.doc.subjectNumber, '10013060');
469
+ assert.strictEqual(change.query.doc.lastUserTransactionId, '6a390af395744083f43fd484');
470
+ assert.strictEqual(change.query.options.session.__kind, 'mongodb_client_session');
471
+ assert.strictEqual(change.query.options.session.id, 'screen-transaction-session-1');
472
+ assert.strictEqual(change.query.options.session.inTransaction, true);
473
+ assert.strictEqual(change.after.subjectNumber, '10013060');
474
+ assert.strictEqual(change.resultMeta.insertedId, 'subject-screen-1');
475
+ assert.strictEqual(change.resultMeta.acknowledged, true);
476
+ assert.strictEqual(manifest.expected.dbChange, 1);
477
+ });
478
+ }
479
+
335
480
  async function testNativeInsertOneIsCaptured() {
336
481
  await withCapturedFetch(async (capturedBodies) => {
337
482
  __reproTestHooks.resetSdkBackgroundQueuesForTest();
@@ -596,6 +741,7 @@ async function testNativeOperationFailureIsCapturedAndRethrown() {
596
741
  await testMongooseSuppressionDoesNotHideExplicitNativeInsertOne();
597
742
  await testReproMiddlewarePatchesPreloadedNativeMongoClientInsertOne();
598
743
  await testMongoClientDbCollectionChainIsPatchedWithoutCollectionExport();
744
+ await testClientScreenNativeMongoInsertOneShapeIsCaptured();
599
745
  await testNativeInsertOneIsCaptured();
600
746
  await testCaptureRawNativeInsertOneUsesJsonSafeTransportValues();
601
747
  await testNativeUpdateOneUpsertIsCaptured();