@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,181 @@
|
|
|
1
|
+
import { GraphError } from "../graph/graph.js";
|
|
2
|
+
import { TrackedReader } from "../graph/tracked.js";
|
|
3
|
+
import { edgeId } from "../graph/types.js";
|
|
4
|
+
export function defineMutation(name, spec) {
|
|
5
|
+
return { ...spec, name };
|
|
6
|
+
}
|
|
7
|
+
/** Whether an act takes the framework's `id` argument: it creates, and has no `id` of its own. */
|
|
8
|
+
export function takesAnId(definition) {
|
|
9
|
+
if (!definition.creates?.length)
|
|
10
|
+
return false;
|
|
11
|
+
const shape = definition.input.shape;
|
|
12
|
+
return shape === undefined || !("id" in shape);
|
|
13
|
+
}
|
|
14
|
+
function requestedId(rawArgs) {
|
|
15
|
+
if (typeof rawArgs !== "object" || rawArgs === null)
|
|
16
|
+
return undefined;
|
|
17
|
+
const id = rawArgs["id"];
|
|
18
|
+
if (id === undefined)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (typeof id !== "string" || id.trim().length === 0) {
|
|
21
|
+
throw new GraphError("An id must be a non-empty string", `Got ${JSON.stringify(id)}.`);
|
|
22
|
+
}
|
|
23
|
+
return id;
|
|
24
|
+
}
|
|
25
|
+
function withoutId(args) {
|
|
26
|
+
const { id: _id, ...rest } = args;
|
|
27
|
+
return rest;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* An id from a name: the name's own letters, folded and hyphenated.
|
|
31
|
+
*
|
|
32
|
+
* It kept ASCII and dropped everything else, so "Zoë Lamarré" became
|
|
33
|
+
* `artist:zo-lamarr` — an address that is neither her name nor anybody's —
|
|
34
|
+
* and a name in any script without Latin letters became `item`. Accents are
|
|
35
|
+
* folded the way search folds them (`zoe-lamarre`, the id a person would
|
|
36
|
+
* guess), and a letter with no Latin form is kept as the letter it is.
|
|
37
|
+
*/
|
|
38
|
+
export function slug(label) {
|
|
39
|
+
return (label
|
|
40
|
+
.normalize("NFKD")
|
|
41
|
+
.replace(/\p{M}/gu, "")
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[^\p{L}\p{N}]+/gu, "-")
|
|
44
|
+
.replace(/^-+|-+$/g, "") || "item");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Runs a mutation against the graph WITHOUT applying it, returning the
|
|
48
|
+
* primitives it would emit plus the causal read set. Applying is the op
|
|
49
|
+
* log's job — keeping the two apart is what makes preview-as-diff free.
|
|
50
|
+
*/
|
|
51
|
+
export function compileMutation(graph, definition, rawArgs) {
|
|
52
|
+
/*
|
|
53
|
+
* THE ID A CALLER BROUGHT. An act that creates a kind takes an optional
|
|
54
|
+
* `id` the framework adds beside its own arguments (see `takesAnId`):
|
|
55
|
+
* lifted here, before the declaration's own schema parses the rest, so a
|
|
56
|
+
* strict input is not asked about an argument it never declared. It goes
|
|
57
|
+
* to the first node `freshId` mints, and an id already in the graph is a
|
|
58
|
+
* refusal — a seed being synced, or an agent that will name this node in
|
|
59
|
+
* its next call, needs exactly the id it asked for or an honest no.
|
|
60
|
+
*/
|
|
61
|
+
const requested = takesAnId(definition) ? requestedId(rawArgs) : undefined;
|
|
62
|
+
const parsed = definition.input.safeParse(requested === undefined ? rawArgs : withoutId(rawArgs));
|
|
63
|
+
if (!parsed.success) {
|
|
64
|
+
throw new GraphError(`Invalid arguments for mutation "${definition.name}"`, parsed.error.issues
|
|
65
|
+
.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`)
|
|
66
|
+
.join("; "));
|
|
67
|
+
}
|
|
68
|
+
const args = parsed.data;
|
|
69
|
+
const reader = new TrackedReader(graph);
|
|
70
|
+
const primitives = [];
|
|
71
|
+
const minted = new Set();
|
|
72
|
+
const context = {
|
|
73
|
+
graph: reader,
|
|
74
|
+
schema: graph.schema,
|
|
75
|
+
emit(primitive) {
|
|
76
|
+
primitives.push(primitive);
|
|
77
|
+
},
|
|
78
|
+
addNode(node) {
|
|
79
|
+
primitives.push({ op: "add-node", node });
|
|
80
|
+
},
|
|
81
|
+
removeNode(id) {
|
|
82
|
+
const node = reader.getNode(id);
|
|
83
|
+
if (!node)
|
|
84
|
+
throw new GraphError(`Cannot remove missing node "${id}"`);
|
|
85
|
+
const touching = new Map();
|
|
86
|
+
for (const edge of graph.outEdges(id))
|
|
87
|
+
touching.set(edgeId(edge), edge);
|
|
88
|
+
for (const edge of graph.inEdges(id))
|
|
89
|
+
touching.set(edgeId(edge), edge);
|
|
90
|
+
for (const edge of touching.values()) {
|
|
91
|
+
reader.getNode(edge.from);
|
|
92
|
+
reader.getNode(edge.to);
|
|
93
|
+
primitives.push({ op: "remove-edge", edge });
|
|
94
|
+
}
|
|
95
|
+
primitives.push({ op: "remove-node", node });
|
|
96
|
+
},
|
|
97
|
+
patchNode(id, fields) {
|
|
98
|
+
const node = reader.getNode(id);
|
|
99
|
+
if (!node)
|
|
100
|
+
throw new GraphError(`Cannot patch missing node "${id}"`);
|
|
101
|
+
const before = {};
|
|
102
|
+
const after = {};
|
|
103
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
104
|
+
const current = node[key];
|
|
105
|
+
if (JSON.stringify(current) === JSON.stringify(value))
|
|
106
|
+
continue;
|
|
107
|
+
before[key] = current;
|
|
108
|
+
after[key] = value;
|
|
109
|
+
}
|
|
110
|
+
if (Object.keys(after).length === 0)
|
|
111
|
+
return;
|
|
112
|
+
primitives.push({ op: "patch-node", id, before, after });
|
|
113
|
+
},
|
|
114
|
+
addEdge(edge) {
|
|
115
|
+
primitives.push({ op: "add-edge", edge });
|
|
116
|
+
},
|
|
117
|
+
removeEdge(edge) {
|
|
118
|
+
primitives.push({ op: "remove-edge", edge });
|
|
119
|
+
},
|
|
120
|
+
setSingleSource(kind, to, from) {
|
|
121
|
+
for (const edge of graph.inEdges(to, kind)) {
|
|
122
|
+
reader.getNode(edge.from);
|
|
123
|
+
if (edge.from === from)
|
|
124
|
+
continue;
|
|
125
|
+
primitives.push({ op: "remove-edge", edge });
|
|
126
|
+
}
|
|
127
|
+
if (!graph.inEdges(to, kind).some((e) => e.from === from)) {
|
|
128
|
+
primitives.push({ op: "add-edge", edge: { kind, from, to } });
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
freshId(label, prefix) {
|
|
132
|
+
if (requested !== undefined && !minted.has(requested)) {
|
|
133
|
+
if (reader.has(requested)) {
|
|
134
|
+
throw new GraphError(`Id "${requested}" is already taken`, `"${definition.name}" was asked to make a node with that id, and the graph has one. Pick another, or leave id out and let the act mint one.`);
|
|
135
|
+
}
|
|
136
|
+
minted.add(requested);
|
|
137
|
+
return requested;
|
|
138
|
+
}
|
|
139
|
+
const base = prefix ? `${prefix}:${slug(label)}` : slug(label);
|
|
140
|
+
if (!reader.has(base) && !minted.has(base)) {
|
|
141
|
+
minted.add(base);
|
|
142
|
+
return base;
|
|
143
|
+
}
|
|
144
|
+
let n = 2;
|
|
145
|
+
while (reader.has(`${base}-${n}`) || minted.has(`${base}-${n}`))
|
|
146
|
+
n++;
|
|
147
|
+
const id = `${base}-${n}`;
|
|
148
|
+
minted.add(id);
|
|
149
|
+
return id;
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
definition.apply(context, args);
|
|
153
|
+
const writes = new Set();
|
|
154
|
+
for (const primitive of primitives) {
|
|
155
|
+
switch (primitive.op) {
|
|
156
|
+
case "add-node":
|
|
157
|
+
case "remove-node":
|
|
158
|
+
writes.add(primitive.node.id);
|
|
159
|
+
break;
|
|
160
|
+
case "patch-node":
|
|
161
|
+
writes.add(primitive.id);
|
|
162
|
+
break;
|
|
163
|
+
case "add-edge":
|
|
164
|
+
case "remove-edge":
|
|
165
|
+
writes.add(primitive.edge.from);
|
|
166
|
+
writes.add(primitive.edge.to);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const intent = definition.describe?.(args, reader) ??
|
|
171
|
+
`${definition.name}(${Object.entries(args)
|
|
172
|
+
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
173
|
+
.join(", ")})`;
|
|
174
|
+
return {
|
|
175
|
+
primitives,
|
|
176
|
+
reads: reader.reads(),
|
|
177
|
+
writes: [...writes],
|
|
178
|
+
intent,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=define-mutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-mutation.js","sourceRoot":"","sources":["../../src/mutations/define-mutation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { AnySchema } from "../schema/schema.js";
|
|
2
|
+
import type { AnyNodeDefinition } from "../schema/types.js";
|
|
3
|
+
import type { AnyMutationDefinition } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* A FIELD YOU COULD SET AT CREATION, YOU CAN CHANGE.
|
|
6
|
+
*
|
|
7
|
+
* Every app here had the same hole: a drill's minimum players asked for
|
|
8
|
+
* when the drill was made, shown on its card, and then frozen — no
|
|
9
|
+
* mutation took it, so the in-place edit honestly said "read-only" and
|
|
10
|
+
* there was nothing to reach for. The culture is right that every change
|
|
11
|
+
* is a named act, so the fix is not an anonymous `update`: it is a DERIVED,
|
|
12
|
+
* titled edit act per kind, covering exactly the settable fields nothing
|
|
13
|
+
* else writes, flowing through the policy like any named mutation. Opting
|
|
14
|
+
* out is a declaration (`fixed`, with the reason); and the checker warns
|
|
15
|
+
* when a field is still out of everyone's reach.
|
|
16
|
+
*/
|
|
17
|
+
/** The fields of a kind a person could change: declared, and not fixed. */
|
|
18
|
+
export declare function settableFields(definition: AnyNodeDefinition): readonly string[];
|
|
19
|
+
/** The kinds a mutation's subject accepts, resolved against the schema. */
|
|
20
|
+
export declare function subjectKindsOf<S extends AnySchema>(schema: S, mutation: AnyMutationDefinition<S>): readonly string[];
|
|
21
|
+
/**
|
|
22
|
+
* Which fields a mutation writes on a given subject kind: its declaration
|
|
23
|
+
* when it has one, the name-match guess when it does not.
|
|
24
|
+
*/
|
|
25
|
+
export declare function fieldsWrittenBy<S extends AnySchema>(mutation: AnyMutationDefinition<S>, definition: AnyNodeDefinition): readonly string[];
|
|
26
|
+
/** kind → field → the declared mutations that write it. */
|
|
27
|
+
export declare function fieldWriters<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): ReadonlyMap<string, ReadonlyMap<string, readonly string[]>>;
|
|
28
|
+
/** The settable fields of a kind that no declared mutation writes. */
|
|
29
|
+
export declare function unwrittenFields<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[], kind: string): readonly string[];
|
|
30
|
+
/** The name the derived edit act for a kind carries. */
|
|
31
|
+
export declare const editMutationName: (kind: string) => string;
|
|
32
|
+
/**
|
|
33
|
+
* The declared acts a derived edit resolves its PERMISSION through: those
|
|
34
|
+
* that already write a field of the kind, and those that create it. Who may
|
|
35
|
+
* edit a drill is whoever the policy already lets change or make a drill —
|
|
36
|
+
* there is no second list.
|
|
37
|
+
*/
|
|
38
|
+
export declare function editVia<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[], kind: string): readonly string[];
|
|
39
|
+
/**
|
|
40
|
+
* One edit act per kind that has something nobody else writes.
|
|
41
|
+
*
|
|
42
|
+
* Its input is the subject plus each uncovered field as an optional
|
|
43
|
+
* argument carrying the kind's OWN field schema, so validation is the
|
|
44
|
+
* declaration's; `writes` names those fields, so `editableFields` needs no
|
|
45
|
+
* guess. A kind whose every settable field is already written derives
|
|
46
|
+
* nothing, and an app that declares its own `edit-<kind>` keeps it.
|
|
47
|
+
*/
|
|
48
|
+
export declare function deriveEditMutations<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): AnyMutationDefinition<S>[];
|
|
49
|
+
/** The name the derived remove act for a kind carries. */
|
|
50
|
+
export declare const removeMutationName: (kind: string) => string;
|
|
51
|
+
/**
|
|
52
|
+
* The declared acts a derived remove resolves its PERMISSION through: the
|
|
53
|
+
* ones that bring the kind into being. Who may make a plot may take one
|
|
54
|
+
* out — narrower than the edit's reading on purpose, because a role that
|
|
55
|
+
* may re-time a drill has not been trusted with losing it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function removeVia<S extends AnySchema>(mutations: readonly AnyMutationDefinition<S>[], kind: string): readonly string[];
|
|
58
|
+
/** The declared acts a derived act rides, whichever act it is. */
|
|
59
|
+
export declare function derivedVia<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[], mutation: AnyMutationDefinition<S>): readonly string[] | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* WHAT WAS MADE CAN BE UNMADE.
|
|
62
|
+
*
|
|
63
|
+
* Every app had a way to add a task and, mostly, no way to lose one — so an
|
|
64
|
+
* agent redesigning a board, or a seed being brought in step with a live
|
|
65
|
+
* store, had nothing to call and rewrote the seed instead. The culture is
|
|
66
|
+
* right that every change is a named act, so the fix is a DERIVED, titled
|
|
67
|
+
* remove act per kind: destructive, so it ranks last and is marked; taking
|
|
68
|
+
* the node's edges with it, as `removeNode` does; logged and undoable like
|
|
69
|
+
* everything else; and permitted through the acts that create the kind.
|
|
70
|
+
* An app that declares its own `remove-<kind>` keeps it.
|
|
71
|
+
*/
|
|
72
|
+
export declare function deriveRemoveMutations<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): AnyMutationDefinition<S>[];
|
|
73
|
+
/** Every act the framework derives for a declaration: the edits, then the removes. */
|
|
74
|
+
export declare function deriveMutations<S extends AnySchema>(schema: S, mutations: readonly AnyMutationDefinition<S>[]): AnyMutationDefinition<S>[];
|
|
75
|
+
//# sourceMappingURL=derive-edits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-edits.d.ts","sourceRoot":"","sources":["../../src/mutations/derive-edits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { labelOf } from "../schema/define-node.js";
|
|
3
|
+
import { humaniseField, nounOf } from "../schema/define-node.js";
|
|
4
|
+
import { nodeRef, nodeRefArgs } from "./node-ref.js";
|
|
5
|
+
/**
|
|
6
|
+
* A FIELD YOU COULD SET AT CREATION, YOU CAN CHANGE.
|
|
7
|
+
*
|
|
8
|
+
* Every app here had the same hole: a drill's minimum players asked for
|
|
9
|
+
* when the drill was made, shown on its card, and then frozen — no
|
|
10
|
+
* mutation took it, so the in-place edit honestly said "read-only" and
|
|
11
|
+
* there was nothing to reach for. The culture is right that every change
|
|
12
|
+
* is a named act, so the fix is not an anonymous `update`: it is a DERIVED,
|
|
13
|
+
* titled edit act per kind, covering exactly the settable fields nothing
|
|
14
|
+
* else writes, flowing through the policy like any named mutation. Opting
|
|
15
|
+
* out is a declaration (`fixed`, with the reason); and the checker warns
|
|
16
|
+
* when a field is still out of everyone's reach.
|
|
17
|
+
*/
|
|
18
|
+
/** The fields of a kind a person could change: declared, and not fixed. */
|
|
19
|
+
export function settableFields(definition) {
|
|
20
|
+
const shape = definition.fields.shape;
|
|
21
|
+
return Object.keys(shape).filter((field) => !(field in (definition.fixed ?? {})));
|
|
22
|
+
}
|
|
23
|
+
/** The kinds a mutation's subject accepts, resolved against the schema. */
|
|
24
|
+
export function subjectKindsOf(schema, mutation) {
|
|
25
|
+
const subject = mutation.subject;
|
|
26
|
+
if (!subject)
|
|
27
|
+
return [];
|
|
28
|
+
return subject.kinds === "*"
|
|
29
|
+
? schema.kinds
|
|
30
|
+
: subject.kinds;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Which fields a mutation writes on a given subject kind: its declaration
|
|
34
|
+
* when it has one, the name-match guess when it does not.
|
|
35
|
+
*/
|
|
36
|
+
export function fieldsWrittenBy(mutation, definition) {
|
|
37
|
+
const subject = mutation.subject;
|
|
38
|
+
if (!subject)
|
|
39
|
+
return [];
|
|
40
|
+
const declared = new Set(Object.keys(definition.fields.shape));
|
|
41
|
+
if (mutation.writes)
|
|
42
|
+
return mutation.writes.filter((field) => declared.has(field));
|
|
43
|
+
const shape = mutation.input.shape ?? {};
|
|
44
|
+
const refs = new Set(nodeRefArgs(mutation.input).map((ref) => ref.name));
|
|
45
|
+
return Object.keys(shape).filter((name) => name !== subject.arg && declared.has(name) && !refs.has(name));
|
|
46
|
+
}
|
|
47
|
+
/** kind → field → the declared mutations that write it. */
|
|
48
|
+
export function fieldWriters(schema, mutations) {
|
|
49
|
+
const writers = new Map();
|
|
50
|
+
for (const mutation of mutations) {
|
|
51
|
+
for (const kind of subjectKindsOf(schema, mutation)) {
|
|
52
|
+
const definition = schema.tryDefinition(kind);
|
|
53
|
+
if (!definition)
|
|
54
|
+
continue;
|
|
55
|
+
for (const field of fieldsWrittenBy(mutation, definition)) {
|
|
56
|
+
const byField = writers.get(kind) ?? new Map();
|
|
57
|
+
byField.set(field, [...(byField.get(field) ?? []), mutation.name]);
|
|
58
|
+
writers.set(kind, byField);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return writers;
|
|
63
|
+
}
|
|
64
|
+
/** The settable fields of a kind that no declared mutation writes. */
|
|
65
|
+
export function unwrittenFields(schema, mutations, kind) {
|
|
66
|
+
const definition = schema.tryDefinition(kind);
|
|
67
|
+
if (!definition)
|
|
68
|
+
return [];
|
|
69
|
+
const written = fieldWriters(schema, mutations).get(kind);
|
|
70
|
+
return settableFields(definition).filter((field) => !written?.has(field));
|
|
71
|
+
}
|
|
72
|
+
/** The name the derived edit act for a kind carries. */
|
|
73
|
+
export const editMutationName = (kind) => `edit-${kind}`;
|
|
74
|
+
/**
|
|
75
|
+
* The declared acts a derived edit resolves its PERMISSION through: those
|
|
76
|
+
* that already write a field of the kind, and those that create it. Who may
|
|
77
|
+
* edit a drill is whoever the policy already lets change or make a drill —
|
|
78
|
+
* there is no second list.
|
|
79
|
+
*/
|
|
80
|
+
export function editVia(schema, mutations, kind) {
|
|
81
|
+
const definition = schema.tryDefinition(kind);
|
|
82
|
+
if (!definition)
|
|
83
|
+
return [];
|
|
84
|
+
const via = new Set();
|
|
85
|
+
for (const mutation of mutations) {
|
|
86
|
+
if (mutation.derived)
|
|
87
|
+
continue;
|
|
88
|
+
if ((mutation.creates ?? []).includes(kind))
|
|
89
|
+
via.add(mutation.name);
|
|
90
|
+
if (subjectKindsOf(schema, mutation).includes(kind) &&
|
|
91
|
+
fieldsWrittenBy(mutation, definition).length > 0) {
|
|
92
|
+
via.add(mutation.name);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [...via];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* One edit act per kind that has something nobody else writes.
|
|
99
|
+
*
|
|
100
|
+
* Its input is the subject plus each uncovered field as an optional
|
|
101
|
+
* argument carrying the kind's OWN field schema, so validation is the
|
|
102
|
+
* declaration's; `writes` names those fields, so `editableFields` needs no
|
|
103
|
+
* guess. A kind whose every settable field is already written derives
|
|
104
|
+
* nothing, and an app that declares its own `edit-<kind>` keeps it.
|
|
105
|
+
*/
|
|
106
|
+
export function deriveEditMutations(schema, mutations) {
|
|
107
|
+
const taken = new Set(mutations.map((mutation) => mutation.name));
|
|
108
|
+
const derived = [];
|
|
109
|
+
for (const definition of schema.definitions) {
|
|
110
|
+
const kind = definition.kind;
|
|
111
|
+
const name = editMutationName(kind);
|
|
112
|
+
if (taken.has(name))
|
|
113
|
+
continue;
|
|
114
|
+
const fields = unwrittenFields(schema, mutations, kind);
|
|
115
|
+
if (fields.length === 0)
|
|
116
|
+
continue;
|
|
117
|
+
const shape = definition.fields.shape;
|
|
118
|
+
const noun = nounOf(definition, kind);
|
|
119
|
+
const said = fields.map((field) => humaniseField(field).toLowerCase());
|
|
120
|
+
derived.push({
|
|
121
|
+
name,
|
|
122
|
+
derived: { kind, act: "edit" },
|
|
123
|
+
title: `Change the ${noun}`,
|
|
124
|
+
description: `Change what was set when this ${noun} was made: ${said.join(", ")}.`,
|
|
125
|
+
subject: { kinds: [kind], arg: "id" },
|
|
126
|
+
writes: fields,
|
|
127
|
+
input: z.object({
|
|
128
|
+
id: nodeRef([kind]),
|
|
129
|
+
...Object.fromEntries(fields.map((field) => [field, shape[field].optional()])),
|
|
130
|
+
}),
|
|
131
|
+
describe: (args, graph) => {
|
|
132
|
+
const node = graph.getNode(args.id);
|
|
133
|
+
const label = node ? labelOf(definition, node) : args.id;
|
|
134
|
+
/*
|
|
135
|
+
* THE CHANGE AS THE RECORD READS IT. The log said "price → 49900"
|
|
136
|
+
* and "condition → \"cpo\"" beside a card that says "Price $49,900"
|
|
137
|
+
* and "Certified pre-owned": the declaration's own labels and
|
|
138
|
+
* formats are the words, and the raw value only where there is none.
|
|
139
|
+
*/
|
|
140
|
+
const display = definition.display;
|
|
141
|
+
const quietly = (label) => (label === label.toUpperCase() ? label : label.charAt(0).toLowerCase() + label.slice(1));
|
|
142
|
+
const changes = fields
|
|
143
|
+
.filter((field) => args[field] !== undefined)
|
|
144
|
+
.map((field) => {
|
|
145
|
+
const value = args[field];
|
|
146
|
+
const format = display?.format?.[field];
|
|
147
|
+
let said;
|
|
148
|
+
try {
|
|
149
|
+
said = format ? String(format(value)) : JSON.stringify(value);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
said = JSON.stringify(value);
|
|
153
|
+
}
|
|
154
|
+
return `${quietly(display?.labels?.[field] ?? humaniseField(field))} → ${said}`;
|
|
155
|
+
});
|
|
156
|
+
return `Change ${label}: ${changes.join(", ") || "nothing"}`;
|
|
157
|
+
},
|
|
158
|
+
apply(ctx, args) {
|
|
159
|
+
const patch = {};
|
|
160
|
+
for (const field of fields) {
|
|
161
|
+
const value = args[field];
|
|
162
|
+
if (value !== undefined)
|
|
163
|
+
patch[field] = value;
|
|
164
|
+
}
|
|
165
|
+
if (Object.keys(patch).length === 0) {
|
|
166
|
+
throw new Error(`Nothing to change — give at least one of ${said.join(", ")} a value.`);
|
|
167
|
+
}
|
|
168
|
+
ctx.patchNode(args.id, patch);
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return derived;
|
|
173
|
+
}
|
|
174
|
+
/** The name the derived remove act for a kind carries. */
|
|
175
|
+
export const removeMutationName = (kind) => `remove-${kind}`;
|
|
176
|
+
/**
|
|
177
|
+
* The declared acts a derived remove resolves its PERMISSION through: the
|
|
178
|
+
* ones that bring the kind into being. Who may make a plot may take one
|
|
179
|
+
* out — narrower than the edit's reading on purpose, because a role that
|
|
180
|
+
* may re-time a drill has not been trusted with losing it.
|
|
181
|
+
*/
|
|
182
|
+
export function removeVia(mutations, kind) {
|
|
183
|
+
return mutations
|
|
184
|
+
.filter((mutation) => !mutation.derived && (mutation.creates ?? []).includes(kind))
|
|
185
|
+
.map((mutation) => mutation.name);
|
|
186
|
+
}
|
|
187
|
+
/** The declared acts a derived act rides, whichever act it is. */
|
|
188
|
+
export function derivedVia(schema, mutations, mutation) {
|
|
189
|
+
if (!mutation.derived)
|
|
190
|
+
return undefined;
|
|
191
|
+
return mutation.derived.act === "edit"
|
|
192
|
+
? editVia(schema, mutations, mutation.derived.kind)
|
|
193
|
+
: removeVia(mutations, mutation.derived.kind);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* WHAT WAS MADE CAN BE UNMADE.
|
|
197
|
+
*
|
|
198
|
+
* Every app had a way to add a task and, mostly, no way to lose one — so an
|
|
199
|
+
* agent redesigning a board, or a seed being brought in step with a live
|
|
200
|
+
* store, had nothing to call and rewrote the seed instead. The culture is
|
|
201
|
+
* right that every change is a named act, so the fix is a DERIVED, titled
|
|
202
|
+
* remove act per kind: destructive, so it ranks last and is marked; taking
|
|
203
|
+
* the node's edges with it, as `removeNode` does; logged and undoable like
|
|
204
|
+
* everything else; and permitted through the acts that create the kind.
|
|
205
|
+
* An app that declares its own `remove-<kind>` keeps it.
|
|
206
|
+
*/
|
|
207
|
+
export function deriveRemoveMutations(schema, mutations) {
|
|
208
|
+
const taken = new Set(mutations.map((mutation) => mutation.name));
|
|
209
|
+
const derived = [];
|
|
210
|
+
for (const definition of schema.definitions) {
|
|
211
|
+
const kind = definition.kind;
|
|
212
|
+
const name = removeMutationName(kind);
|
|
213
|
+
if (taken.has(name))
|
|
214
|
+
continue;
|
|
215
|
+
const noun = nounOf(definition, kind);
|
|
216
|
+
derived.push({
|
|
217
|
+
name,
|
|
218
|
+
derived: { kind, act: "remove" },
|
|
219
|
+
title: `Remove the ${noun}`,
|
|
220
|
+
description: `Take this ${noun} out of the graph, with every tie it has. Undo puts it back.`,
|
|
221
|
+
subject: { kinds: [kind], arg: "id" },
|
|
222
|
+
destructive: true,
|
|
223
|
+
input: z.object({ id: nodeRef([kind]) }),
|
|
224
|
+
describe: (args, graph) => {
|
|
225
|
+
const id = args.id;
|
|
226
|
+
const node = graph.getNode(id);
|
|
227
|
+
return `Remove ${node ? labelOf(definition, node) : id}`;
|
|
228
|
+
},
|
|
229
|
+
apply(ctx, args) {
|
|
230
|
+
ctx.removeNode(args.id);
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return derived;
|
|
235
|
+
}
|
|
236
|
+
/** Every act the framework derives for a declaration: the edits, then the removes. */
|
|
237
|
+
export function deriveMutations(schema, mutations) {
|
|
238
|
+
return [...deriveEditMutations(schema, mutations), ...deriveRemoveMutations(schema, mutations)];
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=derive-edits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-edits.js","sourceRoot":"","sources":["../../src/mutations/derive-edits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* A FORM, derived from a mutation's own input declaration.
|
|
4
|
+
*
|
|
5
|
+
* `argShape` answers "what sort of answer does one scalar argument want",
|
|
6
|
+
* which is enough for a prompt in the actions strip. A page is mostly forms,
|
|
7
|
+
* and a form needs the whole tree: a structured object is a fieldset, a
|
|
8
|
+
* discriminated union is a type picker followed by that type's fields, an
|
|
9
|
+
* array is a repeatable row. Until this existed, any mutation with a
|
|
10
|
+
* structured argument was honestly un-askable — the strip withheld it — and
|
|
11
|
+
* a routed page cannot withhold "New agreement": it has to render.
|
|
12
|
+
*
|
|
13
|
+
* Everything here is PLAIN DATA. A renderer (a page, the strip, an agent
|
|
14
|
+
* explaining itself) walks the tree; nothing downstream touches zod.
|
|
15
|
+
*/
|
|
16
|
+
export type FormField = ScalarField | {
|
|
17
|
+
readonly control: "node";
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly optional: boolean;
|
|
20
|
+
readonly kinds: readonly string[];
|
|
21
|
+
} | {
|
|
22
|
+
readonly control: "group";
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly optional: boolean;
|
|
25
|
+
readonly fields: readonly FormField[];
|
|
26
|
+
} | {
|
|
27
|
+
readonly control: "variant";
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly optional: boolean;
|
|
30
|
+
/** The discriminating literal field shared by every option. */
|
|
31
|
+
readonly tag: string;
|
|
32
|
+
readonly options: readonly {
|
|
33
|
+
readonly value: string;
|
|
34
|
+
/** The option's remaining fields, the tag excluded. */
|
|
35
|
+
readonly fields: readonly FormField[];
|
|
36
|
+
}[];
|
|
37
|
+
} | {
|
|
38
|
+
readonly control: "list";
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly optional: boolean;
|
|
41
|
+
readonly item: FormField;
|
|
42
|
+
} | {
|
|
43
|
+
readonly control: "opaque";
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly optional: boolean;
|
|
46
|
+
};
|
|
47
|
+
export interface ScalarField {
|
|
48
|
+
readonly control: "text" | "date" | "number" | "choice" | "boolean";
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly optional: boolean;
|
|
51
|
+
/** A date with a time of day in it (`YYYY-MM-DDTHH:MM`): asked for with a date AND a time. */
|
|
52
|
+
readonly time?: true;
|
|
53
|
+
readonly options?: readonly string[];
|
|
54
|
+
readonly min?: number;
|
|
55
|
+
readonly max?: number;
|
|
56
|
+
}
|
|
57
|
+
/** Describes one argument as a form control tree. */
|
|
58
|
+
export declare function formField(name: string, schema: unknown): FormField;
|
|
59
|
+
/** The whole form for a mutation input object, one field per argument. */
|
|
60
|
+
export declare function formFields(input: z.ZodType | unknown): readonly FormField[];
|
|
61
|
+
/** True when every control in the tree is renderable — nothing opaque. */
|
|
62
|
+
export declare function formComplete(fields: readonly FormField[]): boolean;
|
|
63
|
+
//# sourceMappingURL=form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/mutations/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,GACjB,WAAW,GACX;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAClH;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GACvH;IACE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,uDAAuD;QACvD,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;KACvC,EAAE,CAAC;CACL,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACzG;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AA6BD,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CA+ElE;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,GAAG,OAAO,GAAG,SAAS,SAAS,EAAE,CAI3E;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAelE"}
|