@kingsy/objectloader2 2.25.7
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/.tshy/build.json +8 -0
- package/.tshy/commonjs.json +17 -0
- package/.tshy/esm.json +16 -0
- package/dist/commonjs/helpers/aggregateQueue.d.ts +8 -0
- package/dist/commonjs/helpers/aggregateQueue.d.ts.map +1 -0
- package/dist/commonjs/helpers/aggregateQueue.js +19 -0
- package/dist/commonjs/helpers/aggregateQueue.js.map +1 -0
- package/dist/commonjs/helpers/asyncGeneratorQueue.d.ts +8 -0
- package/dist/commonjs/helpers/asyncGeneratorQueue.d.ts.map +1 -0
- package/dist/commonjs/helpers/asyncGeneratorQueue.js +35 -0
- package/dist/commonjs/helpers/asyncGeneratorQueue.js.map +1 -0
- package/dist/commonjs/helpers/batchedPool.d.ts +12 -0
- package/dist/commonjs/helpers/batchedPool.d.ts.map +1 -0
- package/dist/commonjs/helpers/batchedPool.js +45 -0
- package/dist/commonjs/helpers/batchedPool.js.map +1 -0
- package/dist/commonjs/helpers/batchingQueue.d.ts +14 -0
- package/dist/commonjs/helpers/batchingQueue.d.ts.map +1 -0
- package/dist/commonjs/helpers/batchingQueue.js +77 -0
- package/dist/commonjs/helpers/batchingQueue.js.map +1 -0
- package/dist/commonjs/helpers/bufferQueue.d.ts +7 -0
- package/dist/commonjs/helpers/bufferQueue.d.ts.map +1 -0
- package/dist/commonjs/helpers/bufferQueue.js +13 -0
- package/dist/commonjs/helpers/bufferQueue.js.map +1 -0
- package/dist/commonjs/helpers/cachePump.d.ts +22 -0
- package/dist/commonjs/helpers/cachePump.d.ts.map +1 -0
- package/dist/commonjs/helpers/cachePump.js +86 -0
- package/dist/commonjs/helpers/cachePump.js.map +1 -0
- package/dist/commonjs/helpers/cacheReader.d.ts +14 -0
- package/dist/commonjs/helpers/cacheReader.d.ts.map +1 -0
- package/dist/commonjs/helpers/cacheReader.js +58 -0
- package/dist/commonjs/helpers/cacheReader.js.map +1 -0
- package/dist/commonjs/helpers/defermentManager.d.ts +28 -0
- package/dist/commonjs/helpers/defermentManager.d.ts.map +1 -0
- package/dist/commonjs/helpers/defermentManager.js +150 -0
- package/dist/commonjs/helpers/defermentManager.js.map +1 -0
- package/dist/commonjs/helpers/deferredBase.d.ts +19 -0
- package/dist/commonjs/helpers/deferredBase.d.ts.map +1 -0
- package/dist/commonjs/helpers/deferredBase.js +51 -0
- package/dist/commonjs/helpers/deferredBase.js.map +1 -0
- package/dist/commonjs/helpers/keyedQueue.d.ts +11 -0
- package/dist/commonjs/helpers/keyedQueue.d.ts.map +1 -0
- package/dist/commonjs/helpers/keyedQueue.js +41 -0
- package/dist/commonjs/helpers/keyedQueue.js.map +1 -0
- package/dist/commonjs/helpers/memoryPump.d.ts +15 -0
- package/dist/commonjs/helpers/memoryPump.d.ts.map +1 -0
- package/dist/commonjs/helpers/memoryPump.js +34 -0
- package/dist/commonjs/helpers/memoryPump.js.map +1 -0
- package/dist/commonjs/helpers/pump.d.ts +8 -0
- package/dist/commonjs/helpers/pump.d.ts.map +1 -0
- package/dist/commonjs/helpers/pump.js +3 -0
- package/dist/commonjs/helpers/pump.js.map +1 -0
- package/dist/commonjs/helpers/queue.d.ts +4 -0
- package/dist/commonjs/helpers/queue.d.ts.map +1 -0
- package/dist/commonjs/helpers/queue.js +3 -0
- package/dist/commonjs/helpers/queue.js.map +1 -0
- package/dist/commonjs/index.d.ts +3 -0
- package/dist/commonjs/index.d.ts.map +1 -0
- package/dist/commonjs/index.js +8 -0
- package/dist/commonjs/index.js.map +1 -0
- package/dist/commonjs/operations/databases/indexedDatabase.d.ts +27 -0
- package/dist/commonjs/operations/databases/indexedDatabase.d.ts.map +1 -0
- package/dist/commonjs/operations/databases/indexedDatabase.js +98 -0
- package/dist/commonjs/operations/databases/indexedDatabase.js.map +1 -0
- package/dist/commonjs/operations/databases/memoryDatabase.d.ts +13 -0
- package/dist/commonjs/operations/databases/memoryDatabase.d.ts.map +1 -0
- package/dist/commonjs/operations/databases/memoryDatabase.js +33 -0
- package/dist/commonjs/operations/databases/memoryDatabase.js.map +1 -0
- package/dist/commonjs/operations/downloaders/memoryDownloader.d.ts +16 -0
- package/dist/commonjs/operations/downloaders/memoryDownloader.d.ts.map +1 -0
- package/dist/commonjs/operations/downloaders/memoryDownloader.js +35 -0
- package/dist/commonjs/operations/downloaders/memoryDownloader.js.map +1 -0
- package/dist/commonjs/operations/downloaders/serverDownloader.d.ts +32 -0
- package/dist/commonjs/operations/downloaders/serverDownloader.d.ts.map +1 -0
- package/dist/commonjs/operations/downloaders/serverDownloader.js +169 -0
- package/dist/commonjs/operations/downloaders/serverDownloader.js.map +1 -0
- package/dist/commonjs/operations/interfaces.d.ts +19 -0
- package/dist/commonjs/operations/interfaces.d.ts.map +1 -0
- package/dist/commonjs/operations/interfaces.js +3 -0
- package/dist/commonjs/operations/interfaces.js.map +1 -0
- package/dist/commonjs/operations/objectLoader2.d.ts +16 -0
- package/dist/commonjs/operations/objectLoader2.d.ts.map +1 -0
- package/dist/commonjs/operations/objectLoader2.js +101 -0
- package/dist/commonjs/operations/objectLoader2.js.map +1 -0
- package/dist/commonjs/operations/objectLoader2Factory.d.ts +25 -0
- package/dist/commonjs/operations/objectLoader2Factory.d.ts.map +1 -0
- package/dist/commonjs/operations/objectLoader2Factory.js +68 -0
- package/dist/commonjs/operations/objectLoader2Factory.js.map +1 -0
- package/dist/commonjs/operations/options.d.ts +26 -0
- package/dist/commonjs/operations/options.d.ts.map +1 -0
- package/dist/commonjs/operations/options.js +3 -0
- package/dist/commonjs/operations/options.js.map +1 -0
- package/dist/commonjs/operations/traverser.d.ts +19 -0
- package/dist/commonjs/operations/traverser.d.ts.map +1 -0
- package/dist/commonjs/operations/traverser.js +96 -0
- package/dist/commonjs/operations/traverser.js.map +1 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types/errors.d.ts +21 -0
- package/dist/commonjs/types/errors.d.ts.map +1 -0
- package/dist/commonjs/types/errors.js +28 -0
- package/dist/commonjs/types/errors.js.map +1 -0
- package/dist/commonjs/types/types.d.ts +25 -0
- package/dist/commonjs/types/types.d.ts.map +1 -0
- package/dist/commonjs/types/types.js +39 -0
- package/dist/commonjs/types/types.js.map +1 -0
- package/dist/esm/helpers/aggregateQueue.d.ts +8 -0
- package/dist/esm/helpers/aggregateQueue.d.ts.map +1 -0
- package/dist/esm/helpers/aggregateQueue.js +16 -0
- package/dist/esm/helpers/aggregateQueue.js.map +1 -0
- package/dist/esm/helpers/asyncGeneratorQueue.d.ts +8 -0
- package/dist/esm/helpers/asyncGeneratorQueue.d.ts.map +1 -0
- package/dist/esm/helpers/asyncGeneratorQueue.js +32 -0
- package/dist/esm/helpers/asyncGeneratorQueue.js.map +1 -0
- package/dist/esm/helpers/batchedPool.d.ts +12 -0
- package/dist/esm/helpers/batchedPool.d.ts.map +1 -0
- package/dist/esm/helpers/batchedPool.js +42 -0
- package/dist/esm/helpers/batchedPool.js.map +1 -0
- package/dist/esm/helpers/batchingQueue.d.ts +14 -0
- package/dist/esm/helpers/batchingQueue.d.ts.map +1 -0
- package/dist/esm/helpers/batchingQueue.js +71 -0
- package/dist/esm/helpers/batchingQueue.js.map +1 -0
- package/dist/esm/helpers/bufferQueue.d.ts +7 -0
- package/dist/esm/helpers/bufferQueue.d.ts.map +1 -0
- package/dist/esm/helpers/bufferQueue.js +10 -0
- package/dist/esm/helpers/bufferQueue.js.map +1 -0
- package/dist/esm/helpers/cachePump.d.ts +22 -0
- package/dist/esm/helpers/cachePump.d.ts.map +1 -0
- package/dist/esm/helpers/cachePump.js +79 -0
- package/dist/esm/helpers/cachePump.js.map +1 -0
- package/dist/esm/helpers/cacheReader.d.ts +14 -0
- package/dist/esm/helpers/cacheReader.d.ts.map +1 -0
- package/dist/esm/helpers/cacheReader.js +51 -0
- package/dist/esm/helpers/cacheReader.js.map +1 -0
- package/dist/esm/helpers/defermentManager.d.ts +28 -0
- package/dist/esm/helpers/defermentManager.d.ts.map +1 -0
- package/dist/esm/helpers/defermentManager.js +146 -0
- package/dist/esm/helpers/defermentManager.js.map +1 -0
- package/dist/esm/helpers/deferredBase.d.ts +19 -0
- package/dist/esm/helpers/deferredBase.d.ts.map +1 -0
- package/dist/esm/helpers/deferredBase.js +47 -0
- package/dist/esm/helpers/deferredBase.js.map +1 -0
- package/dist/esm/helpers/keyedQueue.d.ts +11 -0
- package/dist/esm/helpers/keyedQueue.d.ts.map +1 -0
- package/dist/esm/helpers/keyedQueue.js +38 -0
- package/dist/esm/helpers/keyedQueue.js.map +1 -0
- package/dist/esm/helpers/memoryPump.d.ts +15 -0
- package/dist/esm/helpers/memoryPump.d.ts.map +1 -0
- package/dist/esm/helpers/memoryPump.js +30 -0
- package/dist/esm/helpers/memoryPump.js.map +1 -0
- package/dist/esm/helpers/pump.d.ts +8 -0
- package/dist/esm/helpers/pump.d.ts.map +1 -0
- package/dist/esm/helpers/pump.js +2 -0
- package/dist/esm/helpers/pump.js.map +1 -0
- package/dist/esm/helpers/queue.d.ts +4 -0
- package/dist/esm/helpers/queue.d.ts.map +1 -0
- package/dist/esm/helpers/queue.js +2 -0
- package/dist/esm/helpers/queue.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/operations/databases/indexedDatabase.d.ts +27 -0
- package/dist/esm/operations/databases/indexedDatabase.d.ts.map +1 -0
- package/dist/esm/operations/databases/indexedDatabase.js +93 -0
- package/dist/esm/operations/databases/indexedDatabase.js.map +1 -0
- package/dist/esm/operations/databases/memoryDatabase.d.ts +13 -0
- package/dist/esm/operations/databases/memoryDatabase.d.ts.map +1 -0
- package/dist/esm/operations/databases/memoryDatabase.js +29 -0
- package/dist/esm/operations/databases/memoryDatabase.js.map +1 -0
- package/dist/esm/operations/downloaders/memoryDownloader.d.ts +16 -0
- package/dist/esm/operations/downloaders/memoryDownloader.d.ts.map +1 -0
- package/dist/esm/operations/downloaders/memoryDownloader.js +31 -0
- package/dist/esm/operations/downloaders/memoryDownloader.js.map +1 -0
- package/dist/esm/operations/downloaders/serverDownloader.d.ts +32 -0
- package/dist/esm/operations/downloaders/serverDownloader.d.ts.map +1 -0
- package/dist/esm/operations/downloaders/serverDownloader.js +163 -0
- package/dist/esm/operations/downloaders/serverDownloader.js.map +1 -0
- package/dist/esm/operations/interfaces.d.ts +19 -0
- package/dist/esm/operations/interfaces.d.ts.map +1 -0
- package/dist/esm/operations/interfaces.js +2 -0
- package/dist/esm/operations/interfaces.js.map +1 -0
- package/dist/esm/operations/objectLoader2.d.ts +16 -0
- package/dist/esm/operations/objectLoader2.d.ts.map +1 -0
- package/dist/esm/operations/objectLoader2.js +94 -0
- package/dist/esm/operations/objectLoader2.js.map +1 -0
- package/dist/esm/operations/objectLoader2Factory.d.ts +25 -0
- package/dist/esm/operations/objectLoader2Factory.d.ts.map +1 -0
- package/dist/esm/operations/objectLoader2Factory.js +61 -0
- package/dist/esm/operations/objectLoader2Factory.js.map +1 -0
- package/dist/esm/operations/options.d.ts +26 -0
- package/dist/esm/operations/options.d.ts.map +1 -0
- package/dist/esm/operations/options.js +2 -0
- package/dist/esm/operations/options.js.map +1 -0
- package/dist/esm/operations/traverser.d.ts +19 -0
- package/dist/esm/operations/traverser.d.ts.map +1 -0
- package/dist/esm/operations/traverser.js +93 -0
- package/dist/esm/operations/traverser.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types/errors.d.ts +21 -0
- package/dist/esm/types/errors.d.ts.map +1 -0
- package/dist/esm/types/errors.js +23 -0
- package/dist/esm/types/errors.js.map +1 -0
- package/dist/esm/types/types.d.ts +25 -0
- package/dist/esm/types/types.d.ts.map +1 -0
- package/dist/esm/types/types.js +33 -0
- package/dist/esm/types/types.js.map +1 -0
- package/eslint.config.mjs +60 -0
- package/package.json +76 -0
- package/readme.md +42 -0
- package/src/helpers/__snapshots__/cachePump.spec.ts.snap +31 -0
- package/src/helpers/__snapshots__/cacheReader.spec.ts.snap +8 -0
- package/src/helpers/__snapshots__/defermentManager.spec.ts.snap +8 -0
- package/src/helpers/aggregateQueue.ts +20 -0
- package/src/helpers/asyncGeneratorQueue.ts +35 -0
- package/src/helpers/batchedPool.ts +56 -0
- package/src/helpers/batchingQueue.ts +85 -0
- package/src/helpers/bufferQueue.ts +12 -0
- package/src/helpers/cachePump.disposal.spec.ts +51 -0
- package/src/helpers/cachePump.spec.ts +104 -0
- package/src/helpers/cachePump.ts +107 -0
- package/src/helpers/cacheReader.spec.ts +35 -0
- package/src/helpers/cacheReader.ts +64 -0
- package/src/helpers/defermentManager.defermentTotals.spec.ts +53 -0
- package/src/helpers/defermentManager.disposal.spec.ts +28 -0
- package/src/helpers/defermentManager.spec.ts +37 -0
- package/src/helpers/defermentManager.ts +160 -0
- package/src/helpers/deferredBase.ts +55 -0
- package/src/helpers/keyedQueue.ts +45 -0
- package/src/helpers/memoryPump.ts +40 -0
- package/src/helpers/pump.ts +8 -0
- package/src/helpers/queue.ts +3 -0
- package/src/index.ts +2 -0
- package/src/operations/__snapshots__/objectLoader2.spec.ts.snap +149 -0
- package/src/operations/__snapshots__/traverser.spec.ts.snap +45 -0
- package/src/operations/databases/__snapshots__/indexedDatabase.spec.ts.snap +18 -0
- package/src/operations/databases/indexedDatabase.spec.ts +33 -0
- package/src/operations/databases/indexedDatabase.ts +126 -0
- package/src/operations/databases/memoryDatabase.spec.ts +48 -0
- package/src/operations/databases/memoryDatabase.ts +35 -0
- package/src/operations/downloaders/__snapshots__/memoryDownloader.spec.ts.snap +12 -0
- package/src/operations/downloaders/__snapshots__/serverDownloader.spec.ts.snap +92 -0
- package/src/operations/downloaders/memoryDownloader.spec.ts +49 -0
- package/src/operations/downloaders/memoryDownloader.ts +39 -0
- package/src/operations/downloaders/serverDownloader.spec.ts +161 -0
- package/src/operations/downloaders/serverDownloader.ts +217 -0
- package/src/operations/interfaces.ts +18 -0
- package/src/operations/objectLoader2.spec.ts +229 -0
- package/src/operations/objectLoader2.ts +119 -0
- package/src/operations/objectLoader2Factory.ts +78 -0
- package/src/operations/options.ts +29 -0
- package/src/operations/traverser.spec.ts +58 -0
- package/src/operations/traverser.ts +112 -0
- package/src/test/e2e.spec.ts +43 -0
- package/src/types/errors.ts +25 -0
- package/src/types/types.ts +71 -0
- package/tsconfig.json +103 -0
- package/vitest.config.ts +3 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { ObjectLoader2 } from './objectLoader2.js'
|
|
3
|
+
import { Base, Item } from '../types/types.js'
|
|
4
|
+
import { MemoryDownloader } from './downloaders/memoryDownloader.js'
|
|
5
|
+
import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
|
|
6
|
+
import { MemoryDatabase } from './databases/memoryDatabase.js'
|
|
7
|
+
import IndexedDatabase from './databases/indexedDatabase.js'
|
|
8
|
+
|
|
9
|
+
describe('objectloader2', () => {
|
|
10
|
+
test('can get a root object from cache', async () => {
|
|
11
|
+
const rootId = 'baseId'
|
|
12
|
+
const rootBase: Base = { id: 'baseId', kingsy_type: 'type' }
|
|
13
|
+
const downloader = new MemoryDownloader(
|
|
14
|
+
rootId,
|
|
15
|
+
new Map<string, Base>([[rootId, rootBase]])
|
|
16
|
+
)
|
|
17
|
+
const loader = new ObjectLoader2({
|
|
18
|
+
rootId,
|
|
19
|
+
downloader,
|
|
20
|
+
database: new IndexedDatabase({
|
|
21
|
+
indexedDB: new IDBFactory(),
|
|
22
|
+
keyRange: IDBKeyRange
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
const x = await loader.getRootObject()
|
|
26
|
+
expect(x).toMatchSnapshot()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('can get a root object from downloader', async () => {
|
|
30
|
+
const rootId = 'baseId'
|
|
31
|
+
const rootBase: Base = { id: 'baseId', kingsy_type: 'type' }
|
|
32
|
+
const downloader = new MemoryDownloader(
|
|
33
|
+
rootId,
|
|
34
|
+
new Map<string, Base>([[rootId, rootBase]])
|
|
35
|
+
)
|
|
36
|
+
const loader = new ObjectLoader2({
|
|
37
|
+
rootId,
|
|
38
|
+
downloader,
|
|
39
|
+
database: new IndexedDatabase({
|
|
40
|
+
indexedDB: new IDBFactory(),
|
|
41
|
+
keyRange: IDBKeyRange
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
const x = await loader.getRootObject()
|
|
45
|
+
expect(x).toMatchSnapshot()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('can get single object from cache using iterator', async () => {
|
|
49
|
+
const rootId = 'baseId'
|
|
50
|
+
const rootBase: Base = { id: 'baseId', kingsy_type: 'type' }
|
|
51
|
+
|
|
52
|
+
const downloader = new MemoryDownloader(
|
|
53
|
+
rootId,
|
|
54
|
+
new Map<string, Base>([[rootId, rootBase]])
|
|
55
|
+
)
|
|
56
|
+
const loader = new ObjectLoader2({
|
|
57
|
+
rootId,
|
|
58
|
+
downloader,
|
|
59
|
+
database: new IndexedDatabase({
|
|
60
|
+
indexedDB: new IDBFactory(),
|
|
61
|
+
keyRange: IDBKeyRange
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
const r = []
|
|
65
|
+
for await (const x of loader.getObjectIterator()) {
|
|
66
|
+
r.push(x)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
expect(r).toMatchSnapshot()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('can get root/child object from memory cache using iterator and getObject', async () => {
|
|
73
|
+
const child1Base = { id: 'child1Id', kingsy_type: 'type' } as Base
|
|
74
|
+
const child1 = { baseId: 'child1Id', base: child1Base } as unknown as Item
|
|
75
|
+
|
|
76
|
+
const rootId = 'rootId'
|
|
77
|
+
const rootBase: Base = {
|
|
78
|
+
id: 'rootId',
|
|
79
|
+
kingsy_type: 'type',
|
|
80
|
+
__closure: { child1Id: 100 }
|
|
81
|
+
}
|
|
82
|
+
const root = {
|
|
83
|
+
baseId: rootId,
|
|
84
|
+
base: rootBase
|
|
85
|
+
} as Item
|
|
86
|
+
|
|
87
|
+
const records: Map<string, Base> = new Map<string, Base>()
|
|
88
|
+
records.set(root.baseId, rootBase)
|
|
89
|
+
records.set(child1.baseId, child1Base)
|
|
90
|
+
|
|
91
|
+
const loader = new ObjectLoader2({
|
|
92
|
+
rootId: root.baseId,
|
|
93
|
+
downloader: new MemoryDownloader(rootId, records),
|
|
94
|
+
database: new MemoryDatabase({ items: records })
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const r = []
|
|
98
|
+
const obj = loader.getObject({ id: child1.baseId })
|
|
99
|
+
for await (const x of loader.getObjectIterator()) {
|
|
100
|
+
r.push(x)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
expect(obj).toBeDefined()
|
|
104
|
+
expect(r).toMatchSnapshot()
|
|
105
|
+
const obj2 = await obj
|
|
106
|
+
expect(obj2).toBe(child1Base)
|
|
107
|
+
expect(obj2).toMatchSnapshot()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('can get root/child object from memory downloader using iterator and getObject', async () => {
|
|
111
|
+
const child1Base = { id: 'child1Id', kingsy_type: 'type' } as Base
|
|
112
|
+
const child1 = { baseId: 'child1Id', base: child1Base } as unknown as Item
|
|
113
|
+
|
|
114
|
+
const rootId = 'rootId'
|
|
115
|
+
const rootBase: Base = {
|
|
116
|
+
id: 'rootId',
|
|
117
|
+
kingsy_type: 'type',
|
|
118
|
+
__closure: { child1Id: 100 }
|
|
119
|
+
}
|
|
120
|
+
const root = {
|
|
121
|
+
baseId: rootId,
|
|
122
|
+
base: rootBase
|
|
123
|
+
} as unknown as Item
|
|
124
|
+
|
|
125
|
+
const records: Map<string, Base> = new Map<string, Base>()
|
|
126
|
+
records.set(root.baseId, rootBase)
|
|
127
|
+
records.set(child1.baseId, child1Base)
|
|
128
|
+
|
|
129
|
+
const loader = new ObjectLoader2({
|
|
130
|
+
rootId: root.baseId,
|
|
131
|
+
downloader: new MemoryDownloader(rootId, records),
|
|
132
|
+
database: new IndexedDatabase({
|
|
133
|
+
indexedDB: new IDBFactory(),
|
|
134
|
+
keyRange: IDBKeyRange
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
const r = []
|
|
138
|
+
const obj = loader.getObject({ id: child1.baseId })
|
|
139
|
+
for await (const x of loader.getObjectIterator()) {
|
|
140
|
+
r.push(x)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
expect(obj).toBeDefined()
|
|
144
|
+
expect(r).toMatchSnapshot()
|
|
145
|
+
const obj2 = await obj
|
|
146
|
+
expect(obj2).toBe(child1Base)
|
|
147
|
+
expect(obj2).toMatchSnapshot()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('add extra header', async () => {
|
|
151
|
+
const rootId = 'rootId'
|
|
152
|
+
const rootBase: Base = {
|
|
153
|
+
id: 'rootId',
|
|
154
|
+
kingsy_type: 'type',
|
|
155
|
+
__closure: { child1Id: 100 }
|
|
156
|
+
}
|
|
157
|
+
const root = {
|
|
158
|
+
baseId: rootId,
|
|
159
|
+
base: rootBase
|
|
160
|
+
} as Item
|
|
161
|
+
|
|
162
|
+
const records: Map<string, Base> = new Map<string, Base>()
|
|
163
|
+
records.set(root.baseId, rootBase)
|
|
164
|
+
const headers = new Headers()
|
|
165
|
+
headers.set('x-test', 'asdf')
|
|
166
|
+
const loader = new ObjectLoader2({
|
|
167
|
+
rootId: root.baseId,
|
|
168
|
+
downloader: new MemoryDownloader(rootId, records),
|
|
169
|
+
database: new IndexedDatabase({
|
|
170
|
+
indexedDB: new IDBFactory(),
|
|
171
|
+
keyRange: IDBKeyRange
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
const x = await loader.getRootObject()
|
|
175
|
+
expect(x).toMatchSnapshot()
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test('createFromJSON test', async () => {
|
|
179
|
+
const root = `{
|
|
180
|
+
"list": [{
|
|
181
|
+
"kingsy_type": "reference",
|
|
182
|
+
"referencedId": "0e61e61edee00404ec6e0f9f594bce24",
|
|
183
|
+
"__closure": null
|
|
184
|
+
}],
|
|
185
|
+
"list2": [{
|
|
186
|
+
"kingsy_type": "reference",
|
|
187
|
+
"referencedId": "f70738e3e3e593ac11099a6ed6b71154",
|
|
188
|
+
"__closure": null
|
|
189
|
+
}],
|
|
190
|
+
"arr": null,
|
|
191
|
+
"detachedProp": null,
|
|
192
|
+
"detachedProp2": null,
|
|
193
|
+
"attachedProp": null,
|
|
194
|
+
"crazyProp": null,
|
|
195
|
+
"applicationId": "1",
|
|
196
|
+
"kingsy_type": "KingSy.Core.Tests.Unit.Models.BaseTests+SampleObjectBase2",
|
|
197
|
+
"dynamicProp": 123,
|
|
198
|
+
"id": "efeadaca70a85ae6d3acfc93a8b380db",
|
|
199
|
+
"__closure": {
|
|
200
|
+
"0e61e61edee00404ec6e0f9f594bce24": 100,
|
|
201
|
+
"f70738e3e3e593ac11099a6ed6b71154": 100
|
|
202
|
+
}
|
|
203
|
+
}`
|
|
204
|
+
|
|
205
|
+
const list1 = `{
|
|
206
|
+
"data": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
|
|
207
|
+
"applicationId": null,
|
|
208
|
+
"kingsy_type": "KingSy.Core.Models.DataChunk",
|
|
209
|
+
"id": "0e61e61edee00404ec6e0f9f594bce24"
|
|
210
|
+
}`
|
|
211
|
+
|
|
212
|
+
const list2 = `{
|
|
213
|
+
"data": [1.0, 10.0],
|
|
214
|
+
"applicationId": null,
|
|
215
|
+
"kingsy_type": "KingSy.Core.Models.DataChunk",
|
|
216
|
+
"id": "f70738e3e3e593ac11099a6ed6b71154"
|
|
217
|
+
}`
|
|
218
|
+
const rootObj = JSON.parse(root) as Base
|
|
219
|
+
const list1Obj = JSON.parse(list1) as Base
|
|
220
|
+
const list2Obj = JSON.parse(list2) as Base
|
|
221
|
+
|
|
222
|
+
const loader = ObjectLoader2.createFromObjects([rootObj, list1Obj, list2Obj])
|
|
223
|
+
const r = []
|
|
224
|
+
for await (const x of loader.getObjectIterator()) {
|
|
225
|
+
r.push(x)
|
|
226
|
+
}
|
|
227
|
+
expect(r).toMatchSnapshot()
|
|
228
|
+
})
|
|
229
|
+
})
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import AsyncGeneratorQueue from '../helpers/asyncGeneratorQueue.js'
|
|
2
|
+
import { Downloader, Database } from './interfaces.js'
|
|
3
|
+
import { CustomLogger, Base, Item } from '../types/types.js'
|
|
4
|
+
import { CacheOptions, ObjectLoader2Options } from './options.js'
|
|
5
|
+
import { DefermentManager } from '../helpers/defermentManager.js'
|
|
6
|
+
import { CacheReader } from '../helpers/cacheReader.js'
|
|
7
|
+
import { CachePump } from '../helpers/cachePump.js'
|
|
8
|
+
import AggregateQueue from '../helpers/aggregateQueue.js'
|
|
9
|
+
import { ObjectLoader2Factory } from './objectLoader2Factory.js'
|
|
10
|
+
|
|
11
|
+
export class ObjectLoader2 {
|
|
12
|
+
#rootId: string
|
|
13
|
+
|
|
14
|
+
#logger: CustomLogger
|
|
15
|
+
|
|
16
|
+
#database: Database
|
|
17
|
+
#downloader: Downloader
|
|
18
|
+
#pump: CachePump
|
|
19
|
+
#cache: CacheReader
|
|
20
|
+
|
|
21
|
+
#deferments: DefermentManager
|
|
22
|
+
|
|
23
|
+
#gathered: AsyncGeneratorQueue<Item>
|
|
24
|
+
|
|
25
|
+
#root?: Item = undefined
|
|
26
|
+
|
|
27
|
+
constructor(options: ObjectLoader2Options) {
|
|
28
|
+
this.#rootId = options.rootId
|
|
29
|
+
this.#logger = options.logger || console.log
|
|
30
|
+
|
|
31
|
+
const cacheOptions: CacheOptions = {
|
|
32
|
+
logger: this.#logger,
|
|
33
|
+
maxCacheReadSize: 10_000,
|
|
34
|
+
maxCacheWriteSize: 10_000,
|
|
35
|
+
maxWriteQueueSize: 40_000,
|
|
36
|
+
maxCacheBatchWriteWait: 3_000,
|
|
37
|
+
maxCacheBatchReadWait: 3_000
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.#gathered = new AsyncGeneratorQueue()
|
|
41
|
+
this.#database = options.database
|
|
42
|
+
this.#deferments = new DefermentManager({
|
|
43
|
+
maxSizeInMb: 2_000, // 2 GBs
|
|
44
|
+
ttlms: 15_000, // 15 seconds
|
|
45
|
+
logger: this.#logger
|
|
46
|
+
})
|
|
47
|
+
this.#cache = new CacheReader(this.#database, this.#deferments, cacheOptions)
|
|
48
|
+
this.#pump = new CachePump(
|
|
49
|
+
this.#database,
|
|
50
|
+
this.#gathered,
|
|
51
|
+
this.#deferments,
|
|
52
|
+
cacheOptions
|
|
53
|
+
)
|
|
54
|
+
this.#downloader = options.downloader
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async disposeAsync(): Promise<void> {
|
|
58
|
+
await Promise.all([
|
|
59
|
+
this.#downloader.disposeAsync(),
|
|
60
|
+
this.#cache.disposeAsync(),
|
|
61
|
+
this.#pump.disposeAsync()
|
|
62
|
+
])
|
|
63
|
+
this.#deferments.dispose()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async getRootObject(): Promise<Item | undefined> {
|
|
67
|
+
if (!this.#root) {
|
|
68
|
+
this.#root = (await this.#database.getAll([this.#rootId]))[0]
|
|
69
|
+
if (!this.#root) {
|
|
70
|
+
this.#root = await this.#downloader.downloadSingle()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return this.#root
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async getObject(params: { id: string }): Promise<Base> {
|
|
77
|
+
return await this.#cache.getObject({ id: params.id })
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getTotalObjectCount(): Promise<number> {
|
|
81
|
+
const rootObj = await this.getRootObject()
|
|
82
|
+
const totalChildrenCount = Object.keys(rootObj?.base.__closure || {}).length
|
|
83
|
+
return totalChildrenCount + 1 //count the root
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async *getObjectIterator(): AsyncGenerator<Base> {
|
|
87
|
+
const rootItem = await this.getRootObject()
|
|
88
|
+
if (rootItem === undefined) {
|
|
89
|
+
this.#logger('No root object found!')
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
//only for root
|
|
93
|
+
this.#pump.add(rootItem)
|
|
94
|
+
yield rootItem.base
|
|
95
|
+
if (!rootItem.base.__closure) return
|
|
96
|
+
|
|
97
|
+
//sort the closures by their values descending
|
|
98
|
+
const sortedClosures = Object.entries(rootItem.base.__closure).sort(
|
|
99
|
+
(a, b) => b[1] - a[1]
|
|
100
|
+
)
|
|
101
|
+
const children = sortedClosures.map((x) => x[0])
|
|
102
|
+
const total = children.length
|
|
103
|
+
this.#downloader.initializePool({
|
|
104
|
+
results: new AggregateQueue(this.#gathered, this.#pump),
|
|
105
|
+
total
|
|
106
|
+
})
|
|
107
|
+
for await (const item of this.#pump.gather(children, this.#downloader)) {
|
|
108
|
+
yield item.base
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static createFromObjects(objects: Base[]): ObjectLoader2 {
|
|
113
|
+
return ObjectLoader2Factory.createFromObjects(objects)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static createFromJSON(json: string): ObjectLoader2 {
|
|
117
|
+
return ObjectLoader2Factory.createFromJSON(json)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Base, CustomLogger } from '../types/types.js'
|
|
2
|
+
import IndexedDatabase from './databases/indexedDatabase.js'
|
|
3
|
+
import { MemoryDatabase } from './databases/memoryDatabase.js'
|
|
4
|
+
import { MemoryDownloader } from './downloaders/memoryDownloader.js'
|
|
5
|
+
import ServerDownloader from './downloaders/serverDownloader.js'
|
|
6
|
+
import { ObjectLoader2 } from './objectLoader2.js'
|
|
7
|
+
|
|
8
|
+
export interface ObjectLoader2FactoryOptions {
|
|
9
|
+
useMemoryCache?: boolean
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
11
|
+
keyRange?: { bound: Function; lowerBound: Function; upperBound: Function }
|
|
12
|
+
indexedDB?: IDBFactory
|
|
13
|
+
logger?: CustomLogger
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ObjectLoader2Factory {
|
|
17
|
+
static createFromObjects(objects: Base[]): ObjectLoader2 {
|
|
18
|
+
const root = objects[0]
|
|
19
|
+
const records: Map<string, Base> = new Map<string, Base>()
|
|
20
|
+
objects.forEach((element) => {
|
|
21
|
+
records.set(element.id, element)
|
|
22
|
+
})
|
|
23
|
+
const loader = new ObjectLoader2({
|
|
24
|
+
rootId: root.id,
|
|
25
|
+
database: new MemoryDatabase({ items: records }),
|
|
26
|
+
downloader: new MemoryDownloader(root.id, records)
|
|
27
|
+
})
|
|
28
|
+
return loader
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static createFromJSON(json: string): ObjectLoader2 {
|
|
32
|
+
const jsonObj = JSON.parse(json) as Base[]
|
|
33
|
+
return this.createFromObjects(jsonObj)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static createFromUrl(params: {
|
|
37
|
+
serverUrl: string
|
|
38
|
+
streamId: string
|
|
39
|
+
objectId: string
|
|
40
|
+
token?: string
|
|
41
|
+
headers?: Headers
|
|
42
|
+
options?: ObjectLoader2FactoryOptions
|
|
43
|
+
}): ObjectLoader2 {
|
|
44
|
+
let loader: ObjectLoader2
|
|
45
|
+
if (params.options?.useMemoryCache) {
|
|
46
|
+
loader = new ObjectLoader2({
|
|
47
|
+
rootId: params.objectId,
|
|
48
|
+
downloader: new ServerDownloader({
|
|
49
|
+
serverUrl: params.serverUrl,
|
|
50
|
+
streamId: params.streamId,
|
|
51
|
+
objectId: params.objectId,
|
|
52
|
+
token: params.token,
|
|
53
|
+
headers: params.headers
|
|
54
|
+
}),
|
|
55
|
+
database: new MemoryDatabase({
|
|
56
|
+
items: new Map<string, Base>()
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
} else {
|
|
60
|
+
loader = new ObjectLoader2({
|
|
61
|
+
rootId: params.objectId,
|
|
62
|
+
downloader: new ServerDownloader({
|
|
63
|
+
serverUrl: params.serverUrl,
|
|
64
|
+
streamId: params.streamId,
|
|
65
|
+
objectId: params.objectId,
|
|
66
|
+
token: params.token,
|
|
67
|
+
headers: params.headers
|
|
68
|
+
}),
|
|
69
|
+
database: new IndexedDatabase({
|
|
70
|
+
logger: params.options?.logger,
|
|
71
|
+
indexedDB: params.options?.indexedDB,
|
|
72
|
+
keyRange: params.options?.keyRange
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
return loader
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Base, CustomLogger } from '../types/types.js'
|
|
2
|
+
import { Downloader, Database } from './interfaces.js'
|
|
3
|
+
|
|
4
|
+
export interface ObjectLoader2Options {
|
|
5
|
+
rootId: string
|
|
6
|
+
downloader: Downloader
|
|
7
|
+
database: Database
|
|
8
|
+
logger?: CustomLogger
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CacheOptions {
|
|
12
|
+
logger?: CustomLogger
|
|
13
|
+
maxCacheReadSize: number
|
|
14
|
+
maxCacheWriteSize: number
|
|
15
|
+
maxCacheBatchWriteWait: number
|
|
16
|
+
maxCacheBatchReadWait: number
|
|
17
|
+
maxWriteQueueSize: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface MemoryDatabaseOptions {
|
|
21
|
+
logger?: CustomLogger
|
|
22
|
+
items?: Map<string, Base>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DefermentManagerOptions {
|
|
26
|
+
logger?: CustomLogger
|
|
27
|
+
maxSizeInMb: number
|
|
28
|
+
ttlms: number
|
|
29
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { Base } from '../types/types.js'
|
|
3
|
+
import { ObjectLoader2 } from './objectLoader2.js'
|
|
4
|
+
import Traverser from './traverser.js'
|
|
5
|
+
|
|
6
|
+
describe('Traverser', () => {
|
|
7
|
+
test('root and two children with referenceId', async () => {
|
|
8
|
+
const root = `{
|
|
9
|
+
"list": [{
|
|
10
|
+
"kingsy_type": "reference",
|
|
11
|
+
"referencedId": "0e61e61edee00404ec6e0f9f594bce24",
|
|
12
|
+
"__closure": null
|
|
13
|
+
}],
|
|
14
|
+
"list2": [{
|
|
15
|
+
"kingsy_type": "reference",
|
|
16
|
+
"referencedId": "f70738e3e3e593ac11099a6ed6b71154",
|
|
17
|
+
"__closure": null
|
|
18
|
+
}],
|
|
19
|
+
"arr": null,
|
|
20
|
+
"detachedProp": null,
|
|
21
|
+
"detachedProp2": null,
|
|
22
|
+
"attachedProp": null,
|
|
23
|
+
"crazyProp": null,
|
|
24
|
+
"applicationId": "1",
|
|
25
|
+
"kingsy_type": "KingSy.Core.Tests.Unit.Models.BaseTests+SampleObjectBase2",
|
|
26
|
+
"dynamicProp": 123,
|
|
27
|
+
"id": "efeadaca70a85ae6d3acfc93a8b380db",
|
|
28
|
+
"__closure": {
|
|
29
|
+
"0e61e61edee00404ec6e0f9f594bce24": 100,
|
|
30
|
+
"f70738e3e3e593ac11099a6ed6b71154": 100
|
|
31
|
+
}
|
|
32
|
+
}`
|
|
33
|
+
|
|
34
|
+
const list1 = `{
|
|
35
|
+
"data": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
|
|
36
|
+
"applicationId": null,
|
|
37
|
+
"kingsy_type": "KingSy.Core.Models.DataChunk",
|
|
38
|
+
"id": "0e61e61edee00404ec6e0f9f594bce24"
|
|
39
|
+
}`
|
|
40
|
+
|
|
41
|
+
const list2 = `{
|
|
42
|
+
"data": [1.0, 10.0],
|
|
43
|
+
"applicationId": null,
|
|
44
|
+
"kingsy_type": "KingSy.Core.Models.DataChunk",
|
|
45
|
+
"id": "f70738e3e3e593ac11099a6ed6b71154"
|
|
46
|
+
}`
|
|
47
|
+
|
|
48
|
+
const rootObj = JSON.parse(root) as Base
|
|
49
|
+
const list1Obj = JSON.parse(list1) as Base
|
|
50
|
+
const list2Obj = JSON.parse(list2) as Base
|
|
51
|
+
|
|
52
|
+
const loader = ObjectLoader2.createFromObjects([rootObj, list1Obj, list2Obj])
|
|
53
|
+
|
|
54
|
+
const traverser = new Traverser(loader)
|
|
55
|
+
const r = await traverser.traverse()
|
|
56
|
+
expect(r).toMatchSnapshot()
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Base, DataChunk, isBase, isReference, isScalar } from '../types/types.js'
|
|
2
|
+
import { ObjectLoader2 } from './objectLoader2.js'
|
|
3
|
+
|
|
4
|
+
export type ProgressStage = 'download' | 'construction'
|
|
5
|
+
export type OnProgress = (e: {
|
|
6
|
+
stage: ProgressStage
|
|
7
|
+
current: number
|
|
8
|
+
total: number
|
|
9
|
+
}) => void
|
|
10
|
+
|
|
11
|
+
export interface TraverserOptions {
|
|
12
|
+
excludeProps?: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default class Traverser {
|
|
16
|
+
#loader: ObjectLoader2
|
|
17
|
+
#options: TraverserOptions
|
|
18
|
+
|
|
19
|
+
#totalChildrenCount = 0
|
|
20
|
+
#traversedReferencesCount = 0
|
|
21
|
+
|
|
22
|
+
constructor(loader: ObjectLoader2, options?: TraverserOptions) {
|
|
23
|
+
this.#options = options || {}
|
|
24
|
+
this.#loader = loader
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async traverse(onProgress?: OnProgress): Promise<Base> {
|
|
28
|
+
let firstObjectPromise: Promise<Base> | undefined = undefined
|
|
29
|
+
for await (const obj of this.#loader.getObjectIterator()) {
|
|
30
|
+
if (!firstObjectPromise) {
|
|
31
|
+
firstObjectPromise = this.traverseBase(obj, onProgress)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (firstObjectPromise) {
|
|
36
|
+
return await firstObjectPromise
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error('No objects found')
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async traverseArray(array: Array<unknown>, onProgress?: OnProgress): Promise<void> {
|
|
43
|
+
for (let i = 0; i < 10; i++) {
|
|
44
|
+
const prop = array[i]
|
|
45
|
+
if (isScalar(prop)) continue
|
|
46
|
+
if (isBase(prop)) {
|
|
47
|
+
array[i] = await this.traverseBase(prop, onProgress)
|
|
48
|
+
} else if (isReference(prop)) {
|
|
49
|
+
array[i] = await this.traverseBase(
|
|
50
|
+
await this.#loader.getObject({ id: prop.referencedId }),
|
|
51
|
+
onProgress
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async traverseBase(base: Base, onProgress?: OnProgress): Promise<Base> {
|
|
58
|
+
for (const ignoredProp of this.#options.excludeProps || []) {
|
|
59
|
+
delete (base as never)[ignoredProp]
|
|
60
|
+
}
|
|
61
|
+
if (base.__closure) {
|
|
62
|
+
const ids = Object.keys(base.__closure)
|
|
63
|
+
const promises: Promise<Base>[] = []
|
|
64
|
+
for (const id of ids) {
|
|
65
|
+
promises.push(
|
|
66
|
+
this.traverseBase(await this.#loader.getObject({ id }), onProgress)
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
await Promise.all(promises)
|
|
70
|
+
}
|
|
71
|
+
delete (base as never)['__closure']
|
|
72
|
+
|
|
73
|
+
// De-chunk
|
|
74
|
+
if (base.kingsy_type?.includes('DataChunk')) {
|
|
75
|
+
const chunk = base as DataChunk
|
|
76
|
+
if (chunk.data) {
|
|
77
|
+
await this.traverseArray(chunk.data, onProgress)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//other props
|
|
82
|
+
for (const prop in base) {
|
|
83
|
+
if (prop === '__closure') continue
|
|
84
|
+
if (prop === 'referenceId') continue
|
|
85
|
+
if (prop === 'kingsy_type') continue
|
|
86
|
+
if (prop === 'data') continue
|
|
87
|
+
const baseProp = (base as unknown as Record<string, unknown>)[prop]
|
|
88
|
+
if (isScalar(baseProp)) continue
|
|
89
|
+
if (isBase(baseProp)) {
|
|
90
|
+
await this.traverseBase(baseProp, onProgress)
|
|
91
|
+
} else if (isReference(baseProp)) {
|
|
92
|
+
await this.traverseBase(
|
|
93
|
+
await this.#loader.getObject({ id: baseProp.referencedId }),
|
|
94
|
+
onProgress
|
|
95
|
+
)
|
|
96
|
+
} else if (Array.isArray(baseProp)) {
|
|
97
|
+
await this.traverseArray(baseProp, onProgress)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (onProgress) {
|
|
101
|
+
onProgress({
|
|
102
|
+
stage: 'construction',
|
|
103
|
+
current:
|
|
104
|
+
++this.#traversedReferencesCount > this.#totalChildrenCount
|
|
105
|
+
? this.#totalChildrenCount
|
|
106
|
+
: this.#traversedReferencesCount,
|
|
107
|
+
total: this.#totalChildrenCount
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
return base
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest'
|
|
2
|
+
import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
|
|
3
|
+
import { Base } from '../types/types.js'
|
|
4
|
+
import { TIME_MS } from '@kingsy/shared'
|
|
5
|
+
import { ObjectLoader2Factory } from '../operations/objectLoader2Factory.js'
|
|
6
|
+
|
|
7
|
+
describe('e2e', () => {
|
|
8
|
+
test(
|
|
9
|
+
'download small model',
|
|
10
|
+
async () => {
|
|
11
|
+
// Revit sample house (good for bim-like stuff with many display meshes)
|
|
12
|
+
//const resource = 'https://app.kingsy.systems/streams/da9e320dad/commits/5388ef24b8'
|
|
13
|
+
const loader = ObjectLoader2Factory.createFromUrl({
|
|
14
|
+
serverUrl: 'https://app.kingsy.systems',
|
|
15
|
+
streamId: 'da9e320dad',
|
|
16
|
+
objectId: '31d10c0cea569a1e26809658ed27e281',
|
|
17
|
+
options: {
|
|
18
|
+
indexedDB: new IDBFactory(),
|
|
19
|
+
keyRange: IDBKeyRange
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const getObjectPromise = loader.getObject({
|
|
24
|
+
id: '1708a78e057e8115f924c620ba686db6'
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const bases: Base[] = []
|
|
28
|
+
for await (const obj of loader.getObjectIterator()) {
|
|
29
|
+
bases.push(obj)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
expect(await loader.getTotalObjectCount()).toBe(1328)
|
|
33
|
+
expect(bases.length).toBe(1328)
|
|
34
|
+
const base = await getObjectPromise
|
|
35
|
+
expect(base).toBeDefined()
|
|
36
|
+
expect(base.id).toBe('1708a78e057e8115f924c620ba686db6')
|
|
37
|
+
const base2 = await loader.getObject({ id: '3841e3cbc45d52c47bc2f1b7b0ad4eb9' })
|
|
38
|
+
expect(base2).toBeDefined()
|
|
39
|
+
expect(base2.id).toBe('3841e3cbc45d52c47bc2f1b7b0ad4eb9')
|
|
40
|
+
},
|
|
41
|
+
10 * TIME_MS.second
|
|
42
|
+
)
|
|
43
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base ObjectLoader error
|
|
3
|
+
*/
|
|
4
|
+
class BaseError extends Error {
|
|
5
|
+
/**
|
|
6
|
+
* Default message if none is passed
|
|
7
|
+
*/
|
|
8
|
+
static defaultMessage = 'Unexpected error occurred'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} [message]
|
|
12
|
+
*/
|
|
13
|
+
constructor(message: string) {
|
|
14
|
+
message ||= new.target.defaultMessage
|
|
15
|
+
super(message)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class ObjectLoaderConfigurationError extends BaseError {
|
|
20
|
+
static defaultMessage = 'Object loader configured incorrectly!'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class ObjectLoaderRuntimeError extends BaseError {
|
|
24
|
+
static defaultMessage = 'Object loader encountered a runtime problem!'
|
|
25
|
+
}
|