@dxos/echo-db 2.29.1 → 2.29.2-dev.f64f2a6f
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/src/api/database.d.ts +11 -7
- package/dist/src/api/database.d.ts.map +1 -1
- package/dist/src/api/database.js +20 -23
- package/dist/src/api/database.js.map +1 -1
- package/dist/src/api/database.test.js +13 -13
- package/dist/src/api/database.test.js.map +1 -1
- package/dist/src/api/item.d.ts.map +1 -1
- package/dist/src/api/item.js +1 -1
- package/dist/src/api/item.js.map +1 -1
- package/dist/src/api/result-set.d.ts.map +1 -1
- package/dist/src/api/result-set.js +1 -0
- package/dist/src/api/result-set.js.map +1 -1
- package/dist/src/api/selection/index.d.ts +5 -0
- package/dist/src/api/selection/index.d.ts.map +1 -0
- package/dist/src/api/selection/index.js +20 -0
- package/dist/src/api/selection/index.js.map +1 -0
- package/dist/src/api/selection/queries.d.ts +51 -0
- package/dist/src/api/selection/queries.d.ts.map +1 -0
- package/dist/src/api/selection/queries.js +70 -0
- package/dist/src/api/selection/queries.js.map +1 -0
- package/dist/src/api/selection/result.d.ts +50 -0
- package/dist/src/api/selection/result.d.ts.map +1 -0
- package/dist/src/api/selection/result.js +91 -0
- package/dist/src/api/selection/result.js.map +1 -0
- package/dist/src/api/selection/selection.d.ts +96 -0
- package/dist/src/api/selection/selection.d.ts.map +1 -0
- package/dist/src/api/selection/selection.js +164 -0
- package/dist/src/api/selection/selection.js.map +1 -0
- package/dist/src/api/{selection.test.d.ts → selection/selection.test.d.ts} +0 -0
- package/dist/src/api/selection/selection.test.d.ts.map +1 -0
- package/dist/src/api/{selection.test.js → selection/selection.test.js} +46 -44
- package/dist/src/api/selection/selection.test.js.map +1 -0
- package/dist/src/api/selection/util.d.ts +7 -0
- package/dist/src/api/selection/util.d.ts.map +1 -0
- package/dist/src/api/selection/util.js +25 -0
- package/dist/src/api/selection/util.js.map +1 -0
- package/dist/src/echo.test.js +20 -20
- package/dist/src/echo.test.js.map +1 -1
- package/dist/src/halo/contact-manager.js +2 -2
- package/dist/src/halo/contact-manager.js.map +1 -1
- package/dist/src/halo/preferences.js +6 -6
- package/dist/src/halo/preferences.js.map +1 -1
- package/dist/src/parties/party-core.test.js +3 -3
- package/dist/src/parties/party-core.test.js.map +1 -1
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +3 -3
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-internal.js +3 -3
- package/dist/src/parties/party-internal.js.map +1 -1
- package/dist/src/parties/party-manager.js +1 -1
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/parties/party-manager.test.js +8 -10
- package/dist/src/parties/party-manager.test.js.map +1 -1
- package/dist/src/testing/testing-factories.d.ts +2 -2
- package/dist/src/testing/testing-factories.d.ts.map +1 -1
- package/dist/src/testing/testing-factories.js +1 -1
- package/dist/src/testing/testing-factories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -27
- package/src/api/database.test.ts +13 -13
- package/src/api/database.ts +28 -29
- package/src/api/item.ts +2 -2
- package/src/api/result-set.ts +1 -0
- package/src/api/selection/index.ts +8 -0
- package/src/api/selection/queries.ts +108 -0
- package/src/api/selection/result.ts +112 -0
- package/src/api/{selection.test.ts → selection/selection.test.ts} +50 -48
- package/src/api/{selection.ts → selection/selection.ts} +30 -231
- package/src/api/selection/util.ts +27 -0
- package/src/echo.test.ts +20 -20
- package/src/halo/contact-manager.ts +2 -2
- package/src/halo/preferences.ts +6 -6
- package/src/parties/party-core.test.ts +3 -3
- package/src/parties/party-factory.ts +3 -4
- package/src/parties/party-internal.ts +3 -3
- package/src/parties/party-manager.test.ts +8 -10
- package/src/parties/party-manager.ts +1 -1
- package/src/testing/testing-factories.ts +3 -3
- package/dist/src/api/selection.d.ts +0 -183
- package/dist/src/api/selection.d.ts.map +0 -1
- package/dist/src/api/selection.js +0 -308
- package/dist/src/api/selection.js.map +0 -1
- package/dist/src/api/selection.test.d.ts.map +0 -1
- package/dist/src/api/selection.test.js.map +0 -1
package/src/echo.test.ts
CHANGED
|
@@ -66,13 +66,13 @@ describe('ECHO', () => {
|
|
|
66
66
|
// TODO(burdon): Update currently called after all mutations below have completed?
|
|
67
67
|
expect(parties).toHaveLength(1);
|
|
68
68
|
parties.map(async party => {
|
|
69
|
-
const result1 = party.database.select().
|
|
69
|
+
const result1 = party.database.select().exec();
|
|
70
70
|
result1.entities.forEach(item => {
|
|
71
71
|
log('Item:', String(item));
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
// TODO(burdon): Check item mutations.
|
|
75
|
-
const result2 = party.database.select({ type: '
|
|
75
|
+
const result2 = party.database.select({ type: 'example:item/document' }).exec();
|
|
76
76
|
expect(result2.entities).toHaveLength(2);
|
|
77
77
|
onUpdate();
|
|
78
78
|
});
|
|
@@ -87,9 +87,9 @@ describe('ECHO', () => {
|
|
|
87
87
|
expect(members[0].displayName).toEqual(members[0].publicKey.humanize());
|
|
88
88
|
|
|
89
89
|
// TODO(burdon): Test item mutations.
|
|
90
|
-
await party.database.createItem({ model: ObjectModel, type: '
|
|
91
|
-
await party.database.createItem({ model: ObjectModel, type: '
|
|
92
|
-
await party.database.createItem({ model: ObjectModel, type: '
|
|
90
|
+
await party.database.createItem({ model: ObjectModel, type: 'example:item/document' });
|
|
91
|
+
await party.database.createItem({ model: ObjectModel, type: 'example:item/document' });
|
|
92
|
+
await party.database.createItem({ model: ObjectModel, type: 'example:item/kanban' });
|
|
93
93
|
|
|
94
94
|
await updated;
|
|
95
95
|
unsubscribe();
|
|
@@ -108,12 +108,12 @@ describe('ECHO', () => {
|
|
|
108
108
|
|
|
109
109
|
expect(parties).toHaveLength(1);
|
|
110
110
|
parties.map(async party => {
|
|
111
|
-
const items = party.database.select().
|
|
111
|
+
const items = party.database.select().exec().entities;
|
|
112
112
|
items.forEach(item => {
|
|
113
113
|
log('Item:', String(item));
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
-
const item = party.database.select({ type: '
|
|
116
|
+
const item = party.database.select({ type: 'example:item/document' }).exec().entities[0];
|
|
117
117
|
expect(item.children).toHaveLength(1);
|
|
118
118
|
expect(item.children[0].type).toBe(undefined);
|
|
119
119
|
// TODO(burdon): Test parent.
|
|
@@ -129,7 +129,7 @@ describe('ECHO', () => {
|
|
|
129
129
|
// Within this test, we use the humanized key as the name.
|
|
130
130
|
expect(members[0].displayName).toEqual(members[0].publicKey.humanize());
|
|
131
131
|
|
|
132
|
-
const parent = await party.database.createItem({ model: ObjectModel, type: '
|
|
132
|
+
const parent = await party.database.createItem({ model: ObjectModel, type: 'example:item/document' });
|
|
133
133
|
await party.database.createItem({ model: ObjectModel, parent: parent.id });
|
|
134
134
|
|
|
135
135
|
await updated;
|
|
@@ -151,12 +151,12 @@ describe('ECHO', () => {
|
|
|
151
151
|
// Within this test, we use the humanized key as the name.
|
|
152
152
|
expect(members[0].displayName).toEqual(members[0].publicKey.humanize());
|
|
153
153
|
|
|
154
|
-
const parentA = await party.database.createItem({ model: ObjectModel, type: '
|
|
154
|
+
const parentA = await party.database.createItem({ model: ObjectModel, type: 'example:item/document' });
|
|
155
155
|
const childA = await party.database.createItem({ model: ObjectModel, parent: parentA.id });
|
|
156
156
|
expect(parentA.children).toHaveLength(1);
|
|
157
157
|
expect(parentA.children[0].id).toEqual(childA.id);
|
|
158
158
|
|
|
159
|
-
const parentB = await party.database.createItem({ model: ObjectModel, type: '
|
|
159
|
+
const parentB = await party.database.createItem({ model: ObjectModel, type: 'example:item/document' });
|
|
160
160
|
const childB = await party.database.createItem({ model: ObjectModel, parent: parentB.id });
|
|
161
161
|
expect(parentB.children).toHaveLength(1);
|
|
162
162
|
expect(parentB.children[0].id).toEqual(childB.id);
|
|
@@ -199,7 +199,7 @@ describe('ECHO', () => {
|
|
|
199
199
|
assert(party);
|
|
200
200
|
log('Initialized party');
|
|
201
201
|
|
|
202
|
-
const items = party.database.select().
|
|
202
|
+
const items = party.database.select().exec().entities;
|
|
203
203
|
await waitForCondition(() => items.length > 0);
|
|
204
204
|
expect(items.length).toBeGreaterThan(0);
|
|
205
205
|
});
|
|
@@ -301,7 +301,7 @@ describe('ECHO', () => {
|
|
|
301
301
|
let itemA: Item<any> | null = null;
|
|
302
302
|
|
|
303
303
|
// Subscribe to Item updates on B.
|
|
304
|
-
const updated = partyB.database.select({ type: 'example:item/test' }).
|
|
304
|
+
const updated = partyB.database.select({ type: 'example:item/test' }).exec()
|
|
305
305
|
.update.waitFor(result => !!itemA && !!result.entities.find(item => item.id === itemA?.id));
|
|
306
306
|
|
|
307
307
|
// Create a new Item on A.
|
|
@@ -398,7 +398,7 @@ describe('ECHO', () => {
|
|
|
398
398
|
// Empty across the board.
|
|
399
399
|
for (const node of [a1, a2, b1, b2]) {
|
|
400
400
|
const [party] = node.queryParties().value;
|
|
401
|
-
expect(party.database.select({ type: 'example:item/test' }).
|
|
401
|
+
expect(party.database.select({ type: 'example:item/test' }).exec().entities.length).toBe(0);
|
|
402
402
|
}
|
|
403
403
|
|
|
404
404
|
for await (const node of [a1, a2, b1, b2]) {
|
|
@@ -409,7 +409,7 @@ describe('ECHO', () => {
|
|
|
409
409
|
for (const otherNode of [a1, a2, b1, b2].filter(x => x !== node)) {
|
|
410
410
|
const [otherParty] = otherNode.queryParties().value;
|
|
411
411
|
const [updated, onUpdate] = latch();
|
|
412
|
-
otherParty.database.select({ type: 'example:item/test' }).
|
|
412
|
+
otherParty.database.select({ type: 'example:item/test' }).exec()
|
|
413
413
|
.update.on(result => {
|
|
414
414
|
if (result.entities.find(current => current.id === item?.id)) {
|
|
415
415
|
log(`other has ${item?.id}`);
|
|
@@ -460,8 +460,8 @@ describe('ECHO', () => {
|
|
|
460
460
|
let itemA: Item<any> | null = null;
|
|
461
461
|
|
|
462
462
|
// Subscribe to Item updates on B.
|
|
463
|
-
const
|
|
464
|
-
|
|
463
|
+
const result = b.queryParties().value[0].database.select({ type: 'example:item/test' }).exec();
|
|
464
|
+
const updated = result.update.waitFor(items => !!itemA && !!items.entities.find(item => item.id === itemA?.id));
|
|
465
465
|
|
|
466
466
|
// Create a new Item on A.
|
|
467
467
|
itemA = await a.queryParties().value[0].database
|
|
@@ -592,7 +592,7 @@ describe('ECHO', () => {
|
|
|
592
592
|
let itemA: Item<any> | null = null;
|
|
593
593
|
const [updated, onUpdate] = latch();
|
|
594
594
|
|
|
595
|
-
partyA.database.select({ type: 'example:item/test' }).
|
|
595
|
+
partyA.database.select({ type: 'example:item/test' }).exec()
|
|
596
596
|
.update.on(result => {
|
|
597
597
|
if (result.entities.length) {
|
|
598
598
|
const [receivedItem] = result.entities;
|
|
@@ -605,7 +605,7 @@ describe('ECHO', () => {
|
|
|
605
605
|
itemA = await partyA.database.createItem({ model: ObjectModel, type: 'example:item/test' }) as Item<any>;
|
|
606
606
|
await updated; // Wait for update.
|
|
607
607
|
|
|
608
|
-
expect(partyA.database.select({ type: 'example:item/test' }).
|
|
608
|
+
expect(partyA.database.select({ type: 'example:item/test' }).exec().entities.length).toEqual(1);
|
|
609
609
|
|
|
610
610
|
await partyA.deactivate({ global: true });
|
|
611
611
|
await partyA.activate({ global: true });
|
|
@@ -615,9 +615,9 @@ describe('ECHO', () => {
|
|
|
615
615
|
|
|
616
616
|
await partyA.database
|
|
617
617
|
.select({ type: 'example:item/test' })
|
|
618
|
-
.
|
|
618
|
+
.exec()
|
|
619
619
|
.update.waitFor(result => result.entities.length > 0);
|
|
620
|
-
expect(partyA.database.select({ type: 'example:item/test' }).
|
|
620
|
+
expect(partyA.database.select({ type: 'example:item/test' }).exec().entities.length).toEqual(1);
|
|
621
621
|
}).timeout(10_000);
|
|
622
622
|
|
|
623
623
|
test('Deactivate Party - multi device', async () => {
|
|
@@ -22,12 +22,12 @@ export class ContactManager {
|
|
|
22
22
|
) {}
|
|
23
23
|
|
|
24
24
|
getContactListItem (): Item<ObjectModel> | undefined {
|
|
25
|
-
return this._party.database.select({ type: HALO_PARTY_CONTACT_LIST_TYPE }).
|
|
25
|
+
return this._party.database.select({ type: HALO_PARTY_CONTACT_LIST_TYPE }).exec().entities[0];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
queryContacts (): ResultSet<Contact> {
|
|
29
29
|
const event = new Event();
|
|
30
|
-
const result = this._party.database.select({ type: HALO_PARTY_CONTACT_LIST_TYPE }).
|
|
30
|
+
const result = this._party.database.select({ type: HALO_PARTY_CONTACT_LIST_TYPE }).exec();
|
|
31
31
|
result.update.on(() => {
|
|
32
32
|
event.emit();
|
|
33
33
|
});
|
package/src/halo/preferences.ts
CHANGED
|
@@ -42,8 +42,8 @@ export class Preferences {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
subscribeToPreferences (callback: (preferences: any) => void) {
|
|
45
|
-
const globalResults = this._party.database.select({ type: HALO_PARTY_PREFERENCES_TYPE }).
|
|
46
|
-
const deviceResults = this._party.database.select({ type: HALO_PARTY_DEVICE_PREFERENCES_TYPE }).
|
|
45
|
+
const globalResults = this._party.database.select({ type: HALO_PARTY_PREFERENCES_TYPE }).exec();
|
|
46
|
+
const deviceResults = this._party.database.select({ type: HALO_PARTY_DEVICE_PREFERENCES_TYPE }).exec();
|
|
47
47
|
|
|
48
48
|
const event = new Event<any>();
|
|
49
49
|
|
|
@@ -77,7 +77,7 @@ export class Preferences {
|
|
|
77
77
|
if (!this._party.isOpen) {
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
|
-
const [globalItem] = this._party.database.select({ type: HALO_PARTY_PREFERENCES_TYPE }).
|
|
80
|
+
const [globalItem] = this._party.database.select({ type: HALO_PARTY_PREFERENCES_TYPE }).exec().entities;
|
|
81
81
|
return globalItem;
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -85,7 +85,7 @@ export class Preferences {
|
|
|
85
85
|
if (!this._party.isOpen) {
|
|
86
86
|
return null;
|
|
87
87
|
}
|
|
88
|
-
const deviceItems = this._party.database.select({ type: HALO_PARTY_DEVICE_PREFERENCES_TYPE }).
|
|
88
|
+
const deviceItems = this._party.database.select({ type: HALO_PARTY_DEVICE_PREFERENCES_TYPE }).exec().entities;
|
|
89
89
|
return deviceItems.find(item => this._deviceKey.equals(item.model.get('publicKey')));
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -133,7 +133,7 @@ export class Preferences {
|
|
|
133
133
|
const [partyDesc] = this._party.database
|
|
134
134
|
.select({ type: HALO_PARTY_DESCRIPTOR_TYPE })
|
|
135
135
|
.filter(partyMarker => joinedParty.partyKey.equals(partyMarker.model.get('publicKey')))
|
|
136
|
-
.
|
|
136
|
+
.exec().entities;
|
|
137
137
|
assert(!partyDesc, `Descriptor already exists for Party: ${joinedParty.partyKey.toHex()}`);
|
|
138
138
|
|
|
139
139
|
await this._party.database.createItem({
|
|
@@ -159,7 +159,7 @@ export class Preferences {
|
|
|
159
159
|
};
|
|
160
160
|
};
|
|
161
161
|
|
|
162
|
-
const result = this._party.database.select({ type: HALO_PARTY_DESCRIPTOR_TYPE }).
|
|
162
|
+
const result = this._party.database.select({ type: HALO_PARTY_DESCRIPTOR_TYPE }).exec();
|
|
163
163
|
|
|
164
164
|
// Wrap the query event so we can have manual control.
|
|
165
165
|
const event = new Event();
|
|
@@ -107,9 +107,9 @@ describe('PartyCore', () => {
|
|
|
107
107
|
await party.open();
|
|
108
108
|
|
|
109
109
|
{
|
|
110
|
-
await party.database.select().
|
|
111
|
-
const parent = party.database.select({ type: 'parent' }).
|
|
112
|
-
const child = party.database.select({ type: 'child' }).
|
|
110
|
+
await party.database.select().exec().update.waitFor(result => result.entities.length === 2);
|
|
111
|
+
const parent = party.database.select({ type: 'parent' }).exec().entities[0];
|
|
112
|
+
const child = party.database.select({ type: 'child' }).exec().entities[0];
|
|
113
113
|
|
|
114
114
|
expect(child.parent).toEqual(parent);
|
|
115
115
|
expect(parent.children).toContain(child);
|
|
@@ -51,10 +51,9 @@ export class PartyFactory {
|
|
|
51
51
|
@timed(5_000)
|
|
52
52
|
async createParty (): Promise<PartyInternal> {
|
|
53
53
|
const identity = this._identityProvider();
|
|
54
|
-
|
|
55
|
-
assert(
|
|
56
|
-
assert(
|
|
57
|
-
assert(identity.deviceKeyChain, 'Device KeyChain must exist');
|
|
54
|
+
assert(identity.identityGenesis, 'HALO not initialized.');
|
|
55
|
+
assert(identity.deviceKeyChain, 'Device KeyChain not initialized.');
|
|
56
|
+
assert(!this._options.readOnly, 'PartyFactory is read-only.');
|
|
58
57
|
|
|
59
58
|
const partyKey = await identity.keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
60
59
|
const party = await this.constructParty(partyKey.publicKey);
|
|
@@ -186,7 +186,7 @@ export class PartyInternal {
|
|
|
186
186
|
await this._protocol.start();
|
|
187
187
|
|
|
188
188
|
// Issue an 'update' whenever the properties change.
|
|
189
|
-
this.database.select({ type: PARTY_ITEM_TYPE }).
|
|
189
|
+
this.database.select({ type: PARTY_ITEM_TYPE }).exec().update.on(() => this.update.emit());
|
|
190
190
|
|
|
191
191
|
this.update.emit();
|
|
192
192
|
return this;
|
|
@@ -246,7 +246,7 @@ export class PartyInternal {
|
|
|
246
246
|
assert(this.isOpen, 'Party not open.');
|
|
247
247
|
|
|
248
248
|
await this.database.waitForItem({ type: PARTY_ITEM_TYPE });
|
|
249
|
-
const items = this.database.select({ type: PARTY_ITEM_TYPE }).
|
|
249
|
+
const items = this.database.select({ type: PARTY_ITEM_TYPE }).exec().entities;
|
|
250
250
|
assert(items.length === 1, 'Party properties missing.');
|
|
251
251
|
return items[0] as Item<ObjectModel>;
|
|
252
252
|
}
|
|
@@ -256,7 +256,7 @@ export class PartyInternal {
|
|
|
256
256
|
*/
|
|
257
257
|
getPropertiesSet () {
|
|
258
258
|
assert(this.isOpen, 'Party not open.');
|
|
259
|
-
return this.database.select({ type: PARTY_ITEM_TYPE }).
|
|
259
|
+
return this.database.select({ type: PARTY_ITEM_TYPE }).exec();
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
/**
|
|
@@ -263,14 +263,12 @@ describe('Party manager', () => {
|
|
|
263
263
|
expect(partyB).toBeDefined();
|
|
264
264
|
|
|
265
265
|
const [updated, onUpdate] = latch();
|
|
266
|
-
partyB.database.select({ type: 'example:item/test' }).
|
|
266
|
+
partyB.database.select({ type: 'example:item/test' }).exec()
|
|
267
267
|
.update.on(result => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
onUpdate();
|
|
273
|
-
}
|
|
268
|
+
const [itemB] = result.entities;
|
|
269
|
+
if (itemA && itemA.id === itemB.id) {
|
|
270
|
+
log(`B has ${itemB.id}`);
|
|
271
|
+
onUpdate();
|
|
274
272
|
}
|
|
275
273
|
});
|
|
276
274
|
|
|
@@ -318,7 +316,7 @@ describe('Party manager', () => {
|
|
|
318
316
|
|
|
319
317
|
// Subscribe to Item updates on B.
|
|
320
318
|
const [updated, onUpdate] = latch();
|
|
321
|
-
partyB.database.select({ type: 'example:item/test' }).
|
|
319
|
+
partyB.database.select({ type: 'example:item/test' }).exec()
|
|
322
320
|
.update.on(result => {
|
|
323
321
|
if (result.entities.length) {
|
|
324
322
|
const [itemB] = result.entities;
|
|
@@ -399,7 +397,7 @@ describe('Party manager', () => {
|
|
|
399
397
|
const [updated, onUpdate] = latch();
|
|
400
398
|
|
|
401
399
|
// Subscribe to Item updates on B.
|
|
402
|
-
partyB.database.select({ type: 'example:item/test' }).
|
|
400
|
+
partyB.database.select({ type: 'example:item/test' }).exec()
|
|
403
401
|
.update.on(result => {
|
|
404
402
|
if (result.entities.length) {
|
|
405
403
|
const [itemB] = result.entities;
|
|
@@ -458,7 +456,7 @@ describe('Party manager', () => {
|
|
|
458
456
|
const [updated, onUpdate] = latch();
|
|
459
457
|
|
|
460
458
|
// Subscribe to Item updates on B.
|
|
461
|
-
partyB.database.select({ type: 'example:item/test' }).
|
|
459
|
+
partyB.database.select({ type: 'example:item/test' }).exec()
|
|
462
460
|
.update.on(result => {
|
|
463
461
|
if (result.entities.length) {
|
|
464
462
|
const [itemB] = result.entities;
|
|
@@ -244,7 +244,7 @@ export class PartyManager {
|
|
|
244
244
|
const attachUpdateListeners = () => {
|
|
245
245
|
const debouncedContacts = party.processor.keyOrInfoAdded.debounce(CONTACT_DEBOUNCE_INTERVAL).discardParameter();
|
|
246
246
|
debouncedContacts.on(updateContact);
|
|
247
|
-
party.database.select({ type: PARTY_ITEM_TYPE }).
|
|
247
|
+
party.database.select({ type: PARTY_ITEM_TYPE }).exec().update.on(updateTitle);
|
|
248
248
|
};
|
|
249
249
|
|
|
250
250
|
if (party.isOpen) {
|
|
@@ -8,7 +8,7 @@ import { Model } from '@dxos/model-factory';
|
|
|
8
8
|
import { ObjectModel } from '@dxos/object-model';
|
|
9
9
|
import { range } from '@dxos/util';
|
|
10
10
|
|
|
11
|
-
import { Item,
|
|
11
|
+
import { Item, CreateItemOption } from '../api';
|
|
12
12
|
import { ECHO } from '../echo';
|
|
13
13
|
import { PartyInternal } from '../parties';
|
|
14
14
|
import { createTestInstance, inviteTestPeer } from './testing';
|
|
@@ -54,7 +54,7 @@ const createParties = async (peerCount = 2): Promise<{ peers: ECHO[], parties: W
|
|
|
54
54
|
* @returns Item instances from each of the peers.
|
|
55
55
|
*/
|
|
56
56
|
export const createModelTestBench = async<M extends Model<any>> (
|
|
57
|
-
options:
|
|
57
|
+
options: CreateItemOption<M> & { peerCount?: number}
|
|
58
58
|
): Promise<{ peers: ECHO[], items: WithTestMeta<Item<M>>[] }> => {
|
|
59
59
|
const { peers, parties } = await createParties(options.peerCount ?? 2);
|
|
60
60
|
for (const party of parties) {
|
|
@@ -72,7 +72,7 @@ export const createModelTestBench = async<M extends Model<any>> (
|
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
await party.database.select().
|
|
75
|
+
await party.database.select().exec().update.waitFor(() => !!party.database.getItem(item.id));
|
|
76
76
|
}));
|
|
77
77
|
|
|
78
78
|
const items = parties
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import { Event } from '@dxos/async';
|
|
2
|
-
import { ItemID } from '@dxos/echo-protocol';
|
|
3
|
-
import { Database } from './database';
|
|
4
|
-
import { Entity } from './entity';
|
|
5
|
-
import { Item } from './item';
|
|
6
|
-
import { Link } from './link';
|
|
7
|
-
export declare type OneOrMultiple<T> = T | T[];
|
|
8
|
-
export declare type ItemIdFilter = {
|
|
9
|
-
id: ItemID;
|
|
10
|
-
};
|
|
11
|
-
export declare type ItemFilter = {
|
|
12
|
-
type?: OneOrMultiple<string>;
|
|
13
|
-
parent?: ItemID | Item;
|
|
14
|
-
};
|
|
15
|
-
export declare type LinkFilter = {
|
|
16
|
-
type?: OneOrMultiple<string>;
|
|
17
|
-
};
|
|
18
|
-
export declare type Predicate<T extends Entity> = (entity: T) => boolean;
|
|
19
|
-
export declare type RootFilter = ItemIdFilter | ItemFilter | Predicate<Item>;
|
|
20
|
-
export declare type RootSelector<R = void> = (filter?: RootFilter) => Selection<Item<any>, R>;
|
|
21
|
-
/**
|
|
22
|
-
* Controls how deleted items are filtered.
|
|
23
|
-
*/
|
|
24
|
-
export declare enum ItemFilterDeleted {
|
|
25
|
-
/**
|
|
26
|
-
* Do not return deleted items. Default behaviour.
|
|
27
|
-
*/
|
|
28
|
-
HIDE_DELETED = 0,
|
|
29
|
-
/**
|
|
30
|
-
* Return deleted and regular items.
|
|
31
|
-
*/
|
|
32
|
-
SHOW_DELETED = 1,
|
|
33
|
-
/**
|
|
34
|
-
* Return only deleted items.
|
|
35
|
-
*/
|
|
36
|
-
SHOW_DELETED_ONLY = 2
|
|
37
|
-
}
|
|
38
|
-
export declare type QueryOptions = {
|
|
39
|
-
/**
|
|
40
|
-
* Controls how deleted items are filtered.
|
|
41
|
-
*/
|
|
42
|
-
deleted?: ItemFilterDeleted;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Represents where the selection has started.
|
|
46
|
-
*/
|
|
47
|
-
export declare type SelectionRoot = Database | Entity;
|
|
48
|
-
/**
|
|
49
|
-
* Returned from each stage of the visitor.
|
|
50
|
-
*/
|
|
51
|
-
export declare type SelectionContext<T extends Entity, R> = [entities: T[], result?: R];
|
|
52
|
-
/**
|
|
53
|
-
* Visitor callback.
|
|
54
|
-
* The visitor is passed the current entities and result (accumulator),
|
|
55
|
-
* which may be modified and returned.
|
|
56
|
-
*/
|
|
57
|
-
export declare type Callable<T extends Entity, R> = (entities: T[], result: R) => R;
|
|
58
|
-
/**
|
|
59
|
-
* Factory for selector that provides a root set of items.
|
|
60
|
-
* @param itemsProvider
|
|
61
|
-
* @param updateEventProvider
|
|
62
|
-
* @param root
|
|
63
|
-
* @param filter
|
|
64
|
-
* @param value Initial reducer value.
|
|
65
|
-
*/
|
|
66
|
-
export declare const createSelector: <R>(itemsProvider: () => Item[], updateEventProvider: () => Event<Entity[]>, root: SelectionRoot, filter: RootFilter | undefined, value: R) => Selection<Item<any>, R>;
|
|
67
|
-
/**
|
|
68
|
-
* Factory for specific item selector.
|
|
69
|
-
* @param root
|
|
70
|
-
* @param update
|
|
71
|
-
* @param value Initial reducer value.
|
|
72
|
-
*/
|
|
73
|
-
export declare const createItemSelector: <R>(root: Item<any>, update: Event<Entity[]>, value: R) => Selection<Item<any>, R>;
|
|
74
|
-
/**
|
|
75
|
-
* Selections are used to construct database subscriptions.
|
|
76
|
-
* They are [monads](https://www.quora.com/What-are-monads-in-computer-science) that support
|
|
77
|
-
* the functional composition of predicates to traverse the graph.
|
|
78
|
-
* Additionally, selections may be used to create reducers that compute an aggregated value over the traversal.
|
|
79
|
-
*
|
|
80
|
-
* Implementation:
|
|
81
|
-
* Each Selection contains a visitor
|
|
82
|
-
*/
|
|
83
|
-
export declare class Selection<T extends Entity<any>, R = void> {
|
|
84
|
-
private readonly _visitor;
|
|
85
|
-
private readonly _update;
|
|
86
|
-
private readonly _root;
|
|
87
|
-
private readonly _reducer;
|
|
88
|
-
/**
|
|
89
|
-
* @param _visitor Executes the query.
|
|
90
|
-
* @param _update The unfiltered update event.
|
|
91
|
-
* @param _root The root of the selection. Must be a stable reference.
|
|
92
|
-
* @param _reducer
|
|
93
|
-
*/
|
|
94
|
-
constructor(_visitor: (options: QueryOptions) => SelectionContext<T, R>, _update: Event<Entity[]>, _root: SelectionRoot, _reducer?: boolean);
|
|
95
|
-
/**
|
|
96
|
-
* Creates a derrived selection by aplying a mapping function to the result of the current selection.
|
|
97
|
-
*/
|
|
98
|
-
private _createSubSelection;
|
|
99
|
-
/**
|
|
100
|
-
* Finish the selection and return the result.
|
|
101
|
-
*/
|
|
102
|
-
query(options?: QueryOptions): SelectionResult<T, R>;
|
|
103
|
-
/**
|
|
104
|
-
* The root of the selection. Either a database or an item. Must be a stable reference.
|
|
105
|
-
*/
|
|
106
|
-
get root(): SelectionRoot;
|
|
107
|
-
/**
|
|
108
|
-
* Visitor.
|
|
109
|
-
* @param visitor
|
|
110
|
-
*/
|
|
111
|
-
call(visitor: Callable<T, R>): Selection<T, R>;
|
|
112
|
-
/**
|
|
113
|
-
* Filter entities of this selection.
|
|
114
|
-
* @param filter A filter object or a predicate function.
|
|
115
|
-
*/
|
|
116
|
-
filter(this: Selection<Item<any>, R>, filter: ItemFilter): Selection<Item<any>, R>;
|
|
117
|
-
filter<U extends Entity>(this: Selection<U, R>, filter: Predicate<U>): Selection<U, R>;
|
|
118
|
-
/**
|
|
119
|
-
* Select children of the items in this selection.
|
|
120
|
-
*/
|
|
121
|
-
children(this: Selection<Item<any>, R>, filter?: ItemFilter): Selection<Item<any>, R>;
|
|
122
|
-
/**
|
|
123
|
-
* Select parent of the items in this selection.
|
|
124
|
-
*/
|
|
125
|
-
parent(this: Selection<Item<any>, R>): Selection<Item<any>, R>;
|
|
126
|
-
/**
|
|
127
|
-
* Select links sourcing from the items in this selection.
|
|
128
|
-
*/
|
|
129
|
-
links(this: Selection<Item<any>, R>, filter?: LinkFilter): Selection<Link, R>;
|
|
130
|
-
/**
|
|
131
|
-
* Select links pointing to items in this selection.
|
|
132
|
-
*/
|
|
133
|
-
refs(this: Selection<Item<any>, R>, filter?: LinkFilter): Selection<Link, R>;
|
|
134
|
-
/**
|
|
135
|
-
* Select targets of links in this selection.
|
|
136
|
-
*/
|
|
137
|
-
target(this: Selection<Link, R>, filter?: ItemFilter): Selection<Item<any>, R>;
|
|
138
|
-
/**
|
|
139
|
-
* Select sources of links in this selection.
|
|
140
|
-
*/
|
|
141
|
-
source(this: Selection<Link, R>, filter?: ItemFilter): Selection<Item<any>, R>;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Query subscription.
|
|
145
|
-
* Represents a live-query (subscription) that can notify about future updates to the relevant subset of items.
|
|
146
|
-
*/
|
|
147
|
-
export declare class SelectionResult<T extends Entity, R = any> {
|
|
148
|
-
private readonly _execute;
|
|
149
|
-
private readonly _update;
|
|
150
|
-
private readonly _root;
|
|
151
|
-
private readonly _reducer;
|
|
152
|
-
/**
|
|
153
|
-
* Fired when there are updates in the selection.
|
|
154
|
-
* Only update that are relevant to the selection cause the update.
|
|
155
|
-
*/
|
|
156
|
-
readonly update: Event<SelectionResult<T, any>>;
|
|
157
|
-
private _lastResult;
|
|
158
|
-
constructor(_execute: () => SelectionContext<T, R>, _update: Event<Entity[]>, _root: SelectionRoot, _reducer: boolean);
|
|
159
|
-
/**
|
|
160
|
-
* Re-run query.
|
|
161
|
-
*/
|
|
162
|
-
refresh(): this;
|
|
163
|
-
/**
|
|
164
|
-
* The root of the selection. Either a database or an item. Must be a stable reference.
|
|
165
|
-
*/
|
|
166
|
-
get root(): SelectionRoot;
|
|
167
|
-
/**
|
|
168
|
-
* @deprecated
|
|
169
|
-
*/
|
|
170
|
-
/**
|
|
171
|
-
* Get the result of this selection.
|
|
172
|
-
*/
|
|
173
|
-
get entities(): T[];
|
|
174
|
-
/**
|
|
175
|
-
* Returns the selection or reducer result.
|
|
176
|
-
*/
|
|
177
|
-
get value(): R extends void ? T[] : R;
|
|
178
|
-
/**
|
|
179
|
-
* Return the first element if the set has exactly one element.
|
|
180
|
-
*/
|
|
181
|
-
expectOne(): T;
|
|
182
|
-
}
|
|
183
|
-
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/api/selection.ts"],"names":[],"mappings":"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"}
|