@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.
- package/README.md +7 -0
- package/dist/app.d.ts +17 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js.map +1 -1
- package/dist/arrange.d.ts +3 -2
- package/dist/arrange.d.ts.map +1 -1
- package/dist/arrange.js +19 -2
- package/dist/arrange.js.map +1 -1
- package/dist/beginning.d.ts +5 -2
- package/dist/beginning.d.ts.map +1 -1
- package/dist/beginning.js +28 -0
- package/dist/beginning.js.map +1 -1
- package/dist/capabilities.d.ts +32 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +31 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cli/check/index.d.ts +1 -0
- package/dist/cli/check/index.d.ts.map +1 -1
- package/dist/cli/check/index.js +1 -0
- package/dist/cli/check/index.js.map +1 -1
- package/dist/cli/check/lenses.d.ts.map +1 -1
- package/dist/cli/check/lenses.js +25 -0
- package/dist/cli/check/lenses.js.map +1 -1
- package/dist/cli/check/policy.d.ts.map +1 -1
- package/dist/cli/check/policy.js +35 -0
- package/dist/cli/check/policy.js.map +1 -1
- package/dist/cli/check/relations.d.ts.map +1 -1
- package/dist/cli/check/relations.js +31 -0
- package/dist/cli/check/relations.js.map +1 -1
- package/dist/cli/check/views.d.ts +14 -0
- package/dist/cli/check/views.d.ts.map +1 -0
- package/dist/cli/check/views.js +27 -0
- package/dist/cli/check/views.js.map +1 -0
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +2 -1
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/create.d.ts +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +63 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.d.ts +18 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +66 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/conformance/fixtures.d.ts +41 -0
- package/dist/conformance/fixtures.d.ts.map +1 -0
- package/dist/conformance/fixtures.js +950 -0
- package/dist/conformance/fixtures.js.map +1 -0
- package/dist/conformance/index.d.ts +54 -0
- package/dist/conformance/index.d.ts.map +1 -0
- package/dist/conformance/index.js +81 -0
- package/dist/conformance/index.js.map +1 -0
- package/dist/document/canonical.d.ts +4 -0
- package/dist/document/canonical.d.ts.map +1 -0
- package/dist/document/canonical.js +29 -0
- package/dist/document/canonical.js.map +1 -0
- package/dist/document/compile.d.ts +43 -0
- package/dist/document/compile.d.ts.map +1 -0
- package/dist/document/compile.js +807 -0
- package/dist/document/compile.js.map +1 -0
- package/dist/document/diff.d.ts +32 -0
- package/dist/document/diff.d.ts.map +1 -0
- package/dist/document/diff.js +148 -0
- package/dist/document/diff.js.map +1 -0
- package/dist/document/edit.d.ts +63 -0
- package/dist/document/edit.d.ts.map +1 -0
- package/dist/document/edit.js +1432 -0
- package/dist/document/edit.js.map +1 -0
- package/dist/document/expr/analyze.d.ts +14 -0
- package/dist/document/expr/analyze.d.ts.map +1 -0
- package/dist/document/expr/analyze.js +52 -0
- package/dist/document/expr/analyze.js.map +1 -0
- package/dist/document/expr/evaluate.d.ts +36 -0
- package/dist/document/expr/evaluate.d.ts.map +1 -0
- package/dist/document/expr/evaluate.js +344 -0
- package/dist/document/expr/evaluate.js.map +1 -0
- package/dist/document/expr/index.d.ts +8 -0
- package/dist/document/expr/index.d.ts.map +1 -0
- package/dist/document/expr/index.js +5 -0
- package/dist/document/expr/index.js.map +1 -0
- package/dist/document/expr/parse.d.ts +50 -0
- package/dist/document/expr/parse.d.ts.map +1 -0
- package/dist/document/expr/parse.js +240 -0
- package/dist/document/expr/parse.js.map +1 -0
- package/dist/document/expr/print.d.ts +4 -0
- package/dist/document/expr/print.d.ts.map +1 -0
- package/dist/document/expr/print.js +81 -0
- package/dist/document/expr/print.js.map +1 -0
- package/dist/document/findings.d.ts +15 -0
- package/dist/document/findings.d.ts.map +1 -0
- package/dist/document/findings.js +30 -0
- package/dist/document/findings.js.map +1 -0
- package/dist/document/graview-template.d.ts +148 -0
- package/dist/document/graview-template.d.ts.map +1 -0
- package/dist/document/graview-template.js +450 -0
- package/dist/document/graview-template.js.map +1 -0
- package/dist/document/index.d.ts +27 -0
- package/dist/document/index.d.ts.map +1 -0
- package/dist/document/index.js +16 -0
- package/dist/document/index.js.map +1 -0
- package/dist/document/migrate.d.ts +41 -0
- package/dist/document/migrate.d.ts.map +1 -0
- package/dist/document/migrate.js +252 -0
- package/dist/document/migrate.js.map +1 -0
- package/dist/document/patch.d.ts +16 -0
- package/dist/document/patch.d.ts.map +1 -0
- package/dist/document/patch.js +79 -0
- package/dist/document/patch.js.map +1 -0
- package/dist/document/rules.d.ts +40 -0
- package/dist/document/rules.d.ts.map +1 -0
- package/dist/document/rules.js +88 -0
- package/dist/document/rules.js.map +1 -0
- package/dist/document/schema.d.ts +461 -0
- package/dist/document/schema.d.ts.map +1 -0
- package/dist/document/schema.js +199 -0
- package/dist/document/schema.js.map +1 -0
- package/dist/document/template.d.ts +28 -0
- package/dist/document/template.d.ts.map +1 -0
- package/dist/document/template.js +117 -0
- package/dist/document/template.js.map +1 -0
- package/dist/document/to-document.d.ts +34 -0
- package/dist/document/to-document.d.ts.map +1 -0
- package/dist/document/to-document.js +186 -0
- package/dist/document/to-document.js.map +1 -0
- package/dist/document/upgrade.d.ts +9 -0
- package/dist/document/upgrade.d.ts.map +1 -0
- package/dist/document/upgrade.js +19 -0
- package/dist/document/upgrade.js.map +1 -0
- package/dist/document/views.d.ts +65 -0
- package/dist/document/views.d.ts.map +1 -0
- package/dist/document/views.js +264 -0
- package/dist/document/views.js.map +1 -0
- package/dist/formats.d.ts +50 -0
- package/dist/formats.d.ts.map +1 -0
- package/dist/formats.js +75 -0
- package/dist/formats.js.map +1 -0
- package/dist/graph/graph.d.ts +61 -3
- package/dist/graph/graph.d.ts.map +1 -1
- package/dist/graph/graph.js +187 -20
- package/dist/graph/graph.js.map +1 -1
- package/dist/index.d.ts +43 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -11
- package/dist/index.js.map +1 -1
- package/dist/integrity.d.ts +46 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/integrity.js +179 -0
- package/dist/integrity.js.map +1 -0
- package/dist/invariants/engine.d.ts +8 -0
- package/dist/invariants/engine.d.ts.map +1 -1
- package/dist/invariants/engine.js +40 -2
- package/dist/invariants/engine.js.map +1 -1
- package/dist/invariants/types.d.ts +19 -0
- package/dist/invariants/types.d.ts.map +1 -1
- package/dist/labels.d.ts +65 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +123 -0
- package/dist/labels.js.map +1 -0
- package/dist/mutations/define-mutation.d.ts.map +1 -1
- package/dist/mutations/define-mutation.js +5 -6
- package/dist/mutations/define-mutation.js.map +1 -1
- package/dist/mutations/derive-edits.d.ts.map +1 -1
- package/dist/mutations/derive-edits.js +20 -1
- package/dist/mutations/derive-edits.js.map +1 -1
- package/dist/mutations/form.d.ts +9 -0
- package/dist/mutations/form.d.ts.map +1 -1
- package/dist/mutations/form.js +20 -0
- package/dist/mutations/form.js.map +1 -1
- package/dist/mutations/node-ref.d.ts +6 -0
- package/dist/mutations/node-ref.d.ts.map +1 -1
- package/dist/mutations/node-ref.js +22 -8
- package/dist/mutations/node-ref.js.map +1 -1
- package/dist/mutations/types.d.ts +8 -0
- package/dist/mutations/types.d.ts.map +1 -1
- package/dist/mutations/words.d.ts +49 -0
- package/dist/mutations/words.d.ts.map +1 -0
- package/dist/mutations/words.js +61 -0
- package/dist/mutations/words.js.map +1 -0
- package/dist/ops/log.d.ts +156 -4
- package/dist/ops/log.d.ts.map +1 -1
- package/dist/ops/log.js +234 -51
- package/dist/ops/log.js.map +1 -1
- package/dist/ops/revisions.d.ts +66 -0
- package/dist/ops/revisions.d.ts.map +1 -0
- package/dist/ops/revisions.js +97 -0
- package/dist/ops/revisions.js.map +1 -0
- package/dist/ops/types.d.ts +49 -1
- package/dist/ops/types.d.ts.map +1 -1
- package/dist/ops/undo.d.ts +29 -2
- package/dist/ops/undo.d.ts.map +1 -1
- package/dist/ops/undo.js +110 -1
- package/dist/ops/undo.js.map +1 -1
- package/dist/ops/withheld.d.ts +37 -0
- package/dist/ops/withheld.d.ts.map +1 -0
- package/dist/ops/withheld.js +84 -0
- package/dist/ops/withheld.js.map +1 -0
- package/dist/permissions/policy.d.ts +15 -0
- package/dist/permissions/policy.d.ts.map +1 -1
- package/dist/permissions/policy.js +28 -1
- package/dist/permissions/policy.js.map +1 -1
- package/dist/permissions/sight.d.ts +66 -0
- package/dist/permissions/sight.d.ts.map +1 -0
- package/dist/permissions/sight.js +131 -0
- package/dist/permissions/sight.js.map +1 -0
- package/dist/permissions/types.d.ts +26 -0
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/permissions/types.js.map +1 -1
- package/dist/persistence/memory.d.ts.map +1 -1
- package/dist/persistence/memory.js +25 -0
- package/dist/persistence/memory.js.map +1 -1
- package/dist/persistence/sql.d.ts +43 -0
- package/dist/persistence/sql.d.ts.map +1 -0
- package/dist/persistence/sql.js +154 -0
- package/dist/persistence/sql.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +17 -3
- package/dist/persistence/sqlite.d.ts.map +1 -1
- package/dist/persistence/sqlite.js +32 -96
- package/dist/persistence/sqlite.js.map +1 -1
- package/dist/persistence/types.d.ts +19 -0
- package/dist/persistence/types.d.ts.map +1 -1
- package/dist/presence.d.ts +56 -0
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +62 -2
- package/dist/presence.js.map +1 -1
- package/dist/refusal.d.ts +34 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +40 -0
- package/dist/refusal.js.map +1 -0
- package/dist/scaffold/from-template.d.ts +16 -0
- package/dist/scaffold/from-template.d.ts.map +1 -0
- package/dist/scaffold/from-template.js +157 -0
- package/dist/scaffold/from-template.js.map +1 -0
- package/dist/scaffold/index.d.ts +10 -1
- package/dist/scaffold/index.d.ts.map +1 -1
- package/dist/scaffold/index.js +35 -7
- package/dist/scaffold/index.js.map +1 -1
- package/dist/scaffold/names.d.ts +4 -0
- package/dist/scaffold/names.d.ts.map +1 -1
- package/dist/scaffold/names.js.map +1 -1
- package/dist/scaffold/project.d.ts +1 -1
- package/dist/scaffold/project.d.ts.map +1 -1
- package/dist/scaffold/project.js +44 -13
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/ui.d.ts.map +1 -1
- package/dist/scaffold/ui.js +19 -10
- package/dist/scaffold/ui.js.map +1 -1
- package/dist/schema/define-node.d.ts +20 -0
- package/dist/schema/define-node.d.ts.map +1 -1
- package/dist/schema/define-node.js +27 -2
- package/dist/schema/define-node.js.map +1 -1
- package/dist/schema/path.d.ts +19 -0
- package/dist/schema/path.d.ts.map +1 -0
- package/dist/schema/path.js +34 -0
- package/dist/schema/path.js.map +1 -0
- package/dist/schema/types.d.ts +17 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/seen.d.ts +64 -0
- package/dist/seen.d.ts.map +1 -0
- package/dist/seen.js +200 -0
- package/dist/seen.js.map +1 -0
- package/dist/store.d.ts +378 -8
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +801 -41
- package/dist/store.js.map +1 -1
- package/dist/testing.d.ts +6 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +3 -1
- package/dist/testing.js.map +1 -1
- package/dist/theme/palettes.d.ts.map +1 -1
- package/dist/theme/palettes.js +4 -0
- package/dist/theme/palettes.js.map +1 -1
- package/dist/theme/types.d.ts +9 -0
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/types.js +4 -0
- package/dist/theme/types.js.map +1 -1
- package/dist/validate-graph.d.ts +84 -0
- package/dist/validate-graph.d.ts.map +1 -0
- package/dist/validate-graph.js +295 -0
- package/dist/validate-graph.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/views/types.d.ts +8 -0
- package/dist/views/types.d.ts.map +1 -1
- package/dist/views/types.js +5 -0
- package/dist/views/types.js.map +1 -1
- package/dist/watched.d.ts +39 -0
- package/dist/watched.d.ts.map +1 -1
- package/dist/watched.js +94 -1
- package/dist/watched.js.map +1 -1
- package/dist/who.d.ts +24 -1
- package/dist/who.d.ts.map +1 -1
- package/dist/who.js +49 -2
- package/dist/who.js.map +1 -1
- 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
|
|
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
|
-
/**
|
|
15
|
-
|
|
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
|
-
/**
|
|
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
|
package/dist/ops/log.d.ts.map
CHANGED
|
@@ -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,
|
|
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.
|
|
17
|
-
throw new Error(`Op "${op.id}" has seq ${op.seq} but the log is ${this.
|
|
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
|
-
/**
|
|
22
|
-
|
|
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
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
package/dist/ops/log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"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"}
|