@agentshouse/mdruntime 0.1.0-c8c4b020a3ec7 → 0.1.0-c967d1ca66fee
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 +94 -33
- package/README.md +10 -10
- package/dist/adapter.d.ts +92 -46
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +1 -9
- package/dist/attached-model.d.ts +11 -0
- package/dist/attached-model.d.ts.map +1 -0
- package/dist/attached-model.js +47 -0
- package/dist/bootstrap.d.ts +20 -6
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +89 -35
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +13 -7
- package/dist/change.d.ts +4 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/client.d.ts +8 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +57 -24
- package/dist/collection.d.ts +6 -11
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +56 -19
- package/dist/connection.d.ts +20 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +711 -587
- package/dist/conversation.d.ts +23 -11
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +252 -106
- package/dist/failure.d.ts +13 -0
- package/dist/failure.d.ts.map +1 -0
- package/dist/failure.js +19 -0
- package/dist/host.d.ts +8 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +38 -38
- package/dist/identity.d.ts +1 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +7 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/memory.d.ts +12 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +108 -36
- package/dist/model.d.ts +13 -12
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +6 -3
- package/dist/observation.d.ts +2 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +24 -14
- package/dist/open.d.ts +2 -0
- package/dist/open.d.ts.map +1 -0
- package/dist/open.js +1 -0
- package/dist/outcome.d.ts +22 -3
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +35 -1
- package/dist/overlay.d.ts +1 -1
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +19 -15
- 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 +10 -3
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +78 -36
- package/dist/reach.d.ts +40 -0
- package/dist/reach.d.ts.map +1 -0
- package/dist/reach.js +272 -0
- package/dist/react.d.ts +40 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +64 -0
- package/dist/read-side.d.ts +4 -0
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +116 -54
- package/dist/refresh.d.ts +12 -1
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +35 -22
- package/dist/replica.d.ts +6 -6
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +53 -39
- package/dist/room-draft.d.ts +11 -8
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +19 -26
- package/dist/rows.d.ts +4 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +82 -39
- package/dist/save.d.ts +4 -3
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +127 -68
- package/dist/search.d.ts +3 -2
- package/dist/search.d.ts.map +1 -1
- package/dist/status.d.ts +2 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +0 -8
- package/dist/store.d.ts +25 -2
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +206 -90
- package/dist/wire.d.ts +55 -19
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +62 -61
- package/package.json +14 -2
package/dist/read-side.js
CHANGED
|
@@ -1,62 +1,71 @@
|
|
|
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]));
|
|
56
|
+
}
|
|
57
|
+
function reached(reach, room, document) {
|
|
58
|
+
return reach === null
|
|
59
|
+
? []
|
|
60
|
+
: [or(inArray(room, [...reach.rooms]), inArray(document, [...reach.documents]))];
|
|
52
61
|
}
|
|
53
|
-
function scoped(scope, row, rooms) {
|
|
62
|
+
function scoped(scope, row, rooms, reach) {
|
|
54
63
|
return every([
|
|
55
64
|
eq(row.kind, 'document'),
|
|
56
65
|
...(rooms === null ? [] : [inArray(row.room, [...rooms])]),
|
|
66
|
+
...reached(reach, row.room, row.key),
|
|
57
67
|
...(scope.types === null ? [] : [inArray(row.type, [...scope.types])]),
|
|
58
68
|
...(scope.pathPrefix === null ? [] : [inArray(scope.pathPrefix, row.directories)]),
|
|
59
|
-
...(scope.where === null ? [] : [conditioned(scope.where, row)]),
|
|
60
69
|
]);
|
|
61
70
|
}
|
|
62
71
|
function keyed(key, row) {
|
|
@@ -68,25 +77,26 @@ function live(query) {
|
|
|
68
77
|
startSync: true,
|
|
69
78
|
});
|
|
70
79
|
}
|
|
71
|
-
function related(q, rows, scope, field, kept) {
|
|
80
|
+
function related(q, rows, scope, field, kept, reach) {
|
|
72
81
|
const matched = kept === 'source' ? 'target' : 'source';
|
|
73
82
|
const from = q.from({ r: rows });
|
|
74
|
-
|
|
75
|
-
.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)])]))
|
|
76
85
|
.innerJoin({ m: rows }, ({ r, m }) => eq(r[matched], m.key))
|
|
77
|
-
.where(({ m }) => scoped(scope, m, null))
|
|
86
|
+
.where(({ m }) => scoped(scope, m, null, reach));
|
|
87
|
+
return narrowed(joined, scope.where, 'm')
|
|
78
88
|
.groupBy(({ r }) => r[kept])
|
|
79
89
|
.select(({ r }) => ({ key: r[kept] }));
|
|
80
90
|
}
|
|
81
91
|
function filtered(q, rows, plan) {
|
|
82
92
|
const from = q.from({ d: rows });
|
|
83
|
-
let query = from.where(({ d }) => scoped(plan.root, d, plan.rooms));
|
|
93
|
+
let query = narrowed(from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach)), plan.root.where, 'd');
|
|
84
94
|
if (plan.hop !== null) {
|
|
85
|
-
const hop = related(q, rows, plan.hop, plan.hop.field, 'source');
|
|
95
|
+
const hop = related(q, rows, plan.hop, plan.hop.field, 'source', plan.reach);
|
|
86
96
|
query = query.innerJoin({ h: hop }, ({ d, h }) => eq(d.key, h.key));
|
|
87
97
|
}
|
|
88
98
|
if (plan.backlinks !== null) {
|
|
89
|
-
const backlinks = related(q, rows, plan.backlinks, plan.backlinks.field, 'target');
|
|
99
|
+
const backlinks = related(q, rows, plan.backlinks, plan.backlinks.field, 'target', plan.reach);
|
|
90
100
|
query = query.innerJoin({ k: backlinks }, ({ d, k }) => eq(d.key, k.key));
|
|
91
101
|
}
|
|
92
102
|
return query;
|
|
@@ -111,20 +121,19 @@ function documents(q, rows, plan, shape) {
|
|
|
111
121
|
room: d.room,
|
|
112
122
|
path: d.path,
|
|
113
123
|
type: d.type,
|
|
114
|
-
...(shape.fields ===
|
|
115
|
-
...(Array.isArray(shape.fields) ? named('field', shape.fields, d.fields) : {}),
|
|
124
|
+
...(shape.fields === null ? {} : { fields: d.fields }),
|
|
116
125
|
...(shape.sections === 'all' ? { sections: b.sections } : {}),
|
|
117
126
|
...(Array.isArray(shape.sections) ? named('section', shape.sections, b.sections) : {}),
|
|
118
127
|
...(shape.preamble ? { preamble: b.preamble } : {}),
|
|
119
128
|
...(shape.markdown ? { markdown: b.markdown } : {}),
|
|
120
|
-
...(shape.backlinks ? { backlinks: toArray(backlinked(q, rows, d)) } : {}),
|
|
129
|
+
...(shape.backlinks ? { backlinks: toArray(backlinked(q, rows, d, plan.reach)) } : {}),
|
|
121
130
|
...(shape.change ? { change: d.change } : {}),
|
|
122
131
|
}));
|
|
123
132
|
}
|
|
124
|
-
function backlinked(q, rows, document) {
|
|
133
|
+
function backlinked(q, rows, document, reach) {
|
|
125
134
|
const from = q.from({ r: rows });
|
|
126
135
|
return from
|
|
127
|
-
.where(({ r }) => eq(r.target, document.key))
|
|
136
|
+
.where(({ r }) => every([eq(r.target, document.key), ...reached(reach, r.room, r.source)]))
|
|
128
137
|
.orderBy(({ r }) => r.path, { stringSort: 'lexical' })
|
|
129
138
|
.orderBy(({ r }) => r.field, { stringSort: 'lexical' })
|
|
130
139
|
.select(({ r }) => ({ path: r.path, type: r.type, field: r.field }));
|
|
@@ -170,6 +179,55 @@ function part(row, prefix, names, whole) {
|
|
|
170
179
|
return whole;
|
|
171
180
|
return present(names.map((name, index) => [name, row[`${prefix}${index}`]]));
|
|
172
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
|
+
}
|
|
173
231
|
function documentOf(row, shape) {
|
|
174
232
|
if (row.type === null)
|
|
175
233
|
return { room: row.room, path: row.path };
|
|
@@ -179,7 +237,11 @@ function documentOf(row, shape) {
|
|
|
179
237
|
type: row.type,
|
|
180
238
|
...(shape.fields === null
|
|
181
239
|
? {}
|
|
182
|
-
: {
|
|
240
|
+
: {
|
|
241
|
+
fields: shape.fields === 'all'
|
|
242
|
+
? row.fields
|
|
243
|
+
: selected(row.fields, shape.fields),
|
|
244
|
+
}),
|
|
183
245
|
...(shape.sections === null
|
|
184
246
|
? {}
|
|
185
247
|
: {
|
|
@@ -214,7 +276,7 @@ function keyedOf(plan, entries) {
|
|
|
214
276
|
keys: bounded.map(([key]) => key),
|
|
215
277
|
};
|
|
216
278
|
}
|
|
217
|
-
function reconciled(previous, next) {
|
|
279
|
+
export function reconciled(previous, next) {
|
|
218
280
|
const before = rowsOf(previous.result);
|
|
219
281
|
const held = new Map(previous.keys.map((key, index) => [key, before[index]]));
|
|
220
282
|
const changed = [];
|
package/dist/refresh.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import type { Adapter, AdapterFailure, Authorization, RetryableRefusal } from './adapter.js';
|
|
2
|
+
import type { Remodel } from './bootstrap.js';
|
|
2
3
|
import { type ConfirmedLayer } from './replica.js';
|
|
4
|
+
import type { ReplicaRecord } from './store.js';
|
|
3
5
|
import { type Refused, type Unconfirmed } from './transfer.js';
|
|
6
|
+
export type Advancement = {
|
|
7
|
+
kind: 'still-current';
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'advanced';
|
|
10
|
+
record: ReplicaRecord;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'beyond-horizon';
|
|
13
|
+
} | RetryableRefusal | Unconfirmed | AdapterFailure;
|
|
4
14
|
export type RefreshOutcome = {
|
|
5
15
|
kind: 'still-current';
|
|
6
16
|
} | {
|
|
@@ -9,5 +19,6 @@ export type RefreshOutcome = {
|
|
|
9
19
|
} | {
|
|
10
20
|
kind: 'beyond-horizon';
|
|
11
21
|
} | RetryableRefusal | Unconfirmed | Refused | AdapterFailure;
|
|
12
|
-
export declare function
|
|
22
|
+
export declare function advancement(adapter: Adapter, authorization: Authorization, held: ReplicaRecord, remodel: Remodel, continuing: () => boolean): Promise<Advancement>;
|
|
23
|
+
export declare function refreshRoom(adapter: Adapter, authorization: Authorization, confirmed: ConfirmedLayer, remodel: Remodel, continuing: () => boolean): Promise<RefreshOutcome>;
|
|
13
24
|
//# sourceMappingURL=refresh.d.ts.map
|
package/dist/refresh.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../src/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,aAAa,EAGb,gBAAgB,EAEjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAe,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B,gBAAgB,GAChB,WAAW,GACX,OAAO,GACP,cAAc,CAAC;AAEnB,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,EAC5B,
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../src/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,aAAa,EAGb,gBAAgB,EAEjB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAe,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B,gBAAgB,GAChB,WAAW,GACX,cAAc,CAAC;AAEnB,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B,gBAAgB,GAChB,WAAW,GACX,OAAO,GACP,cAAc,CAAC;AAEnB,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,GACxB,OAAO,CAAC,WAAW,CAAC,CA4EtB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,GACxB,OAAO,CAAC,cAAc,CAAC,CAKzB"}
|
package/dist/refresh.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { declaredAttachments } from './attachment.js';
|
|
2
2
|
import { readStaged } from './replica.js';
|
|
3
3
|
import { unconfirmed } from './transfer.js';
|
|
4
|
-
export async function
|
|
5
|
-
const locator =
|
|
6
|
-
const fromRoomVersion =
|
|
4
|
+
export async function advancement(adapter, authorization, held, remodel, continuing) {
|
|
5
|
+
const locator = held.locator;
|
|
6
|
+
const fromRoomVersion = held.roomVersion;
|
|
7
7
|
const first = await adapter.refresh(authorization, {
|
|
8
8
|
locator,
|
|
9
|
-
selection:
|
|
9
|
+
selection: held.replica.selection,
|
|
10
10
|
fromRoomVersion,
|
|
11
|
-
...(minPosition === undefined ? {} : { minPosition }),
|
|
12
11
|
});
|
|
13
12
|
if (first.kind !== 'net-advancement')
|
|
14
13
|
return first;
|
|
15
14
|
const roomVersion = first.roomVersion;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
15
|
+
const models = remodel(first.models, {
|
|
16
|
+
collection: held.model,
|
|
17
|
+
selection: held.selectionModel,
|
|
18
|
+
});
|
|
19
|
+
const documents = { ...held.documents };
|
|
20
|
+
const revisions = { ...held.revisions };
|
|
21
|
+
const changes = { ...held.changes };
|
|
22
|
+
const written = { ...held.written };
|
|
23
|
+
const binaryTargets = new Set(held.binaryTargets);
|
|
21
24
|
const attachments = [];
|
|
22
25
|
const stage = (page) => {
|
|
23
26
|
if (page.attachments !== undefined)
|
|
@@ -52,9 +55,8 @@ export async function refreshRoom(adapter, authorization, confirmed, continuing,
|
|
|
52
55
|
return unconfirmed;
|
|
53
56
|
const page = await adapter.refresh(authorization, {
|
|
54
57
|
locator,
|
|
55
|
-
selection:
|
|
58
|
+
selection: held.replica.selection,
|
|
56
59
|
fromRoomVersion,
|
|
57
|
-
...(minPosition === undefined ? {} : { minPosition }),
|
|
58
60
|
pageToken,
|
|
59
61
|
});
|
|
60
62
|
if (page.kind === 'still-current' || page.kind === 'beyond-horizon')
|
|
@@ -66,15 +68,26 @@ export async function refreshRoom(adapter, authorization, confirmed, continuing,
|
|
|
66
68
|
stage(page);
|
|
67
69
|
pageToken = page.pageToken;
|
|
68
70
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
return {
|
|
72
|
+
kind: 'advanced',
|
|
73
|
+
record: {
|
|
74
|
+
...held,
|
|
75
|
+
model: models.collection,
|
|
76
|
+
selectionModel: models.selection,
|
|
77
|
+
roomVersion,
|
|
78
|
+
documents,
|
|
79
|
+
binaryTargets: [...binaryTargets].sort(),
|
|
80
|
+
revisions,
|
|
81
|
+
changes,
|
|
82
|
+
written,
|
|
83
|
+
attachments: attachments.length === 0 ? held.attachments : declaredAttachments(attachments),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export async function refreshRoom(adapter, authorization, confirmed, remodel, continuing) {
|
|
88
|
+
const advanced = await advancement(adapter, authorization, confirmed.record, remodel, continuing);
|
|
89
|
+
if (advanced.kind !== 'advanced')
|
|
90
|
+
return advanced;
|
|
91
|
+
const staged = readStaged(advanced.record, confirmed);
|
|
79
92
|
return staged.kind === 'staged' ? { kind: 'advanced', confirmed: staged.confirmed } : staged;
|
|
80
93
|
}
|
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 {
|
|
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 = {
|
|
@@ -29,15 +29,15 @@ type ReplayStep = {
|
|
|
29
29
|
collection?: Collection;
|
|
30
30
|
};
|
|
31
31
|
export declare function compositionOf(record: ReplicaRecord): Composition;
|
|
32
|
-
export declare function
|
|
32
|
+
export declare function confirmedOf(record: ReplicaRecord, previous?: ConfirmedLayer): ConfirmedLayer;
|
|
33
33
|
export declare function sameMembership(record: ReplicaRecord, other: ReplicaRecord): boolean;
|
|
34
34
|
export declare function readStaged(record: ReplicaRecord, previous?: ConfirmedLayer): Staged;
|
|
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[], roomVersion: string): Staged;
|
|
39
|
-
export declare function replicaOf(confirmed: ConfirmedLayer, queue: readonly ChangeBatch[],
|
|
40
|
-
export declare function landed(batch: ChangeBatch, confirmed: ConfirmedLayer): boolean;
|
|
41
|
-
export declare function withdrawals(confirmed: ConfirmedLayer, queue: readonly ChangeBatch[], withdrawable: (batch: ChangeBatch) => boolean,
|
|
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
|
+
export declare function replicaOf(confirmed: ConfirmedLayer, queue: readonly ChangeBatch[], previous?: Replica): Replica;
|
|
40
|
+
export declare function landed(batch: ChangeBatch, confirmed: ConfirmedLayer, current?: Readonly<Record<string, string>>): boolean;
|
|
41
|
+
export declare function withdrawals(confirmed: ConfirmedLayer, queue: readonly ChangeBatch[], withdrawable: (batch: ChangeBatch) => boolean, local: 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;
|
|
1
|
+
{"version":3,"file":"replica.d.ts","sourceRoot":"","sources":["../src/replica.ts"],"names":[],"mappings":"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"}
|
package/dist/replica.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { parse } from '@agentshouse/mdmodel';
|
|
1
|
+
import { equalValue, parse } from '@agentshouse/mdmodel';
|
|
2
2
|
import { immutable } from './change.js';
|
|
3
|
-
import {
|
|
3
|
+
import { collectionOf, unreadable, validateCollection, } from './collection.js';
|
|
4
4
|
import { overlay, overlayChanged, sameLayerText } from './overlay.js';
|
|
5
5
|
import { providerRewritten } from './save.js';
|
|
6
|
-
import {
|
|
6
|
+
import { declaredAttachments } from './attachment.js';
|
|
7
7
|
export function compositionOf(record) {
|
|
8
8
|
return {
|
|
9
9
|
model: record.model,
|
|
@@ -12,52 +12,62 @@ export function compositionOf(record) {
|
|
|
12
12
|
: { roots: record.typedSelection.roots, model: record.selectionModel },
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
-
export function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
:
|
|
19
|
-
|
|
20
|
-
? { kind: 'staged', confirmed: { record, collection: read.collection } }
|
|
21
|
-
: read;
|
|
15
|
+
export function confirmedOf(record, previous) {
|
|
16
|
+
return {
|
|
17
|
+
record,
|
|
18
|
+
collection: collectionOf(record.documents, compositionOf(record), previous?.collection),
|
|
19
|
+
};
|
|
22
20
|
}
|
|
23
21
|
export function sameMembership(record, other) {
|
|
24
22
|
return (JSON.stringify(record.typedSelection?.roots ?? null) ===
|
|
25
23
|
JSON.stringify(other.typedSelection?.roots ?? null));
|
|
26
24
|
}
|
|
27
25
|
export function readStaged(record, previous) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
record.
|
|
26
|
+
const textChanged = previous === undefined || !sameLayerText(record, previous.record);
|
|
27
|
+
const modeled = record.model.status !== 'unavailable' || record.selectionModel.status !== 'unavailable';
|
|
28
|
+
if (modeled &&
|
|
29
|
+
(textChanged ||
|
|
30
|
+
record.model !== previous?.record.model ||
|
|
31
|
+
record.selectionModel !== previous?.record.selectionModel)) {
|
|
33
32
|
const verdict = validateCollection(record.documents, record.binaryTargets, compositionOf(record));
|
|
34
33
|
if (verdict.verdict === 'refuse' && verdict.rule !== 'model-unavailable') {
|
|
35
34
|
return { kind: 'refused', refusal: verdict };
|
|
36
35
|
}
|
|
36
|
+
if (verdict.verdict === 'refuse') {
|
|
37
|
+
const refused = unreadable(record.documents, previous?.record.documents);
|
|
38
|
+
if (refused !== null)
|
|
39
|
+
return refused;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (textChanged) {
|
|
43
|
+
const refused = unreadable(record.documents, previous?.record.documents);
|
|
44
|
+
if (refused !== null)
|
|
45
|
+
return refused;
|
|
37
46
|
}
|
|
38
|
-
return
|
|
47
|
+
return { kind: 'staged', confirmed: confirmedOf(record, previous) };
|
|
39
48
|
}
|
|
40
49
|
export function readReclassified(record, previous) {
|
|
41
50
|
const verdict = validateCollection(record.documents, record.binaryTargets, compositionOf(record));
|
|
42
51
|
if (verdict.verdict !== 'refuse')
|
|
43
|
-
return
|
|
52
|
+
return { kind: 'staged', confirmed: confirmedOf(record, previous) };
|
|
44
53
|
return verdict.rule === 'model-unavailable'
|
|
45
54
|
? { kind: 'deferred' }
|
|
46
55
|
: { kind: 'refused', refusal: verdict };
|
|
47
56
|
}
|
|
48
|
-
export function applyReturned(confirmed, documents, revisions, removals, roomVersion) {
|
|
57
|
+
export function applyReturned(confirmed, documents, revisions, changes, removals, attachments, roomVersion, writtenAt) {
|
|
49
58
|
const nextDocuments = { ...confirmed.record.documents, ...documents };
|
|
50
59
|
const nextRevisions = { ...confirmed.record.revisions, ...revisions };
|
|
51
60
|
const nextChanges = { ...confirmed.record.changes };
|
|
52
61
|
const nextWritten = {
|
|
53
62
|
...confirmed.record.written,
|
|
54
|
-
...Object.fromEntries(Object.keys(documents).map((path) => [path,
|
|
63
|
+
...Object.fromEntries(Object.keys(documents).map((path) => [path, writtenAt])),
|
|
55
64
|
};
|
|
56
65
|
const binaryTargets = new Set(confirmed.record.binaryTargets);
|
|
57
66
|
for (const [path, revision] of Object.entries(revisions)) {
|
|
58
67
|
if (confirmed.record.revisions[path] !== revision)
|
|
59
68
|
delete nextChanges[path];
|
|
60
69
|
}
|
|
70
|
+
Object.assign(nextChanges, changes);
|
|
61
71
|
for (const path of removals) {
|
|
62
72
|
delete nextDocuments[path];
|
|
63
73
|
delete nextRevisions[path];
|
|
@@ -73,6 +83,9 @@ export function applyReturned(confirmed, documents, revisions, removals, roomVer
|
|
|
73
83
|
changes: nextChanges,
|
|
74
84
|
written: nextWritten,
|
|
75
85
|
binaryTargets: [...binaryTargets].sort(),
|
|
86
|
+
attachments: attachments === undefined
|
|
87
|
+
? confirmed.record.attachments
|
|
88
|
+
: declaredAttachments([attachments]),
|
|
76
89
|
}, confirmed);
|
|
77
90
|
}
|
|
78
91
|
function predicted(confirmed, batches, previous) {
|
|
@@ -93,9 +106,7 @@ function predicted(confirmed, batches, previous) {
|
|
|
93
106
|
const collection = hasMove
|
|
94
107
|
? reuseRewrite
|
|
95
108
|
? old.collection
|
|
96
|
-
:
|
|
97
|
-
? { text: confirmed.record.documents, collection: confirmed.collection }
|
|
98
|
-
: { text: old.before.documents, collection: old.collection })
|
|
109
|
+
: collectionOf(before.documents, composition, old?.collection ?? confirmed.collection)
|
|
99
110
|
: undefined;
|
|
100
111
|
const effective = collection === undefined
|
|
101
112
|
? batch
|
|
@@ -116,7 +127,7 @@ function predicted(confirmed, batches, previous) {
|
|
|
116
127
|
}
|
|
117
128
|
return { layer, replay };
|
|
118
129
|
}
|
|
119
|
-
export function replicaOf(confirmed, queue,
|
|
130
|
+
export function replicaOf(confirmed, queue, previous) {
|
|
120
131
|
const batches = Object.freeze(queue.map(immutable));
|
|
121
132
|
if (batches.length === 0) {
|
|
122
133
|
return {
|
|
@@ -132,21 +143,14 @@ export function replicaOf(confirmed, queue, rewriting, previous) {
|
|
|
132
143
|
replay: [],
|
|
133
144
|
};
|
|
134
145
|
}
|
|
135
|
-
const
|
|
136
|
-
const layer = rewriting === 'provider'
|
|
137
|
-
? predictedState.layer
|
|
138
|
-
: previous === undefined
|
|
139
|
-
? overlay(confirmed.record, batches)
|
|
140
|
-
: overlayChanged(confirmed.record, batches, previous.confirmed.record, previous.queue, previous.visible);
|
|
146
|
+
const { layer, replay } = predicted(confirmed, batches, previous);
|
|
141
147
|
return {
|
|
142
148
|
confirmed,
|
|
143
149
|
queue: batches,
|
|
144
|
-
replay
|
|
150
|
+
replay,
|
|
145
151
|
visible: {
|
|
146
152
|
...layer,
|
|
147
|
-
collection:
|
|
148
|
-
? undefined
|
|
149
|
-
: { text: previous.visible.documents, collection: previous.visible.collection }),
|
|
153
|
+
collection: collectionOf(layer.documents, compositionOf(confirmed.record), previous?.visible.collection ?? confirmed.collection),
|
|
150
154
|
},
|
|
151
155
|
};
|
|
152
156
|
}
|
|
@@ -172,6 +176,8 @@ function holds(layer, preconditions) {
|
|
|
172
176
|
if (precondition.kind === 'revision') {
|
|
173
177
|
return present(layer, path) && layer.revisions[path] === precondition.revision;
|
|
174
178
|
}
|
|
179
|
+
if (precondition.kind === 'content')
|
|
180
|
+
return layer.documents[path] === precondition.content;
|
|
175
181
|
const document = documentAt(path);
|
|
176
182
|
if (document === null)
|
|
177
183
|
return false;
|
|
@@ -230,8 +236,8 @@ function after(changes, index, path) {
|
|
|
230
236
|
}
|
|
231
237
|
return at;
|
|
232
238
|
}
|
|
233
|
-
export function landed(batch, confirmed) {
|
|
234
|
-
const layer = confirmed.record;
|
|
239
|
+
export function landed(batch, confirmed, current = {}) {
|
|
240
|
+
const layer = { ...confirmed.record, documents: { ...confirmed.record.documents, ...current } };
|
|
235
241
|
return batch.changes.every((change, index) => {
|
|
236
242
|
if (change.kind === 'replace' || (change.kind === 'create' && 'content' in change)) {
|
|
237
243
|
const at = after(batch.changes, index, change.path);
|
|
@@ -245,7 +251,7 @@ export function landed(batch, confirmed) {
|
|
|
245
251
|
});
|
|
246
252
|
});
|
|
247
253
|
}
|
|
248
|
-
export function withdrawals(confirmed, queue, withdrawable,
|
|
254
|
+
export function withdrawals(confirmed, queue, withdrawable, local) {
|
|
249
255
|
if (!queue.some(withdrawable))
|
|
250
256
|
return [];
|
|
251
257
|
const composition = compositionOf(confirmed.record);
|
|
@@ -256,13 +262,21 @@ export function withdrawals(confirmed, queue, withdrawable, rewriting) {
|
|
|
256
262
|
withdrawn.push(batch);
|
|
257
263
|
continue;
|
|
258
264
|
}
|
|
259
|
-
const effective =
|
|
265
|
+
const effective = batch.changes.some((change) => change.kind === 'move')
|
|
260
266
|
? providerRewritten(batch, {
|
|
261
267
|
...layer,
|
|
262
|
-
collection:
|
|
268
|
+
collection: collectionOf(layer.documents, composition),
|
|
263
269
|
})
|
|
264
270
|
: batch;
|
|
265
|
-
|
|
271
|
+
let unapplied = false;
|
|
272
|
+
const next = overlay(layer, [effective], () => {
|
|
273
|
+
unapplied = true;
|
|
274
|
+
});
|
|
275
|
+
if (local && unapplied) {
|
|
276
|
+
withdrawn.push(batch);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
layer = next;
|
|
266
280
|
}
|
|
267
281
|
return withdrawn;
|
|
268
282
|
}
|