@speckle/objectloader2 2.25.1 → 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.
Files changed (222) hide show
  1. package/dist/commonjs/helpers/aggregateQueue.d.ts +8 -0
  2. package/dist/commonjs/helpers/aggregateQueue.d.ts.map +1 -0
  3. package/dist/commonjs/helpers/aggregateQueue.js +19 -0
  4. package/dist/commonjs/helpers/aggregateQueue.js.map +1 -0
  5. package/dist/commonjs/helpers/asyncGeneratorQueue.d.ts +8 -0
  6. package/dist/commonjs/helpers/asyncGeneratorQueue.d.ts.map +1 -0
  7. package/dist/commonjs/helpers/asyncGeneratorQueue.js +35 -0
  8. package/dist/commonjs/helpers/asyncGeneratorQueue.js.map +1 -0
  9. package/dist/commonjs/helpers/batchedPool.d.ts +12 -0
  10. package/dist/commonjs/helpers/batchedPool.d.ts.map +1 -0
  11. package/dist/commonjs/helpers/batchedPool.js +45 -0
  12. package/dist/commonjs/helpers/batchedPool.js.map +1 -0
  13. package/dist/commonjs/helpers/batchingQueue.d.ts +14 -0
  14. package/dist/commonjs/helpers/batchingQueue.d.ts.map +1 -0
  15. package/dist/commonjs/helpers/batchingQueue.js +77 -0
  16. package/dist/commonjs/helpers/batchingQueue.js.map +1 -0
  17. package/dist/commonjs/helpers/bufferQueue.d.ts +7 -0
  18. package/dist/commonjs/helpers/bufferQueue.d.ts.map +1 -0
  19. package/dist/commonjs/helpers/bufferQueue.js +13 -0
  20. package/dist/commonjs/helpers/bufferQueue.js.map +1 -0
  21. package/dist/commonjs/helpers/cachePump.d.ts +22 -0
  22. package/dist/commonjs/helpers/cachePump.d.ts.map +1 -0
  23. package/dist/commonjs/helpers/cachePump.js +86 -0
  24. package/dist/commonjs/helpers/cachePump.js.map +1 -0
  25. package/dist/commonjs/helpers/cacheReader.d.ts +14 -0
  26. package/dist/commonjs/helpers/cacheReader.d.ts.map +1 -0
  27. package/dist/commonjs/helpers/cacheReader.js +58 -0
  28. package/dist/commonjs/helpers/cacheReader.js.map +1 -0
  29. package/dist/commonjs/helpers/defermentManager.d.ts +28 -0
  30. package/dist/commonjs/helpers/defermentManager.d.ts.map +1 -0
  31. package/dist/commonjs/helpers/defermentManager.js +150 -0
  32. package/dist/commonjs/helpers/defermentManager.js.map +1 -0
  33. package/dist/commonjs/helpers/deferredBase.d.ts +19 -0
  34. package/dist/commonjs/helpers/deferredBase.d.ts.map +1 -0
  35. package/dist/commonjs/helpers/deferredBase.js +51 -0
  36. package/dist/commonjs/helpers/deferredBase.js.map +1 -0
  37. package/dist/commonjs/helpers/keyedQueue.d.ts +11 -0
  38. package/dist/commonjs/helpers/keyedQueue.d.ts.map +1 -0
  39. package/dist/commonjs/helpers/keyedQueue.js +41 -0
  40. package/dist/commonjs/helpers/keyedQueue.js.map +1 -0
  41. package/dist/commonjs/helpers/memoryPump.d.ts +15 -0
  42. package/dist/commonjs/helpers/memoryPump.d.ts.map +1 -0
  43. package/dist/commonjs/helpers/memoryPump.js +34 -0
  44. package/dist/commonjs/helpers/memoryPump.js.map +1 -0
  45. package/dist/commonjs/helpers/pump.d.ts +8 -0
  46. package/dist/commonjs/helpers/pump.d.ts.map +1 -0
  47. package/dist/commonjs/helpers/pump.js +3 -0
  48. package/dist/commonjs/helpers/pump.js.map +1 -0
  49. package/dist/commonjs/helpers/queue.d.ts +4 -0
  50. package/dist/commonjs/helpers/queue.d.ts.map +1 -0
  51. package/dist/commonjs/helpers/queue.js +3 -0
  52. package/dist/commonjs/helpers/queue.js.map +1 -0
  53. package/dist/commonjs/index.d.ts +3 -0
  54. package/dist/commonjs/index.d.ts.map +1 -0
  55. package/dist/commonjs/index.js +1 -3
  56. package/dist/commonjs/index.js.map +1 -0
  57. package/dist/commonjs/operations/databases/indexedDatabase.d.ts +27 -0
  58. package/dist/commonjs/operations/databases/indexedDatabase.d.ts.map +1 -0
  59. package/dist/commonjs/operations/databases/indexedDatabase.js +98 -0
  60. package/dist/commonjs/operations/databases/indexedDatabase.js.map +1 -0
  61. package/dist/commonjs/operations/databases/memoryDatabase.d.ts +13 -0
  62. package/dist/commonjs/operations/databases/memoryDatabase.d.ts.map +1 -0
  63. package/dist/commonjs/operations/databases/memoryDatabase.js +33 -0
  64. package/dist/commonjs/operations/databases/memoryDatabase.js.map +1 -0
  65. package/dist/commonjs/operations/downloaders/memoryDownloader.d.ts +16 -0
  66. package/dist/commonjs/operations/downloaders/memoryDownloader.d.ts.map +1 -0
  67. package/dist/commonjs/operations/downloaders/memoryDownloader.js +35 -0
  68. package/dist/commonjs/operations/downloaders/memoryDownloader.js.map +1 -0
  69. package/dist/commonjs/operations/downloaders/serverDownloader.d.ts +32 -0
  70. package/dist/commonjs/operations/downloaders/serverDownloader.d.ts.map +1 -0
  71. package/dist/commonjs/operations/downloaders/serverDownloader.js +169 -0
  72. package/dist/commonjs/operations/downloaders/serverDownloader.js.map +1 -0
  73. package/dist/commonjs/operations/interfaces.d.ts +19 -0
  74. package/dist/commonjs/operations/interfaces.d.ts.map +1 -0
  75. package/dist/commonjs/operations/interfaces.js +3 -0
  76. package/dist/commonjs/operations/interfaces.js.map +1 -0
  77. package/dist/commonjs/operations/objectLoader2.d.ts +16 -0
  78. package/dist/commonjs/operations/objectLoader2.d.ts.map +1 -0
  79. package/dist/commonjs/operations/objectLoader2.js +101 -0
  80. package/dist/commonjs/operations/objectLoader2.js.map +1 -0
  81. package/dist/commonjs/operations/objectLoader2Factory.d.ts +25 -0
  82. package/dist/commonjs/operations/objectLoader2Factory.d.ts.map +1 -0
  83. package/dist/commonjs/operations/objectLoader2Factory.js +68 -0
  84. package/dist/commonjs/operations/objectLoader2Factory.js.map +1 -0
  85. package/dist/commonjs/operations/options.d.ts +26 -0
  86. package/dist/commonjs/operations/options.d.ts.map +1 -0
  87. package/dist/commonjs/operations/options.js +3 -0
  88. package/dist/commonjs/operations/options.js.map +1 -0
  89. package/dist/commonjs/operations/traverser.d.ts +19 -0
  90. package/dist/commonjs/operations/traverser.d.ts.map +1 -0
  91. package/dist/commonjs/operations/traverser.js +96 -0
  92. package/dist/commonjs/operations/traverser.js.map +1 -0
  93. package/dist/commonjs/package.json +3 -0
  94. package/dist/commonjs/types/errors.d.ts +21 -0
  95. package/dist/commonjs/types/errors.d.ts.map +1 -0
  96. package/dist/commonjs/types/errors.js +28 -0
  97. package/dist/commonjs/types/errors.js.map +1 -0
  98. package/dist/commonjs/types/types.d.ts +25 -0
  99. package/dist/commonjs/types/types.d.ts.map +1 -0
  100. package/dist/commonjs/types/types.js +39 -0
  101. package/dist/commonjs/types/types.js.map +1 -0
  102. package/dist/esm/helpers/aggregateQueue.d.ts +8 -0
  103. package/dist/esm/helpers/aggregateQueue.d.ts.map +1 -0
  104. package/dist/esm/helpers/aggregateQueue.js +16 -0
  105. package/dist/esm/helpers/aggregateQueue.js.map +1 -0
  106. package/dist/esm/helpers/asyncGeneratorQueue.d.ts +8 -0
  107. package/dist/esm/helpers/asyncGeneratorQueue.d.ts.map +1 -0
  108. package/dist/esm/helpers/asyncGeneratorQueue.js +32 -0
  109. package/dist/esm/helpers/asyncGeneratorQueue.js.map +1 -0
  110. package/dist/esm/helpers/batchedPool.d.ts +12 -0
  111. package/dist/esm/helpers/batchedPool.d.ts.map +1 -0
  112. package/dist/esm/helpers/batchedPool.js +42 -0
  113. package/dist/esm/helpers/batchedPool.js.map +1 -0
  114. package/dist/esm/helpers/batchingQueue.d.ts +14 -0
  115. package/dist/esm/helpers/batchingQueue.d.ts.map +1 -0
  116. package/dist/esm/helpers/batchingQueue.js +71 -0
  117. package/dist/esm/helpers/batchingQueue.js.map +1 -0
  118. package/dist/esm/helpers/bufferQueue.d.ts +7 -0
  119. package/dist/esm/helpers/bufferQueue.d.ts.map +1 -0
  120. package/dist/esm/helpers/bufferQueue.js +10 -0
  121. package/dist/esm/helpers/bufferQueue.js.map +1 -0
  122. package/dist/esm/helpers/cachePump.d.ts +22 -0
  123. package/dist/esm/helpers/cachePump.d.ts.map +1 -0
  124. package/dist/esm/helpers/cachePump.js +79 -0
  125. package/dist/esm/helpers/cachePump.js.map +1 -0
  126. package/dist/esm/helpers/cacheReader.d.ts +14 -0
  127. package/dist/esm/helpers/cacheReader.d.ts.map +1 -0
  128. package/dist/esm/helpers/cacheReader.js +51 -0
  129. package/dist/esm/helpers/cacheReader.js.map +1 -0
  130. package/dist/esm/helpers/defermentManager.d.ts +28 -0
  131. package/dist/esm/helpers/defermentManager.d.ts.map +1 -0
  132. package/dist/esm/helpers/defermentManager.js +146 -0
  133. package/dist/esm/helpers/defermentManager.js.map +1 -0
  134. package/dist/esm/helpers/deferredBase.d.ts +19 -0
  135. package/dist/esm/helpers/deferredBase.d.ts.map +1 -0
  136. package/dist/esm/helpers/deferredBase.js +47 -0
  137. package/dist/esm/helpers/deferredBase.js.map +1 -0
  138. package/dist/esm/helpers/keyedQueue.d.ts +11 -0
  139. package/dist/esm/helpers/keyedQueue.d.ts.map +1 -0
  140. package/dist/esm/helpers/keyedQueue.js +38 -0
  141. package/dist/esm/helpers/keyedQueue.js.map +1 -0
  142. package/dist/esm/helpers/memoryPump.d.ts +15 -0
  143. package/dist/esm/helpers/memoryPump.d.ts.map +1 -0
  144. package/dist/esm/helpers/memoryPump.js +30 -0
  145. package/dist/esm/helpers/memoryPump.js.map +1 -0
  146. package/dist/esm/helpers/pump.d.ts +8 -0
  147. package/dist/esm/helpers/pump.d.ts.map +1 -0
  148. package/dist/esm/helpers/pump.js +2 -0
  149. package/dist/esm/helpers/pump.js.map +1 -0
  150. package/dist/esm/helpers/queue.d.ts +4 -0
  151. package/dist/esm/helpers/queue.d.ts.map +1 -0
  152. package/dist/esm/helpers/queue.js +2 -0
  153. package/dist/esm/helpers/queue.js.map +1 -0
  154. package/dist/esm/index.d.ts +3 -0
  155. package/dist/esm/index.d.ts.map +1 -0
  156. package/dist/esm/index.js +0 -1
  157. package/dist/esm/index.js.map +1 -0
  158. package/dist/esm/operations/databases/indexedDatabase.d.ts +27 -0
  159. package/dist/esm/operations/databases/indexedDatabase.d.ts.map +1 -0
  160. package/dist/esm/operations/databases/indexedDatabase.js +93 -0
  161. package/dist/esm/operations/databases/indexedDatabase.js.map +1 -0
  162. package/dist/esm/operations/databases/memoryDatabase.d.ts +13 -0
  163. package/dist/esm/operations/databases/memoryDatabase.d.ts.map +1 -0
  164. package/dist/esm/operations/databases/memoryDatabase.js +29 -0
  165. package/dist/esm/operations/databases/memoryDatabase.js.map +1 -0
  166. package/dist/esm/operations/downloaders/memoryDownloader.d.ts +16 -0
  167. package/dist/esm/operations/downloaders/memoryDownloader.d.ts.map +1 -0
  168. package/dist/esm/operations/downloaders/memoryDownloader.js +31 -0
  169. package/dist/esm/operations/downloaders/memoryDownloader.js.map +1 -0
  170. package/dist/esm/operations/downloaders/serverDownloader.d.ts +32 -0
  171. package/dist/esm/operations/downloaders/serverDownloader.d.ts.map +1 -0
  172. package/dist/esm/operations/downloaders/serverDownloader.js +163 -0
  173. package/dist/esm/operations/downloaders/serverDownloader.js.map +1 -0
  174. package/dist/esm/operations/interfaces.d.ts +19 -0
  175. package/dist/esm/operations/interfaces.d.ts.map +1 -0
  176. package/dist/esm/operations/interfaces.js +2 -0
  177. package/dist/esm/operations/interfaces.js.map +1 -0
  178. package/dist/esm/operations/objectLoader2.d.ts +16 -0
  179. package/dist/esm/operations/objectLoader2.d.ts.map +1 -0
  180. package/dist/esm/operations/objectLoader2.js +94 -0
  181. package/dist/esm/operations/objectLoader2.js.map +1 -0
  182. package/dist/esm/operations/objectLoader2Factory.d.ts +25 -0
  183. package/dist/esm/operations/objectLoader2Factory.d.ts.map +1 -0
  184. package/dist/esm/operations/objectLoader2Factory.js +61 -0
  185. package/dist/esm/operations/objectLoader2Factory.js.map +1 -0
  186. package/dist/esm/operations/options.d.ts +26 -0
  187. package/dist/esm/operations/options.d.ts.map +1 -0
  188. package/dist/esm/operations/options.js +2 -0
  189. package/dist/esm/operations/options.js.map +1 -0
  190. package/dist/esm/operations/traverser.d.ts +19 -0
  191. package/dist/esm/operations/traverser.d.ts.map +1 -0
  192. package/dist/esm/operations/traverser.js +93 -0
  193. package/dist/esm/operations/traverser.js.map +1 -0
  194. package/dist/esm/package.json +3 -0
  195. package/dist/esm/types/errors.d.ts +21 -0
  196. package/dist/esm/types/errors.d.ts.map +1 -0
  197. package/dist/esm/types/errors.js +23 -0
  198. package/dist/esm/types/errors.js.map +1 -0
  199. package/dist/esm/types/types.d.ts +25 -0
  200. package/dist/esm/types/types.d.ts.map +1 -0
  201. package/dist/esm/types/types.js +33 -0
  202. package/dist/esm/types/types.js.map +1 -0
  203. package/package.json +2 -2
  204. package/src/helpers/cachePump.disposal.spec.ts +3 -1
  205. package/src/helpers/cachePump.spec.ts +2 -1
  206. package/src/helpers/cachePump.ts +9 -1
  207. package/src/helpers/defermentManager.defermentTotals.spec.ts +53 -0
  208. package/src/helpers/defermentManager.ts +20 -1
  209. package/src/index.ts +0 -1
  210. package/src/operations/databases/__snapshots__/indexedDatabase.spec.ts.snap +13 -26
  211. package/src/operations/databases/indexedDatabase.spec.ts +23 -27
  212. package/src/operations/databases/indexedDatabase.ts +1 -25
  213. package/src/operations/databases/memoryDatabase.spec.ts +48 -0
  214. package/src/operations/databases/memoryDatabase.ts +0 -8
  215. package/src/operations/downloaders/__snapshots__/memoryDownloader.spec.ts.snap +12 -0
  216. package/src/operations/downloaders/memoryDownloader.spec.ts +49 -0
  217. package/src/operations/downloaders/memoryDownloader.ts +1 -1
  218. package/src/operations/downloaders/serverDownloader.ts +1 -1
  219. package/src/operations/interfaces.ts +0 -1
  220. package/src/operations/objectLoader2.ts +12 -4
  221. package/src/operations/objectLoader2Factory.ts +40 -18
  222. package/src/test/e2e.spec.ts +4 -2
@@ -0,0 +1,19 @@
1
+ import { Base } from '../types/types.js';
2
+ import { ObjectLoader2 } from './objectLoader2.js';
3
+ export type ProgressStage = 'download' | 'construction';
4
+ export type OnProgress = (e: {
5
+ stage: ProgressStage;
6
+ current: number;
7
+ total: number;
8
+ }) => void;
9
+ export interface TraverserOptions {
10
+ excludeProps?: string[];
11
+ }
12
+ export default class Traverser {
13
+ #private;
14
+ constructor(loader: ObjectLoader2, options?: TraverserOptions);
15
+ traverse(onProgress?: OnProgress): Promise<Base>;
16
+ traverseArray(array: Array<unknown>, onProgress?: OnProgress): Promise<void>;
17
+ traverseBase(base: Base, onProgress?: OnProgress): Promise<Base>;
18
+ }
19
+ //# sourceMappingURL=traverser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverser.d.ts","sourceRoot":"","sources":["../../../src/operations/traverser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA4C,MAAM,mBAAmB,CAAA;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,cAAc,CAAA;AACvD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE;IAC3B,KAAK,EAAE,aAAa,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,KAAK,IAAI,CAAA;AAEV,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB;AAED,MAAM,CAAC,OAAO,OAAO,SAAS;;gBAOhB,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,gBAAgB;IAKvD,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAehD,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5E,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAuDvE"}
@@ -0,0 +1,93 @@
1
+ import { isBase, isReference, isScalar } from '../types/types.js';
2
+ export default class Traverser {
3
+ #loader;
4
+ #options;
5
+ #totalChildrenCount = 0;
6
+ #traversedReferencesCount = 0;
7
+ constructor(loader, options) {
8
+ this.#options = options || {};
9
+ this.#loader = loader;
10
+ }
11
+ async traverse(onProgress) {
12
+ let firstObjectPromise = undefined;
13
+ for await (const obj of this.#loader.getObjectIterator()) {
14
+ if (!firstObjectPromise) {
15
+ firstObjectPromise = this.traverseBase(obj, onProgress);
16
+ }
17
+ }
18
+ if (firstObjectPromise) {
19
+ return await firstObjectPromise;
20
+ }
21
+ else {
22
+ throw new Error('No objects found');
23
+ }
24
+ }
25
+ async traverseArray(array, onProgress) {
26
+ for (let i = 0; i < 10; i++) {
27
+ const prop = array[i];
28
+ if (isScalar(prop))
29
+ continue;
30
+ if (isBase(prop)) {
31
+ array[i] = await this.traverseBase(prop, onProgress);
32
+ }
33
+ else if (isReference(prop)) {
34
+ array[i] = await this.traverseBase(await this.#loader.getObject({ id: prop.referencedId }), onProgress);
35
+ }
36
+ }
37
+ }
38
+ async traverseBase(base, onProgress) {
39
+ for (const ignoredProp of this.#options.excludeProps || []) {
40
+ delete base[ignoredProp];
41
+ }
42
+ if (base.__closure) {
43
+ const ids = Object.keys(base.__closure);
44
+ const promises = [];
45
+ for (const id of ids) {
46
+ promises.push(this.traverseBase(await this.#loader.getObject({ id }), onProgress));
47
+ }
48
+ await Promise.all(promises);
49
+ }
50
+ delete base['__closure'];
51
+ // De-chunk
52
+ if (base.speckle_type?.includes('DataChunk')) {
53
+ const chunk = base;
54
+ if (chunk.data) {
55
+ await this.traverseArray(chunk.data, onProgress);
56
+ }
57
+ }
58
+ //other props
59
+ for (const prop in base) {
60
+ if (prop === '__closure')
61
+ continue;
62
+ if (prop === 'referenceId')
63
+ continue;
64
+ if (prop === 'speckle_type')
65
+ continue;
66
+ if (prop === 'data')
67
+ continue;
68
+ const baseProp = base[prop];
69
+ if (isScalar(baseProp))
70
+ continue;
71
+ if (isBase(baseProp)) {
72
+ await this.traverseBase(baseProp, onProgress);
73
+ }
74
+ else if (isReference(baseProp)) {
75
+ await this.traverseBase(await this.#loader.getObject({ id: baseProp.referencedId }), onProgress);
76
+ }
77
+ else if (Array.isArray(baseProp)) {
78
+ await this.traverseArray(baseProp, onProgress);
79
+ }
80
+ }
81
+ if (onProgress) {
82
+ onProgress({
83
+ stage: 'construction',
84
+ current: ++this.#traversedReferencesCount > this.#totalChildrenCount
85
+ ? this.#totalChildrenCount
86
+ : this.#traversedReferencesCount,
87
+ total: this.#totalChildrenCount
88
+ });
89
+ }
90
+ return base;
91
+ }
92
+ }
93
+ //# sourceMappingURL=traverser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverser.js","sourceRoot":"","sources":["../../../src/operations/traverser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Base ObjectLoader error
3
+ */
4
+ declare class BaseError extends Error {
5
+ /**
6
+ * Default message if none is passed
7
+ */
8
+ static defaultMessage: string;
9
+ /**
10
+ * @param {string} [message]
11
+ */
12
+ constructor(message: string);
13
+ }
14
+ export declare class ObjectLoaderConfigurationError extends BaseError {
15
+ static defaultMessage: string;
16
+ }
17
+ export declare class ObjectLoaderRuntimeError extends BaseError {
18
+ static defaultMessage: string;
19
+ }
20
+ export {};
21
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/types/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAM,SAAU,SAAQ,KAAK;IAC3B;;OAEG;IACH,MAAM,CAAC,cAAc,SAA8B;IAEnD;;OAEG;gBACS,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,8BAA+B,SAAQ,SAAS;IAC3D,MAAM,CAAC,cAAc,SAA0C;CAChE;AAED,qBAAa,wBAAyB,SAAQ,SAAS;IACrD,MAAM,CAAC,cAAc,SAAiD;CACvE"}
@@ -0,0 +1,23 @@
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
+ * @param {string} [message]
11
+ */
12
+ constructor(message) {
13
+ message ||= new.target.defaultMessage;
14
+ super(message);
15
+ }
16
+ }
17
+ export class ObjectLoaderConfigurationError extends BaseError {
18
+ static defaultMessage = 'Object loader configured incorrectly!';
19
+ }
20
+ export class ObjectLoaderRuntimeError extends BaseError {
21
+ static defaultMessage = 'Object loader encountered a runtime problem!';
22
+ }
23
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/types/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,SAAU,SAAQ,KAAK;IAC3B;;OAEG;IACH,MAAM,CAAC,cAAc,GAAG,2BAA2B,CAAA;IAEnD;;OAEG;IACH,YAAY,OAAe;QACzB,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC,cAAc,CAAA;QACrC,KAAK,CAAC,OAAO,CAAC,CAAA;IAChB,CAAC;;AAGH,MAAM,OAAO,8BAA+B,SAAQ,SAAS;IAC3D,MAAM,CAAC,cAAc,GAAG,uCAAuC,CAAA;;AAGjE,MAAM,OAAO,wBAAyB,SAAQ,SAAS;IACrD,MAAM,CAAC,cAAc,GAAG,8CAA8C,CAAA"}
@@ -0,0 +1,25 @@
1
+ export type CustomLogger = (message?: string, ...optionalParams: unknown[]) => void;
2
+ export type Fetcher = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
3
+ export interface Item {
4
+ baseId: string;
5
+ base: Base;
6
+ size?: number;
7
+ }
8
+ export interface Base {
9
+ id: string;
10
+ speckle_type: string;
11
+ __closure?: Record<string, number>;
12
+ }
13
+ export interface Reference {
14
+ speckle_type: string;
15
+ referencedId: string;
16
+ __closure?: Record<string, number>;
17
+ }
18
+ export interface DataChunk extends Base {
19
+ data?: Base[];
20
+ }
21
+ export declare function isBase(maybeBase?: unknown): maybeBase is Base;
22
+ export declare function isReference(maybeRef?: unknown): maybeRef is Reference;
23
+ export declare function isScalar(value: unknown): value is string | number | boolean | bigint | symbol | undefined;
24
+ export declare function take<T>(it: Iterator<T>, count: number): T[];
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;AAEnF,MAAM,MAAM,OAAO,GAAG,CACpB,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEtB,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,SAAU,SAAQ,IAAI;IACrC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAA;CACd;AAED,wBAAgB,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,IAAI,IAAI,CAO7D;AAED,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,IAAI,SAAS,CAOrE;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAWlE;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAQ3D"}
@@ -0,0 +1,33 @@
1
+ export function isBase(maybeBase) {
2
+ return (maybeBase !== null &&
3
+ typeof maybeBase === 'object' &&
4
+ 'id' in maybeBase &&
5
+ typeof maybeBase.id === 'string');
6
+ }
7
+ export function isReference(maybeRef) {
8
+ return (maybeRef !== null &&
9
+ typeof maybeRef === 'object' &&
10
+ 'referencedId' in maybeRef &&
11
+ typeof maybeRef.referencedId === 'string');
12
+ }
13
+ export function isScalar(value) {
14
+ const type = typeof value;
15
+ return (value === null ||
16
+ type === 'string' ||
17
+ type === 'number' ||
18
+ type === 'boolean' ||
19
+ type === 'bigint' ||
20
+ type === 'symbol' ||
21
+ type === 'undefined');
22
+ }
23
+ export function take(it, count) {
24
+ const result = [];
25
+ for (let i = 0; i < count; i++) {
26
+ const itr = it.next();
27
+ if (itr.done)
28
+ break;
29
+ result.push(itr.value);
30
+ }
31
+ return result;
32
+ }
33
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/types/types.ts"],"names":[],"mappings":"AA6BA,MAAM,UAAU,MAAM,CAAC,SAAmB;IACxC,OAAO,CACL,SAAS,KAAK,IAAI;QAClB,OAAO,SAAS,KAAK,QAAQ;QAC7B,IAAI,IAAI,SAAS;QACjB,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ,CACjC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAkB;IAC5C,OAAO,CACL,QAAQ,KAAK,IAAI;QACjB,OAAO,QAAQ,KAAK,QAAQ;QAC5B,cAAc,IAAI,QAAQ;QAC1B,OAAO,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAC1C,CAAA;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,KAAc;IAEd,MAAM,IAAI,GAAG,OAAO,KAAK,CAAA;IACzB,OAAO,CACL,KAAK,KAAK,IAAI;QACd,IAAI,KAAK,QAAQ;QACjB,IAAI,KAAK,QAAQ;QACjB,IAAI,KAAK,SAAS;QAClB,IAAI,KAAK,QAAQ;QACjB,IAAI,KAAK,QAAQ;QACjB,IAAI,KAAK,WAAW,CACrB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAI,EAAe,EAAE,KAAa;IACpD,MAAM,MAAM,GAAQ,EAAE,CAAA;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;QACrB,IAAI,GAAG,CAAC,IAAI;YAAE,MAAK;QACnB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speckle/objectloader2",
3
- "version": "2.25.1",
3
+ "version": "2.25.7",
4
4
  "description": "This is an updated objectloader for the Speckle viewer written in typescript",
5
5
  "main": "./dist/commonjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -33,7 +33,7 @@
33
33
  "author": "AEC Systems",
34
34
  "license": "Apache-2.0",
35
35
  "dependencies": {
36
- "@speckle/shared": "^2.25.1",
36
+ "@speckle/shared": "^2.25.7",
37
37
  "dexie": "^4.0.11"
38
38
  },
39
39
  "devDependencies": {
@@ -8,7 +8,9 @@ import { DefermentManager } from './defermentManager.js'
8
8
  const makeDatabase = (): Database =>
9
9
  ({
10
10
  cacheSaveBatch: async (): Promise<void> => {},
11
- getAll: async (): Promise<(Item | undefined)[]> => Promise.resolve([])
11
+ getAll: async (): Promise<(Item | undefined)[]> => Promise.resolve([]),
12
+ getItem: async (): Promise<Item | undefined> => Promise.resolve(undefined),
13
+ disposeAsync: async (): Promise<void> => {}
12
14
  } as unknown as Database)
13
15
  const makeGathered = (): AsyncGeneratorQueue<Item> =>
14
16
  ({
@@ -78,7 +78,8 @@ describe('CachePump testing', () => {
78
78
  const i2: Item = { baseId: 'id2', base: { id: 'id', speckle_type: 'type' } }
79
79
 
80
80
  const db: Database = {
81
- getAll: async () => Promise.resolve([])
81
+ getAll: async () => Promise.resolve([]),
82
+ disposeAsync: async (): Promise<void> => {}
82
83
  } as unknown as Database
83
84
  const gathered = new AsyncGeneratorQueue<Item>()
84
85
  const deferments = new DefermentManager({ maxSizeInMb: 1, ttlms: 1 })
@@ -19,6 +19,8 @@ export class CachePump implements Pump {
19
19
 
20
20
  #options: CacheOptions
21
21
 
22
+ #disposed = false
23
+
22
24
  constructor(
23
25
  database: Database,
24
26
  gathered: AsyncGeneratorQueue<Item>,
@@ -46,6 +48,12 @@ export class CachePump implements Pump {
46
48
 
47
49
  async disposeAsync(): Promise<void> {
48
50
  await this.#writeQueue?.disposeAsync()
51
+ await this.#database.disposeAsync()
52
+ this.#disposed = true
53
+ }
54
+
55
+ get isDisposed(): boolean {
56
+ return this.#disposed
49
57
  }
50
58
 
51
59
  async pumpItems(params: {
@@ -57,7 +65,7 @@ export class CachePump implements Pump {
57
65
  const maxCacheReadSize = this.#options.maxCacheReadSize
58
66
 
59
67
  for (let i = 0; i < ids.length; ) {
60
- if (this.#writeQueue?.isDisposed()) break
68
+ if (this.isDisposed) break
61
69
  if ((this.#writeQueue?.count() ?? 0) > this.#options.maxWriteQueueSize) {
62
70
  this.#logger(
63
71
  'pausing reads (# in write queue: ' + this.#writeQueue?.count() + ')'
@@ -0,0 +1,53 @@
1
+ import { describe, test, expect, beforeEach } from 'vitest'
2
+ import { DefermentManager } from './defermentManager.js'
3
+ import { DefermentManagerOptions } from '../operations/options.js'
4
+ import { Base, Item } from '../types/types.js'
5
+
6
+ const makeItem = (id: string, size = 1): Item => ({
7
+ baseId: id,
8
+ base: { foo: 'bar' } as unknown as Base,
9
+ size
10
+ })
11
+
12
+ describe('DefermentManager totalDefermentRequests', () => {
13
+ let manager: DefermentManager
14
+ let options: DefermentManagerOptions
15
+
16
+ beforeEach(() => {
17
+ options = { maxSizeInMb: 1, ttlms: 1000, logger: (): void => {} }
18
+ manager = new DefermentManager(options)
19
+ })
20
+
21
+ test('tracks deferment requests for each id', () => {
22
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
23
+ manager.defer({ id: 'a' })
24
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
25
+ manager.defer({ id: 'a' })
26
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
27
+ manager.defer({ id: 'b' })
28
+ // @ts-expect-error: access private for test
29
+ expect(manager.totalDefermentRequests.get('a')).toBe(2)
30
+ // @ts-expect-error: access private for test
31
+ expect(manager.totalDefermentRequests.get('b')).toBe(1)
32
+ })
33
+
34
+ test('increments and does not reset on undefer', () => {
35
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
36
+ manager.defer({ id: 'x' })
37
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
38
+ manager.defer({ id: 'x' })
39
+ manager.undefer(makeItem('x'))
40
+ // @ts-expect-error: access private for test
41
+ expect(manager.totalDefermentRequests.get('x')).toBe(2)
42
+ // @ts-expect-error: access private for test
43
+ const deferredBase = manager.deferments.get('x')
44
+ expect(deferredBase).toBeDefined()
45
+ expect(deferredBase?.getId()).toBe('x')
46
+ })
47
+
48
+ test('does not increment for undefer only', () => {
49
+ manager.undefer(makeItem('y'))
50
+ // @ts-expect-error: access private for test
51
+ expect(manager.totalDefermentRequests.get('y')).toBeUndefined()
52
+ })
53
+ })
@@ -8,6 +8,9 @@ export class DefermentManager {
8
8
  private logger: CustomLogger
9
9
  private currentSize = 0
10
10
  private disposed = false
11
+ //tracks total deferment requests for each id
12
+ //this is used to prevent cleaning up deferments that are still being requested
13
+ private totalDefermentRequests: Map<string, number> = new Map()
11
14
 
12
15
  constructor(private options: DefermentManagerOptions) {
13
16
  this.resetGlobalTimer()
@@ -29,6 +32,7 @@ export class DefermentManager {
29
32
 
30
33
  async defer(params: { id: string }): Promise<Base> {
31
34
  if (this.disposed) throw new Error('DefermentManager is disposed')
35
+ this.trackDefermentRequest(params.id)
32
36
  const now = this.now()
33
37
  const deferredBase = this.deferments.get(params.id)
34
38
  if (deferredBase) {
@@ -44,6 +48,15 @@ export class DefermentManager {
44
48
  return notYetFound.getPromise()
45
49
  }
46
50
 
51
+ private trackDefermentRequest(id: string): void {
52
+ const request = this.totalDefermentRequests.get(id)
53
+ if (request) {
54
+ this.totalDefermentRequests.set(id, request + 1)
55
+ } else {
56
+ this.totalDefermentRequests.set(id, 1)
57
+ }
58
+ }
59
+
47
60
  undefer(item: Item): void {
48
61
  if (this.disposed) throw new Error('DefermentManager is disposed')
49
62
  const now = this.now()
@@ -108,6 +121,12 @@ export class DefermentManager {
108
121
  .filter((x) => x.isExpired(now))
109
122
  .sort((a, b) => this.compareMaybeBasesBySize(a.getItem(), b.getItem()))) {
110
123
  if (deferredBase.done(now)) {
124
+ //if the deferment is done but has been requested multiple times,
125
+ //we do not clean it up to allow the requests to resolve
126
+ const requestCount = this.totalDefermentRequests.get(deferredBase.getId())
127
+ if (requestCount && requestCount > 1) {
128
+ return
129
+ }
111
130
  this.currentSize -= deferredBase.getItem()?.size || 0
112
131
  this.deferments.delete(deferredBase.getId())
113
132
  cleaned++
@@ -117,7 +136,7 @@ export class DefermentManager {
117
136
  }
118
137
  }
119
138
  this.logger(
120
- 'cleaned deferments, cleaned, left',
139
+ 'cleaned deferments: cleaned, left, time',
121
140
  cleaned,
122
141
  this.deferments.size,
123
142
  performance.now() - start
package/src/index.ts CHANGED
@@ -1,3 +1,2 @@
1
- export { MemoryDatabase } from './operations/databases/memoryDatabase.js'
2
1
  export { ObjectLoader2 } from './operations/objectLoader2.js'
3
2
  export { ObjectLoader2Factory } from './operations/objectLoader2Factory.js'
@@ -1,31 +1,18 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`database cache > write single item to queue use getItem 1`] = `
4
- {
5
- "base": {
6
- "id": "id",
7
- "speckle_type": "type",
3
+ exports[`IndexedDatabase > should add and get multiple items 1`] = `
4
+ [
5
+ {
6
+ "baseId": "id1",
7
+ "item": {
8
+ "foo": "bar",
9
+ },
8
10
  },
9
- "baseId": "id",
10
- }
11
- `;
12
-
13
- exports[`database cache > write two items to queue use getItem 1`] = `
14
- {
15
- "base": {
16
- "id": "id",
17
- "speckle_type": "type",
18
- },
19
- "baseId": "id1",
20
- }
21
- `;
22
-
23
- exports[`database cache > write two items to queue use getItem 2`] = `
24
- {
25
- "base": {
26
- "id": "id",
27
- "speckle_type": "type",
11
+ {
12
+ "baseId": "id2",
13
+ "item": {
14
+ "foo": "bar",
15
+ },
28
16
  },
29
- "baseId": "id2",
30
- }
17
+ ]
31
18
  `;
@@ -1,37 +1,33 @@
1
- import { describe, expect, test } from 'vitest'
2
- import IndexedDatabase from './indexedDatabase.js'
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest'
3
2
  import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
3
+ import IndexedDatabase, { IndexedDatabaseOptions } from './indexedDatabase.js'
4
4
  import { Item } from '../../types/types.js'
5
5
 
6
- describe('database cache', () => {
7
- test('write single item to queue use getItem', async () => {
8
- const i: Item = { baseId: 'id', base: { id: 'id', speckle_type: 'type' } }
9
- const database = new IndexedDatabase({
10
- indexedDB: new IDBFactory(),
11
- keyRange: IDBKeyRange
12
- })
13
- await database.add(i)
14
- await database.disposeAsync()
6
+ // Mock Item
7
+ const defaultItem = (id: string): Item => ({ baseId: id, item: { foo: 'bar' } })
15
8
 
16
- const x = await database.getItem({ id: 'id' })
17
- expect(x).toMatchSnapshot()
9
+ describe('IndexedDatabase', () => {
10
+ let db: IndexedDatabase
11
+ let options: IndexedDatabaseOptions
12
+
13
+ beforeEach(() => {
14
+ options = { indexedDB: new IDBFactory(), keyRange: IDBKeyRange }
15
+ db = new IndexedDatabase(options)
18
16
  })
19
17
 
20
- test('write two items to queue use getItem', async () => {
21
- const i1: Item = { baseId: 'id1', base: { id: 'id', speckle_type: 'type' } }
22
- const i2: Item = { baseId: 'id2', base: { id: 'id', speckle_type: 'type' } }
23
- const database = new IndexedDatabase({
24
- indexedDB: new IDBFactory(),
25
- keyRange: IDBKeyRange
26
- })
27
- await database.add(i1)
28
- await database.add(i2)
29
- await database.disposeAsync()
18
+ afterEach(async () => {
19
+ await db.disposeAsync()
20
+ })
30
21
 
31
- const x1 = await database.getItem({ id: i1.baseId })
32
- expect(x1).toMatchSnapshot()
22
+ it('should add and get multiple items', async () => {
23
+ const items = [defaultItem('id1'), defaultItem('id2')]
24
+ await db.cacheSaveBatch({ batch: items })
25
+ const result = await db.getAll(['id1', 'id2'])
26
+ expect(result).toMatchSnapshot()
27
+ expect(result).toEqual(items)
28
+ })
33
29
 
34
- const x2 = await database.getItem({ id: i2.baseId })
35
- expect(x2).toMatchSnapshot()
30
+ it('should dispose without error', async () => {
31
+ await expect(db.disposeAsync()).resolves.not.toThrow()
36
32
  })
37
33
  })
@@ -5,7 +5,7 @@ import { isSafari } from '@speckle/shared'
5
5
  import { Dexie, DexieOptions, Table } from 'dexie'
6
6
  import { Database } from '../interfaces.js'
7
7
 
8
- class ObjectStore extends Dexie {
8
+ export class ObjectStore extends Dexie {
9
9
  static #databaseName: string = 'speckle-cache'
10
10
  objects!: Table<Item, string> // Table type: <entity, primaryKey>
11
11
 
@@ -83,30 +83,6 @@ export default class IndexedDatabase implements Database {
83
83
  this.#cacheDB = await this.#openDatabase()
84
84
  }
85
85
 
86
- //this is for testing only - in the real world we will not use this
87
- async add(item: Item): Promise<void> {
88
- await this.#setupCacheDb()
89
- await this.#cacheDB!.transaction('rw', this.#cacheDB!.objects, async () => {
90
- return await this.#cacheDB?.objects.add(item)
91
- })
92
- }
93
-
94
- async getItem(params: { id: string }): Promise<Item | undefined> {
95
- const { id } = params
96
- await this.#setupCacheDb()
97
- //might not be in the real DB yet, so check the write queue first
98
- if (this.#writeQueue) {
99
- const item = this.#writeQueue.get(id)
100
- if (item) {
101
- return item
102
- }
103
- }
104
-
105
- return this.#cacheDB!.transaction('r', this.#cacheDB!.objects, async () => {
106
- return await this.#cacheDB?.objects.get(id)
107
- })
108
- }
109
-
110
86
  async cacheSaveBatch(params: { batch: Item[] }): Promise<void> {
111
87
  await this.#setupCacheDb()
112
88
  const { batch } = params
@@ -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
+ })
@@ -29,14 +29,6 @@ export class MemoryDatabase implements Database {
29
29
  return Promise.resolve()
30
30
  }
31
31
 
32
- getItem(params: { id: string }): Promise<Item | undefined> {
33
- const item = this.items.get(params.id)
34
- if (item) {
35
- return Promise.resolve({ baseId: params.id, base: item })
36
- }
37
- return Promise.resolve(undefined)
38
- }
39
-
40
32
  disposeAsync(): Promise<void> {
41
33
  return Promise.resolve()
42
34
  }