@graview/core 0.1.0
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/LICENSE +96 -0
- package/README.md +35 -0
- package/dist/app.d.ts +294 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +49 -0
- package/dist/app.js.map +1 -0
- package/dist/arrange.d.ts +185 -0
- package/dist/arrange.d.ts.map +1 -0
- package/dist/arrange.js +456 -0
- package/dist/arrange.js.map +1 -0
- package/dist/beginning.d.ts +65 -0
- package/dist/beginning.d.ts.map +1 -0
- package/dist/beginning.js +94 -0
- package/dist/beginning.js.map +1 -0
- package/dist/bind.d.ts +42 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +26 -0
- package/dist/bind.js.map +1 -0
- package/dist/city.d.ts +93 -0
- package/dist/city.d.ts.map +1 -0
- package/dist/city.js +160 -0
- package/dist/city.js.map +1 -0
- package/dist/cli/check/arrangement.d.ts +13 -0
- package/dist/cli/check/arrangement.d.ts.map +1 -0
- package/dist/cli/check/arrangement.js +63 -0
- package/dist/cli/check/arrangement.js.map +1 -0
- package/dist/cli/check/beginnings.d.ts +16 -0
- package/dist/cli/check/beginnings.d.ts.map +1 -0
- package/dist/cli/check/beginnings.js +53 -0
- package/dist/cli/check/beginnings.js.map +1 -0
- package/dist/cli/check/brand.d.ts +17 -0
- package/dist/cli/check/brand.d.ts.map +1 -0
- package/dist/cli/check/brand.js +153 -0
- package/dist/cli/check/brand.js.map +1 -0
- package/dist/cli/check/city.d.ts +17 -0
- package/dist/cli/check/city.d.ts.map +1 -0
- package/dist/cli/check/city.js +58 -0
- package/dist/cli/check/city.js.map +1 -0
- package/dist/cli/check/context.d.ts +50 -0
- package/dist/cli/check/context.d.ts.map +1 -0
- package/dist/cli/check/context.js +37 -0
- package/dist/cli/check/context.js.map +1 -0
- package/dist/cli/check/fields.d.ts +16 -0
- package/dist/cli/check/fields.d.ts.map +1 -0
- package/dist/cli/check/fields.js +237 -0
- package/dist/cli/check/fields.js.map +1 -0
- package/dist/cli/check/index.d.ts +14 -0
- package/dist/cli/check/index.d.ts.map +1 -0
- package/dist/cli/check/index.js +14 -0
- package/dist/cli/check/index.js.map +1 -0
- package/dist/cli/check/intelligence.d.ts +17 -0
- package/dist/cli/check/intelligence.d.ts.map +1 -0
- package/dist/cli/check/intelligence.js +136 -0
- package/dist/cli/check/intelligence.js.map +1 -0
- package/dist/cli/check/lenses.d.ts +17 -0
- package/dist/cli/check/lenses.d.ts.map +1 -0
- package/dist/cli/check/lenses.js +239 -0
- package/dist/cli/check/lenses.js.map +1 -0
- package/dist/cli/check/migrations.d.ts +16 -0
- package/dist/cli/check/migrations.d.ts.map +1 -0
- package/dist/cli/check/migrations.js +43 -0
- package/dist/cli/check/migrations.js.map +1 -0
- package/dist/cli/check/modules.d.ts +16 -0
- package/dist/cli/check/modules.d.ts.map +1 -0
- package/dist/cli/check/modules.js +123 -0
- package/dist/cli/check/modules.js.map +1 -0
- package/dist/cli/check/policy.d.ts +16 -0
- package/dist/cli/check/policy.d.ts.map +1 -0
- package/dist/cli/check/policy.js +90 -0
- package/dist/cli/check/policy.js.map +1 -0
- package/dist/cli/check/relations.d.ts +29 -0
- package/dist/cli/check/relations.d.ts.map +1 -0
- package/dist/cli/check/relations.js +279 -0
- package/dist/cli/check/relations.js.map +1 -0
- package/dist/cli/check/routes.d.ts +16 -0
- package/dist/cli/check/routes.d.ts.map +1 -0
- package/dist/cli/check/routes.js +31 -0
- package/dist/cli/check/routes.js.map +1 -0
- package/dist/cli/check/settings.d.ts +16 -0
- package/dist/cli/check/settings.d.ts.map +1 -0
- package/dist/cli/check/settings.js +81 -0
- package/dist/cli/check/settings.js.map +1 -0
- package/dist/cli/check.d.ts +36 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +76 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/create.d.ts +20 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +251 -0
- package/dist/cli/create.js.map +1 -0
- package/dist/cli/describe.d.ts +35 -0
- package/dist/cli/describe.d.ts.map +1 -0
- package/dist/cli/describe.js +230 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/docs.d.ts +11 -0
- package/dist/cli/docs.d.ts.map +1 -0
- package/dist/cli/docs.js +152 -0
- package/dist/cli/docs.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +281 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/extend.d.ts +23 -0
- package/dist/extend.d.ts.map +1 -0
- package/dist/extend.js +53 -0
- package/dist/extend.js.map +1 -0
- package/dist/graph/diff.d.ts +31 -0
- package/dist/graph/diff.d.ts.map +1 -0
- package/dist/graph/diff.js +71 -0
- package/dist/graph/diff.js.map +1 -0
- package/dist/graph/graph.d.ts +69 -0
- package/dist/graph/graph.d.ts.map +1 -0
- package/dist/graph/graph.js +284 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/primitives.d.ts +52 -0
- package/dist/graph/primitives.d.ts.map +1 -0
- package/dist/graph/primitives.js +62 -0
- package/dist/graph/primitives.js.map +1 -0
- package/dist/graph/tracked.d.ts +31 -0
- package/dist/graph/tracked.d.ts.map +1 -0
- package/dist/graph/tracked.js +69 -0
- package/dist/graph/tracked.js.map +1 -0
- package/dist/graph/types.d.ts +34 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +0 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/installation.d.ts +112 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +193 -0
- package/dist/installation.js.map +1 -0
- package/dist/intelligence-bridge.d.ts +73 -0
- package/dist/intelligence-bridge.d.ts.map +1 -0
- package/dist/intelligence-bridge.js +31 -0
- package/dist/intelligence-bridge.js.map +1 -0
- package/dist/invariants/engine.d.ts +36 -0
- package/dist/invariants/engine.d.ts.map +1 -0
- package/dist/invariants/engine.js +88 -0
- package/dist/invariants/engine.js.map +1 -0
- package/dist/invariants/types.d.ts +75 -0
- package/dist/invariants/types.d.ts.map +1 -0
- package/dist/invariants/types.js +2 -0
- package/dist/invariants/types.js.map +1 -0
- package/dist/modules.d.ts +75 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +87 -0
- package/dist/modules.js.map +1 -0
- package/dist/mutations/decidable.d.ts +26 -0
- package/dist/mutations/decidable.d.ts.map +1 -0
- package/dist/mutations/decidable.js +39 -0
- package/dist/mutations/decidable.js.map +1 -0
- package/dist/mutations/define-mutation.d.ts +32 -0
- package/dist/mutations/define-mutation.d.ts.map +1 -0
- package/dist/mutations/define-mutation.js +181 -0
- package/dist/mutations/define-mutation.js.map +1 -0
- package/dist/mutations/derive-edits.d.ts +75 -0
- package/dist/mutations/derive-edits.d.ts.map +1 -0
- package/dist/mutations/derive-edits.js +240 -0
- package/dist/mutations/derive-edits.js.map +1 -0
- package/dist/mutations/form.d.ts +63 -0
- package/dist/mutations/form.d.ts.map +1 -0
- package/dist/mutations/form.js +113 -0
- package/dist/mutations/form.js.map +1 -0
- package/dist/mutations/node-ref.d.ts +83 -0
- package/dist/mutations/node-ref.d.ts.map +1 -0
- package/dist/mutations/node-ref.js +113 -0
- package/dist/mutations/node-ref.js.map +1 -0
- package/dist/mutations/types.d.ts +136 -0
- package/dist/mutations/types.d.ts.map +1 -0
- package/dist/mutations/types.js +2 -0
- package/dist/mutations/types.js.map +1 -0
- package/dist/ops/log.d.ts +35 -0
- package/dist/ops/log.d.ts.map +1 -0
- package/dist/ops/log.js +103 -0
- package/dist/ops/log.js.map +1 -0
- package/dist/ops/types.d.ts +52 -0
- package/dist/ops/types.d.ts.map +1 -0
- package/dist/ops/types.js +2 -0
- package/dist/ops/types.js.map +1 -0
- package/dist/ops/undo.d.ts +33 -0
- package/dist/ops/undo.d.ts.map +1 -0
- package/dist/ops/undo.js +65 -0
- package/dist/ops/undo.js.map +1 -0
- package/dist/permissions/policy.d.ts +68 -0
- package/dist/permissions/policy.d.ts.map +1 -0
- package/dist/permissions/policy.js +191 -0
- package/dist/permissions/policy.js.map +1 -0
- package/dist/permissions/types.d.ts +78 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/persistence/memory.d.ts +6 -0
- package/dist/persistence/memory.d.ts.map +1 -0
- package/dist/persistence/memory.js +31 -0
- package/dist/persistence/memory.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +59 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +22 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +2 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/presence.d.ts +38 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +50 -0
- package/dist/presence.js.map +1 -0
- package/dist/scaffold/domain.d.ts +8 -0
- package/dist/scaffold/domain.d.ts.map +1 -0
- package/dist/scaffold/domain.js +331 -0
- package/dist/scaffold/domain.js.map +1 -0
- package/dist/scaffold/index.d.ts +66 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +142 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lens.d.ts +31 -0
- package/dist/scaffold/lens.d.ts.map +1 -0
- package/dist/scaffold/lens.js +176 -0
- package/dist/scaffold/lens.js.map +1 -0
- package/dist/scaffold/names.d.ts +44 -0
- package/dist/scaffold/names.d.ts.map +1 -0
- package/dist/scaffold/names.js +69 -0
- package/dist/scaffold/names.js.map +1 -0
- package/dist/scaffold/project.d.ts +41 -0
- package/dist/scaffold/project.d.ts.map +1 -0
- package/dist/scaffold/project.js +604 -0
- package/dist/scaffold/project.js.map +1 -0
- package/dist/scaffold/ui.d.ts +15 -0
- package/dist/scaffold/ui.d.ts.map +1 -0
- package/dist/scaffold/ui.js +536 -0
- package/dist/scaffold/ui.js.map +1 -0
- package/dist/schema/define-node.d.ts +132 -0
- package/dist/schema/define-node.d.ts.map +1 -0
- package/dist/schema/define-node.js +254 -0
- package/dist/schema/define-node.js.map +1 -0
- package/dist/schema/figures.d.ts +42 -0
- package/dist/schema/figures.d.ts.map +1 -0
- package/dist/schema/figures.js +220 -0
- package/dist/schema/figures.js.map +1 -0
- package/dist/schema/json-schema.d.ts +39 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +74 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +43 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +102 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/types.d.ts +201 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/search.d.ts +215 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +449 -0
- package/dist/search.js.map +1 -0
- package/dist/settings.d.ts +30 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +74 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +284 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +660 -0
- package/dist/store.js.map +1 -0
- package/dist/studio-door.d.ts +187 -0
- package/dist/studio-door.d.ts.map +1 -0
- package/dist/studio-door.js +20 -0
- package/dist/studio-door.js.map +1 -0
- package/dist/sync/conflict.d.ts +37 -0
- package/dist/sync/conflict.d.ts.map +1 -0
- package/dist/sync/conflict.js +56 -0
- package/dist/sync/conflict.js.map +1 -0
- package/dist/sync/engine.d.ts +118 -0
- package/dist/sync/engine.d.ts.map +1 -0
- package/dist/sync/engine.js +341 -0
- package/dist/sync/engine.js.map +1 -0
- package/dist/sync/google-calendar.d.ts +54 -0
- package/dist/sync/google-calendar.d.ts.map +1 -0
- package/dist/sync/google-calendar.js +167 -0
- package/dist/sync/google-calendar.js.map +1 -0
- package/dist/sync/types.d.ts +125 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +6 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/temporal/effectivity.d.ts +75 -0
- package/dist/temporal/effectivity.d.ts.map +1 -0
- package/dist/temporal/effectivity.js +89 -0
- package/dist/temporal/effectivity.js.map +1 -0
- package/dist/testing.d.ts +63 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +194 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme/contrast.d.ts +47 -0
- package/dist/theme/contrast.d.ts.map +1 -0
- package/dist/theme/contrast.js +172 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/derive.d.ts +81 -0
- package/dist/theme/derive.d.ts.map +1 -0
- package/dist/theme/derive.js +171 -0
- package/dist/theme/derive.js.map +1 -0
- package/dist/theme/kit.d.ts +106 -0
- package/dist/theme/kit.d.ts.map +1 -0
- package/dist/theme/kit.js +84 -0
- package/dist/theme/kit.js.map +1 -0
- package/dist/theme/palettes.d.ts +32 -0
- package/dist/theme/palettes.d.ts.map +1 -0
- package/dist/theme/palettes.js +96 -0
- package/dist/theme/palettes.js.map +1 -0
- package/dist/theme/types.d.ts +131 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +23 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/views/types.d.ts +89 -0
- package/dist/views/types.d.ts.map +1 -0
- package/dist/views/types.js +88 -0
- package/dist/views/types.js.map +1 -0
- package/dist/watched.d.ts +33 -0
- package/dist/watched.d.ts.map +1 -0
- package/dist/watched.js +50 -0
- package/dist/watched.js.map +1 -0
- package/dist/who.d.ts +26 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +20 -0
- package/dist/who.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { describeArg, nodeRefKinds, unwrap } from "./node-ref.js";
|
|
2
|
+
const isOptional = (schema) => schema.safeParse?.(undefined).success ?? false;
|
|
3
|
+
const shapeOf = (schema) => unwrap(schema).shape;
|
|
4
|
+
/** The single literal value of a zod literal, or undefined. */
|
|
5
|
+
const literalValue = (schema) => {
|
|
6
|
+
const field = unwrap(schema);
|
|
7
|
+
if (field._def?.type !== "literal")
|
|
8
|
+
return undefined;
|
|
9
|
+
const values = field._def.values;
|
|
10
|
+
return values && values.length === 1 && typeof values[0] === "string" ? values[0] : undefined;
|
|
11
|
+
};
|
|
12
|
+
/** Describes one argument as a form control tree. */
|
|
13
|
+
export function formField(name, schema) {
|
|
14
|
+
const optional = isOptional(schema);
|
|
15
|
+
const field = unwrap(schema);
|
|
16
|
+
const type = field._def?.type;
|
|
17
|
+
const kinds = nodeRefKinds(schema);
|
|
18
|
+
if (kinds)
|
|
19
|
+
return { control: "node", name, optional, kinds };
|
|
20
|
+
if (type === "boolean")
|
|
21
|
+
return { control: "boolean", name, optional };
|
|
22
|
+
if (type === "object") {
|
|
23
|
+
const shape = field.shape ?? {};
|
|
24
|
+
return {
|
|
25
|
+
control: "group",
|
|
26
|
+
name,
|
|
27
|
+
optional,
|
|
28
|
+
fields: Object.entries(shape).map(([child, childSchema]) => formField(child, childSchema)),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (type === "union") {
|
|
32
|
+
const options = field._def?.options ?? [];
|
|
33
|
+
/*
|
|
34
|
+
* A DISCRIMINATED union renders as one picker and then that option's
|
|
35
|
+
* fields — the household example's constraint spec is the canonical case. The tag is
|
|
36
|
+
* whichever literal field every option shares; without one, a union of
|
|
37
|
+
* scalars collapses to a choice when every arm is a literal, and
|
|
38
|
+
* anything else is opaque rather than guessed at.
|
|
39
|
+
*/
|
|
40
|
+
const shapes = options.map((option) => shapeOf(option));
|
|
41
|
+
if (shapes.every((shape) => shape !== undefined)) {
|
|
42
|
+
const tag = Object.keys(shapes[0] ?? {}).find((key) => shapes.every((shape) => literalValue(shape?.[key]) !== undefined));
|
|
43
|
+
if (tag) {
|
|
44
|
+
return {
|
|
45
|
+
control: "variant",
|
|
46
|
+
name,
|
|
47
|
+
optional,
|
|
48
|
+
tag,
|
|
49
|
+
options: options.map((_, index) => ({
|
|
50
|
+
value: literalValue(shapes[index]?.[tag]) ?? "",
|
|
51
|
+
fields: Object.entries(shapes[index] ?? {})
|
|
52
|
+
.filter(([key]) => key !== tag)
|
|
53
|
+
.map(([child, childSchema]) => formField(child, childSchema)),
|
|
54
|
+
})),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const literals = options.map((option) => literalValue(option));
|
|
59
|
+
if (literals.every((value) => value !== undefined)) {
|
|
60
|
+
return { control: "choice", name, optional, options: literals };
|
|
61
|
+
}
|
|
62
|
+
return { control: "opaque", name, optional };
|
|
63
|
+
}
|
|
64
|
+
if (type === "array") {
|
|
65
|
+
const element = field._def?.element;
|
|
66
|
+
if (element !== undefined) {
|
|
67
|
+
return { control: "list", name, optional, item: formField(name, element) };
|
|
68
|
+
}
|
|
69
|
+
return { control: "opaque", name, optional };
|
|
70
|
+
}
|
|
71
|
+
const scalar = describeArg(schema);
|
|
72
|
+
if (scalar.type === "text")
|
|
73
|
+
return { control: "text", name, optional };
|
|
74
|
+
if (scalar.type === "date")
|
|
75
|
+
return { control: "date", name, optional, ...(scalar.time ? { time: true } : {}) };
|
|
76
|
+
if (scalar.type === "number") {
|
|
77
|
+
return {
|
|
78
|
+
control: "number",
|
|
79
|
+
name,
|
|
80
|
+
optional,
|
|
81
|
+
...(scalar.min === undefined ? {} : { min: scalar.min }),
|
|
82
|
+
...(scalar.max === undefined ? {} : { max: scalar.max }),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (scalar.type === "choice")
|
|
86
|
+
return { control: "choice", name, optional, options: scalar.options };
|
|
87
|
+
return { control: "opaque", name, optional };
|
|
88
|
+
}
|
|
89
|
+
/** The whole form for a mutation input object, one field per argument. */
|
|
90
|
+
export function formFields(input) {
|
|
91
|
+
const shape = input.shape;
|
|
92
|
+
if (!shape)
|
|
93
|
+
return [];
|
|
94
|
+
return Object.entries(shape).map(([name, schema]) => formField(name, schema));
|
|
95
|
+
}
|
|
96
|
+
/** True when every control in the tree is renderable — nothing opaque. */
|
|
97
|
+
export function formComplete(fields) {
|
|
98
|
+
return fields.every((field) => {
|
|
99
|
+
switch (field.control) {
|
|
100
|
+
case "opaque":
|
|
101
|
+
return false;
|
|
102
|
+
case "group":
|
|
103
|
+
return formComplete(field.fields);
|
|
104
|
+
case "variant":
|
|
105
|
+
return field.options.every((option) => formComplete(option.fields));
|
|
106
|
+
case "list":
|
|
107
|
+
return formComplete([field.item]);
|
|
108
|
+
default:
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/mutations/form.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* A mutation argument that names a node. Declaring the acceptable kinds is
|
|
4
|
+
* what lets the affordance layer bind a selection to an argument without
|
|
5
|
+
* anyone writing per-selection code, and lets an agent tool schema say
|
|
6
|
+
* which ids are legal.
|
|
7
|
+
*/
|
|
8
|
+
export declare function nodeRef<const K extends string>(kinds?: readonly K[] | "*"): z.ZodString;
|
|
9
|
+
/** The node kinds an argument accepts, or undefined if it is not a node ref. */
|
|
10
|
+
export declare function nodeRefKinds(schema: unknown): readonly string[] | undefined;
|
|
11
|
+
/** Reads the node-ref arguments off a mutation input object schema. */
|
|
12
|
+
export declare function nodeRefArgs(input: z.ZodType): {
|
|
13
|
+
name: string;
|
|
14
|
+
kinds: readonly string[];
|
|
15
|
+
optional: boolean;
|
|
16
|
+
}[];
|
|
17
|
+
/**
|
|
18
|
+
* What sort of answer an argument wants, read off its own declaration.
|
|
19
|
+
*
|
|
20
|
+
* The affordance layer could already say "this needs a `label`" and offer
|
|
21
|
+
* candidate ids for a node reference — but for a plain string or a date it
|
|
22
|
+
* offered a list of nothing, so half the actions in an interface were dead
|
|
23
|
+
* ends that looked live. The mutation's schema knows perfectly well that
|
|
24
|
+
* `label` is a non-empty string and `date` is `YYYY-MM-DD`; nothing had
|
|
25
|
+
* asked it.
|
|
26
|
+
*/
|
|
27
|
+
export type ArgShape = {
|
|
28
|
+
readonly type: "text";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A DATE, AND WITH `time` A TIME OF DAY IN IT. A workshop's start is
|
|
32
|
+
* `YYYY-MM-DDTHH:MM`; read as a plain date it got a date picker, whose
|
|
33
|
+
* `YYYY-MM-DD` the act's own pattern refused — on every face, so the
|
|
34
|
+
* workshop could not be made and the talk could not be given its slot.
|
|
35
|
+
*/
|
|
36
|
+
| {
|
|
37
|
+
readonly type: "date";
|
|
38
|
+
readonly time?: true;
|
|
39
|
+
} | {
|
|
40
|
+
readonly type: "number";
|
|
41
|
+
readonly min?: number;
|
|
42
|
+
readonly max?: number;
|
|
43
|
+
} | {
|
|
44
|
+
readonly type: "choice";
|
|
45
|
+
readonly options: readonly string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* YES OR NO — an argument that takes a boolean.
|
|
49
|
+
*
|
|
50
|
+
* Undescribable until now, for the same reason a list was: an interface
|
|
51
|
+
* can only offer what it can ask for, so "Add a field" — whose `required`
|
|
52
|
+
* is a plain boolean — was derived NOWHERE. The studio's central act, in
|
|
53
|
+
* the studio, unreachable, because nothing could ask one question.
|
|
54
|
+
*/
|
|
55
|
+
| {
|
|
56
|
+
readonly type: "boolean";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* SEVERAL OF A THING — an argument that takes a list.
|
|
60
|
+
*
|
|
61
|
+
* "Invite somebody as coordinator and gardener" is one act with two roles
|
|
62
|
+
* in one argument, and without this shape it described itself as `unknown`:
|
|
63
|
+
* an interface can only offer what it can ask for, so the act was offered
|
|
64
|
+
* NOWHERE. Not hidden behind a refusal — simply never derived, in every
|
|
65
|
+
* installation the framework ships.
|
|
66
|
+
*/
|
|
67
|
+
| {
|
|
68
|
+
readonly type: "several";
|
|
69
|
+
readonly of: ArgShape;
|
|
70
|
+
} | {
|
|
71
|
+
readonly type: "unknown";
|
|
72
|
+
};
|
|
73
|
+
/** Unwraps optional/default/nullable so a wrapped field still describes itself. */
|
|
74
|
+
export declare function unwrap(schema: unknown): unknown;
|
|
75
|
+
/**
|
|
76
|
+
* Zod 4 keeps the primitive type on `_def.type` and the refinements a UI
|
|
77
|
+
* actually needs — bounds, patterns — in `_zod.bag`. Reading them here, in
|
|
78
|
+
* one place, keeps every other layer free of zod internals.
|
|
79
|
+
*/
|
|
80
|
+
export declare function describeArg(schema: unknown): ArgShape;
|
|
81
|
+
/** The declared shape of one named argument of a mutation input object. */
|
|
82
|
+
export declare function argShape(input: unknown, name: string): ArgShape;
|
|
83
|
+
//# sourceMappingURL=node-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-ref.d.ts","sourceRoot":"","sources":["../../src/mutations/node-ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAC5C,KAAK,GAAE,SAAS,CAAC,EAAE,GAAG,GAAS,GAC9B,CAAC,CAAC,SAAS,CAab;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAW3E;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CACzB,KAAK,EAAE,CAAC,CAAC,OAAO,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,EAAE,CAUjE;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC3B;;;;;GAKG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AAClE;;;;;;;GAOG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE;AAC9B;;;;;;;;GAQG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAEjC,mFAAmF;AACnF,wBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAG/C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAmDrD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAI/D"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const NODE_REFS = new WeakMap();
|
|
3
|
+
/**
|
|
4
|
+
* A mutation argument that names a node. Declaring the acceptable kinds is
|
|
5
|
+
* what lets the affordance layer bind a selection to an argument without
|
|
6
|
+
* anyone writing per-selection code, and lets an agent tool schema say
|
|
7
|
+
* which ids are legal.
|
|
8
|
+
*/
|
|
9
|
+
export function nodeRef(kinds = "*") {
|
|
10
|
+
const schema = z.string().min(1);
|
|
11
|
+
const accepted = kinds === "*" ? ["*"] : kinds;
|
|
12
|
+
NODE_REFS.set(schema, accepted);
|
|
13
|
+
/*
|
|
14
|
+
* `.describe()` and `.meta()` CLONE the schema and share its def, so a
|
|
15
|
+
* described node reference — the natural thing to write, since the
|
|
16
|
+
* description is the question a decision provider is asked — used to
|
|
17
|
+
* come back as a plain string. The def is the stable identity.
|
|
18
|
+
*/
|
|
19
|
+
const def = schema._def;
|
|
20
|
+
if (def)
|
|
21
|
+
NODE_REFS.set(def, accepted);
|
|
22
|
+
return schema;
|
|
23
|
+
}
|
|
24
|
+
/** The node kinds an argument accepts, or undefined if it is not a node ref. */
|
|
25
|
+
export function nodeRefKinds(schema) {
|
|
26
|
+
if (typeof schema !== "object" || schema === null)
|
|
27
|
+
return undefined;
|
|
28
|
+
const direct = NODE_REFS.get(schema);
|
|
29
|
+
if (direct)
|
|
30
|
+
return direct;
|
|
31
|
+
const def = schema._def;
|
|
32
|
+
const byDef = def ? NODE_REFS.get(def) : undefined;
|
|
33
|
+
if (byDef)
|
|
34
|
+
return byDef;
|
|
35
|
+
// Unwrap optional/default/nullable wrappers so `nodeRef([...]).optional()`
|
|
36
|
+
// keeps its meaning.
|
|
37
|
+
const inner = schema._def?.innerType;
|
|
38
|
+
return inner ? nodeRefKinds(inner) : undefined;
|
|
39
|
+
}
|
|
40
|
+
/** Reads the node-ref arguments off a mutation input object schema. */
|
|
41
|
+
export function nodeRefArgs(input) {
|
|
42
|
+
const shape = input.shape;
|
|
43
|
+
if (!shape)
|
|
44
|
+
return [];
|
|
45
|
+
const args = [];
|
|
46
|
+
for (const [name, field] of Object.entries(shape)) {
|
|
47
|
+
const kinds = nodeRefKinds(field);
|
|
48
|
+
if (!kinds)
|
|
49
|
+
continue;
|
|
50
|
+
args.push({ name, kinds, optional: field.safeParse(undefined).success });
|
|
51
|
+
}
|
|
52
|
+
return args;
|
|
53
|
+
}
|
|
54
|
+
/** Unwraps optional/default/nullable so a wrapped field still describes itself. */
|
|
55
|
+
export function unwrap(schema) {
|
|
56
|
+
const inner = schema._def?.innerType;
|
|
57
|
+
return inner === undefined ? schema : unwrap(inner);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Zod 4 keeps the primitive type on `_def.type` and the refinements a UI
|
|
61
|
+
* actually needs — bounds, patterns — in `_zod.bag`. Reading them here, in
|
|
62
|
+
* one place, keeps every other layer free of zod internals.
|
|
63
|
+
*/
|
|
64
|
+
export function describeArg(schema) {
|
|
65
|
+
const field = unwrap(schema);
|
|
66
|
+
const type = field?._def?.type;
|
|
67
|
+
const bag = field?._zod?.bag ?? {};
|
|
68
|
+
if (type === "enum")
|
|
69
|
+
return { type: "choice", options: Object.keys(field?._def?.entries ?? {}) };
|
|
70
|
+
if (type === "boolean")
|
|
71
|
+
return { type: "boolean" };
|
|
72
|
+
/*
|
|
73
|
+
* A list describes itself through what it holds. An array of something
|
|
74
|
+
* nothing can describe is still unknown — saying "several unknowns" would
|
|
75
|
+
* make an unaskable argument look askable, which is the failure this whole
|
|
76
|
+
* shape exists to prevent.
|
|
77
|
+
*/
|
|
78
|
+
if (type === "array") {
|
|
79
|
+
const of = describeArg(field._def?.element);
|
|
80
|
+
return of.type === "unknown" ? { type: "unknown" } : { type: "several", of };
|
|
81
|
+
}
|
|
82
|
+
if (type === "number") {
|
|
83
|
+
const min = typeof bag["minimum"] === "number" ? bag["minimum"] : undefined;
|
|
84
|
+
const max = typeof bag["maximum"] === "number" ? bag["maximum"] : undefined;
|
|
85
|
+
return {
|
|
86
|
+
type: "number",
|
|
87
|
+
...(min === undefined ? {} : { min }),
|
|
88
|
+
...(max === undefined ? {} : { max }),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (type === "string") {
|
|
92
|
+
// A date is a string with a date-shaped pattern. Recognising it means
|
|
93
|
+
// the interface offers a date picker instead of a free text box, which
|
|
94
|
+
// is the difference between an action anyone can run and one only its
|
|
95
|
+
// author knows the format for.
|
|
96
|
+
const patterns = bag["patterns"];
|
|
97
|
+
const sources = patterns instanceof Set ? [...patterns].map((pattern) => String(pattern.source)) : [];
|
|
98
|
+
if (sources.some((source) => source.includes("\\d{4}"))) {
|
|
99
|
+
// A time of day in the pattern as well: `T\d{2}:\d{2}`, or a space before it.
|
|
100
|
+
return sources.some((source) => source.includes("\\d{2}:\\d{2}")) ? { type: "date", time: true } : { type: "date" };
|
|
101
|
+
}
|
|
102
|
+
return { type: "text" };
|
|
103
|
+
}
|
|
104
|
+
return { type: "unknown" };
|
|
105
|
+
}
|
|
106
|
+
/** The declared shape of one named argument of a mutation input object. */
|
|
107
|
+
export function argShape(input, name) {
|
|
108
|
+
const shape = input?.shape;
|
|
109
|
+
if (!shape || !(name in shape))
|
|
110
|
+
return { type: "unknown" };
|
|
111
|
+
return describeArg(shape[name]);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=node-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-ref.js","sourceRoot":"","sources":["../../src/mutations/node-ref.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { Primitive } from "../graph/primitives.js";
|
|
3
|
+
import type { GraphEdge, GraphReader } from "../graph/types.js";
|
|
4
|
+
import type { AnySchema, KindOfSchema, NodeOfSchema } from "../schema/schema.js";
|
|
5
|
+
/**
|
|
6
|
+
* What a mutation is handed. Reads go through a tracked reader so the op log
|
|
7
|
+
* records causality; writes go out as primitives so every op has an inverse.
|
|
8
|
+
*/
|
|
9
|
+
export interface MutationContext<S extends AnySchema> {
|
|
10
|
+
readonly graph: GraphReader<NodeOfSchema<S>>;
|
|
11
|
+
readonly schema: S;
|
|
12
|
+
addNode(node: NodeOfSchema<S>): void;
|
|
13
|
+
/** Removes a node together with every edge touching it. */
|
|
14
|
+
removeNode(id: string): void;
|
|
15
|
+
patchNode(id: string, fields: Record<string, unknown>): void;
|
|
16
|
+
addEdge(edge: GraphEdge): void;
|
|
17
|
+
removeEdge(edge: GraphEdge): void;
|
|
18
|
+
/** Replaces every `kind` edge arriving at `to` with one from `from`. */
|
|
19
|
+
setSingleSource(kind: string, to: string, from: string): void;
|
|
20
|
+
/** A deterministic, collision-free id derived from a label. */
|
|
21
|
+
freshId(label: string, prefix?: string): string;
|
|
22
|
+
/** Raw escape hatch — prefer the helpers above. */
|
|
23
|
+
emit(primitive: Primitive): void;
|
|
24
|
+
}
|
|
25
|
+
export interface MutationDefinitionSpec<S extends AnySchema, I extends z.ZodType> {
|
|
26
|
+
readonly input: I;
|
|
27
|
+
/** Short human title, e.g. "Reassign run". */
|
|
28
|
+
readonly title?: string;
|
|
29
|
+
readonly description?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Node kinds this mutation acts on, and the argument the subject binds to.
|
|
32
|
+
* This is the seam that makes affordances derivable: given a selection of
|
|
33
|
+
* `duty` nodes, every mutation whose subject accepts `duty` is legal.
|
|
34
|
+
*/
|
|
35
|
+
readonly subject?: {
|
|
36
|
+
readonly kinds: readonly KindOfSchema<S>[] | "*";
|
|
37
|
+
readonly arg: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* True when applying this loses something a person made — a node removed,
|
|
41
|
+
* work dropped, an edge severed for good. The interface lists these after
|
|
42
|
+
* everything else and marks them; an agent seat inherits the same order.
|
|
43
|
+
* Absent means safe, which is the common case and the safe default to get
|
|
44
|
+
* wrong: an unmarked destructive mutation is merely unranked, a marked
|
|
45
|
+
* safe one is merely over-cautious.
|
|
46
|
+
*/
|
|
47
|
+
readonly destructive?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Node kinds this mutation brings into existence.
|
|
50
|
+
*
|
|
51
|
+
* The other half of the affordance seam. `subject` answers "what can I do
|
|
52
|
+
* WITH this thing"; `creates` answers the question an empty kind card
|
|
53
|
+
* poses — "how does the first one get here". Declared rather than
|
|
54
|
+
* inferred, because what `apply` adds is not statically knowable, and the
|
|
55
|
+
* empty state is exactly where a wrong guess would strand someone.
|
|
56
|
+
*
|
|
57
|
+
* An act that declares this also takes an optional `id` argument the
|
|
58
|
+
* framework adds: the id of the node it makes, when the caller has one —
|
|
59
|
+
* a seed being synced, an agent that will refer to the node in its next
|
|
60
|
+
* call. `freshId` hands it out first; an id already in the graph is
|
|
61
|
+
* refused by name rather than quietly suffixed.
|
|
62
|
+
*/
|
|
63
|
+
readonly creates?: readonly KindOfSchema<S>[];
|
|
64
|
+
/**
|
|
65
|
+
* Edge kinds this mutation makes, and edge kinds it breaks.
|
|
66
|
+
*
|
|
67
|
+
* The seam that lets a LINE offer its own actions: select the drawn edge
|
|
68
|
+
* and every mutation that declares its kind derives an offer, endpoints
|
|
69
|
+
* prefilled by matching argument kinds. Declared, like `creates`, because
|
|
70
|
+
* what `apply` does to edges is not statically knowable.
|
|
71
|
+
*/
|
|
72
|
+
readonly connects?: readonly string[];
|
|
73
|
+
readonly severs?: readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* How this act reads from the OTHER end of the tie.
|
|
76
|
+
*
|
|
77
|
+
* An act that declares what it connects or severs is offered from either
|
|
78
|
+
* endpoint — standing on a person, "take this one off the run" is the
|
|
79
|
+
* natural thing to say. The button there was labelled with `title`, which
|
|
80
|
+
* is written from the subject's side: "Hand it to someone", offered on the
|
|
81
|
+
* person, reads as handing the PERSON to someone.
|
|
82
|
+
*
|
|
83
|
+
* Declared rather than derived, for the reason `connects` is: an edge's
|
|
84
|
+
* `inverse` gives the relation's two readings but not the verb, and a
|
|
85
|
+
* guessed verb on a control that changes the graph is the wrong place to
|
|
86
|
+
* be nearly right. `graview check` warns `act-without-far-end-reading`
|
|
87
|
+
* when an act is offerable from an end it has no words for, naming that
|
|
88
|
+
* end — the same warning shape as `edge-without-inverse`.
|
|
89
|
+
*/
|
|
90
|
+
readonly fromTheOtherEnd?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Fields of the SUBJECT this mutation writes.
|
|
93
|
+
*
|
|
94
|
+
* The declared answer to "what changes this field", which the in-place
|
|
95
|
+
* edit and the derived edit act both read. Without it the framework
|
|
96
|
+
* guesses from names — an input argument called exactly like a field
|
|
97
|
+
* writes that field — which is right for `rename(label)` and blind to
|
|
98
|
+
* `finish()` setting `done`. Declared, the guess is replaced rather than
|
|
99
|
+
* added to: a mutation that says what it writes is believed about it, and
|
|
100
|
+
* only about it.
|
|
101
|
+
*/
|
|
102
|
+
readonly writes?: readonly string[];
|
|
103
|
+
/**
|
|
104
|
+
* The app saying "this is the act of this product". A pinned mutation
|
|
105
|
+
* ranks above its unpinned peers wherever actions are offered — never
|
|
106
|
+
* above a rule's repairs, never out of the destructive tail — and sits
|
|
107
|
+
* in the menu's head section. A person's own pins, made from the menu,
|
|
108
|
+
* outrank the app's.
|
|
109
|
+
*/
|
|
110
|
+
readonly pinned?: boolean;
|
|
111
|
+
/** One-line description of a concrete application, for previews and logs. */
|
|
112
|
+
readonly describe?: (args: z.infer<I>, graph: GraphReader<NodeOfSchema<S>>) => string;
|
|
113
|
+
readonly apply: (context: MutationContext<S>, args: z.infer<I>) => void;
|
|
114
|
+
}
|
|
115
|
+
export interface MutationDefinition<S extends AnySchema = AnySchema, Name extends string = string, I extends z.ZodType = z.ZodType> extends MutationDefinitionSpec<S, I> {
|
|
116
|
+
readonly name: Name;
|
|
117
|
+
/**
|
|
118
|
+
* Set by the framework on a mutation it derived rather than an app
|
|
119
|
+
* declared: the per-kind edit act, or the per-kind remove act. An edit's
|
|
120
|
+
* permission resolves through the declared acts that already write or
|
|
121
|
+
* create the kind; a remove's through the acts that create it — who may
|
|
122
|
+
* bring a thing into being may take it out — so a policy needs no second
|
|
123
|
+
* list for either.
|
|
124
|
+
*/
|
|
125
|
+
readonly derived?: {
|
|
126
|
+
readonly kind: string;
|
|
127
|
+
readonly act: "edit" | "remove";
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export type AnyMutationDefinition<S extends AnySchema = AnySchema> = MutationDefinition<S, string, z.ZodType>;
|
|
131
|
+
/** A concrete, ready-to-apply mutation: a name plus validated arguments. */
|
|
132
|
+
export interface MutationCall<Name extends string = string> {
|
|
133
|
+
readonly name: Name;
|
|
134
|
+
readonly args: Record<string, unknown>;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mutations/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mutations/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Graph } from "../graph/graph.js";
|
|
2
|
+
import type { AnySchema } from "../schema/schema.js";
|
|
3
|
+
import type { Batch, Operation } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* The append-only log. Nothing here mutates or removes an entry: an undo is
|
|
6
|
+
* a new op carrying the inverse, so history is never destroyed and the log
|
|
7
|
+
* doubles as an audit trail of what an agent did on your behalf.
|
|
8
|
+
*/
|
|
9
|
+
export declare class OperationLog {
|
|
10
|
+
private readonly ops;
|
|
11
|
+
get length(): number;
|
|
12
|
+
all(): readonly Operation[];
|
|
13
|
+
append(op: Operation): void;
|
|
14
|
+
/** Restores a log from storage, checking the sequence is intact. */
|
|
15
|
+
static from(ops: readonly Operation[]): OperationLog;
|
|
16
|
+
get(id: string): Operation | undefined;
|
|
17
|
+
/** Ops that have not been inverted by a later op. */
|
|
18
|
+
live(): Operation[];
|
|
19
|
+
/**
|
|
20
|
+
* An op stands unless a LIVE op undoes it. That one sentence is the whole
|
|
21
|
+
* redo mechanism: undoing an undo makes the undo itself not live, which
|
|
22
|
+
* revives its target. Undoers always follow their target, so resolving
|
|
23
|
+
* from the end of the log backwards terminates in one pass.
|
|
24
|
+
*/
|
|
25
|
+
undoneIds(): Set<string>;
|
|
26
|
+
opsInBatch(batchId: string): Operation[];
|
|
27
|
+
batches(): Batch[];
|
|
28
|
+
/** Rebuilds the graph from empty by folding every live op forward. */
|
|
29
|
+
fold<S extends AnySchema>(schema: S, options?: {
|
|
30
|
+
validate?: boolean;
|
|
31
|
+
}): Graph<S>;
|
|
32
|
+
/** Serializable form for a persistence adapter. */
|
|
33
|
+
toJSON(): Operation[];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=log.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/ops/log.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Graph } from "../graph/graph.js";
|
|
2
|
+
/**
|
|
3
|
+
* The append-only log. Nothing here mutates or removes an entry: an undo is
|
|
4
|
+
* a new op carrying the inverse, so history is never destroyed and the log
|
|
5
|
+
* doubles as an audit trail of what an agent did on your behalf.
|
|
6
|
+
*/
|
|
7
|
+
export class OperationLog {
|
|
8
|
+
ops = [];
|
|
9
|
+
get length() {
|
|
10
|
+
return this.ops.length;
|
|
11
|
+
}
|
|
12
|
+
all() {
|
|
13
|
+
return this.ops;
|
|
14
|
+
}
|
|
15
|
+
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`);
|
|
18
|
+
}
|
|
19
|
+
this.ops.push(op);
|
|
20
|
+
}
|
|
21
|
+
/** Restores a log from storage, checking the sequence is intact. */
|
|
22
|
+
static from(ops) {
|
|
23
|
+
const log = new OperationLog();
|
|
24
|
+
for (const op of ops)
|
|
25
|
+
log.append(op);
|
|
26
|
+
return log;
|
|
27
|
+
}
|
|
28
|
+
get(id) {
|
|
29
|
+
return this.ops.find((op) => op.id === id);
|
|
30
|
+
}
|
|
31
|
+
/** Ops that have not been inverted by a later op. */
|
|
32
|
+
live() {
|
|
33
|
+
const undone = this.undoneIds();
|
|
34
|
+
return this.ops.filter((op) => !undone.has(op.id));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* An op stands unless a LIVE op undoes it. That one sentence is the whole
|
|
38
|
+
* redo mechanism: undoing an undo makes the undo itself not live, which
|
|
39
|
+
* revives its target. Undoers always follow their target, so resolving
|
|
40
|
+
* from the end of the log backwards terminates in one pass.
|
|
41
|
+
*/
|
|
42
|
+
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));
|
|
60
|
+
}
|
|
61
|
+
opsInBatch(batchId) {
|
|
62
|
+
return this.ops.filter((op) => op.batch === batchId);
|
|
63
|
+
}
|
|
64
|
+
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
|
+
}
|
|
76
|
+
}
|
|
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);
|
|
95
|
+
}
|
|
96
|
+
return graph;
|
|
97
|
+
}
|
|
98
|
+
/** Serializable form for a persistence adapter. */
|
|
99
|
+
toJSON() {
|
|
100
|
+
return [...this.ops];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/ops/log.ts"],"names":[],"mappings":"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"}
|