@verdant-web/store 3.12.0 → 4.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 (281) hide show
  1. package/dist/bundle/index.js +11 -13
  2. package/dist/bundle/index.js.map +4 -4
  3. package/dist/esm/__tests__/batching.test.js +5 -5
  4. package/dist/esm/__tests__/batching.test.js.map +1 -1
  5. package/dist/esm/__tests__/entities.test.js +1 -1
  6. package/dist/esm/__tests__/entities.test.js.map +1 -1
  7. package/dist/esm/__tests__/fixtures/testStorage.d.ts +1 -3
  8. package/dist/esm/__tests__/fixtures/testStorage.js +3 -3
  9. package/dist/esm/__tests__/fixtures/testStorage.js.map +1 -1
  10. package/dist/esm/__tests__/queries.test.js.map +1 -1
  11. package/dist/esm/backup.d.ts +3 -4
  12. package/dist/esm/backup.js.map +1 -1
  13. package/dist/esm/client/Client.d.ts +28 -33
  14. package/dist/esm/client/Client.js +50 -161
  15. package/dist/esm/client/Client.js.map +1 -1
  16. package/dist/esm/client/ClientDescriptor.d.ts +8 -11
  17. package/dist/esm/client/ClientDescriptor.js +39 -141
  18. package/dist/esm/client/ClientDescriptor.js.map +1 -1
  19. package/dist/esm/context/Time.d.ts +13 -0
  20. package/dist/esm/context/Time.js +27 -0
  21. package/dist/esm/context/Time.js.map +1 -0
  22. package/dist/esm/context/context.d.ts +170 -0
  23. package/dist/esm/{context.js.map → context/context.js.map} +1 -1
  24. package/dist/esm/entities/DocumentManager.js.map +1 -1
  25. package/dist/esm/entities/Entity.d.ts +4 -5
  26. package/dist/esm/entities/Entity.js +5 -3
  27. package/dist/esm/entities/Entity.js.map +1 -1
  28. package/dist/esm/entities/Entity.test.js +4 -3
  29. package/dist/esm/entities/Entity.test.js.map +1 -1
  30. package/dist/esm/entities/EntityCache.d.ts +0 -3
  31. package/dist/esm/entities/EntityCache.js +0 -9
  32. package/dist/esm/entities/EntityCache.js.map +1 -1
  33. package/dist/esm/entities/EntityMetadata.d.ts +1 -1
  34. package/dist/esm/entities/EntityMetadata.js +6 -5
  35. package/dist/esm/entities/EntityMetadata.js.map +1 -1
  36. package/dist/esm/entities/EntityStore.d.ts +2 -6
  37. package/dist/esm/entities/EntityStore.js +22 -16
  38. package/dist/esm/entities/EntityStore.js.map +1 -1
  39. package/dist/esm/entities/OperationBatcher.d.ts +2 -5
  40. package/dist/esm/entities/OperationBatcher.js +9 -7
  41. package/dist/esm/entities/OperationBatcher.js.map +1 -1
  42. package/dist/esm/entities/types.d.ts +1 -1
  43. package/dist/esm/errors.d.ts +8 -0
  44. package/dist/esm/errors.js +12 -0
  45. package/dist/esm/errors.js.map +1 -0
  46. package/dist/esm/files/EntityFile.d.ts +6 -3
  47. package/dist/esm/files/EntityFile.js +22 -19
  48. package/dist/esm/files/EntityFile.js.map +1 -1
  49. package/dist/esm/files/FileManager.d.ts +8 -39
  50. package/dist/esm/files/FileManager.js +15 -170
  51. package/dist/esm/files/FileManager.js.map +1 -1
  52. package/dist/esm/files/utils.d.ts +0 -1
  53. package/dist/esm/files/utils.js +0 -14
  54. package/dist/esm/files/utils.js.map +1 -1
  55. package/dist/esm/index.d.ts +1 -2
  56. package/dist/esm/index.js +0 -1
  57. package/dist/esm/index.js.map +1 -1
  58. package/dist/esm/{metadata → persistence}/MessageCreator.d.ts +5 -6
  59. package/dist/esm/{metadata → persistence}/MessageCreator.js +31 -38
  60. package/dist/esm/persistence/MessageCreator.js.map +1 -0
  61. package/dist/esm/persistence/PersistenceFiles.d.ts +48 -0
  62. package/dist/esm/persistence/PersistenceFiles.js +160 -0
  63. package/dist/esm/persistence/PersistenceFiles.js.map +1 -0
  64. package/dist/esm/persistence/PersistenceMetadata.d.ts +69 -0
  65. package/dist/esm/persistence/PersistenceMetadata.js +302 -0
  66. package/dist/esm/persistence/PersistenceMetadata.js.map +1 -0
  67. package/dist/esm/persistence/PersistenceQueries.d.ts +34 -0
  68. package/dist/esm/persistence/PersistenceQueries.js +15 -0
  69. package/dist/esm/persistence/PersistenceQueries.js.map +1 -0
  70. package/dist/esm/persistence/PersistenceRebaser.d.ts +32 -0
  71. package/dist/esm/persistence/PersistenceRebaser.js +120 -0
  72. package/dist/esm/persistence/PersistenceRebaser.js.map +1 -0
  73. package/dist/esm/{IDBService.d.ts → persistence/idb/IdbService.d.ts} +9 -7
  74. package/dist/esm/{IDBService.js → persistence/idb/IdbService.js} +29 -8
  75. package/dist/esm/persistence/idb/IdbService.js.map +1 -0
  76. package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.d.ts +58 -0
  77. package/dist/esm/{files/FileStorage.js → persistence/idb/files/IdbPersistenceFileDb.js} +85 -50
  78. package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.js.map +1 -0
  79. package/dist/esm/persistence/idb/idbPersistence.d.ts +19 -0
  80. package/dist/esm/persistence/idb/idbPersistence.js +80 -0
  81. package/dist/esm/persistence/idb/idbPersistence.js.map +1 -0
  82. package/dist/esm/persistence/idb/metadata/IdbMetadataDb.d.ts +72 -0
  83. package/dist/esm/persistence/idb/metadata/IdbMetadataDb.js +235 -0
  84. package/dist/esm/persistence/idb/metadata/IdbMetadataDb.js.map +1 -0
  85. package/dist/esm/{metadata → persistence/idb/metadata}/openMetadataDatabase.d.ts +3 -1
  86. package/dist/esm/{metadata → persistence/idb/metadata}/openMetadataDatabase.js +12 -3
  87. package/dist/esm/persistence/idb/metadata/openMetadataDatabase.js.map +1 -0
  88. package/dist/esm/persistence/idb/queries/IdbQueryDb.d.ts +41 -0
  89. package/dist/esm/persistence/idb/queries/IdbQueryDb.js +174 -0
  90. package/dist/esm/persistence/idb/queries/IdbQueryDb.js.map +1 -0
  91. package/dist/esm/{migration → persistence/idb/queries/migration}/db.d.ts +1 -1
  92. package/dist/esm/{migration → persistence/idb/queries/migration}/db.js +10 -48
  93. package/dist/esm/persistence/idb/queries/migration/db.js.map +1 -0
  94. package/dist/esm/persistence/idb/queries/migration/engine.d.ts +12 -0
  95. package/dist/esm/{migration → persistence/idb/queries/migration}/engine.js +29 -46
  96. package/dist/esm/persistence/idb/queries/migration/engine.js.map +1 -0
  97. package/dist/esm/{migration → persistence/idb/queries/migration}/migrations.d.ts +1 -3
  98. package/dist/esm/{migration → persistence/idb/queries/migration}/migrations.js +11 -10
  99. package/dist/esm/persistence/idb/queries/migration/migrations.js.map +1 -0
  100. package/dist/esm/{migration → persistence/idb/queries/migration}/openQueryDatabase.d.ts +1 -3
  101. package/dist/esm/{migration → persistence/idb/queries/migration}/openQueryDatabase.js +4 -7
  102. package/dist/esm/persistence/idb/queries/migration/openQueryDatabase.js.map +1 -0
  103. package/dist/esm/{migration → persistence/idb/queries/migration}/paths.js +2 -2
  104. package/dist/esm/persistence/idb/queries/migration/paths.js.map +1 -0
  105. package/dist/esm/persistence/idb/queries/migration/paths.test.js.map +1 -0
  106. package/dist/esm/persistence/idb/queries/migration/types.d.ts +6 -0
  107. package/dist/esm/persistence/idb/queries/migration/types.js.map +1 -0
  108. package/dist/esm/persistence/idb/queries/ranges.d.ts +2 -0
  109. package/dist/esm/persistence/idb/queries/ranges.js +66 -0
  110. package/dist/esm/persistence/idb/queries/ranges.js.map +1 -0
  111. package/dist/esm/{idb.d.ts → persistence/idb/util.d.ts} +11 -0
  112. package/dist/esm/{idb.js → persistence/idb/util.js} +58 -1
  113. package/dist/esm/persistence/idb/util.js.map +1 -0
  114. package/dist/esm/persistence/interfaces.d.ts +181 -0
  115. package/dist/esm/persistence/interfaces.js +2 -0
  116. package/dist/esm/persistence/interfaces.js.map +1 -0
  117. package/dist/esm/persistence/persistence.d.ts +4 -0
  118. package/dist/esm/persistence/persistence.js +126 -0
  119. package/dist/esm/persistence/persistence.js.map +1 -0
  120. package/dist/esm/queries/BaseQuery.d.ts +2 -1
  121. package/dist/esm/queries/BaseQuery.js +3 -0
  122. package/dist/esm/queries/BaseQuery.js.map +1 -1
  123. package/dist/esm/queries/CollectionQueries.d.ts +1 -1
  124. package/dist/esm/queries/FindAllQuery.js +1 -3
  125. package/dist/esm/queries/FindAllQuery.js.map +1 -1
  126. package/dist/esm/queries/FindInfiniteQuery.js +2 -5
  127. package/dist/esm/queries/FindInfiniteQuery.js.map +1 -1
  128. package/dist/esm/queries/FindOneQuery.js +1 -3
  129. package/dist/esm/queries/FindOneQuery.js.map +1 -1
  130. package/dist/esm/queries/FindPageQuery.js +1 -3
  131. package/dist/esm/queries/FindPageQuery.js.map +1 -1
  132. package/dist/esm/queries/QueryCache.d.ts +1 -1
  133. package/dist/esm/queries/QueryCache.js +4 -0
  134. package/dist/esm/queries/QueryCache.js.map +1 -1
  135. package/dist/esm/sync/FileSync.d.ts +23 -8
  136. package/dist/esm/sync/FileSync.js +76 -28
  137. package/dist/esm/sync/FileSync.js.map +1 -1
  138. package/dist/esm/sync/PresenceManager.d.ts +4 -3
  139. package/dist/esm/sync/PresenceManager.js +2 -2
  140. package/dist/esm/sync/PresenceManager.js.map +1 -1
  141. package/dist/esm/sync/PushPullSync.d.ts +4 -6
  142. package/dist/esm/sync/PushPullSync.js +13 -12
  143. package/dist/esm/sync/PushPullSync.js.map +1 -1
  144. package/dist/esm/sync/Sync.d.ts +9 -11
  145. package/dist/esm/sync/Sync.js +34 -29
  146. package/dist/esm/sync/Sync.js.map +1 -1
  147. package/dist/esm/sync/WebSocketSync.d.ts +4 -6
  148. package/dist/esm/sync/WebSocketSync.js +20 -22
  149. package/dist/esm/sync/WebSocketSync.js.map +1 -1
  150. package/dist/esm/utils/Disposable.d.ts +5 -2
  151. package/dist/esm/utils/Disposable.js +3 -2
  152. package/dist/esm/utils/Disposable.js.map +1 -1
  153. package/dist/esm/utils/wip.d.ts +2 -0
  154. package/dist/esm/utils/wip.js +5 -0
  155. package/dist/esm/utils/wip.js.map +1 -0
  156. package/package.json +2 -2
  157. package/src/__tests__/batching.test.ts +6 -6
  158. package/src/__tests__/entities.test.ts +1 -1
  159. package/src/__tests__/fixtures/testStorage.ts +2 -10
  160. package/src/__tests__/queries.test.ts +1 -1
  161. package/src/backup.ts +3 -4
  162. package/src/client/Client.ts +69 -226
  163. package/src/client/ClientDescriptor.ts +53 -184
  164. package/src/context/Time.ts +35 -0
  165. package/src/context/context.ts +200 -0
  166. package/src/entities/DocumentManager.ts +0 -3
  167. package/src/entities/Entity.test.ts +9 -9
  168. package/src/entities/Entity.ts +6 -12
  169. package/src/entities/EntityCache.ts +0 -9
  170. package/src/entities/EntityMetadata.ts +4 -4
  171. package/src/entities/EntityStore.ts +26 -29
  172. package/src/entities/OperationBatcher.ts +9 -11
  173. package/src/entities/types.ts +1 -1
  174. package/src/errors.ts +13 -0
  175. package/src/files/EntityFile.ts +16 -5
  176. package/src/files/FileManager.ts +18 -245
  177. package/src/files/utils.ts +0 -15
  178. package/src/index.ts +2 -1
  179. package/src/{metadata → persistence}/MessageCreator.ts +46 -36
  180. package/src/persistence/PersistenceFiles.ts +227 -0
  181. package/src/persistence/PersistenceMetadata.ts +425 -0
  182. package/src/persistence/PersistenceQueries.ts +22 -0
  183. package/src/persistence/PersistenceRebaser.ts +171 -0
  184. package/src/{IDBService.ts → persistence/idb/IdbService.ts} +45 -12
  185. package/src/{files/FileStorage.ts → persistence/idb/files/IdbPersistenceFileDb.ts} +128 -86
  186. package/src/persistence/idb/idbPersistence.ts +116 -0
  187. package/src/persistence/idb/metadata/IdbMetadataDb.ts +460 -0
  188. package/src/{metadata → persistence/idb/metadata}/openMetadataDatabase.ts +21 -4
  189. package/src/persistence/idb/queries/IdbQueryDb.ts +251 -0
  190. package/src/{migration → persistence/idb/queries/migration}/db.ts +18 -72
  191. package/src/{migration → persistence/idb/queries/migration}/engine.ts +39 -62
  192. package/src/{migration → persistence/idb/queries/migration}/migrations.ts +13 -18
  193. package/src/{migration → persistence/idb/queries/migration}/openQueryDatabase.ts +5 -14
  194. package/src/{migration → persistence/idb/queries/migration}/paths.ts +4 -3
  195. package/src/persistence/idb/queries/migration/types.ts +8 -0
  196. package/src/persistence/idb/queries/ranges.ts +107 -0
  197. package/src/{idb.ts → persistence/idb/util.ts} +75 -0
  198. package/src/persistence/interfaces.ts +240 -0
  199. package/src/persistence/persistence.ts +223 -0
  200. package/src/queries/BaseQuery.ts +5 -1
  201. package/src/queries/CollectionQueries.ts +2 -2
  202. package/src/queries/FindAllQuery.ts +1 -3
  203. package/src/queries/FindInfiniteQuery.ts +2 -5
  204. package/src/queries/FindOneQuery.ts +1 -3
  205. package/src/queries/FindPageQuery.ts +1 -3
  206. package/src/queries/QueryCache.ts +20 -1
  207. package/src/sync/FileSync.ts +93 -30
  208. package/src/sync/PresenceManager.ts +5 -7
  209. package/src/sync/PushPullSync.ts +23 -19
  210. package/src/sync/Sync.ts +45 -36
  211. package/src/sync/WebSocketSync.ts +41 -27
  212. package/src/utils/Disposable.ts +7 -4
  213. package/src/utils/wip.ts +5 -0
  214. package/dist/esm/IDBService.js.map +0 -1
  215. package/dist/esm/__tests__/legacyOids.test.d.ts +0 -1
  216. package/dist/esm/__tests__/legacyOids.test.js +0 -352
  217. package/dist/esm/__tests__/legacyOids.test.js.map +0 -1
  218. package/dist/esm/context.d.ts +0 -45
  219. package/dist/esm/files/FileStorage.d.ts +0 -47
  220. package/dist/esm/files/FileStorage.js.map +0 -1
  221. package/dist/esm/idb.js.map +0 -1
  222. package/dist/esm/metadata/AckInfoStore.d.ts +0 -10
  223. package/dist/esm/metadata/AckInfoStore.js +0 -22
  224. package/dist/esm/metadata/AckInfoStore.js.map +0 -1
  225. package/dist/esm/metadata/BaselinesStore.d.ts +0 -40
  226. package/dist/esm/metadata/BaselinesStore.js +0 -102
  227. package/dist/esm/metadata/BaselinesStore.js.map +0 -1
  228. package/dist/esm/metadata/LocalReplicaStore.d.ts +0 -19
  229. package/dist/esm/metadata/LocalReplicaStore.js +0 -56
  230. package/dist/esm/metadata/LocalReplicaStore.js.map +0 -1
  231. package/dist/esm/metadata/MessageCreator.js.map +0 -1
  232. package/dist/esm/metadata/Metadata.d.ts +0 -146
  233. package/dist/esm/metadata/Metadata.js +0 -452
  234. package/dist/esm/metadata/Metadata.js.map +0 -1
  235. package/dist/esm/metadata/OperationsStore.d.ts +0 -62
  236. package/dist/esm/metadata/OperationsStore.js +0 -175
  237. package/dist/esm/metadata/OperationsStore.js.map +0 -1
  238. package/dist/esm/metadata/SchemaStore.d.ts +0 -9
  239. package/dist/esm/metadata/SchemaStore.js +0 -35
  240. package/dist/esm/metadata/SchemaStore.js.map +0 -1
  241. package/dist/esm/metadata/openMetadataDatabase.js.map +0 -1
  242. package/dist/esm/migration/db.js.map +0 -1
  243. package/dist/esm/migration/engine.d.ts +0 -15
  244. package/dist/esm/migration/engine.js.map +0 -1
  245. package/dist/esm/migration/errors.d.ts +0 -5
  246. package/dist/esm/migration/errors.js +0 -8
  247. package/dist/esm/migration/errors.js.map +0 -1
  248. package/dist/esm/migration/migrations.js.map +0 -1
  249. package/dist/esm/migration/openQueryDatabase.js.map +0 -1
  250. package/dist/esm/migration/openWIPDatabase.d.ts +0 -11
  251. package/dist/esm/migration/openWIPDatabase.js +0 -65
  252. package/dist/esm/migration/openWIPDatabase.js.map +0 -1
  253. package/dist/esm/migration/paths.js.map +0 -1
  254. package/dist/esm/migration/paths.test.js.map +0 -1
  255. package/dist/esm/migration/types.d.ts +0 -3
  256. package/dist/esm/migration/types.js.map +0 -1
  257. package/dist/esm/queries/QueryableStorage.d.ts +0 -20
  258. package/dist/esm/queries/QueryableStorage.js +0 -90
  259. package/dist/esm/queries/QueryableStorage.js.map +0 -1
  260. package/dist/esm/queries/dbQueries.d.ts +0 -22
  261. package/dist/esm/queries/dbQueries.js +0 -130
  262. package/dist/esm/queries/dbQueries.js.map +0 -1
  263. package/src/__tests__/legacyOids.test.ts +0 -375
  264. package/src/context.ts +0 -55
  265. package/src/metadata/AckInfoStore.ts +0 -30
  266. package/src/metadata/BaselinesStore.ts +0 -188
  267. package/src/metadata/LocalReplicaStore.ts +0 -79
  268. package/src/metadata/Metadata.ts +0 -685
  269. package/src/metadata/OperationsStore.ts +0 -332
  270. package/src/metadata/SchemaStore.ts +0 -47
  271. package/src/migration/errors.ts +0 -7
  272. package/src/migration/openWIPDatabase.ts +0 -97
  273. package/src/migration/types.ts +0 -4
  274. package/src/queries/QueryableStorage.ts +0 -122
  275. package/src/queries/dbQueries.ts +0 -161
  276. /package/dist/esm/{context.js → context/context.js} +0 -0
  277. /package/dist/esm/{migration → persistence/idb/queries/migration}/paths.d.ts +0 -0
  278. /package/dist/esm/{migration → persistence/idb/queries/migration}/paths.test.d.ts +0 -0
  279. /package/dist/esm/{migration → persistence/idb/queries/migration}/paths.test.js +0 -0
  280. /package/dist/esm/{migration → persistence/idb/queries/migration}/types.js +0 -0
  281. /package/src/{migration → persistence/idb/queries/migration}/paths.test.ts +0 -0
@@ -2,36 +2,19 @@ import {
2
2
  debounce,
3
3
  DocumentBaseline,
4
4
  EventSubscriber,
5
- getTimestampSchemaVersion,
6
- Migration,
7
5
  Operation,
8
6
  } from '@verdant-web/common';
9
- import { Context } from '../context.js';
7
+ import { Context } from '../context/context.js';
10
8
  import { DocumentManager } from '../entities/DocumentManager.js';
11
9
  import { EntityStore } from '../entities/EntityStore.js';
12
- import { FileManager, FileManagerConfig } from '../files/FileManager.js';
13
- import { ReturnedFileData } from '../files/FileStorage.js';
14
- import {
15
- closeDatabase,
16
- deleteAllDatabases,
17
- getSizeOfObjectStore,
18
- } from '../idb.js';
19
- import {
20
- ExportData,
21
- Metadata,
22
- supportLegacyExport,
23
- } from '../metadata/Metadata.js';
24
- import { openQueryDatabase } from '../migration/openQueryDatabase.js';
10
+ import { FileManager } from '../files/FileManager.js';
11
+ import { deleteAllDatabases } from '../persistence/idb/util.js';
25
12
  import { CollectionQueries } from '../queries/CollectionQueries.js';
26
13
  import { QueryCache } from '../queries/QueryCache.js';
27
- import { NoSync, ServerSync, ServerSyncOptions, Sync } from '../sync/Sync.js';
14
+ import { NoSync, ServerSync, Sync } from '../sync/Sync.js';
28
15
  import { getLatestVersion } from '../utils/versions.js';
29
-
30
- interface ClientConfig<Presence = any> {
31
- syncConfig?: ServerSyncOptions<Presence>;
32
- migrations: Migration[];
33
- files?: FileManagerConfig;
34
- }
16
+ import { ExportedData } from '../persistence/interfaces.js';
17
+ import { importPersistence } from '../persistence/persistence.js';
35
18
 
36
19
  // not actually used below, but helpful for internal code which
37
20
  // might rely on this stuff...
@@ -62,13 +45,22 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
62
45
  * indicate the client is in an unrecoverable state.
63
46
  */
64
47
  developerError: (err: Error) => void;
48
+ /**
49
+ * Listen for operations as they are applied to the database.
50
+ * Wouldn't recommend using this unless you know what you're doing.
51
+ * It's a very hot code path...
52
+ */
53
+ operation: (operation: Operation) => void;
54
+ /**
55
+ * Emitted when storage rebases history. This should never actually affect application behavior
56
+ * or stored data, but is useful for debugging and testing.
57
+ */
58
+ rebase: () => void;
65
59
  }> {
66
- readonly meta: Metadata;
67
60
  private _entities: EntityStore;
68
61
  private _queryCache: QueryCache;
69
62
  private _documentManager: DocumentManager<any>;
70
63
  private _fileManager: FileManager;
71
- private _closed = false;
72
64
 
73
65
  readonly collectionNames: string[];
74
66
 
@@ -86,23 +78,17 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
86
78
  return this._documentManager;
87
79
  }
88
80
 
89
- constructor(
90
- private config: ClientConfig,
91
- private context: Context,
92
- components: { meta: Metadata },
93
- ) {
81
+ constructor(private context: Context) {
94
82
  super();
95
- this.meta = components.meta;
96
83
  this.collectionNames = Object.keys(context.schema.collections);
97
84
  this._sync =
98
- this.config.syncConfig && !context.schema.wip
99
- ? new ServerSync<Presence, Profile>(this.config.syncConfig, {
100
- meta: this.meta,
85
+ this.context.config.sync && !context.schema.wip
86
+ ? new ServerSync<Presence, Profile>(this.context.config.sync, {
101
87
  onData: this.addData,
102
88
  ctx: this.context,
103
89
  })
104
- : new NoSync<Presence, Profile>({ meta: this.meta });
105
- if (context.schema.wip && this.config.syncConfig) {
90
+ : new NoSync<Presence, Profile>(this.context);
91
+ if (context.schema.wip && this.context.config.sync) {
106
92
  context.log(
107
93
  'warn',
108
94
  '⚠️⚠️ Sync is disabled for WIP schemas. Commit your schema changes to start syncing again. ⚠️⚠️',
@@ -110,20 +96,20 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
110
96
  }
111
97
 
112
98
  this._fileManager = new FileManager({
113
- db: this.metaDb,
114
99
  sync: this.sync,
115
100
  context: this.context,
116
- config: this.config.files,
117
- meta: this.meta,
118
- });
119
- this._queryCache = new QueryCache({
120
- context,
121
101
  });
122
102
  this._entities = new EntityStore({
123
103
  ctx: this.context,
124
- meta: this.meta,
125
104
  files: this._fileManager,
126
105
  });
106
+ // note: query cache must be initialized after EntityStore,
107
+ // since EntityStore needs to clear its cache before queries
108
+ // refresh.
109
+ // FIXME: make this less fragile
110
+ this._queryCache = new QueryCache({
111
+ context,
112
+ });
127
113
  this._documentManager = new DocumentManager(this.schema, this._entities);
128
114
 
129
115
  const notifyFutureSeen = debounce(() => {
@@ -133,18 +119,11 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
133
119
  this.context.globalEvents.subscribe('resetToServer', () => {
134
120
  this.emit('resetToServer');
135
121
  });
136
-
137
- this.watchForVersionChange();
138
-
139
- this.metaDb.addEventListener('versionchange', () => {
140
- this.context.log?.(
141
- 'warn',
142
- `Another tab has requested a version change for ${this.namespace}`,
143
- );
144
- this.metaDb.close();
145
- if (typeof window !== 'undefined') {
146
- window.location.reload();
147
- }
122
+ this.context.globalEvents.subscribe('operation', (operation) => {
123
+ this.emit('operation', operation);
124
+ });
125
+ this.context.globalEvents.subscribe('rebase', () => {
126
+ this.emit('rebase');
148
127
  });
149
128
 
150
129
  // self-assign collection shortcuts. these are not typed
@@ -163,19 +142,6 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
163
142
  }
164
143
  }
165
144
 
166
- private watchForVersionChange = () => {
167
- this.documentDb.addEventListener('versionchange', () => {
168
- this.context.log?.(
169
- 'warn',
170
- `Another tab has requested a version change for ${this.namespace}`,
171
- );
172
- this.documentDb.close();
173
- if (typeof window !== 'undefined') {
174
- window.location.reload();
175
- }
176
- });
177
- };
178
-
179
145
  private importingPromise = Promise.resolve();
180
146
  private addData = async (data: {
181
147
  operations: Operation[];
@@ -240,14 +206,6 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
240
206
  }
241
207
  };
242
208
 
243
- get documentDb() {
244
- return this.context.documentDb;
245
- }
246
-
247
- get metaDb() {
248
- return this.context.metaDb;
249
- }
250
-
251
209
  get schema() {
252
210
  return this.context.schema;
253
211
  }
@@ -275,25 +233,11 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
275
233
  }
276
234
 
277
235
  stats = async (): Promise<ClientStats> => {
278
- const collectionNames = Object.keys(this.schema.collections);
279
- let collections = {} as Record<string, { count: number; size: number }>;
280
236
  if (this.disposed) {
281
237
  return {} as any;
282
238
  }
283
- for (const collectionName of collectionNames) {
284
- try {
285
- collections[collectionName] = await getSizeOfObjectStore(
286
- this.documentDb,
287
- collectionName,
288
- );
289
- } catch (err) {
290
- this.context.log?.('error', err);
291
- }
292
- }
293
- if (this.disposed) {
294
- return { collections } as any;
295
- }
296
- const meta = await this.meta.stats();
239
+ const collections = await this.context.queries.stats();
240
+ const meta = await this.context.meta.stats();
297
241
  const storage =
298
242
  typeof navigator !== 'undefined' &&
299
243
  typeof navigator.storage !== 'undefined' &&
@@ -301,7 +245,7 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
301
245
  ? await navigator.storage.estimate()
302
246
  : undefined;
303
247
 
304
- const files = await this._fileManager.stats();
248
+ const files = await this.context.files.stats();
305
249
 
306
250
  // determine data:metadata ratio for total size of all collections vs metadata
307
251
  const totalCollectionsSize = Object.values(collections).reduce(
@@ -327,25 +271,26 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
327
271
  };
328
272
 
329
273
  close = async () => {
330
- this._closed = true;
331
274
  this.sync.ignoreIncoming();
332
275
  await this._entities.flushAllBatches();
333
- this._fileManager.close();
276
+ // NOTE: this happens after flushing or else flushed data
277
+ // won't be written to storage or synced.
278
+ this.context.closing = true;
279
+ this.context.files.dispose();
334
280
  this.sync.stop();
335
281
  this.sync.destroy();
336
282
  // this step does have the potential to flush
337
283
  // changes to storage, so don't close metadata db yet
338
284
  await this._entities.destroy();
339
285
 
340
- this.meta.close();
286
+ this.context.queries.dispose();
287
+ this.context.meta.dispose();
341
288
 
342
289
  // the idea here is to flush the microtask queue -
343
290
  // we may have queued tasks related to queries that
344
291
  // we want to settle before closing the databases
345
292
  // to avoid invalid state errors
346
- await new Promise<void>(async (resolve) => {
347
- await closeDatabase(this.documentDb);
348
- await closeDatabase(this.metaDb);
293
+ await new Promise<void>((resolve) => {
349
294
  resolve();
350
295
  });
351
296
 
@@ -361,35 +306,11 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
361
306
  { downloadRemoteFiles }: { downloadRemoteFiles?: boolean } = {
362
307
  downloadRemoteFiles: true,
363
308
  },
364
- ) => {
309
+ ): Promise<ExportedData> => {
365
310
  this.context.log('info', 'Exporting data...');
366
- const metaExport = await this.meta.export();
367
- const filesExport = await this._fileManager.exportAll(downloadRemoteFiles);
368
- // split files into data and files
369
- const fileData: Array<Omit<ReturnedFileData, 'file'>> = [];
370
- const files: Array<File> = [];
371
-
372
- for (const fileExport of filesExport) {
373
- const file = fileExport.file;
374
- delete fileExport.file;
375
- fileData.push(fileExport);
376
- if (file) {
377
- // rename with ID
378
- const asFile = new File(
379
- [file],
380
- this.getFileExportName(fileExport.name, fileExport.id),
381
- {
382
- type: fileExport.type,
383
- },
384
- );
385
- files.push(asFile);
386
- } else {
387
- this.context.log(
388
- 'warn',
389
- `File ${fileExport.id} was could not be loaded locally or from the server. It will be missing in the export.`,
390
- );
391
- }
392
- }
311
+ const metaExport = await this.context.meta.export();
312
+ const { fileData, files } =
313
+ await this.context.files.export(downloadRemoteFiles);
393
314
  return {
394
315
  data: metaExport,
395
316
  fileData,
@@ -397,24 +318,7 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
397
318
  };
398
319
  };
399
320
 
400
- private getFileExportName = (originalFileName: string, id: string) => {
401
- return `${id}___${originalFileName}`;
402
- };
403
-
404
- private parseFileExportname = (name: string) => {
405
- const [id, originalFileName] = name.split('___');
406
- return { id, originalFileName };
407
- };
408
-
409
- import = async ({
410
- data: rawData,
411
- fileData,
412
- files,
413
- }: {
414
- data: ExportData;
415
- fileData: Array<Omit<ReturnedFileData, 'file'>>;
416
- files: File[];
417
- }) => {
321
+ import = async ({ data, fileData, files }: ExportedData) => {
418
322
  /**
419
323
  * Importing is a pretty involved procedure because of the possibility of
420
324
  * importing an export from an older version of the schema. We can't add
@@ -435,90 +339,16 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
435
339
  resolve = res;
436
340
  });
437
341
 
438
- const data = supportLegacyExport(rawData);
439
342
  this.context.log('info', 'Importing data...');
440
- // close the document DB
441
- await closeDatabase(this.context.documentDb);
442
-
443
- await this.meta.resetFrom(data);
444
- // re-attach files to their file data and import
445
- const fileToIdMap = new Map(
446
- files.map((file) => {
447
- const { id } = this.parseFileExportname(file.name);
448
- return [id, file];
449
- }),
450
- );
451
- const importedFiles: ReturnedFileData[] = fileData.map((fileData) => {
452
- const file = fileToIdMap.get(fileData.id);
453
-
454
- return {
455
- ...fileData,
456
- file,
457
- };
458
- });
459
- await this._fileManager.importAll(importedFiles);
460
- // now delete the document DB, open it to the specified version
461
- // and run migrations to get it to the latest version
462
- const version = data.schemaVersion;
463
- const deleteReq = indexedDB.deleteDatabase(
464
- [this.namespace, 'collections'].join('_'),
465
- );
466
- await new Promise((resolve, reject) => {
467
- deleteReq.onsuccess = resolve;
468
- deleteReq.onerror = reject;
469
- });
470
- // reset our context to the imported schema for now
471
- const currentSchema = this.context.schema;
472
- if (currentSchema.version !== version) {
473
- const oldSchema = this.context.oldSchemas?.find(
474
- (s) => s.version === version,
475
- );
476
- if (!oldSchema) {
477
- this.emit(
478
- 'developerError',
479
- new Error(`Could not find schema for version ${version}`),
480
- );
481
- throw new Error(`Could not find schema for version ${version}`);
482
- }
483
343
 
484
- this.context.schema = oldSchema;
485
- }
486
- // now open the document DB empty at the specified version
487
- // and initialize it from the meta DB
488
- this.context.documentDb = await openQueryDatabase({
489
- meta: this.meta,
490
- migrations: this.config.migrations,
491
- context: this.context,
492
- version,
493
- });
494
- this.context.internalEvents.emit('documentDbChanged', this.documentDb);
495
- // re-initialize data
496
- this.context.log('info', 'Re-initializing data from imported data...');
497
- await this._entities.addData({
498
- operations: data.operations,
499
- baselines: data.baselines,
500
- reset: true,
501
- });
502
- // close the database and reopen to latest version, applying
503
- // migrations
504
- await closeDatabase(this.context.documentDb);
505
- this.context.log('info', 'Migrating up to latest schema...');
506
- // put the schema back
507
- this.context.schema = currentSchema;
508
- this.context.documentDb = await openQueryDatabase({
509
- meta: this.meta,
510
- migrations: this.config.migrations,
511
- context: this.context,
512
- version: currentSchema.version,
513
- });
514
- this.context.internalEvents.emit('documentDbChanged', this.documentDb);
515
- // re-establish watcher on database
516
- this.watchForVersionChange();
344
+ await importPersistence(this.context, { data, files, fileData });
517
345
 
518
346
  // finally... clear out memory cache of entities and
519
347
  // re-run all active queries.
520
- this.entities.clearCache();
521
- this._queryCache.forceRefreshAll();
348
+ // this.entities.clearCache();
349
+ // this._queryCache.forceRefreshAll();
350
+
351
+ // ^ this is now done via the persistenceReset internal event.
522
352
 
523
353
  resolve();
524
354
  };
@@ -549,7 +379,7 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
549
379
  * invoking this manually will not skip that 3 day waiting period.
550
380
  */
551
381
  __cleanupFilesImmediately = () => {
552
- return this._fileManager.tryCleanupDeletedFiles();
382
+ return this.context.files.cleanupDeletedFiles();
553
383
  };
554
384
 
555
385
  /**
@@ -557,7 +387,20 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
557
387
  * rebasing rules. Rebases already happen automatically
558
388
  * during normal operation, so you probably don't need this.
559
389
  */
560
- __manualRebase = () => this.meta.manualRebase();
390
+ __manualRebase = () => this.context.meta.manualRebase();
391
+
392
+ /**
393
+ * WARNING: the internal functions of the persistence layer
394
+ * are not guaranteed and cannot be relied upon for application
395
+ * behavior. They are subject to change without notice.
396
+ */
397
+ get __persistence() {
398
+ return {
399
+ meta: this.context.meta,
400
+ queries: this.context.queries,
401
+ files: this.context.files,
402
+ };
403
+ }
561
404
  }
562
405
 
563
406
  export interface ClientStats {