@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,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { takesAnId } from "../mutations/define-mutation.js";
|
|
3
|
+
import { nodeRefArgs } from "../mutations/node-ref.js";
|
|
4
|
+
/**
|
|
5
|
+
* One source, three outputs: the same Zod declaration produces runtime
|
|
6
|
+
* validation, TypeScript inference, and the JSON Schema an agent tool
|
|
7
|
+
* definition needs. Nothing is written twice, so nothing drifts.
|
|
8
|
+
*/
|
|
9
|
+
export function toJsonSchema(schema) {
|
|
10
|
+
const convert = z
|
|
11
|
+
.toJSONSchema;
|
|
12
|
+
if (typeof convert !== "function") {
|
|
13
|
+
throw new Error("This Zod build has no toJSONSchema(). Upgrade to zod >= 3.25 / 4.x, " +
|
|
14
|
+
"or pass a JSON Schema explicitly.");
|
|
15
|
+
}
|
|
16
|
+
return convert(schema, { io: "input", unrepresentable: "any" });
|
|
17
|
+
}
|
|
18
|
+
/** JSON Schema for one node kind, including its id and kind discriminator. */
|
|
19
|
+
export function nodeJsonSchema(definition) {
|
|
20
|
+
return toJsonSchema(definition.fields.extend({
|
|
21
|
+
id: z.string().min(1),
|
|
22
|
+
kind: z.literal(definition.kind),
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Derives an agent-facing tool schema from a mutation declaration. The
|
|
27
|
+
* `nodeRefs` metadata travels alongside so a caller can resolve "a person"
|
|
28
|
+
* to real ids without the agent guessing.
|
|
29
|
+
*/
|
|
30
|
+
export function mutationToolSchema(mutation) {
|
|
31
|
+
const refs = nodeRefArgs(mutation.input);
|
|
32
|
+
const base = toJsonSchema(mutation.input);
|
|
33
|
+
const properties = (base["properties"] ?? {});
|
|
34
|
+
/*
|
|
35
|
+
* THE ID A CALLER MAY BRING. An act that creates takes it beside its own
|
|
36
|
+
* arguments (`compileMutation` lifts it before the input parses), so the
|
|
37
|
+
* tool says so — an agent that will name the node in its next call, or a
|
|
38
|
+
* seed being synced, asks for the id it needs rather than reading one back.
|
|
39
|
+
*/
|
|
40
|
+
if (takesAnId(mutation)) {
|
|
41
|
+
const made = mutation.creates.join(" | ");
|
|
42
|
+
properties["id"] = {
|
|
43
|
+
type: "string",
|
|
44
|
+
minLength: 1,
|
|
45
|
+
description: `Optional: the id for the ${made} this makes. Refused if the graph already has it; left out, one is minted from the label.`,
|
|
46
|
+
};
|
|
47
|
+
base["properties"] = properties;
|
|
48
|
+
}
|
|
49
|
+
for (const ref of refs) {
|
|
50
|
+
const property = properties[ref.name];
|
|
51
|
+
if (!property)
|
|
52
|
+
continue;
|
|
53
|
+
const kinds = ref.kinds.includes("*") ? "any node kind" : ref.kinds.join(" | ");
|
|
54
|
+
property["description"] = [property["description"], `Id of a node (${kinds}).`]
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.join(" ");
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
name: mutation.name,
|
|
60
|
+
...(mutation.title === undefined ? {} : { title: mutation.title }),
|
|
61
|
+
description: mutation.description ?? mutation.title ?? mutation.name,
|
|
62
|
+
inputSchema: base,
|
|
63
|
+
nodeRefs: refs,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** Every node kind's JSON Schema, keyed by kind. */
|
|
67
|
+
export function schemaJson(schema) {
|
|
68
|
+
const out = {};
|
|
69
|
+
for (const definition of schema.definitions) {
|
|
70
|
+
out[definition.kind] = nodeJsonSchema(definition);
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=json-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../src/schema/json-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { AnyNodeDefinition, NodeOf, ValidateEdgeTargets } from "./types.js";
|
|
2
|
+
export interface EdgeKindInfo {
|
|
3
|
+
readonly kind: string;
|
|
4
|
+
/** Node kinds this edge may leave. */
|
|
5
|
+
readonly from: readonly string[];
|
|
6
|
+
/** Node kinds this edge may point at, or `"*"`. */
|
|
7
|
+
readonly to: readonly string[] | "*";
|
|
8
|
+
readonly cardinality: "one" | "many";
|
|
9
|
+
readonly description?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Schema<Defs extends readonly AnyNodeDefinition[] = readonly AnyNodeDefinition[]> {
|
|
12
|
+
readonly definitions: Defs;
|
|
13
|
+
readonly kinds: readonly Defs[number]["kind"][];
|
|
14
|
+
readonly edgeKinds: readonly string[];
|
|
15
|
+
definition<K extends Defs[number]["kind"]>(kind: K): Extract<Defs[number], {
|
|
16
|
+
kind: K;
|
|
17
|
+
}>;
|
|
18
|
+
tryDefinition(kind: string): Defs[number] | undefined;
|
|
19
|
+
edge(kind: string): EdgeKindInfo | undefined;
|
|
20
|
+
/** Whether an edge of `kind` may run from one node kind to another. */
|
|
21
|
+
edgeAllowed(kind: string, fromKind: string, toKind: string): boolean;
|
|
22
|
+
/** Runtime validation of a node against its declared fields. */
|
|
23
|
+
parseNode(node: unknown): NodeOf<Defs[number]>;
|
|
24
|
+
/** Phantom carrier for the node union — never populated at runtime. */
|
|
25
|
+
readonly __node: NodeOf<Defs[number]>;
|
|
26
|
+
}
|
|
27
|
+
export type AnySchema = Schema<readonly AnyNodeDefinition[]>;
|
|
28
|
+
export type NodeOfSchema<S extends AnySchema> = S["__node"];
|
|
29
|
+
export type KindOfSchema<S extends AnySchema> = NodeOfSchema<S>["kind"];
|
|
30
|
+
export type NodeOfKind<S extends AnySchema, K extends KindOfSchema<S>> = Extract<NodeOfSchema<S>, {
|
|
31
|
+
kind: K;
|
|
32
|
+
}>;
|
|
33
|
+
export declare class SchemaError extends Error {
|
|
34
|
+
readonly hint?: string | undefined;
|
|
35
|
+
constructor(message: string, hint?: string | undefined);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Assembles declarations into one schema. The `ValidateEdgeTargets` guard
|
|
39
|
+
* makes an edge to an undeclared kind a typecheck failure; the runtime
|
|
40
|
+
* checks here catch the same class of mistake for dynamically built schemas.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createSchema<const Defs extends readonly AnyNodeDefinition[]>(definitions: Defs & ValidateEdgeTargets<Defs>): Schema<Defs>;
|
|
43
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EAEjB,MAAM,EACN,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC;IACrC,QAAQ,CAAC,WAAW,EAAE,KAAK,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,MAAM,CAAC,IAAI,SAAS,SAAS,iBAAiB,EAAE,GAAG,SAAS,iBAAiB,EAAE;IAC9F,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,UAAU,CAAC,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EACvC,IAAI,EAAE,CAAC,GACN,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IACtC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IACtD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC7C,uEAAuE;IACvE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACrE,gEAAgE;IAChE,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/C,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC;AAC7D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC5D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACxE,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,IAAI,OAAO,CAC9E,YAAY,CAAC,CAAC,CAAC,EACf;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CACZ,CAAC;AAEF,qBAAa,WAAY,SAAQ,KAAK;IAGlC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;gBADtB,OAAO,EAAE,MAAM,EACN,IAAI,CAAC,EAAE,MAAM,YAAA;CAKzB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,SAAS,iBAAiB,EAAE,EAC1E,WAAW,EAAE,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,GAC5C,MAAM,CAAC,IAAI,CAAC,CAuGd"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export class SchemaError extends Error {
|
|
3
|
+
hint;
|
|
4
|
+
constructor(message, hint) {
|
|
5
|
+
super(hint ? `${message}\n → ${hint}` : message);
|
|
6
|
+
this.hint = hint;
|
|
7
|
+
this.name = "SchemaError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Assembles declarations into one schema. The `ValidateEdgeTargets` guard
|
|
12
|
+
* makes an edge to an undeclared kind a typecheck failure; the runtime
|
|
13
|
+
* checks here catch the same class of mistake for dynamically built schemas.
|
|
14
|
+
*/
|
|
15
|
+
export function createSchema(definitions) {
|
|
16
|
+
const defs = definitions;
|
|
17
|
+
const byKind = new Map();
|
|
18
|
+
for (const def of defs) {
|
|
19
|
+
if (byKind.has(def.kind)) {
|
|
20
|
+
throw new SchemaError(`Duplicate node kind "${def.kind}"`, "Each kind may be declared once; merge the two defineNode calls.");
|
|
21
|
+
}
|
|
22
|
+
byKind.set(def.kind, def);
|
|
23
|
+
}
|
|
24
|
+
const edges = new Map();
|
|
25
|
+
for (const def of defs) {
|
|
26
|
+
for (const [edgeKind, decl] of Object.entries(def.edges)) {
|
|
27
|
+
if (decl.to !== "*") {
|
|
28
|
+
for (const target of decl.to) {
|
|
29
|
+
if (!byKind.has(target)) {
|
|
30
|
+
throw new SchemaError(`Edge "${edgeKind}" on "${def.kind}" points at undeclared kind "${target}"`, `Declared kinds: ${[...byKind.keys()].join(", ")}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const existing = edges.get(edgeKind);
|
|
35
|
+
if (existing) {
|
|
36
|
+
existing.from.push(def.kind);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
edges.set(edgeKind, { from: [def.kind], decl });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const edgeInfo = new Map();
|
|
44
|
+
for (const [kind, { from, decl }] of edges) {
|
|
45
|
+
// Every declaring kind's targets, not only the first's.
|
|
46
|
+
const targets = from.map((one) => byKind.get(one).edges[kind].to);
|
|
47
|
+
edgeInfo.set(kind, {
|
|
48
|
+
kind,
|
|
49
|
+
from,
|
|
50
|
+
to: targets.includes("*") ? "*" : [...new Set(targets.flat())],
|
|
51
|
+
cardinality: decl.cardinality ?? "many",
|
|
52
|
+
...(decl.description === undefined ? {} : { description: decl.description }),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const nodeSchemas = new Map();
|
|
56
|
+
for (const def of defs) {
|
|
57
|
+
nodeSchemas.set(def.kind, def.fields.extend({ id: z.string().min(1), kind: z.literal(def.kind) }));
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
definitions: defs,
|
|
61
|
+
kinds: defs.map((d) => d.kind),
|
|
62
|
+
edgeKinds: [...edgeInfo.keys()],
|
|
63
|
+
definition(kind) {
|
|
64
|
+
const def = byKind.get(kind);
|
|
65
|
+
if (!def) {
|
|
66
|
+
throw new SchemaError(`Unknown node kind "${String(kind)}"`, `Declared kinds: ${[...byKind.keys()].join(", ")}`);
|
|
67
|
+
}
|
|
68
|
+
return def;
|
|
69
|
+
},
|
|
70
|
+
tryDefinition(kind) {
|
|
71
|
+
return byKind.get(kind);
|
|
72
|
+
},
|
|
73
|
+
edge(kind) {
|
|
74
|
+
return edgeInfo.get(kind);
|
|
75
|
+
},
|
|
76
|
+
edgeAllowed(kind, fromKind, toKind) {
|
|
77
|
+
/*
|
|
78
|
+
* Asked of the DECLARING kind's own declaration. An edge name two
|
|
79
|
+
* kinds both declare kept the first one's targets for both, so the
|
|
80
|
+
* second kind's edge was refused to its own declared targets and
|
|
81
|
+
* allowed to the first kind's.
|
|
82
|
+
*/
|
|
83
|
+
const declared = byKind.get(fromKind)?.edges[kind];
|
|
84
|
+
if (!declared)
|
|
85
|
+
return false;
|
|
86
|
+
return declared.to === "*" || declared.to.includes(toKind);
|
|
87
|
+
},
|
|
88
|
+
parseNode(node) {
|
|
89
|
+
const kind = node?.kind;
|
|
90
|
+
if (typeof kind !== "string") {
|
|
91
|
+
throw new SchemaError("Node is missing a `kind`");
|
|
92
|
+
}
|
|
93
|
+
const parser = nodeSchemas.get(kind);
|
|
94
|
+
if (!parser) {
|
|
95
|
+
throw new SchemaError(`Unknown node kind "${kind}"`, `Declared kinds: ${[...byKind.keys()].join(", ")}`);
|
|
96
|
+
}
|
|
97
|
+
return parser.parse(node);
|
|
98
|
+
},
|
|
99
|
+
__node: undefined,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2CxB,MAAM,OAAO,WAAY,SAAQ,KAAK;IAGzB;IAFX,YACE,OAAe,EACN,IAAa;QAEtB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAFzC,SAAI,GAAJ,IAAI,CAAS;QAGtB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,WAA6C;IAE7C,MAAM,IAAI,GAAG,WAAmB,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IACpD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,WAAW,CACnB,wBAAwB,GAAG,CAAC,IAAI,GAAG,EACnC,iEAAiE,CAClE,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqD,CAAC;IAC3E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,IAAI,IAAI,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC;gBACpB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;oBAC7B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;wBACxB,MAAM,IAAI,WAAW,CACnB,SAAS,QAAQ,SAAS,GAAG,CAAC,IAAI,gCAAgC,MAAM,GAAG,EAC3E,mBAAmB,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnD,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC3C,wDAAwD;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,KAAK,CAAC,IAAI,CAAqB,CAAC,EAAE,CAAC,CAAC;QACxF,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE;YACjB,IAAI;YACJ,IAAI;YACJ,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAc,CAAC,CAAC;YAC1E,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,MAAM;YACvC,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;SAC7E,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAqB,CAAC;IACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,WAAW,CAAC,GAAG,CACb,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CACxE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW,EAAE,IAAI;QACjB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAoC;QACjE,SAAS,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI;YACb,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,WAAW,CACnB,sBAAsB,MAAM,CAAC,IAAI,CAAC,GAAG,EACrC,mBAAmB,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnD,CAAC;YACJ,CAAC;YACD,OAAO,GAAmD,CAAC;QAC7D,CAAC;QACD,aAAa,CAAC,IAAI;YAChB,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAA6B,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,IAAI;YACP,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM;YAChC;;;;;eAKG;YACH,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,IAAI,CAAgC,CAAC;YAClF,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5B,OAAO,QAAQ,CAAC,EAAE,KAAK,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC7D,CAAC;QACD,SAAS,CAAC,IAAI;YACZ,MAAM,IAAI,GAAI,IAA2B,EAAE,IAAI,CAAC;YAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,IAAI,WAAW,CAAC,0BAA0B,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,WAAW,CACnB,sBAAsB,IAAI,GAAG,EAC7B,mBAAmB,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnD,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC;QACpD,CAAC;QACD,MAAM,EAAE,SAAkB;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { Figure } from "./figures.js";
|
|
3
|
+
/** How many edges of a kind may leave one node. */
|
|
4
|
+
export type EdgeCardinality = "one" | "many";
|
|
5
|
+
/**
|
|
6
|
+
* An edge declared on the node kind it leaves. `to` names the kinds it may
|
|
7
|
+
* point at; `"*"` opts out of target checking for genuinely universal edges
|
|
8
|
+
* (the household example's `justifies` is the motivating case).
|
|
9
|
+
*/
|
|
10
|
+
export interface EdgeDeclaration<TargetKind extends string = string> {
|
|
11
|
+
readonly to: readonly TargetKind[] | "*";
|
|
12
|
+
readonly cardinality?: EdgeCardinality;
|
|
13
|
+
/**
|
|
14
|
+
* How the edge reads FROM THE KIND THAT DECLARES IT — "who does the run",
|
|
15
|
+
* "the tasks in this list".
|
|
16
|
+
*/
|
|
17
|
+
readonly description?: string;
|
|
18
|
+
/**
|
|
19
|
+
* How it reads from the OTHER END.
|
|
20
|
+
*
|
|
21
|
+
* An edge has one direction and two readings, and using the declaring side's
|
|
22
|
+
* words for both is how a task's page ended up captioned "the tasks in this
|
|
23
|
+
* list" — as though the task contained tasks. The list holds the task; the
|
|
24
|
+
* task is on a list. Same edge, and neither sentence works in both places.
|
|
25
|
+
*
|
|
26
|
+
* Without one, an incoming edge is captioned with the edge kind in plain
|
|
27
|
+
* words, which says less and is at least not wrong.
|
|
28
|
+
*/
|
|
29
|
+
readonly inverse?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Declares that this relation, once made, is never unmade — an entry in a
|
|
32
|
+
* record, not a tie anyone severs. `graview check` warns about any edge
|
|
33
|
+
* kind some mutation can make and none can break (`edge-without-severer`),
|
|
34
|
+
* because a way in with no way out is usually an oversight; this is the
|
|
35
|
+
* declaration that says it is not. The suppression is the documentation:
|
|
36
|
+
* a reader of the schema learns the edge is append-only on purpose.
|
|
37
|
+
*/
|
|
38
|
+
readonly appendOnly?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export type EdgeMap = Readonly<Record<string, EdgeDeclaration>>;
|
|
41
|
+
/**
|
|
42
|
+
* A kind that declares no edges. Deliberately `{}` rather than
|
|
43
|
+
* `Record<string, never>`: the latter has `keyof` of `string`, which makes
|
|
44
|
+
* the edge-target extraction below fall back to its constraint and silently
|
|
45
|
+
* defeat the build-time check.
|
|
46
|
+
*/
|
|
47
|
+
export type EmptyEdgeMap = {};
|
|
48
|
+
/** A field role lets a lens ask for "the start time" without knowing the field name. */
|
|
49
|
+
export type FieldRoleMap = Readonly<Record<string, string>>;
|
|
50
|
+
export interface NodeDefinitionSpec<F extends z.ZodObject<z.ZodRawShape>, E extends EdgeMap> {
|
|
51
|
+
/** Zod object: the single source of runtime validation, TS types and JSON Schema. */
|
|
52
|
+
readonly fields: F;
|
|
53
|
+
readonly edges?: E;
|
|
54
|
+
/** Human label for one node. Falls back to a `label` field, then the id. */
|
|
55
|
+
readonly label?: (node: {
|
|
56
|
+
id: string;
|
|
57
|
+
} & z.infer<F>) => string;
|
|
58
|
+
/** Longer prose used for accessibility labels and agent tool descriptions. */
|
|
59
|
+
readonly describe?: (node: {
|
|
60
|
+
id: string;
|
|
61
|
+
} & z.infer<F>) => string;
|
|
62
|
+
/** Plural noun for aggregates ("People"). Defaults to `kind + "s"`. */
|
|
63
|
+
readonly plural?: string;
|
|
64
|
+
/**
|
|
65
|
+
* What ONE of them is called, in lower case, where the kind's id does not
|
|
66
|
+
* say it: a kind called `staff` whose one member is "a staff member", a
|
|
67
|
+
* kind called `equipment` whose one is "a piece of equipment". Defaults to
|
|
68
|
+
* the id, spoken ("work-order" → "work order").
|
|
69
|
+
*/
|
|
70
|
+
readonly noun?: string;
|
|
71
|
+
readonly description?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Maps a node onto the invariant it requires. The engine uses this to detect
|
|
74
|
+
* nodes whose rule was never registered, and to skip or throw per config.
|
|
75
|
+
*/
|
|
76
|
+
readonly requiresInvariant?: (node: {
|
|
77
|
+
id: string;
|
|
78
|
+
} & z.infer<F>) => string | null;
|
|
79
|
+
/**
|
|
80
|
+
* Names semantic roles the node's own fields fill, so lenses bind to roles
|
|
81
|
+
* rather than field names (`{ start: "at", end: "endsAt" }`).
|
|
82
|
+
*/
|
|
83
|
+
readonly fieldRoles?: FieldRoleMap;
|
|
84
|
+
/**
|
|
85
|
+
* How this kind's fields READ to a person.
|
|
86
|
+
*
|
|
87
|
+
* The framework renders a record from the declaration alone, which is most
|
|
88
|
+
* of what makes a new kind usable before anyone writes a view — and it can
|
|
89
|
+
* only get so far on its own. `540` is a truthful rendering of a number of
|
|
90
|
+
* minutes and a useless one; `order: 0` is a truthful rendering of an
|
|
91
|
+
* implementation detail nobody should ever be shown.
|
|
92
|
+
*
|
|
93
|
+
* Both are decisions only the declaration can make, so this is where they
|
|
94
|
+
* are made — once, rather than in every view that renders the kind.
|
|
95
|
+
*/
|
|
96
|
+
readonly display?: {
|
|
97
|
+
/** Field names never shown to a person. Ordering keys, internal ids. */
|
|
98
|
+
readonly hide?: readonly string[];
|
|
99
|
+
/** Overrides the humanised default for a field's label. */
|
|
100
|
+
readonly labels?: Readonly<Record<string, string>>;
|
|
101
|
+
/** Turns a stored value into the words for it. */
|
|
102
|
+
readonly format?: Readonly<Record<string, (value: unknown) => string>>;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* When a node of this kind stops being CURRENT.
|
|
106
|
+
*
|
|
107
|
+
* The graph accumulates; the interface must not. A kind that declares its
|
|
108
|
+
* lifecycle lets every derived surface aggregate over the horizon by
|
|
109
|
+
* default — counts, districts, rosters, violations — with the past one
|
|
110
|
+
* deliberate step away rather than gone. Nothing here deletes: retiring
|
|
111
|
+
* is an ordinary field write through an ordinary mutation, and widening
|
|
112
|
+
* the horizon is ordinary view state.
|
|
113
|
+
*
|
|
114
|
+
* Two shapes, one field: `retired` lists the values that mean "past"
|
|
115
|
+
* (a status enum), or is the string "date", which reads the field as an
|
|
116
|
+
* ISO date after which the node has expired (effectivity's `until`).
|
|
117
|
+
*/
|
|
118
|
+
readonly lifecycle?: LifecycleDeclaration;
|
|
119
|
+
/**
|
|
120
|
+
* Fields that NEVER change once set, and why.
|
|
121
|
+
*
|
|
122
|
+
* A field you could set at creation, you can change: every settable field
|
|
123
|
+
* no declared mutation writes is covered by a derived edit act per kind
|
|
124
|
+
* (`edit-<kind>`), so nothing is frozen by accident. Opting OUT is this
|
|
125
|
+
* declaration — the field name, and the sentence that says why it is not
|
|
126
|
+
* yours to change ("the client's words, as sent"). The reason is the
|
|
127
|
+
* documentation: a reader of the schema learns the field is fixed on
|
|
128
|
+
* purpose, and `graview check` stops asking who writes it.
|
|
129
|
+
*/
|
|
130
|
+
readonly fixed?: Readonly<Record<string, string>>;
|
|
131
|
+
/**
|
|
132
|
+
* A DRAWING OF THE THING, wherever the kind is drawn.
|
|
133
|
+
*
|
|
134
|
+
* Inline SVG — one `viewBox`, `currentColor` strokes, no fill — or the
|
|
135
|
+
* name of one from the shipped set (`FIGURES`). The kind card stands it
|
|
136
|
+
* on its block at altitude, the district carries it beside the plural, a
|
|
137
|
+
* chip draws it where it stays legible, the record and list pages carry
|
|
138
|
+
* it, and the relation key uses it. All from here.
|
|
139
|
+
*
|
|
140
|
+
* A kind without one is drawn exactly as it was. Nothing about a figure
|
|
141
|
+
* is required, and a figure is never decoration: it is line art of the
|
|
142
|
+
* thing, at the isometric city's own angle, or it should not be there.
|
|
143
|
+
*/
|
|
144
|
+
readonly figure?: Figure;
|
|
145
|
+
/**
|
|
146
|
+
* WHERE THIS KIND STANDS IN THE CITY, hand-laid, in lattice cells.
|
|
147
|
+
*
|
|
148
|
+
* The map is drawn from the declaration and needs no help; this is for
|
|
149
|
+
* an installation that wants a kind on a particular corner. Used
|
|
150
|
+
* verbatim — `graview check` reports two kinds laid on one block as
|
|
151
|
+
* `plot-overlap`. The studio will write these back one day; a plot is
|
|
152
|
+
* a fact about the declaration, so it belongs here rather than in a
|
|
153
|
+
* person's storage.
|
|
154
|
+
*/
|
|
155
|
+
readonly plot?: {
|
|
156
|
+
readonly col: number;
|
|
157
|
+
readonly row: number;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export interface LifecycleDeclaration {
|
|
161
|
+
/** The field that carries the node's currency. */
|
|
162
|
+
readonly field: string;
|
|
163
|
+
/** Values meaning "past", or "date" to expire after the field's ISO date. */
|
|
164
|
+
readonly retired: readonly unknown[] | "date";
|
|
165
|
+
}
|
|
166
|
+
export interface NodeDefinition<K extends string = string, F extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>, E extends EdgeMap = EdgeMap> extends NodeDefinitionSpec<F, E> {
|
|
167
|
+
readonly kind: K;
|
|
168
|
+
readonly edges: E;
|
|
169
|
+
}
|
|
170
|
+
export type AnyNodeDefinition = NodeDefinition<string, z.ZodObject<z.ZodRawShape>, EdgeMap>;
|
|
171
|
+
/**
|
|
172
|
+
* The runtime shape of a node of one declared kind. Distributive on purpose:
|
|
173
|
+
* given a union of declarations this yields a union of node types, not one
|
|
174
|
+
* node with every field intersected.
|
|
175
|
+
*/
|
|
176
|
+
export type NodeOf<D extends AnyNodeDefinition> = D extends AnyNodeDefinition ? {
|
|
177
|
+
readonly id: string;
|
|
178
|
+
readonly kind: D["kind"];
|
|
179
|
+
} & z.infer<D["fields"]> : never;
|
|
180
|
+
/**
|
|
181
|
+
* Every edge target named across a set of declarations. A `"*"` target is
|
|
182
|
+
* not an array, so it drops out here — a wildcard edge opts out of target
|
|
183
|
+
* checking by construction rather than by a special case.
|
|
184
|
+
*/
|
|
185
|
+
export type DeclaredEdgeTargets<Defs extends readonly AnyNodeDefinition[]> = {
|
|
186
|
+
[I in keyof Defs]: {
|
|
187
|
+
[N in keyof Defs[I]["edges"]]: Defs[I]["edges"][N]["to"] extends readonly (infer T extends string)[] ? T : never;
|
|
188
|
+
}[keyof Defs[I]["edges"]];
|
|
189
|
+
}[number];
|
|
190
|
+
/**
|
|
191
|
+
* Build-time guard: an edge pointing at a kind nobody declared makes the
|
|
192
|
+
* whole schema unassignable, so `tsc` fails at the declaration rather than
|
|
193
|
+
* the render.
|
|
194
|
+
*/
|
|
195
|
+
export type ValidateEdgeTargets<Defs extends readonly AnyNodeDefinition[]> = [
|
|
196
|
+
Exclude<DeclaredEdgeTargets<Defs>, Defs[number]["kind"]>
|
|
197
|
+
] extends [never] ? Defs : {
|
|
198
|
+
readonly __graviewError: "Edge declared to an undeclared node kind";
|
|
199
|
+
readonly undeclaredKinds: Exclude<DeclaredEdgeTargets<Defs>, Defs[number]["kind"]>;
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":""}
|