@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,48 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { MemoryDatabase } from './memoryDatabase.js'
|
|
3
|
+
import { Base, Item } from '../../types/types.js'
|
|
4
|
+
|
|
5
|
+
const makeItem = (id: string, foo = 'bar'): Item => ({
|
|
6
|
+
baseId: id,
|
|
7
|
+
base: { foo } as unknown as Base
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
describe('MemoryDatabase', () => {
|
|
11
|
+
let db: MemoryDatabase
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
db = new MemoryDatabase()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should return undefined for missing keys', async () => {
|
|
18
|
+
const result = await db.getAll(['missing'])
|
|
19
|
+
expect(result).toEqual([undefined])
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should add and retrieve a single item', async () => {
|
|
23
|
+
const item = makeItem('id1')
|
|
24
|
+
await db.cacheSaveBatch({ batch: [item] })
|
|
25
|
+
const result = await db.getAll(['id1'])
|
|
26
|
+
expect(result).toEqual([item])
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should add and retrieve multiple items', async () => {
|
|
30
|
+
const items = [makeItem('id1'), makeItem('id2', 'baz')]
|
|
31
|
+
await db.cacheSaveBatch({ batch: items })
|
|
32
|
+
const result = await db.getAll(['id1', 'id2'])
|
|
33
|
+
expect(result).toEqual(items)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should overwrite items with the same key', async () => {
|
|
37
|
+
const item1 = makeItem('id1', 'foo')
|
|
38
|
+
const item2 = makeItem('id1', 'bar')
|
|
39
|
+
await db.cacheSaveBatch({ batch: [item1] })
|
|
40
|
+
await db.cacheSaveBatch({ batch: [item2] })
|
|
41
|
+
const result = await db.getAll(['id1'])
|
|
42
|
+
expect(result).toEqual([item2])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('disposeAsync should resolve', async () => {
|
|
46
|
+
await expect(db.disposeAsync()).resolves.not.toThrow()
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Base, Item } from '../../types/types.js'
|
|
2
|
+
import { Database } from '../interfaces.js'
|
|
3
|
+
import { MemoryDatabaseOptions } from '../options.js'
|
|
4
|
+
|
|
5
|
+
export class MemoryDatabase implements Database {
|
|
6
|
+
private items: Map<string, Base>
|
|
7
|
+
|
|
8
|
+
constructor(options?: MemoryDatabaseOptions) {
|
|
9
|
+
this.items = options?.items || new Map<string, Base>()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getAll(keys: string[]): Promise<(Item | undefined)[]> {
|
|
13
|
+
const found: (Item | undefined)[] = []
|
|
14
|
+
for (const key of keys) {
|
|
15
|
+
const item = this.items.get(key)
|
|
16
|
+
if (item) {
|
|
17
|
+
found.push({ baseId: key, base: item })
|
|
18
|
+
} else {
|
|
19
|
+
found.push(undefined)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return Promise.resolve(found)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
cacheSaveBatch({ batch }: { batch: Item[] }): Promise<void> {
|
|
26
|
+
for (const item of batch) {
|
|
27
|
+
this.items.set(item.baseId, item.base)
|
|
28
|
+
}
|
|
29
|
+
return Promise.resolve()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
disposeAsync(): Promise<void> {
|
|
33
|
+
return Promise.resolve()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`downloader > add extra header 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"base": {
|
|
6
|
+
"__closure": {
|
|
7
|
+
"childIds": 1,
|
|
8
|
+
},
|
|
9
|
+
"id": "id",
|
|
10
|
+
"kingsy_type": "type",
|
|
11
|
+
},
|
|
12
|
+
"baseId": "id",
|
|
13
|
+
"size": 0,
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
exports[`downloader > download batch of one 1`] = `
|
|
18
|
+
[
|
|
19
|
+
{
|
|
20
|
+
"base": {
|
|
21
|
+
"id": "id",
|
|
22
|
+
"kingsy_type": "type",
|
|
23
|
+
},
|
|
24
|
+
"baseId": "id",
|
|
25
|
+
"size": 33,
|
|
26
|
+
},
|
|
27
|
+
]
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
exports[`downloader > download batch of three 1`] = `
|
|
31
|
+
[
|
|
32
|
+
{
|
|
33
|
+
"base": {
|
|
34
|
+
"id": "id1",
|
|
35
|
+
"kingsy_type": "type",
|
|
36
|
+
},
|
|
37
|
+
"baseId": "id1",
|
|
38
|
+
"size": 34,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"base": {
|
|
42
|
+
"id": "id2",
|
|
43
|
+
"kingsy_type": "type",
|
|
44
|
+
},
|
|
45
|
+
"baseId": "id2",
|
|
46
|
+
"size": 34,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"base": {
|
|
50
|
+
"id": "id3",
|
|
51
|
+
"kingsy_type": "type",
|
|
52
|
+
},
|
|
53
|
+
"baseId": "id3",
|
|
54
|
+
"size": 34,
|
|
55
|
+
},
|
|
56
|
+
]
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
exports[`downloader > download batch of two 1`] = `
|
|
60
|
+
[
|
|
61
|
+
{
|
|
62
|
+
"base": {
|
|
63
|
+
"id": "id1",
|
|
64
|
+
"kingsy_type": "type",
|
|
65
|
+
},
|
|
66
|
+
"baseId": "id1",
|
|
67
|
+
"size": 34,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"base": {
|
|
71
|
+
"id": "id2",
|
|
72
|
+
"kingsy_type": "type",
|
|
73
|
+
},
|
|
74
|
+
"baseId": "id2",
|
|
75
|
+
"size": 34,
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
exports[`downloader > download single exists 1`] = `
|
|
81
|
+
{
|
|
82
|
+
"base": {
|
|
83
|
+
"__closure": {
|
|
84
|
+
"childIds": 1,
|
|
85
|
+
},
|
|
86
|
+
"id": "id",
|
|
87
|
+
"kingsy_type": "type",
|
|
88
|
+
},
|
|
89
|
+
"baseId": "id",
|
|
90
|
+
"size": 0,
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { MemoryDownloader } from './memoryDownloader.js'
|
|
3
|
+
import { Base, Item } from '../../types/types.js'
|
|
4
|
+
import Queue from '../../helpers/queue.js'
|
|
5
|
+
import BufferQueue from '../../helpers/bufferQueue.js'
|
|
6
|
+
|
|
7
|
+
const makeBase = (foo: string): Base => ({ foo } as unknown as Base)
|
|
8
|
+
|
|
9
|
+
describe('MemoryDownloader', () => {
|
|
10
|
+
let items: Map<string, Base>
|
|
11
|
+
let downloader: MemoryDownloader
|
|
12
|
+
let results: Queue<Item>
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
items = new Map([
|
|
16
|
+
['id1', makeBase('foo')],
|
|
17
|
+
['id2', makeBase('bar')]
|
|
18
|
+
])
|
|
19
|
+
downloader = new MemoryDownloader('id1', items)
|
|
20
|
+
results = new BufferQueue<Item>()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should download the root item', async () => {
|
|
24
|
+
const item = await downloader.downloadSingle()
|
|
25
|
+
expect(item).toEqual({ baseId: 'id1', base: { foo: 'foo' } })
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should throw if root item is missing', async () => {
|
|
29
|
+
const missingDownloader = new MemoryDownloader('missing', items)
|
|
30
|
+
await expect(missingDownloader.downloadSingle()).rejects.toThrow(
|
|
31
|
+
'Method not implemented.'
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('should add found item to results queue', () => {
|
|
36
|
+
downloader.initializePool({ results, total: 2 })
|
|
37
|
+
downloader.add('id2')
|
|
38
|
+
expect(items).toMatchSnapshot()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should throw if added item is missing', () => {
|
|
42
|
+
downloader.initializePool({ results, total: 2 })
|
|
43
|
+
expect(() => downloader.add('missing')).toThrow()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('disposeAsync should resolve', async () => {
|
|
47
|
+
await expect(downloader.disposeAsync()).resolves.not.toThrow()
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import Queue from '../../helpers/queue.js'
|
|
2
|
+
import { Base, Item } from '../../types/types.js'
|
|
3
|
+
import { Downloader } from '../interfaces.js'
|
|
4
|
+
|
|
5
|
+
export class MemoryDownloader implements Downloader {
|
|
6
|
+
#items: Map<string, Base>
|
|
7
|
+
#rootId: string
|
|
8
|
+
#results?: Queue<Item>
|
|
9
|
+
|
|
10
|
+
constructor(rootId: string, items: Map<string, Base>) {
|
|
11
|
+
this.#rootId = rootId
|
|
12
|
+
this.#items = items
|
|
13
|
+
}
|
|
14
|
+
initializePool(params: {
|
|
15
|
+
results: Queue<Item>
|
|
16
|
+
total: number
|
|
17
|
+
maxDownloadBatchWait?: number
|
|
18
|
+
}): void {
|
|
19
|
+
this.#results = params.results
|
|
20
|
+
}
|
|
21
|
+
downloadSingle(): Promise<Item> {
|
|
22
|
+
const root = this.#items.get(this.#rootId)
|
|
23
|
+
if (root) {
|
|
24
|
+
return Promise.resolve({ baseId: this.#rootId, base: root })
|
|
25
|
+
}
|
|
26
|
+
return Promise.reject(new Error('Method not implemented.'))
|
|
27
|
+
}
|
|
28
|
+
disposeAsync(): Promise<void> {
|
|
29
|
+
return Promise.resolve()
|
|
30
|
+
}
|
|
31
|
+
add(id: string): void {
|
|
32
|
+
const base = this.#items.get(id)
|
|
33
|
+
if (base) {
|
|
34
|
+
this.#results?.add({ baseId: id, base })
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
throw new Error('Method not implemented.')
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import createFetchMock from 'vitest-fetch-mock'
|
|
3
|
+
import { vi } from 'vitest'
|
|
4
|
+
import { Item } from '../../types/types.js'
|
|
5
|
+
import ServerDownloader from './serverDownloader.js'
|
|
6
|
+
import { MemoryPump } from '../../helpers/memoryPump.js'
|
|
7
|
+
|
|
8
|
+
describe('downloader', () => {
|
|
9
|
+
test('download batch of one', async () => {
|
|
10
|
+
const fetchMocker = createFetchMock(vi)
|
|
11
|
+
const i: Item = { baseId: 'id', base: { id: 'id', kingsy_type: 'type' } }
|
|
12
|
+
fetchMocker.mockResponseOnce('id\t' + JSON.stringify(i.base) + '\n')
|
|
13
|
+
const pump = new MemoryPump()
|
|
14
|
+
const downloader = new ServerDownloader({
|
|
15
|
+
serverUrl: 'http://kingsy.test',
|
|
16
|
+
streamId: 'streamId',
|
|
17
|
+
objectId: 'objectId',
|
|
18
|
+
token: 'token',
|
|
19
|
+
fetch: fetchMocker
|
|
20
|
+
})
|
|
21
|
+
downloader.initializePool({ results: pump, total: 1, maxDownloadBatchWait: 200 })
|
|
22
|
+
downloader.add('id')
|
|
23
|
+
await downloader.disposeAsync()
|
|
24
|
+
const r = []
|
|
25
|
+
for await (const x of pump.gather([i.baseId])) {
|
|
26
|
+
r.push(x)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
expect(r).toMatchSnapshot()
|
|
30
|
+
await downloader.disposeAsync()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('download batch of two', async () => {
|
|
34
|
+
const fetchMocker = createFetchMock(vi)
|
|
35
|
+
const i1: Item = { baseId: 'id1', base: { id: 'id1', kingsy_type: 'type' } }
|
|
36
|
+
const i2: Item = { baseId: 'id2', base: { id: 'id2', kingsy_type: 'type' } }
|
|
37
|
+
fetchMocker.mockResponseOnce(
|
|
38
|
+
'id1\t' + JSON.stringify(i1.base) + '\nid2\t' + JSON.stringify(i2.base) + '\n'
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const pump = new MemoryPump()
|
|
42
|
+
const downloader = new ServerDownloader({
|
|
43
|
+
serverUrl: 'http://kingsy.test',
|
|
44
|
+
streamId: 'streamId',
|
|
45
|
+
objectId: 'objectId',
|
|
46
|
+
token: 'token',
|
|
47
|
+
|
|
48
|
+
fetch: fetchMocker
|
|
49
|
+
})
|
|
50
|
+
downloader.initializePool({ results: pump, total: 2, maxDownloadBatchWait: 200 })
|
|
51
|
+
downloader.add('id1')
|
|
52
|
+
downloader.add('id2')
|
|
53
|
+
await downloader.disposeAsync()
|
|
54
|
+
const r = []
|
|
55
|
+
for await (const x of pump.gather([i1.baseId, i2.baseId])) {
|
|
56
|
+
r.push(x)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
expect(r).toMatchSnapshot()
|
|
60
|
+
await downloader.disposeAsync()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('download batch of three', async () => {
|
|
64
|
+
const fetchMocker = createFetchMock(vi)
|
|
65
|
+
const i1: Item = { baseId: 'id1', base: { id: 'id1', kingsy_type: 'type' } }
|
|
66
|
+
const i2: Item = { baseId: 'id2', base: { id: 'id2', kingsy_type: 'type' } }
|
|
67
|
+
const i3: Item = { baseId: 'id3', base: { id: 'id3', kingsy_type: 'type' } }
|
|
68
|
+
fetchMocker.mockResponseOnce(
|
|
69
|
+
'id1\t' +
|
|
70
|
+
JSON.stringify(i1.base) +
|
|
71
|
+
'\nid2\t' +
|
|
72
|
+
JSON.stringify(i2.base) +
|
|
73
|
+
'\nid3\t' +
|
|
74
|
+
JSON.stringify(i3.base) +
|
|
75
|
+
'\n'
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
const pump = new MemoryPump()
|
|
79
|
+
const downloader = new ServerDownloader({
|
|
80
|
+
serverUrl: 'http://kingsy.test',
|
|
81
|
+
streamId: 'streamId',
|
|
82
|
+
objectId: 'objectId',
|
|
83
|
+
token: 'token',
|
|
84
|
+
|
|
85
|
+
fetch: fetchMocker
|
|
86
|
+
})
|
|
87
|
+
downloader.initializePool({ results: pump, total: 3, maxDownloadBatchWait: 200 })
|
|
88
|
+
downloader.add('id1')
|
|
89
|
+
downloader.add('id2')
|
|
90
|
+
downloader.add('id3')
|
|
91
|
+
await downloader.disposeAsync()
|
|
92
|
+
const r = []
|
|
93
|
+
for await (const x of pump.gather([i1.baseId, i2.baseId, i3.baseId])) {
|
|
94
|
+
r.push(x)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
expect(r).toMatchSnapshot()
|
|
98
|
+
await downloader.disposeAsync()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('download single exists', async () => {
|
|
102
|
+
const fetchMocker = createFetchMock(vi)
|
|
103
|
+
const i: Item = {
|
|
104
|
+
baseId: 'id',
|
|
105
|
+
base: { id: 'id', kingsy_type: 'type', __closure: { childIds: 1 } }
|
|
106
|
+
}
|
|
107
|
+
fetchMocker.mockResponseOnce(JSON.stringify(i.base))
|
|
108
|
+
const downloader = new ServerDownloader({
|
|
109
|
+
serverUrl: 'http://kingsy.test',
|
|
110
|
+
streamId: 'streamId',
|
|
111
|
+
objectId: i.baseId,
|
|
112
|
+
token: 'token',
|
|
113
|
+
|
|
114
|
+
fetch: fetchMocker
|
|
115
|
+
})
|
|
116
|
+
const x = await downloader.downloadSingle()
|
|
117
|
+
expect(x).toMatchSnapshot()
|
|
118
|
+
await downloader.disposeAsync()
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('add extra header', async () => {
|
|
122
|
+
const fetchMocker = createFetchMock(vi)
|
|
123
|
+
const i: Item = {
|
|
124
|
+
baseId: 'id',
|
|
125
|
+
base: { id: 'id', kingsy_type: 'type', __closure: { childIds: 1 } }
|
|
126
|
+
}
|
|
127
|
+
fetchMocker.mockResponseIf(
|
|
128
|
+
(req) => req.headers.get('x-test') === 'asdf',
|
|
129
|
+
JSON.stringify(i.base)
|
|
130
|
+
)
|
|
131
|
+
const headers = new Headers()
|
|
132
|
+
headers.set('x-test', 'asdf')
|
|
133
|
+
const downloader = new ServerDownloader({
|
|
134
|
+
serverUrl: 'http://kingsy.test',
|
|
135
|
+
headers,
|
|
136
|
+
streamId: 'streamId',
|
|
137
|
+
objectId: i.baseId,
|
|
138
|
+
token: 'token',
|
|
139
|
+
|
|
140
|
+
fetch: fetchMocker
|
|
141
|
+
})
|
|
142
|
+
const x = await downloader.downloadSingle()
|
|
143
|
+
expect(x).toMatchSnapshot()
|
|
144
|
+
await downloader.disposeAsync()
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test('can dispose used', async () => {
|
|
148
|
+
const fetchMocker = createFetchMock(vi)
|
|
149
|
+
const headers = new Headers()
|
|
150
|
+
const downloader = new ServerDownloader({
|
|
151
|
+
serverUrl: 'http://kingsy.test',
|
|
152
|
+
headers,
|
|
153
|
+
streamId: 'streamId',
|
|
154
|
+
objectId: 'objectId',
|
|
155
|
+
token: 'token',
|
|
156
|
+
|
|
157
|
+
fetch: fetchMocker
|
|
158
|
+
})
|
|
159
|
+
await downloader.disposeAsync()
|
|
160
|
+
})
|
|
161
|
+
})
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import BatchedPool from '../../helpers/batchedPool.js'
|
|
2
|
+
import Queue from '../../helpers/queue.js'
|
|
3
|
+
import { ObjectLoaderRuntimeError } from '../../types/errors.js'
|
|
4
|
+
import { Fetcher, isBase, Item, take } from '../../types/types.js'
|
|
5
|
+
import { Downloader } from '../interfaces.js'
|
|
6
|
+
|
|
7
|
+
export interface ServerDownloaderOptions {
|
|
8
|
+
serverUrl: string
|
|
9
|
+
streamId: string
|
|
10
|
+
objectId: string
|
|
11
|
+
token?: string
|
|
12
|
+
headers?: Headers
|
|
13
|
+
fetch?: Fetcher
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default class ServerDownloader implements Downloader {
|
|
17
|
+
#requestUrlRootObj: string
|
|
18
|
+
#requestUrlChildren: string
|
|
19
|
+
#headers: HeadersInit
|
|
20
|
+
#options: ServerDownloaderOptions
|
|
21
|
+
#fetch: Fetcher
|
|
22
|
+
#results?: Queue<Item>
|
|
23
|
+
|
|
24
|
+
#downloadQueue?: BatchedPool<string>
|
|
25
|
+
#decoder = new TextDecoder()
|
|
26
|
+
|
|
27
|
+
constructor(options: ServerDownloaderOptions) {
|
|
28
|
+
this.#options = options
|
|
29
|
+
this.#fetch =
|
|
30
|
+
options.fetch ?? ((...args): Promise<Response> => globalThis.fetch(...args))
|
|
31
|
+
|
|
32
|
+
this.#headers = {}
|
|
33
|
+
if (options.headers) {
|
|
34
|
+
for (const header of options.headers.entries()) {
|
|
35
|
+
this.#headers[header[0]] = header[1]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
this.#headers['Accept'] = `text/plain`
|
|
39
|
+
|
|
40
|
+
if (this.#options.token) {
|
|
41
|
+
this.#headers['Authorization'] = `Bearer ${this.#options.token}`
|
|
42
|
+
}
|
|
43
|
+
this.#requestUrlChildren = `${this.#options.serverUrl}/api/getobjects/${
|
|
44
|
+
this.#options.streamId
|
|
45
|
+
}`
|
|
46
|
+
this.#requestUrlRootObj = `${this.#options.serverUrl}/objects/${
|
|
47
|
+
this.#options.streamId
|
|
48
|
+
}/${this.#options.objectId}/single`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#getDownloadCountAndSizes(total: number): number[] {
|
|
52
|
+
if (total <= 50) {
|
|
53
|
+
return [total]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return [10000, 25000, 10000, 1000]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
initializePool(params: {
|
|
60
|
+
results: Queue<Item>
|
|
61
|
+
total: number
|
|
62
|
+
maxDownloadBatchWait?: number
|
|
63
|
+
}): void {
|
|
64
|
+
const { results, total } = params
|
|
65
|
+
this.#results = results
|
|
66
|
+
this.#downloadQueue = new BatchedPool<string>({
|
|
67
|
+
concurrencyAndSizes: this.#getDownloadCountAndSizes(total),
|
|
68
|
+
maxWaitTime: params.maxDownloadBatchWait,
|
|
69
|
+
processFunction: (batch: string[]): Promise<void> =>
|
|
70
|
+
this.downloadBatch({
|
|
71
|
+
batch,
|
|
72
|
+
url: this.#requestUrlChildren,
|
|
73
|
+
headers: this.#headers
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#getPool(): BatchedPool<string> {
|
|
79
|
+
if (this.#downloadQueue) {
|
|
80
|
+
return this.#downloadQueue
|
|
81
|
+
}
|
|
82
|
+
throw new Error('Download pool is not initialized')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
add(id: string): void {
|
|
86
|
+
this.#getPool().add(id)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async disposeAsync(): Promise<void> {
|
|
90
|
+
await this.#downloadQueue?.disposeAsync()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#processJson(baseId: string, unparsedBase: string): Item {
|
|
94
|
+
let base: unknown
|
|
95
|
+
try {
|
|
96
|
+
base = JSON.parse(unparsedBase)
|
|
97
|
+
} catch (e: unknown) {
|
|
98
|
+
throw new Error(`Error parsing object ${baseId}: ${(e as Error).message}`)
|
|
99
|
+
}
|
|
100
|
+
if (isBase(base)) {
|
|
101
|
+
return { baseId, base }
|
|
102
|
+
} else {
|
|
103
|
+
throw new ObjectLoaderRuntimeError(`${baseId} is not a base`)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async downloadBatch(params: {
|
|
108
|
+
batch: string[]
|
|
109
|
+
url: string
|
|
110
|
+
headers: HeadersInit
|
|
111
|
+
}): Promise<void> {
|
|
112
|
+
const { batch, url, headers } = params
|
|
113
|
+
const keys = new Set<string>(batch)
|
|
114
|
+
const response = await this.#fetch(url, {
|
|
115
|
+
method: 'POST',
|
|
116
|
+
headers: { ...headers, 'Content-Type': 'application/json' },
|
|
117
|
+
body: JSON.stringify({ objects: JSON.stringify(batch) })
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
this.#validateResponse(response)
|
|
121
|
+
if (!response.body) {
|
|
122
|
+
throw new Error('ReadableStream not supported or response has no body.')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const reader = response.body.getReader()
|
|
126
|
+
let leftover = new Uint8Array(0)
|
|
127
|
+
|
|
128
|
+
let count = 0
|
|
129
|
+
while (true) {
|
|
130
|
+
const { done, value } = await reader.read()
|
|
131
|
+
if (done) break
|
|
132
|
+
|
|
133
|
+
leftover = await this.processArray(leftover, value, keys, async () => {
|
|
134
|
+
count++
|
|
135
|
+
if (count % 1000 === 0) {
|
|
136
|
+
await new Promise((resolve) => setTimeout(resolve, 100)) //allow other stuff to happen
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
if (keys.size > 0) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
'Items requested were not downloaded: ' + take(keys.values(), 10).join(',')
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async processArray(
|
|
148
|
+
leftover: Uint8Array,
|
|
149
|
+
value: Uint8Array,
|
|
150
|
+
keys: Set<string>,
|
|
151
|
+
callback: () => Promise<void>
|
|
152
|
+
): Promise<Uint8Array> {
|
|
153
|
+
//this concat will allocate a new array
|
|
154
|
+
const combined = this.concatUint8Arrays(leftover, value)
|
|
155
|
+
let start = 0
|
|
156
|
+
|
|
157
|
+
//subarray doesn't allocate
|
|
158
|
+
for (let i = 0; i < combined.length; i++) {
|
|
159
|
+
if (combined[i] === 0x0a) {
|
|
160
|
+
const line = combined.subarray(start, i) // line without \n
|
|
161
|
+
//strings are allocated here
|
|
162
|
+
const item = this.processLine(line)
|
|
163
|
+
this.#results?.add(item)
|
|
164
|
+
start = i + 1
|
|
165
|
+
await callback()
|
|
166
|
+
keys.delete(item.baseId)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return combined.subarray(start) // carry over remainder
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
processLine(line: Uint8Array): Item {
|
|
173
|
+
for (let i = 0; i < line.length; i++) {
|
|
174
|
+
if (line[i] === 0x09) {
|
|
175
|
+
//this is a tab
|
|
176
|
+
const baseId = this.#decoder.decode(line.subarray(0, i))
|
|
177
|
+
const json = line.subarray(i + 1)
|
|
178
|
+
const base = this.#decoder.decode(json)
|
|
179
|
+
const item = this.#processJson(baseId, base)
|
|
180
|
+
item.size = json.length
|
|
181
|
+
return item
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
throw new ObjectLoaderRuntimeError(
|
|
185
|
+
'Invalid line format: ' + this.#decoder.decode(line)
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
concatUint8Arrays(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
190
|
+
const c = new Uint8Array(a.length + b.length)
|
|
191
|
+
c.set(a, 0)
|
|
192
|
+
c.set(b, a.length)
|
|
193
|
+
return c
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async downloadSingle(): Promise<Item> {
|
|
197
|
+
const response = await this.#fetch(this.#requestUrlRootObj, {
|
|
198
|
+
headers: this.#headers
|
|
199
|
+
})
|
|
200
|
+
this.#validateResponse(response)
|
|
201
|
+
const responseText = await response.text()
|
|
202
|
+
const item = this.#processJson(this.#options.objectId, responseText)
|
|
203
|
+
item.size = 0
|
|
204
|
+
return item
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
#validateResponse(response: Response): void {
|
|
208
|
+
if (!response.ok) {
|
|
209
|
+
if ([401, 403].includes(response.status)) {
|
|
210
|
+
throw new ObjectLoaderRuntimeError('You do not have access!')
|
|
211
|
+
}
|
|
212
|
+
throw new ObjectLoaderRuntimeError(
|
|
213
|
+
`Failed to fetch objects: ${response.status} ${response.statusText})`
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Queue from '../helpers/queue.js'
|
|
2
|
+
import { Item } from '../types/types.js'
|
|
3
|
+
|
|
4
|
+
export interface Downloader extends Queue<string> {
|
|
5
|
+
initializePool(params: {
|
|
6
|
+
results: Queue<Item>
|
|
7
|
+
total: number
|
|
8
|
+
maxDownloadBatchWait?: number
|
|
9
|
+
}): void
|
|
10
|
+
downloadSingle(): Promise<Item>
|
|
11
|
+
disposeAsync(): Promise<void>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Database {
|
|
15
|
+
getAll(keys: string[]): Promise<(Item | undefined)[]>
|
|
16
|
+
cacheSaveBatch(params: { batch: Item[] }): Promise<void>
|
|
17
|
+
disposeAsync(): Promise<void>
|
|
18
|
+
}
|