@verdant-web/store 2.8.5 → 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.
- package/dist/bundle/index.js +9 -10
- package/dist/bundle/index.js.map +4 -4
- package/dist/cjs/DocumentManager.d.ts +6 -5
- package/dist/cjs/DocumentManager.js +2 -2
- package/dist/cjs/DocumentManager.js.map +1 -1
- package/dist/cjs/IDBService.d.ts +28 -7
- package/dist/cjs/IDBService.js +50 -13
- package/dist/cjs/IDBService.js.map +1 -1
- package/dist/cjs/UndoHistory.d.ts +1 -1
- package/dist/cjs/UndoHistory.js +6 -2
- package/dist/cjs/UndoHistory.js.map +1 -1
- package/dist/cjs/__tests__/batching.test.js +3 -1
- package/dist/cjs/__tests__/batching.test.js.map +1 -1
- package/dist/cjs/__tests__/documents.test.js +37 -6
- package/dist/cjs/__tests__/documents.test.js.map +1 -1
- package/dist/cjs/__tests__/fixtures/testStorage.d.ts +2 -2
- package/dist/cjs/__tests__/fixtures/testStorage.js +2 -1
- package/dist/cjs/__tests__/fixtures/testStorage.js.map +1 -1
- package/dist/cjs/__tests__/legacyOids.test.js +50 -17
- package/dist/cjs/__tests__/legacyOids.test.js.map +1 -1
- package/dist/cjs/__tests__/mutations.test.js +9 -3
- package/dist/cjs/__tests__/mutations.test.js.map +1 -1
- package/dist/cjs/__tests__/queries.test.js +6 -2
- package/dist/cjs/__tests__/queries.test.js.map +1 -1
- package/dist/cjs/__tests__/setup/indexedDB.d.ts +1 -1
- package/dist/cjs/__tests__/setup/indexedDB.js +8 -1
- package/dist/cjs/__tests__/setup/indexedDB.js.map +1 -1
- package/dist/cjs/__tests__/undo.test.js +16 -9
- package/dist/cjs/__tests__/undo.test.js.map +1 -1
- package/dist/cjs/client/Client.d.ts +2 -3
- package/dist/cjs/client/Client.js +8 -4
- package/dist/cjs/client/Client.js.map +1 -1
- package/dist/cjs/client/ClientDescriptor.js +21 -6
- package/dist/cjs/client/ClientDescriptor.js.map +1 -1
- package/dist/cjs/context.d.ts +10 -1
- package/dist/cjs/entities/2/Entity.d.ts +148 -0
- package/dist/cjs/entities/2/Entity.js +711 -0
- package/dist/cjs/entities/2/Entity.js.map +1 -0
- package/dist/cjs/entities/2/Entity.test.d.ts +1 -0
- package/dist/cjs/entities/2/Entity.test.js +194 -0
- package/dist/cjs/entities/2/Entity.test.js.map +1 -0
- package/dist/cjs/entities/2/EntityCache.d.ts +15 -0
- package/dist/cjs/entities/2/EntityCache.js +39 -0
- package/dist/cjs/entities/2/EntityCache.js.map +1 -0
- package/dist/cjs/entities/2/EntityMetadata.d.ts +68 -0
- package/dist/cjs/entities/2/EntityMetadata.js +261 -0
- package/dist/cjs/entities/2/EntityMetadata.js.map +1 -0
- package/dist/cjs/entities/2/EntityStore.d.ts +78 -0
- package/dist/cjs/entities/2/EntityStore.js +352 -0
- package/dist/cjs/entities/2/EntityStore.js.map +1 -0
- package/dist/cjs/entities/2/OperationBatcher.d.ts +52 -0
- package/dist/cjs/entities/2/OperationBatcher.js +165 -0
- package/dist/cjs/entities/2/OperationBatcher.js.map +1 -0
- package/dist/cjs/entities/2/types.d.ts +84 -0
- package/dist/cjs/entities/2/types.js +3 -0
- package/dist/cjs/entities/2/types.js.map +1 -0
- package/dist/cjs/entities/Entity.d.ts +0 -7
- package/dist/cjs/entities/Entity.js +7 -0
- package/dist/cjs/entities/Entity.js.map +1 -1
- package/dist/cjs/entities/EntityStore.js +4 -20
- package/dist/cjs/entities/EntityStore.js.map +1 -1
- package/dist/cjs/entities/FakeWeakRef.d.ts +11 -0
- package/dist/cjs/entities/FakeWeakRef.js +19 -0
- package/dist/cjs/entities/FakeWeakRef.js.map +1 -0
- package/dist/cjs/files/EntityFile.d.ts +5 -2
- package/dist/cjs/files/EntityFile.js +8 -4
- package/dist/cjs/files/EntityFile.js.map +1 -1
- package/dist/cjs/files/FileManager.d.ts +3 -1
- package/dist/cjs/files/FileManager.js +5 -3
- package/dist/cjs/files/FileManager.js.map +1 -1
- package/dist/cjs/files/FileStorage.js +7 -7
- package/dist/cjs/files/FileStorage.js.map +1 -1
- package/dist/cjs/files/utils.d.ts +2 -0
- package/dist/cjs/files/utils.js +5 -2
- package/dist/cjs/files/utils.js.map +1 -1
- package/dist/cjs/idb.d.ts +2 -0
- package/dist/cjs/idb.js +50 -4
- package/dist/cjs/idb.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/indexes.d.ts +3 -0
- package/dist/cjs/indexes.js +20 -0
- package/dist/cjs/indexes.js.map +1 -0
- package/dist/cjs/metadata/AckInfoStore.js +1 -1
- package/dist/cjs/metadata/AckInfoStore.js.map +1 -1
- package/dist/cjs/metadata/BaselinesStore.d.ts +4 -1
- package/dist/cjs/metadata/BaselinesStore.js +19 -10
- package/dist/cjs/metadata/BaselinesStore.js.map +1 -1
- package/dist/cjs/metadata/LocalReplicaStore.d.ts +1 -1
- package/dist/cjs/metadata/LocalReplicaStore.js +11 -5
- package/dist/cjs/metadata/LocalReplicaStore.js.map +1 -1
- package/dist/cjs/metadata/Metadata.d.ts +26 -5
- package/dist/cjs/metadata/Metadata.js +55 -18
- package/dist/cjs/metadata/Metadata.js.map +1 -1
- package/dist/cjs/metadata/OperationsStore.d.ts +3 -0
- package/dist/cjs/metadata/OperationsStore.js +35 -15
- package/dist/cjs/metadata/OperationsStore.js.map +1 -1
- package/dist/cjs/migration/openDatabase.js +31 -10
- package/dist/cjs/migration/openDatabase.js.map +1 -1
- package/dist/cjs/queries/BaseQuery.js +14 -2
- package/dist/cjs/queries/BaseQuery.js.map +1 -1
- package/dist/cjs/queries/CollectionQueries.d.ts +2 -4
- package/dist/cjs/queries/CollectionQueries.js +1 -1
- package/dist/cjs/queries/CollectionQueries.js.map +1 -1
- package/dist/cjs/queries/FindAllQuery.js +1 -0
- package/dist/cjs/queries/FindAllQuery.js.map +1 -1
- package/dist/cjs/queries/QueryCache.d.ts +1 -0
- package/dist/cjs/queries/QueryCache.js +4 -0
- package/dist/cjs/queries/QueryCache.js.map +1 -1
- package/dist/cjs/queries/QueryableStorage.d.ts +20 -0
- package/dist/cjs/queries/QueryableStorage.js +84 -0
- package/dist/cjs/queries/QueryableStorage.js.map +1 -0
- package/dist/cjs/queries/dbQueries.js +13 -3
- package/dist/cjs/queries/dbQueries.js.map +1 -1
- package/dist/cjs/queries/utils.js +1 -1
- package/dist/cjs/queries/utils.js.map +1 -1
- package/dist/cjs/sync/FileSync.d.ts +1 -0
- package/dist/cjs/sync/FileSync.js +1 -0
- package/dist/cjs/sync/FileSync.js.map +1 -1
- package/dist/cjs/sync/PushPullSync.d.ts +2 -1
- package/dist/cjs/sync/PushPullSync.js +7 -1
- package/dist/cjs/sync/PushPullSync.js.map +1 -1
- package/dist/cjs/sync/Sync.d.ts +6 -3
- package/dist/cjs/sync/Sync.js +9 -4
- package/dist/cjs/sync/Sync.js.map +1 -1
- package/dist/cjs/sync/WebSocketSync.d.ts +4 -1
- package/dist/cjs/sync/WebSocketSync.js +41 -11
- package/dist/cjs/sync/WebSocketSync.js.map +1 -1
- package/dist/esm/DocumentManager.d.ts +6 -5
- package/dist/esm/DocumentManager.js +2 -2
- package/dist/esm/DocumentManager.js.map +1 -1
- package/dist/esm/IDBService.d.ts +28 -7
- package/dist/esm/IDBService.js +51 -14
- package/dist/esm/IDBService.js.map +1 -1
- package/dist/esm/UndoHistory.d.ts +1 -1
- package/dist/esm/UndoHistory.js +6 -2
- package/dist/esm/UndoHistory.js.map +1 -1
- package/dist/esm/__tests__/batching.test.js +3 -1
- package/dist/esm/__tests__/batching.test.js.map +1 -1
- package/dist/esm/__tests__/documents.test.js +37 -6
- package/dist/esm/__tests__/documents.test.js.map +1 -1
- package/dist/esm/__tests__/fixtures/testStorage.d.ts +2 -2
- package/dist/esm/__tests__/fixtures/testStorage.js +2 -1
- package/dist/esm/__tests__/fixtures/testStorage.js.map +1 -1
- package/dist/esm/__tests__/legacyOids.test.js +50 -17
- package/dist/esm/__tests__/legacyOids.test.js.map +1 -1
- package/dist/esm/__tests__/mutations.test.js +9 -3
- package/dist/esm/__tests__/mutations.test.js.map +1 -1
- package/dist/esm/__tests__/queries.test.js +6 -2
- package/dist/esm/__tests__/queries.test.js.map +1 -1
- package/dist/esm/__tests__/setup/indexedDB.d.ts +1 -1
- package/dist/esm/__tests__/setup/indexedDB.js +8 -1
- package/dist/esm/__tests__/setup/indexedDB.js.map +1 -1
- package/dist/esm/__tests__/undo.test.js +16 -9
- package/dist/esm/__tests__/undo.test.js.map +1 -1
- package/dist/esm/client/Client.d.ts +2 -3
- package/dist/esm/client/Client.js +8 -4
- package/dist/esm/client/Client.js.map +1 -1
- package/dist/esm/client/ClientDescriptor.js +21 -6
- package/dist/esm/client/ClientDescriptor.js.map +1 -1
- package/dist/esm/context.d.ts +10 -1
- package/dist/esm/entities/2/Entity.d.ts +148 -0
- package/dist/esm/entities/2/Entity.js +707 -0
- package/dist/esm/entities/2/Entity.js.map +1 -0
- package/dist/esm/entities/2/Entity.test.d.ts +1 -0
- package/dist/esm/entities/2/Entity.test.js +192 -0
- package/dist/esm/entities/2/Entity.test.js.map +1 -0
- package/dist/esm/entities/2/EntityCache.d.ts +15 -0
- package/dist/esm/entities/2/EntityCache.js +35 -0
- package/dist/esm/entities/2/EntityCache.js.map +1 -0
- package/dist/esm/entities/2/EntityMetadata.d.ts +68 -0
- package/dist/esm/entities/2/EntityMetadata.js +256 -0
- package/dist/esm/entities/2/EntityMetadata.js.map +1 -0
- package/dist/esm/entities/2/EntityStore.d.ts +78 -0
- package/dist/esm/entities/2/EntityStore.js +348 -0
- package/dist/esm/entities/2/EntityStore.js.map +1 -0
- package/dist/esm/entities/2/OperationBatcher.d.ts +52 -0
- package/dist/esm/entities/2/OperationBatcher.js +161 -0
- package/dist/esm/entities/2/OperationBatcher.js.map +1 -0
- package/dist/esm/entities/2/types.d.ts +84 -0
- package/dist/esm/entities/2/types.js +2 -0
- package/dist/esm/entities/2/types.js.map +1 -0
- package/dist/esm/entities/Entity.d.ts +0 -7
- package/dist/esm/entities/Entity.js +7 -0
- package/dist/esm/entities/Entity.js.map +1 -1
- package/dist/esm/entities/EntityStore.js +4 -20
- package/dist/esm/entities/EntityStore.js.map +1 -1
- package/dist/esm/entities/FakeWeakRef.d.ts +11 -0
- package/dist/esm/entities/FakeWeakRef.js +15 -0
- package/dist/esm/entities/FakeWeakRef.js.map +1 -0
- package/dist/esm/files/EntityFile.d.ts +5 -2
- package/dist/esm/files/EntityFile.js +8 -4
- package/dist/esm/files/EntityFile.js.map +1 -1
- package/dist/esm/files/FileManager.d.ts +3 -1
- package/dist/esm/files/FileManager.js +5 -3
- package/dist/esm/files/FileManager.js.map +1 -1
- package/dist/esm/files/FileStorage.js +7 -7
- package/dist/esm/files/FileStorage.js.map +1 -1
- package/dist/esm/files/utils.d.ts +2 -0
- package/dist/esm/files/utils.js +4 -2
- package/dist/esm/files/utils.js.map +1 -1
- package/dist/esm/idb.d.ts +2 -0
- package/dist/esm/idb.js +47 -3
- package/dist/esm/idb.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/indexes.d.ts +3 -0
- package/dist/esm/indexes.js +15 -0
- package/dist/esm/indexes.js.map +1 -0
- package/dist/esm/metadata/AckInfoStore.js +1 -1
- package/dist/esm/metadata/AckInfoStore.js.map +1 -1
- package/dist/esm/metadata/BaselinesStore.d.ts +4 -1
- package/dist/esm/metadata/BaselinesStore.js +19 -10
- package/dist/esm/metadata/BaselinesStore.js.map +1 -1
- package/dist/esm/metadata/LocalReplicaStore.d.ts +1 -1
- package/dist/esm/metadata/LocalReplicaStore.js +11 -5
- package/dist/esm/metadata/LocalReplicaStore.js.map +1 -1
- package/dist/esm/metadata/Metadata.d.ts +26 -5
- package/dist/esm/metadata/Metadata.js +56 -19
- package/dist/esm/metadata/Metadata.js.map +1 -1
- package/dist/esm/metadata/OperationsStore.d.ts +3 -0
- package/dist/esm/metadata/OperationsStore.js +35 -15
- package/dist/esm/metadata/OperationsStore.js.map +1 -1
- package/dist/esm/migration/openDatabase.js +32 -11
- package/dist/esm/migration/openDatabase.js.map +1 -1
- package/dist/esm/queries/BaseQuery.js +14 -2
- package/dist/esm/queries/BaseQuery.js.map +1 -1
- package/dist/esm/queries/CollectionQueries.d.ts +2 -4
- package/dist/esm/queries/CollectionQueries.js +1 -1
- package/dist/esm/queries/CollectionQueries.js.map +1 -1
- package/dist/esm/queries/FindAllQuery.js +1 -0
- package/dist/esm/queries/FindAllQuery.js.map +1 -1
- package/dist/esm/queries/QueryCache.d.ts +1 -0
- package/dist/esm/queries/QueryCache.js +4 -0
- package/dist/esm/queries/QueryCache.js.map +1 -1
- package/dist/esm/queries/QueryableStorage.d.ts +20 -0
- package/dist/esm/queries/QueryableStorage.js +80 -0
- package/dist/esm/queries/QueryableStorage.js.map +1 -0
- package/dist/esm/queries/dbQueries.js +13 -3
- package/dist/esm/queries/dbQueries.js.map +1 -1
- package/dist/esm/queries/utils.js +1 -1
- package/dist/esm/queries/utils.js.map +1 -1
- package/dist/esm/sync/FileSync.d.ts +1 -0
- package/dist/esm/sync/FileSync.js +1 -0
- package/dist/esm/sync/FileSync.js.map +1 -1
- package/dist/esm/sync/PushPullSync.d.ts +2 -1
- package/dist/esm/sync/PushPullSync.js +7 -1
- package/dist/esm/sync/PushPullSync.js.map +1 -1
- package/dist/esm/sync/Sync.d.ts +6 -3
- package/dist/esm/sync/Sync.js +9 -4
- package/dist/esm/sync/Sync.js.map +1 -1
- package/dist/esm/sync/WebSocketSync.d.ts +4 -1
- package/dist/esm/sync/WebSocketSync.js +41 -11
- package/dist/esm/sync/WebSocketSync.js.map +1 -1
- package/dist/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
- package/src/DocumentManager.ts +3 -7
- package/src/IDBService.ts +78 -17
- package/src/UndoHistory.ts +5 -3
- package/src/__tests__/batching.test.ts +5 -2
- package/src/__tests__/documents.test.ts +44 -6
- package/src/__tests__/fixtures/testStorage.ts +3 -0
- package/src/__tests__/legacyOids.test.ts +53 -17
- package/src/__tests__/mutations.test.ts +9 -3
- package/src/__tests__/queries.test.ts +6 -2
- package/src/__tests__/setup/indexedDB.ts +8 -1
- package/src/__tests__/undo.test.ts +17 -9
- package/src/client/Client.ts +8 -4
- package/src/client/ClientDescriptor.ts +24 -8
- package/src/context.ts +16 -1
- package/src/entities/2/Entity.test.ts +218 -0
- package/src/entities/2/Entity.ts +954 -0
- package/src/entities/2/EntityCache.ts +41 -0
- package/src/entities/2/EntityMetadata.ts +364 -0
- package/src/entities/2/EntityStore.ts +490 -0
- package/src/entities/2/NOTES.md +22 -0
- package/src/entities/2/OperationBatcher.ts +251 -0
- package/src/entities/2/types.ts +154 -0
- package/src/files/EntityFile.ts +9 -4
- package/src/files/FileManager.ts +5 -3
- package/src/files/FileStorage.ts +7 -13
- package/src/files/utils.ts +6 -2
- package/src/idb.ts +51 -3
- package/src/index.ts +2 -2
- package/src/metadata/AckInfoStore.ts +1 -1
- package/src/metadata/BaselinesStore.ts +16 -24
- package/src/metadata/LocalReplicaStore.ts +13 -6
- package/src/metadata/Metadata.ts +109 -24
- package/src/metadata/OperationsStore.ts +37 -16
- package/src/migration/openDatabase.ts +32 -10
- package/src/queries/BaseQuery.ts +15 -2
- package/src/queries/CollectionQueries.ts +3 -3
- package/src/queries/FindAllQuery.ts +4 -0
- package/src/queries/QueryCache.ts +5 -0
- package/src/queries/QueryableStorage.ts +107 -0
- package/src/queries/dbQueries.ts +10 -3
- package/src/queries/utils.ts +1 -1
- package/src/sync/FileSync.ts +2 -0
- package/src/sync/PushPullSync.ts +8 -1
- package/src/sync/Sync.ts +14 -6
- package/src/sync/WebSocketSync.ts +47 -10
- package/src/entities/DocumentFamiliyCache.ts +0 -426
- package/src/entities/Entity.ts +0 -874
- 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
|
|
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.
|
|
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
|
|
|
@@ -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
|
+
}
|
package/src/queries/dbQueries.ts
CHANGED
|
@@ -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
|
}
|
package/src/queries/utils.ts
CHANGED
package/src/sync/FileSync.ts
CHANGED
|
@@ -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
|
}
|
package/src/sync/PushPullSync.ts
CHANGED
|
@@ -152,11 +152,18 @@ export class PushPullSync
|
|
|
152
152
|
this._status = 'paused';
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
|
457
|
-
this.
|
|
458
|
-
|
|
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
|
-
|
|
111
|
-
this.
|
|
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.
|
|
151
|
+
if (!this.synced) {
|
|
122
152
|
this.log(
|
|
123
|
-
`
|
|
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
|
-
|
|
219
|
-
this.
|
|
220
|
-
this.
|
|
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.
|
|
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
|
}
|