@agentshouse/mdruntime 0.1.0-c30ed2b8e04d5 → 0.1.0-c389df724fd2f
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/AGENTS.md +55 -19
- package/README.md +7 -6
- package/dist/adapter.d.ts +30 -2
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +15 -2
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +1 -0
- package/dist/client.d.ts +6 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +35 -0
- package/dist/connection.d.ts +8 -5
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +70 -27
- package/dist/conversation.d.ts +17 -6
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +167 -78
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/memory.d.ts +3 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +20 -1
- package/dist/model.d.ts +10 -6
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +6 -3
- package/dist/paths.d.ts +0 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +0 -16
- package/dist/query.d.ts +1 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +71 -33
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +9 -16
- package/dist/react.d.ts +39 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +63 -0
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +102 -46
- package/dist/replica.d.ts +3 -3
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +4 -3
- package/dist/rows.d.ts +2 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +75 -38
- package/dist/save.d.ts +1 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +89 -45
- package/dist/store.d.ts +5 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +13 -2
- package/dist/wire.d.ts +2 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +2 -0
- package/package.json +14 -2
package/dist/query.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { pointerFacts, } from '@agentshouse/mdmodel';
|
|
2
|
+
import { referenceField } from './model.js';
|
|
1
3
|
import { normalize } from './paths.js';
|
|
2
4
|
export class QueryError extends Error {
|
|
3
5
|
constructor(code, at, problem) {
|
|
@@ -11,6 +13,7 @@ const RELATED = ['types', 'where', 'pathPrefix', 'field'];
|
|
|
11
13
|
const PARTS = ['fields', 'sections', 'preamble', 'markdown', 'backlinks', 'change'];
|
|
12
14
|
const ORDER = ['by', 'direction', 'nulls', 'stringSort', 'locale', 'localeOptions'];
|
|
13
15
|
const CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
16
|
+
const STRAY_ESCAPE = /~(?![01])/u;
|
|
14
17
|
export function invalid(at, problem) {
|
|
15
18
|
throw new QueryError('invalid-query', at, problem);
|
|
16
19
|
}
|
|
@@ -68,23 +71,29 @@ function calendarDate(value) {
|
|
|
68
71
|
const date = new Date(Date.UTC(year, month - 1, day));
|
|
69
72
|
return (date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day);
|
|
70
73
|
}
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
function itemOf(facts) {
|
|
75
|
+
return facts.type === 'array' ? facts.items : facts;
|
|
76
|
+
}
|
|
77
|
+
function fits(facts, value) {
|
|
78
|
+
const item = itemOf(facts);
|
|
79
|
+
if (item?.type === undefined)
|
|
80
|
+
return true;
|
|
81
|
+
if (item.values !== undefined)
|
|
82
|
+
return item.values.includes(value);
|
|
83
|
+
if (item.type === 'number')
|
|
74
84
|
return typeof value === 'number';
|
|
75
|
-
if (
|
|
85
|
+
if (item.type === 'integer')
|
|
86
|
+
return Number.isSafeInteger(value);
|
|
87
|
+
if (item.type === 'boolean')
|
|
88
|
+
return typeof value === 'boolean';
|
|
89
|
+
if (item.type !== 'string' || typeof value !== 'string')
|
|
76
90
|
return false;
|
|
77
|
-
if (item.
|
|
78
|
-
return item.values.includes(value);
|
|
79
|
-
if (item.kind === 'date')
|
|
80
|
-
return calendarDate(value);
|
|
81
|
-
if (item.kind === 'reference')
|
|
91
|
+
if (item.reference !== undefined)
|
|
82
92
|
return value !== '' && normalize(value) === value;
|
|
93
|
+
if (item.format === 'date')
|
|
94
|
+
return calendarDate(value);
|
|
83
95
|
return true;
|
|
84
96
|
}
|
|
85
|
-
function reference(spec) {
|
|
86
|
-
return spec.kind === 'reference' || (spec.kind === 'list' && spec.of.kind === 'reference');
|
|
87
|
-
}
|
|
88
97
|
function typing(facts, rooms, types, at) {
|
|
89
98
|
const read = rooms === null ? facts.rooms : facts.rooms.filter((room) => rooms.includes(room.locator));
|
|
90
99
|
const acquiring = !facts.listed &&
|
|
@@ -102,22 +111,46 @@ function typing(facts, rooms, types, at) {
|
|
|
102
111
|
types: types === null ? declared : declared.filter((type) => types.includes(type.name)),
|
|
103
112
|
};
|
|
104
113
|
}
|
|
105
|
-
function
|
|
106
|
-
|
|
114
|
+
function pointer(input, at) {
|
|
115
|
+
if (typeof input !== 'string' || !input.startsWith('/') || STRAY_ESCAPE.test(input)) {
|
|
116
|
+
invalid(at, 'expects a JSON Pointer');
|
|
117
|
+
}
|
|
118
|
+
return input;
|
|
119
|
+
}
|
|
120
|
+
function specs(typed, input, at) {
|
|
121
|
+
const field = pointer(input, at);
|
|
122
|
+
const declared = typed.types.flatMap((type) => {
|
|
123
|
+
const spec = pointerFacts(type, field);
|
|
124
|
+
return spec === undefined ? [] : [spec];
|
|
125
|
+
});
|
|
107
126
|
if (declared.length === 0 && !typed.untyped) {
|
|
108
127
|
throw new QueryError('unknown-field', at, `no MD Type it reads declares ${field}`);
|
|
109
128
|
}
|
|
110
|
-
|
|
129
|
+
if (!declared.some((spec) => spec.conditional))
|
|
130
|
+
return declared;
|
|
131
|
+
return declared.map((spec) => ({
|
|
132
|
+
facts: { prose: false },
|
|
133
|
+
through: several(spec),
|
|
134
|
+
conditional: true,
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
function several(spec) {
|
|
138
|
+
return spec.through || spec.facts.type === 'array';
|
|
139
|
+
}
|
|
140
|
+
function single(spec) {
|
|
141
|
+
return spec.facts.type !== undefined && spec.facts.type !== 'array';
|
|
142
|
+
}
|
|
143
|
+
function every(declared, holds) {
|
|
144
|
+
return declared.length > 0 && declared.every(holds);
|
|
111
145
|
}
|
|
112
146
|
function kind(declared, checked, at) {
|
|
113
|
-
if (checked === null ||
|
|
147
|
+
if (checked === null ||
|
|
148
|
+
declared.length === 0 ||
|
|
149
|
+
declared.some((spec) => fits(spec.facts, checked))) {
|
|
114
150
|
return;
|
|
115
151
|
}
|
|
116
152
|
throw new QueryError('wrong-kind', at, `${JSON.stringify(checked)} is not of its field's kind`);
|
|
117
153
|
}
|
|
118
|
-
function listed(declared, list) {
|
|
119
|
-
return declared.length > 0 && declared.every((spec) => (spec.kind === 'list') === list);
|
|
120
|
-
}
|
|
121
154
|
function test(declared, input, at) {
|
|
122
155
|
if (!plain(input)) {
|
|
123
156
|
const equal = value(input, at);
|
|
@@ -131,8 +164,11 @@ function test(declared, input, at) {
|
|
|
131
164
|
const stray = operators.find((operator) => !RANGE.includes(operator));
|
|
132
165
|
if (stray !== undefined)
|
|
133
166
|
invalid(place(at, stray), 'cannot join a range');
|
|
134
|
-
if (
|
|
167
|
+
if (every(declared, (spec) => spec.facts.type === 'array'))
|
|
135
168
|
invalid(at, 'a range on a list');
|
|
169
|
+
if (every(declared, (spec) => spec.facts.type === 'boolean' || spec.facts.type === 'object')) {
|
|
170
|
+
throw new QueryError('wrong-kind', at, 'its field does not compare in order');
|
|
171
|
+
}
|
|
136
172
|
return {
|
|
137
173
|
op: 'range',
|
|
138
174
|
bounds: RANGE.filter((operator) => operators.includes(operator)).map((operator) => {
|
|
@@ -165,7 +201,7 @@ function test(declared, input, at) {
|
|
|
165
201
|
return { op: 'nin', values: compared };
|
|
166
202
|
if (compared.includes(null))
|
|
167
203
|
invalid(where, 'a list holds no null');
|
|
168
|
-
if (
|
|
204
|
+
if (every(declared, single))
|
|
169
205
|
invalid(where, 'the field is not a list');
|
|
170
206
|
return { op: 'all', values: compared };
|
|
171
207
|
}
|
|
@@ -173,7 +209,7 @@ function test(declared, input, at) {
|
|
|
173
209
|
if (!Number.isSafeInteger(operand) || operand < 0) {
|
|
174
210
|
invalid(where, 'expects a nonnegative integer');
|
|
175
211
|
}
|
|
176
|
-
if (
|
|
212
|
+
if (every(declared, single))
|
|
177
213
|
invalid(where, 'the field is not a list');
|
|
178
214
|
return { op: 'size', size: operand };
|
|
179
215
|
}
|
|
@@ -186,7 +222,7 @@ function condition(typed, input, at) {
|
|
|
186
222
|
invalid(at, 'expects an object of field predicates');
|
|
187
223
|
const conditions = [];
|
|
188
224
|
for (const name of Object.keys(input).sort()) {
|
|
189
|
-
const where = place(at, name);
|
|
225
|
+
const where = name.startsWith('/') ? `${at}${name}` : place(at, name);
|
|
190
226
|
const entry = input[name];
|
|
191
227
|
if (name === '$and' || name === '$or') {
|
|
192
228
|
const nested = list(entry, where).map((item, index) => condition(typed, item, `${where}[${index}]`));
|
|
@@ -215,19 +251,19 @@ function scope(facts, rooms, input, at) {
|
|
|
215
251
|
pathPrefix: input.pathPrefix === undefined ? null : directory(input.pathPrefix, place(at, 'pathPrefix')),
|
|
216
252
|
};
|
|
217
253
|
}
|
|
218
|
-
function
|
|
219
|
-
if (typeof field !== 'string')
|
|
220
|
-
invalid(at, 'expects a field name');
|
|
254
|
+
function referenceName(typed, field, at) {
|
|
221
255
|
const declared = specs(typed, field, at);
|
|
222
|
-
if (declared.length > 0 &&
|
|
256
|
+
if (declared.length > 0 &&
|
|
257
|
+
!declared.some((spec) => spec.conditional || referenceField(spec.facts))) {
|
|
223
258
|
invalid(at, 'not a reference field');
|
|
259
|
+
}
|
|
224
260
|
return field;
|
|
225
261
|
}
|
|
226
262
|
function hopOf(facts, rooms, root, input) {
|
|
227
263
|
if (!plain(input))
|
|
228
264
|
invalid('hop', 'expects an object');
|
|
229
265
|
known(input, RELATED, 'hop');
|
|
230
|
-
const field =
|
|
266
|
+
const field = referenceName(root, input.field, 'hop.field');
|
|
231
267
|
const { types, where, pathPrefix } = scope(facts, rooms, input, 'hop');
|
|
232
268
|
return { types, where, pathPrefix, field };
|
|
233
269
|
}
|
|
@@ -236,14 +272,16 @@ function backlinksOf(facts, rooms, input) {
|
|
|
236
272
|
invalid('backlinks', 'expects an object');
|
|
237
273
|
known(input, RELATED, 'backlinks');
|
|
238
274
|
const { typed, types, where, pathPrefix } = scope(facts, rooms, input, 'backlinks');
|
|
239
|
-
const field = input.field === undefined ? null :
|
|
275
|
+
const field = input.field === undefined ? null : referenceName(typed, input.field, 'backlinks.field');
|
|
240
276
|
return { types, where, pathPrefix, field };
|
|
241
277
|
}
|
|
242
278
|
function keyPlan(typed, input, at, path) {
|
|
243
279
|
if (input === 'room' || input === 'type' || (path && input === 'path'))
|
|
244
280
|
return { of: input };
|
|
245
|
-
if (plain(input) &&
|
|
246
|
-
specs(typed, input.field, place(at, 'field'))
|
|
281
|
+
if (plain(input) && Object.hasOwn(input, 'field') && Object.keys(input).length === 1) {
|
|
282
|
+
if (specs(typed, input.field, place(at, 'field')).some(several)) {
|
|
283
|
+
invalid(place(at, 'field'), 'a path that can hold several values');
|
|
284
|
+
}
|
|
247
285
|
return { of: 'field', field: input.field };
|
|
248
286
|
}
|
|
249
287
|
return invalid(at, path ? 'expects room, path, type or a field' : 'expects room, type or a field');
|
|
@@ -301,10 +339,10 @@ function parts(typed, input, at, fields) {
|
|
|
301
339
|
return 'all';
|
|
302
340
|
const named = list(input, at);
|
|
303
341
|
named.forEach((name, index) => {
|
|
304
|
-
if (typeof name !== 'string')
|
|
305
|
-
invalid(`${at}[${index}]`, 'expects a name');
|
|
306
342
|
if (fields)
|
|
307
343
|
specs(typed, name, `${at}[${index}]`);
|
|
344
|
+
else if (typeof name !== 'string')
|
|
345
|
+
invalid(`${at}[${index}]`, 'expects a name');
|
|
308
346
|
});
|
|
309
347
|
return named;
|
|
310
348
|
}
|
package/dist/reach.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,SAAS,
|
|
1
|
+
{"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,SAAS,EAAe,YAAY,EAAc,MAAM,iBAAiB,CAAC;AAMjG,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAEjD,MAAM,MAAM,KAAK,GAAG,CAClB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,OAAO,KACb,MAAM,IAAI,CAAC;AAEhB,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG;IAAE,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;CAAE,CAAC;AAEnF,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG;IACpC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IACpD,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACxE,CAAC;AA2BF,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAMpE;AAMD,wBAAgB,OAAO,CACrB,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,IAAI,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE;QAAE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,GAC/F;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAU/D;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CASnE;AA8ED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,YAAY,CAgKlF"}
|
package/dist/reach.js
CHANGED
|
@@ -62,22 +62,7 @@ export function planReach(reach) {
|
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
function roomsWithin(reach, rooms) {
|
|
65
|
-
|
|
66
|
-
return rooms;
|
|
67
|
-
return rooms
|
|
68
|
-
.filter((room) => holds(reach, room.locator))
|
|
69
|
-
.map((room) => {
|
|
70
|
-
if (wholly(reach, room.locator))
|
|
71
|
-
return room;
|
|
72
|
-
const governed = governs(reach, room);
|
|
73
|
-
return {
|
|
74
|
-
...room,
|
|
75
|
-
model: governed.collection ? room.model : modelTypes(NO_MODEL),
|
|
76
|
-
typedSelection: governed.selection ? room.typedSelection : null,
|
|
77
|
-
roomVersion: null,
|
|
78
|
-
attachments: [],
|
|
79
|
-
};
|
|
80
|
-
});
|
|
65
|
+
return rooms.filter((room) => wholly(reach, room.locator));
|
|
81
66
|
}
|
|
82
67
|
function typesWithin(reach, room, types) {
|
|
83
68
|
if (room === undefined)
|
|
@@ -201,6 +186,14 @@ export function narrowed(runtime, given) {
|
|
|
201
186
|
return () => { };
|
|
202
187
|
});
|
|
203
188
|
}
|
|
189
|
+
if (topic === 'conversations') {
|
|
190
|
+
return following(() => {
|
|
191
|
+
if (conversing(reach))
|
|
192
|
+
return watch(topic, input, deliver);
|
|
193
|
+
deliver([]);
|
|
194
|
+
return () => { };
|
|
195
|
+
});
|
|
196
|
+
}
|
|
204
197
|
return watch(topic, input, deliver);
|
|
205
198
|
};
|
|
206
199
|
const conversation = () => (conversing(reach) ? md.conversation : NO_CONVERSATION);
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { MdRuntimeClient } from './client.js';
|
|
2
|
+
import type { AppRoom, ConnectionRefusal, SaveResult } from './connection.js';
|
|
3
|
+
import type { Member, ServiceMode } from './adapter.js';
|
|
4
|
+
import type { ConversationEntry, ConversationOptions, ConversationView } from './conversation.js';
|
|
5
|
+
import type { QueueEntry } from './outcome.js';
|
|
6
|
+
import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult } from './query.js';
|
|
7
|
+
import type { RoomDraft, RoomDraftParts } from './room-draft.js';
|
|
8
|
+
import type { SyncStatus } from './status.js';
|
|
9
|
+
type Client = MdRuntimeClient | null;
|
|
10
|
+
export type Observed<T> = {
|
|
11
|
+
readonly state: 'loading';
|
|
12
|
+
} | {
|
|
13
|
+
readonly state: 'ready';
|
|
14
|
+
readonly value: T;
|
|
15
|
+
};
|
|
16
|
+
export declare function useObserve(client: Client, topic: 'deployment-facts'): Observed<unknown>;
|
|
17
|
+
export declare function useObserve(client: Client, topic: 'rooms'): Observed<readonly AppRoom[]>;
|
|
18
|
+
export declare function useObserve(client: Client, topic: 'connection-refusal'): Observed<ConnectionRefusal | null>;
|
|
19
|
+
export declare function useObserve(client: Client, topic: 'storage-loss'): Observed<string | null>;
|
|
20
|
+
export declare function useObserve(client: Client, topic: 'sync-status'): Observed<SyncStatus>;
|
|
21
|
+
export declare function useObserve(client: Client, topic: 'service-mode'): Observed<ServiceMode>;
|
|
22
|
+
export declare function useObserve(client: Client, topic: 'member'): Observed<Member | null>;
|
|
23
|
+
export declare function useObserve(client: Client, topic: 'query', query: DocumentQuery): Observed<DocumentResult>;
|
|
24
|
+
export declare function useObserve(client: Client, topic: 'query', query: GroupQuery): Observed<GroupResult>;
|
|
25
|
+
export declare function useObserve(client: Client, topic: 'queue', locator: string): Observed<readonly QueueEntry[]>;
|
|
26
|
+
export declare function useObserve(client: Client, topic: 'room-drafts'): Observed<readonly RoomDraft[]>;
|
|
27
|
+
export declare function useObserve(client: Client, topic: 'presentation'): Observed<unknown>;
|
|
28
|
+
export declare function useObserve(client: Client, topic: 'conversation', conversation: string, options: ConversationOptions): Observed<ConversationView>;
|
|
29
|
+
export declare function useObserve(client: Client, topic: 'conversations'): Observed<readonly ConversationEntry[]>;
|
|
30
|
+
export type Saving = {
|
|
31
|
+
readonly busy: boolean;
|
|
32
|
+
readonly outcome: SaveResult | null;
|
|
33
|
+
readonly failure: Error | null;
|
|
34
|
+
save(room: string, roomDrafts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
|
|
35
|
+
};
|
|
36
|
+
export declare function saveRoomDrafts(client: MdRuntimeClient, room: string, roomDrafts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
|
|
37
|
+
export declare function useSave(client: MdRuntimeClient): Saving;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
|
2
|
+
const LOADING = { state: 'loading' };
|
|
3
|
+
export function useObserve(client, topic, ...input) {
|
|
4
|
+
const key = JSON.stringify([topic, ...input]);
|
|
5
|
+
const [held, setHeld] = useState(null);
|
|
6
|
+
const opened = useRef(input);
|
|
7
|
+
opened.current = input;
|
|
8
|
+
useLayoutEffect(() => {
|
|
9
|
+
if (client === null)
|
|
10
|
+
return;
|
|
11
|
+
let live = true;
|
|
12
|
+
let observation = null;
|
|
13
|
+
const observe = client.observe;
|
|
14
|
+
void observe(topic, ...opened.current).then((open) => {
|
|
15
|
+
if (!live) {
|
|
16
|
+
open.close();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
observation = open;
|
|
20
|
+
const take = (value) => {
|
|
21
|
+
if (live)
|
|
22
|
+
setHeld({ client, key, observed: { state: 'ready', value } });
|
|
23
|
+
};
|
|
24
|
+
take(open.current());
|
|
25
|
+
open.subscribe(take);
|
|
26
|
+
});
|
|
27
|
+
return () => {
|
|
28
|
+
live = false;
|
|
29
|
+
observation?.close();
|
|
30
|
+
};
|
|
31
|
+
}, [client, key]);
|
|
32
|
+
return held !== null && held.client === client && held.key === key ? held.observed : LOADING;
|
|
33
|
+
}
|
|
34
|
+
const IDLE = { busy: false, outcome: null, failure: null };
|
|
35
|
+
export async function saveRoomDrafts(client, room, roomDrafts) {
|
|
36
|
+
const kept = [];
|
|
37
|
+
for (const [path, parts] of roomDrafts) {
|
|
38
|
+
const prior = await client.roomDraft.read(room, path);
|
|
39
|
+
const write = await client.roomDraft.write(room, path, prior?.revision ?? null, parts);
|
|
40
|
+
if (write.outcome !== 'written' || write.roomDraft === null) {
|
|
41
|
+
throw new Error(`the Room Draft at ${path} was not written`);
|
|
42
|
+
}
|
|
43
|
+
kept.push({ path, revision: write.roomDraft.revision });
|
|
44
|
+
}
|
|
45
|
+
return client.save(room, kept);
|
|
46
|
+
}
|
|
47
|
+
export function useSave(client) {
|
|
48
|
+
const [state, setState] = useState(IDLE);
|
|
49
|
+
const save = useCallback(async (room, roomDrafts) => {
|
|
50
|
+
setState({ busy: true, outcome: null, failure: null });
|
|
51
|
+
try {
|
|
52
|
+
const outcome = await saveRoomDrafts(client, room, roomDrafts);
|
|
53
|
+
setState({ busy: false, outcome, failure: null });
|
|
54
|
+
return outcome;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
58
|
+
setState({ busy: false, outcome: null, failure });
|
|
59
|
+
throw failure;
|
|
60
|
+
}
|
|
61
|
+
}, [client]);
|
|
62
|
+
return { ...state, save };
|
|
63
|
+
}
|
package/dist/read-side.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-side.d.ts","sourceRoot":"","sources":["../src/read-side.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"read-side.d.ts","sourceRoot":"","sources":["../src/read-side.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAU,KAAK,WAAW,EAAE,KAAK,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC3F,OAAO,KAAK,EAOV,IAAI,EAIJ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAuDpD,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,KAAK,CACH,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,KAAK,IAAI,GACpD,MAAM,IAAI,CAAC;IACd,SAAS,IAAI,SAAS,gBAAgB,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC9D,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AA+UF,wBAAgB,UAAU,CACxB,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,WAAW,GAChB;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG,IAAI,CA4BpD;AAED,wBAAgB,cAAc,IAAI,QAAQ,CA4HzC"}
|
package/dist/read-side.js
CHANGED
|
@@ -1,54 +1,58 @@
|
|
|
1
|
-
import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq,
|
|
1
|
+
import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq, inArray, or, toArray, } from '@tanstack/db';
|
|
2
|
+
import { ARRAY_INDEX, pointerSegments } from '@agentshouse/mdmodel';
|
|
2
3
|
import { rowsOf } from './observation.js';
|
|
3
4
|
import { documentKey } from './rows.js';
|
|
4
5
|
function every(expressions) {
|
|
5
6
|
const [first, second, ...rest] = expressions;
|
|
6
7
|
return second === undefined ? first : and(first, second, ...rest);
|
|
7
8
|
}
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
return second === undefined ? first : or(first, second, ...rest);
|
|
9
|
+
function same(held, value) {
|
|
10
|
+
return Array.isArray(held) ? held.includes(value) : held === value;
|
|
11
11
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
12
|
+
function ordered(held, [operator, bound]) {
|
|
13
|
+
if (typeof held !== typeof bound || held === null || typeof held === 'object')
|
|
14
|
+
return false;
|
|
15
|
+
const left = held;
|
|
16
|
+
const right = bound;
|
|
17
|
+
if (operator === 'gt')
|
|
18
|
+
return left > right;
|
|
19
|
+
if (operator === 'gte')
|
|
20
|
+
return left >= right;
|
|
21
|
+
if (operator === 'lt')
|
|
22
|
+
return left < right;
|
|
23
|
+
return left <= right;
|
|
14
24
|
}
|
|
15
|
-
function
|
|
25
|
+
function satisfied(test, held) {
|
|
16
26
|
if (test.op === 'eq')
|
|
17
|
-
return
|
|
18
|
-
if (test.op === 'ne')
|
|
19
|
-
return test.value
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const compare = { gt, gte, lt, lte };
|
|
37
|
-
return every(test.bounds.map(([operator, bound]) => compare[operator](field, bound)));
|
|
38
|
-
}
|
|
39
|
-
if (test.op === 'all') {
|
|
40
|
-
return every([not(isUndefined(size)), ...test.values.map((value) => inArray(value, field))]);
|
|
41
|
-
}
|
|
42
|
-
if (test.op === 'size')
|
|
43
|
-
return eq(size, test.size);
|
|
44
|
-
return test.exists ? not(isUndefined(written)) : isUndefined(written);
|
|
27
|
+
return same(held, test.value);
|
|
28
|
+
if (test.op === 'ne')
|
|
29
|
+
return !same(held, test.value);
|
|
30
|
+
if (test.op === 'in')
|
|
31
|
+
return test.values.some((value) => same(held, value));
|
|
32
|
+
if (test.op === 'nin')
|
|
33
|
+
return !test.values.some((value) => same(held, value));
|
|
34
|
+
if (test.op === 'range')
|
|
35
|
+
return test.bounds.every((bound) => ordered(held, bound));
|
|
36
|
+
if (test.op === 'all')
|
|
37
|
+
return Array.isArray(held) && test.values.every((value) => same(held, value));
|
|
38
|
+
return Array.isArray(held) && held.length === test.size;
|
|
39
|
+
}
|
|
40
|
+
function tested(test, reached) {
|
|
41
|
+
if (test.op === 'exists')
|
|
42
|
+
return test.exists === (reached !== undefined);
|
|
43
|
+
if (reached === undefined)
|
|
44
|
+
return test.op === 'ne' || test.op === 'nin';
|
|
45
|
+
return reached.some((held) => satisfied(test, held));
|
|
45
46
|
}
|
|
46
47
|
function conditioned(condition, row) {
|
|
47
48
|
if ('every' in condition)
|
|
48
|
-
return
|
|
49
|
+
return condition.every.every((item) => conditioned(item, row));
|
|
49
50
|
if ('some' in condition)
|
|
50
|
-
return
|
|
51
|
-
return tested(condition.test, row.
|
|
51
|
+
return condition.some.some((item) => conditioned(item, row));
|
|
52
|
+
return tested(condition.test, row.reached[condition.field]);
|
|
53
|
+
}
|
|
54
|
+
function narrowed(query, where, alias) {
|
|
55
|
+
return where === null ? query : query.fn.where((row) => conditioned(where, row[alias]));
|
|
52
56
|
}
|
|
53
57
|
function reached(reach, room, document) {
|
|
54
58
|
return reach === null
|
|
@@ -62,7 +66,6 @@ function scoped(scope, row, rooms, reach) {
|
|
|
62
66
|
...reached(reach, row.room, row.key),
|
|
63
67
|
...(scope.types === null ? [] : [inArray(row.type, [...scope.types])]),
|
|
64
68
|
...(scope.pathPrefix === null ? [] : [inArray(scope.pathPrefix, row.directories)]),
|
|
65
|
-
...(scope.where === null ? [] : [conditioned(scope.where, row)]),
|
|
66
69
|
]);
|
|
67
70
|
}
|
|
68
71
|
function keyed(key, row) {
|
|
@@ -77,16 +80,17 @@ function live(query) {
|
|
|
77
80
|
function related(q, rows, scope, field, kept, reach) {
|
|
78
81
|
const matched = kept === 'source' ? 'target' : 'source';
|
|
79
82
|
const from = q.from({ r: rows });
|
|
80
|
-
|
|
81
|
-
.where(({ r }) => every([eq(r.kind, 'reference'), ...(field === null ? [] : [
|
|
83
|
+
const joined = from
|
|
84
|
+
.where(({ r }) => every([eq(r.kind, 'reference'), ...(field === null ? [] : [inArray(field, r.forms)])]))
|
|
82
85
|
.innerJoin({ m: rows }, ({ r, m }) => eq(r[matched], m.key))
|
|
83
|
-
.where(({ m }) => scoped(scope, m, null, reach))
|
|
86
|
+
.where(({ m }) => scoped(scope, m, null, reach));
|
|
87
|
+
return narrowed(joined, scope.where, 'm')
|
|
84
88
|
.groupBy(({ r }) => r[kept])
|
|
85
89
|
.select(({ r }) => ({ key: r[kept] }));
|
|
86
90
|
}
|
|
87
91
|
function filtered(q, rows, plan) {
|
|
88
92
|
const from = q.from({ d: rows });
|
|
89
|
-
let query = from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach));
|
|
93
|
+
let query = narrowed(from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach)), plan.root.where, 'd');
|
|
90
94
|
if (plan.hop !== null) {
|
|
91
95
|
const hop = related(q, rows, plan.hop, plan.hop.field, 'source', plan.reach);
|
|
92
96
|
query = query.innerJoin({ h: hop }, ({ d, h }) => eq(d.key, h.key));
|
|
@@ -117,8 +121,7 @@ function documents(q, rows, plan, shape) {
|
|
|
117
121
|
room: d.room,
|
|
118
122
|
path: d.path,
|
|
119
123
|
type: d.type,
|
|
120
|
-
...(shape.fields ===
|
|
121
|
-
...(Array.isArray(shape.fields) ? named('field', shape.fields, d.fields) : {}),
|
|
124
|
+
...(shape.fields === null ? {} : { fields: d.fields }),
|
|
122
125
|
...(shape.sections === 'all' ? { sections: b.sections } : {}),
|
|
123
126
|
...(Array.isArray(shape.sections) ? named('section', shape.sections, b.sections) : {}),
|
|
124
127
|
...(shape.preamble ? { preamble: b.preamble } : {}),
|
|
@@ -176,6 +179,55 @@ function part(row, prefix, names, whole) {
|
|
|
176
179
|
return whole;
|
|
177
180
|
return present(names.map((name, index) => [name, row[`${prefix}${index}`]]));
|
|
178
181
|
}
|
|
182
|
+
function masked(pointers) {
|
|
183
|
+
const root = { whole: false, members: new Map() };
|
|
184
|
+
for (const pointer of pointers) {
|
|
185
|
+
let mask = root;
|
|
186
|
+
for (const token of pointerSegments(pointer)) {
|
|
187
|
+
const next = mask.members.get(token) ?? { whole: false, members: new Map() };
|
|
188
|
+
mask.members.set(token, next);
|
|
189
|
+
mask = next;
|
|
190
|
+
}
|
|
191
|
+
mask.whole = true;
|
|
192
|
+
}
|
|
193
|
+
return root;
|
|
194
|
+
}
|
|
195
|
+
function merged(left, right) {
|
|
196
|
+
if (left === undefined)
|
|
197
|
+
return right;
|
|
198
|
+
const members = new Map(left.members);
|
|
199
|
+
for (const [token, mask] of right.members)
|
|
200
|
+
members.set(token, merged(members.get(token), mask));
|
|
201
|
+
return { whole: left.whole || right.whole, members };
|
|
202
|
+
}
|
|
203
|
+
function cut(value, mask) {
|
|
204
|
+
if (mask.whole)
|
|
205
|
+
return value;
|
|
206
|
+
if (Array.isArray(value)) {
|
|
207
|
+
const each = {
|
|
208
|
+
whole: false,
|
|
209
|
+
members: new Map([...mask.members].filter(([token]) => !ARRAY_INDEX.test(token))),
|
|
210
|
+
};
|
|
211
|
+
const kept = [];
|
|
212
|
+
value.forEach((item, index) => {
|
|
213
|
+
const part = cut(item, merged(mask.members.get(String(index)), each));
|
|
214
|
+
if (part !== undefined)
|
|
215
|
+
kept[index] = part;
|
|
216
|
+
});
|
|
217
|
+
return kept.length === 0 ? undefined : kept;
|
|
218
|
+
}
|
|
219
|
+
if (typeof value !== 'object' || value === null)
|
|
220
|
+
return undefined;
|
|
221
|
+
const kept = Object.entries(value).flatMap(([key, held]) => {
|
|
222
|
+
const member = mask.members.get(key);
|
|
223
|
+
const part = member === undefined ? undefined : cut(held, member);
|
|
224
|
+
return part === undefined ? [] : [[key, part]];
|
|
225
|
+
});
|
|
226
|
+
return kept.length === 0 ? undefined : Object.fromEntries(kept);
|
|
227
|
+
}
|
|
228
|
+
function selected(fields, pointers) {
|
|
229
|
+
return (cut(fields, masked(pointers)) ?? {});
|
|
230
|
+
}
|
|
179
231
|
function documentOf(row, shape) {
|
|
180
232
|
if (row.type === null)
|
|
181
233
|
return { room: row.room, path: row.path };
|
|
@@ -185,7 +237,11 @@ function documentOf(row, shape) {
|
|
|
185
237
|
type: row.type,
|
|
186
238
|
...(shape.fields === null
|
|
187
239
|
? {}
|
|
188
|
-
: {
|
|
240
|
+
: {
|
|
241
|
+
fields: shape.fields === 'all'
|
|
242
|
+
? row.fields
|
|
243
|
+
: selected(row.fields, shape.fields),
|
|
244
|
+
}),
|
|
189
245
|
...(shape.sections === null
|
|
190
246
|
? {}
|
|
191
247
|
: {
|
package/dist/replica.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ChangeBatch } from './change.js';
|
|
2
2
|
import { type Collection, type Composition } from './collection.js';
|
|
3
3
|
import { type Layer } from './overlay.js';
|
|
4
|
-
import type { RoomAttachment } from './adapter.js';
|
|
4
|
+
import type { HeadChange, RoomAttachment } from './adapter.js';
|
|
5
5
|
import type { ReplicaRecord } from './store.js';
|
|
6
6
|
import type { Refused } from './transfer.js';
|
|
7
7
|
export type ConfirmedLayer = {
|
|
@@ -35,9 +35,9 @@ export declare function readStaged(record: ReplicaRecord, previous?: ConfirmedLa
|
|
|
35
35
|
export declare function readReclassified(record: ReplicaRecord, previous: ConfirmedLayer): Staged | {
|
|
36
36
|
kind: 'deferred';
|
|
37
37
|
};
|
|
38
|
-
export declare function applyReturned(confirmed: ConfirmedLayer, documents: Readonly<Record<string, string>>, revisions: Readonly<Record<string, string>>, removals: readonly string[], attachments: readonly RoomAttachment[] | undefined, roomVersion: string, writtenAt: string): Staged;
|
|
38
|
+
export declare function applyReturned(confirmed: ConfirmedLayer, documents: Readonly<Record<string, string>>, revisions: Readonly<Record<string, string>>, changes: Readonly<Record<string, HeadChange>>, removals: readonly string[], attachments: readonly RoomAttachment[] | undefined, roomVersion: string, writtenAt: string): Staged;
|
|
39
39
|
export declare function replicaOf(confirmed: ConfirmedLayer, queue: readonly ChangeBatch[], previous?: Replica): Replica;
|
|
40
|
-
export declare function landed(batch: ChangeBatch, confirmed: ConfirmedLayer): boolean;
|
|
40
|
+
export declare function landed(batch: ChangeBatch, confirmed: ConfirmedLayer, current?: Readonly<Record<string, string>>): boolean;
|
|
41
41
|
export declare function withdrawals(confirmed: ConfirmedLayer, queue: readonly ChangeBatch[], withdrawable: (batch: ChangeBatch) => boolean): readonly ChangeBatch[];
|
|
42
42
|
export {};
|
|
43
43
|
//# sourceMappingURL=replica.d.ts.map
|
package/dist/replica.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replica.d.ts","sourceRoot":"","sources":["../src/replica.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,WAAW,EAAqB,MAAM,aAAa,CAAC;AAC1F,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAA0C,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAGlF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"replica.d.ts","sourceRoot":"","sources":["../src/replica.ts"],"names":[],"mappings":"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"}
|
package/dist/replica.js
CHANGED
|
@@ -46,7 +46,7 @@ export function readReclassified(record, previous) {
|
|
|
46
46
|
? { kind: 'deferred' }
|
|
47
47
|
: { kind: 'refused', refusal: verdict };
|
|
48
48
|
}
|
|
49
|
-
export function applyReturned(confirmed, documents, revisions, removals, attachments, roomVersion, writtenAt) {
|
|
49
|
+
export function applyReturned(confirmed, documents, revisions, changes, removals, attachments, roomVersion, writtenAt) {
|
|
50
50
|
const nextDocuments = { ...confirmed.record.documents, ...documents };
|
|
51
51
|
const nextRevisions = { ...confirmed.record.revisions, ...revisions };
|
|
52
52
|
const nextChanges = { ...confirmed.record.changes };
|
|
@@ -59,6 +59,7 @@ export function applyReturned(confirmed, documents, revisions, removals, attachm
|
|
|
59
59
|
if (confirmed.record.revisions[path] !== revision)
|
|
60
60
|
delete nextChanges[path];
|
|
61
61
|
}
|
|
62
|
+
Object.assign(nextChanges, changes);
|
|
62
63
|
for (const path of removals) {
|
|
63
64
|
delete nextDocuments[path];
|
|
64
65
|
delete nextRevisions[path];
|
|
@@ -229,8 +230,8 @@ function after(changes, index, path) {
|
|
|
229
230
|
}
|
|
230
231
|
return at;
|
|
231
232
|
}
|
|
232
|
-
export function landed(batch, confirmed) {
|
|
233
|
-
const layer = confirmed.record;
|
|
233
|
+
export function landed(batch, confirmed, current = {}) {
|
|
234
|
+
const layer = { ...confirmed.record, documents: { ...confirmed.record.documents, ...current } };
|
|
234
235
|
return batch.changes.every((change, index) => {
|
|
235
236
|
if (change.kind === 'replace' || (change.kind === 'create' && 'content' in change)) {
|
|
236
237
|
const at = after(batch.changes, index, change.path);
|