@verdant-web/store 3.12.1 → 4.0.0-next.1
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 +11 -13
- package/dist/bundle/index.js.map +4 -4
- package/dist/esm/__tests__/batching.test.js +5 -5
- package/dist/esm/__tests__/batching.test.js.map +1 -1
- package/dist/esm/__tests__/entities.test.js +1 -1
- package/dist/esm/__tests__/entities.test.js.map +1 -1
- package/dist/esm/__tests__/fixtures/testStorage.d.ts +1 -3
- package/dist/esm/__tests__/fixtures/testStorage.js +3 -3
- package/dist/esm/__tests__/fixtures/testStorage.js.map +1 -1
- package/dist/esm/__tests__/queries.test.js.map +1 -1
- package/dist/esm/backup.d.ts +3 -4
- package/dist/esm/backup.js.map +1 -1
- package/dist/esm/client/Client.d.ts +28 -33
- package/dist/esm/client/Client.js +50 -161
- package/dist/esm/client/Client.js.map +1 -1
- package/dist/esm/client/ClientDescriptor.d.ts +8 -11
- package/dist/esm/client/ClientDescriptor.js +39 -141
- package/dist/esm/client/ClientDescriptor.js.map +1 -1
- package/dist/esm/context/Time.d.ts +13 -0
- package/dist/esm/context/Time.js +27 -0
- package/dist/esm/context/Time.js.map +1 -0
- package/dist/esm/context/context.d.ts +170 -0
- package/dist/esm/{context.js.map → context/context.js.map} +1 -1
- package/dist/esm/entities/DocumentManager.js.map +1 -1
- package/dist/esm/entities/Entity.d.ts +4 -5
- package/dist/esm/entities/Entity.js +5 -3
- package/dist/esm/entities/Entity.js.map +1 -1
- package/dist/esm/entities/Entity.test.js +4 -3
- package/dist/esm/entities/Entity.test.js.map +1 -1
- package/dist/esm/entities/EntityCache.d.ts +0 -3
- package/dist/esm/entities/EntityCache.js +0 -9
- package/dist/esm/entities/EntityCache.js.map +1 -1
- package/dist/esm/entities/EntityMetadata.d.ts +1 -1
- package/dist/esm/entities/EntityMetadata.js +6 -5
- package/dist/esm/entities/EntityMetadata.js.map +1 -1
- package/dist/esm/entities/EntityStore.d.ts +2 -6
- package/dist/esm/entities/EntityStore.js +22 -16
- package/dist/esm/entities/EntityStore.js.map +1 -1
- package/dist/esm/entities/OperationBatcher.d.ts +2 -5
- package/dist/esm/entities/OperationBatcher.js +9 -7
- package/dist/esm/entities/OperationBatcher.js.map +1 -1
- package/dist/esm/errors.d.ts +8 -0
- package/dist/esm/errors.js +12 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/files/EntityFile.d.ts +6 -3
- package/dist/esm/files/EntityFile.js +22 -19
- package/dist/esm/files/EntityFile.js.map +1 -1
- package/dist/esm/files/FileManager.d.ts +8 -39
- package/dist/esm/files/FileManager.js +26 -170
- package/dist/esm/files/FileManager.js.map +1 -1
- package/dist/esm/files/utils.d.ts +0 -1
- package/dist/esm/files/utils.js +0 -14
- package/dist/esm/files/utils.js.map +1 -1
- package/dist/esm/index.d.ts +1 -2
- package/dist/esm/index.js +0 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/{metadata → persistence}/MessageCreator.d.ts +5 -6
- package/dist/esm/{metadata → persistence}/MessageCreator.js +31 -38
- package/dist/esm/persistence/MessageCreator.js.map +1 -0
- package/dist/esm/persistence/PersistenceFiles.d.ts +48 -0
- package/dist/esm/persistence/PersistenceFiles.js +160 -0
- package/dist/esm/persistence/PersistenceFiles.js.map +1 -0
- package/dist/esm/persistence/PersistenceMetadata.d.ts +69 -0
- package/dist/esm/persistence/PersistenceMetadata.js +302 -0
- package/dist/esm/persistence/PersistenceMetadata.js.map +1 -0
- package/dist/esm/persistence/PersistenceQueries.d.ts +34 -0
- package/dist/esm/persistence/PersistenceQueries.js +15 -0
- package/dist/esm/persistence/PersistenceQueries.js.map +1 -0
- package/dist/esm/persistence/PersistenceRebaser.d.ts +32 -0
- package/dist/esm/persistence/PersistenceRebaser.js +120 -0
- package/dist/esm/persistence/PersistenceRebaser.js.map +1 -0
- package/dist/esm/{IDBService.d.ts → persistence/idb/IdbService.d.ts} +9 -7
- package/dist/esm/{IDBService.js → persistence/idb/IdbService.js} +29 -8
- package/dist/esm/persistence/idb/IdbService.js.map +1 -0
- package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.d.ts +58 -0
- package/dist/esm/{files/FileStorage.js → persistence/idb/files/IdbPersistenceFileDb.js} +85 -50
- package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.js.map +1 -0
- package/dist/esm/persistence/idb/idbPersistence.d.ts +19 -0
- package/dist/esm/persistence/idb/idbPersistence.js +80 -0
- package/dist/esm/persistence/idb/idbPersistence.js.map +1 -0
- package/dist/esm/persistence/idb/metadata/IdbMetadataDb.d.ts +72 -0
- package/dist/esm/persistence/idb/metadata/IdbMetadataDb.js +235 -0
- package/dist/esm/persistence/idb/metadata/IdbMetadataDb.js.map +1 -0
- package/dist/esm/{metadata → persistence/idb/metadata}/openMetadataDatabase.d.ts +3 -1
- package/dist/esm/{metadata → persistence/idb/metadata}/openMetadataDatabase.js +12 -3
- package/dist/esm/persistence/idb/metadata/openMetadataDatabase.js.map +1 -0
- package/dist/esm/persistence/idb/queries/IdbQueryDb.d.ts +41 -0
- package/dist/esm/persistence/idb/queries/IdbQueryDb.js +174 -0
- package/dist/esm/persistence/idb/queries/IdbQueryDb.js.map +1 -0
- package/dist/esm/{migration → persistence/idb/queries/migration}/db.d.ts +1 -1
- package/dist/esm/{migration → persistence/idb/queries/migration}/db.js +10 -48
- package/dist/esm/persistence/idb/queries/migration/db.js.map +1 -0
- package/dist/esm/persistence/idb/queries/migration/engine.d.ts +12 -0
- package/dist/esm/{migration → persistence/idb/queries/migration}/engine.js +29 -46
- package/dist/esm/persistence/idb/queries/migration/engine.js.map +1 -0
- package/dist/esm/{migration → persistence/idb/queries/migration}/migrations.d.ts +1 -3
- package/dist/esm/{migration → persistence/idb/queries/migration}/migrations.js +11 -10
- package/dist/esm/persistence/idb/queries/migration/migrations.js.map +1 -0
- package/dist/esm/{migration → persistence/idb/queries/migration}/openQueryDatabase.d.ts +1 -3
- package/dist/esm/{migration → persistence/idb/queries/migration}/openQueryDatabase.js +4 -7
- package/dist/esm/persistence/idb/queries/migration/openQueryDatabase.js.map +1 -0
- package/dist/esm/{migration → persistence/idb/queries/migration}/paths.js +2 -2
- package/dist/esm/persistence/idb/queries/migration/paths.js.map +1 -0
- package/dist/esm/persistence/idb/queries/migration/paths.test.js.map +1 -0
- package/dist/esm/persistence/idb/queries/migration/types.d.ts +6 -0
- package/dist/esm/persistence/idb/queries/migration/types.js.map +1 -0
- package/dist/esm/persistence/idb/queries/ranges.d.ts +2 -0
- package/dist/esm/persistence/idb/queries/ranges.js +66 -0
- package/dist/esm/persistence/idb/queries/ranges.js.map +1 -0
- package/dist/esm/{idb.d.ts → persistence/idb/util.d.ts} +11 -0
- package/dist/esm/{idb.js → persistence/idb/util.js} +58 -1
- package/dist/esm/persistence/idb/util.js.map +1 -0
- package/dist/esm/persistence/interfaces.d.ts +181 -0
- package/dist/esm/persistence/interfaces.js +2 -0
- package/dist/esm/persistence/interfaces.js.map +1 -0
- package/dist/esm/persistence/persistence.d.ts +4 -0
- package/dist/esm/persistence/persistence.js +126 -0
- package/dist/esm/persistence/persistence.js.map +1 -0
- package/dist/esm/queries/BaseQuery.d.ts +2 -1
- package/dist/esm/queries/BaseQuery.js +3 -0
- package/dist/esm/queries/BaseQuery.js.map +1 -1
- package/dist/esm/queries/CollectionQueries.d.ts +1 -1
- package/dist/esm/queries/FindAllQuery.js +1 -3
- package/dist/esm/queries/FindAllQuery.js.map +1 -1
- package/dist/esm/queries/FindInfiniteQuery.js +2 -5
- package/dist/esm/queries/FindInfiniteQuery.js.map +1 -1
- package/dist/esm/queries/FindOneQuery.js +1 -3
- package/dist/esm/queries/FindOneQuery.js.map +1 -1
- package/dist/esm/queries/FindPageQuery.js +1 -3
- package/dist/esm/queries/FindPageQuery.js.map +1 -1
- package/dist/esm/queries/QueryCache.d.ts +1 -1
- package/dist/esm/queries/QueryCache.js +4 -0
- package/dist/esm/queries/QueryCache.js.map +1 -1
- package/dist/esm/sync/FileSync.d.ts +23 -8
- package/dist/esm/sync/FileSync.js +76 -28
- package/dist/esm/sync/FileSync.js.map +1 -1
- package/dist/esm/sync/PresenceManager.d.ts +4 -3
- package/dist/esm/sync/PresenceManager.js +2 -2
- package/dist/esm/sync/PresenceManager.js.map +1 -1
- package/dist/esm/sync/PushPullSync.d.ts +4 -6
- package/dist/esm/sync/PushPullSync.js +13 -12
- package/dist/esm/sync/PushPullSync.js.map +1 -1
- package/dist/esm/sync/Sync.d.ts +10 -11
- package/dist/esm/sync/Sync.js +55 -30
- package/dist/esm/sync/Sync.js.map +1 -1
- package/dist/esm/sync/WebSocketSync.d.ts +4 -6
- package/dist/esm/sync/WebSocketSync.js +20 -22
- package/dist/esm/sync/WebSocketSync.js.map +1 -1
- package/dist/esm/utils/Disposable.d.ts +5 -2
- package/dist/esm/utils/Disposable.js +3 -2
- package/dist/esm/utils/Disposable.js.map +1 -1
- package/dist/esm/utils/wip.d.ts +2 -0
- package/dist/esm/utils/wip.js +5 -0
- package/dist/esm/utils/wip.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/batching.test.ts +6 -6
- package/src/__tests__/entities.test.ts +1 -1
- package/src/__tests__/fixtures/testStorage.ts +2 -10
- package/src/__tests__/queries.test.ts +1 -1
- package/src/backup.ts +3 -4
- package/src/client/Client.ts +69 -226
- package/src/client/ClientDescriptor.ts +53 -184
- package/src/context/Time.ts +35 -0
- package/src/context/context.ts +200 -0
- package/src/entities/DocumentManager.ts +0 -3
- package/src/entities/Entity.test.ts +9 -9
- package/src/entities/Entity.ts +6 -12
- package/src/entities/EntityCache.ts +0 -9
- package/src/entities/EntityMetadata.ts +4 -4
- package/src/entities/EntityStore.ts +26 -29
- package/src/entities/OperationBatcher.ts +9 -11
- package/src/errors.ts +13 -0
- package/src/files/EntityFile.ts +16 -5
- package/src/files/FileManager.ts +35 -245
- package/src/files/utils.ts +0 -15
- package/src/index.ts +2 -1
- package/src/{metadata → persistence}/MessageCreator.ts +46 -36
- package/src/persistence/PersistenceFiles.ts +227 -0
- package/src/persistence/PersistenceMetadata.ts +425 -0
- package/src/persistence/PersistenceQueries.ts +22 -0
- package/src/persistence/PersistenceRebaser.ts +171 -0
- package/src/{IDBService.ts → persistence/idb/IdbService.ts} +45 -12
- package/src/{files/FileStorage.ts → persistence/idb/files/IdbPersistenceFileDb.ts} +128 -86
- package/src/persistence/idb/idbPersistence.ts +116 -0
- package/src/persistence/idb/metadata/IdbMetadataDb.ts +460 -0
- package/src/{metadata → persistence/idb/metadata}/openMetadataDatabase.ts +21 -4
- package/src/persistence/idb/queries/IdbQueryDb.ts +251 -0
- package/src/{migration → persistence/idb/queries/migration}/db.ts +18 -72
- package/src/{migration → persistence/idb/queries/migration}/engine.ts +39 -62
- package/src/{migration → persistence/idb/queries/migration}/migrations.ts +13 -18
- package/src/{migration → persistence/idb/queries/migration}/openQueryDatabase.ts +5 -14
- package/src/{migration → persistence/idb/queries/migration}/paths.ts +4 -3
- package/src/persistence/idb/queries/migration/types.ts +8 -0
- package/src/persistence/idb/queries/ranges.ts +107 -0
- package/src/{idb.ts → persistence/idb/util.ts} +75 -0
- package/src/persistence/interfaces.ts +240 -0
- package/src/persistence/persistence.ts +223 -0
- package/src/queries/BaseQuery.ts +5 -1
- package/src/queries/CollectionQueries.ts +2 -2
- package/src/queries/FindAllQuery.ts +1 -3
- package/src/queries/FindInfiniteQuery.ts +2 -5
- package/src/queries/FindOneQuery.ts +1 -3
- package/src/queries/FindPageQuery.ts +1 -3
- package/src/queries/QueryCache.ts +20 -1
- package/src/sync/FileSync.ts +93 -30
- package/src/sync/PresenceManager.ts +5 -7
- package/src/sync/PushPullSync.ts +23 -19
- package/src/sync/Sync.ts +71 -37
- package/src/sync/WebSocketSync.ts +41 -27
- package/src/utils/Disposable.ts +7 -4
- package/src/utils/wip.ts +5 -0
- package/dist/esm/IDBService.js.map +0 -1
- package/dist/esm/__tests__/legacyOids.test.d.ts +0 -1
- package/dist/esm/__tests__/legacyOids.test.js +0 -352
- package/dist/esm/__tests__/legacyOids.test.js.map +0 -1
- package/dist/esm/context.d.ts +0 -45
- package/dist/esm/files/FileStorage.d.ts +0 -47
- package/dist/esm/files/FileStorage.js.map +0 -1
- package/dist/esm/idb.js.map +0 -1
- package/dist/esm/metadata/AckInfoStore.d.ts +0 -10
- package/dist/esm/metadata/AckInfoStore.js +0 -22
- package/dist/esm/metadata/AckInfoStore.js.map +0 -1
- package/dist/esm/metadata/BaselinesStore.d.ts +0 -40
- package/dist/esm/metadata/BaselinesStore.js +0 -102
- package/dist/esm/metadata/BaselinesStore.js.map +0 -1
- package/dist/esm/metadata/LocalReplicaStore.d.ts +0 -19
- package/dist/esm/metadata/LocalReplicaStore.js +0 -56
- package/dist/esm/metadata/LocalReplicaStore.js.map +0 -1
- package/dist/esm/metadata/MessageCreator.js.map +0 -1
- package/dist/esm/metadata/Metadata.d.ts +0 -146
- package/dist/esm/metadata/Metadata.js +0 -452
- package/dist/esm/metadata/Metadata.js.map +0 -1
- package/dist/esm/metadata/OperationsStore.d.ts +0 -62
- package/dist/esm/metadata/OperationsStore.js +0 -175
- package/dist/esm/metadata/OperationsStore.js.map +0 -1
- package/dist/esm/metadata/SchemaStore.d.ts +0 -9
- package/dist/esm/metadata/SchemaStore.js +0 -35
- package/dist/esm/metadata/SchemaStore.js.map +0 -1
- package/dist/esm/metadata/openMetadataDatabase.js.map +0 -1
- package/dist/esm/migration/db.js.map +0 -1
- package/dist/esm/migration/engine.d.ts +0 -15
- package/dist/esm/migration/engine.js.map +0 -1
- package/dist/esm/migration/errors.d.ts +0 -5
- package/dist/esm/migration/errors.js +0 -8
- package/dist/esm/migration/errors.js.map +0 -1
- package/dist/esm/migration/migrations.js.map +0 -1
- package/dist/esm/migration/openQueryDatabase.js.map +0 -1
- package/dist/esm/migration/openWIPDatabase.d.ts +0 -11
- package/dist/esm/migration/openWIPDatabase.js +0 -65
- package/dist/esm/migration/openWIPDatabase.js.map +0 -1
- package/dist/esm/migration/paths.js.map +0 -1
- package/dist/esm/migration/paths.test.js.map +0 -1
- package/dist/esm/migration/types.d.ts +0 -3
- package/dist/esm/migration/types.js.map +0 -1
- package/dist/esm/queries/QueryableStorage.d.ts +0 -20
- package/dist/esm/queries/QueryableStorage.js +0 -90
- package/dist/esm/queries/QueryableStorage.js.map +0 -1
- package/dist/esm/queries/dbQueries.d.ts +0 -22
- package/dist/esm/queries/dbQueries.js +0 -130
- package/dist/esm/queries/dbQueries.js.map +0 -1
- package/src/__tests__/legacyOids.test.ts +0 -375
- package/src/context.ts +0 -55
- package/src/metadata/AckInfoStore.ts +0 -30
- package/src/metadata/BaselinesStore.ts +0 -188
- package/src/metadata/LocalReplicaStore.ts +0 -79
- package/src/metadata/Metadata.ts +0 -685
- package/src/metadata/OperationsStore.ts +0 -332
- package/src/metadata/SchemaStore.ts +0 -47
- package/src/migration/errors.ts +0 -7
- package/src/migration/openWIPDatabase.ts +0 -97
- package/src/migration/types.ts +0 -4
- package/src/queries/QueryableStorage.ts +0 -122
- package/src/queries/dbQueries.ts +0 -161
- /package/dist/esm/{context.js → context/context.js} +0 -0
- /package/dist/esm/{migration → persistence/idb/queries/migration}/paths.d.ts +0 -0
- /package/dist/esm/{migration → persistence/idb/queries/migration}/paths.test.d.ts +0 -0
- /package/dist/esm/{migration → persistence/idb/queries/migration}/paths.test.js +0 -0
- /package/dist/esm/{migration → persistence/idb/queries/migration}/types.js +0 -0
- /package/src/{migration → persistence/idb/queries/migration}/paths.test.ts +0 -0
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EventSubscriber,
|
|
3
|
+
HybridLogicalClockTimestampProvider,
|
|
3
4
|
Migration,
|
|
4
|
-
|
|
5
|
+
PatchCreator,
|
|
5
6
|
StorageSchema,
|
|
6
|
-
|
|
7
|
+
noop,
|
|
7
8
|
} from '@verdant-web/common';
|
|
8
|
-
import {
|
|
9
|
-
import { FileManagerConfig } from '../files/FileManager.js';
|
|
10
|
-
import { Metadata } from '../metadata/Metadata.js';
|
|
11
|
-
import {
|
|
12
|
-
openMetadataDatabase,
|
|
13
|
-
openWIPMetadataDatabase,
|
|
14
|
-
} from '../metadata/openMetadataDatabase.js';
|
|
15
|
-
import { openWIPDatabase } from '../migration/openWIPDatabase.js';
|
|
9
|
+
import { FileConfig, InitialContext } from '../context/context.js';
|
|
16
10
|
import { ServerSyncOptions } from '../sync/Sync.js';
|
|
17
11
|
import { UndoHistory } from '../UndoHistory.js';
|
|
18
12
|
import { Client } from './Client.js';
|
|
19
|
-
import {
|
|
20
|
-
deleteAllDatabases,
|
|
21
|
-
deleteDatabase,
|
|
22
|
-
getAllDatabaseNamesAndVersions,
|
|
23
|
-
} from '../idb.js';
|
|
13
|
+
import { deleteAllDatabases } from '../persistence/idb/util.js';
|
|
24
14
|
import { FakeWeakRef } from '../FakeWeakRef.js';
|
|
25
15
|
import { METADATA_VERSION_KEY } from './constants.js';
|
|
26
|
-
import {
|
|
16
|
+
import { Time } from '../context/Time.js';
|
|
17
|
+
import { initializePersistence } from '../persistence/persistence.js';
|
|
18
|
+
import { PersistenceImplementation } from '../persistence/interfaces.js';
|
|
19
|
+
import { IdbPersistence } from '../persistence/idb/idbPersistence.js';
|
|
27
20
|
|
|
28
21
|
export interface ClientDescriptorOptions<Presence = any, Profile = any> {
|
|
29
22
|
/** The schema used to create this client */
|
|
30
23
|
schema: StorageSchema<any>;
|
|
31
|
-
oldSchemas
|
|
24
|
+
oldSchemas: StorageSchema<any>[];
|
|
32
25
|
/** Migrations, in order, to upgrade to each successive version of the schema */
|
|
33
26
|
migrations: Migration<any>[];
|
|
34
27
|
/** Provide a sync config to turn on synchronization with a server */
|
|
@@ -52,6 +45,7 @@ export interface ClientDescriptorOptions<Presence = any, Profile = any> {
|
|
|
52
45
|
...args: any[]
|
|
53
46
|
) => void;
|
|
54
47
|
disableRebasing?: boolean;
|
|
48
|
+
rebaseTimeout?: number;
|
|
55
49
|
/**
|
|
56
50
|
* Provide a specific schema number to override the schema version
|
|
57
51
|
* in the database. This is useful for testing migrations or recovering
|
|
@@ -62,14 +56,13 @@ export interface ClientDescriptorOptions<Presence = any, Profile = any> {
|
|
|
62
56
|
/**
|
|
63
57
|
* Configuration for file management
|
|
64
58
|
*/
|
|
65
|
-
files?:
|
|
59
|
+
files?: FileConfig;
|
|
66
60
|
|
|
67
61
|
/**
|
|
68
|
-
*
|
|
69
|
-
* Wouldn't recommend using this unless you know what you're doing.
|
|
70
|
-
* It's a very hot code path...
|
|
62
|
+
* Override the default IndexedDB persistence implementation.
|
|
71
63
|
*/
|
|
72
|
-
|
|
64
|
+
persistence?: PersistenceImplementation;
|
|
65
|
+
|
|
73
66
|
/**
|
|
74
67
|
* Enables experimental WeakRef usage to cull documents
|
|
75
68
|
* from cache that aren't being used. This is a performance
|
|
@@ -121,7 +114,7 @@ export class ClientDescriptor<
|
|
|
121
114
|
// we can't initialize the storage
|
|
122
115
|
if (typeof window === 'undefined' && !init.indexedDb) {
|
|
123
116
|
throw new Error(
|
|
124
|
-
'A
|
|
117
|
+
'A Verdant client was initialized in an environment without IndexedDB. If you are using verdant in a server-rendered framework, you must enforce that all clients are initialized on the client-side, or you must provide some mock interface of IDBFactory to the ClientDescriptor options.',
|
|
125
118
|
);
|
|
126
119
|
}
|
|
127
120
|
|
|
@@ -130,17 +123,43 @@ export class ClientDescriptor<
|
|
|
130
123
|
}
|
|
131
124
|
this._initializing = true;
|
|
132
125
|
try {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
126
|
+
const time = new Time(
|
|
127
|
+
new HybridLogicalClockTimestampProvider(),
|
|
128
|
+
init.schema.version,
|
|
129
|
+
);
|
|
130
|
+
let ctx: InitialContext = {
|
|
131
|
+
closing: false,
|
|
132
|
+
entityEvents: new EventSubscriber(),
|
|
133
|
+
globalEvents: new EventSubscriber(),
|
|
134
|
+
internalEvents: new EventSubscriber(),
|
|
135
|
+
log: init.log || noop,
|
|
136
|
+
migrations: init.migrations,
|
|
137
|
+
namespace: init.namespace,
|
|
138
|
+
originalNamespace: init.namespace,
|
|
139
|
+
schema: init.schema,
|
|
140
|
+
oldSchemas: init.oldSchemas,
|
|
141
|
+
time,
|
|
142
|
+
undoHistory: init.undoHistory || new UndoHistory(),
|
|
143
|
+
weakRef: (val) =>
|
|
144
|
+
init.EXPERIMENTAL_weakRefs
|
|
145
|
+
? new WeakRef(val)
|
|
146
|
+
: (new FakeWeakRef(val) as any),
|
|
147
|
+
patchCreator: new PatchCreator(() => time.now),
|
|
148
|
+
config: {
|
|
149
|
+
files: init.files,
|
|
150
|
+
sync: init.sync,
|
|
151
|
+
persistence: {
|
|
152
|
+
disableRebasing: init.disableRebasing,
|
|
153
|
+
rebaseTimeout: init.rebaseTimeout,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
persistence: init.persistence || new IdbPersistence(init.indexedDb),
|
|
157
|
+
};
|
|
158
|
+
const context = await initializePersistence(ctx);
|
|
159
|
+
const client = new Client(context) as ClientImpl;
|
|
160
|
+
this.resolveReady(client);
|
|
161
|
+
this._resolvedValue = client;
|
|
162
|
+
return client;
|
|
144
163
|
} catch (err) {
|
|
145
164
|
if (err instanceof Error) {
|
|
146
165
|
this.rejectReady(err as Error);
|
|
@@ -153,156 +172,6 @@ export class ClientDescriptor<
|
|
|
153
172
|
}
|
|
154
173
|
};
|
|
155
174
|
|
|
156
|
-
private initializeDatabases = async (init: ClientDescriptorOptions) => {
|
|
157
|
-
const metadataVersion = init[METADATA_VERSION_KEY];
|
|
158
|
-
const { db: metaDb } = await openMetadataDatabase({
|
|
159
|
-
indexedDB: init.indexedDb,
|
|
160
|
-
log: init.log,
|
|
161
|
-
namespace: init.namespace,
|
|
162
|
-
metadataVersion,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
const context: Omit<Context, 'documentDb' | 'getNow'> = {
|
|
166
|
-
namespace: this._namespace,
|
|
167
|
-
metaDb,
|
|
168
|
-
schema: init.schema,
|
|
169
|
-
log: init.log || (() => {}),
|
|
170
|
-
undoHistory: init.undoHistory || new UndoHistory(),
|
|
171
|
-
entityEvents: new EventSubscriber(),
|
|
172
|
-
globalEvents: new EventSubscriber(),
|
|
173
|
-
internalEvents: new EventSubscriber(),
|
|
174
|
-
weakRef: (value) => {
|
|
175
|
-
if (init.EXPERIMENTAL_weakRefs) {
|
|
176
|
-
return new WeakRef(value);
|
|
177
|
-
} else {
|
|
178
|
-
return new FakeWeakRef(value) as unknown as WeakRef<typeof value>;
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
migrations: init.migrations,
|
|
182
|
-
oldSchemas: init.oldSchemas,
|
|
183
|
-
};
|
|
184
|
-
const meta = new Metadata({
|
|
185
|
-
context,
|
|
186
|
-
disableRebasing: init.disableRebasing,
|
|
187
|
-
onOperation: init.onOperation,
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// verify schema integrity
|
|
191
|
-
await meta.updateSchema(init.schema, init.overrideSchemaConflict);
|
|
192
|
-
|
|
193
|
-
const contextWithNow: Omit<Context, 'documentDb'> = Object.assign(context, {
|
|
194
|
-
getNow: () => meta.now,
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
const documentDb = await openQueryDatabase({
|
|
198
|
-
context: contextWithNow,
|
|
199
|
-
version: init.schema.version,
|
|
200
|
-
meta,
|
|
201
|
-
migrations: init.migrations,
|
|
202
|
-
indexedDB: init.indexedDb,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const fullContext: Context = Object.assign(contextWithNow, { documentDb });
|
|
206
|
-
|
|
207
|
-
const storage = new Client(
|
|
208
|
-
{
|
|
209
|
-
syncConfig: init.sync,
|
|
210
|
-
migrations: init.migrations,
|
|
211
|
-
files: init.files,
|
|
212
|
-
},
|
|
213
|
-
fullContext,
|
|
214
|
-
{
|
|
215
|
-
meta,
|
|
216
|
-
},
|
|
217
|
-
) as ClientImpl;
|
|
218
|
-
|
|
219
|
-
return storage;
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
private initializeWIPDatabases = async (init: ClientDescriptorOptions) => {
|
|
223
|
-
const schemaHash = hashObject(init.schema);
|
|
224
|
-
console.info(`WIP schema in use. Opening database with hash ${schemaHash}`);
|
|
225
|
-
|
|
226
|
-
const wipNamespace = `@@wip_${init.namespace}_${schemaHash}`;
|
|
227
|
-
const { db: metaDb } = await openWIPMetadataDatabase({
|
|
228
|
-
indexedDB: init.indexedDb,
|
|
229
|
-
log: init.log,
|
|
230
|
-
namespace: init.namespace,
|
|
231
|
-
wipNamespace: wipNamespace,
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
const context: Omit<Context, 'documentDb' | 'getNow'> = {
|
|
235
|
-
namespace: this._namespace,
|
|
236
|
-
metaDb,
|
|
237
|
-
schema: init.schema,
|
|
238
|
-
log: init.log || (() => {}),
|
|
239
|
-
undoHistory: init.undoHistory || new UndoHistory(),
|
|
240
|
-
entityEvents: new EventSubscriber(),
|
|
241
|
-
globalEvents: new EventSubscriber(),
|
|
242
|
-
internalEvents: new EventSubscriber(),
|
|
243
|
-
weakRef: (value) => {
|
|
244
|
-
if (init.EXPERIMENTAL_weakRefs) {
|
|
245
|
-
return new WeakRef(value);
|
|
246
|
-
} else {
|
|
247
|
-
return new FakeWeakRef(value) as unknown as WeakRef<typeof value>;
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
migrations: init.migrations,
|
|
251
|
-
oldSchemas: init.oldSchemas,
|
|
252
|
-
};
|
|
253
|
-
const meta = new Metadata({
|
|
254
|
-
context,
|
|
255
|
-
disableRebasing: init.disableRebasing,
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
const contextWithNow: Omit<Context, 'documentDb'> = Object.assign(context, {
|
|
259
|
-
getNow: () => meta.now,
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// verify schema integrity
|
|
263
|
-
await meta.updateSchema(init.schema, init.overrideSchemaConflict);
|
|
264
|
-
|
|
265
|
-
const documentDb = await openWIPDatabase({
|
|
266
|
-
context: contextWithNow,
|
|
267
|
-
version: init.schema.version,
|
|
268
|
-
meta,
|
|
269
|
-
migrations: init.migrations,
|
|
270
|
-
indexedDB: init.indexedDb,
|
|
271
|
-
wipNamespace,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
const fullContext: Context = Object.assign(contextWithNow, { documentDb });
|
|
275
|
-
|
|
276
|
-
const storage = new Client(
|
|
277
|
-
{
|
|
278
|
-
syncConfig: init.sync,
|
|
279
|
-
migrations: init.migrations,
|
|
280
|
-
files: init.files,
|
|
281
|
-
},
|
|
282
|
-
fullContext,
|
|
283
|
-
{
|
|
284
|
-
meta,
|
|
285
|
-
},
|
|
286
|
-
) as ClientImpl;
|
|
287
|
-
|
|
288
|
-
return storage;
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
private cleanupWIPDatabases = async (init: ClientDescriptorOptions) => {
|
|
292
|
-
const databaseInfo = await getAllDatabaseNamesAndVersions(init.indexedDb);
|
|
293
|
-
const wipDatabases = databaseInfo
|
|
294
|
-
.filter((db) => db.name?.startsWith('@@wip_'))
|
|
295
|
-
.map((db) => db.name!);
|
|
296
|
-
// don't clear a current WIP database.
|
|
297
|
-
const wipDatabasesToDelete = wipDatabases.filter(
|
|
298
|
-
(db) =>
|
|
299
|
-
!db.startsWith(`@@wip_${init.namespace}_${hashObject(init.schema)}`),
|
|
300
|
-
);
|
|
301
|
-
for (const db of wipDatabasesToDelete) {
|
|
302
|
-
await deleteDatabase(db, init.indexedDb);
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
|
|
306
175
|
get current() {
|
|
307
176
|
// exposing an immediate value if already resolved lets us
|
|
308
177
|
// skip the promise microtask when accessing this externally if
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { TimestampProvider } from '@verdant-web/common';
|
|
2
|
+
|
|
3
|
+
export class Time {
|
|
4
|
+
private overrideNow?: () => string;
|
|
5
|
+
constructor(
|
|
6
|
+
private base: TimestampProvider,
|
|
7
|
+
private version: number,
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
get now() {
|
|
11
|
+
return this.overrideNow ? this.overrideNow() : this.base.now(this.version);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
withMigrationTime = async (version: number, run: () => Promise<void>) => {
|
|
15
|
+
this.overrideNow = () => {
|
|
16
|
+
return this.base.zero(version);
|
|
17
|
+
};
|
|
18
|
+
await run();
|
|
19
|
+
this.overrideNow = undefined;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
update = this.base.update.bind(this.base);
|
|
23
|
+
|
|
24
|
+
nowWithVersion = (version: number) => {
|
|
25
|
+
return this.base.now(version);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
get zero() {
|
|
29
|
+
return this.base.zero(this.version);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
zeroWithVersion = (version: number) => {
|
|
33
|
+
return this.base.zero(version);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClientMessage,
|
|
3
|
+
EventSubscriber,
|
|
4
|
+
FileData,
|
|
5
|
+
FileRef,
|
|
6
|
+
Migration,
|
|
7
|
+
ObjectIdentifier,
|
|
8
|
+
Operation,
|
|
9
|
+
PatchCreator,
|
|
10
|
+
StorageSchema,
|
|
11
|
+
} from '@verdant-web/common';
|
|
12
|
+
import { UndoHistory } from '../UndoHistory.js';
|
|
13
|
+
import { Time } from './Time.js';
|
|
14
|
+
import type { PersistenceQueries } from '../persistence/PersistenceQueries.js';
|
|
15
|
+
import type { PersistenceMetadata } from '../persistence/PersistenceMetadata.js';
|
|
16
|
+
import { PersistenceFiles } from '../persistence/PersistenceFiles.js';
|
|
17
|
+
import {
|
|
18
|
+
PersistedFileData,
|
|
19
|
+
PersistenceImplementation,
|
|
20
|
+
} from '../persistence/interfaces.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Common components utilized across various client
|
|
24
|
+
* services.
|
|
25
|
+
*/
|
|
26
|
+
export interface Context {
|
|
27
|
+
namespace: string;
|
|
28
|
+
/**
|
|
29
|
+
* when in WIP mode, namespace might be set to a temporary value. This will always point to the
|
|
30
|
+
* namespace the user passed in.
|
|
31
|
+
*/
|
|
32
|
+
originalNamespace: string;
|
|
33
|
+
time: Time;
|
|
34
|
+
|
|
35
|
+
meta: PersistenceMetadata;
|
|
36
|
+
queries: PersistenceQueries;
|
|
37
|
+
files: PersistenceFiles;
|
|
38
|
+
|
|
39
|
+
undoHistory: UndoHistory;
|
|
40
|
+
schema: StorageSchema;
|
|
41
|
+
oldSchemas: StorageSchema[];
|
|
42
|
+
log: (
|
|
43
|
+
level: 'debug' | 'info' | 'warn' | 'error' | 'critical',
|
|
44
|
+
...args: any[]
|
|
45
|
+
) => void;
|
|
46
|
+
entityEvents: EventSubscriber<{
|
|
47
|
+
collectionsChanged: (names: string[]) => void;
|
|
48
|
+
documentChanged: (oid: ObjectIdentifier) => void;
|
|
49
|
+
}>;
|
|
50
|
+
internalEvents: EventSubscriber<{
|
|
51
|
+
/**
|
|
52
|
+
* Fired when persisted data changes fundamentally, like resetting to 0,
|
|
53
|
+
* or importing different data.
|
|
54
|
+
*/
|
|
55
|
+
persistenceReset: () => void;
|
|
56
|
+
filesDeleted: (files: FileRef[]) => void;
|
|
57
|
+
fileAdded: (file: FileData) => void;
|
|
58
|
+
[ev: `fileUploaded:${string}`]: () => void;
|
|
59
|
+
}>;
|
|
60
|
+
globalEvents: EventSubscriber<{
|
|
61
|
+
/**
|
|
62
|
+
* A change from a future version of the application has been
|
|
63
|
+
* witnessed. These changes are not applied but it indicates
|
|
64
|
+
* the app has been updated and we should prompt the user
|
|
65
|
+
* to reload or have their app user manually reload.
|
|
66
|
+
*
|
|
67
|
+
* The parameter is the timestamp of the future change.
|
|
68
|
+
*/
|
|
69
|
+
futureSeen: (timestamp: string) => void;
|
|
70
|
+
/**
|
|
71
|
+
* The server requested this replica reset its state
|
|
72
|
+
* completely. This can happen when the replica has
|
|
73
|
+
* been offline for too long and reconnects.
|
|
74
|
+
*/
|
|
75
|
+
resetToServer: () => void;
|
|
76
|
+
/**
|
|
77
|
+
* An operation has been processed by the system. This could be a locally sourced
|
|
78
|
+
* operation or a remote operation from sync.
|
|
79
|
+
*/
|
|
80
|
+
operation: (operation: Operation) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Emitted when storage rebases history. This should never actually affect application behavior
|
|
83
|
+
* or stored data, but is useful for debugging and testing.
|
|
84
|
+
*/
|
|
85
|
+
rebase: () => void;
|
|
86
|
+
}>;
|
|
87
|
+
weakRef<T extends object>(value: T): WeakRef<T>;
|
|
88
|
+
migrations: Migration<any>[];
|
|
89
|
+
closing: boolean;
|
|
90
|
+
patchCreator: PatchCreator;
|
|
91
|
+
|
|
92
|
+
config: {
|
|
93
|
+
files?: FileConfig;
|
|
94
|
+
sync?: SyncConfig;
|
|
95
|
+
persistence?: PersistenceConfig;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
persistence: PersistenceImplementation;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface FileConfig {
|
|
102
|
+
/**
|
|
103
|
+
* Override the heuristic for deciding when a deleted file can be cleaned up.
|
|
104
|
+
* By default this waits 3 days since deletion, then deletes the file data.
|
|
105
|
+
* If the file has been synchronized to a server, it could still be restored
|
|
106
|
+
* if the server has not yet deleted it.
|
|
107
|
+
*/
|
|
108
|
+
canCleanupDeletedFile?: (file: PersistedFileData) => boolean;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface ServerSyncEndpointProviderConfig {
|
|
112
|
+
/**
|
|
113
|
+
* The location of the endpoint used to retrieve an
|
|
114
|
+
* authorization token for the client.
|
|
115
|
+
*/
|
|
116
|
+
authEndpoint?: string;
|
|
117
|
+
/**
|
|
118
|
+
* A custom function to retrieve authorization
|
|
119
|
+
* data. Use whatever fetching mechanism you want.
|
|
120
|
+
*/
|
|
121
|
+
fetchAuth?: () => Promise<{
|
|
122
|
+
accessToken: string;
|
|
123
|
+
}>;
|
|
124
|
+
/**
|
|
125
|
+
* A spec-compliant fetch implementation. If not provided,
|
|
126
|
+
* the global fetch will be used. authEndpoint will
|
|
127
|
+
* be used to fetch the token.
|
|
128
|
+
*/
|
|
129
|
+
fetch?: typeof fetch;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type SyncTransportMode = 'realtime' | 'pull';
|
|
133
|
+
|
|
134
|
+
export interface SyncConfig<Profile = any, Presence = any>
|
|
135
|
+
extends ServerSyncEndpointProviderConfig {
|
|
136
|
+
/**
|
|
137
|
+
* When a client first connects, it will use this presence value.
|
|
138
|
+
*/
|
|
139
|
+
initialPresence: Presence;
|
|
140
|
+
/**
|
|
141
|
+
* Before connecting to the server, the local client will have
|
|
142
|
+
* this value for their profile data. You can either cache and store
|
|
143
|
+
* profile data from a previous connection or provide defaults like
|
|
144
|
+
* empty strings.
|
|
145
|
+
*/
|
|
146
|
+
defaultProfile: Profile;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Provide `false` to disable transport selection. Transport selection
|
|
150
|
+
* automatically switches between HTTP and WebSocket based sync depending
|
|
151
|
+
* on the number of peers connected. If a user is alone, they will use
|
|
152
|
+
* HTTP push/pull to sync changes. If another user joins, both users will
|
|
153
|
+
* be upgraded to websockets.
|
|
154
|
+
*
|
|
155
|
+
* Provide `peers-only` to only automatically use websockets if other
|
|
156
|
+
* users connect, but not if another device for the current user connects.
|
|
157
|
+
* By default, automatic transport selection will upgrade to websockets if
|
|
158
|
+
* another device from the current user connects, but if realtime sync is
|
|
159
|
+
* not necessary for such cases, you can save bandwidth by disabling this.
|
|
160
|
+
*
|
|
161
|
+
* Turning off this feature allows you more control over the transport
|
|
162
|
+
* which can be useful for low-power devices or to save server traffic.
|
|
163
|
+
* To modify transport modes manually, utilize `client.sync.setMode`.
|
|
164
|
+
* The built-in behavior is essentially switching modes based on
|
|
165
|
+
* the number of peers detected by client.sync.presence.
|
|
166
|
+
*/
|
|
167
|
+
automaticTransportSelection?: boolean | 'peers-only';
|
|
168
|
+
initialTransport?: SyncTransportMode;
|
|
169
|
+
autoStart?: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Optionally specify an interval, in milliseconds, to poll the server
|
|
172
|
+
* when in pull mode.
|
|
173
|
+
*/
|
|
174
|
+
pullInterval?: number;
|
|
175
|
+
/**
|
|
176
|
+
* Presence updates are batched to reduce number of requests / messages
|
|
177
|
+
* sent to the server. You can specify the batching time slice, in milliseconds,
|
|
178
|
+
*/
|
|
179
|
+
presenceUpdateBatchTimeout?: number;
|
|
180
|
+
/**
|
|
181
|
+
* Experimental: sync messages over a broadcast channel between tabs.
|
|
182
|
+
* Fixes tabs not reactively updating to changes when other tabs are open,
|
|
183
|
+
* but is not yet thoroughly vetted.
|
|
184
|
+
*/
|
|
185
|
+
useBroadcastChannel?: boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Listen for outgoing messages from the client to the server.
|
|
188
|
+
* Not sure why you want to do this, but be careful.
|
|
189
|
+
*/
|
|
190
|
+
onOutgoingMessage?: (message: ClientMessage) => void;
|
|
191
|
+
|
|
192
|
+
EXPERIMENTAL_backgroundSync?: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface PersistenceConfig {
|
|
196
|
+
disableRebasing?: boolean;
|
|
197
|
+
rebaseTimeout?: number;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export type InitialContext = Omit<Context, 'queries' | 'meta' | 'files'>;
|
|
@@ -11,9 +11,6 @@ import {
|
|
|
11
11
|
AuthorizationKey,
|
|
12
12
|
} from '@verdant-web/common';
|
|
13
13
|
import { EntityCreateOptions, EntityStore } from '../entities/EntityStore.js';
|
|
14
|
-
import { Metadata } from '../metadata/Metadata.js';
|
|
15
|
-
import { Sync } from '../sync/Sync.js';
|
|
16
|
-
import { Context } from '../context.js';
|
|
17
14
|
import { ObjectEntity } from '../index.js';
|
|
18
15
|
|
|
19
16
|
/**
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import { Entity } from './Entity.js';
|
|
3
3
|
import { EntityFamilyMetadata } from './EntityMetadata.js';
|
|
4
|
-
import { Context } from '../context.js';
|
|
4
|
+
import { Context } from '../context/context.js';
|
|
5
5
|
import { EntityStoreEvents } from './EntityStore.js';
|
|
6
6
|
import { WeakEvent } from 'weak-event';
|
|
7
7
|
import { FileManager } from '../files/FileManager.js';
|
|
8
8
|
import {
|
|
9
9
|
NaiveTimestampProvider,
|
|
10
10
|
PatchCreator,
|
|
11
|
-
createRef,
|
|
12
11
|
groupPatchesByOid,
|
|
13
12
|
} from '@verdant-web/common';
|
|
13
|
+
import { Time } from '../context/Time.js';
|
|
14
14
|
|
|
15
15
|
describe('Entity', () => {
|
|
16
16
|
const schema = {
|
|
@@ -60,18 +60,19 @@ describe('Entity', () => {
|
|
|
60
60
|
resetAll: new WeakEvent(),
|
|
61
61
|
};
|
|
62
62
|
const time = new NaiveTimestampProvider();
|
|
63
|
-
const mockContext = {
|
|
64
|
-
log: vi.fn(),
|
|
65
|
-
getNow: () => time.now(1),
|
|
66
|
-
} as any as Context;
|
|
67
63
|
const patchCreator = new PatchCreator(() => time.now(1));
|
|
64
|
+
const mockContext: Partial<Context> = {
|
|
65
|
+
log: vi.fn(),
|
|
66
|
+
time: new Time(time, 1),
|
|
67
|
+
patchCreator,
|
|
68
|
+
};
|
|
68
69
|
const entity = new Entity({
|
|
69
70
|
oid: 'test/1',
|
|
70
71
|
schema,
|
|
71
|
-
ctx: mockContext,
|
|
72
|
+
ctx: mockContext as Context,
|
|
72
73
|
storeEvents: events,
|
|
73
74
|
metadataFamily: new EntityFamilyMetadata({
|
|
74
|
-
ctx: mockContext,
|
|
75
|
+
ctx: mockContext as Context,
|
|
75
76
|
onPendingOperations,
|
|
76
77
|
rootOid: 'test/1',
|
|
77
78
|
}),
|
|
@@ -79,7 +80,6 @@ describe('Entity', () => {
|
|
|
79
80
|
add: vi.fn(),
|
|
80
81
|
get: vi.fn(),
|
|
81
82
|
} as any as FileManager,
|
|
82
|
-
patchCreator,
|
|
83
83
|
readonlyKeys: ['id'],
|
|
84
84
|
deleteSelf: vi.fn(),
|
|
85
85
|
});
|
package/src/entities/Entity.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DocumentBaseline,
|
|
3
2
|
EntityValidationProblem,
|
|
4
3
|
EventSubscriber,
|
|
5
4
|
ObjectIdentifier,
|
|
6
5
|
Operation,
|
|
7
|
-
PatchCreator,
|
|
8
6
|
StorageFieldSchema,
|
|
9
|
-
StorageFieldsSchema,
|
|
10
7
|
assert,
|
|
11
8
|
assignOid,
|
|
12
9
|
cloneDeep,
|
|
@@ -20,15 +17,13 @@ import {
|
|
|
20
17
|
isFile,
|
|
21
18
|
isNullable,
|
|
22
19
|
isObject,
|
|
23
|
-
isObjectRef,
|
|
24
|
-
isPrunePoint,
|
|
25
20
|
isRef,
|
|
26
21
|
maybeGetOid,
|
|
27
22
|
memoByKeys,
|
|
28
23
|
traverseCollectionFieldsAndApplyDefaults,
|
|
29
24
|
validateEntityField,
|
|
30
25
|
} from '@verdant-web/common';
|
|
31
|
-
import { Context } from '../context.js';
|
|
26
|
+
import { Context } from '../context/context.js';
|
|
32
27
|
import { FileManager } from '../files/FileManager.js';
|
|
33
28
|
import { processValueFiles } from '../files/utils.js';
|
|
34
29
|
import { EntityFile } from '../index.js';
|
|
@@ -37,7 +32,6 @@ import { EntityFamilyMetadata, EntityMetadataView } from './EntityMetadata.js';
|
|
|
37
32
|
import {
|
|
38
33
|
BaseEntityValue,
|
|
39
34
|
DataFromInit,
|
|
40
|
-
DeepPartial,
|
|
41
35
|
EntityChange,
|
|
42
36
|
EntityEvents,
|
|
43
37
|
ListEntity,
|
|
@@ -58,7 +52,6 @@ export interface EntityInit {
|
|
|
58
52
|
files: FileManager;
|
|
59
53
|
readonlyKeys?: string[];
|
|
60
54
|
fieldPath?: (string | number)[];
|
|
61
|
-
patchCreator: PatchCreator;
|
|
62
55
|
storeEvents: EntityStoreEvents;
|
|
63
56
|
deleteSelf: () => void;
|
|
64
57
|
}
|
|
@@ -84,7 +77,6 @@ export class Entity<
|
|
|
84
77
|
private parent: Entity | undefined;
|
|
85
78
|
private ctx;
|
|
86
79
|
private files;
|
|
87
|
-
private patchCreator;
|
|
88
80
|
private storeEvents;
|
|
89
81
|
|
|
90
82
|
// an internal representation of this Entity.
|
|
@@ -110,7 +102,6 @@ export class Entity<
|
|
|
110
102
|
metadataFamily,
|
|
111
103
|
readonlyKeys,
|
|
112
104
|
files,
|
|
113
|
-
patchCreator,
|
|
114
105
|
storeEvents,
|
|
115
106
|
deleteSelf,
|
|
116
107
|
}: EntityInit) {
|
|
@@ -128,7 +119,6 @@ export class Entity<
|
|
|
128
119
|
new EntityCache({
|
|
129
120
|
initial: [this],
|
|
130
121
|
});
|
|
131
|
-
this.patchCreator = patchCreator;
|
|
132
122
|
this.metadataFamily = metadataFamily;
|
|
133
123
|
this.storeEvents = storeEvents;
|
|
134
124
|
this.parent = parent;
|
|
@@ -160,6 +150,10 @@ export class Entity<
|
|
|
160
150
|
return this.metadataFamily.get(this.oid);
|
|
161
151
|
}
|
|
162
152
|
|
|
153
|
+
private get patchCreator() {
|
|
154
|
+
return this.ctx.patchCreator;
|
|
155
|
+
}
|
|
156
|
+
|
|
163
157
|
/**
|
|
164
158
|
* The view of this Entity, not including nested
|
|
165
159
|
* entities (that's the snapshot - see #getSnapshot())
|
|
@@ -585,7 +579,6 @@ export class Entity<
|
|
|
585
579
|
ctx: this.ctx,
|
|
586
580
|
files: this.files,
|
|
587
581
|
fieldPath: [...this.fieldPath, key],
|
|
588
|
-
patchCreator: this.patchCreator,
|
|
589
582
|
storeEvents: this.storeEvents,
|
|
590
583
|
deleteSelf: this.delete.bind(this, key),
|
|
591
584
|
});
|
|
@@ -635,6 +628,7 @@ export class Entity<
|
|
|
635
628
|
}
|
|
636
629
|
const file = this.files.get(child.id, {
|
|
637
630
|
downloadRemote: !!fieldSchema.downloadRemote,
|
|
631
|
+
ctx: this.ctx,
|
|
638
632
|
});
|
|
639
633
|
|
|
640
634
|
// FIXME: this seems bad and inconsistent
|
|
@@ -26,15 +26,6 @@ export class EntityCache {
|
|
|
26
26
|
return this.cache.has(oid);
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
getFile = (id: string, options: { downloadRemote: boolean }): EntityFile => {
|
|
30
|
-
if (this.cache.has(id)) {
|
|
31
|
-
return this.cache.get(id)! as EntityFile;
|
|
32
|
-
}
|
|
33
|
-
const file = new EntityFile(id, options);
|
|
34
|
-
this.cache.set(id, file);
|
|
35
|
-
return file;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
29
|
getCached = (oid: string) => {
|
|
39
30
|
return this.cache.get(oid);
|
|
40
31
|
};
|