jexidb 2.1.2 → 2.1.3
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/Database.cjs +468 -226
- package/package.json +1 -1
- package/src/Database.mjs +137 -84
package/package.json
CHANGED
package/src/Database.mjs
CHANGED
|
@@ -1319,38 +1319,21 @@ class Database extends EventEmitter {
|
|
|
1319
1319
|
this.pendingIndexUpdates = []
|
|
1320
1320
|
}
|
|
1321
1321
|
|
|
1322
|
-
// CRITICAL FIX:
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
//
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
// CRITICAL FIX: Verify write buffer is empty after I/O completion
|
|
1329
|
-
// But allow for ongoing insertions during high-volume scenarios
|
|
1330
|
-
if (this.writeBuffer.length > 0) {
|
|
1331
|
-
if (this.opts.debugMode) {
|
|
1332
|
-
console.log(`💾 Save: WriteBuffer still has ${this.writeBuffer.length} items after flush - this may indicate ongoing insertions`)
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
|
-
// If we have a reasonable number of items, continue processing
|
|
1336
|
-
if (this.writeBuffer.length < 10000) { // Reasonable threshold
|
|
1337
|
-
if (this.opts.debugMode) {
|
|
1338
|
-
console.log(`💾 Save: Continuing to process remaining ${this.writeBuffer.length} items`)
|
|
1339
|
-
}
|
|
1340
|
-
// Continue with the save process - the remaining items will be included in the final save
|
|
1341
|
-
} else {
|
|
1342
|
-
// Too many items remaining - likely a real problem
|
|
1343
|
-
throw new Error(`WriteBuffer has too many items after flush: ${this.writeBuffer.length} items remaining (threshold: 10000)`)
|
|
1344
|
-
}
|
|
1322
|
+
// CRITICAL FIX: DO NOT flush writeBuffer before processing existing records
|
|
1323
|
+
// This prevents duplicating updated records in the file.
|
|
1324
|
+
// The _streamExistingRecords() will handle replacing old records with updated ones from writeBufferSnapshot.
|
|
1325
|
+
// After processing, all records (existing + updated + new) will be written to file in one operation.
|
|
1326
|
+
if (this.opts.debugMode) {
|
|
1327
|
+
console.log(`💾 Save: writeBufferSnapshot captured with ${writeBufferSnapshot.length} records (will be processed with existing records)`)
|
|
1345
1328
|
}
|
|
1346
1329
|
|
|
1347
1330
|
// OPTIMIZATION: Parallel operations - cleanup and data preparation
|
|
1348
1331
|
let allData = []
|
|
1349
1332
|
let orphanedCount = 0
|
|
1350
1333
|
|
|
1351
|
-
// Check if there are
|
|
1352
|
-
// CRITICAL FIX:
|
|
1353
|
-
//
|
|
1334
|
+
// Check if there are records to save from writeBufferSnapshot
|
|
1335
|
+
// CRITICAL FIX: Process writeBufferSnapshot records (both new and updated) with existing records
|
|
1336
|
+
// Updated records will replace old ones via _streamExistingRecords, new records will be added
|
|
1354
1337
|
if (this.opts.debugMode) {
|
|
1355
1338
|
console.log(`💾 Save: writeBuffer.length=${this.writeBuffer.length}, writeBufferSnapshot.length=${writeBufferSnapshot.length}`)
|
|
1356
1339
|
}
|
|
@@ -1397,11 +1380,49 @@ class Database extends EventEmitter {
|
|
|
1397
1380
|
// CRITICAL FIX: Normalize IDs to strings for consistent comparison
|
|
1398
1381
|
const existingRecordIds = new Set(existingRecords.filter(r => r && r.id).map(r => String(r.id)))
|
|
1399
1382
|
|
|
1383
|
+
// CRITICAL FIX: Create a map of records in existingRecords by ID for comparison
|
|
1384
|
+
const existingRecordsById = new Map()
|
|
1385
|
+
existingRecords.forEach(r => {
|
|
1386
|
+
if (r && r.id) {
|
|
1387
|
+
existingRecordsById.set(String(r.id), r)
|
|
1388
|
+
}
|
|
1389
|
+
})
|
|
1390
|
+
|
|
1400
1391
|
// Add only NEW records from writeBufferSnapshot (not updates, as those are already in existingRecords)
|
|
1392
|
+
// CRITICAL FIX: Also ensure that if an updated record wasn't properly replaced, we replace it now
|
|
1401
1393
|
for (const record of writeBufferSnapshot) {
|
|
1402
|
-
if (
|
|
1394
|
+
if (!record || !record.id) continue
|
|
1395
|
+
if (deletedIdsSnapshot.has(String(record.id))) continue
|
|
1396
|
+
|
|
1397
|
+
const recordIdStr = String(record.id)
|
|
1398
|
+
const existingRecord = existingRecordsById.get(recordIdStr)
|
|
1399
|
+
|
|
1400
|
+
if (!existingRecord) {
|
|
1403
1401
|
// This is a new record, not an update
|
|
1404
1402
|
allData.push(record)
|
|
1403
|
+
if (this.opts.debugMode) {
|
|
1404
|
+
console.log(`💾 Save: Adding NEW record to allData:`, { id: recordIdStr, price: record.price, app_id: record.app_id, currency: record.currency })
|
|
1405
|
+
}
|
|
1406
|
+
} else {
|
|
1407
|
+
// This is an update - verify that existingRecords contains the updated version
|
|
1408
|
+
// If not, replace it (this handles edge cases where substitution might have failed)
|
|
1409
|
+
const existingIndex = allData.findIndex(r => r && r.id && String(r.id) === recordIdStr)
|
|
1410
|
+
if (existingIndex !== -1) {
|
|
1411
|
+
// Verify if the existing record is actually the updated one
|
|
1412
|
+
// Compare key fields to detect if replacement is needed
|
|
1413
|
+
const needsReplacement = JSON.stringify(allData[existingIndex]) !== JSON.stringify(record)
|
|
1414
|
+
if (needsReplacement) {
|
|
1415
|
+
if (this.opts.debugMode) {
|
|
1416
|
+
console.log(`💾 Save: REPLACING existing record with updated version in allData:`, {
|
|
1417
|
+
old: { id: String(allData[existingIndex].id), price: allData[existingIndex].price },
|
|
1418
|
+
new: { id: recordIdStr, price: record.price }
|
|
1419
|
+
})
|
|
1420
|
+
}
|
|
1421
|
+
allData[existingIndex] = record
|
|
1422
|
+
} else if (this.opts.debugMode) {
|
|
1423
|
+
console.log(`💾 Save: Record already correctly updated in allData:`, { id: recordIdStr })
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1405
1426
|
}
|
|
1406
1427
|
}
|
|
1407
1428
|
})
|
|
@@ -1452,13 +1473,52 @@ class Database extends EventEmitter {
|
|
|
1452
1473
|
allData = [...existingRecords]
|
|
1453
1474
|
|
|
1454
1475
|
// OPTIMIZATION: Use Set for faster lookups of existing record IDs
|
|
1455
|
-
|
|
1476
|
+
// CRITICAL FIX: Normalize IDs to strings for consistent comparison
|
|
1477
|
+
const existingRecordIds = new Set(existingRecords.filter(r => r && r.id).map(r => String(r.id)))
|
|
1478
|
+
|
|
1479
|
+
// CRITICAL FIX: Create a map of records in existingRecords by ID for comparison
|
|
1480
|
+
const existingRecordsById = new Map()
|
|
1481
|
+
existingRecords.forEach(r => {
|
|
1482
|
+
if (r && r.id) {
|
|
1483
|
+
existingRecordsById.set(String(r.id), r)
|
|
1484
|
+
}
|
|
1485
|
+
})
|
|
1456
1486
|
|
|
1457
1487
|
// Add only NEW records from writeBufferSnapshot (not updates, as those are already in existingRecords)
|
|
1488
|
+
// CRITICAL FIX: Also ensure that if an updated record wasn't properly replaced, we replace it now
|
|
1458
1489
|
for (const record of writeBufferSnapshot) {
|
|
1459
|
-
if (
|
|
1490
|
+
if (!record || !record.id) continue
|
|
1491
|
+
if (deletedIdsSnapshot.has(String(record.id))) continue
|
|
1492
|
+
|
|
1493
|
+
const recordIdStr = String(record.id)
|
|
1494
|
+
const existingRecord = existingRecordsById.get(recordIdStr)
|
|
1495
|
+
|
|
1496
|
+
if (!existingRecord) {
|
|
1460
1497
|
// This is a new record, not an update
|
|
1461
1498
|
allData.push(record)
|
|
1499
|
+
if (this.opts.debugMode) {
|
|
1500
|
+
console.log(`💾 Save: Adding NEW record to allData:`, { id: recordIdStr, price: record.price, app_id: record.app_id, currency: record.currency })
|
|
1501
|
+
}
|
|
1502
|
+
} else {
|
|
1503
|
+
// This is an update - verify that existingRecords contains the updated version
|
|
1504
|
+
// If not, replace it (this handles edge cases where substitution might have failed)
|
|
1505
|
+
const existingIndex = allData.findIndex(r => r && r.id && String(r.id) === recordIdStr)
|
|
1506
|
+
if (existingIndex !== -1) {
|
|
1507
|
+
// Verify if the existing record is actually the updated one
|
|
1508
|
+
// Compare key fields to detect if replacement is needed
|
|
1509
|
+
const needsReplacement = JSON.stringify(allData[existingIndex]) !== JSON.stringify(record)
|
|
1510
|
+
if (needsReplacement) {
|
|
1511
|
+
if (this.opts.debugMode) {
|
|
1512
|
+
console.log(`💾 Save: REPLACING existing record with updated version in allData:`, {
|
|
1513
|
+
old: { id: String(allData[existingIndex].id), price: allData[existingIndex].price },
|
|
1514
|
+
new: { id: recordIdStr, price: record.price }
|
|
1515
|
+
})
|
|
1516
|
+
}
|
|
1517
|
+
allData[existingIndex] = record
|
|
1518
|
+
} else if (this.opts.debugMode) {
|
|
1519
|
+
console.log(`💾 Save: Record already correctly updated in allData:`, { id: recordIdStr })
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1462
1522
|
}
|
|
1463
1523
|
}
|
|
1464
1524
|
|
|
@@ -1466,10 +1526,11 @@ class Database extends EventEmitter {
|
|
|
1466
1526
|
const updatedCount = writeBufferSnapshot.filter(r => r && r.id && existingRecordIds.has(String(r.id))).length
|
|
1467
1527
|
const newCount = writeBufferSnapshot.filter(r => r && r.id && !existingRecordIds.has(String(r.id))).length
|
|
1468
1528
|
console.log(`💾 Save: Combined data - existingRecords: ${existingRecords.length}, updatedFromBuffer: ${updatedCount}, newFromBuffer: ${newCount}, total: ${allData.length}`)
|
|
1469
|
-
console.log(`💾 Save: WriteBuffer record IDs:`, writeBufferSnapshot.map(r => r && r.id ? r.id : 'no-id'))
|
|
1529
|
+
console.log(`💾 Save: WriteBuffer record IDs:`, writeBufferSnapshot.map(r => r && r.id ? String(r.id) : 'no-id'))
|
|
1470
1530
|
console.log(`💾 Save: Existing record IDs:`, Array.from(existingRecordIds))
|
|
1471
|
-
console.log(`💾 Save:
|
|
1472
|
-
console.log(`💾 Save: Sample
|
|
1531
|
+
console.log(`💾 Save: All records in allData:`, allData.map(r => r && r.id ? { id: String(r.id), price: r.price, app_id: r.app_id, currency: r.currency } : 'no-id'))
|
|
1532
|
+
console.log(`💾 Save: Sample existing record:`, existingRecords[0] ? { id: String(existingRecords[0].id), price: existingRecords[0].price, app_id: existingRecords[0].app_id, currency: existingRecords[0].currency } : 'null')
|
|
1533
|
+
console.log(`💾 Save: Sample writeBuffer record:`, writeBufferSnapshot[0] ? { id: String(writeBufferSnapshot[0].id), price: writeBufferSnapshot[0].price, app_id: writeBufferSnapshot[0].app_id, currency: writeBufferSnapshot[0].currency } : 'null')
|
|
1473
1534
|
}
|
|
1474
1535
|
}).catch(error => {
|
|
1475
1536
|
if (this.opts.debugMode) {
|
|
@@ -1545,6 +1606,7 @@ class Database extends EventEmitter {
|
|
|
1545
1606
|
|
|
1546
1607
|
if (this.opts.debugMode) {
|
|
1547
1608
|
console.log(`💾 Save: allData.length=${allData.length}, cleanedData.length=${cleanedData.length}`)
|
|
1609
|
+
console.log(`💾 Save: All records in allData before serialization:`, allData.map(r => r && r.id ? { id: String(r.id), price: r.price, app_id: r.app_id, currency: r.currency } : 'no-id'))
|
|
1548
1610
|
console.log(`💾 Save: Sample cleaned record:`, cleanedData[0] ? Object.keys(cleanedData[0]) : 'null')
|
|
1549
1611
|
}
|
|
1550
1612
|
|
|
@@ -1556,6 +1618,7 @@ class Database extends EventEmitter {
|
|
|
1556
1618
|
|
|
1557
1619
|
if (this.opts.debugMode) {
|
|
1558
1620
|
console.log(`💾 Save: Serialized ${lines.length} lines`)
|
|
1621
|
+
console.log(`💾 Save: All records in allData after serialization check:`, allData.map(r => r && r.id ? { id: String(r.id), price: r.price, app_id: r.app_id, currency: r.currency } : 'no-id'))
|
|
1559
1622
|
if (lines.length > 0) {
|
|
1560
1623
|
console.log(`💾 Save: First line (first 200 chars):`, lines[0].substring(0, 200))
|
|
1561
1624
|
}
|
|
@@ -1578,56 +1641,9 @@ class Database extends EventEmitter {
|
|
|
1578
1641
|
console.log(`💾 Save: Calculated indexOffset: ${this.indexOffset}, allData.length: ${allData.length}`)
|
|
1579
1642
|
}
|
|
1580
1643
|
|
|
1581
|
-
//
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
// Add main file write operation
|
|
1585
|
-
parallelWriteOperations.push(
|
|
1586
|
-
this.fileHandler.writeBatch([jsonlData])
|
|
1587
|
-
)
|
|
1588
|
-
|
|
1589
|
-
// Add index file operations - ALWAYS save offsets, even without indexed fields
|
|
1590
|
-
if (this.indexManager) {
|
|
1591
|
-
const idxPath = this.normalizedFile.replace('.jdb', '.idx.jdb')
|
|
1592
|
-
|
|
1593
|
-
// OPTIMIZATION: Parallel data preparation
|
|
1594
|
-
const indexDataPromise = Promise.resolve({
|
|
1595
|
-
index: this.indexManager.indexedFields && this.indexManager.indexedFields.length > 0 ? this.indexManager.toJSON() : {},
|
|
1596
|
-
offsets: this.offsets, // Save actual offsets for efficient file operations
|
|
1597
|
-
indexOffset: this.indexOffset // Save file size for proper range calculations
|
|
1598
|
-
})
|
|
1599
|
-
|
|
1600
|
-
// Add term mapping data if needed
|
|
1601
|
-
const termMappingFields = this.getTermMappingFields()
|
|
1602
|
-
if (termMappingFields.length > 0 && this.termManager) {
|
|
1603
|
-
const termDataPromise = this.termManager.saveTerms()
|
|
1604
|
-
|
|
1605
|
-
// Combine index data and term data
|
|
1606
|
-
const combinedDataPromise = Promise.all([indexDataPromise, termDataPromise]).then(([indexData, termData]) => {
|
|
1607
|
-
indexData.termMapping = termData
|
|
1608
|
-
return indexData
|
|
1609
|
-
})
|
|
1610
|
-
|
|
1611
|
-
// Add index file write operation
|
|
1612
|
-
parallelWriteOperations.push(
|
|
1613
|
-
combinedDataPromise.then(indexData => {
|
|
1614
|
-
const idxFileHandler = new FileHandler(idxPath, this.fileMutex, this.opts)
|
|
1615
|
-
return idxFileHandler.writeAll(JSON.stringify(indexData, null, 2))
|
|
1616
|
-
})
|
|
1617
|
-
)
|
|
1618
|
-
} else {
|
|
1619
|
-
// Add index file write operation without term mapping
|
|
1620
|
-
parallelWriteOperations.push(
|
|
1621
|
-
indexDataPromise.then(indexData => {
|
|
1622
|
-
const idxFileHandler = new FileHandler(idxPath, this.fileMutex, this.opts)
|
|
1623
|
-
return idxFileHandler.writeAll(JSON.stringify(indexData, null, 2))
|
|
1624
|
-
})
|
|
1625
|
-
)
|
|
1626
|
-
}
|
|
1627
|
-
}
|
|
1628
|
-
|
|
1629
|
-
// Execute parallel write operations
|
|
1630
|
-
await Promise.all(parallelWriteOperations)
|
|
1644
|
+
// CRITICAL FIX: Write main data file first
|
|
1645
|
+
// Index will be saved AFTER reconstruction to ensure it contains correct data
|
|
1646
|
+
await this.fileHandler.writeBatch([jsonlData])
|
|
1631
1647
|
|
|
1632
1648
|
if (this.opts.debugMode) {
|
|
1633
1649
|
console.log(`💾 Saved ${allData.length} records to ${this.normalizedFile}`)
|
|
@@ -1661,9 +1677,16 @@ class Database extends EventEmitter {
|
|
|
1661
1677
|
|
|
1662
1678
|
// Rebuild index from the saved records
|
|
1663
1679
|
// CRITICAL: Process term mapping for records loaded from file to ensure ${field}Ids are available
|
|
1680
|
+
if (this.opts.debugMode) {
|
|
1681
|
+
console.log(`💾 Save: Rebuilding index from ${allData.length} records in allData`)
|
|
1682
|
+
}
|
|
1664
1683
|
for (let i = 0; i < allData.length; i++) {
|
|
1665
1684
|
let record = allData[i]
|
|
1666
1685
|
|
|
1686
|
+
if (this.opts.debugMode && i < 3) {
|
|
1687
|
+
console.log(`💾 Save: Rebuilding index record[${i}]:`, { id: String(record.id), price: record.price, app_id: record.app_id, currency: record.currency })
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1667
1690
|
// CRITICAL FIX: Ensure records have ${field}Ids for term mapping fields
|
|
1668
1691
|
// Records from writeBuffer already have ${field}Ids from processTermMapping
|
|
1669
1692
|
// Records from file need to be processed to restore ${field}Ids
|
|
@@ -1690,6 +1713,9 @@ class Database extends EventEmitter {
|
|
|
1690
1713
|
|
|
1691
1714
|
await this.indexManager.add(record, i)
|
|
1692
1715
|
}
|
|
1716
|
+
if (this.opts.debugMode) {
|
|
1717
|
+
console.log(`💾 Save: Index rebuilt with ${allData.length} records`)
|
|
1718
|
+
}
|
|
1693
1719
|
}
|
|
1694
1720
|
}
|
|
1695
1721
|
|
|
@@ -2574,11 +2600,20 @@ class Database extends EventEmitter {
|
|
|
2574
2600
|
|
|
2575
2601
|
const updated = { ...record, ...updateData }
|
|
2576
2602
|
|
|
2603
|
+
// DEBUG: Log the update operation details
|
|
2604
|
+
if (this.opts.debugMode) {
|
|
2605
|
+
console.log(`🔄 UPDATE: Original record ID: ${record.id}, type: ${typeof record.id}`)
|
|
2606
|
+
console.log(`🔄 UPDATE: Updated record ID: ${updated.id}, type: ${typeof updated.id}`)
|
|
2607
|
+
console.log(`🔄 UPDATE: Update data keys:`, Object.keys(updateData))
|
|
2608
|
+
console.log(`🔄 UPDATE: Updated record keys:`, Object.keys(updated))
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2577
2611
|
// Process term mapping for update
|
|
2578
2612
|
const termMappingStart = Date.now()
|
|
2579
2613
|
this.processTermMapping(updated, true, record)
|
|
2580
2614
|
if (this.opts.debugMode) {
|
|
2581
2615
|
console.log(`🔄 UPDATE: Term mapping completed in ${Date.now() - termMappingStart}ms`)
|
|
2616
|
+
console.log(`🔄 UPDATE: After term mapping - ID: ${updated.id}, type: ${typeof updated.id}`)
|
|
2582
2617
|
}
|
|
2583
2618
|
|
|
2584
2619
|
// CRITICAL FIX: Remove old terms from index before adding new ones
|
|
@@ -4084,14 +4119,23 @@ class Database extends EventEmitter {
|
|
|
4084
4119
|
// Create a map of updated records for quick lookup
|
|
4085
4120
|
// CRITICAL FIX: Normalize IDs to strings for consistent comparison
|
|
4086
4121
|
const updatedRecordsMap = new Map()
|
|
4087
|
-
writeBufferSnapshot.forEach(record => {
|
|
4122
|
+
writeBufferSnapshot.forEach((record, index) => {
|
|
4088
4123
|
if (record && record.id !== undefined && record.id !== null) {
|
|
4089
4124
|
// Normalize ID to string for consistent comparison
|
|
4090
4125
|
const normalizedId = String(record.id)
|
|
4091
4126
|
updatedRecordsMap.set(normalizedId, record)
|
|
4127
|
+
if (this.opts.debugMode) {
|
|
4128
|
+
console.log(`💾 Save: Added to updatedRecordsMap: ID=${normalizedId} (original: ${record.id}, type: ${typeof record.id}), index=${index}`)
|
|
4129
|
+
}
|
|
4130
|
+
} else if (this.opts.debugMode) {
|
|
4131
|
+
console.log(`⚠️ Save: Skipped record in writeBufferSnapshot[${index}] - missing or invalid ID:`, record ? { id: record.id, keys: Object.keys(record) } : 'null')
|
|
4092
4132
|
}
|
|
4093
4133
|
})
|
|
4094
4134
|
|
|
4135
|
+
if (this.opts.debugMode) {
|
|
4136
|
+
console.log(`💾 Save: updatedRecordsMap size: ${updatedRecordsMap.size}, keys:`, Array.from(updatedRecordsMap.keys()))
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4095
4139
|
// OPTIMIZATION: Cache file stats to avoid repeated stat() calls
|
|
4096
4140
|
let fileSize = 0
|
|
4097
4141
|
if (this._cachedFileStats && this._cachedFileStats.timestamp > Date.now() - 1000) {
|
|
@@ -4301,11 +4345,20 @@ class Database extends EventEmitter {
|
|
|
4301
4345
|
|
|
4302
4346
|
// CRITICAL FIX: Normalize ID to string for consistent comparison
|
|
4303
4347
|
const normalizedId = String(recordWithIds.id)
|
|
4348
|
+
if (this.opts.debugMode) {
|
|
4349
|
+
console.log(`💾 Save: Checking record ID=${normalizedId} (original: ${recordWithIds.id}, type: ${typeof recordWithIds.id}) in updatedRecordsMap`)
|
|
4350
|
+
console.log(`💾 Save: updatedRecordsMap.has(${normalizedId}): ${updatedRecordsMap.has(normalizedId)}`)
|
|
4351
|
+
if (!updatedRecordsMap.has(normalizedId)) {
|
|
4352
|
+
console.log(`💾 Save: Record ${normalizedId} NOT found in updatedRecordsMap. Available keys:`, Array.from(updatedRecordsMap.keys()))
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4304
4355
|
if (updatedRecordsMap.has(normalizedId)) {
|
|
4305
4356
|
// Replace with updated version
|
|
4306
4357
|
const updatedRecord = updatedRecordsMap.get(normalizedId)
|
|
4307
4358
|
if (this.opts.debugMode) {
|
|
4308
|
-
console.log(`💾 Save:
|
|
4359
|
+
console.log(`💾 Save: ✅ REPLACING record ${recordWithIds.id} with updated version`)
|
|
4360
|
+
console.log(`💾 Save: Old record:`, { id: recordWithIds.id, price: recordWithIds.price, app_id: recordWithIds.app_id, currency: recordWithIds.currency })
|
|
4361
|
+
console.log(`💾 Save: New record:`, { id: updatedRecord.id, price: updatedRecord.price, app_id: updatedRecord.app_id, currency: updatedRecord.currency })
|
|
4309
4362
|
}
|
|
4310
4363
|
return {
|
|
4311
4364
|
type: 'updated',
|