@verdant-web/store 4.1.2 → 4.1.4

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 (54) hide show
  1. package/dist/bundle/index.js +5 -5
  2. package/dist/bundle/index.js.map +4 -4
  3. package/dist/esm/__tests__/fixtures/testStorage.js +5 -0
  4. package/dist/esm/__tests__/fixtures/testStorage.js.map +1 -1
  5. package/dist/esm/__tests__/queries.test.js +51 -2
  6. package/dist/esm/__tests__/queries.test.js.map +1 -1
  7. package/dist/esm/__tests__/schema.test.d.ts +1 -0
  8. package/dist/esm/__tests__/schema.test.js +64 -0
  9. package/dist/esm/__tests__/schema.test.js.map +1 -0
  10. package/dist/esm/client/Client.d.ts +3 -1
  11. package/dist/esm/client/Client.js +8 -1
  12. package/dist/esm/client/Client.js.map +1 -1
  13. package/dist/esm/client/ClientDescriptor.d.ts +6 -2
  14. package/dist/esm/client/ClientDescriptor.js +7 -6
  15. package/dist/esm/client/ClientDescriptor.js.map +1 -1
  16. package/dist/esm/context/context.d.ts +17 -3
  17. package/dist/esm/entities/Entity.d.ts +2 -2
  18. package/dist/esm/entities/Entity.js +5 -1
  19. package/dist/esm/entities/Entity.js.map +1 -1
  20. package/dist/esm/entities/types.d.ts +41 -0
  21. package/dist/esm/files/FileManager.d.ts +3 -1
  22. package/dist/esm/files/FileManager.js +9 -2
  23. package/dist/esm/files/FileManager.js.map +1 -1
  24. package/dist/esm/persistence/PersistenceFiles.js +3 -2
  25. package/dist/esm/persistence/PersistenceFiles.js.map +1 -1
  26. package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.d.ts +2 -2
  27. package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.js +12 -4
  28. package/dist/esm/persistence/idb/files/IdbPersistenceFileDb.js.map +1 -1
  29. package/dist/esm/persistence/persistence.js +3 -3
  30. package/dist/esm/persistence/persistence.js.map +1 -1
  31. package/dist/esm/queries/BaseQuery.js +2 -1
  32. package/dist/esm/queries/BaseQuery.js.map +1 -1
  33. package/dist/esm/queries/QueryCache.d.ts +8 -1
  34. package/dist/esm/queries/QueryCache.js +33 -2
  35. package/dist/esm/queries/QueryCache.js.map +1 -1
  36. package/dist/esm/sync/FileSync.d.ts +1 -1
  37. package/dist/esm/sync/FileSync.js +2 -1
  38. package/dist/esm/sync/FileSync.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/__tests__/fixtures/testStorage.ts +7 -1
  41. package/src/__tests__/queries.test.ts +70 -3
  42. package/src/__tests__/schema.test.ts +85 -0
  43. package/src/client/Client.ts +13 -7
  44. package/src/client/ClientDescriptor.ts +14 -8
  45. package/src/context/context.ts +18 -3
  46. package/src/entities/Entity.ts +8 -4
  47. package/src/entities/types.ts +57 -24
  48. package/src/files/FileManager.ts +15 -2
  49. package/src/persistence/PersistenceFiles.ts +11 -6
  50. package/src/persistence/idb/files/IdbPersistenceFileDb.ts +22 -9
  51. package/src/persistence/persistence.ts +4 -2
  52. package/src/queries/BaseQuery.ts +3 -1
  53. package/src/queries/QueryCache.ts +56 -2
  54. package/src/sync/FileSync.ts +3 -2
@@ -8,7 +8,6 @@ export class FileSync extends Disposable {
8
8
  this.ctx.log('debug', 'Uploading file', data.id, data.name);
9
9
  try {
10
10
  await this.uploadFile(data);
11
- this.ctx.internalEvents.emit(`fileUploaded:${data.id}`, data);
12
11
  }
13
12
  catch (e) {
14
13
  this.ctx.log('error', 'File upload failed', e);
@@ -37,6 +36,8 @@ export class FileSync extends Disposable {
37
36
  },
38
37
  });
39
38
  if (response.ok) {
39
+ this.ctx.internalEvents.emit(`fileUploaded:${data.id}`, data);
40
+ this.ctx.internalEvents.emit('fileUploaded', data);
40
41
  this.ctx.log('info', 'File upload successful');
41
42
  return {
42
43
  success: true,
@@ -1 +1 @@
1
- {"version":3,"file":"FileSync.js","sourceRoot":"","sources":["../../../src/sync/FileSync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileSync.js","sourceRoot":"","sources":["../../../src/sync/FileSync.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdant-web/store",
3
- "version": "4.1.2",
3
+ "version": "4.1.4",
4
4
  "access": "public",
5
5
  "type": "module",
6
6
  "main": "dist/esm/index.js",
@@ -34,7 +34,7 @@
34
34
  "jszip": "^3.10.1",
35
35
  "jwt-decode": "^3.1.2",
36
36
  "weak-event": "^2.0.5",
37
- "@verdant-web/common": "2.7.0"
37
+ "@verdant-web/common": "2.7.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "20.10.5",
@@ -2,11 +2,17 @@ import { createMigration, schema } from '@verdant-web/common';
2
2
  // @ts-ignore
3
3
  import { IDBFactory } from 'fake-indexeddb';
4
4
  import {
5
- ClientWithCollections,
6
5
  ClientDescriptor,
6
+ ClientWithCollections,
7
7
  IdbPersistence,
8
8
  } from '../../index.js';
9
9
 
10
+ const test = schema.fields.object({
11
+ fields: {
12
+ foo: schema.fields.string(),
13
+ },
14
+ });
15
+
10
16
  export const todoCollection = schema.collection({
11
17
  name: 'todo',
12
18
  primaryKey: 'id',
@@ -1,7 +1,7 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createTestStorage } from './fixtures/testStorage.js';
3
- import type { ClientWithCollections } from '../index.js';
4
1
  import { assert } from '@verdant-web/common';
2
+ import { afterEach, describe, expect, it, vi } from 'vitest';
3
+ import type { ClientWithCollections } from '../index.js';
4
+ import { createTestStorage } from './fixtures/testStorage.js';
5
5
 
6
6
  async function addTestingItems(storage: ClientWithCollections) {
7
7
  let items = [];
@@ -55,6 +55,10 @@ async function addTestingItems(storage: ClientWithCollections) {
55
55
  return items;
56
56
  }
57
57
 
58
+ afterEach(() => {
59
+ vi.useRealTimers();
60
+ });
61
+
58
62
  describe('storage queries', () => {
59
63
  it('can query synthetic indexes', async () => {
60
64
  const storage = await createTestStorage();
@@ -255,6 +259,69 @@ describe('storage queries', () => {
255
259
  items[5].get('id'),
256
260
  ]);
257
261
  });
262
+
263
+ it('disposes of unsubscribed queries after a period', async () => {
264
+ const storage = await createTestStorage();
265
+ const items = await addTestingItems(storage);
266
+
267
+ vi.useFakeTimers();
268
+
269
+ const query = storage.todos.findAll({
270
+ index: {
271
+ where: 'categorySortedByDone',
272
+ match: {
273
+ category: 'general',
274
+ },
275
+ order: 'asc',
276
+ },
277
+ });
278
+
279
+ expect(storage.queries.activeKeys).toContain(query.key);
280
+
281
+ // since the query is not subscribed, it should be disposed after a period (defaults 5s)
282
+ vi.advanceTimersByTime(5001);
283
+
284
+ expect(storage.queries.activeKeys).not.toContain(query.key);
285
+
286
+ vi.useRealTimers();
287
+ });
288
+
289
+ it('keeps unsubscribed queries alive when told to', async () => {
290
+ const storage = await createTestStorage();
291
+ const items = await addTestingItems(storage);
292
+
293
+ vi.useFakeTimers();
294
+
295
+ const query = storage.todos.findAll({
296
+ index: {
297
+ where: 'categorySortedByDone',
298
+ match: {
299
+ category: 'general',
300
+ },
301
+ order: 'asc',
302
+ },
303
+ });
304
+
305
+ expect(storage.queries.activeKeys).toContain(query.key);
306
+ storage.queries.keepAlive(query.key);
307
+
308
+ // since the query is not subscribed, it should be disposed after a period (defaults 5s)
309
+ // overshoot that to be sure
310
+ vi.advanceTimersByTime(10 * 1000);
311
+
312
+ expect(storage.queries.activeKeys).toContain(query.key);
313
+
314
+ // remove hold
315
+ storage.queries.dropKeepAlive(query.key);
316
+
317
+ // doesn't get disposed immediately
318
+ expect(storage.queries.activeKeys).toContain(query.key);
319
+
320
+ // should be disposed after the normal period
321
+ vi.advanceTimersByTime(5001);
322
+
323
+ expect(storage.queries.activeKeys).not.toContain(query.key);
324
+ });
258
325
  });
259
326
 
260
327
  describe('query reactivity', () => {
@@ -0,0 +1,85 @@
1
+ import {
2
+ createMigration,
3
+ schema,
4
+ StorageMapFieldSchema,
5
+ StorageObjectFieldSchema,
6
+ StorageStringFieldSchema,
7
+ } from '@verdant-web/common';
8
+ import { describe, expect, it } from 'vitest';
9
+ import { ClientDescriptor } from '../client/ClientDescriptor.js';
10
+ import { ClientWithCollections } from '../index.js';
11
+ import { IdbPersistence } from '../persistence/idb/idbPersistence.js';
12
+
13
+ describe('schema', () => {
14
+ it('supports recursive nested fields without breaking', async () => {
15
+ type NestedField = StorageObjectFieldSchema<{
16
+ foo: StorageStringFieldSchema;
17
+ bar: StorageMapFieldSchema<NestedField>;
18
+ }>;
19
+ const baseField = schema.fields.object({
20
+ fields: {
21
+ foo: schema.fields.string(),
22
+ },
23
+ });
24
+ const nestedField: NestedField = schema.fields.replaceObjectFields(
25
+ baseField,
26
+ {
27
+ foo: schema.fields.string(),
28
+ bar: schema.fields.map({
29
+ values: baseField,
30
+ }),
31
+ },
32
+ );
33
+
34
+ const tests = schema.collection({
35
+ name: 'tests',
36
+ primaryKey: 'id',
37
+ fields: {
38
+ id: schema.fields.string(),
39
+ nested: nestedField,
40
+ },
41
+ indexes: {
42
+ testLevel3: {
43
+ type: 'string',
44
+ compute: (doc) => doc.nested.bar?.baz?.bar?.baz?.foo ?? '',
45
+ },
46
+ },
47
+ });
48
+
49
+ const testSchema = schema({
50
+ version: 1,
51
+ collections: {
52
+ tests,
53
+ },
54
+ });
55
+
56
+ const storage: ClientWithCollections = (await new ClientDescriptor({
57
+ schema: testSchema,
58
+ migrations: [createMigration<{}>(testSchema)],
59
+ namespace: 'schematest',
60
+ oldSchemas: [testSchema],
61
+ persistence: new IdbPersistence(new IDBFactory()),
62
+ }).open()) as any;
63
+
64
+ const doc = await storage.tests.put({
65
+ id: 'test',
66
+ nested: {
67
+ foo: 'foo',
68
+ bar: {
69
+ baz: {
70
+ foo: 'bar',
71
+ bar: {
72
+ baz: {
73
+ foo: 'bar',
74
+ },
75
+ },
76
+ },
77
+ },
78
+ },
79
+ });
80
+
81
+ expect(
82
+ doc.get('nested').get('bar').get('baz').get('bar').get('baz').get('foo'),
83
+ ).toBe('bar');
84
+ });
85
+ });
@@ -10,12 +10,12 @@ import { DocumentManager } from '../entities/DocumentManager.js';
10
10
  import { EntityStore } from '../entities/EntityStore.js';
11
11
  import { FileManager } from '../files/FileManager.js';
12
12
  import { deleteAllDatabases } from '../persistence/idb/util.js';
13
+ import { ExportedData } from '../persistence/interfaces.js';
14
+ import { importPersistence } from '../persistence/persistence.js';
13
15
  import { CollectionQueries } from '../queries/CollectionQueries.js';
14
- import { QueryCache } from '../queries/QueryCache.js';
16
+ import { PublicQueryCacheAPI, QueryCache } from '../queries/QueryCache.js';
15
17
  import { NoSync, ServerSync, Sync } from '../sync/Sync.js';
16
18
  import { getLatestVersion } from '../utils/versions.js';
17
- import { ExportedData } from '../persistence/interfaces.js';
18
- import { importPersistence } from '../persistence/persistence.js';
19
19
 
20
20
  // not actually used below, but helpful for internal code which
21
21
  // might rely on this stuff...
@@ -91,7 +91,7 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
91
91
  ? new ServerSync<Presence, Profile>(this.context.config.sync, {
92
92
  onData: this.addData,
93
93
  ctx: this.context,
94
- })
94
+ })
95
95
  : new NoSync<Presence, Profile>(this.context);
96
96
  if (context.schema.wip && this.context.config.sync) {
97
97
  context.log(
@@ -114,6 +114,7 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
114
114
  // FIXME: make this less fragile
115
115
  this._queryCache = new QueryCache({
116
116
  context,
117
+ evictionTime: context.config.queries?.evictionTime,
117
118
  });
118
119
  this._documentManager = new DocumentManager(this.schema, this._entities);
119
120
 
@@ -226,6 +227,10 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
226
227
  return this.context.undoHistory;
227
228
  }
228
229
 
230
+ get queries(): PublicQueryCacheAPI {
231
+ return this._queryCache;
232
+ }
233
+
229
234
  /**
230
235
  * Batch multiple operations together to be executed in a single transaction.
231
236
  * The changes made will not be included in the same undo history step as
@@ -294,6 +299,8 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
294
299
  await this._entities.destroy();
295
300
 
296
301
  this.context.persistenceShutdownHandler.shutdown();
302
+ this.context.internalEvents.disable();
303
+ this.context.entityEvents.disable();
297
304
 
298
305
  // the idea here is to flush the microtask queue -
299
306
  // we may have queued tasks related to queries that
@@ -318,9 +325,8 @@ export class Client<Presence = any, Profile = any> extends EventSubscriber<{
318
325
  ): Promise<ExportedData> => {
319
326
  this.context.log('info', 'Exporting data...');
320
327
  const metaExport = await this.context.meta.export();
321
- const { fileData, files } = await this.context.files.export(
322
- downloadRemoteFiles,
323
- );
328
+ const { fileData, files } =
329
+ await this.context.files.export(downloadRemoteFiles);
324
330
  return {
325
331
  data: metaExport,
326
332
  fileData,
@@ -6,17 +6,17 @@ import {
6
6
  StorageSchema,
7
7
  noop,
8
8
  } from '@verdant-web/common';
9
- import { FileConfig, InitialContext } from '../context/context.js';
9
+ import { FileConfig, InitialContext, QueryConfig } from '../context/context.js';
10
+ import { ShutdownHandler } from '../context/ShutdownHandler.js';
11
+ import { Time } from '../context/Time.js';
12
+ import { FakeWeakRef } from '../FakeWeakRef.js';
13
+ import { IdbPersistence } from '../persistence/idb/idbPersistence.js';
14
+ import { deleteAllDatabases } from '../persistence/idb/util.js';
15
+ import { PersistenceImplementation } from '../persistence/interfaces.js';
16
+ import { initializePersistence } from '../persistence/persistence.js';
10
17
  import { ServerSyncOptions } from '../sync/Sync.js';
11
18
  import { UndoHistory } from '../UndoHistory.js';
12
19
  import { Client } from './Client.js';
13
- import { deleteAllDatabases } from '../persistence/idb/util.js';
14
- import { FakeWeakRef } from '../FakeWeakRef.js';
15
- import { Time } from '../context/Time.js';
16
- import { initializePersistence } from '../persistence/persistence.js';
17
- import { PersistenceImplementation } from '../persistence/interfaces.js';
18
- import { IdbPersistence } from '../persistence/idb/idbPersistence.js';
19
- import { ShutdownHandler } from '../context/ShutdownHandler.js';
20
20
 
21
21
  export interface ClientDescriptorOptions<Presence = any, Profile = any> {
22
22
  /** The schema used to create this client */
@@ -76,6 +76,11 @@ export interface ClientDescriptorOptions<Presence = any, Profile = any> {
76
76
  * before turning it on.
77
77
  */
78
78
  EXPERIMENTAL_weakRefs?: boolean;
79
+
80
+ /**
81
+ * Customize querying behavior.
82
+ */
83
+ queries?: QueryConfig;
79
84
  }
80
85
 
81
86
  /**
@@ -155,6 +160,7 @@ export class ClientDescriptor<
155
160
  disableRebasing: init.disableRebasing,
156
161
  rebaseTimeout: init.rebaseTimeout,
157
162
  },
163
+ queries: init.queries,
158
164
  },
159
165
  persistence:
160
166
  init.persistence || new IdbPersistence(environment.indexedDB),
@@ -10,15 +10,15 @@ import {
10
10
  StorageSchema,
11
11
  } from '@verdant-web/common';
12
12
  import { UndoHistory } from '../UndoHistory.js';
13
- import { Time } from './Time.js';
14
- import type { PersistenceDocuments } from '../persistence/PersistenceQueries.js';
15
- import type { PersistenceMetadata } from '../persistence/PersistenceMetadata.js';
16
13
  import { PersistenceFiles } from '../persistence/PersistenceFiles.js';
14
+ import type { PersistenceMetadata } from '../persistence/PersistenceMetadata.js';
15
+ import type { PersistenceDocuments } from '../persistence/PersistenceQueries.js';
17
16
  import {
18
17
  PersistedFileData,
19
18
  PersistenceImplementation,
20
19
  } from '../persistence/interfaces.js';
21
20
  import { ShutdownHandler } from './ShutdownHandler.js';
21
+ import { Time } from './Time.js';
22
22
 
23
23
  /**
24
24
  * Common components utilized across various client
@@ -57,6 +57,7 @@ export interface Context {
57
57
  filesDeleted: (files: FileRef[]) => void;
58
58
  fileAdded: (file: FileData) => void;
59
59
  [ev: `fileUploaded:${string}`]: (file: FileData) => void;
60
+ fileUploaded: (file: FileData) => void;
60
61
  }>;
61
62
  globalEvents: EventSubscriber<{
62
63
  /**
@@ -99,6 +100,7 @@ export interface Context {
99
100
  files?: FileConfig;
100
101
  sync?: SyncConfig;
101
102
  persistence?: PersistenceConfig;
103
+ queries?: QueryConfig;
102
104
  };
103
105
 
104
106
  environment: {
@@ -209,4 +211,17 @@ export interface PersistenceConfig {
209
211
  rebaseTimeout?: number;
210
212
  }
211
213
 
214
+ export interface QueryConfig {
215
+ /**
216
+ * Milliseconds to hold a query in memory after it is unsubscribed before
217
+ * disposing of it. Once a query is disposed, it must be loaded fresh again
218
+ * on next use. Queries are cached based on their `key`, which you can
219
+ * manually override. By default keys are determined by the parameters
220
+ * passed to the query.
221
+ *
222
+ * Defaults to 5 seconds.
223
+ */
224
+ evictionTime?: number;
225
+ }
226
+
212
227
  export type InitialContext = Omit<Context, 'documents' | 'meta' | 'files'>;
@@ -13,8 +13,8 @@ import {
13
13
  getChildFieldSchema,
14
14
  getDefault,
15
15
  hasDefault,
16
- isFileRef,
17
16
  isFile,
17
+ isFileRef,
18
18
  isNullable,
19
19
  isObject,
20
20
  isRef,
@@ -29,6 +29,8 @@ import { processValueFiles } from '../files/utils.js';
29
29
  import { EntityFile } from '../index.js';
30
30
  import { EntityCache } from './EntityCache.js';
31
31
  import { EntityFamilyMetadata, EntityMetadataView } from './EntityMetadata.js';
32
+ import { EntityStoreEventData, EntityStoreEvents } from './EntityStore.js';
33
+ import { entityFieldSubscriber } from './entityFieldSubscriber.js';
32
34
  import {
33
35
  BaseEntityValue,
34
36
  DataFromInit,
@@ -39,8 +41,6 @@ import {
39
41
  ListItemValue,
40
42
  ObjectEntity,
41
43
  } from './types.js';
42
- import { EntityStoreEventData, EntityStoreEvents } from './EntityStore.js';
43
- import { entityFieldSubscriber } from './entityFieldSubscriber.js';
44
44
 
45
45
  export interface EntityInit {
46
46
  oid: ObjectIdentifier;
@@ -73,7 +73,7 @@ export class Entity<
73
73
  private entityFamily: EntityCache;
74
74
  private metadataFamily;
75
75
 
76
- private schema;
76
+ readonly schema;
77
77
  private parent: Entity | undefined;
78
78
  private ctx;
79
79
  private files;
@@ -657,6 +657,10 @@ export class Entity<
657
657
  })
658
658
  ) {
659
659
  if (hasDefault(fieldSchema)) {
660
+ // FIXME: this returns []/{} for arrays and objects, but the contract
661
+ // of this method should return an Entity for such object fields.
662
+ // I want to write a test case for this one before attempting to fix
663
+ // just to be sure the fix works.
660
664
  return getDefault(fieldSchema);
661
665
  }
662
666
  if (isNullable(fieldSchema)) {
@@ -1,19 +1,16 @@
1
1
  import { ObjectIdentifier, StorageFieldSchema } from '@verdant-web/common';
2
2
  import type { Entity } from './Entity.js';
3
3
 
4
- export type AccessibleEntityProperty<T> = T extends Array<any>
5
- ? number
6
- : T extends object
7
- ? keyof T
8
- : never;
4
+ export type AccessibleEntityProperty<T> =
5
+ T extends Array<any> ? number : T extends object ? keyof T : never;
9
6
 
10
7
  export type DataFromInit<Init> = Init extends { [key: string]: any }
11
8
  ? {
12
9
  [Key in keyof Init]: Init[Key];
13
- }
10
+ }
14
11
  : Init extends Array<any>
15
- ? Init
16
- : any;
12
+ ? Init
13
+ : any;
17
14
 
18
15
  // reduces keys of an object to only ones with an optional
19
16
  // value
@@ -23,15 +20,11 @@ export type DeletableKeys<T> = keyof {
23
20
  type IfNullableThen<T, Out> = undefined extends T
24
21
  ? Out
25
22
  : null extends T
26
- ? Out
27
- : never;
23
+ ? Out
24
+ : never;
28
25
 
29
- export type EntityShape<E extends Entity<any, any>> = E extends Entity<
30
- infer Value,
31
- any
32
- >
33
- ? Value
34
- : never;
26
+ export type EntityShape<E extends Entity<any, any>> =
27
+ E extends Entity<infer Value, any> ? Value : never;
35
28
 
36
29
  export type BaseEntityValue = { [Key: string]: any } | any[];
37
30
 
@@ -73,21 +66,62 @@ export interface BaseEntity<
73
66
  ) => void,
74
67
  ): () => void;
75
68
  get<Key extends keyof Value>(key: Key): Value[Key];
69
+ /**
70
+ * Returns a plain object or array containing sub-Entities and their data.
71
+ * Equivalent to "destructuring" the entity. Unlike getSnapshot, sub-level
72
+ * data is still reactive.
73
+ */
76
74
  getAll(): Readonly<Value>;
75
+ /**
76
+ * Returns a plain Javascript object representing the current state of the entity.
77
+ */
77
78
  getSnapshot(): Snapshot;
79
+ /**
80
+ * Returns the schema for the entity as specified in your Verdant schema.
81
+ * For root Documents, this will be an Object schema with properties
82
+ * representing each field in the document.
83
+ */
84
+ readonly schema: StorageFieldSchema;
85
+ /**
86
+ * Returns the schema for a field in the entity as specified in
87
+ * your Verdant schema.
88
+ */
78
89
  getFieldSchema<FieldName extends keyof Value>(
79
90
  key: FieldName,
80
91
  ): StorageFieldSchema;
92
+ /**
93
+ * Will be marked true after an entity has been deleted. Any attempt to
94
+ * access the entity's data will result in an error.
95
+ */
81
96
  readonly deleted: boolean;
97
+ /**
98
+ * A Unix Epoch timestamp representing the last time this entity was updated.
99
+ */
82
100
  readonly updatedAt: number;
101
+ /**
102
+ * A Unix Epoch timestamp representing the last time this entity or any of its
103
+ * sub-entities were updated.
104
+ *
105
+ * NOTE: reading this property requires a bit of computation, but the result
106
+ * is cached. If an entity is being frequently updated and this is frequently
107
+ * read, it may result in mild performance degradation.
108
+ */
109
+ readonly deepUpdatedAt: number;
110
+ /** A unique, opaque key for this Entity in the system. */
83
111
  readonly uid: string;
112
+ /** If true, this Entity has authorization rules applied to it. */
84
113
  readonly isAuthorized: boolean;
114
+ /** The authorization configuration string applied to this entity. */
115
+ readonly access: string | undefined;
116
+ readonly invalid: boolean;
117
+ /** The Verdant store namespace which contains this object */
118
+ readonly namespace: string;
85
119
  }
86
120
 
87
121
  export type DeepPartial<T> = T extends object
88
122
  ? {
89
123
  [P in keyof T]?: DeepPartial<T[P]>;
90
- }
124
+ }
91
125
  : T;
92
126
 
93
127
  export interface ObjectEntity<
@@ -200,22 +234,21 @@ export type AnyEntity<
200
234
  | ListEntity<Init, KeyValue, Snapshot>
201
235
  | ObjectEntity<Init, KeyValue, Snapshot>;
202
236
 
203
- export type ListItemValue<KeyValue> = KeyValue extends Array<infer T>
204
- ? T
205
- : never;
237
+ export type ListItemValue<KeyValue> =
238
+ KeyValue extends Array<infer T> ? T : never;
206
239
  export type ListItemInit<Init> = Init extends Array<infer T> ? T : never;
207
240
 
208
241
  export type EntityDestructured<T extends AnyEntity<any, any, any> | null> =
209
242
  | (T extends ListEntity<any, infer KeyValue, any>
210
243
  ? KeyValue
211
244
  : T extends ObjectEntity<any, infer KeyValue, any>
212
- ? KeyValue
213
- : never)
245
+ ? KeyValue
246
+ : never)
214
247
  | (T extends null ? null : never);
215
248
 
216
249
  export type EntityInit<T extends AnyEntity<any, any, any>> =
217
250
  T extends ListEntity<infer Init, any, any>
218
251
  ? Init
219
252
  : T extends ObjectEntity<infer Init, any, any>
220
- ? Init
221
- : never;
253
+ ? Init
254
+ : never;
@@ -1,17 +1,25 @@
1
1
  import { FileData } from '@verdant-web/common';
2
2
  import { Context } from '../context/context.js';
3
+ import { Disposable } from '../internal.js';
3
4
  import { Sync } from '../sync/Sync.js';
4
5
  import { EntityFile, MARK_FAILED, UPDATE } from './EntityFile.js';
5
6
 
6
- export class FileManager {
7
+ export class FileManager extends Disposable {
7
8
  private sync;
8
9
  private context;
9
10
 
10
11
  private cache = new Map<string, EntityFile>();
11
12
 
12
13
  constructor({ sync, context }: { sync: Sync; context: Context }) {
14
+ super();
13
15
  this.sync = sync;
14
16
  this.context = context;
17
+ this.addDispose(
18
+ this.context.internalEvents.subscribe(
19
+ 'fileUploaded',
20
+ this.onFileUploaded,
21
+ ),
22
+ );
15
23
  }
16
24
 
17
25
  add = async (file: FileData) => {
@@ -72,8 +80,8 @@ export class FileManager {
72
80
 
73
81
  const result = await this.sync.getFile(file.id);
74
82
  if (result.success) {
75
- file[UPDATE](result.data);
76
83
  await this.context.files.add(result.data);
84
+ file[UPDATE](result.data);
77
85
  } else {
78
86
  this.context.log('error', 'Failed to load file', result);
79
87
  file[MARK_FAILED]();
@@ -84,4 +92,9 @@ export class FileManager {
84
92
  }
85
93
  }
86
94
  };
95
+
96
+ private onFileUploaded = (data: FileData) => {
97
+ this.context.log('debug', 'Marking file as uploaded', data.id);
98
+ this.context.files.onUploaded(data.id);
99
+ };
87
100
  }