@dxos/echo-db 2.28.17-dev.1adfe6e6 → 2.28.17-dev.e18b5d13

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 (63) hide show
  1. package/dist/src/api/database.d.ts +4 -4
  2. package/dist/src/api/database.d.ts.map +1 -1
  3. package/dist/src/api/database.js +7 -6
  4. package/dist/src/api/database.js.map +1 -1
  5. package/dist/src/api/database.test.js +8 -8
  6. package/dist/src/api/database.test.js.map +1 -1
  7. package/dist/src/api/item.d.ts +7 -6
  8. package/dist/src/api/item.d.ts.map +1 -1
  9. package/dist/src/api/item.js +7 -6
  10. package/dist/src/api/item.js.map +1 -1
  11. package/dist/src/database/data-mirror.test.js +2 -2
  12. package/dist/src/database/data-mirror.test.js.map +1 -1
  13. package/dist/src/database/item-demuxer.test.js +1 -1
  14. package/dist/src/database/item-demuxer.test.js.map +1 -1
  15. package/dist/src/database/item-manager.js +1 -1
  16. package/dist/src/database/item-manager.js.map +1 -1
  17. package/dist/src/database/testing.js +2 -2
  18. package/dist/src/database/testing.js.map +1 -1
  19. package/dist/src/echo.test.js +6 -6
  20. package/dist/src/echo.test.js.map +1 -1
  21. package/dist/src/halo/party-preferences.d.ts.map +1 -1
  22. package/dist/src/halo/party-preferences.js +1 -0
  23. package/dist/src/halo/party-preferences.js.map +1 -1
  24. package/dist/src/halo/preferences.js +9 -9
  25. package/dist/src/halo/preferences.js.map +1 -1
  26. package/dist/src/metadata/metadata-store.test.js.map +1 -1
  27. package/dist/src/parties/party-core.js +1 -1
  28. package/dist/src/parties/party-core.js.map +1 -1
  29. package/dist/src/parties/party-core.test.js +2 -2
  30. package/dist/src/parties/party-core.test.js.map +1 -1
  31. package/dist/src/parties/party-internal.d.ts.map +1 -1
  32. package/dist/src/parties/party-internal.js +2 -2
  33. package/dist/src/parties/party-internal.js.map +1 -1
  34. package/dist/src/parties/party-manager.d.ts.map +1 -1
  35. package/dist/src/parties/party-manager.js +5 -6
  36. package/dist/src/parties/party-manager.js.map +1 -1
  37. package/dist/src/parties/party-manager.test.js +2 -2
  38. package/dist/src/parties/party-manager.test.js.map +1 -1
  39. package/dist/src/snapshots/snapshot.test.js +6 -7
  40. package/dist/src/snapshots/snapshot.test.js.map +1 -1
  41. package/dist/src/testing/testing-factories.d.ts.map +1 -1
  42. package/dist/src/testing/testing-factories.js +2 -1
  43. package/dist/src/testing/testing-factories.js.map +1 -1
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +24 -22
  46. package/src/api/database.test.ts +8 -8
  47. package/src/api/database.ts +10 -9
  48. package/src/api/item.ts +7 -6
  49. package/src/database/data-mirror.test.ts +2 -2
  50. package/src/database/item-demuxer.test.ts +1 -1
  51. package/src/database/item-manager.ts +1 -1
  52. package/src/database/testing.ts +2 -2
  53. package/src/echo.test.ts +6 -6
  54. package/src/halo/party-preferences.ts +1 -0
  55. package/src/halo/preferences.ts +8 -8
  56. package/src/metadata/metadata-store.test.ts +0 -3
  57. package/src/parties/party-core.test.ts +2 -2
  58. package/src/parties/party-core.ts +1 -1
  59. package/src/parties/party-internal.ts +3 -2
  60. package/src/parties/party-manager.test.ts +2 -2
  61. package/src/parties/party-manager.ts +4 -6
  62. package/src/snapshots/snapshot.test.ts +6 -7
  63. package/src/testing/testing-factories.ts +2 -1
@@ -14,13 +14,13 @@ import { DatabaseBackend, DataServiceHost, ItemManager } from '../database';
14
14
  import { Entity } from './entity';
15
15
  import { Item } from './item';
16
16
  import { Link } from './link';
17
- import { Selection, createSelector, RootFilter } from './selection';
17
+ import { RootFilter, Selection, createSelector } from './selection';
18
18
 
19
19
  export interface ItemCreationOptions<M extends Model> {
20
- model: ModelConstructor<M>
20
+ model?: ModelConstructor<M>
21
21
  type?: ItemType
22
22
  parent?: ItemID
23
- props?: any // TODO(marik-d): Type this better.
23
+ props?: any // TODO(marik-d): Type this better. Rename properties?
24
24
  }
25
25
 
26
26
  export interface LinkCreationOptions<M extends Model, L extends Model, R extends Model> {
@@ -47,7 +47,7 @@ export class Database {
47
47
  private _state = State.INITIAL;
48
48
 
49
49
  /**
50
- * Creates a new database instance. `database.init()` must be called afterwards to complete the initialization.
50
+ * Creates a new database instance. `database.initialize()` must be called afterwards to complete the initialization.
51
51
  */
52
52
  constructor (
53
53
  private readonly _modelFactory: ModelFactory,
@@ -79,7 +79,7 @@ export class Database {
79
79
  }
80
80
 
81
81
  @synchronized
82
- async init () {
82
+ async initialize () {
83
83
  if (this._state !== State.INITIAL) {
84
84
  throw new Error('Invalid state: database was already initialized.');
85
85
  }
@@ -101,12 +101,10 @@ export class Database {
101
101
  /**
102
102
  * Creates a new item with the given queryable type and model.
103
103
  */
104
- // TODO(burdon): Get modelType from somewhere other than `ObjectModel.meta.type`.
105
104
  async createItem <M extends Model<any>> (options: ItemCreationOptions<M>): Promise<Item<M>> {
106
105
  this._assertInitialized();
107
-
108
106
  if (!options.model) {
109
- throw new TypeError('Missing model class.');
107
+ options.model = ObjectModel as any as ModelConstructor<M>;
110
108
  }
111
109
 
112
110
  validateModelClass(options.model);
@@ -119,7 +117,10 @@ export class Database {
119
117
  throw new TypeError('Optional parent item id must be a string id of an existing item.');
120
118
  }
121
119
 
122
- return this._itemManager.createItem(options.model.meta.type, options.type, options.parent, options.props) as any;
120
+ // TODO(burdon): Get modelType from somewhere other than `ObjectModel.meta.type`.
121
+ const item = await this._itemManager.createItem(
122
+ options.model.meta.type, options.type, options.parent, options.props) as any;
123
+ return item;
123
124
  }
124
125
 
125
126
  async createLink<M extends Model<any>, S extends Model<any>, T extends Model<any>> (
package/src/api/item.ts CHANGED
@@ -51,16 +51,17 @@ export class Item<M extends Model | null = Model> extends Entity<M> {
51
51
 
52
52
  /**
53
53
  * Items are constructed by the `Database` object.
54
- * @param {ItemID} itemId - Addressable ID.
55
- * @param {ItemType} itemType - User defined type (DXN).
56
- * @param {Model} model - Data model (provided by `ModelFactory`).
57
- * @param [_writeStream] - Write stream (if not read-only).
58
- * @param {Item<any>} [parent] - Parent Item (if not a root Item).
54
+ * @param itemManager
55
+ * @param itemId Addressable ID.
56
+ * @param itemType User defined type (DXN).
57
+ * @param stateManager Data model (provided by `ModelFactory`).
58
+ * @param _writeStream Write stream (if not read-only).
59
+ * @param parent Parent Item (if not a root Item).
59
60
  */
60
61
  constructor (
61
62
  itemManager: ItemManager,
62
63
  itemId: ItemID,
63
- itemType: ItemType | undefined, // TODO(burdon): Why undefined?
64
+ itemType: ItemType | undefined, // TODO(burdon): Why allow undefined?
64
65
  stateManager: StateManager<NonNullable<M>>,
65
66
  private readonly _writeStream?: FeedWriter<EchoEnvelope>,
66
67
  parent?: Item<any> | null
@@ -60,9 +60,9 @@ describe('DataMirror', () => {
60
60
  // Mutate model
61
61
  await Promise.all([
62
62
  promiseTimeout(mirroredItem!.model.update.waitForCount(1), 1000, new Error('timeout')),
63
- item.model.setProperty('foo', 'bar')
63
+ item.model.set('foo', 'bar')
64
64
  ]);
65
65
 
66
- expect(item.model.getProperty('foo')).toEqual('bar');
66
+ expect(item.model.get('foo')).toEqual('bar');
67
67
  });
68
68
  });
@@ -78,7 +78,7 @@ describe('Item demuxer', () => {
78
78
  onUpdate();
79
79
  });
80
80
 
81
- await model.setProperty('title', 'Hello');
81
+ await model.set('title', 'Hello');
82
82
 
83
83
  //
84
84
  // Wait for model mutation to propagate.
@@ -154,7 +154,7 @@ export class ItemManager {
154
154
  if (initProps) {
155
155
  const meta = this._modelFactory.getModelMeta(modelType);
156
156
  if (!meta.getInitMutation) {
157
- throw new Error('Tried to provide initialization params to a model with no initializer');
157
+ throw new Error('Tried to provide initialization params to a model with no initializer.');
158
158
  }
159
159
  mutation = meta.mutation.encode(await meta.getInitMutation(initProps));
160
160
  }
@@ -24,7 +24,7 @@ export const createInMemoryDatabase = async (modelFactory: ModelFactory) => {
24
24
  PublicKey.random()
25
25
  );
26
26
 
27
- await database.init();
27
+ await database.initialize();
28
28
  return database;
29
29
  };
30
30
 
@@ -41,6 +41,6 @@ export const createRemoteDatabaseFromDataServiceHost = async (
41
41
  new RemoteDatabaseBackend(dataServiceRouter, partyKey),
42
42
  PublicKey.random()
43
43
  );
44
- await frontend.init();
44
+ await frontend.initialize();
45
45
  return frontend;
46
46
  };
package/src/echo.test.ts CHANGED
@@ -211,8 +211,8 @@ describe('ECHO', () => {
211
211
 
212
212
  const item = await party.database.createItem({ model: ObjectModel, props: { foo: 'bar', baz: 123 } });
213
213
 
214
- expect(item.model.getProperty('foo')).toEqual('bar');
215
- expect(item.model.getProperty('baz')).toEqual(123);
214
+ expect(item.model.get('foo')).toEqual('bar');
215
+ expect(item.model.get('baz')).toEqual(123);
216
216
  });
217
217
 
218
218
  test('open and close', async () => {
@@ -510,7 +510,7 @@ describe('ECHO', () => {
510
510
 
511
511
  await partyA.setTitle('A');
512
512
  expect(partyA.title).toBe('A');
513
- expect((await partyA.getPropertiesItem()).model.getProperty('title')).toBe('A');
513
+ expect((await partyA.getPropertiesItem()).model.get('title')).toBe('A');
514
514
 
515
515
  await partyA.deactivate({ global: true });
516
516
  expect(partyA.isOpen).toBe(false);
@@ -522,7 +522,7 @@ describe('ECHO', () => {
522
522
  expect(partyA.isActive).toBe(true);
523
523
  expect(partyA.title).toBe('A');
524
524
 
525
- await waitForCondition(async () => (await partyA.getPropertiesItem()).model.getProperty('title') === 'A', 4000);
525
+ await waitForCondition(async () => (await partyA.getPropertiesItem()).model.get('title') === 'A', 4000);
526
526
  });
527
527
 
528
528
  test('Deactivating and activating party, setting properties after', async () => {
@@ -713,13 +713,13 @@ describe('ECHO', () => {
713
713
  await partyA.setTitle('Test');
714
714
 
715
715
  for (const party of [partyA, partyB, partyC]) {
716
- await waitForCondition(async () => (await partyA.getPropertiesItem()).model.getProperty('title') === 'Test', 3000);
716
+ await waitForCondition(async () => (await partyA.getPropertiesItem()).model.get('title') === 'Test', 3000);
717
717
  await waitForCondition(() => party.title === 'Test', 3000);
718
718
  expect(party.title).toEqual('Test');
719
719
  }
720
720
 
721
721
  // For the other member of the party, title propagates correctly as well.
722
- await waitForCondition(async () => (await partyA.getPropertiesItem()).model.getProperty('title') === 'Test', 3000);
722
+ await waitForCondition(async () => (await partyA.getPropertiesItem()).model.get('title') === 'Test', 3000);
723
723
  await waitForCondition(() => partyD.title === 'Test', 3000);
724
724
  expect(partyD.title).toEqual('Test'); // However this does not.
725
725
  }).retries(1);
@@ -70,6 +70,7 @@ export class PartyPreferences {
70
70
  }
71
71
  }
72
72
 
73
+ // TODO(burdon): Currently HALO Party stores other party titles? Move to local storage.
73
74
  getLastKnownTitle () {
74
75
  return this._preferences.getGlobalPartyPreference(this._party.key, PARTY_TITLE_PROPERTY);
75
76
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  import assert from 'assert';
6
6
  import stableStringify from 'json-stable-stringify';
7
- import defaultsDeep from 'lodash/defaultsDeep';
7
+ import defaultsDeep from 'lodash.defaultsdeep';
8
8
 
9
9
  import { Event } from '@dxos/async';
10
10
  import { KeyHint } from '@dxos/credentials';
@@ -86,7 +86,7 @@ export class Preferences {
86
86
  return null;
87
87
  }
88
88
  const deviceItems = this._party.database.select({ type: HALO_PARTY_DEVICE_PREFERENCES_TYPE }).query().entities;
89
- return deviceItems.find(item => this._deviceKey.equals(item.model.getProperty('publicKey')));
89
+ return deviceItems.find(item => this._deviceKey.equals(item.model.get('publicKey')));
90
90
  }
91
91
 
92
92
  public getGlobalPartyPreference (partyKey: PublicKey, key: string) {
@@ -116,23 +116,23 @@ export class Preferences {
116
116
  // TODO(burdon): DO NOT USE THE PARTY KEY AS A TOP-LEVEL KEY!
117
117
  public _getPartyPreference (preferences: Item<any>, partyKey: PublicKey, key: string) {
118
118
  const path = partyKey.toHex();
119
- const partyPrefs = preferences.model.getProperty(path, {});
119
+ const partyPrefs = preferences.model.get(path, {});
120
120
  return partyPrefs[key];
121
121
  }
122
122
 
123
123
  // TODO(burdon): DO NOT USE THE PARTY KEY AS A TOP-LEVEL KEY!
124
124
  public async _setPartyPreference (preferences: Item<any>, party: PartyInternal, key: string, value: any) {
125
125
  const path = party.key.toHex();
126
- const partyPrefs = preferences.model.getProperty(path, {});
126
+ const partyPrefs = preferences.model.get(path, {});
127
127
  partyPrefs[key] = value;
128
- await preferences.model.setProperty(party.key.toHex(), partyPrefs);
128
+ await preferences.model.set(party.key.toHex(), partyPrefs);
129
129
  party.update.emit(); // TODO(burdon): Should subscribe to database changes only?
130
130
  }
131
131
 
132
132
  async recordPartyJoining (joinedParty: JoinedParty) {
133
133
  const [partyDesc] = this._party.database
134
134
  .select({ type: HALO_PARTY_DESCRIPTOR_TYPE })
135
- .filter(partyMarker => joinedParty.partyKey.equals(partyMarker.model.getProperty('publicKey')))
135
+ .filter(partyMarker => joinedParty.partyKey.equals(partyMarker.model.get('publicKey')))
136
136
  .query().entities;
137
137
  assert(!partyDesc, `Descriptor already exists for Party: ${joinedParty.partyKey.toHex()}`);
138
138
 
@@ -151,8 +151,8 @@ export class Preferences {
151
151
  const converter = (partyDesc: Item<any>) => {
152
152
  // TODO(burdon): Define type.
153
153
  return {
154
- partyKey: PublicKey.from(partyDesc.model.getProperty('publicKey')),
155
- keyHints: Object.values(partyDesc.model.getProperty('hints')).map((hint: any) => ({
154
+ partyKey: PublicKey.from(partyDesc.model.get('publicKey')),
155
+ keyHints: Object.values(partyDesc.model.get('hints')).map((hint: any) => ({
156
156
  ...hint,
157
157
  publicKey: PublicKey.from(hint.publicKey)
158
158
  } as KeyHint))
@@ -12,7 +12,6 @@ import { MetadataStore } from './metadata-store';
12
12
  describe('MetadataStore in-memory', () => {
13
13
  it('Creates party and adds feeds to it', async () => {
14
14
  const store = new MetadataStore(createRamStorage());
15
-
16
15
  await store.load();
17
16
  expect(store.parties?.length).toBe(0);
18
17
 
@@ -35,7 +34,6 @@ describe('MetadataStore in-memory', () => {
35
34
 
36
35
  it('Creates party when adding feed', async () => {
37
36
  const store = new MetadataStore(createRamStorage());
38
-
39
37
  await store.load();
40
38
 
41
39
  const partyKey = PublicKey.random();
@@ -48,7 +46,6 @@ describe('MetadataStore in-memory', () => {
48
46
 
49
47
  it('Doesn\'t add same feed twice', async () => {
50
48
  const store = new MetadataStore(createRamStorage());
51
-
52
49
  await store.load();
53
50
 
54
51
  const partyKey = PublicKey.random();
@@ -83,9 +83,9 @@ describe('PartyCore', () => {
83
83
  const { party } = await setup();
84
84
 
85
85
  const item = await party.database.createItem({ model: ObjectModel });
86
- await item.model.setProperty('foo', 'bar');
86
+ await item.model.set('foo', 'bar');
87
87
 
88
- expect(item.model.getProperty('foo')).toEqual('bar');
88
+ expect(item.model.get('foo')).toEqual('bar');
89
89
  });
90
90
 
91
91
  test('create item with parent and then reload', async () => {
@@ -151,7 +151,7 @@ export class PartyCore {
151
151
  this._memberKey
152
152
  );
153
153
 
154
- await this._database.init();
154
+ await this._database.initialize();
155
155
 
156
156
  // TODO(burdon): Propagate errors.
157
157
  this._subscriptions.push(this._pipeline.errors.on(err => console.error(err)));
@@ -23,7 +23,8 @@ import { PartyCore, PartyOptions } from './party-core';
23
23
  import { CONTACT_DEBOUNCE_INTERVAL } from './party-manager';
24
24
 
25
25
  export const PARTY_ITEM_TYPE = 'dxos:item/party';
26
- export const PARTY_TITLE_PROPERTY = 'title';
26
+
27
+ export const PARTY_TITLE_PROPERTY = 'title'; // TODO(burdon): Remove (should not be special).
27
28
 
28
29
  // TODO(burdon): Factor out public API.
29
30
  export interface PartyMember {
@@ -139,7 +140,7 @@ export class PartyInternal {
139
140
 
140
141
  async setTitle (title: string) {
141
142
  const item = await this.getPropertiesItem();
142
- await item.model.setProperty(PARTY_TITLE_PROPERTY, title);
143
+ await item.model.set(PARTY_TITLE_PROPERTY, title);
143
144
  await this._preferences?.setLastKnownTitle(title);
144
145
  }
145
146
 
@@ -499,13 +499,13 @@ describe('Party manager', () => {
499
499
  const original = await partyManager.createParty();
500
500
  const item1 = await original.database.createItem({ model: ObjectModel });
501
501
  const item2 = await original.database.createItem({ model: ObjectModel, parent: item1.id, type: 'example' });
502
- await item2.model.setProperty('foo', 'bar');
502
+ await item2.model.set('foo', 'bar');
503
503
 
504
504
  const clone = await partyManager.cloneParty(original.createSnapshot());
505
505
  expect(clone.key.equals(original.key)).toBe(false);
506
506
  const item = await clone.database.getItem(item2.id);
507
507
  assert(item);
508
- expect(item.model.getProperty('foo')).toBe('bar');
508
+ expect(item.model.get('foo')).toBe('bar');
509
509
  expect(item.parent).toBeDefined();
510
510
  });
511
511
  });
@@ -4,7 +4,7 @@
4
4
 
5
5
  import assert from 'assert';
6
6
  import debug from 'debug';
7
- import unionWith from 'lodash/unionWith';
7
+ import unionWith from 'lodash.unionwith';
8
8
 
9
9
  import { Event, synchronized } from '@dxos/async';
10
10
  import { KeyHint, KeyType, SecretProvider } from '@dxos/credentials';
@@ -264,12 +264,10 @@ export class PartyManager {
264
264
  }
265
265
 
266
266
  const identity = this._identityProvider();
267
-
268
267
  const item = await party.getPropertiesItem();
269
- const currentTitle = item.model.getProperty(PARTY_TITLE_PROPERTY);
268
+ const currentTitle = item.model.get(PARTY_TITLE_PROPERTY);
270
269
  const storedTitle = identity.preferences?.getGlobalPartyPreference(party.key, PARTY_TITLE_PROPERTY);
271
270
  if (storedTitle !== currentTitle) {
272
- log(`Updating stored name from ${storedTitle} to ${currentTitle} for Party ${party.key.toHex()}`);
273
271
  await identity.preferences?.setGlobalPartyPreference(party, PARTY_TITLE_PROPERTY, currentTitle);
274
272
  }
275
273
  }
@@ -305,12 +303,12 @@ export class PartyManager {
305
303
  if (memberInfo && contact.displayName !== memberInfo.displayName) {
306
304
  log(`Updating contact ${hexKey} to ${memberInfo.displayName}`);
307
305
  contact.displayName = memberInfo.displayName;
308
- await contactListItem.model.setProperty(hexKey, memberInfo);
306
+ await contactListItem.model.set(hexKey, memberInfo);
309
307
  }
310
308
  } else {
311
309
  const displayName = memberInfo?.displayName ?? hexKey;
312
310
  log(`Creating contact ${hexKey} to ${displayName}`);
313
- await contactListItem.model.setProperty(hexKey, { publicKey, displayName });
311
+ await contactListItem.model.set(hexKey, { publicKey, displayName });
314
312
  }
315
313
  }
316
314
  }
@@ -16,9 +16,8 @@ import { ItemDemuxer, ItemManager } from '../database';
16
16
  import { createTestInstance } from '../testing';
17
17
 
18
18
  const log = debug('dxos:snapshot:test');
19
- debug.enable('dxos:echo-db:*');
19
+ // debug.enable('dxos:echo-db:*');
20
20
 
21
- // TODO(burdon): Remove "foo", etc from tests.
22
21
  describe('snapshot', () => {
23
22
  test.skip('loading large party', async () => {
24
23
  const echo = await createTestInstance({ initialize: true });
@@ -32,9 +31,9 @@ describe('snapshot', () => {
32
31
  const item = await party.database.createItem({ model: ObjectModel });
33
32
  itemId = item.id;
34
33
  for (let i = 0; i < 1_000; i++) {
35
- await item.model.setProperty('foo', i);
34
+ await item.model.set('foo', i);
36
35
  }
37
- await item.model.setProperty('foo', 'done');
36
+ await item.model.set('foo', 'done');
38
37
 
39
38
  await echo.close();
40
39
  }
@@ -47,7 +46,7 @@ describe('snapshot', () => {
47
46
 
48
47
  await waitForCondition(() => {
49
48
  const item = party!.database.getItem(itemId);
50
- return item!.model.getProperty('foo') === 'done';
49
+ return item!.model.get('foo') === 'done';
51
50
  });
52
51
 
53
52
  await echo.close();
@@ -61,9 +60,9 @@ describe('snapshot', () => {
61
60
  const echo = await createTestInstance({ initialize: true });
62
61
  const party = await echo.createParty();
63
62
  const item1 = await party.database.createItem({ model: ObjectModel, props: { title: 'Item1 - Creation' } });
64
- await item1.model.setProperty('title', 'Item1 - Modified');
63
+ await item1.model.set('title', 'Item1 - Modified');
65
64
  const item2 = await party.database.createItem({ model: ObjectModel, props: { title: 'Item2 - Creation' } });
66
- await item2.model.setProperty('title', 'Item2 - Modified');
65
+ await item2.model.set('title', 'Item2 - Modified');
67
66
 
68
67
  const link = await party.database.createLink({ source: item1, target: item2 });
69
68
 
@@ -5,6 +5,7 @@
5
5
  import assert from 'assert';
6
6
 
7
7
  import { Model } from '@dxos/model-factory';
8
+ import { ObjectModel } from '@dxos/object-model';
8
9
  import { range } from '@dxos/util';
9
10
 
10
11
  import { Item, ItemCreationOptions } from '../api';
@@ -57,7 +58,7 @@ export const createModelTestBench = async<M extends Model<any>> (
57
58
  ): Promise<{ peers: ECHO[], items: WithTestMeta<Item<M>>[] }> => {
58
59
  const { peers, parties } = await createParties(options.peerCount ?? 2);
59
60
  for (const party of parties) {
60
- const { model } = options;
61
+ const { model = ObjectModel } = options;
61
62
  const { modelFactory } = party.testMeta; // TODO(burdon): Remove.
62
63
  if (!modelFactory.hasModel(model.meta.type)) {
63
64
  modelFactory.registerModel(model);