@graview/core 0.1.0 → 0.1.3

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 (296) hide show
  1. package/README.md +7 -0
  2. package/dist/app.d.ts +17 -0
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js.map +1 -1
  5. package/dist/arrange.d.ts +3 -2
  6. package/dist/arrange.d.ts.map +1 -1
  7. package/dist/arrange.js +19 -2
  8. package/dist/arrange.js.map +1 -1
  9. package/dist/beginning.d.ts +5 -2
  10. package/dist/beginning.d.ts.map +1 -1
  11. package/dist/beginning.js +28 -0
  12. package/dist/beginning.js.map +1 -1
  13. package/dist/capabilities.d.ts +32 -0
  14. package/dist/capabilities.d.ts.map +1 -0
  15. package/dist/capabilities.js +31 -0
  16. package/dist/capabilities.js.map +1 -0
  17. package/dist/cli/check/index.d.ts +1 -0
  18. package/dist/cli/check/index.d.ts.map +1 -1
  19. package/dist/cli/check/index.js +1 -0
  20. package/dist/cli/check/index.js.map +1 -1
  21. package/dist/cli/check/lenses.d.ts.map +1 -1
  22. package/dist/cli/check/lenses.js +25 -0
  23. package/dist/cli/check/lenses.js.map +1 -1
  24. package/dist/cli/check/policy.d.ts.map +1 -1
  25. package/dist/cli/check/policy.js +35 -0
  26. package/dist/cli/check/policy.js.map +1 -1
  27. package/dist/cli/check/relations.d.ts.map +1 -1
  28. package/dist/cli/check/relations.js +31 -0
  29. package/dist/cli/check/relations.js.map +1 -1
  30. package/dist/cli/check/views.d.ts +14 -0
  31. package/dist/cli/check/views.d.ts.map +1 -0
  32. package/dist/cli/check/views.js +27 -0
  33. package/dist/cli/check/views.js.map +1 -0
  34. package/dist/cli/check.d.ts.map +1 -1
  35. package/dist/cli/check.js +2 -1
  36. package/dist/cli/check.js.map +1 -1
  37. package/dist/cli/create.d.ts +1 -1
  38. package/dist/cli/create.d.ts.map +1 -1
  39. package/dist/cli/create.js +63 -1
  40. package/dist/cli/create.js.map +1 -1
  41. package/dist/cli/index.d.ts +18 -1
  42. package/dist/cli/index.d.ts.map +1 -1
  43. package/dist/cli/index.js +66 -1
  44. package/dist/cli/index.js.map +1 -1
  45. package/dist/conformance/fixtures.d.ts +41 -0
  46. package/dist/conformance/fixtures.d.ts.map +1 -0
  47. package/dist/conformance/fixtures.js +950 -0
  48. package/dist/conformance/fixtures.js.map +1 -0
  49. package/dist/conformance/index.d.ts +54 -0
  50. package/dist/conformance/index.d.ts.map +1 -0
  51. package/dist/conformance/index.js +81 -0
  52. package/dist/conformance/index.js.map +1 -0
  53. package/dist/document/canonical.d.ts +4 -0
  54. package/dist/document/canonical.d.ts.map +1 -0
  55. package/dist/document/canonical.js +29 -0
  56. package/dist/document/canonical.js.map +1 -0
  57. package/dist/document/compile.d.ts +43 -0
  58. package/dist/document/compile.d.ts.map +1 -0
  59. package/dist/document/compile.js +807 -0
  60. package/dist/document/compile.js.map +1 -0
  61. package/dist/document/diff.d.ts +32 -0
  62. package/dist/document/diff.d.ts.map +1 -0
  63. package/dist/document/diff.js +148 -0
  64. package/dist/document/diff.js.map +1 -0
  65. package/dist/document/edit.d.ts +63 -0
  66. package/dist/document/edit.d.ts.map +1 -0
  67. package/dist/document/edit.js +1432 -0
  68. package/dist/document/edit.js.map +1 -0
  69. package/dist/document/expr/analyze.d.ts +14 -0
  70. package/dist/document/expr/analyze.d.ts.map +1 -0
  71. package/dist/document/expr/analyze.js +52 -0
  72. package/dist/document/expr/analyze.js.map +1 -0
  73. package/dist/document/expr/evaluate.d.ts +36 -0
  74. package/dist/document/expr/evaluate.d.ts.map +1 -0
  75. package/dist/document/expr/evaluate.js +344 -0
  76. package/dist/document/expr/evaluate.js.map +1 -0
  77. package/dist/document/expr/index.d.ts +8 -0
  78. package/dist/document/expr/index.d.ts.map +1 -0
  79. package/dist/document/expr/index.js +5 -0
  80. package/dist/document/expr/index.js.map +1 -0
  81. package/dist/document/expr/parse.d.ts +50 -0
  82. package/dist/document/expr/parse.d.ts.map +1 -0
  83. package/dist/document/expr/parse.js +240 -0
  84. package/dist/document/expr/parse.js.map +1 -0
  85. package/dist/document/expr/print.d.ts +4 -0
  86. package/dist/document/expr/print.d.ts.map +1 -0
  87. package/dist/document/expr/print.js +81 -0
  88. package/dist/document/expr/print.js.map +1 -0
  89. package/dist/document/findings.d.ts +15 -0
  90. package/dist/document/findings.d.ts.map +1 -0
  91. package/dist/document/findings.js +30 -0
  92. package/dist/document/findings.js.map +1 -0
  93. package/dist/document/graview-template.d.ts +148 -0
  94. package/dist/document/graview-template.d.ts.map +1 -0
  95. package/dist/document/graview-template.js +450 -0
  96. package/dist/document/graview-template.js.map +1 -0
  97. package/dist/document/index.d.ts +27 -0
  98. package/dist/document/index.d.ts.map +1 -0
  99. package/dist/document/index.js +16 -0
  100. package/dist/document/index.js.map +1 -0
  101. package/dist/document/migrate.d.ts +41 -0
  102. package/dist/document/migrate.d.ts.map +1 -0
  103. package/dist/document/migrate.js +252 -0
  104. package/dist/document/migrate.js.map +1 -0
  105. package/dist/document/patch.d.ts +16 -0
  106. package/dist/document/patch.d.ts.map +1 -0
  107. package/dist/document/patch.js +79 -0
  108. package/dist/document/patch.js.map +1 -0
  109. package/dist/document/rules.d.ts +40 -0
  110. package/dist/document/rules.d.ts.map +1 -0
  111. package/dist/document/rules.js +88 -0
  112. package/dist/document/rules.js.map +1 -0
  113. package/dist/document/schema.d.ts +461 -0
  114. package/dist/document/schema.d.ts.map +1 -0
  115. package/dist/document/schema.js +199 -0
  116. package/dist/document/schema.js.map +1 -0
  117. package/dist/document/template.d.ts +28 -0
  118. package/dist/document/template.d.ts.map +1 -0
  119. package/dist/document/template.js +117 -0
  120. package/dist/document/template.js.map +1 -0
  121. package/dist/document/to-document.d.ts +34 -0
  122. package/dist/document/to-document.d.ts.map +1 -0
  123. package/dist/document/to-document.js +186 -0
  124. package/dist/document/to-document.js.map +1 -0
  125. package/dist/document/upgrade.d.ts +9 -0
  126. package/dist/document/upgrade.d.ts.map +1 -0
  127. package/dist/document/upgrade.js +19 -0
  128. package/dist/document/upgrade.js.map +1 -0
  129. package/dist/document/views.d.ts +65 -0
  130. package/dist/document/views.d.ts.map +1 -0
  131. package/dist/document/views.js +264 -0
  132. package/dist/document/views.js.map +1 -0
  133. package/dist/formats.d.ts +50 -0
  134. package/dist/formats.d.ts.map +1 -0
  135. package/dist/formats.js +75 -0
  136. package/dist/formats.js.map +1 -0
  137. package/dist/graph/graph.d.ts +61 -3
  138. package/dist/graph/graph.d.ts.map +1 -1
  139. package/dist/graph/graph.js +187 -20
  140. package/dist/graph/graph.js.map +1 -1
  141. package/dist/index.d.ts +43 -18
  142. package/dist/index.d.ts.map +1 -1
  143. package/dist/index.js +31 -11
  144. package/dist/index.js.map +1 -1
  145. package/dist/integrity.d.ts +46 -0
  146. package/dist/integrity.d.ts.map +1 -0
  147. package/dist/integrity.js +179 -0
  148. package/dist/integrity.js.map +1 -0
  149. package/dist/invariants/engine.d.ts +8 -0
  150. package/dist/invariants/engine.d.ts.map +1 -1
  151. package/dist/invariants/engine.js +40 -2
  152. package/dist/invariants/engine.js.map +1 -1
  153. package/dist/invariants/types.d.ts +19 -0
  154. package/dist/invariants/types.d.ts.map +1 -1
  155. package/dist/labels.d.ts +65 -0
  156. package/dist/labels.d.ts.map +1 -0
  157. package/dist/labels.js +123 -0
  158. package/dist/labels.js.map +1 -0
  159. package/dist/mutations/define-mutation.d.ts.map +1 -1
  160. package/dist/mutations/define-mutation.js +5 -6
  161. package/dist/mutations/define-mutation.js.map +1 -1
  162. package/dist/mutations/derive-edits.d.ts.map +1 -1
  163. package/dist/mutations/derive-edits.js +20 -1
  164. package/dist/mutations/derive-edits.js.map +1 -1
  165. package/dist/mutations/form.d.ts +9 -0
  166. package/dist/mutations/form.d.ts.map +1 -1
  167. package/dist/mutations/form.js +20 -0
  168. package/dist/mutations/form.js.map +1 -1
  169. package/dist/mutations/node-ref.d.ts +6 -0
  170. package/dist/mutations/node-ref.d.ts.map +1 -1
  171. package/dist/mutations/node-ref.js +22 -8
  172. package/dist/mutations/node-ref.js.map +1 -1
  173. package/dist/mutations/types.d.ts +8 -0
  174. package/dist/mutations/types.d.ts.map +1 -1
  175. package/dist/mutations/words.d.ts +49 -0
  176. package/dist/mutations/words.d.ts.map +1 -0
  177. package/dist/mutations/words.js +61 -0
  178. package/dist/mutations/words.js.map +1 -0
  179. package/dist/ops/log.d.ts +156 -4
  180. package/dist/ops/log.d.ts.map +1 -1
  181. package/dist/ops/log.js +234 -51
  182. package/dist/ops/log.js.map +1 -1
  183. package/dist/ops/revisions.d.ts +66 -0
  184. package/dist/ops/revisions.d.ts.map +1 -0
  185. package/dist/ops/revisions.js +97 -0
  186. package/dist/ops/revisions.js.map +1 -0
  187. package/dist/ops/types.d.ts +49 -1
  188. package/dist/ops/types.d.ts.map +1 -1
  189. package/dist/ops/undo.d.ts +29 -2
  190. package/dist/ops/undo.d.ts.map +1 -1
  191. package/dist/ops/undo.js +110 -1
  192. package/dist/ops/undo.js.map +1 -1
  193. package/dist/ops/withheld.d.ts +37 -0
  194. package/dist/ops/withheld.d.ts.map +1 -0
  195. package/dist/ops/withheld.js +84 -0
  196. package/dist/ops/withheld.js.map +1 -0
  197. package/dist/permissions/policy.d.ts +15 -0
  198. package/dist/permissions/policy.d.ts.map +1 -1
  199. package/dist/permissions/policy.js +28 -1
  200. package/dist/permissions/policy.js.map +1 -1
  201. package/dist/permissions/sight.d.ts +66 -0
  202. package/dist/permissions/sight.d.ts.map +1 -0
  203. package/dist/permissions/sight.js +131 -0
  204. package/dist/permissions/sight.js.map +1 -0
  205. package/dist/permissions/types.d.ts +26 -0
  206. package/dist/permissions/types.d.ts.map +1 -1
  207. package/dist/permissions/types.js.map +1 -1
  208. package/dist/persistence/memory.d.ts.map +1 -1
  209. package/dist/persistence/memory.js +25 -0
  210. package/dist/persistence/memory.js.map +1 -1
  211. package/dist/persistence/sql.d.ts +43 -0
  212. package/dist/persistence/sql.d.ts.map +1 -0
  213. package/dist/persistence/sql.js +154 -0
  214. package/dist/persistence/sql.js.map +1 -0
  215. package/dist/persistence/sqlite.d.ts +17 -3
  216. package/dist/persistence/sqlite.d.ts.map +1 -1
  217. package/dist/persistence/sqlite.js +32 -96
  218. package/dist/persistence/sqlite.js.map +1 -1
  219. package/dist/persistence/types.d.ts +19 -0
  220. package/dist/persistence/types.d.ts.map +1 -1
  221. package/dist/presence.d.ts +56 -0
  222. package/dist/presence.d.ts.map +1 -1
  223. package/dist/presence.js +62 -2
  224. package/dist/presence.js.map +1 -1
  225. package/dist/refusal.d.ts +34 -0
  226. package/dist/refusal.d.ts.map +1 -0
  227. package/dist/refusal.js +40 -0
  228. package/dist/refusal.js.map +1 -0
  229. package/dist/scaffold/from-template.d.ts +16 -0
  230. package/dist/scaffold/from-template.d.ts.map +1 -0
  231. package/dist/scaffold/from-template.js +157 -0
  232. package/dist/scaffold/from-template.js.map +1 -0
  233. package/dist/scaffold/index.d.ts +10 -1
  234. package/dist/scaffold/index.d.ts.map +1 -1
  235. package/dist/scaffold/index.js +35 -7
  236. package/dist/scaffold/index.js.map +1 -1
  237. package/dist/scaffold/names.d.ts +4 -0
  238. package/dist/scaffold/names.d.ts.map +1 -1
  239. package/dist/scaffold/names.js.map +1 -1
  240. package/dist/scaffold/project.d.ts +1 -1
  241. package/dist/scaffold/project.d.ts.map +1 -1
  242. package/dist/scaffold/project.js +44 -13
  243. package/dist/scaffold/project.js.map +1 -1
  244. package/dist/scaffold/ui.d.ts.map +1 -1
  245. package/dist/scaffold/ui.js +19 -10
  246. package/dist/scaffold/ui.js.map +1 -1
  247. package/dist/schema/define-node.d.ts +20 -0
  248. package/dist/schema/define-node.d.ts.map +1 -1
  249. package/dist/schema/define-node.js +27 -2
  250. package/dist/schema/define-node.js.map +1 -1
  251. package/dist/schema/path.d.ts +19 -0
  252. package/dist/schema/path.d.ts.map +1 -0
  253. package/dist/schema/path.js +34 -0
  254. package/dist/schema/path.js.map +1 -0
  255. package/dist/schema/types.d.ts +17 -0
  256. package/dist/schema/types.d.ts.map +1 -1
  257. package/dist/seen.d.ts +64 -0
  258. package/dist/seen.d.ts.map +1 -0
  259. package/dist/seen.js +200 -0
  260. package/dist/seen.js.map +1 -0
  261. package/dist/store.d.ts +378 -8
  262. package/dist/store.d.ts.map +1 -1
  263. package/dist/store.js +801 -41
  264. package/dist/store.js.map +1 -1
  265. package/dist/testing.d.ts +6 -0
  266. package/dist/testing.d.ts.map +1 -1
  267. package/dist/testing.js +3 -1
  268. package/dist/testing.js.map +1 -1
  269. package/dist/theme/palettes.d.ts.map +1 -1
  270. package/dist/theme/palettes.js +4 -0
  271. package/dist/theme/palettes.js.map +1 -1
  272. package/dist/theme/types.d.ts +9 -0
  273. package/dist/theme/types.d.ts.map +1 -1
  274. package/dist/theme/types.js +4 -0
  275. package/dist/theme/types.js.map +1 -1
  276. package/dist/validate-graph.d.ts +84 -0
  277. package/dist/validate-graph.d.ts.map +1 -0
  278. package/dist/validate-graph.js +295 -0
  279. package/dist/validate-graph.js.map +1 -0
  280. package/dist/version.d.ts +3 -0
  281. package/dist/version.d.ts.map +1 -0
  282. package/dist/version.js +3 -0
  283. package/dist/version.js.map +1 -0
  284. package/dist/views/types.d.ts +8 -0
  285. package/dist/views/types.d.ts.map +1 -1
  286. package/dist/views/types.js +5 -0
  287. package/dist/views/types.js.map +1 -1
  288. package/dist/watched.d.ts +39 -0
  289. package/dist/watched.d.ts.map +1 -1
  290. package/dist/watched.js +94 -1
  291. package/dist/watched.js.map +1 -1
  292. package/dist/who.d.ts +24 -1
  293. package/dist/who.d.ts.map +1 -1
  294. package/dist/who.js +49 -2
  295. package/dist/who.js.map +1 -1
  296. package/package.json +9 -1
@@ -0,0 +1,61 @@
1
+ import { GraphError } from "../graph/graph.js";
2
+ import { fieldWords, humaniseField } from "../schema/define-node.js";
3
+ /**
4
+ * AN ARGUMENT ASKED FOR IN THE RECORD'S OWN WORDS.
5
+ *
6
+ * A form walked off a mutation's input named each field by its argument —
7
+ * "Vin", "Body", "Label" — and offered a choice's raw values — "suv",
8
+ * "plug-in-hybrid" — while the record the act makes, one page later, said
9
+ * "VIN", "Body style", "Name", "SUV" and "Plug-in hybrid", because the kind
10
+ * declares them. An argument that fills a field of the kind the act makes
11
+ * or acts on is that field, and is asked for in that field's words.
12
+ */
13
+ export function argumentWords(schema, mutation, name) {
14
+ const kinds = [...(mutation?.creates ?? []), ...(mutation?.subject && mutation.subject.kinds !== "*" ? mutation.subject.kinds : [])];
15
+ for (const kind of kinds) {
16
+ const definition = schema.tryDefinition(kind);
17
+ const shape = (definition?.fields?.shape ?? {});
18
+ if (!definition || !(name in shape))
19
+ continue;
20
+ const format = definition.display?.format?.[name];
21
+ const declared = definition.display?.labels?.[name];
22
+ return {
23
+ // A kind's `label` is its name: "Label *" is the field's key, not a word for it.
24
+ label: declared ?? (name === "label" ? "Name" : fieldWords(definition, name)),
25
+ option: (value) => (format ? format(value) : humaniseField(value)),
26
+ };
27
+ }
28
+ return { label: name === "label" ? "Name" : humaniseField(name), option: (value) => humaniseField(value) };
29
+ }
30
+ /** Arguments a mutation refused, each with where it was and what was wrong. */
31
+ export class InvalidArguments extends GraphError {
32
+ mutation;
33
+ issues;
34
+ constructor(mutation, issues) {
35
+ super(`Invalid arguments for mutation "${mutation}"`, issues.map((issue) => `${issue.path.map(String).join(".") || "(root)"}: ${issue.message}`).join("; "));
36
+ this.mutation = mutation;
37
+ this.issues = issues;
38
+ this.name = "InvalidArguments";
39
+ }
40
+ }
41
+ /**
42
+ * WHY A PRESS DID NOT TAKE, in a person's words.
43
+ *
44
+ * Arguments a mutation refused are said field by field, in the words the
45
+ * form asked in: "Email — Invalid email address", never `Invalid arguments
46
+ * for mutation "sign-up" email: Invalid email address`, which named the act
47
+ * by its id and the field by its key to somebody who had only ever seen
48
+ * "Sign up" and "Email". Anything else is the refusal's own sentence.
49
+ */
50
+ export function failureWords(schema, mutations, error) {
51
+ if (error instanceof InvalidArguments) {
52
+ const mutation = mutations.find((one) => one.name === error.mutation);
53
+ const said = error.issues.map((issue) => {
54
+ const field = issue.path.length > 0 ? argumentWords(schema, mutation, String(issue.path[0])).label : undefined;
55
+ return field ? `${field} — ${issue.message.replace(/^./, (first) => first.toLowerCase())}` : issue.message;
56
+ });
57
+ return `Not yet: ${said.join("; ")}.`;
58
+ }
59
+ return error instanceof Error ? error.message : String(error);
60
+ }
61
+ //# sourceMappingURL=words.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"words.js","sourceRoot":"","sources":["../../src/mutations/words.ts"],"names":[],"mappings":"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"}
package/dist/ops/log.d.ts CHANGED
@@ -1,18 +1,142 @@
1
1
  import { Graph } from "../graph/graph.js";
2
+ import type { GraphSnapshot } from "../graph/types.js";
2
3
  import type { AnySchema } from "../schema/schema.js";
3
4
  import type { Batch, Operation } from "./types.js";
5
+ /**
6
+ * A POINT THE LOG CAN BE FOLDED FROM (FR-27): the graph as it stood, and
7
+ * the seq of the first op that folds onto it.
8
+ *
9
+ * A log that spans a declaration change cannot be folded from empty under
10
+ * the new declaration, because the ops before the change wrote the old
11
+ * shape. So each declaration version begins an epoch: ship records one when
12
+ * a migration runs, with the migrated graph as its base, and one for the
13
+ * seed a store first opened on, which was never an operation. Verifying
14
+ * folds from the last epoch, and undo does not reach back across an epoch
15
+ * that changed the declaration.
16
+ */
17
+ export interface Epoch {
18
+ /** The seq of the first op folded onto `base`; every op before it is history behind the base. */
19
+ readonly seq: number;
20
+ /** The graph at that point. */
21
+ readonly base: GraphSnapshot;
22
+ /** The declaration version the epoch begins, when one is known. */
23
+ readonly version?: number;
24
+ /**
25
+ * What changed to begin it, in a sentence ("migration 1→2: size words
26
+ * become bed counts"). Present when the declaration changed; undo does
27
+ * not cross an epoch that has one. A seed, or a store from before epochs
28
+ * adopting what it holds, begins an epoch without one.
29
+ */
30
+ readonly change?: string;
31
+ /** When it began. */
32
+ readonly at?: string;
33
+ /**
34
+ * THE UNDO HORIZON (FR-23): this epoch is a checkpoint, and the ops
35
+ * before its seq were archived. A log restored with it begins at its seq,
36
+ * a normal open loads it and the ops after it and nothing older, and undo
37
+ * does not reach behind it. Absent on every other epoch.
38
+ */
39
+ readonly horizon?: true;
40
+ }
41
+ /**
42
+ * WHAT A COMPACTION MOVED OUT OF THE LOG (FR-23): the ops before the
43
+ * horizon, and the epochs before it, oldest first. An adapter keeps them
44
+ * where a normal open does not load them (`loadArchive`), and a full export
45
+ * puts them back in front of the tail.
46
+ */
47
+ export interface LogArchive {
48
+ readonly ops: readonly Operation[];
49
+ readonly epochs: readonly Epoch[];
50
+ }
4
51
  /**
5
52
  * The append-only log. Nothing here mutates or removes an entry: an undo is
6
53
  * a new op carrying the inverse, so history is never destroyed and the log
7
54
  * doubles as an audit trail of what an agent did on your behalf.
55
+ *
56
+ * A LOG BEGINS AT ITS HORIZON (FR-23). Its seqs are contiguous from there:
57
+ * from 0 for a whole log, from the checkpoint's seq for one compacted
58
+ * behind an undo horizon, whose older ops an adapter archived.
8
59
  */
9
60
  export declare class OperationLog {
10
- private readonly ops;
61
+ private ops;
62
+ private marks;
63
+ private start;
64
+ /**
65
+ * The seq the next op takes, which is how long the log is counting what
66
+ * a compaction archived (FR-23). The log holds `length - horizon` ops.
67
+ */
11
68
  get length(): number;
69
+ /**
70
+ * THE SEQ THE LOG BEGINS AT (FR-23): 0 for a whole log, the checkpoint's
71
+ * seq for one compacted behind an undo horizon. The ops before it are
72
+ * archived, not here.
73
+ */
74
+ get horizon(): number;
75
+ /** The ops this log holds, oldest first: from its horizon on. */
12
76
  all(): readonly Operation[];
77
+ /** The ops from `seq` on; from the horizon when `seq` is behind it. */
78
+ opsFrom(seq: number): readonly Operation[];
13
79
  append(op: Operation): void;
14
- /** Restores a log from storage, checking the sequence is intact. */
15
- static from(ops: readonly Operation[]): OperationLog;
80
+ /**
81
+ * Restores a log and its epochs from storage, checking the sequence is
82
+ * intact. A COMPACTED LOG (FR-23) begins at its horizon: the seq of the
83
+ * checkpoint among `epochs` (the last one marked `horizon`), or
84
+ * `options.horizon` for a log handed over without its base, as a client
85
+ * hydrating on a snapshot is. Its first op must carry that seq, and no
86
+ * epoch may be older than it. Without either, a log begins at 0.
87
+ */
88
+ static from(ops: readonly Operation[], epochs?: readonly Epoch[], options?: {
89
+ readonly horizon?: number;
90
+ }): OperationLog;
91
+ /**
92
+ * TAKES ANOTHER LOG WHOLESALE (FR-53): its ops, its epochs and its
93
+ * horizon, checked exactly as `from` checks them, in place of what this
94
+ * log held. For a client that resynced and takes the server's history as
95
+ * the server has it (`Store.adopt`); like `truncate`, it is not for
96
+ * history another store has seen. All or nothing: a log that is not
97
+ * intact is refused and this one is as it was.
98
+ */
99
+ replace(ops: readonly Operation[], epochs?: readonly Epoch[], options?: {
100
+ readonly horizon?: number;
101
+ }): void;
102
+ /** The epochs this log can be folded from, oldest first. */
103
+ epochs(): readonly Epoch[];
104
+ /** The epoch the current graph folds from, if any was marked. */
105
+ lastEpoch(): Epoch | undefined;
106
+ /**
107
+ * Begins an epoch at `epoch.seq`, usually the log's current length: the
108
+ * next op folds onto `epoch.base`. Epochs are in order and none starts
109
+ * past the end of the log.
110
+ */
111
+ markEpoch(epoch: Epoch): void;
112
+ /**
113
+ * ROLLS THE LOG BACK TO `length`, for ops that were only ever
114
+ * provisional: an optimistic client's pending tail, cut back before the
115
+ * server's ops land under it (`Store.rebase`). This is the one way an
116
+ * entry leaves the log, and it is not for history: ops another store has
117
+ * seen are undone by appending, never cut. Refuses to cut behind an epoch.
118
+ * Returns what was cut, oldest first.
119
+ */
120
+ truncate(length: number): Operation[];
121
+ /**
122
+ * THE GRAPH AS IT STOOD AT `seq`, AS AN EPOCH TO FOLD FROM (FR-23): the
123
+ * base of the last epoch at or before it, with the ops up to it folded
124
+ * on. An epoch already at `seq` is that graph and is kept as it is,
125
+ * declaration change and all. Marked `horizon`, so `compact` can make it
126
+ * the undo horizon. `at` is when the last op before it was made.
127
+ */
128
+ checkpointAt<S extends AnySchema>(schema: S, seq: number, options?: {
129
+ validate?: boolean;
130
+ }): Epoch;
131
+ /**
132
+ * MOVES THE UNDO HORIZON TO `checkpoint` (FR-23). The ops before its seq
133
+ * leave the log, with the epochs before it; the checkpoint becomes the
134
+ * first epoch, and the log begins at its seq. What left is returned,
135
+ * oldest first, for an adapter to archive: nothing here forgets history,
136
+ * it only stops carrying it. The graph is untouched, and still folds
137
+ * from the checkpoint with the ops after it.
138
+ */
139
+ compact(checkpoint: Epoch): LogArchive;
16
140
  get(id: string): Operation | undefined;
17
141
  /** Ops that have not been inverted by a later op. */
18
142
  live(): Operation[];
@@ -25,11 +149,39 @@ export declare class OperationLog {
25
149
  undoneIds(): Set<string>;
26
150
  opsInBatch(batchId: string): Operation[];
27
151
  batches(): Batch[];
28
- /** Rebuilds the graph from empty by folding every live op forward. */
152
+ /**
153
+ * Rebuilds the graph by folding every op forward: from empty, or, given
154
+ * `from`, from that epoch's base with the ops from its seq on (FR-27),
155
+ * up to the op before seq `to` when that is given. A compacted log folds
156
+ * only from its checkpoint or an epoch after it (FR-23).
157
+ *
158
+ * Each op lands as it landed when it was made: a write is judged as a
159
+ * write (a default filled in on the way in is filled in again), an undo
160
+ * puts back what was there. An op an older declaration accepted and this
161
+ * one does not is HELD AS WRITTEN rather than refusing the whole history
162
+ * (FR-28) — `validateGraph` says what no longer fits. Only an op that
163
+ * cannot apply at all (a patch to a record that is not there) fails.
164
+ */
29
165
  fold<S extends AnySchema>(schema: S, options?: {
30
166
  validate?: boolean;
167
+ from?: Epoch;
168
+ to?: number;
31
169
  }): Graph<S>;
32
170
  /** Serializable form for a persistence adapter. */
33
171
  toJSON(): Operation[];
34
172
  }
173
+ /**
174
+ * What `checkUndo` reads of a log: its ops, which of them are undone, and
175
+ * its epochs. An `OperationLog` is one; so is a log as one seat may see it.
176
+ */
177
+ export interface LogReading {
178
+ /** The ops it holds: from the undo horizon on, when the log was compacted (FR-23). */
179
+ all(): readonly Operation[];
180
+ undoneIds(): Set<string>;
181
+ epochs(): readonly Epoch[];
182
+ }
183
+ /** The ops of a list that a live op undoes (`OperationLog.undoneIds`). */
184
+ export declare function undoneIn(ops: readonly Operation[]): Set<string>;
185
+ /** Ops grouped into the gestures they were made in, in the order each began. */
186
+ export declare function batchesOf(ops: readonly Operation[], undone: ReadonlySet<string>): Batch[];
35
187
  //# sourceMappingURL=log.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmB;IAEvC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,GAAG,IAAI,SAAS,SAAS,EAAE;IAI3B,MAAM,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAS3B,oEAAoE;IACpE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,SAAS,EAAE,GAAG,YAAY;IAMpD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAItC,qDAAqD;IACrD,IAAI,IAAI,SAAS,EAAE;IAKnB;;;;;OAKG;IACH,SAAS,IAAI,GAAG,CAAC,MAAM,CAAC;IAqBxB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE;IAIxC,OAAO,IAAI,KAAK,EAAE;IA0BlB,sEAAsE;IACtE,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,KAAK,CAAC,CAAC,CAAC;IAQhF,mDAAmD;IACnD,MAAM,IAAI,SAAS,EAAE;CAGtB"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"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"}
package/dist/ops/log.js CHANGED
@@ -1,30 +1,176 @@
1
1
  import { Graph } from "../graph/graph.js";
2
+ const beginsPastZero = (op) => `Op "${op.id}" has seq ${op.seq}, so the log begins at seq ${op.seq}: a log that begins past 0 begins at its undo horizon, and none was given (a checkpoint epoch, or { horizon })`;
2
3
  /**
3
4
  * The append-only log. Nothing here mutates or removes an entry: an undo is
4
5
  * a new op carrying the inverse, so history is never destroyed and the log
5
6
  * doubles as an audit trail of what an agent did on your behalf.
7
+ *
8
+ * A LOG BEGINS AT ITS HORIZON (FR-23). Its seqs are contiguous from there:
9
+ * from 0 for a whole log, from the checkpoint's seq for one compacted
10
+ * behind an undo horizon, whose older ops an adapter archived.
6
11
  */
7
12
  export class OperationLog {
8
13
  ops = [];
14
+ marks = [];
15
+ start = 0;
16
+ /**
17
+ * The seq the next op takes, which is how long the log is counting what
18
+ * a compaction archived (FR-23). The log holds `length - horizon` ops.
19
+ */
9
20
  get length() {
10
- return this.ops.length;
21
+ return this.start + this.ops.length;
11
22
  }
23
+ /**
24
+ * THE SEQ THE LOG BEGINS AT (FR-23): 0 for a whole log, the checkpoint's
25
+ * seq for one compacted behind an undo horizon. The ops before it are
26
+ * archived, not here.
27
+ */
28
+ get horizon() {
29
+ return this.start;
30
+ }
31
+ /** The ops this log holds, oldest first: from its horizon on. */
12
32
  all() {
13
33
  return this.ops;
14
34
  }
35
+ /** The ops from `seq` on; from the horizon when `seq` is behind it. */
36
+ opsFrom(seq) {
37
+ return this.ops.slice(Math.max(0, seq - this.start));
38
+ }
15
39
  append(op) {
16
- if (op.seq !== this.ops.length) {
17
- throw new Error(`Op "${op.id}" has seq ${op.seq} but the log is ${this.ops.length} long`);
40
+ if (op.seq !== this.length) {
41
+ throw new Error(this.length === 0 && op.seq > 0 ? beginsPastZero(op) : `Op "${op.id}" has seq ${op.seq} but the log is ${this.length} long`);
18
42
  }
19
43
  this.ops.push(op);
20
44
  }
21
- /** Restores a log from storage, checking the sequence is intact. */
22
- static from(ops) {
45
+ /**
46
+ * Restores a log and its epochs from storage, checking the sequence is
47
+ * intact. A COMPACTED LOG (FR-23) begins at its horizon: the seq of the
48
+ * checkpoint among `epochs` (the last one marked `horizon`), or
49
+ * `options.horizon` for a log handed over without its base, as a client
50
+ * hydrating on a snapshot is. Its first op must carry that seq, and no
51
+ * epoch may be older than it. Without either, a log begins at 0.
52
+ */
53
+ static from(ops, epochs = [], options = {}) {
23
54
  const log = new OperationLog();
55
+ const checkpoint = [...epochs].reverse().find((epoch) => epoch.horizon);
56
+ const horizon = options.horizon ?? checkpoint?.seq ?? 0;
57
+ if (!Number.isInteger(horizon) || horizon < 0)
58
+ throw new Error(`A log cannot begin at seq ${horizon}`);
59
+ if (checkpoint && options.horizon !== undefined && checkpoint.seq !== options.horizon) {
60
+ throw new Error(`A log said to begin at seq ${options.horizon} has its checkpoint at seq ${checkpoint.seq}`);
61
+ }
62
+ const first = ops[0];
63
+ if (first && horizon > 0 && first.seq !== horizon) {
64
+ throw new Error(`A log compacted at seq ${horizon} begins with op "${first.id}" at seq ${first.seq}`);
65
+ }
66
+ log.start = horizon;
24
67
  for (const op of ops)
25
68
  log.append(op);
69
+ for (const epoch of epochs)
70
+ log.markEpoch(epoch);
26
71
  return log;
27
72
  }
73
+ /**
74
+ * TAKES ANOTHER LOG WHOLESALE (FR-53): its ops, its epochs and its
75
+ * horizon, checked exactly as `from` checks them, in place of what this
76
+ * log held. For a client that resynced and takes the server's history as
77
+ * the server has it (`Store.adopt`); like `truncate`, it is not for
78
+ * history another store has seen. All or nothing: a log that is not
79
+ * intact is refused and this one is as it was.
80
+ */
81
+ replace(ops, epochs = [], options = {}) {
82
+ const next = OperationLog.from(ops, epochs, options);
83
+ this.ops = next.ops;
84
+ this.marks = next.marks;
85
+ this.start = next.start;
86
+ }
87
+ /** The epochs this log can be folded from, oldest first. */
88
+ epochs() {
89
+ return this.marks;
90
+ }
91
+ /** The epoch the current graph folds from, if any was marked. */
92
+ lastEpoch() {
93
+ return this.marks.at(-1);
94
+ }
95
+ /**
96
+ * Begins an epoch at `epoch.seq`, usually the log's current length: the
97
+ * next op folds onto `epoch.base`. Epochs are in order and none starts
98
+ * past the end of the log.
99
+ */
100
+ markEpoch(epoch) {
101
+ if (!Number.isInteger(epoch.seq) || epoch.seq < 0 || epoch.seq > this.length) {
102
+ throw new Error(`An epoch at seq ${epoch.seq} starts past the end of a log ${this.length} long`);
103
+ }
104
+ if (epoch.seq < this.start) {
105
+ throw new Error(`An epoch at seq ${epoch.seq} is behind the horizon at seq ${this.start}: it went to the archive with the ops before it`);
106
+ }
107
+ const last = this.lastEpoch();
108
+ if (last && epoch.seq < last.seq) {
109
+ throw new Error(`An epoch at seq ${epoch.seq} comes before the last one, at seq ${last.seq}`);
110
+ }
111
+ this.marks.push(epoch);
112
+ }
113
+ /**
114
+ * ROLLS THE LOG BACK TO `length`, for ops that were only ever
115
+ * provisional: an optimistic client's pending tail, cut back before the
116
+ * server's ops land under it (`Store.rebase`). This is the one way an
117
+ * entry leaves the log, and it is not for history: ops another store has
118
+ * seen are undone by appending, never cut. Refuses to cut behind an epoch.
119
+ * Returns what was cut, oldest first.
120
+ */
121
+ truncate(length) {
122
+ if (!Number.isInteger(length) || length < this.start || length > this.length) {
123
+ throw new Error(`Cannot cut a log ${this.length} long back to ${length}`);
124
+ }
125
+ const last = this.lastEpoch();
126
+ if (last && last.seq > length) {
127
+ throw new Error(`Cannot cut the log back to ${length}: an epoch begins at seq ${last.seq}`);
128
+ }
129
+ return this.ops.splice(length - this.start);
130
+ }
131
+ /**
132
+ * THE GRAPH AS IT STOOD AT `seq`, AS AN EPOCH TO FOLD FROM (FR-23): the
133
+ * base of the last epoch at or before it, with the ops up to it folded
134
+ * on. An epoch already at `seq` is that graph and is kept as it is,
135
+ * declaration change and all. Marked `horizon`, so `compact` can make it
136
+ * the undo horizon. `at` is when the last op before it was made.
137
+ */
138
+ checkpointAt(schema, seq, options = {}) {
139
+ if (!Number.isInteger(seq) || seq < this.start || seq > this.length) {
140
+ throw new Error(`No checkpoint at seq ${seq}: this log holds seqs ${this.start} to ${this.length}`);
141
+ }
142
+ const from = [...this.marks].reverse().find((epoch) => epoch.seq <= seq);
143
+ if (from?.seq === seq)
144
+ return { ...from, horizon: true };
145
+ const base = this.fold(schema, { ...options, ...(from ? { from } : {}), to: seq }).snapshot();
146
+ const at = this.ops[seq - 1 - this.start]?.at ?? from?.at;
147
+ return {
148
+ seq,
149
+ base,
150
+ ...(from?.version !== undefined ? { version: from.version } : {}),
151
+ ...(at !== undefined ? { at } : {}),
152
+ horizon: true,
153
+ };
154
+ }
155
+ /**
156
+ * MOVES THE UNDO HORIZON TO `checkpoint` (FR-23). The ops before its seq
157
+ * leave the log, with the epochs before it; the checkpoint becomes the
158
+ * first epoch, and the log begins at its seq. What left is returned,
159
+ * oldest first, for an adapter to archive: nothing here forgets history,
160
+ * it only stops carrying it. The graph is untouched, and still folds
161
+ * from the checkpoint with the ops after it.
162
+ */
163
+ compact(checkpoint) {
164
+ if (!Number.isInteger(checkpoint.seq) || checkpoint.seq < this.start || checkpoint.seq > this.length) {
165
+ throw new Error(`Cannot compact at seq ${checkpoint.seq}: this log holds seqs ${this.start} to ${this.length}`);
166
+ }
167
+ const ops = this.ops.slice(0, checkpoint.seq - this.start);
168
+ const epochs = this.marks.filter((epoch) => epoch.seq < checkpoint.seq);
169
+ this.ops = this.ops.slice(checkpoint.seq - this.start);
170
+ this.marks = [{ ...checkpoint, horizon: true }, ...this.marks.filter((epoch) => epoch.seq > checkpoint.seq)];
171
+ this.start = checkpoint.seq;
172
+ return { ops, epochs };
173
+ }
28
174
  get(id) {
29
175
  return this.ops.find((op) => op.id === id);
30
176
  }
@@ -40,58 +186,48 @@ export class OperationLog {
40
186
  * from the end of the log backwards terminates in one pass.
41
187
  */
42
188
  undoneIds() {
43
- const undoers = new Map();
44
- for (const op of this.ops) {
45
- if (!op.undoes)
46
- continue;
47
- const list = undoers.get(op.undoes);
48
- if (list)
49
- list.push(op.id);
50
- else
51
- undoers.set(op.undoes, [op.id]);
52
- }
53
- const live = new Map();
54
- for (let i = this.ops.length - 1; i >= 0; i--) {
55
- const op = this.ops[i];
56
- const mine = undoers.get(op.id) ?? [];
57
- live.set(op.id, !mine.some((id) => live.get(id) === true));
58
- }
59
- return new Set(this.ops.filter((op) => live.get(op.id) === false).map((op) => op.id));
189
+ return undoneIn(this.ops);
60
190
  }
61
191
  opsInBatch(batchId) {
62
192
  return this.ops.filter((op) => op.batch === batchId);
63
193
  }
64
194
  batches() {
65
- const undone = this.undoneIds();
66
- const order = [];
67
- const grouped = new Map();
68
- for (const op of this.ops) {
69
- const list = grouped.get(op.batch);
70
- if (list)
71
- list.push(op);
72
- else {
73
- grouped.set(op.batch, [op]);
74
- order.push(op.batch);
75
- }
195
+ return batchesOf(this.ops, this.undoneIds());
196
+ }
197
+ /**
198
+ * Rebuilds the graph by folding every op forward: from empty, or, given
199
+ * `from`, from that epoch's base with the ops from its seq on (FR-27),
200
+ * up to the op before seq `to` when that is given. A compacted log folds
201
+ * only from its checkpoint or an epoch after it (FR-23).
202
+ *
203
+ * Each op lands as it landed when it was made: a write is judged as a
204
+ * write (a default filled in on the way in is filled in again), an undo
205
+ * puts back what was there. An op an older declaration accepted and this
206
+ * one does not is HELD AS WRITTEN rather than refusing the whole history
207
+ * (FR-28) — `validateGraph` says what no longer fits. Only an op that
208
+ * cannot apply at all (a patch to a record that is not there) fails.
209
+ */
210
+ fold(schema, options = {}) {
211
+ const from = options.from?.seq ?? 0;
212
+ if (from < this.start) {
213
+ throw new Error(options.from
214
+ ? `An epoch at seq ${from} is behind the horizon at seq ${this.start}: fold from the checkpoint`
215
+ : `A log compacted at seq ${this.start} does not fold from empty: fold from its checkpoint`);
76
216
  }
77
- return order.map((id) => {
78
- const ops = grouped.get(id) ?? [];
79
- const first = ops[0];
80
- return {
81
- id,
82
- author: first.author,
83
- intent: first.intent,
84
- at: first.at,
85
- ops,
86
- undone: ops.every((op) => undone.has(op.id)),
87
- };
88
- });
89
- }
90
- /** Rebuilds the graph from empty by folding every live op forward. */
91
- fold(schema, options) {
92
- const graph = new Graph(schema, options);
93
- for (const op of this.ops) {
94
- graph.applyPrimitives(op.primitives);
217
+ const base = (options.from?.base ?? { nodes: [], edges: [] });
218
+ const graph = Graph.from(schema, base, options.validate !== undefined ? { validate: options.validate } : {});
219
+ const to = options.to ?? this.length;
220
+ for (const op of this.ops.slice(from - this.start, Math.max(0, to - this.start))) {
221
+ if (op.undoes !== undefined) {
222
+ graph.applyPrimitives(op.primitives, { restoring: true });
223
+ continue;
224
+ }
225
+ try {
226
+ graph.applyPrimitives(op.primitives);
227
+ }
228
+ catch {
229
+ graph.applyPrimitives(op.primitives, { restoring: true });
230
+ }
95
231
  }
96
232
  return graph;
97
233
  }
@@ -100,4 +236,51 @@ export class OperationLog {
100
236
  return [...this.ops];
101
237
  }
102
238
  }
239
+ /** The ops of a list that a live op undoes (`OperationLog.undoneIds`). */
240
+ export function undoneIn(ops) {
241
+ const undoers = new Map();
242
+ for (const op of ops) {
243
+ if (!op.undoes)
244
+ continue;
245
+ const list = undoers.get(op.undoes);
246
+ if (list)
247
+ list.push(op.id);
248
+ else
249
+ undoers.set(op.undoes, [op.id]);
250
+ }
251
+ const live = new Map();
252
+ for (let i = ops.length - 1; i >= 0; i--) {
253
+ const op = ops[i];
254
+ const mine = undoers.get(op.id) ?? [];
255
+ live.set(op.id, !mine.some((id) => live.get(id) === true));
256
+ }
257
+ return new Set(ops.filter((op) => live.get(op.id) === false).map((op) => op.id));
258
+ }
259
+ /** Ops grouped into the gestures they were made in, in the order each began. */
260
+ export function batchesOf(ops, undone) {
261
+ const order = [];
262
+ const grouped = new Map();
263
+ for (const op of ops) {
264
+ const list = grouped.get(op.batch);
265
+ if (list)
266
+ list.push(op);
267
+ else {
268
+ grouped.set(op.batch, [op]);
269
+ order.push(op.batch);
270
+ }
271
+ }
272
+ return order.map((id) => {
273
+ const ops = grouped.get(id) ?? [];
274
+ const first = ops[0];
275
+ return {
276
+ id,
277
+ author: first.author,
278
+ // What the gesture was for, when its caller said; else its first op's own sentence.
279
+ intent: first.batchIntent ?? first.intent,
280
+ at: first.at,
281
+ ops,
282
+ undone: ops.every((op) => undone.has(op.id)),
283
+ };
284
+ });
285
+ }
103
286
  //# sourceMappingURL=log.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C;;;;GAIG;AACH,MAAM,OAAO,YAAY;IACN,GAAG,GAAgB,EAAE,CAAC;IAEvC,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;IACzB,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,EAAa;QAClB,IAAI,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG,mBAAmB,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CACzE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAC,IAAI,CAAC,GAAyB;QACnC,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,qDAAqD;IACrD,IAAI;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;IAED;;;;;OAKG;IACH,SAAS;QACP,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;QAC5C,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAC1B,IAAI,CAAC,EAAE,CAAC,MAAM;gBAAE,SAAS;YACzB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,IAAI;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;;gBACtB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;QACxC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;YACxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,IAAI,GAAG,CACZ,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CACtE,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,OAAe;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QACL,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;QAC/C,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,IAAI;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;iBACnB,CAAC;gBACJ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;YACtB,OAAO;gBACL,EAAE;gBACF,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,GAAG;gBACH,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aAC7C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAsB,MAAS,EAAE,OAAgC;QACnE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAC1B,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mDAAmD;IACnD,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;CACF"}
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"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"}