braid-blob 0.0.39 → 0.0.41
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/AI-README.md +13 -32
- package/index.js +325 -320
- package/package.json +1 -1
- package/test/tests.js +199 -78
package/package.json
CHANGED
package/test/tests.js
CHANGED
|
@@ -378,7 +378,7 @@ runTest(
|
|
|
378
378
|
|
|
379
379
|
return r.status
|
|
380
380
|
},
|
|
381
|
-
'
|
|
381
|
+
'200'
|
|
382
382
|
)
|
|
383
383
|
|
|
384
384
|
runTest(
|
|
@@ -431,45 +431,35 @@ runTest(
|
|
|
431
431
|
)
|
|
432
432
|
|
|
433
433
|
runTest(
|
|
434
|
-
"test
|
|
434
|
+
"test that aborting cleans up subscription",
|
|
435
435
|
async () => {
|
|
436
436
|
var r1 = await braid_fetch(`/eval`, {
|
|
437
437
|
method: 'POST',
|
|
438
438
|
body: `void (async () => {
|
|
439
|
-
var test_id = 'test-
|
|
440
|
-
var db_folder = __dirname + '/' + test_id + '-db'
|
|
441
|
-
var meta_folder = __dirname + '/' + test_id + '-meta'
|
|
439
|
+
var test_id = '/test-' + Math.random().toString(36).slice(2)
|
|
442
440
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
bb.meta_folder = meta_folder
|
|
441
|
+
// Put a file
|
|
442
|
+
await braid_blob.put(test_id, 'hello')
|
|
446
443
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
subscribe: (update) => { got_update = true }
|
|
455
|
-
})
|
|
444
|
+
// Subscribe to it
|
|
445
|
+
var got_update = false
|
|
446
|
+
var ac = new AbortController()
|
|
447
|
+
await braid_blob.get(test_id, {
|
|
448
|
+
signal: ac.signal,
|
|
449
|
+
subscribe: (update) => { got_update = true }
|
|
450
|
+
})
|
|
456
451
|
|
|
457
|
-
|
|
458
|
-
|
|
452
|
+
// Verify subscription exists
|
|
453
|
+
var has_sub_before = !!braid_blob.key_to_subs[test_id]
|
|
459
454
|
|
|
460
|
-
|
|
461
|
-
|
|
455
|
+
await new Promise(done => setTimeout(done, 30))
|
|
456
|
+
ac.abort()
|
|
457
|
+
await new Promise(done => setTimeout(done, 30))
|
|
462
458
|
|
|
463
|
-
|
|
464
|
-
|
|
459
|
+
// Verify subscription is cleaned up
|
|
460
|
+
var has_sub_after = !!braid_blob.key_to_subs[test_id]
|
|
465
461
|
|
|
466
|
-
|
|
467
|
-
} catch (e) {
|
|
468
|
-
res.end('error: ' + e.message)
|
|
469
|
-
} finally {
|
|
470
|
-
await require('fs').promises.rm(db_folder, { recursive: true, force: true })
|
|
471
|
-
await require('fs').promises.rm(meta_folder, { recursive: true, force: true })
|
|
472
|
-
}
|
|
462
|
+
res.end('' + (has_sub_before && !has_sub_after))
|
|
473
463
|
})()`
|
|
474
464
|
})
|
|
475
465
|
return await r1.text()
|
|
@@ -640,19 +630,6 @@ runTest(
|
|
|
640
630
|
'false'
|
|
641
631
|
)
|
|
642
632
|
|
|
643
|
-
runTest(
|
|
644
|
-
"test that subscribe sends 404 if there is no file.",
|
|
645
|
-
async () => {
|
|
646
|
-
var key = 'test-' + Math.random().toString(36).slice(2)
|
|
647
|
-
|
|
648
|
-
var r = await braid_fetch(`/${key}`, {
|
|
649
|
-
subscribe: true,
|
|
650
|
-
})
|
|
651
|
-
return r.status
|
|
652
|
-
},
|
|
653
|
-
'404'
|
|
654
|
-
)
|
|
655
|
-
|
|
656
633
|
runTest(
|
|
657
634
|
"test that we get 404 when file doesn't exist, on GET without subscribe.",
|
|
658
635
|
async () => {
|
|
@@ -1072,8 +1049,7 @@ runTest(
|
|
|
1072
1049
|
method: 'POST',
|
|
1073
1050
|
body: `void (async () => {
|
|
1074
1051
|
try {
|
|
1075
|
-
var
|
|
1076
|
-
var remote_url = new URL('http://localhost:' + req.socket.localPort + '${remote_key}')
|
|
1052
|
+
var remote_url = new URL('http://localhost:' + port + '${remote_key}')
|
|
1077
1053
|
|
|
1078
1054
|
// Start sync with URL as first argument (should swap internally)
|
|
1079
1055
|
braid_blob.sync(remote_url, '${local_key}')
|
|
@@ -1165,10 +1141,8 @@ runTest(
|
|
|
1165
1141
|
method: 'POST',
|
|
1166
1142
|
body: `void (async () => {
|
|
1167
1143
|
try {
|
|
1168
|
-
var braid_blob = require(\`\${__dirname}/../index.js\`)
|
|
1169
|
-
|
|
1170
1144
|
// Put locally with SAME version - so when sync connects, no updates need to flow
|
|
1171
|
-
await braid_blob.put('${local_key}',
|
|
1145
|
+
await braid_blob.put('${local_key}', 'same content', { version: ['same-version-123'] })
|
|
1172
1146
|
|
|
1173
1147
|
// Wrap db.read to count calls for our specific key
|
|
1174
1148
|
var read_count = 0
|
|
@@ -1178,7 +1152,7 @@ runTest(
|
|
|
1178
1152
|
return original_read.call(this, key)
|
|
1179
1153
|
}
|
|
1180
1154
|
|
|
1181
|
-
var remote_url = new URL('http://localhost:' +
|
|
1155
|
+
var remote_url = new URL('http://localhost:' + port + '/${remote_key}')
|
|
1182
1156
|
|
|
1183
1157
|
// Create an AbortController to stop the sync
|
|
1184
1158
|
var ac = new AbortController()
|
|
@@ -1305,7 +1279,6 @@ runTest(
|
|
|
1305
1279
|
// Try to subscribe with parents 200 (newer than what server has)
|
|
1306
1280
|
// This triggers the "unknown version" error which gets caught and returns 309
|
|
1307
1281
|
var r = await braid_fetch(`/${key}`, {
|
|
1308
|
-
subscribe: true,
|
|
1309
1282
|
parents: ['200']
|
|
1310
1283
|
})
|
|
1311
1284
|
|
|
@@ -1537,38 +1510,22 @@ runTest(
|
|
|
1537
1510
|
var r1 = await braid_fetch(`/eval`, {
|
|
1538
1511
|
method: 'POST',
|
|
1539
1512
|
body: `void (async () => {
|
|
1540
|
-
var
|
|
1541
|
-
var test_id = 'test-abort-get-' + Math.random().toString(36).slice(2)
|
|
1542
|
-
var db_folder = __dirname + '/' + test_id + '-db'
|
|
1543
|
-
var meta_folder = __dirname + '/' + test_id + '-meta'
|
|
1513
|
+
var test_id = '/test-abort-get-' + Math.random().toString(36).slice(2)
|
|
1544
1514
|
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
bb.db_folder = db_folder
|
|
1548
|
-
bb.meta_folder = meta_folder
|
|
1549
|
-
|
|
1550
|
-
// Put a file first
|
|
1551
|
-
await bb.put('/test-file', Buffer.from('hello'), { version: ['1'] })
|
|
1515
|
+
// Put a file first
|
|
1516
|
+
await braid_blob.put(test_id, 'hello', { version: ['1'] })
|
|
1552
1517
|
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1518
|
+
// Create an already-aborted signal
|
|
1519
|
+
var ac = new AbortController()
|
|
1520
|
+
ac.abort()
|
|
1556
1521
|
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
header_cb: () => { header_called = true }
|
|
1562
|
-
})
|
|
1522
|
+
// Try to get with aborted signal (after header_cb)
|
|
1523
|
+
var result = await braid_blob.get(test_id, {
|
|
1524
|
+
signal: ac.signal,
|
|
1525
|
+
})
|
|
1563
1526
|
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
} catch (e) {
|
|
1567
|
-
res.end('error: ' + e.message)
|
|
1568
|
-
} finally {
|
|
1569
|
-
await fs.rm(db_folder, { recursive: true, force: true })
|
|
1570
|
-
await fs.rm(meta_folder, { recursive: true, force: true })
|
|
1571
|
-
}
|
|
1527
|
+
// Result should be undefined since operation was aborted already
|
|
1528
|
+
res.end(result === undefined ? 'aborted' : 'not aborted')
|
|
1572
1529
|
})()`
|
|
1573
1530
|
})
|
|
1574
1531
|
return await r1.text()
|
|
@@ -1678,6 +1635,170 @@ runTest(
|
|
|
1678
1635
|
'stopped'
|
|
1679
1636
|
)
|
|
1680
1637
|
|
|
1638
|
+
runTest(
|
|
1639
|
+
"test options.db in put writes to custom db",
|
|
1640
|
+
async () => {
|
|
1641
|
+
var r1 = await braid_fetch(`/eval`, {
|
|
1642
|
+
method: 'POST',
|
|
1643
|
+
body: `void (async () => {
|
|
1644
|
+
var test_key = '/test-custom-db-put-' + Math.random().toString(36).slice(2)
|
|
1645
|
+
|
|
1646
|
+
// Create a simple in-memory db
|
|
1647
|
+
var custom_storage = {}
|
|
1648
|
+
var custom_db = {
|
|
1649
|
+
read: async (key) => custom_storage[key] || null,
|
|
1650
|
+
write: async (key, data) => { custom_storage[key] = data },
|
|
1651
|
+
delete: async (key) => { delete custom_storage[key] }
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
// Put using the custom db
|
|
1655
|
+
await braid_blob.put(test_key, Buffer.from('custom db content'), {
|
|
1656
|
+
version: ['100'],
|
|
1657
|
+
db: custom_db
|
|
1658
|
+
})
|
|
1659
|
+
|
|
1660
|
+
// Verify content is in custom db
|
|
1661
|
+
var custom_content = await custom_db.read(test_key)
|
|
1662
|
+
var custom_ok = custom_content && custom_content.toString() === 'custom db content'
|
|
1663
|
+
|
|
1664
|
+
// Verify content is NOT in the default db
|
|
1665
|
+
var default_content = await braid_blob.db.read(test_key)
|
|
1666
|
+
var default_empty = default_content === null
|
|
1667
|
+
|
|
1668
|
+
res.end(custom_ok && default_empty ? 'true' :
|
|
1669
|
+
'custom_ok=' + custom_ok + ', default_empty=' + default_empty)
|
|
1670
|
+
})()`
|
|
1671
|
+
})
|
|
1672
|
+
return await r1.text()
|
|
1673
|
+
},
|
|
1674
|
+
'true'
|
|
1675
|
+
)
|
|
1676
|
+
|
|
1677
|
+
runTest(
|
|
1678
|
+
"test options.db in get reads from custom db",
|
|
1679
|
+
async () => {
|
|
1680
|
+
var r1 = await braid_fetch(`/eval`, {
|
|
1681
|
+
method: 'POST',
|
|
1682
|
+
body: `void (async () => {
|
|
1683
|
+
var test_key = '/test-custom-db-get-' + Math.random().toString(36).slice(2)
|
|
1684
|
+
|
|
1685
|
+
// Create a simple in-memory db with some content
|
|
1686
|
+
var custom_storage = {}
|
|
1687
|
+
custom_storage[test_key] = Buffer.from('from custom db')
|
|
1688
|
+
var custom_db = {
|
|
1689
|
+
read: async (key) => custom_storage[key] || null,
|
|
1690
|
+
write: async (key, data) => { custom_storage[key] = data },
|
|
1691
|
+
delete: async (key) => { delete custom_storage[key] }
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// Put with skip_write to just create meta
|
|
1695
|
+
await braid_blob.put(test_key, Buffer.from('ignored'), {
|
|
1696
|
+
version: ['200'],
|
|
1697
|
+
skip_write: true
|
|
1698
|
+
})
|
|
1699
|
+
|
|
1700
|
+
// Get using the custom db - should read from custom db
|
|
1701
|
+
var result = await braid_blob.get(test_key, { db: custom_db })
|
|
1702
|
+
|
|
1703
|
+
res.end(result && result.body.toString() === 'from custom db' ? 'true' :
|
|
1704
|
+
'got: ' + (result ? result.body.toString() : 'null'))
|
|
1705
|
+
})()`
|
|
1706
|
+
})
|
|
1707
|
+
return await r1.text()
|
|
1708
|
+
},
|
|
1709
|
+
'true'
|
|
1710
|
+
)
|
|
1711
|
+
|
|
1712
|
+
runTest(
|
|
1713
|
+
"test options.db in delete deletes from custom db",
|
|
1714
|
+
async () => {
|
|
1715
|
+
var r1 = await braid_fetch(`/eval`, {
|
|
1716
|
+
method: 'POST',
|
|
1717
|
+
body: `void (async () => {
|
|
1718
|
+
var test_key = '/test-custom-db-delete-' + Math.random().toString(36).slice(2)
|
|
1719
|
+
|
|
1720
|
+
// Create a simple in-memory db
|
|
1721
|
+
var custom_storage = {}
|
|
1722
|
+
custom_storage[test_key] = Buffer.from('custom content')
|
|
1723
|
+
var custom_db = {
|
|
1724
|
+
read: async (key) => custom_storage[key] || null,
|
|
1725
|
+
write: async (key, data) => { custom_storage[key] = data },
|
|
1726
|
+
delete: async (key) => { delete custom_storage[key] }
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
// Also put to default db
|
|
1730
|
+
await braid_blob.put(test_key, Buffer.from('default content'), {
|
|
1731
|
+
version: ['300']
|
|
1732
|
+
})
|
|
1733
|
+
|
|
1734
|
+
// Delete using custom db - should only delete from custom db
|
|
1735
|
+
await braid_blob.delete(test_key, { db: custom_db })
|
|
1736
|
+
|
|
1737
|
+
// Verify custom db content is gone
|
|
1738
|
+
var custom_content = await custom_db.read(test_key)
|
|
1739
|
+
var custom_deleted = custom_content === null
|
|
1740
|
+
|
|
1741
|
+
// Verify default db content still exists
|
|
1742
|
+
var default_content = await braid_blob.db.read(test_key)
|
|
1743
|
+
var default_exists = default_content && default_content.toString() === 'default content'
|
|
1744
|
+
|
|
1745
|
+
res.end(custom_deleted && default_exists ? 'true' :
|
|
1746
|
+
'custom_deleted=' + custom_deleted + ', default_exists=' + default_exists)
|
|
1747
|
+
})()`
|
|
1748
|
+
})
|
|
1749
|
+
return await r1.text()
|
|
1750
|
+
},
|
|
1751
|
+
'true'
|
|
1752
|
+
)
|
|
1753
|
+
|
|
1754
|
+
runTest(
|
|
1755
|
+
"test options.db in get subscribe uses custom db for initial update",
|
|
1756
|
+
async () => {
|
|
1757
|
+
var r1 = await braid_fetch(`/eval`, {
|
|
1758
|
+
method: 'POST',
|
|
1759
|
+
body: `void (async () => {
|
|
1760
|
+
var test_key = '/test-custom-db-sub-' + Math.random().toString(36).slice(2)
|
|
1761
|
+
|
|
1762
|
+
// Create a simple in-memory db with content
|
|
1763
|
+
var custom_storage = {}
|
|
1764
|
+
custom_storage[test_key] = Buffer.from('subscribe custom content')
|
|
1765
|
+
var custom_db = {
|
|
1766
|
+
read: async (key) => custom_storage[key] || null,
|
|
1767
|
+
write: async (key, data) => { custom_storage[key] = data },
|
|
1768
|
+
delete: async (key) => { delete custom_storage[key] }
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
// Create meta with version using skip_write
|
|
1772
|
+
await braid_blob.put(test_key, Buffer.from('ignored'), {
|
|
1773
|
+
version: ['400'],
|
|
1774
|
+
skip_write: true
|
|
1775
|
+
})
|
|
1776
|
+
|
|
1777
|
+
// Subscribe using custom db - initial update should come from custom db
|
|
1778
|
+
var ac = new AbortController()
|
|
1779
|
+
var received_content = null
|
|
1780
|
+
|
|
1781
|
+
await braid_blob.get(test_key, {
|
|
1782
|
+
db: custom_db,
|
|
1783
|
+
signal: ac.signal,
|
|
1784
|
+
subscribe: (update) => {
|
|
1785
|
+
received_content = update.body.toString()
|
|
1786
|
+
}
|
|
1787
|
+
})
|
|
1788
|
+
|
|
1789
|
+
// Wait for update
|
|
1790
|
+
await new Promise(done => setTimeout(done, 50))
|
|
1791
|
+
ac.abort()
|
|
1792
|
+
|
|
1793
|
+
res.end(received_content === 'subscribe custom content' ? 'true' :
|
|
1794
|
+
'got: ' + received_content)
|
|
1795
|
+
})()`
|
|
1796
|
+
})
|
|
1797
|
+
return await r1.text()
|
|
1798
|
+
},
|
|
1799
|
+
'true'
|
|
1800
|
+
)
|
|
1801
|
+
|
|
1681
1802
|
}
|
|
1682
1803
|
|
|
1683
1804
|
// Export for Node.js (CommonJS)
|