@verdant-web/store 2.8.4 → 3.0.0-next.0

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 (307) hide show
  1. package/dist/bundle/index.js +9 -10
  2. package/dist/bundle/index.js.map +4 -4
  3. package/dist/cjs/DocumentManager.d.ts +6 -5
  4. package/dist/cjs/DocumentManager.js +2 -2
  5. package/dist/cjs/DocumentManager.js.map +1 -1
  6. package/dist/cjs/IDBService.d.ts +28 -7
  7. package/dist/cjs/IDBService.js +50 -13
  8. package/dist/cjs/IDBService.js.map +1 -1
  9. package/dist/cjs/UndoHistory.d.ts +1 -1
  10. package/dist/cjs/UndoHistory.js +6 -2
  11. package/dist/cjs/UndoHistory.js.map +1 -1
  12. package/dist/cjs/__tests__/batching.test.js +3 -1
  13. package/dist/cjs/__tests__/batching.test.js.map +1 -1
  14. package/dist/cjs/__tests__/documents.test.js +54 -6
  15. package/dist/cjs/__tests__/documents.test.js.map +1 -1
  16. package/dist/cjs/__tests__/fixtures/testStorage.d.ts +8 -2
  17. package/dist/cjs/__tests__/fixtures/testStorage.js +8 -1
  18. package/dist/cjs/__tests__/fixtures/testStorage.js.map +1 -1
  19. package/dist/cjs/__tests__/legacyOids.test.js +50 -17
  20. package/dist/cjs/__tests__/legacyOids.test.js.map +1 -1
  21. package/dist/cjs/__tests__/mutations.test.js +9 -3
  22. package/dist/cjs/__tests__/mutations.test.js.map +1 -1
  23. package/dist/cjs/__tests__/queries.test.js +6 -2
  24. package/dist/cjs/__tests__/queries.test.js.map +1 -1
  25. package/dist/cjs/__tests__/setup/indexedDB.d.ts +1 -1
  26. package/dist/cjs/__tests__/setup/indexedDB.js +13 -1
  27. package/dist/cjs/__tests__/setup/indexedDB.js.map +1 -1
  28. package/dist/cjs/__tests__/undo.test.js +16 -9
  29. package/dist/cjs/__tests__/undo.test.js.map +1 -1
  30. package/dist/cjs/client/Client.d.ts +2 -3
  31. package/dist/cjs/client/Client.js +8 -4
  32. package/dist/cjs/client/Client.js.map +1 -1
  33. package/dist/cjs/client/ClientDescriptor.js +21 -6
  34. package/dist/cjs/client/ClientDescriptor.js.map +1 -1
  35. package/dist/cjs/context.d.ts +10 -1
  36. package/dist/cjs/entities/2/Entity.d.ts +148 -0
  37. package/dist/cjs/entities/2/Entity.js +711 -0
  38. package/dist/cjs/entities/2/Entity.js.map +1 -0
  39. package/dist/cjs/entities/2/Entity.test.d.ts +1 -0
  40. package/dist/cjs/entities/2/Entity.test.js +194 -0
  41. package/dist/cjs/entities/2/Entity.test.js.map +1 -0
  42. package/dist/cjs/entities/2/EntityCache.d.ts +15 -0
  43. package/dist/cjs/entities/2/EntityCache.js +39 -0
  44. package/dist/cjs/entities/2/EntityCache.js.map +1 -0
  45. package/dist/cjs/entities/2/EntityMetadata.d.ts +68 -0
  46. package/dist/cjs/entities/2/EntityMetadata.js +261 -0
  47. package/dist/cjs/entities/2/EntityMetadata.js.map +1 -0
  48. package/dist/cjs/entities/2/EntityStore.d.ts +78 -0
  49. package/dist/cjs/entities/2/EntityStore.js +352 -0
  50. package/dist/cjs/entities/2/EntityStore.js.map +1 -0
  51. package/dist/cjs/entities/2/OperationBatcher.d.ts +52 -0
  52. package/dist/cjs/entities/2/OperationBatcher.js +165 -0
  53. package/dist/cjs/entities/2/OperationBatcher.js.map +1 -0
  54. package/dist/cjs/entities/2/types.d.ts +84 -0
  55. package/dist/cjs/entities/2/types.js +3 -0
  56. package/dist/cjs/entities/2/types.js.map +1 -0
  57. package/dist/cjs/entities/Entity.d.ts +0 -7
  58. package/dist/cjs/entities/Entity.js +7 -0
  59. package/dist/cjs/entities/Entity.js.map +1 -1
  60. package/dist/cjs/entities/EntityStore.js +4 -20
  61. package/dist/cjs/entities/EntityStore.js.map +1 -1
  62. package/dist/cjs/entities/FakeWeakRef.d.ts +11 -0
  63. package/dist/cjs/entities/FakeWeakRef.js +19 -0
  64. package/dist/cjs/entities/FakeWeakRef.js.map +1 -0
  65. package/dist/cjs/files/EntityFile.d.ts +5 -2
  66. package/dist/cjs/files/EntityFile.js +8 -4
  67. package/dist/cjs/files/EntityFile.js.map +1 -1
  68. package/dist/cjs/files/FileManager.d.ts +3 -1
  69. package/dist/cjs/files/FileManager.js +5 -3
  70. package/dist/cjs/files/FileManager.js.map +1 -1
  71. package/dist/cjs/files/FileStorage.js +7 -7
  72. package/dist/cjs/files/FileStorage.js.map +1 -1
  73. package/dist/cjs/files/utils.d.ts +2 -0
  74. package/dist/cjs/files/utils.js +8 -2
  75. package/dist/cjs/files/utils.js.map +1 -1
  76. package/dist/cjs/idb.d.ts +2 -0
  77. package/dist/cjs/idb.js +50 -4
  78. package/dist/cjs/idb.js.map +1 -1
  79. package/dist/cjs/index.d.ts +2 -2
  80. package/dist/cjs/index.js +1 -1
  81. package/dist/cjs/index.js.map +1 -1
  82. package/dist/cjs/indexes.d.ts +3 -0
  83. package/dist/cjs/indexes.js +20 -0
  84. package/dist/cjs/indexes.js.map +1 -0
  85. package/dist/cjs/metadata/AckInfoStore.js +1 -1
  86. package/dist/cjs/metadata/AckInfoStore.js.map +1 -1
  87. package/dist/cjs/metadata/BaselinesStore.d.ts +4 -1
  88. package/dist/cjs/metadata/BaselinesStore.js +19 -10
  89. package/dist/cjs/metadata/BaselinesStore.js.map +1 -1
  90. package/dist/cjs/metadata/LocalReplicaStore.d.ts +1 -1
  91. package/dist/cjs/metadata/LocalReplicaStore.js +11 -5
  92. package/dist/cjs/metadata/LocalReplicaStore.js.map +1 -1
  93. package/dist/cjs/metadata/Metadata.d.ts +26 -5
  94. package/dist/cjs/metadata/Metadata.js +55 -18
  95. package/dist/cjs/metadata/Metadata.js.map +1 -1
  96. package/dist/cjs/metadata/OperationsStore.d.ts +3 -0
  97. package/dist/cjs/metadata/OperationsStore.js +35 -15
  98. package/dist/cjs/metadata/OperationsStore.js.map +1 -1
  99. package/dist/cjs/migration/openDatabase.js +31 -10
  100. package/dist/cjs/migration/openDatabase.js.map +1 -1
  101. package/dist/cjs/queries/BaseQuery.js +14 -2
  102. package/dist/cjs/queries/BaseQuery.js.map +1 -1
  103. package/dist/cjs/queries/CollectionQueries.d.ts +2 -4
  104. package/dist/cjs/queries/CollectionQueries.js +1 -1
  105. package/dist/cjs/queries/CollectionQueries.js.map +1 -1
  106. package/dist/cjs/queries/FindAllQuery.js +1 -0
  107. package/dist/cjs/queries/FindAllQuery.js.map +1 -1
  108. package/dist/cjs/queries/QueryCache.d.ts +1 -0
  109. package/dist/cjs/queries/QueryCache.js +4 -0
  110. package/dist/cjs/queries/QueryCache.js.map +1 -1
  111. package/dist/cjs/queries/QueryableStorage.d.ts +20 -0
  112. package/dist/cjs/queries/QueryableStorage.js +84 -0
  113. package/dist/cjs/queries/QueryableStorage.js.map +1 -0
  114. package/dist/cjs/queries/dbQueries.js +13 -3
  115. package/dist/cjs/queries/dbQueries.js.map +1 -1
  116. package/dist/cjs/queries/utils.js +1 -1
  117. package/dist/cjs/queries/utils.js.map +1 -1
  118. package/dist/cjs/sync/FileSync.d.ts +1 -0
  119. package/dist/cjs/sync/FileSync.js +1 -0
  120. package/dist/cjs/sync/FileSync.js.map +1 -1
  121. package/dist/cjs/sync/PushPullSync.d.ts +2 -1
  122. package/dist/cjs/sync/PushPullSync.js +7 -1
  123. package/dist/cjs/sync/PushPullSync.js.map +1 -1
  124. package/dist/cjs/sync/Sync.d.ts +6 -3
  125. package/dist/cjs/sync/Sync.js +9 -4
  126. package/dist/cjs/sync/Sync.js.map +1 -1
  127. package/dist/cjs/sync/WebSocketSync.d.ts +4 -1
  128. package/dist/cjs/sync/WebSocketSync.js +41 -11
  129. package/dist/cjs/sync/WebSocketSync.js.map +1 -1
  130. package/dist/esm/DocumentManager.d.ts +6 -5
  131. package/dist/esm/DocumentManager.js +2 -2
  132. package/dist/esm/DocumentManager.js.map +1 -1
  133. package/dist/esm/IDBService.d.ts +28 -7
  134. package/dist/esm/IDBService.js +51 -14
  135. package/dist/esm/IDBService.js.map +1 -1
  136. package/dist/esm/UndoHistory.d.ts +1 -1
  137. package/dist/esm/UndoHistory.js +6 -2
  138. package/dist/esm/UndoHistory.js.map +1 -1
  139. package/dist/esm/__tests__/batching.test.js +3 -1
  140. package/dist/esm/__tests__/batching.test.js.map +1 -1
  141. package/dist/esm/__tests__/documents.test.js +54 -6
  142. package/dist/esm/__tests__/documents.test.js.map +1 -1
  143. package/dist/esm/__tests__/fixtures/testStorage.d.ts +8 -2
  144. package/dist/esm/__tests__/fixtures/testStorage.js +8 -1
  145. package/dist/esm/__tests__/fixtures/testStorage.js.map +1 -1
  146. package/dist/esm/__tests__/legacyOids.test.js +50 -17
  147. package/dist/esm/__tests__/legacyOids.test.js.map +1 -1
  148. package/dist/esm/__tests__/mutations.test.js +9 -3
  149. package/dist/esm/__tests__/mutations.test.js.map +1 -1
  150. package/dist/esm/__tests__/queries.test.js +6 -2
  151. package/dist/esm/__tests__/queries.test.js.map +1 -1
  152. package/dist/esm/__tests__/setup/indexedDB.d.ts +1 -1
  153. package/dist/esm/__tests__/setup/indexedDB.js +13 -1
  154. package/dist/esm/__tests__/setup/indexedDB.js.map +1 -1
  155. package/dist/esm/__tests__/undo.test.js +16 -9
  156. package/dist/esm/__tests__/undo.test.js.map +1 -1
  157. package/dist/esm/client/Client.d.ts +2 -3
  158. package/dist/esm/client/Client.js +8 -4
  159. package/dist/esm/client/Client.js.map +1 -1
  160. package/dist/esm/client/ClientDescriptor.js +21 -6
  161. package/dist/esm/client/ClientDescriptor.js.map +1 -1
  162. package/dist/esm/context.d.ts +10 -1
  163. package/dist/esm/entities/2/Entity.d.ts +148 -0
  164. package/dist/esm/entities/2/Entity.js +707 -0
  165. package/dist/esm/entities/2/Entity.js.map +1 -0
  166. package/dist/esm/entities/2/Entity.test.d.ts +1 -0
  167. package/dist/esm/entities/2/Entity.test.js +192 -0
  168. package/dist/esm/entities/2/Entity.test.js.map +1 -0
  169. package/dist/esm/entities/2/EntityCache.d.ts +15 -0
  170. package/dist/esm/entities/2/EntityCache.js +35 -0
  171. package/dist/esm/entities/2/EntityCache.js.map +1 -0
  172. package/dist/esm/entities/2/EntityMetadata.d.ts +68 -0
  173. package/dist/esm/entities/2/EntityMetadata.js +256 -0
  174. package/dist/esm/entities/2/EntityMetadata.js.map +1 -0
  175. package/dist/esm/entities/2/EntityStore.d.ts +78 -0
  176. package/dist/esm/entities/2/EntityStore.js +348 -0
  177. package/dist/esm/entities/2/EntityStore.js.map +1 -0
  178. package/dist/esm/entities/2/OperationBatcher.d.ts +52 -0
  179. package/dist/esm/entities/2/OperationBatcher.js +161 -0
  180. package/dist/esm/entities/2/OperationBatcher.js.map +1 -0
  181. package/dist/esm/entities/2/types.d.ts +84 -0
  182. package/dist/esm/entities/2/types.js +2 -0
  183. package/dist/esm/entities/2/types.js.map +1 -0
  184. package/dist/esm/entities/Entity.d.ts +0 -7
  185. package/dist/esm/entities/Entity.js +7 -0
  186. package/dist/esm/entities/Entity.js.map +1 -1
  187. package/dist/esm/entities/EntityStore.js +4 -20
  188. package/dist/esm/entities/EntityStore.js.map +1 -1
  189. package/dist/esm/entities/FakeWeakRef.d.ts +11 -0
  190. package/dist/esm/entities/FakeWeakRef.js +15 -0
  191. package/dist/esm/entities/FakeWeakRef.js.map +1 -0
  192. package/dist/esm/files/EntityFile.d.ts +5 -2
  193. package/dist/esm/files/EntityFile.js +8 -4
  194. package/dist/esm/files/EntityFile.js.map +1 -1
  195. package/dist/esm/files/FileManager.d.ts +3 -1
  196. package/dist/esm/files/FileManager.js +5 -3
  197. package/dist/esm/files/FileManager.js.map +1 -1
  198. package/dist/esm/files/FileStorage.js +7 -7
  199. package/dist/esm/files/FileStorage.js.map +1 -1
  200. package/dist/esm/files/utils.d.ts +2 -0
  201. package/dist/esm/files/utils.js +6 -1
  202. package/dist/esm/files/utils.js.map +1 -1
  203. package/dist/esm/idb.d.ts +2 -0
  204. package/dist/esm/idb.js +47 -3
  205. package/dist/esm/idb.js.map +1 -1
  206. package/dist/esm/index.d.ts +2 -2
  207. package/dist/esm/index.js +1 -1
  208. package/dist/esm/index.js.map +1 -1
  209. package/dist/esm/indexes.d.ts +3 -0
  210. package/dist/esm/indexes.js +15 -0
  211. package/dist/esm/indexes.js.map +1 -0
  212. package/dist/esm/metadata/AckInfoStore.js +1 -1
  213. package/dist/esm/metadata/AckInfoStore.js.map +1 -1
  214. package/dist/esm/metadata/BaselinesStore.d.ts +4 -1
  215. package/dist/esm/metadata/BaselinesStore.js +19 -10
  216. package/dist/esm/metadata/BaselinesStore.js.map +1 -1
  217. package/dist/esm/metadata/LocalReplicaStore.d.ts +1 -1
  218. package/dist/esm/metadata/LocalReplicaStore.js +11 -5
  219. package/dist/esm/metadata/LocalReplicaStore.js.map +1 -1
  220. package/dist/esm/metadata/Metadata.d.ts +26 -5
  221. package/dist/esm/metadata/Metadata.js +56 -19
  222. package/dist/esm/metadata/Metadata.js.map +1 -1
  223. package/dist/esm/metadata/OperationsStore.d.ts +3 -0
  224. package/dist/esm/metadata/OperationsStore.js +35 -15
  225. package/dist/esm/metadata/OperationsStore.js.map +1 -1
  226. package/dist/esm/migration/openDatabase.js +32 -11
  227. package/dist/esm/migration/openDatabase.js.map +1 -1
  228. package/dist/esm/queries/BaseQuery.js +14 -2
  229. package/dist/esm/queries/BaseQuery.js.map +1 -1
  230. package/dist/esm/queries/CollectionQueries.d.ts +2 -4
  231. package/dist/esm/queries/CollectionQueries.js +1 -1
  232. package/dist/esm/queries/CollectionQueries.js.map +1 -1
  233. package/dist/esm/queries/FindAllQuery.js +1 -0
  234. package/dist/esm/queries/FindAllQuery.js.map +1 -1
  235. package/dist/esm/queries/QueryCache.d.ts +1 -0
  236. package/dist/esm/queries/QueryCache.js +4 -0
  237. package/dist/esm/queries/QueryCache.js.map +1 -1
  238. package/dist/esm/queries/QueryableStorage.d.ts +20 -0
  239. package/dist/esm/queries/QueryableStorage.js +80 -0
  240. package/dist/esm/queries/QueryableStorage.js.map +1 -0
  241. package/dist/esm/queries/dbQueries.js +13 -3
  242. package/dist/esm/queries/dbQueries.js.map +1 -1
  243. package/dist/esm/queries/utils.js +1 -1
  244. package/dist/esm/queries/utils.js.map +1 -1
  245. package/dist/esm/sync/FileSync.d.ts +1 -0
  246. package/dist/esm/sync/FileSync.js +1 -0
  247. package/dist/esm/sync/FileSync.js.map +1 -1
  248. package/dist/esm/sync/PushPullSync.d.ts +2 -1
  249. package/dist/esm/sync/PushPullSync.js +7 -1
  250. package/dist/esm/sync/PushPullSync.js.map +1 -1
  251. package/dist/esm/sync/Sync.d.ts +6 -3
  252. package/dist/esm/sync/Sync.js +9 -4
  253. package/dist/esm/sync/Sync.js.map +1 -1
  254. package/dist/esm/sync/WebSocketSync.d.ts +4 -1
  255. package/dist/esm/sync/WebSocketSync.js +41 -11
  256. package/dist/esm/sync/WebSocketSync.js.map +1 -1
  257. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  258. package/dist/tsconfig.tsbuildinfo +1 -1
  259. package/package.json +8 -7
  260. package/src/DocumentManager.ts +3 -7
  261. package/src/IDBService.ts +78 -17
  262. package/src/UndoHistory.ts +5 -3
  263. package/src/__tests__/batching.test.ts +5 -2
  264. package/src/__tests__/documents.test.ts +66 -6
  265. package/src/__tests__/fixtures/testStorage.ts +9 -0
  266. package/src/__tests__/legacyOids.test.ts +53 -17
  267. package/src/__tests__/mutations.test.ts +9 -3
  268. package/src/__tests__/queries.test.ts +6 -2
  269. package/src/__tests__/setup/indexedDB.ts +14 -1
  270. package/src/__tests__/undo.test.ts +17 -9
  271. package/src/client/Client.ts +8 -4
  272. package/src/client/ClientDescriptor.ts +24 -8
  273. package/src/context.ts +16 -1
  274. package/src/entities/2/Entity.test.ts +218 -0
  275. package/src/entities/2/Entity.ts +954 -0
  276. package/src/entities/2/EntityCache.ts +41 -0
  277. package/src/entities/2/EntityMetadata.ts +364 -0
  278. package/src/entities/2/EntityStore.ts +490 -0
  279. package/src/entities/2/NOTES.md +22 -0
  280. package/src/entities/2/OperationBatcher.ts +251 -0
  281. package/src/entities/2/types.ts +154 -0
  282. package/src/files/EntityFile.ts +9 -4
  283. package/src/files/FileManager.ts +5 -3
  284. package/src/files/FileStorage.ts +7 -13
  285. package/src/files/utils.ts +9 -1
  286. package/src/idb.ts +51 -3
  287. package/src/index.ts +2 -2
  288. package/src/metadata/AckInfoStore.ts +1 -1
  289. package/src/metadata/BaselinesStore.ts +16 -24
  290. package/src/metadata/LocalReplicaStore.ts +13 -6
  291. package/src/metadata/Metadata.ts +109 -24
  292. package/src/metadata/OperationsStore.ts +37 -16
  293. package/src/migration/openDatabase.ts +32 -10
  294. package/src/queries/BaseQuery.ts +15 -2
  295. package/src/queries/CollectionQueries.ts +3 -3
  296. package/src/queries/FindAllQuery.ts +4 -0
  297. package/src/queries/QueryCache.ts +5 -0
  298. package/src/queries/QueryableStorage.ts +107 -0
  299. package/src/queries/dbQueries.ts +10 -3
  300. package/src/queries/utils.ts +1 -1
  301. package/src/sync/FileSync.ts +2 -0
  302. package/src/sync/PushPullSync.ts +8 -1
  303. package/src/sync/Sync.ts +14 -6
  304. package/src/sync/WebSocketSync.ts +47 -10
  305. package/src/entities/DocumentFamiliyCache.ts +0 -426
  306. package/src/entities/Entity.ts +0 -874
  307. package/src/entities/EntityStore.ts +0 -731
@@ -1,6 +1,6 @@
1
1
  import { CollectionFilter, hashObject } from '@verdant-web/common';
2
2
  import { Context } from '../context.js';
3
- import { EntityStore } from '../entities/EntityStore.js';
3
+ import { EntityStore } from '../entities/2/EntityStore.js';
4
4
  import { GetQuery } from './GetQuery.js';
5
5
  import { QueryCache } from './QueryCache.js';
6
6
  import { FindOneQuery } from './FindOneQuery.js';
@@ -22,7 +22,7 @@ export class CollectionQueries<
22
22
  private context;
23
23
  private documentManager;
24
24
 
25
- put: (init: Init, options?: { undoable?: boolean }) => Promise<T>;
25
+ put: (init: Init) => Promise<T>;
26
26
  delete: (id: string, options?: { undoable?: boolean }) => Promise<void>;
27
27
  deleteAll: (ids: string[], options?: { undoable?: boolean }) => Promise<void>;
28
28
 
@@ -41,7 +41,7 @@ export class CollectionQueries<
41
41
  }) {
42
42
  this.cache = cache;
43
43
  this.collection = collection;
44
- this.hydrate = entities.get as any;
44
+ this.hydrate = entities.hydrate as any;
45
45
  this.context = context;
46
46
  this.documentManager = documentManager;
47
47
 
@@ -29,6 +29,10 @@ export class FindAllQuery<T> extends BaseQuery<T[]> {
29
29
  index: this.index,
30
30
  context: this.context,
31
31
  });
32
+ this.context.log(
33
+ 'debug',
34
+ `FindAllQuery: ${oids.length} oids found: ${oids}`,
35
+ );
32
36
  this.setValue(await Promise.all(oids.map(this.hydrate)));
33
37
  };
34
38
 
@@ -53,4 +53,9 @@ export class QueryCache extends Disposable {
53
53
  }
54
54
  }, this._evictionTime);
55
55
  };
56
+
57
+ dropAll = () => {
58
+ this._cache.forEach((query) => query.dispose());
59
+ this._cache.clear();
60
+ };
56
61
  }
@@ -0,0 +1,107 @@
1
+ import {
2
+ ObjectIdentifier,
3
+ decomposeOid,
4
+ getIndexValues,
5
+ } from '@verdant-web/common';
6
+ import { IDBService } from '../IDBService.js';
7
+ import { Context } from '../context.js';
8
+ import { storeRequestPromise } from '../idb.js';
9
+
10
+ export class QueryableStorage extends IDBService {
11
+ private ctx;
12
+
13
+ constructor({ ctx }: { ctx: Context }) {
14
+ super(ctx.documentDb, { log: ctx.log });
15
+ this.ctx = ctx;
16
+ this.addDispose(
17
+ this.ctx.internalEvents.subscribe('documentDbChanged', (db) => {
18
+ this.db = db;
19
+ }),
20
+ );
21
+ }
22
+
23
+ /**
24
+ * DELETES EVERYTHING IN THE QUERYABLE DATABASE
25
+ */
26
+ reset = async () => {
27
+ const allCollections = Object.keys(this.ctx.schema.collections);
28
+ const tx = this.ctx.documentDb.transaction(allCollections, 'readwrite');
29
+ await Promise.all(
30
+ allCollections.map((collection) => {
31
+ const store = tx.objectStore(collection);
32
+ return storeRequestPromise(store.clear());
33
+ }),
34
+ );
35
+ // notify queries to re-run now.
36
+ this.ctx.entityEvents.emit('collectionsChanged', allCollections);
37
+ this.ctx.log('info', '💨 Reset queryable storage');
38
+ };
39
+
40
+ saveEntities = async (
41
+ entities: { oid: ObjectIdentifier; getSnapshot: () => any }[],
42
+ opts?: { abort?: AbortSignal },
43
+ ) => {
44
+ if (entities.length === 0) {
45
+ return;
46
+ }
47
+
48
+ const collections = Array.from(
49
+ new Set(entities.map((e) => decomposeOid(e.oid).collection)),
50
+ );
51
+ const options = {
52
+ transaction: this.createTransaction(collections, {
53
+ mode: 'readwrite',
54
+ abort: opts?.abort,
55
+ }),
56
+ };
57
+ await Promise.all(
58
+ entities.map(async (e) => {
59
+ const snapshot = e.getSnapshot();
60
+ try {
61
+ await this.saveDocument(e.oid, snapshot, options);
62
+ } catch (err) {
63
+ this.ctx.log(
64
+ 'error',
65
+ `Error saving document ${e.oid} (${JSON.stringify(snapshot)})`,
66
+ err,
67
+ );
68
+ if (err instanceof Error) {
69
+ throw err;
70
+ } else {
71
+ throw new Error('Unknown error saving document');
72
+ }
73
+ }
74
+ }),
75
+ );
76
+ options.transaction.commit();
77
+ this.ctx.entityEvents.emit('collectionsChanged', collections);
78
+ for (const entity of entities) {
79
+ this.ctx.entityEvents.emit('documentChanged', entity.oid);
80
+ }
81
+ };
82
+
83
+ private saveDocument = async (
84
+ oid: ObjectIdentifier,
85
+ doc: any,
86
+ { transaction }: { transaction?: IDBTransaction },
87
+ ) => {
88
+ this.ctx.log('debug', `Saving document indexes for querying ${oid}`, doc);
89
+ const { collection, id } = decomposeOid(oid);
90
+ if (!doc) {
91
+ await this.run(collection, (store) => store.delete(id), {
92
+ mode: 'readwrite',
93
+ transaction,
94
+ });
95
+ this.ctx.log('debug', `Deleted document indexes for querying ${oid}`);
96
+ } else {
97
+ const schema = this.ctx.schema.collections[collection];
98
+ // no need to validate before storing; the entity's snapshot is already validated.
99
+ const indexes = getIndexValues(schema, doc);
100
+ await this.run(collection, (store) => store.put(indexes), {
101
+ mode: 'readwrite',
102
+ transaction,
103
+ });
104
+ this.ctx.log('debug', `Saved document indexes for querying ${oid}`, doc);
105
+ }
106
+ };
107
+ }
@@ -1,6 +1,7 @@
1
1
  import { CollectionFilter, createOid } from '@verdant-web/common';
2
2
  import { Context } from '../context.js';
3
3
  import { getRange } from './ranges.js';
4
+ import { isAbortError } from '../idb.js';
4
5
 
5
6
  function getStore(db: IDBDatabase, collection: string, write?: boolean) {
6
7
  return db
@@ -18,7 +19,7 @@ export async function findOneOid({
18
19
  context: Context;
19
20
  }) {
20
21
  const store = getStore(context.documentDb, collection);
21
- const source = index ? store.index(index.where) : store;
22
+ const source = index?.where ? store.index(index.where) : store;
22
23
  const range = getRange(context.schema, collection, index);
23
24
  const direction = index?.order === 'desc' ? 'prev' : 'next';
24
25
  const request = source.openCursor(range, direction);
@@ -39,6 +40,8 @@ export async function findOneOid({
39
40
  request.error,
40
41
  );
41
42
  resolve(null);
43
+ } else if (isAbortError(request.error)) {
44
+ resolve(null);
42
45
  } else {
43
46
  reject(request.error);
44
47
  }
@@ -57,7 +60,7 @@ export async function findAllOids({
57
60
  context: Context;
58
61
  }) {
59
62
  const store = getStore(context.documentDb, collection);
60
- const source = index ? store.index(index.where) : store;
63
+ const source = index?.where ? store.index(index.where) : store;
61
64
  const range = getRange(context.schema, collection, index);
62
65
  const direction = index?.order === 'desc' ? 'prev' : 'next';
63
66
  const request = source.openCursor(range, direction);
@@ -80,6 +83,8 @@ export async function findAllOids({
80
83
  request.error,
81
84
  );
82
85
  resolve([]);
86
+ } else if (isAbortError(request.error)) {
87
+ resolve([]);
83
88
  } else {
84
89
  reject(request.error);
85
90
  }
@@ -102,7 +107,7 @@ export async function findPageOfOids({
102
107
  offset?: number;
103
108
  }) {
104
109
  const store = getStore(context.documentDb, collection);
105
- const source = index ? store.index(index.where) : store;
110
+ const source = index?.where ? store.index(index.where) : store;
106
111
  const range = getRange(context.schema, collection, index);
107
112
  const direction = index?.order === 'desc' ? 'prev' : 'next';
108
113
  const request = source.openCursor(range, direction);
@@ -141,6 +146,8 @@ export async function findPageOfOids({
141
146
  request.error,
142
147
  );
143
148
  resolve([]);
149
+ } else if (isAbortError(request.error)) {
150
+ resolve([]);
144
151
  } else {
145
152
  reject(request.error);
146
153
  }
@@ -1,5 +1,5 @@
1
1
  import { CollectionIndexFilter, hashObject } from '@verdant-web/common';
2
- import { Entity } from '../entities/Entity.js';
2
+ import { Entity } from '../entities/2/Entity.js';
3
3
 
4
4
  function existsFilter<T>(x: T | null): x is T {
5
5
  return x !== null;
@@ -14,6 +14,7 @@ export type FilePullResult =
14
14
  | {
15
15
  success: false;
16
16
  retry: boolean;
17
+ error?: any;
17
18
  };
18
19
 
19
20
  export class FileSync {
@@ -117,6 +118,7 @@ export class FileSync {
117
118
  this.log('error', 'File information fetch failed', e);
118
119
  return {
119
120
  success: false,
121
+ error: e,
120
122
  retry: true,
121
123
  };
122
124
  }
@@ -152,11 +152,18 @@ export class PushPullSync
152
152
  this._status = 'paused';
153
153
  }
154
154
 
155
- dispose = () => {};
155
+ destroy = () => {
156
+ this.dispose();
157
+ this.stop();
158
+ };
156
159
  reconnect(): void {
157
160
  this.heartbeat.start(true);
158
161
  }
159
162
 
163
+ ignoreIncoming(): void {
164
+ this.stop();
165
+ }
166
+
160
167
  // on a heartbeat, do a sync
161
168
  private onHeartbeat = async () => {
162
169
  // for HTTP sync we send presence first, so that the sync-resp message
package/src/sync/Sync.ts CHANGED
@@ -40,9 +40,10 @@ export interface SyncTransport {
40
40
  send(message: ClientMessage): void;
41
41
 
42
42
  start(): void;
43
+ ignoreIncoming(): void;
43
44
  stop(): void;
44
45
 
45
- dispose(): void;
46
+ destroy(): void;
46
47
 
47
48
  reconnect(): void;
48
49
 
@@ -71,7 +72,9 @@ export class NoSync<Presence = any, Profile = any>
71
72
 
72
73
  public stop(): void {}
73
74
 
74
- public dispose = () => {};
75
+ public ignoreIncoming(): void {}
76
+
77
+ public destroy = () => {};
75
78
 
76
79
  public reconnect(): void {}
77
80
 
@@ -285,7 +288,7 @@ export class ServerSync<Presence = any, Profile = any>
285
288
  }, 1000);
286
289
  }
287
290
  };
288
- let switchoverTimeout: NodeJS.Timer;
291
+ let switchoverTimeout: NodeJS.Timeout;
289
292
  this.presence.subscribe('peersChanged', decideIfUpgrade);
290
293
  if (automaticTransportSelection !== 'peers-only') {
291
294
  this.presence.subscribe('selfChanged', decideIfUpgrade);
@@ -453,9 +456,14 @@ export class ServerSync<Presence = any, Profile = any>
453
456
  return this.activeSync.stop();
454
457
  };
455
458
 
456
- public dispose = () => {
457
- this.webSocketSync.dispose();
458
- this.pushPullSync.dispose();
459
+ public ignoreIncoming(): void {
460
+ this.activeSync.ignoreIncoming();
461
+ }
462
+
463
+ public destroy = () => {
464
+ this.dispose();
465
+ this.webSocketSync.destroy();
466
+ this.pushPullSync.destroy();
459
467
  };
460
468
 
461
469
  public reconnect = () => {
@@ -21,10 +21,13 @@ export class WebSocketSync
21
21
  private connectQueue: ClientMessage[] = [];
22
22
  // messages awaiting sync response to send
23
23
  private syncQueue: ClientMessage[] = [];
24
+ // messages waiting for sync to finish
25
+ private incomingQueue: ServerMessage[] = [];
24
26
  private endpointProvider;
25
27
  private _status: 'active' | 'paused' = 'paused';
26
28
  private synced = false;
27
29
  private hasStartedSync = false;
30
+ private _ignoreIncoming = false;
28
31
 
29
32
  readonly mode = 'realtime';
30
33
  private log = (...args: any[]) => {};
@@ -75,6 +78,9 @@ export class WebSocketSync
75
78
 
76
79
  private onOnlineChange = async (online: boolean) => {
77
80
  this.log('Socket online change', online);
81
+ if (this.disposed) {
82
+ return;
83
+ }
78
84
  if (!online) {
79
85
  this.hasStartedSync = false;
80
86
  this.synced = false;
@@ -95,6 +101,14 @@ export class WebSocketSync
95
101
  };
96
102
 
97
103
  private onMessage = async (event: MessageEvent) => {
104
+ if (this._ignoreIncoming) {
105
+ this.log(
106
+ 'Ignoring incoming message (ignore incoming flag set)',
107
+ event.data,
108
+ );
109
+ return;
110
+ }
111
+
98
112
  const message = JSON.parse(event.data) as ServerMessage;
99
113
  switch (message.type) {
100
114
  case 'sync-resp':
@@ -107,22 +121,39 @@ export class WebSocketSync
107
121
  this.hasStartedSync = true;
108
122
  this.synced = true;
109
123
  if (this.syncQueue.length) {
110
- for (const msg of this.syncQueue) {
111
- this.send(msg);
124
+ if (message.overwriteLocalData) {
125
+ this.log(
126
+ 'warn',
127
+ 'Overwriting local data - dropping outgoing message queue',
128
+ );
129
+ this.syncQueue = [];
130
+ } else {
131
+ for (const msg of this.syncQueue) {
132
+ this.send(msg);
133
+ }
134
+ this.syncQueue = [];
112
135
  }
113
- this.syncQueue = [];
114
136
  }
137
+ this.emit('message', message);
138
+ if (this.incomingQueue.length) {
139
+ for (const msg of this.incomingQueue) {
140
+ this.emit('message', msg);
141
+ }
142
+ this.incomingQueue = [];
143
+ }
144
+ break;
115
145
  case 'need-since':
116
146
  case 'presence-changed':
117
147
  case 'presence-offline':
118
148
  this.emit('message', message);
119
149
  break;
120
150
  case 'op-re':
121
- if (!this.hasStartedSync) {
151
+ if (!this.synced) {
122
152
  this.log(
123
- `Skipping op-re message because sync hasn't started yet`,
153
+ `Enqueueing op-re message because sync hasn't finished yet`,
124
154
  message,
125
155
  );
156
+ this.incomingQueue.push(message);
126
157
  break;
127
158
  }
128
159
  this.emit('message', message);
@@ -215,10 +246,9 @@ export class WebSocketSync
215
246
  }
216
247
  };
217
248
 
218
- dispose = () => {
219
- this.socket?.removeEventListener('message', this.onMessage);
220
- this.socket?.removeEventListener('close', this.onClose);
221
- this.socket?.close();
249
+ destroy = () => {
250
+ this.dispose();
251
+ this.stop();
222
252
  };
223
253
 
224
254
  start = () => {
@@ -230,11 +260,18 @@ export class WebSocketSync
230
260
  };
231
261
 
232
262
  stop = () => {
233
- this.dispose();
263
+ this.socket?.removeEventListener('message', this.onMessage);
264
+ this.socket?.removeEventListener('close', this.onClose);
265
+ this.socket?.close();
234
266
  this.socket = null;
235
267
  this._status = 'paused';
236
268
  };
237
269
 
270
+ ignoreIncoming(): void {
271
+ this.incomingQueue = [];
272
+ this._ignoreIncoming = true;
273
+ }
274
+
238
275
  get isConnected() {
239
276
  return this.socket?.readyState === WebSocket.OPEN;
240
277
  }