s3db.js 11.0.0 → 11.0.2

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": "s3db.js",
3
- "version": "11.0.0",
3
+ "version": "11.0.2",
4
4
  "description": "Use AWS S3, the world's most reliable document storage, as a database with this ORM.",
5
5
  "main": "dist/s3db.cjs.js",
6
6
  "module": "dist/s3db.es.js",
@@ -133,6 +133,7 @@
133
133
  "dev": "rollup -c -w",
134
134
  "test": "pnpm run test:js && pnpm run test:ts",
135
135
  "test:js": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js",
136
+ "test:quick": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --maxWorkers=2 --bail",
136
137
  "test:ts": "tsc --noEmit --project tests/typescript/tsconfig.json",
137
138
  "test:coverage": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --maxWorkers=1",
138
139
  "test:serial": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand",
@@ -17,6 +17,18 @@ import { groupByCohort } from "./utils.js";
17
17
  export async function updateAnalytics(transactions, analyticsResource, config) {
18
18
  if (!analyticsResource || transactions.length === 0) return;
19
19
 
20
+ // CRITICAL VALIDATION: Ensure field is set in config
21
+ // This can be undefined due to race conditions when multiple handlers share config
22
+ if (!config.field) {
23
+ throw new Error(
24
+ `[EventualConsistency] CRITICAL BUG: config.field is undefined in updateAnalytics()!\n` +
25
+ `This indicates a race condition in the plugin where multiple handlers are sharing the same config object.\n` +
26
+ `Config: ${JSON.stringify({ resource: config.resource, field: config.field })}\n` +
27
+ `Transactions count: ${transactions.length}\n` +
28
+ `AnalyticsResource: ${analyticsResource?.name || 'unknown'}`
29
+ );
30
+ }
31
+
20
32
  if (config.verbose) {
21
33
  console.log(
22
34
  `[EventualConsistency] ${config.resource}.${config.field} - ` +
@@ -413,17 +413,71 @@ export async function consolidateRecord(
413
413
  );
414
414
  }
415
415
 
416
+ // 🔥 DEBUG: Log BEFORE update
417
+ if (config.verbose) {
418
+ console.log(
419
+ `🔥 [DEBUG] BEFORE targetResource.update() {` +
420
+ `\n originalId: '${originalId}',` +
421
+ `\n field: '${config.field}',` +
422
+ `\n consolidatedValue: ${consolidatedValue},` +
423
+ `\n currentValue: ${currentValue}` +
424
+ `\n}`
425
+ );
426
+ }
427
+
416
428
  // Update the original record
417
429
  // NOTE: We do NOT attempt to insert non-existent records because:
418
430
  // 1. Target resources typically have required fields we don't know about
419
431
  // 2. Record creation should be the application's responsibility
420
432
  // 3. Transactions will remain pending until the record is created
421
- const [updateOk, updateErr] = await tryFn(() =>
433
+ const [updateOk, updateErr, updateResult] = await tryFn(() =>
422
434
  targetResource.update(originalId, {
423
435
  [config.field]: consolidatedValue
424
436
  })
425
437
  );
426
438
 
439
+ // 🔥 DEBUG: Log AFTER update
440
+ if (config.verbose) {
441
+ console.log(
442
+ `🔥 [DEBUG] AFTER targetResource.update() {` +
443
+ `\n updateOk: ${updateOk},` +
444
+ `\n updateErr: ${updateErr?.message || 'undefined'},` +
445
+ `\n updateResult: ${JSON.stringify(updateResult, null, 2)},` +
446
+ `\n hasField: ${updateResult?.[config.field]}` +
447
+ `\n}`
448
+ );
449
+ }
450
+
451
+ // 🔥 VERIFY: Check if update actually persisted
452
+ if (updateOk && config.verbose) {
453
+ // Bypass cache to get fresh data
454
+ const [verifyOk, verifyErr, verifiedRecord] = await tryFn(() =>
455
+ targetResource.get(originalId, { skipCache: true })
456
+ );
457
+
458
+ console.log(
459
+ `🔥 [DEBUG] VERIFICATION (fresh from S3, no cache) {` +
460
+ `\n verifyOk: ${verifyOk},` +
461
+ `\n verifiedRecord[${config.field}]: ${verifiedRecord?.[config.field]},` +
462
+ `\n expectedValue: ${consolidatedValue},` +
463
+ `\n ✅ MATCH: ${verifiedRecord?.[config.field] === consolidatedValue}` +
464
+ `\n}`
465
+ );
466
+
467
+ // If verification fails, this is a critical bug
468
+ if (verifyOk && verifiedRecord?.[config.field] !== consolidatedValue) {
469
+ console.error(
470
+ `❌ [CRITICAL BUG] Update reported success but value not persisted!` +
471
+ `\n Resource: ${config.resource}` +
472
+ `\n Field: ${config.field}` +
473
+ `\n Record ID: ${originalId}` +
474
+ `\n Expected: ${consolidatedValue}` +
475
+ `\n Actually got: ${verifiedRecord?.[config.field]}` +
476
+ `\n This indicates a bug in s3db.js resource.update()`
477
+ );
478
+ }
479
+ }
480
+
427
481
  if (!updateOk) {
428
482
  // Check if record doesn't exist
429
483
  if (updateErr?.message?.includes('does not exist')) {