@xyo-network/archivist-indexeddb 5.1.22 → 5.1.23

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": "@xyo-network/archivist-indexeddb",
3
- "version": "5.1.22",
3
+ "version": "5.1.23",
4
4
  "description": "Primary SDK for using XYO Protocol 2.0",
5
5
  "homepage": "https://xyo.network",
6
6
  "bugs": {
@@ -30,36 +30,39 @@
30
30
  "types": "dist/browser/index.d.ts",
31
31
  "files": [
32
32
  "dist",
33
- "src"
33
+ "src",
34
+ "!**/*.bench.*",
35
+ "!**/*.spec.*",
36
+ "!**/*.test.*"
34
37
  ],
35
38
  "dependencies": {
36
- "@xylabs/array": "~5.0.24",
37
- "@xylabs/assert": "~5.0.24",
38
- "@xylabs/exists": "~5.0.24",
39
- "@xylabs/hex": "~5.0.24",
40
- "@xylabs/indexed-db": "~5.0.24",
41
- "@xylabs/typeof": "~5.0.24",
42
- "@xyo-network/archivist-abstract": "~5.1.22",
43
- "@xyo-network/archivist-model": "~5.1.22",
44
- "@xyo-network/module-model": "~5.1.22",
45
- "@xyo-network/payload-builder": "~5.1.22",
46
- "@xyo-network/payload-model": "~5.1.22",
39
+ "@xylabs/array": "~5.0.33",
40
+ "@xylabs/assert": "~5.0.33",
41
+ "@xylabs/exists": "~5.0.33",
42
+ "@xylabs/hex": "~5.0.33",
43
+ "@xylabs/indexed-db": "~5.0.33",
44
+ "@xylabs/typeof": "~5.0.33",
45
+ "@xyo-network/archivist-abstract": "~5.1.23",
46
+ "@xyo-network/archivist-model": "~5.1.23",
47
+ "@xyo-network/module-model": "~5.1.23",
48
+ "@xyo-network/payload-builder": "~5.1.23",
49
+ "@xyo-network/payload-model": "~5.1.23",
47
50
  "idb": "~8.0.3"
48
51
  },
49
52
  "devDependencies": {
50
- "@xylabs/delay": "~5.0.24",
51
- "@xylabs/object": "~5.0.24",
53
+ "@xylabs/delay": "~5.0.33",
54
+ "@xylabs/object": "~5.0.33",
52
55
  "@xylabs/ts-scripts-yarn3": "~7.2.8",
53
56
  "@xylabs/tsconfig": "~7.2.8",
54
- "@xyo-network/account": "~5.1.22",
55
- "@xyo-network/account-model": "~5.1.22",
56
- "@xyo-network/archivist-acceptance-tests": "~5.1.22",
57
- "@xyo-network/id-payload-plugin": "~5.1.22",
58
- "@xyo-network/payload-wrapper": "~5.1.22",
57
+ "@xyo-network/account": "~5.1.23",
58
+ "@xyo-network/account-model": "~5.1.23",
59
+ "@xyo-network/archivist-acceptance-tests": "~5.1.23",
60
+ "@xyo-network/id-payload-plugin": "~5.1.23",
61
+ "@xyo-network/payload-wrapper": "~5.1.23",
59
62
  "fake-indexeddb": "~6.2.5",
60
63
  "typescript": "~5.9.3",
61
64
  "uuid": "~13.0.0",
62
- "vitest": "~4.0.8"
65
+ "vitest": "~4.0.9"
63
66
  },
64
67
  "publishConfig": {
65
68
  "access": "public"
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=Archivist.Upgrade.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Archivist.Upgrade.spec.d.ts","sourceRoot":"","sources":["../../../src/spec/Archivist.Upgrade.spec.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=Archivist.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Archivist.spec.d.ts","sourceRoot":"","sources":["../../../src/spec/Archivist.spec.ts"],"names":[],"mappings":""}
@@ -1,126 +0,0 @@
1
- import { Account } from '@xyo-network/account'
2
- import type { AccountInstance } from '@xyo-network/account-model'
3
- import type { ArchivistInstance } from '@xyo-network/archivist-model'
4
- import { IdSchema } from '@xyo-network/id-payload-plugin'
5
- import {
6
- IDBCursor,
7
- IDBCursorWithValue,
8
- IDBDatabase,
9
- IDBFactory,
10
- IDBIndex,
11
- IDBKeyRange,
12
- IDBObjectStore,
13
- IDBOpenDBRequest,
14
- IDBRequest,
15
- IDBTransaction,
16
- IDBVersionChangeEvent,
17
- indexedDB,
18
- } from 'fake-indexeddb'
19
- import {
20
- beforeAll, describe, expect, it,
21
- } from 'vitest'
22
-
23
- import { IndexedDbArchivist } from '../Archivist.ts'
24
- import type { IndexedDbArchivistConfig } from '../Config.ts'
25
- import { IndexedDbArchivistConfigSchema } from '../Config.ts'
26
-
27
- // Augment window with prototypes to ensure instance of comparisons work
28
- globalThis.IDBCursor = IDBCursor
29
- globalThis.IDBCursorWithValue = IDBCursorWithValue
30
- globalThis.IDBDatabase = IDBDatabase
31
- globalThis.IDBFactory = IDBFactory
32
- globalThis.IDBIndex = IDBIndex
33
- globalThis.IDBKeyRange = IDBKeyRange
34
- globalThis.IDBObjectStore = IDBObjectStore
35
- globalThis.IDBOpenDBRequest = IDBOpenDBRequest
36
- globalThis.IDBRequest = IDBRequest
37
- globalThis.IDBTransaction = IDBTransaction
38
- globalThis.IDBVersionChangeEvent = IDBVersionChangeEvent
39
- globalThis.indexedDB = indexedDB
40
-
41
- /**
42
- * @group module
43
- * @group archivist
44
- */
45
-
46
- const fillDb = async (db: ArchivistInstance, count: number = 10) => {
47
- const sources = Array.from({ length: count }).map((_, i) => {
48
- return { salt: `${i}`, schema: IdSchema }
49
- })
50
- for (const source of sources) {
51
- await db.insert([source])
52
- }
53
- return sources
54
- }
55
-
56
- describe.skip('IndexedDbArchivist.Upgrade', () => {
57
- let account: AccountInstance
58
- type UpgradeTestData = [oldVersion: number | undefined, newVersion: number | undefined, dbName: string, storeName: string]
59
-
60
- beforeAll(async () => {
61
- account = await Account.random()
62
- })
63
-
64
- describe('with same version specified', () => {
65
- const cases: UpgradeTestData[] = [
66
- [undefined, undefined, '4db66c75-bb44-4a80-a846-6e2b142271a2', '4ab1aaa8-c64d-4b31-af94-01a60e27c33c'],
67
- [undefined, 1, 'c2fad8ae-c11a-4136-8634-1f080ddc485f', '16eb2cf0-eedb-4802-bd51-eb228735ab25'],
68
- [1, 1, '125f20d6-410a-4c3b-b66a-ffaefe501e63', '16a755bf-5baa-480d-839b-f5adfaec6d7a'],
69
- [2, 2, '9a688c8d-18a2-4093-a107-560aafd5d256', '569ccb65-96ee-4b5d-ad20-d8556bb0b72b'],
70
- ]
71
- it.each(cases)('handles reopening', async (oldVersion, newVersion, dbName, storeName) => {
72
- const oldConfig: IndexedDbArchivistConfig = {
73
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
74
- }
75
- if (oldVersion) oldConfig.dbVersion = oldVersion
76
- let archivistModule = await IndexedDbArchivist.create({ account, config: oldConfig })
77
- expect(archivistModule).toBeDefined()
78
- // expect(archivistModule?.dbVersion).toBe(oldVersion ?? 1)
79
- const payloads = await fillDb(archivistModule)
80
- let all = await archivistModule?.all?.()
81
- expect(all?.length).toBe(payloads.length)
82
- const newConfig: IndexedDbArchivistConfig = {
83
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
84
- }
85
- if (newVersion) newConfig.dbVersion = newVersion
86
- archivistModule = await IndexedDbArchivist.create({ account, config: newConfig })
87
- expect(archivistModule).toBeDefined()
88
- // expect(archivistModule?.dbVersion).toBe(newVersion ?? 1)
89
- all = await archivistModule?.all?.()
90
- expect(all?.length).toBe(10)
91
- })
92
- })
93
- describe('with newer version specified', () => {
94
- const cases: UpgradeTestData[] = [
95
- [1, 2, '5e75de01-4b3b-416b-b1bc-4b9686cc4119', '72207e1f-5b50-4b53-a03a-21636d241599'],
96
- [2, 3, 'e371f396-0c5b-42ff-9472-04282afdef10', '5ce3bc2e-49ac-45c1-8fce-ab68961d327d'],
97
- ]
98
- it.each(cases)('handles upgrade', async (oldVersion, newVersion, dbName, storeName) => {
99
- const oldConfig: IndexedDbArchivistConfig = {
100
- dbName,
101
- schema: IndexedDbArchivistConfigSchema,
102
- storeName,
103
- storage: { indexes: [{ key: { _hash: 1 }, unique: true }] },
104
- }
105
- if (oldVersion) oldConfig.dbVersion = oldVersion
106
- let archivistModule = await IndexedDbArchivist.create({ account, config: oldConfig })
107
- expect(archivistModule).toBeDefined()
108
- // expect(archivistModule?.dbVersion).toBe(oldVersion ?? 1)
109
- const payloads = await fillDb(archivistModule)
110
- let all = await archivistModule?.all?.()
111
- expect(all?.length).toBe(payloads.length)
112
- const newConfig: IndexedDbArchivistConfig = {
113
- dbName,
114
- schema: IndexedDbArchivistConfigSchema,
115
- storeName,
116
- storage: { indexes: [{ key: { _hash: 1 }, unique: true }, { key: { _dataHash: 1 }, unique: true }] },
117
- }
118
- if (newVersion) newConfig.dbVersion = newVersion
119
- archivistModule = await IndexedDbArchivist.create({ account, config: newConfig })
120
- expect(archivistModule).toBeDefined()
121
- // expect(archivistModule?.dbVersion).toBe(newVersion ?? 1)
122
- all = await archivistModule?.all?.()
123
- expect(all?.length).toBe(10)
124
- })
125
- })
126
- })
@@ -1,462 +0,0 @@
1
- /* eslint-disable complexity */
2
- /* eslint-disable max-statements */
3
-
4
- import { delay } from '@xylabs/delay'
5
- import type { Hash } from '@xylabs/hex'
6
- import type { AnyObject } from '@xylabs/object'
7
- import { toSafeJsonString } from '@xylabs/object'
8
- import { Account } from '@xyo-network/account'
9
- import type { AccountInstance } from '@xyo-network/account-model'
10
- import { generateArchivistNextTests } from '@xyo-network/archivist-acceptance-tests'
11
- import type { ArchivistInstance } from '@xyo-network/archivist-model'
12
- import { isArchivistInstance, isArchivistModule } from '@xyo-network/archivist-model'
13
- import { IdSchema } from '@xyo-network/id-payload-plugin'
14
- import { PayloadBuilder } from '@xyo-network/payload-builder'
15
- import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
16
- import { PayloadWrapper } from '@xyo-network/payload-wrapper'
17
- import {
18
- IDBCursor,
19
- IDBCursorWithValue,
20
- IDBDatabase,
21
- IDBFactory,
22
- IDBIndex,
23
- IDBKeyRange,
24
- IDBObjectStore,
25
- IDBOpenDBRequest,
26
- IDBRequest,
27
- IDBTransaction,
28
- IDBVersionChangeEvent,
29
- indexedDB,
30
- } from 'fake-indexeddb'
31
- import { v4 } from 'uuid'
32
- import {
33
- beforeAll, describe, expect, it,
34
- } from 'vitest'
35
-
36
- import { IndexedDbArchivist } from '../Archivist.ts'
37
- import { IndexedDbArchivistConfigSchema } from '../Config.ts'
38
-
39
- /**
40
- * @group module
41
- * @group archivist
42
- */
43
- describe.skip('IndexedDbArchivist', () => {
44
- type TestPayload = Payload<{ salt: string; schema: string }>
45
-
46
- // Augment window with prototypes to ensure instance of comparisons work
47
- globalThis.IDBCursor = IDBCursor
48
- globalThis.IDBCursorWithValue = IDBCursorWithValue
49
- globalThis.IDBDatabase = IDBDatabase
50
- globalThis.IDBFactory = IDBFactory
51
- globalThis.IDBIndex = IDBIndex
52
- globalThis.IDBKeyRange = IDBKeyRange
53
- globalThis.IDBObjectStore = IDBObjectStore
54
- globalThis.IDBOpenDBRequest = IDBOpenDBRequest
55
- globalThis.IDBRequest = IDBRequest
56
- globalThis.IDBTransaction = IDBTransaction
57
- globalThis.IDBVersionChangeEvent = IDBVersionChangeEvent
58
- globalThis.indexedDB = indexedDB
59
-
60
- const fillDb = async (db: ArchivistInstance, count: number = 10): Promise<TestPayload[]> => {
61
- const sources = Array.from({ length: count }).map((_, i) => {
62
- return { salt: `${i}`, schema: IdSchema }
63
- })
64
- await db.insert(sources)
65
- return sources
66
- }
67
-
68
- const shuffleArray = <T>(original: Array<T>) => {
69
- const shuffled = [...original]
70
- for (let i = shuffled.length - 1; i > 0; i--) {
71
- // Generate a random index between 0 and i
72
- const j = Math.floor(Math.random() * (i + 1))
73
- // Swap elements at indices i and j
74
- ;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]
75
- }
76
- return shuffled
77
- }
78
- let account: AccountInstance
79
- beforeAll(async () => {
80
- account = await Account.random()
81
- })
82
- describe('config', () => {
83
- describe('dbName', () => {
84
- it('supplied via config uses config value', async () => {
85
- const dbName = 'testDbName'
86
- const archivist = await IndexedDbArchivist.create({
87
- account,
88
- config: { dbName, schema: IndexedDbArchivistConfigSchema },
89
- })
90
- expect(archivist.dbName).toBe(dbName)
91
- })
92
- it('not supplied via config uses module name', async () => {
93
- const name = 'testModuleName'
94
- const archivist = await IndexedDbArchivist.create({
95
- account,
96
- config: { name, schema: IndexedDbArchivistConfigSchema },
97
- })
98
- expect(archivist.dbName).toBe(name)
99
- })
100
- it('not supplied via config or module name uses default value', async () => {
101
- const archivist = await IndexedDbArchivist.create({ account, config: { schema: IndexedDbArchivistConfigSchema } })
102
- expect(archivist.dbName).toBe(IndexedDbArchivist.defaultDbName)
103
- })
104
- })
105
- describe('dbStore', () => {
106
- it('supplied via config uses config value', async () => {
107
- const storeName = 'testStoreName'
108
- const archivist = await IndexedDbArchivist.create({
109
- account,
110
- config: { schema: IndexedDbArchivistConfigSchema, storeName },
111
- })
112
- expect(archivist.storeName).toBe(storeName)
113
- })
114
- it('not supplied via config uses default value', async () => {
115
- const archivist = await IndexedDbArchivist.create({ account, config: { schema: IndexedDbArchivistConfigSchema } })
116
- expect(archivist.storeName).toBe(IndexedDbArchivist.defaultStoreName)
117
- })
118
- it('allows for multiple dbStores within the same dbName', async () => {
119
- const dbName = 'testDbName'
120
- const storeName1 = 'testStoreName1'
121
- const storeName2 = 'testStoreName2'
122
- const archivist1 = await IndexedDbArchivist.create({
123
- account,
124
- config: {
125
- dbName, schema: IndexedDbArchivistConfigSchema, storeName: storeName1,
126
- },
127
- })
128
- const archivist2 = await IndexedDbArchivist.create({
129
- account,
130
- config: {
131
- dbName, schema: IndexedDbArchivistConfigSchema, storeName: storeName2,
132
- },
133
- })
134
-
135
- expect(isArchivistInstance(archivist1)).toBeTruthy()
136
- expect(isArchivistModule(archivist1)).toBeTruthy()
137
-
138
- // TODO: This test is not testing the end state of indexedDB, but rather the
139
- // state of the Archivist instance and therefore isn't valid. We'd want to actually
140
- // open indexedDB and check the state of the stores matches what we want (which it doesn't).
141
- expect(archivist1.storeName).toBe(storeName1)
142
- expect(archivist2.storeName).toBe(storeName2)
143
- })
144
- })
145
- })
146
- describe('all', () => {
147
- const dbName = 'e926a178-9c6a-4604-b65c-d1fccd97f1de'
148
- const storeName = '27fcea19-c30f-415a-a7f9-0b0514705cb1'
149
- let sources: Payload[] = []
150
- let archivistModule: ArchivistInstance
151
- beforeAll(async () => {
152
- archivistModule = await IndexedDbArchivist.create({
153
- account,
154
- config: {
155
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
156
- },
157
- })
158
- sources = await fillDb(archivistModule)
159
- })
160
- it('returns all data', async () => {
161
- const getResult = await archivistModule.all?.()
162
- expect(getResult).toBeDefined()
163
- expect(getResult?.length).toBe(sources.length)
164
- expect(PayloadBuilder.omitStorageMeta(getResult)).toEqual(sources)
165
- })
166
- })
167
-
168
- describe('delete', () => {
169
- const dbName = '6e3fcd65-f24f-4ebc-b314-f597b385fb8e'
170
- const storeName = 'c0872f52-32b9-415e-8ca9-af78713cee28'
171
- let sources: Payload[] = []
172
- let archivistModule: ArchivistInstance
173
- beforeAll(async () => {
174
- archivistModule = await IndexedDbArchivist.create({
175
- account,
176
- config: {
177
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
178
- },
179
- })
180
- sources = await fillDb(archivistModule)
181
- })
182
- it('deletes data', async () => {
183
- const getResult = (await archivistModule.all?.()) ?? []
184
- expect(getResult).toBeDefined()
185
- expect(getResult?.length).toBe(sources.length)
186
- const dataHashes = (await PayloadBuilder.dataHashes(getResult)) ?? []
187
- const deleteResult = await archivistModule.delete?.(dataHashes)
188
- expect(deleteResult.length).toBe(dataHashes.length)
189
- expect((await archivistModule.all?.()).length).toBe(0)
190
- })
191
- })
192
- describe('get', () => {
193
- const dbName = 'b4379714-73d1-42c6-88e7-1a363b7ed86f'
194
- const storeName = '3dbdb153-79d0-45d0-b2f7-9f06cdd74b1e'
195
- let sources: TestPayload[] = []
196
- let archivistModule: ArchivistInstance
197
- beforeAll(async () => {
198
- archivistModule = await IndexedDbArchivist.create({
199
- account,
200
- config: {
201
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
202
- },
203
- })
204
- sources = await fillDb(archivistModule)
205
- })
206
- it('gets existing data', async () => {
207
- for (const source of sources) {
208
- const sourceHash = await PayloadBuilder.dataHash(source)
209
- const getResult = await archivistModule.get([sourceHash])
210
- expect(getResult).toBeDefined()
211
- expect(getResult.length).toBe(1)
212
- const resultHash = await PayloadWrapper.wrap(getResult[0]).dataHash()
213
- expect(resultHash).toBe(sourceHash)
214
- }
215
- })
216
- it('returned by order of insertion', async () => {
217
- const shuffled = shuffleArray(sources)
218
- const sourceHashes = await Promise.all(shuffled.map(source => PayloadBuilder.dataHash(source)))
219
- const getResult = (await archivistModule.get(sourceHashes)) as WithStorageMeta<TestPayload>[]
220
- expect(getResult).toBeDefined()
221
- expect(getResult.length).toBe(sourceHashes.length)
222
- const salts = sources.map(source => source.salt)
223
- const resultSalts = getResult.map(result => result?.salt)
224
- expect(resultSalts).toEqual(salts)
225
- })
226
- it('returns nothing for non-existing hashes', async () => {
227
- const hashThatDoesNotExist = '0000000000000000000000000000000000000000000000000000000000000000' as Hash
228
- const getResult = await archivistModule.get([hashThatDoesNotExist])
229
- expect(getResult).toBeDefined()
230
- expect(getResult.length).toBe(0)
231
- })
232
- describe('by hash', () => {
233
- let payload1: Payload<AnyObject>
234
- let payload2: Payload<AnyObject>
235
- let dataHash1: Hash
236
- let dataHash2: Hash
237
- let rootHash1: Hash
238
- let rootHash2: Hash
239
- beforeAll(async () => {
240
- const salt = '650123f6-191e-4cc4-a813-f7a29dcbfb0e'
241
- payload1 = {
242
- $some: [
243
- '12bed6aa884f5b7ffc08e19790b5db0da724b8b7471138dcbec090a0798861db0da8255f0d9297ba981b2cbbea65d9eadabac6632124f10f22c709d333a1f285',
244
- ],
245
- salt,
246
- schema: IdSchema,
247
- }
248
- payload2 = {
249
- $some: [
250
- '22bed6aa884f5b7ffc08e19790b5db0da724b8b7471138dcbec090a0798861db0da8255f0d9297ba981b2cbbea65d9eadabac6632124f10f22c709d333a1f285',
251
- ],
252
- salt,
253
- schema: IdSchema,
254
- }
255
- dataHash1 = await PayloadBuilder.dataHash(payload1)
256
- dataHash2 = await PayloadBuilder.dataHash(payload2)
257
- rootHash1 = await PayloadBuilder.hash(payload1)
258
- rootHash2 = await PayloadBuilder.hash(payload2)
259
- expect(dataHash1).toBe(dataHash2)
260
- expect(rootHash1).not.toBe(rootHash2)
261
- await archivistModule.insert([payload1])
262
- await archivistModule.insert([payload2])
263
- })
264
- describe('data hash', () => {
265
- it('returns value using hash', async () => {
266
- const result = await archivistModule.get([dataHash1])
267
- expect(result).toBeDefined()
268
- expect(result.length).toBe(1)
269
- })
270
- it('deduplicates multiple hashes', async () => {
271
- const result = await archivistModule.get([dataHash1, dataHash2])
272
- expect(result).toBeDefined()
273
- expect(result.length).toBe(1)
274
- })
275
- it('returns the any occurrence of the dataHash', async () => {
276
- // Same data hash contained by multiple root hashes
277
- const result = (await archivistModule.get([dataHash2])).pop()
278
- expect(result).toBeDefined()
279
- // Returns the first occurrence of the data hash
280
- if (result) {
281
- expect(await PayloadBuilder.dataHash(result)).toEqual(await PayloadBuilder.dataHash(payload1))
282
- }
283
- })
284
- })
285
- describe('root hash', () => {
286
- it('returns value using hash', async () => {
287
- const result = await archivistModule.get([rootHash1])
288
- expect(result).toBeDefined()
289
- expect(result.length).toBe(1)
290
- })
291
- it('deduplicates multiple hashes', async () => {
292
- const result = await archivistModule.get([rootHash1, rootHash1])
293
- expect(result).toBeDefined()
294
- expect(result.length).toBe(1)
295
- })
296
- })
297
- })
298
- })
299
- describe('insert', () => {
300
- describe('with unique data', () => {
301
- const dbName = 'bd86d2dd-dc48-4621-8c1f-105ba2e90287'
302
- const storeName = 'f8d14049-2966-4198-a2ab-1c096a949315'
303
- let sources: Payload[] = []
304
- let archivistModule: ArchivistInstance
305
- beforeAll(async () => {
306
- archivistModule = await IndexedDbArchivist.create({
307
- account,
308
- config: {
309
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
310
- },
311
- })
312
- sources = await fillDb(archivistModule)
313
- })
314
- it('can round trip data using data hash', async () => {
315
- await Promise.all(
316
- sources.map(async (source) => {
317
- const sourceHash = await PayloadBuilder.dataHash(source)
318
- const getResult = await archivistModule.get([sourceHash])
319
- expect(getResult).toBeDefined()
320
- expect(getResult.length).toBe(1)
321
- const [result] = getResult
322
- expect(PayloadBuilder.omitStorageMeta(result)).toEqual(PayloadBuilder.omitStorageMeta(source))
323
- const resultHash = await PayloadBuilder.dataHash(result)
324
- expect(resultHash).toBe(sourceHash)
325
- }),
326
- )
327
- })
328
- it('can round trip data using root hash', async () => {
329
- await Promise.all(
330
- sources.map(async (source) => {
331
- const sourceHash = await PayloadBuilder.hash(source)
332
- const getResult = await archivistModule.get([sourceHash])
333
- expect(getResult).toBeDefined()
334
- expect(getResult.length).toBe(1)
335
- const [result] = getResult
336
- expect(PayloadBuilder.omitStorageMeta(result)).toEqual(PayloadBuilder.omitStorageMeta(source))
337
- const resultHash = await PayloadBuilder.hash(result)
338
- expect(resultHash).toBe(sourceHash)
339
- }),
340
- )
341
- })
342
- })
343
- describe('with duplicate data', () => {
344
- const dbName = 'bb43b6fe-2f9e-4bda-8177-f94336353f98'
345
- const storeName = '91c6b87d-3ac8-4cfd-8aee-d509f3de0299'
346
- let archivistModule: ArchivistInstance
347
- beforeAll(async () => {
348
- archivistModule = await IndexedDbArchivist.create({
349
- account,
350
- config: {
351
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
352
- },
353
- })
354
- })
355
- it('handles duplicate insertions', async () => {
356
- // Insert same payload twice
357
- const source = { salt: '2d515e1d-d82c-4545-9903-3eded7fefa7c', schema: IdSchema }
358
- // First insertion should succeed and return the inserted payload
359
- expect((await archivistModule.insert([source]))[0]._hash).toEqual(await PayloadBuilder.hash(source))
360
- // Second insertion should succeed but return empty array since no new data was inserted
361
- expect(await archivistModule.insert([source])).toEqual([])
362
- // Ensure we can get the inserted payload
363
- const sourceHash = await PayloadBuilder.dataHash(source)
364
- const getResult = await archivistModule.get([sourceHash])
365
- expect(getResult).toBeDefined()
366
- expect(getResult.length).toBe(1)
367
- const resultHash = await PayloadBuilder.dataHash(getResult[0])
368
- expect(resultHash).toBe(sourceHash)
369
- // Ensure the DB has only one instance of the payload written to it
370
- const allResult = await archivistModule.all?.()
371
- expect(allResult).toBeDefined()
372
- expect(allResult.length).toBe(1)
373
- })
374
- })
375
- })
376
-
377
- describe('next', () => {
378
- const dbName = 'bd86d2dd-dc48-4621-8c1f-105ba2e90288'
379
- const storeName = 'f8d14049-2966-4198-a2ab-1c096a949316'
380
- it('next', async () => {
381
- const archivist = await IndexedDbArchivist.create({
382
- account: 'random',
383
- config: {
384
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
385
- },
386
- })
387
- const account = await Account.random()
388
-
389
- const payloads1 = [
390
- { schema: 'network.xyo.test', value: 1 },
391
- ]
392
-
393
- const payloads2 = [
394
- { schema: 'network.xyo.test', value: 2 },
395
- ]
396
-
397
- const payloads3 = [
398
- { schema: 'network.xyo.test', value: 3 },
399
- ]
400
-
401
- const payloads4 = [
402
- { schema: 'network.xyo.test', value: 4 },
403
- ]
404
-
405
- await archivist.insert(payloads1)
406
- await delay(1)
407
- console.log(toSafeJsonString(payloads1, 10))
408
- const [bw, payloads, errors] = await archivist.insertQuery(payloads2, account)
409
- await delay(1)
410
- await archivist.insert(payloads3)
411
- await delay(1)
412
- await archivist.insert(payloads4)
413
- await delay(1)
414
- expect(bw).toBeDefined()
415
- expect(payloads).toBeDefined()
416
- expect(errors).toBeDefined()
417
-
418
- const batch1 = await archivist.next?.({ limit: 2 })
419
- expect(batch1.length).toBe(2)
420
- expect(await PayloadBuilder.dataHash(batch1?.[0])).toEqual(await PayloadBuilder.dataHash(payloads1[0]))
421
-
422
- const batch2 = await archivist.next?.({ limit: 2, cursor: batch1?.[1]._sequence })
423
- expect(batch2.length).toBe(2)
424
- expect(await PayloadBuilder.dataHash(batch2?.[1])).toEqual(await PayloadBuilder.dataHash(payloads4[0]))
425
-
426
- const batch3 = await archivist.next?.({ limit: 20 })
427
- expect(batch3.length).toBe(4)
428
- expect(await PayloadBuilder.dataHash(batch3?.[0])).toEqual(await PayloadBuilder.dataHash(payloads1[0]))
429
-
430
- const batch4 = await archivist.next?.({ limit: 20, cursor: batch1?.[0]._sequence })
431
- expect(batch4.length).toBe(3)
432
- expect(await PayloadBuilder.dataHash(batch4?.[0])).toEqual(await PayloadBuilder.dataHash(payloads2[0]))
433
-
434
- // desc
435
- const batch1Desc = await archivist.next?.({ limit: 2, order: 'desc' })
436
- expect(batch1Desc.length).toBe(2)
437
- expect(await PayloadBuilder.dataHash(batch1Desc?.[0])).toEqual(await PayloadBuilder.dataHash(payloads4[0]))
438
-
439
- const batch2Desc = await archivist.next?.({
440
- limit: 2, cursor: batch1Desc?.[1]._sequence, order: 'desc',
441
- })
442
- expect(batch2Desc.length).toBe(2)
443
- expect(await PayloadBuilder.dataHash(batch2Desc?.[1])).toEqual(await PayloadBuilder.dataHash(payloads1[0]))
444
-
445
- const batch3Desc = await archivist.next?.({
446
- limit: 20, cursor: batch1Desc?.[1]._sequence, order: 'desc',
447
- })
448
- expect(batch3Desc.length).toBe(2)
449
- expect(await PayloadBuilder.dataHash(batch3Desc?.[1])).toEqual(await PayloadBuilder.dataHash(payloads1[0]))
450
- })
451
- })
452
- generateArchivistNextTests(async () => {
453
- const dbName = v4()
454
- const storeName = v4()
455
- return await IndexedDbArchivist.create({
456
- account,
457
- config: {
458
- dbName, schema: IndexedDbArchivistConfigSchema, storeName,
459
- },
460
- })
461
- })
462
- })