@agentshouse/mdruntime 0.1.0-cf6041a06849c → 0.1.0-cf6d5f0a5c9c8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/AGENTS.md +45 -23
  2. package/README.md +9 -9
  3. package/dist/adapter.d.ts +8 -0
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/attached-model.d.ts.map +1 -1
  6. package/dist/attached-model.js +15 -2
  7. package/dist/bootstrap.d.ts +17 -5
  8. package/dist/bootstrap.d.ts.map +1 -1
  9. package/dist/bootstrap.js +89 -35
  10. package/dist/change-set.d.ts.map +1 -1
  11. package/dist/change-set.js +13 -7
  12. package/dist/client.d.ts +3 -1
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.js +35 -0
  15. package/dist/collection.d.ts +6 -11
  16. package/dist/collection.d.ts.map +1 -1
  17. package/dist/collection.js +56 -19
  18. package/dist/connection.d.ts +5 -2
  19. package/dist/connection.d.ts.map +1 -1
  20. package/dist/connection.js +165 -51
  21. package/dist/host.d.ts +1 -0
  22. package/dist/host.d.ts.map +1 -1
  23. package/dist/host.js +1 -0
  24. package/dist/identity.d.ts +1 -0
  25. package/dist/identity.d.ts.map +1 -1
  26. package/dist/identity.js +7 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/memory.d.ts +2 -1
  30. package/dist/memory.d.ts.map +1 -1
  31. package/dist/memory.js +16 -6
  32. package/dist/model.d.ts +7 -0
  33. package/dist/model.d.ts.map +1 -1
  34. package/dist/model.js +2 -0
  35. package/dist/paths.d.ts +0 -1
  36. package/dist/paths.d.ts.map +1 -1
  37. package/dist/paths.js +0 -16
  38. package/dist/query.d.ts +1 -1
  39. package/dist/query.d.ts.map +1 -1
  40. package/dist/query.js +49 -19
  41. package/dist/reach.d.ts.map +1 -1
  42. package/dist/reach.js +1 -16
  43. package/dist/react.d.ts +22 -14
  44. package/dist/react.d.ts.map +1 -1
  45. package/dist/react.js +7 -6
  46. package/dist/read-side.d.ts.map +1 -1
  47. package/dist/read-side.js +102 -46
  48. package/dist/refresh.d.ts +10 -0
  49. package/dist/refresh.d.ts.map +1 -1
  50. package/dist/refresh.js +33 -24
  51. package/dist/replica.d.ts +4 -4
  52. package/dist/replica.d.ts.map +1 -1
  53. package/dist/replica.js +31 -25
  54. package/dist/room-draft.js +1 -1
  55. package/dist/rows.d.ts +4 -1
  56. package/dist/rows.d.ts.map +1 -1
  57. package/dist/rows.js +84 -38
  58. package/dist/save.d.ts +1 -0
  59. package/dist/save.d.ts.map +1 -1
  60. package/dist/save.js +106 -53
  61. package/dist/store.d.ts +25 -1
  62. package/dist/store.d.ts.map +1 -1
  63. package/dist/store.js +206 -90
  64. package/dist/wire.d.ts +1 -0
  65. package/dist/wire.d.ts.map +1 -1
  66. package/dist/wire.js +1 -0
  67. package/package.json +2 -2
package/dist/read-side.js CHANGED
@@ -1,54 +1,58 @@
1
- import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq, gt, gte, inArray, isNull, isUndefined, lt, lte, not, or, toArray, } from '@tanstack/db';
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 some(expressions) {
9
- const [first, second, ...rest] = expressions;
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 equal(field, value) {
13
- return or(eq(field, value), inArray(value, field));
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 tested(test, field, size, written) {
25
+ function satisfied(test, held) {
16
26
  if (test.op === 'eq')
17
- return test.value === null ? isNull(field) : equal(field, test.value);
18
- if (test.op === 'ne') {
19
- return test.value === null
20
- ? not(isNull(field))
21
- : or(isUndefined(field), isNull(field), not(equal(field, test.value)));
22
- }
23
- if (test.op === 'in' || test.op === 'nin') {
24
- const matches = test.values.length === 0
25
- ? inArray(field, [])
26
- : some(test.values.map((value) => (value === null ? isNull(field) : equal(field, value))));
27
- if (test.op === 'in')
28
- return matches;
29
- return some([
30
- isUndefined(field),
31
- ...(test.values.includes(null) ? [] : [isNull(field)]),
32
- not(matches),
33
- ]);
34
- }
35
- if (test.op === 'range') {
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 every(condition.every.map((item) => conditioned(item, row)));
49
+ return condition.every.every((item) => conditioned(item, row));
49
50
  if ('some' in condition)
50
- return some(condition.some.map((item) => conditioned(item, row)));
51
- return tested(condition.test, row.values[condition.field], row.sizes[condition.field], row.fields[condition.field]);
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
- return from
81
- .where(({ r }) => every([eq(r.kind, 'reference'), ...(field === null ? [] : [eq(r.field, field)])]))
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 === 'all' ? { fields: d.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
- : { fields: part(row, 'field', shape.fields, row.fields) }),
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/refresh.d.ts CHANGED
@@ -1,7 +1,16 @@
1
1
  import type { Adapter, AdapterFailure, Authorization, RetryableRefusal } from './adapter.js';
2
2
  import type { Remodel } from './bootstrap.js';
3
3
  import { type ConfirmedLayer } from './replica.js';
4
+ import type { ReplicaRecord } from './store.js';
4
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;
5
14
  export type RefreshOutcome = {
6
15
  kind: 'still-current';
7
16
  } | {
@@ -10,5 +19,6 @@ export type RefreshOutcome = {
10
19
  } | {
11
20
  kind: 'beyond-horizon';
12
21
  } | RetryableRefusal | Unconfirmed | Refused | AdapterFailure;
22
+ export declare function advancement(adapter: Adapter, authorization: Authorization, held: ReplicaRecord, remodel: Remodel, continuing: () => boolean): Promise<Advancement>;
13
23
  export declare function refreshRoom(adapter: Adapter, authorization: Authorization, confirmed: ConfirmedLayer, remodel: Remodel, continuing: () => boolean): Promise<RefreshOutcome>;
14
24
  //# sourceMappingURL=refresh.d.ts.map
@@ -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,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,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,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,GACxB,OAAO,CAAC,cAAc,CAAC,CA8EzB"}
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,26 +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 refreshRoom(adapter, authorization, confirmed, remodel, continuing) {
5
- const locator = confirmed.record.locator;
6
- const fromRoomVersion = confirmed.record.roomVersion;
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: confirmed.record.replica.selection,
9
+ selection: held.replica.selection,
10
10
  fromRoomVersion,
11
11
  });
12
12
  if (first.kind !== 'net-advancement')
13
13
  return first;
14
14
  const roomVersion = first.roomVersion;
15
15
  const models = remodel(first.models, {
16
- collection: confirmed.record.model,
17
- selection: confirmed.record.selectionModel,
16
+ collection: held.model,
17
+ selection: held.selectionModel,
18
18
  });
19
- const documents = { ...confirmed.record.documents };
20
- const revisions = { ...confirmed.record.revisions };
21
- const changes = { ...confirmed.record.changes };
22
- const written = { ...confirmed.record.written };
23
- const binaryTargets = new Set(confirmed.record.binaryTargets);
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);
24
24
  const attachments = [];
25
25
  const stage = (page) => {
26
26
  if (page.attachments !== undefined)
@@ -55,7 +55,7 @@ export async function refreshRoom(adapter, authorization, confirmed, remodel, co
55
55
  return unconfirmed;
56
56
  const page = await adapter.refresh(authorization, {
57
57
  locator,
58
- selection: confirmed.record.replica.selection,
58
+ selection: held.replica.selection,
59
59
  fromRoomVersion,
60
60
  pageToken,
61
61
  });
@@ -68,17 +68,26 @@ export async function refreshRoom(adapter, authorization, confirmed, remodel, co
68
68
  stage(page);
69
69
  pageToken = page.pageToken;
70
70
  }
71
- const staged = readStaged({
72
- ...confirmed.record,
73
- model: models.collection,
74
- selectionModel: models.selection,
75
- roomVersion,
76
- documents,
77
- binaryTargets: [...binaryTargets].sort(),
78
- revisions,
79
- changes,
80
- written,
81
- attachments: attachments.length === 0 ? confirmed.record.attachments : declaredAttachments(attachments),
82
- }, confirmed);
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);
83
92
  return staged.kind === 'staged' ? { kind: 'advanced', confirmed: staged.confirmed } : staged;
84
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 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 = {
@@ -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 readConfirmed(record: ReplicaRecord, previous?: ConfirmedLayer): Staged;
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[], 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
@@ -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;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG;IACjC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GAAG,OAAO,CAAC;AAE7E,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;CAC/B,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAQhE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CAWtF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAKnF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CAkBnF;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,cAAc,GACvB,MAAM,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAM/B;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC3C,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC3C,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,WAAW,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAClD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,CAmCR;AAsDD,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,CAAC,EAAE,OAAO,GACjB,OAAO,CAgCT;AAkFD,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAa7E;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,YAAY,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,GAC5C,SAAS,WAAW,EAAE,CAmBxB"}
1
+ {"version":3,"file":"replica.d.ts","sourceRoot":"","sources":["../src/replica.ts"],"names":[],"mappings":"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"}
package/dist/replica.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { parse } from '@agentshouse/mdmodel';
2
2
  import { immutable } from './change.js';
3
- import { parseCollection, readCollection, validateCollection, } from './collection.js';
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
6
  import { equalValue } from './room-draft.js';
@@ -13,40 +13,49 @@ export function compositionOf(record) {
13
13
  : { roots: record.typedSelection.roots, model: record.selectionModel },
14
14
  };
15
15
  }
16
- export function readConfirmed(record, previous) {
17
- const read = readCollection(record.documents, compositionOf(record), previous === undefined
18
- ? undefined
19
- : { text: previous.record.documents, collection: previous.collection });
20
- return read.kind === 'read'
21
- ? { kind: 'staged', confirmed: { record, collection: read.collection } }
22
- : read;
16
+ export function confirmedOf(record, previous) {
17
+ return {
18
+ record,
19
+ collection: collectionOf(record.documents, compositionOf(record), previous?.collection),
20
+ };
23
21
  }
24
22
  export function sameMembership(record, other) {
25
23
  return (JSON.stringify(record.typedSelection?.roots ?? null) ===
26
24
  JSON.stringify(other.typedSelection?.roots ?? null));
27
25
  }
28
26
  export function readStaged(record, previous) {
29
- if ((record.model.status !== 'unavailable' || record.selectionModel.status !== 'unavailable') &&
30
- (previous === undefined ||
31
- !sameLayerText(record, previous.record) ||
32
- record.model !== previous.record.model ||
33
- record.selectionModel !== previous.record.selectionModel)) {
27
+ const textChanged = previous === undefined || !sameLayerText(record, previous.record);
28
+ const modeled = record.model.status !== 'unavailable' || record.selectionModel.status !== 'unavailable';
29
+ if (modeled &&
30
+ (textChanged ||
31
+ record.model !== previous?.record.model ||
32
+ record.selectionModel !== previous?.record.selectionModel)) {
34
33
  const verdict = validateCollection(record.documents, record.binaryTargets, compositionOf(record));
35
34
  if (verdict.verdict === 'refuse' && verdict.rule !== 'model-unavailable') {
36
35
  return { kind: 'refused', refusal: verdict };
37
36
  }
37
+ if (verdict.verdict === 'refuse') {
38
+ const refused = unreadable(record.documents, previous?.record.documents);
39
+ if (refused !== null)
40
+ return refused;
41
+ }
42
+ }
43
+ else if (textChanged) {
44
+ const refused = unreadable(record.documents, previous?.record.documents);
45
+ if (refused !== null)
46
+ return refused;
38
47
  }
39
- return readConfirmed(record, previous);
48
+ return { kind: 'staged', confirmed: confirmedOf(record, previous) };
40
49
  }
41
50
  export function readReclassified(record, previous) {
42
51
  const verdict = validateCollection(record.documents, record.binaryTargets, compositionOf(record));
43
52
  if (verdict.verdict !== 'refuse')
44
- return readConfirmed(record, previous);
53
+ return { kind: 'staged', confirmed: confirmedOf(record, previous) };
45
54
  return verdict.rule === 'model-unavailable'
46
55
  ? { kind: 'deferred' }
47
56
  : { kind: 'refused', refusal: verdict };
48
57
  }
49
- export function applyReturned(confirmed, documents, revisions, removals, attachments, roomVersion, writtenAt) {
58
+ export function applyReturned(confirmed, documents, revisions, changes, removals, attachments, roomVersion, writtenAt) {
50
59
  const nextDocuments = { ...confirmed.record.documents, ...documents };
51
60
  const nextRevisions = { ...confirmed.record.revisions, ...revisions };
52
61
  const nextChanges = { ...confirmed.record.changes };
@@ -59,6 +68,7 @@ export function applyReturned(confirmed, documents, revisions, removals, attachm
59
68
  if (confirmed.record.revisions[path] !== revision)
60
69
  delete nextChanges[path];
61
70
  }
71
+ Object.assign(nextChanges, changes);
62
72
  for (const path of removals) {
63
73
  delete nextDocuments[path];
64
74
  delete nextRevisions[path];
@@ -97,9 +107,7 @@ function predicted(confirmed, batches, previous) {
97
107
  const collection = hasMove
98
108
  ? reuseRewrite
99
109
  ? old.collection
100
- : parseCollection(before.documents, composition, old?.collection === undefined
101
- ? { text: confirmed.record.documents, collection: confirmed.collection }
102
- : { text: old.before.documents, collection: old.collection })
110
+ : collectionOf(before.documents, composition, old?.collection ?? confirmed.collection)
103
111
  : undefined;
104
112
  const effective = collection === undefined
105
113
  ? batch
@@ -143,9 +151,7 @@ export function replicaOf(confirmed, queue, previous) {
143
151
  replay,
144
152
  visible: {
145
153
  ...layer,
146
- collection: parseCollection(layer.documents, compositionOf(confirmed.record), previous === undefined
147
- ? undefined
148
- : { text: previous.visible.documents, collection: previous.visible.collection }),
154
+ collection: collectionOf(layer.documents, compositionOf(confirmed.record), previous?.visible.collection ?? confirmed.collection),
149
155
  },
150
156
  };
151
157
  }
@@ -229,8 +235,8 @@ function after(changes, index, path) {
229
235
  }
230
236
  return at;
231
237
  }
232
- export function landed(batch, confirmed) {
233
- const layer = confirmed.record;
238
+ export function landed(batch, confirmed, current = {}) {
239
+ const layer = { ...confirmed.record, documents: { ...confirmed.record.documents, ...current } };
234
240
  return batch.changes.every((change, index) => {
235
241
  if (change.kind === 'replace' || (change.kind === 'create' && 'content' in change)) {
236
242
  const at = after(batch.changes, index, change.path);
@@ -258,7 +264,7 @@ export function withdrawals(confirmed, queue, withdrawable) {
258
264
  const effective = batch.changes.some((change) => change.kind === 'move')
259
265
  ? providerRewritten(batch, {
260
266
  ...layer,
261
- collection: parseCollection(layer.documents, composition),
267
+ collection: collectionOf(layer.documents, composition),
262
268
  })
263
269
  : batch;
264
270
  layer = overlay(layer, [effective]);
@@ -174,7 +174,7 @@ function sameField(left, right) {
174
174
  }
175
175
  export function underneath(parts, path, visible) {
176
176
  const markdown = visible?.documents[path] ?? null;
177
- const document = visible?.collection.documents[path];
177
+ const document = visible?.collection.document(path);
178
178
  const report = {};
179
179
  const fields = {};
180
180
  for (const [name, part] of named(parts.fields)) {
package/dist/rows.d.ts CHANGED
@@ -10,7 +10,7 @@ export type DocumentRow = {
10
10
  type: string | null;
11
11
  fields: Fields;
12
12
  values: Fields;
13
- sizes: Readonly<Record<string, number>>;
13
+ reached: Readonly<Record<string, readonly unknown[]>>;
14
14
  directories: readonly string[];
15
15
  body: string;
16
16
  change: HeadChange | null;
@@ -31,11 +31,14 @@ export type ReferenceRow = {
31
31
  source: string;
32
32
  target: string;
33
33
  field: string;
34
+ forms: readonly string[];
34
35
  path: string;
35
36
  type: string;
36
37
  };
37
38
  export type Row = DocumentRow | BodyRow | ReferenceRow;
38
39
  export declare function documentKey(room: string, path: string): string;
40
+ export declare function roomOfKey(key: string): string;
41
+ export declare function markdownPath(path: string): boolean;
39
42
  export declare function rowsOf(room: string, path: string, document: Document | null, composition: Composition, change: HeadChange | null): readonly Row[];
40
43
  export {};
41
44
  //# sourceMappingURL=rows.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;AAMvD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAiBD,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GAAG,IAAI,EACzB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,UAAU,GAAG,IAAI,GACxB,SAAS,GAAG,EAAE,CAsEhB"}
1
+ {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;IACtD,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;AAMvD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAmFD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GAAG,IAAI,EACzB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,UAAU,GAAG,IAAI,GACxB,SAAS,GAAG,EAAE,CAuEhB"}