@agentshouse/mdruntime 0.1.0-cc7bd7a53214e → 0.1.0-ccbb89b0ca151

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 (186) hide show
  1. package/README.md +24 -11
  2. package/dist/adapter.d.ts +187 -48
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js +1 -9
  5. package/dist/attached-model.d.ts +15 -0
  6. package/dist/attached-model.d.ts.map +1 -0
  7. package/dist/attached-model.js +64 -0
  8. package/dist/attempt.d.ts +16 -0
  9. package/dist/attempt.d.ts.map +1 -0
  10. package/dist/attempt.js +70 -0
  11. package/dist/binary.d.ts +18 -0
  12. package/dist/binary.d.ts.map +1 -0
  13. package/dist/binary.js +8 -0
  14. package/dist/bootstrap.d.ts +44 -7
  15. package/dist/bootstrap.d.ts.map +1 -1
  16. package/dist/bootstrap.js +223 -45
  17. package/dist/chain.d.ts +11 -0
  18. package/dist/chain.d.ts.map +1 -0
  19. package/dist/chain.js +64 -0
  20. package/dist/change-set.d.ts +9 -14
  21. package/dist/change-set.d.ts.map +1 -1
  22. package/dist/change-set.js +11 -56
  23. package/dist/change.d.ts +45 -0
  24. package/dist/change.d.ts.map +1 -1
  25. package/dist/change.js +34 -0
  26. package/dist/client.d.ts +37 -15
  27. package/dist/client.d.ts.map +1 -1
  28. package/dist/client.js +159 -29
  29. package/dist/collection.d.ts +9 -13
  30. package/dist/collection.d.ts.map +1 -1
  31. package/dist/collection.js +46 -56
  32. package/dist/compile.d.ts +16 -0
  33. package/dist/compile.d.ts.map +1 -0
  34. package/dist/compile.js +765 -0
  35. package/dist/connection.d.ts +64 -25
  36. package/dist/connection.d.ts.map +1 -1
  37. package/dist/connection.js +3926 -961
  38. package/dist/conversation.d.ts +54 -16
  39. package/dist/conversation.d.ts.map +1 -1
  40. package/dist/conversation.js +730 -243
  41. package/dist/digest.d.ts +7 -0
  42. package/dist/digest.d.ts.map +1 -0
  43. package/dist/digest.js +113 -0
  44. package/dist/durability.d.ts +5 -1
  45. package/dist/durability.d.ts.map +1 -1
  46. package/dist/durability.js +5 -0
  47. package/dist/entry.d.ts +19 -0
  48. package/dist/entry.d.ts.map +1 -0
  49. package/dist/entry.js +151 -0
  50. package/dist/expectation.d.ts +21 -0
  51. package/dist/expectation.d.ts.map +1 -0
  52. package/dist/expectation.js +70 -0
  53. package/dist/failure.d.ts +13 -0
  54. package/dist/failure.d.ts.map +1 -0
  55. package/dist/failure.js +19 -0
  56. package/dist/fence.d.ts +6 -0
  57. package/dist/fence.d.ts.map +1 -0
  58. package/dist/fence.js +10 -0
  59. package/dist/file.d.ts +2 -19
  60. package/dist/file.d.ts.map +1 -1
  61. package/dist/file.js +7 -122
  62. package/dist/fulltext.d.ts +27 -0
  63. package/dist/fulltext.d.ts.map +1 -0
  64. package/dist/fulltext.js +368 -0
  65. package/dist/host.d.ts +15 -2
  66. package/dist/host.d.ts.map +1 -1
  67. package/dist/host.js +136 -31
  68. package/dist/identity.d.ts +4 -0
  69. package/dist/identity.d.ts.map +1 -1
  70. package/dist/identity.js +16 -1
  71. package/dist/index.d.ts +19 -9
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +8 -0
  74. package/dist/live.d.ts +22 -0
  75. package/dist/live.d.ts.map +1 -0
  76. package/dist/live.js +124 -0
  77. package/dist/media.d.ts +8 -0
  78. package/dist/media.d.ts.map +1 -0
  79. package/dist/media.js +195 -0
  80. package/dist/memory.d.ts +22 -8
  81. package/dist/memory.d.ts.map +1 -1
  82. package/dist/memory.js +207 -47
  83. package/dist/messages.d.ts +28 -0
  84. package/dist/messages.d.ts.map +1 -0
  85. package/dist/messages.js +90 -0
  86. package/dist/model.d.ts +17 -14
  87. package/dist/model.d.ts.map +1 -1
  88. package/dist/model.js +16 -4
  89. package/dist/name.d.ts +4 -0
  90. package/dist/name.d.ts.map +1 -0
  91. package/dist/name.js +122 -0
  92. package/dist/observation.d.ts +19 -2
  93. package/dist/observation.d.ts.map +1 -1
  94. package/dist/observation.js +113 -12
  95. package/dist/open.d.ts +2 -0
  96. package/dist/open.d.ts.map +1 -0
  97. package/dist/open.js +1 -0
  98. package/dist/opened.d.ts +22 -0
  99. package/dist/opened.d.ts.map +1 -0
  100. package/dist/opened.js +107 -0
  101. package/dist/outcome.d.ts +73 -3
  102. package/dist/outcome.d.ts.map +1 -1
  103. package/dist/outcome.js +79 -1
  104. package/dist/overlay.d.ts +15 -5
  105. package/dist/overlay.d.ts.map +1 -1
  106. package/dist/overlay.js +136 -180
  107. package/dist/paths.d.ts +0 -1
  108. package/dist/paths.d.ts.map +1 -1
  109. package/dist/paths.js +0 -16
  110. package/dist/query.d.ts +71 -5
  111. package/dist/query.d.ts.map +1 -1
  112. package/dist/query.js +122 -40
  113. package/dist/reach.d.ts +17 -4
  114. package/dist/reach.d.ts.map +1 -1
  115. package/dist/reach.js +251 -81
  116. package/dist/react.d.ts +43 -0
  117. package/dist/react.d.ts.map +1 -0
  118. package/dist/react.js +54 -0
  119. package/dist/readiness.d.ts +64 -0
  120. package/dist/readiness.d.ts.map +1 -0
  121. package/dist/readiness.js +33 -0
  122. package/dist/reads.d.ts +11 -0
  123. package/dist/reads.d.ts.map +1 -0
  124. package/dist/reads.js +100 -0
  125. package/dist/recovery.d.ts +25 -0
  126. package/dist/recovery.d.ts.map +1 -0
  127. package/dist/recovery.js +198 -0
  128. package/dist/refresh.d.ts +19 -7
  129. package/dist/refresh.d.ts.map +1 -1
  130. package/dist/refresh.js +125 -53
  131. package/dist/replica.d.ts +59 -33
  132. package/dist/replica.d.ts.map +1 -1
  133. package/dist/replica.js +321 -156
  134. package/dist/room-draft.d.ts +41 -9
  135. package/dist/room-draft.d.ts.map +1 -1
  136. package/dist/room-draft.js +186 -37
  137. package/dist/rows.d.ts +39 -34
  138. package/dist/rows.d.ts.map +1 -1
  139. package/dist/rows.js +195 -81
  140. package/dist/save.d.ts +72 -6
  141. package/dist/save.d.ts.map +1 -1
  142. package/dist/save.js +889 -178
  143. package/dist/search.d.ts +41 -29
  144. package/dist/search.d.ts.map +1 -1
  145. package/dist/search.js +37 -105
  146. package/dist/seed.d.ts +16 -0
  147. package/dist/seed.d.ts.map +1 -0
  148. package/dist/seed.js +75 -0
  149. package/dist/shared.d.ts +16 -0
  150. package/dist/shared.d.ts.map +1 -0
  151. package/dist/shared.js +431 -0
  152. package/dist/status.d.ts +6 -2
  153. package/dist/status.d.ts.map +1 -1
  154. package/dist/status.js +0 -8
  155. package/dist/store.d.ts +119 -58
  156. package/dist/store.d.ts.map +1 -1
  157. package/dist/store.js +362 -344
  158. package/dist/stored.d.ts +152 -0
  159. package/dist/stored.d.ts.map +1 -0
  160. package/dist/stored.js +607 -0
  161. package/dist/tables.d.ts +352 -0
  162. package/dist/tables.d.ts.map +1 -0
  163. package/dist/tables.js +624 -0
  164. package/dist/turn.d.ts +9 -0
  165. package/dist/turn.d.ts.map +1 -0
  166. package/dist/turn.js +75 -0
  167. package/dist/validation.d.ts +30 -0
  168. package/dist/validation.d.ts.map +1 -0
  169. package/dist/validation.js +162 -0
  170. package/dist/windows.d.ts +22 -0
  171. package/dist/windows.d.ts.map +1 -0
  172. package/dist/windows.js +89 -0
  173. package/dist/wire.d.ts +174 -45
  174. package/dist/wire.d.ts.map +1 -1
  175. package/dist/wire.js +70 -46
  176. package/dist/words.d.ts +19 -0
  177. package/dist/words.d.ts.map +1 -0
  178. package/dist/words.js +150 -0
  179. package/package.json +33 -10
  180. package/AGENTS.md +0 -215
  181. package/dist/attachment.d.ts +0 -3
  182. package/dist/attachment.d.ts.map +0 -1
  183. package/dist/attachment.js +0 -8
  184. package/dist/read-side.d.ts +0 -18
  185. package/dist/read-side.d.ts.map +0 -1
  186. package/dist/read-side.js +0 -377
package/dist/outcome.js CHANGED
@@ -1 +1,79 @@
1
- export {};
1
+ export const UNREADABLE = {
2
+ kind: 'unreadable',
3
+ code: 'room-not-readable',
4
+ fields: {},
5
+ retryable: false,
6
+ };
7
+ export const LOCKED_UNREADABLE = {
8
+ kind: 'unreadable',
9
+ code: 'room-locked',
10
+ fields: {},
11
+ retryable: true,
12
+ };
13
+ export const ABSENT_TARGET = {
14
+ kind: 'absent',
15
+ code: 'reference-absent',
16
+ fields: {},
17
+ retryable: false,
18
+ };
19
+ export function absentBinary(path) {
20
+ return { kind: 'absent', code: 'binary-file-absent', fields: { path }, retryable: false };
21
+ }
22
+ export function binaryAnswer(result) {
23
+ return result.kind === 'binary' || result.kind === 'rejected' ? result : failure(result);
24
+ }
25
+ const OCTET_STREAM = 'application/octet-stream';
26
+ export function binaryLinkAnswer(result, held) {
27
+ if (result.kind === 'link') {
28
+ return {
29
+ kind: 'link',
30
+ url: result.url,
31
+ name: result.name,
32
+ mediaType: result.mediaType ?? held ?? OCTET_STREAM,
33
+ };
34
+ }
35
+ return result.kind === 'rejected' ? result : failure(result);
36
+ }
37
+ export function attachAnswer(result) {
38
+ return result.kind === 'attached' || result.kind === 'rejected' ? result : failure(result);
39
+ }
40
+ export const ROOM_LOCKED = 'room-locked';
41
+ export function lockedRoom(locator) {
42
+ return { kind: ROOM_LOCKED, locator, code: ROOM_LOCKED, fields: {}, retryable: true };
43
+ }
44
+ export const OFFLINE = { kind: 'offline' };
45
+ export const UNCERTAIN = {
46
+ kind: 'transport-uncertainty',
47
+ code: 'transport-uncertainty',
48
+ fields: {},
49
+ retryable: true,
50
+ };
51
+ export function undeclared(name) {
52
+ return { kind: 'undeclared', code: 'action-undeclared', fields: { name }, retryable: false };
53
+ }
54
+ export function failure(result) {
55
+ switch (result.kind) {
56
+ case 'transport-uncertainty':
57
+ return UNCERTAIN;
58
+ case 'revoked-authorization':
59
+ return { kind: result.kind, code: result.kind, fields: {}, retryable: false };
60
+ case 'room-not-readable':
61
+ return {
62
+ kind: result.kind,
63
+ locator: result.locator,
64
+ code: result.kind,
65
+ fields: {},
66
+ retryable: false,
67
+ };
68
+ case 'scoped-refusal':
69
+ return result;
70
+ }
71
+ }
72
+ export function calledResult(result) {
73
+ return result.kind === 'action' || result.kind === 'rejected' ? result : failure(result);
74
+ }
75
+ export function historyAnswer(result) {
76
+ return result.kind === 'history' || result.kind === 'revision' || result.kind === 'no-history'
77
+ ? result
78
+ : failure(result);
79
+ }
package/dist/overlay.d.ts CHANGED
@@ -1,15 +1,25 @@
1
- import type { HeadChange } from './adapter.js';
1
+ import type { BinaryFile, HeadChange } from './adapter.js';
2
2
  import type { ChangeBatch } from './change.js';
3
3
  export type Heads = {
4
4
  revisions: Readonly<Record<string, string>>;
5
+ fileIds: Readonly<Record<string, string>>;
5
6
  changes: Readonly<Record<string, HeadChange>>;
6
7
  };
8
+ export type HeldBinary = ({
9
+ readonly state: 'accepted';
10
+ } & BinaryFile) | {
11
+ readonly state: 'pending';
12
+ readonly localId: string;
13
+ readonly byteLength: number;
14
+ readonly mediaType: string;
15
+ readonly sha256: string;
16
+ };
7
17
  export type Layer = Heads & {
8
18
  documents: Readonly<Record<string, string>>;
9
- binaryTargets: readonly string[];
19
+ binaries: Readonly<Record<string, HeldBinary>>;
10
20
  };
21
+ export declare function acceptedBinaries(files: Readonly<Record<string, BinaryFile>>): Generator<readonly [string, HeldBinary]>;
22
+ export declare function sameBinary(left: HeldBinary | undefined, right: HeldBinary | undefined): boolean;
11
23
  export declare function sameChange(left: HeadChange | undefined, right: HeadChange | undefined): boolean;
12
- export declare function overlay(base: Layer, queue: readonly ChangeBatch[]): Layer;
13
- export declare function sameLayerText(left: Layer, right: Layer): boolean;
14
- export declare function overlayChanged(base: Layer, queue: readonly ChangeBatch[], previousBase: Layer, previousQueue: readonly ChangeBatch[], previousVisible: Layer): Layer;
24
+ export declare function overlaying(base: Layer, queue: readonly ChangeBatch[], unapplied?: () => void): Generator<number, Layer, void>;
15
25
  //# sourceMappingURL=overlay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAU,WAAW,EAAgB,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,KAAK,GAAG;IAC1B,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAQ/F;AAoJD,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,KAAK,CAiBzE;AAQD,wBAAgB,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAQhE;AAmBD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,YAAY,EAAE,KAAK,EACnB,aAAa,EAAE,SAAS,WAAW,EAAE,EACrC,eAAe,EAAE,KAAK,GACrB,KAAK,CA4FP"}
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAU,WAAW,EAAgB,MAAM,aAAa,CAAC;AAIrE,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,UAAU,CAAC,GAC7C;IACE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEN,MAAM,MAAM,KAAK,GAAG,KAAK,GAAG;IAC1B,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CAChD,CAAC;AAEF,wBAAiB,gBAAgB,CAC/B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAC1C,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAE1C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAW/F;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAQ/F;AAqMD,wBAAiB,UAAU,CACzB,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,SAAS,CAAC,EAAE,MAAM,IAAI,GACrB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAoChC"}
package/dist/overlay.js CHANGED
@@ -1,4 +1,21 @@
1
- import { apply, parse, serialize } from '@agentshouse/mdmodel';
1
+ import { apply, frontmatterValue, parse, serialize, } from '@agentshouse/mdmodel';
2
+ import { drafted, entriesIn, settling } from './shared.js';
3
+ import { ROW_WEIGHT } from './turn.js';
4
+ export function* acceptedBinaries(files) {
5
+ for (const [path, file] of entriesIn(files))
6
+ yield [path, { state: 'accepted', ...file }];
7
+ }
8
+ export function sameBinary(left, right) {
9
+ if (left === undefined || right === undefined)
10
+ return left === right;
11
+ return (left.state === right.state &&
12
+ left.byteLength === right.byteLength &&
13
+ left.mediaType === right.mediaType &&
14
+ left.sha256 === right.sha256 &&
15
+ (left.state === 'accepted'
16
+ ? right.state === 'accepted'
17
+ : right.state === 'pending' && left.localId === right.localId));
18
+ }
2
19
  export function sameChange(left, right) {
3
20
  if (left === undefined || right === undefined)
4
21
  return left === right;
@@ -8,10 +25,13 @@ export function sameChange(left, right) {
8
25
  left.author?.name === right.author?.name);
9
26
  }
10
27
  const EMPTY_FRONTMATTER = '---\n---\n';
28
+ function isPart(change) {
29
+ return change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble';
30
+ }
11
31
  function at(path, name) {
12
32
  return `${path} ${name}`;
13
33
  }
14
- function priorsOf(preconditions) {
34
+ function* priorsOf(preconditions) {
15
35
  const fields = new Map();
16
36
  const sections = new Map();
17
37
  const preambles = new Map();
@@ -25,6 +45,7 @@ function priorsOf(preconditions) {
25
45
  if (precondition.kind === 'preamble') {
26
46
  preambles.set(precondition.path, precondition.value);
27
47
  }
48
+ yield ROW_WEIGHT;
28
49
  }
29
50
  return {
30
51
  field: (path, name) => fields.get(at(path, name)),
@@ -40,49 +61,50 @@ function compose(fields, sections) {
40
61
  const opened = parse(skeleton);
41
62
  if (!opened.ok)
42
63
  return skeleton;
43
- let document = opened.document;
44
- for (const [name, value] of Object.entries(fields)) {
45
- const next = apply(document, { kind: 'field', name, value, prior: undefined });
46
- if (next.outcome === 'applied')
47
- document = next.document;
48
- }
49
- return serialize(document);
64
+ const next = apply(opened.document, Object.entries(fields).flatMap(([name, value]) => frontmatterValue(value) ? [{ kind: 'field', name, value, prior: undefined }] : []));
65
+ return serialize(next.outcome === 'applied' ? next.document : opened.document);
50
66
  }
51
- function edited(document, change, priors) {
52
- if (change.kind === 'field') {
53
- return apply(document, {
67
+ function edited(change, priors) {
68
+ if (change.kind === 'field')
69
+ return {
54
70
  kind: 'field',
55
71
  name: change.name,
56
72
  value: change.value,
57
73
  prior: priors.field(change.path, change.name),
58
- });
59
- }
60
- if (change.kind === 'preamble') {
61
- return apply(document, {
62
- kind: 'preamble',
63
- value: change.value,
64
- prior: priors.preamble(change.path),
65
- });
66
- }
67
- if (change.kind !== 'section')
68
- return null;
69
- return apply(document, {
74
+ };
75
+ if (change.kind === 'preamble')
76
+ return { kind: 'preamble', value: change.value, prior: priors.preamble(change.path) };
77
+ return {
70
78
  kind: 'section',
71
79
  name: change.name,
72
80
  value: change.value,
73
81
  prior: priors.section(change.path, change.name),
74
- });
82
+ };
75
83
  }
76
- function edit(staged, change, priors) {
77
- const text = staged.documents[change.path];
84
+ function edit(staged, changes, priors) {
85
+ const path = changes[0].path;
86
+ delete staged.revisions[path];
87
+ const text = staged.documents[path];
78
88
  if (text === undefined)
79
- return;
80
- const parsed = parse(text, change.path);
89
+ return changes.length;
90
+ const parsed = parse(text, path);
81
91
  if (!parsed.ok)
82
- return;
83
- const next = edited(parsed.document, change, priors);
84
- if (next?.outcome === 'applied')
85
- staged.documents[change.path] = serialize(next.document);
92
+ return changes.length;
93
+ const wanted = changes.map((change) => edited(change, priors));
94
+ const first = apply(parsed.document, wanted);
95
+ if (first.outcome === 'refuse')
96
+ return changes.length;
97
+ if (first.outcome === 'applied') {
98
+ staged.documents[path] = serialize(first.document);
99
+ return 0;
100
+ }
101
+ const stale = new Set(first.stale);
102
+ const kept = wanted.filter((_, at) => !stale.has(at));
103
+ const rest = apply(parsed.document, kept);
104
+ if (rest.outcome !== 'applied')
105
+ return changes.length;
106
+ staged.documents[path] = serialize(rest.document);
107
+ return first.stale.length;
86
108
  }
87
109
  function relocate(staged, from, to) {
88
110
  const text = staged.documents[from];
@@ -90,194 +112,128 @@ function relocate(staged, from, to) {
90
112
  delete staged.documents[from];
91
113
  staged.documents[to] = text;
92
114
  }
93
- else if (staged.binaryTargets.delete(from)) {
94
- staged.binaryTargets.add(to);
115
+ else if (staged.binaries[from] !== undefined) {
116
+ staged.binaries[to] = staged.binaries[from];
117
+ delete staged.binaries[from];
95
118
  }
96
119
  else {
97
- return;
120
+ return false;
98
121
  }
99
122
  moveHead(staged, from, to);
123
+ return true;
100
124
  }
101
125
  function moveHead(heads, from, to) {
102
126
  const revision = heads.revisions[from];
127
+ const fileId = heads.fileIds[from];
103
128
  const change = heads.changes[from];
104
129
  delete heads.revisions[from];
130
+ delete heads.fileIds[from];
105
131
  delete heads.changes[from];
132
+ delete heads.fileIds[to];
106
133
  delete heads.changes[to];
107
134
  if (revision !== undefined)
108
135
  heads.revisions[to] = revision;
136
+ if (fileId !== undefined)
137
+ heads.fileIds[to] = fileId;
109
138
  if (change !== undefined)
110
139
  heads.changes[to] = change;
111
140
  }
112
141
  function erase(staged, path) {
113
142
  delete staged.documents[path];
114
143
  delete staged.revisions[path];
144
+ delete staged.fileIds[path];
115
145
  delete staged.changes[path];
116
- staged.binaryTargets.delete(path);
146
+ delete staged.binaries[path];
117
147
  }
118
- function stage(staged, change, priors) {
119
- if (change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble') {
120
- edit(staged, change, priors);
121
- return;
122
- }
148
+ function stage(staged, change) {
123
149
  if (change.kind === 'create') {
124
150
  staged.documents[change.path] =
125
151
  'content' in change ? change.content : compose(change.fields, change.sections);
152
+ delete staged.fileIds[change.path];
126
153
  delete staged.changes[change.path];
127
- return;
154
+ return true;
128
155
  }
129
156
  if (change.kind === 'replace') {
157
+ delete staged.revisions[change.path];
130
158
  if (staged.documents[change.path] === undefined)
131
- return;
159
+ return false;
132
160
  staged.documents[change.path] = change.content;
133
- return;
161
+ return true;
162
+ }
163
+ if (change.kind === 'binary') {
164
+ if (staged.documents[change.path] !== undefined)
165
+ return false;
166
+ staged.binaries[change.path] = {
167
+ state: 'pending',
168
+ localId: change.localId,
169
+ byteLength: change.byteLength,
170
+ mediaType: change.mediaType,
171
+ sha256: change.sha256,
172
+ };
173
+ delete staged.revisions[change.path];
174
+ delete staged.changes[change.path];
175
+ return true;
134
176
  }
135
177
  if (change.kind === 'move') {
136
- relocate(staged, change.path, change.to);
137
- return;
178
+ return relocate(staged, change.path, change.to);
179
+ }
180
+ if (change.kind === 'arrival') {
181
+ erase(staged, change.path);
182
+ if ('content' in change)
183
+ staged.documents[change.path] = change.content;
184
+ else
185
+ staged.binaries[change.path] = { state: 'accepted', ...change.binary };
186
+ arrive(staged, change);
187
+ return true;
138
188
  }
139
189
  erase(staged, change.path);
190
+ return true;
191
+ }
192
+ function arrive(heads, change) {
193
+ if (change.revision !== undefined)
194
+ heads.revisions[change.path] = change.revision;
195
+ if (change.fileId !== undefined)
196
+ heads.fileIds[change.path] = change.fileId;
197
+ if (change.change !== undefined)
198
+ heads.changes[change.path] = change.change;
140
199
  }
141
- export function overlay(base, queue) {
200
+ export function* overlaying(base, queue, unapplied) {
142
201
  const staged = {
143
- documents: { ...base.documents },
144
- binaryTargets: new Set(base.binaryTargets),
145
- revisions: { ...base.revisions },
146
- changes: { ...base.changes },
147
- };
148
- for (const batch of queue) {
149
- const priors = priorsOf(batch.preconditions);
150
- for (const change of batch.changes)
151
- stage(staged, change, priors);
152
- }
153
- return {
154
- documents: staged.documents,
155
- binaryTargets: [...staged.binaryTargets].sort(),
156
- revisions: staged.revisions,
157
- changes: staged.changes,
202
+ documents: drafted(base.documents),
203
+ binaries: drafted(base.binaries),
204
+ revisions: drafted(base.revisions),
205
+ fileIds: drafted(base.fileIds),
206
+ changes: drafted(base.changes),
158
207
  };
159
- }
160
- function pathsOf(batch) {
161
- return batch.changes.flatMap((change) => change.kind === 'move' ? [change.path, change.to] : [change.path]);
162
- }
163
- export function sameLayerText(left, right) {
164
- const paths = Object.keys(left.documents);
165
- return (paths.length === Object.keys(right.documents).length &&
166
- paths.every((path) => left.documents[path] === right.documents[path]) &&
167
- left.binaryTargets.length === right.binaryTargets.length &&
168
- left.binaryTargets.every((path) => right.binaryTargets.includes(path)));
169
- }
170
- function replayHeads(base, queue) {
171
- const heads = { revisions: { ...base.revisions }, changes: { ...base.changes } };
172
208
  for (const batch of queue) {
173
- for (const change of batch.changes) {
174
- if (change.kind === 'remove') {
175
- delete heads.revisions[change.path];
176
- delete heads.changes[change.path];
177
- }
178
- else if (change.kind === 'create') {
179
- delete heads.changes[change.path];
180
- }
181
- else if (change.kind === 'move') {
182
- moveHead(heads, change.path, change.to);
183
- }
184
- }
185
- }
186
- return heads;
187
- }
188
- export function overlayChanged(base, queue, previousBase, previousQueue, previousVisible) {
189
- const before = previousQueue.map((batch) => JSON.stringify(batch));
190
- const after = queue.map((batch) => JSON.stringify(batch));
191
- if (before.length === after.length &&
192
- before.every((id, index) => id === after[index]) &&
193
- sameLayerText(base, previousBase)) {
194
- return {
195
- documents: previousVisible.documents,
196
- binaryTargets: previousVisible.binaryTargets,
197
- ...replayHeads(base, queue),
198
- };
199
- }
200
- const affected = new Set();
201
- const paths = new Set([
202
- ...Object.keys(base.documents),
203
- ...Object.keys(previousBase.documents),
204
- ...Object.keys(base.revisions),
205
- ...Object.keys(previousBase.revisions),
206
- ...Object.keys(base.changes),
207
- ...Object.keys(previousBase.changes),
208
- ...base.binaryTargets,
209
- ...previousBase.binaryTargets,
210
- ]);
211
- for (const path of paths) {
212
- if (base.documents[path] !== previousBase.documents[path] ||
213
- base.revisions[path] !== previousBase.revisions[path] ||
214
- !sameChange(base.changes[path], previousBase.changes[path]) ||
215
- base.binaryTargets.includes(path) !== previousBase.binaryTargets.includes(path))
216
- affected.add(path);
217
- }
218
- const oldIds = new Set(before);
219
- const newIds = new Set(after);
220
- for (const batch of previousQueue) {
221
- if (!newIds.has(JSON.stringify(batch)))
222
- for (const path of pathsOf(batch))
223
- affected.add(path);
224
- }
225
- for (const batch of queue) {
226
- if (!oldIds.has(JSON.stringify(batch)))
227
- for (const path of pathsOf(batch))
228
- affected.add(path);
229
- }
230
- let expanded = true;
231
- while (expanded) {
232
- expanded = false;
233
- for (const batch of queue) {
234
- const touched = pathsOf(batch);
235
- if (!touched.some((path) => affected.has(path)))
209
+ const priors = yield* priorsOf(batch.preconditions);
210
+ for (let index = 0; index < batch.changes.length; index += 1) {
211
+ const change = batch.changes[index];
212
+ if (!isPart(change)) {
213
+ if (!stage(staged, change))
214
+ unapplied?.();
215
+ yield ROW_WEIGHT;
236
216
  continue;
237
- for (const path of touched) {
238
- if (affected.has(path))
239
- continue;
240
- affected.add(path);
241
- expanded = true;
242
217
  }
218
+ const run = [change];
219
+ while (index + 1 < batch.changes.length) {
220
+ const next = batch.changes[index + 1];
221
+ if (!isPart(next) || next.path !== change.path)
222
+ break;
223
+ run.push(next);
224
+ index += 1;
225
+ }
226
+ const text = staged.documents[change.path] ?? '';
227
+ for (let left = edit(staged, run, priors); left > 0; left -= 1)
228
+ unapplied?.();
229
+ yield ROW_WEIGHT + text.length;
243
230
  }
244
231
  }
245
- const documents = {};
246
- const revisions = {};
247
- const changes = {};
248
- for (const path of affected) {
249
- if (base.documents[path] !== undefined)
250
- documents[path] = base.documents[path];
251
- if (base.revisions[path] !== undefined)
252
- revisions[path] = base.revisions[path];
253
- if (base.changes[path] !== undefined)
254
- changes[path] = base.changes[path];
255
- }
256
- const staged = overlay({
257
- documents,
258
- revisions,
259
- changes,
260
- binaryTargets: base.binaryTargets.filter((path) => affected.has(path)),
261
- }, queue.filter((batch) => pathsOf(batch).some((path) => affected.has(path))));
262
- const mergedDocuments = { ...previousVisible.documents };
263
- const mergedRevisions = { ...previousVisible.revisions };
264
- const mergedChanges = { ...previousVisible.changes };
265
- const mergedTargets = new Set(previousVisible.binaryTargets);
266
- for (const path of affected) {
267
- delete mergedDocuments[path];
268
- delete mergedRevisions[path];
269
- delete mergedChanges[path];
270
- mergedTargets.delete(path);
271
- }
272
- Object.assign(mergedDocuments, staged.documents);
273
- Object.assign(mergedRevisions, staged.revisions);
274
- Object.assign(mergedChanges, staged.changes);
275
- for (const path of staged.binaryTargets)
276
- mergedTargets.add(path);
277
232
  return {
278
- documents: mergedDocuments,
279
- revisions: mergedRevisions,
280
- changes: mergedChanges,
281
- binaryTargets: [...mergedTargets].sort(),
233
+ documents: yield* settling(staged.documents),
234
+ binaries: yield* settling(staged.binaries),
235
+ revisions: yield* settling(staged.revisions),
236
+ fileIds: yield* settling(staged.fileIds),
237
+ changes: yield* settling(staged.changes),
282
238
  };
283
239
  }
package/dist/paths.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export declare function normalize(path: string): string | null;
2
- export declare function relative(from: string, target: string): string;
3
2
  export declare function beneath(prefix: string, path: string): boolean;
4
3
  export declare function covered(prefixes: readonly string[], path: string): boolean;
5
4
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1E"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1E"}
package/dist/paths.js CHANGED
@@ -1,7 +1,3 @@
1
- function dirname(path) {
2
- const index = path.lastIndexOf('/');
3
- return index === -1 ? '' : path.slice(0, index);
4
- }
5
1
  export function normalize(path) {
6
2
  const parts = [];
7
3
  for (const part of path.split('/')) {
@@ -17,18 +13,6 @@ export function normalize(path) {
17
13
  }
18
14
  return parts.join('/');
19
15
  }
20
- export function relative(from, target) {
21
- const base = dirname(from)
22
- .split('/')
23
- .filter((part) => part !== '');
24
- const parts = target.split('/');
25
- let shared = 0;
26
- while (shared < base.length && shared + 1 < parts.length && base[shared] === parts[shared]) {
27
- shared += 1;
28
- }
29
- const up = Array.from({ length: base.length - shared }, () => '..');
30
- return [...up, ...parts.slice(shared)].join('/');
31
- }
32
16
  export function beneath(prefix, path) {
33
17
  return path === prefix || path.startsWith(`${prefix}/`);
34
18
  }