@graview/core 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/dist/app.d.ts +41 -2
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js.map +1 -1
- package/dist/capabilities.js +1 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/city.d.ts +29 -0
- package/dist/city.d.ts.map +1 -1
- package/dist/city.js +66 -0
- package/dist/city.js.map +1 -1
- package/dist/cli/check/arrangement.d.ts.map +1 -1
- package/dist/cli/check/arrangement.js +3 -2
- package/dist/cli/check/arrangement.js.map +1 -1
- package/dist/cli/check/computed.d.ts +14 -0
- package/dist/cli/check/computed.d.ts.map +1 -0
- package/dist/cli/check/computed.js +34 -0
- package/dist/cli/check/computed.js.map +1 -0
- package/dist/cli/check/index.d.ts +1 -0
- package/dist/cli/check/index.d.ts.map +1 -1
- package/dist/cli/check/index.js +1 -0
- package/dist/cli/check/index.js.map +1 -1
- package/dist/cli/check/lenses.d.ts +10 -0
- package/dist/cli/check/lenses.d.ts.map +1 -1
- package/dist/cli/check/lenses.js +37 -19
- package/dist/cli/check/lenses.js.map +1 -1
- package/dist/cli/check/relations.d.ts.map +1 -1
- package/dist/cli/check/relations.js +2 -1
- package/dist/cli/check/relations.js.map +1 -1
- package/dist/cli/check/views.d.ts.map +1 -1
- package/dist/cli/check/views.js +8 -2
- package/dist/cli/check/views.js.map +1 -1
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +4 -1
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/describe.d.ts.map +1 -1
- package/dist/cli/describe.js +54 -1
- package/dist/cli/describe.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +21 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/describe.d.ts +3 -0
- package/dist/describe.d.ts.map +1 -0
- package/dist/describe.js +12 -0
- package/dist/describe.js.map +1 -0
- package/dist/document/blocks.d.ts +182 -0
- package/dist/document/blocks.d.ts.map +1 -0
- package/dist/document/blocks.js +382 -0
- package/dist/document/blocks.js.map +1 -0
- package/dist/document/compile.d.ts.map +1 -1
- package/dist/document/compile.js +57 -15
- package/dist/document/compile.js.map +1 -1
- package/dist/document/computed-values.d.ts +33 -0
- package/dist/document/computed-values.d.ts.map +1 -0
- package/dist/document/computed-values.js +60 -0
- package/dist/document/computed-values.js.map +1 -0
- package/dist/document/computed.d.ts +42 -0
- package/dist/document/computed.d.ts.map +1 -0
- package/dist/document/computed.js +173 -0
- package/dist/document/computed.js.map +1 -0
- package/dist/document/describe-place.d.ts +95 -0
- package/dist/document/describe-place.d.ts.map +1 -0
- package/dist/document/describe-place.js +257 -0
- package/dist/document/describe-place.js.map +1 -0
- package/dist/document/diff.d.ts.map +1 -1
- package/dist/document/diff.js +72 -3
- package/dist/document/diff.js.map +1 -1
- package/dist/document/edit.d.ts +1 -1
- package/dist/document/edit.d.ts.map +1 -1
- package/dist/document/edit.js +816 -103
- package/dist/document/edit.js.map +1 -1
- package/dist/document/expr/analyze.d.ts +22 -0
- package/dist/document/expr/analyze.d.ts.map +1 -1
- package/dist/document/expr/analyze.js +49 -3
- package/dist/document/expr/analyze.js.map +1 -1
- package/dist/document/expr/evaluate.d.ts +7 -1
- package/dist/document/expr/evaluate.d.ts.map +1 -1
- package/dist/document/expr/evaluate.js +95 -6
- package/dist/document/expr/evaluate.js.map +1 -1
- package/dist/document/expr/index.d.ts +1 -1
- package/dist/document/expr/index.d.ts.map +1 -1
- package/dist/document/expr/index.js +1 -1
- package/dist/document/expr/index.js.map +1 -1
- package/dist/document/index.d.ts +10 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/document/index.js +5 -1
- package/dist/document/index.js.map +1 -1
- package/dist/document/rules.d.ts +2 -1
- package/dist/document/rules.d.ts.map +1 -1
- package/dist/document/rules.js +5 -1
- package/dist/document/rules.js.map +1 -1
- package/dist/document/schema.d.ts +35 -3
- package/dist/document/schema.d.ts.map +1 -1
- package/dist/document/schema.js +22 -2
- package/dist/document/schema.js.map +1 -1
- package/dist/document/template.d.ts +17 -2
- package/dist/document/template.d.ts.map +1 -1
- package/dist/document/template.js +136 -16
- package/dist/document/template.js.map +1 -1
- package/dist/document/thumbnail.d.ts +34 -0
- package/dist/document/thumbnail.d.ts.map +1 -0
- package/dist/document/thumbnail.js +165 -0
- package/dist/document/thumbnail.js.map +1 -0
- package/dist/document/to-document.d.ts.map +1 -1
- package/dist/document/to-document.js +4 -1
- package/dist/document/to-document.js.map +1 -1
- package/dist/document/views.d.ts +47 -3
- package/dist/document/views.d.ts.map +1 -1
- package/dist/document/views.js +289 -21
- package/dist/document/views.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/places.d.ts +186 -0
- package/dist/places.d.ts.map +1 -0
- package/dist/places.js +358 -0
- package/dist/places.js.map +1 -0
- package/dist/scaffold/project.d.ts.map +1 -1
- package/dist/scaffold/project.js +9 -0
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/ui.d.ts.map +1 -1
- package/dist/scaffold/ui.js +13 -10
- package/dist/scaffold/ui.js.map +1 -1
- package/dist/scene-districts.d.ts +24 -0
- package/dist/scene-districts.d.ts.map +1 -0
- package/dist/scene-districts.js +27 -0
- package/dist/scene-districts.js.map +1 -0
- package/dist/schema/define-node.d.ts +3 -0
- package/dist/schema/define-node.d.ts.map +1 -1
- package/dist/schema/define-node.js +3 -1
- package/dist/schema/define-node.js.map +1 -1
- package/dist/schema/types.d.ts +17 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/theme/layers.d.ts +82 -0
- package/dist/theme/layers.d.ts.map +1 -0
- package/dist/theme/layers.js +79 -0
- package/dist/theme/layers.js.map +1 -0
- package/dist/theme/look.d.ts +96 -0
- package/dist/theme/look.d.ts.map +1 -0
- package/dist/theme/look.js +110 -0
- package/dist/theme/look.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/views/types.d.ts +19 -0
- package/dist/views/types.d.ts.map +1 -1
- package/dist/views/types.js +14 -0
- package/dist/views/types.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { fieldWords, valueWords } from "../schema/define-node.js";
|
|
2
|
+
import { evaluateExpr, NodeSet } from "./expr/evaluate.js";
|
|
3
|
+
import { parseExpr } from "./expr/parse.js";
|
|
4
|
+
import { formatValue, parseTemplate } from "./template.js";
|
|
5
|
+
import { fieldSpecOf } from "./to-document.js";
|
|
6
|
+
import { FIGURE_FORMATS, LIST_AS, MAX_LIST_LIMIT, VIEW_FIELD_FORMATS, VIEW_TONES } from "./views.js";
|
|
7
|
+
const safely = (f) => {
|
|
8
|
+
try {
|
|
9
|
+
return f();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const isTone = (value) => typeof value === "string" && VIEW_TONES.includes(value);
|
|
16
|
+
function toneOf(tone) {
|
|
17
|
+
if (tone === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
if (isTone(tone))
|
|
20
|
+
return tone;
|
|
21
|
+
if (tone && typeof tone === "object" && typeof tone.expr === "string")
|
|
22
|
+
return { expr: safely(() => parseExpr(tone.expr)) };
|
|
23
|
+
// A tone outside the kit is the check's to refuse; drawn, it is quiet.
|
|
24
|
+
return "neutral";
|
|
25
|
+
}
|
|
26
|
+
const MAX_DEPTH = 4;
|
|
27
|
+
/**
|
|
28
|
+
* A LIST, PARSED (FR-81, FR-82). Its order by a key is the language's own
|
|
29
|
+
* `sort(…)` around its source, so it is judged under the same budget as
|
|
30
|
+
* every other expression; an order by a choice field's declared choices is
|
|
31
|
+
* done after, from the declaration.
|
|
32
|
+
*/
|
|
33
|
+
function listOf(block) {
|
|
34
|
+
const source = typeof block["list"] === "string" ? safely(() => parseExpr(block["list"])) : null;
|
|
35
|
+
const sort = block["sort"];
|
|
36
|
+
const by = typeof sort === "string" ? sort : sort && typeof sort === "object" && typeof sort.by === "string" ? sort.by : undefined;
|
|
37
|
+
const direction = sort && typeof sort === "object" ? sort.direction : undefined;
|
|
38
|
+
let ordered = source;
|
|
39
|
+
let choiceOrder;
|
|
40
|
+
if (source && by !== undefined) {
|
|
41
|
+
if (direction === "choices")
|
|
42
|
+
choiceOrder = by;
|
|
43
|
+
else {
|
|
44
|
+
const key = safely(() => parseExpr(by));
|
|
45
|
+
ordered = key ? { t: "call", fn: "sort", args: [source, key, { t: "lit", value: direction === "desc" ? "desc" : "asc", at: 0 }], at: 0 } : null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const limit = typeof block["limit"] === "number" && Number.isInteger(block["limit"]) && block["limit"] >= 1 ? Math.min(block["limit"], MAX_LIST_LIMIT) : undefined;
|
|
49
|
+
const group = block["group"];
|
|
50
|
+
const groupBy = typeof group === "string" ? group : group && typeof group === "object" && typeof group.by === "string" ? group.by : undefined;
|
|
51
|
+
const headings = group && typeof group === "object" && group.headings && typeof group.headings === "object" ? group.headings : {};
|
|
52
|
+
return {
|
|
53
|
+
t: "list",
|
|
54
|
+
source: ordered,
|
|
55
|
+
...(choiceOrder ? { choiceOrder } : {}),
|
|
56
|
+
...(limit ? { limit } : {}),
|
|
57
|
+
...(groupBy ? { group: { by: groupBy, headings: Object.fromEntries(Object.entries(headings).filter((entry) => typeof entry[1] === "string")) } } : {}),
|
|
58
|
+
...(typeof block["empty"] === "string" ? { empty: block["empty"] } : {}),
|
|
59
|
+
as: block["as"] === "card" ? "card" : "row",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Parse a spec's blocks. A spec `graview check` passed parses cleanly; a
|
|
64
|
+
* part that does not is said as "—", and a block outside the vocabulary is
|
|
65
|
+
* not drawn at all.
|
|
66
|
+
*/
|
|
67
|
+
export function compileBlocks(blocks, depth = 1) {
|
|
68
|
+
if (!Array.isArray(blocks) || depth > MAX_DEPTH)
|
|
69
|
+
return [];
|
|
70
|
+
return blocks.flatMap((raw) => {
|
|
71
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
72
|
+
return [];
|
|
73
|
+
const block = raw;
|
|
74
|
+
const template = (source) => (typeof source === "string" ? safely(() => parseTemplate(source)) : null);
|
|
75
|
+
const expr = (source) => (typeof source === "string" ? safely(() => parseExpr(source)) : null);
|
|
76
|
+
const tone = toneOf(block["tone"]);
|
|
77
|
+
const label = typeof block["label"] === "string" ? block["label"] : undefined;
|
|
78
|
+
const has = (key) => Object.prototype.hasOwnProperty.call(block, key);
|
|
79
|
+
// A list first: its `group` is how it is grouped, not a group block.
|
|
80
|
+
if (has("list"))
|
|
81
|
+
return [listOf(block)];
|
|
82
|
+
if (has("headline"))
|
|
83
|
+
return [{ t: "headline", parts: template(block["headline"]) }];
|
|
84
|
+
if (has("figure") && typeof block["figure"] === "string") {
|
|
85
|
+
const as = FIGURE_FORMATS.includes(block["as"]) ? block["as"] : undefined;
|
|
86
|
+
const currency = typeof block["currency"] === "string" && /^[A-Z]{3}$/.test(block["currency"]) ? block["currency"] : undefined;
|
|
87
|
+
return [{ t: "number", value: expr(block["figure"]), ...(as ? { as } : {}), ...(currency ? { currency } : {}), ...(label ? { label } : {}) }];
|
|
88
|
+
}
|
|
89
|
+
if (has("title"))
|
|
90
|
+
return [{ t: "title", parts: template(block["title"]) }];
|
|
91
|
+
if (has("text"))
|
|
92
|
+
return [{ t: "text", parts: template(block["text"]), ...(tone ? { tone } : {}) }];
|
|
93
|
+
if (has("badge"))
|
|
94
|
+
return [{ t: "badge", parts: template(block["badge"]), ...(tone ? { tone } : {}) }];
|
|
95
|
+
if (has("field")) {
|
|
96
|
+
const as = VIEW_FIELD_FORMATS.includes(block["as"]) ? block["as"] : undefined;
|
|
97
|
+
return [{ t: "field", field: String(block["field"]), ...(as ? { as } : {}), ...(label ? { label } : {}) }];
|
|
98
|
+
}
|
|
99
|
+
if (has("progress")) {
|
|
100
|
+
const p = (block["progress"] ?? {});
|
|
101
|
+
return [{ t: "progress", value: expr(p.value), max: expr(p.max), ...(label ? { label } : {}) }];
|
|
102
|
+
}
|
|
103
|
+
if (has("group"))
|
|
104
|
+
return [{ t: "group", blocks: compileBlocks(block["group"], depth + 1), direction: block["direction"] === "row" ? "row" : "column" }];
|
|
105
|
+
if (has("when"))
|
|
106
|
+
return [{ t: "when", when: expr(block["when"]), show: compileBlocks(block["show"], depth + 1) }];
|
|
107
|
+
if (has("divider"))
|
|
108
|
+
return [{ t: "divider" }];
|
|
109
|
+
if (has("figure"))
|
|
110
|
+
return [{ t: "figure" }];
|
|
111
|
+
return [];
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const NOTHING = "—";
|
|
115
|
+
/** The allowance a card's template gets: a card is drawn many times a frame. */
|
|
116
|
+
const BUDGET = 500;
|
|
117
|
+
const EMPTY_GRAPH = {
|
|
118
|
+
getNode: () => undefined,
|
|
119
|
+
allNodes: () => [],
|
|
120
|
+
allEdges: () => [],
|
|
121
|
+
nodesOfKind: () => [],
|
|
122
|
+
edgesOfKind: () => [],
|
|
123
|
+
out: () => [],
|
|
124
|
+
in: () => [],
|
|
125
|
+
neighbors: () => [],
|
|
126
|
+
has: () => false,
|
|
127
|
+
};
|
|
128
|
+
function judge(expr, ctx) {
|
|
129
|
+
if (!expr)
|
|
130
|
+
return { ok: false, problem: "an expression that does not parse" };
|
|
131
|
+
try {
|
|
132
|
+
return { ok: true, value: evaluateExpr(expr, { graph: ctx.graph ?? EMPTY_GRAPH, subject: ctx.node, kinds: ctx.kinds, today: ctx.today, budget: ctx.budget ?? BUDGET }) };
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
return { ok: false, problem: e instanceof Error ? e.message : String(e) };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** A template's words, each part judged as `renderTemplate` judges it — and what could not be, said. */
|
|
139
|
+
function say(parts, ctx) {
|
|
140
|
+
if (!parts)
|
|
141
|
+
return { text: NOTHING, problem: "a template that does not parse" };
|
|
142
|
+
let problem;
|
|
143
|
+
const text = parts
|
|
144
|
+
.map((part) => {
|
|
145
|
+
if (part.text !== undefined)
|
|
146
|
+
return part.text;
|
|
147
|
+
const judged = judge(part.expr ?? null, ctx);
|
|
148
|
+
if (!judged.ok) {
|
|
149
|
+
problem ??= `{${part.source ?? ""}}: ${judged.problem}`;
|
|
150
|
+
return NOTHING;
|
|
151
|
+
}
|
|
152
|
+
return formatValue(judged.value, part.format, ctx.today, part.formatArgs);
|
|
153
|
+
})
|
|
154
|
+
.join("");
|
|
155
|
+
return problem ? { text, problem } : { text };
|
|
156
|
+
}
|
|
157
|
+
function toneWord(tone, ctx) {
|
|
158
|
+
if (tone === undefined)
|
|
159
|
+
return undefined;
|
|
160
|
+
if (typeof tone === "string")
|
|
161
|
+
return tone;
|
|
162
|
+
const judged = judge(tone.expr, ctx);
|
|
163
|
+
return judged.ok && isTone(judged.value) ? judged.value : "neutral";
|
|
164
|
+
}
|
|
165
|
+
/** Only http(s) is ever a link; anything else — `javascript:`, `data:`, a typo — is shown as words. */
|
|
166
|
+
export function safeHref(value) {
|
|
167
|
+
if (typeof value !== "string")
|
|
168
|
+
return undefined;
|
|
169
|
+
try {
|
|
170
|
+
const url = new URL(value);
|
|
171
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url.href : undefined;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function fieldText(key, value, ctx, as) {
|
|
178
|
+
if (value === null || value === undefined || value === "")
|
|
179
|
+
return NOTHING;
|
|
180
|
+
if (typeof value === "boolean")
|
|
181
|
+
return value ? "yes" : "no";
|
|
182
|
+
if (as)
|
|
183
|
+
return formatValue(value, as, ctx.today);
|
|
184
|
+
const spec = ctx.fields[key];
|
|
185
|
+
if (ctx.definition?.display?.format?.[key])
|
|
186
|
+
return valueWords(ctx.definition, key, value);
|
|
187
|
+
if (spec?.type === "date")
|
|
188
|
+
return formatValue(value, "date", ctx.today);
|
|
189
|
+
if (spec?.type === "enum" && typeof value === "string")
|
|
190
|
+
return valueWords(ctx.definition, key, value);
|
|
191
|
+
if (typeof value === "number")
|
|
192
|
+
return value.toLocaleString("en-US");
|
|
193
|
+
if (Array.isArray(value))
|
|
194
|
+
return value.map((one) => String(one)).join(", ");
|
|
195
|
+
if (typeof value === "object")
|
|
196
|
+
return NOTHING;
|
|
197
|
+
return String(value);
|
|
198
|
+
}
|
|
199
|
+
/** A figure's words: a number in figures, money (in a currency when it names one) or a fraction as a percent. */
|
|
200
|
+
export function sayNumber(value, as, currency, today) {
|
|
201
|
+
if (typeof value !== "number")
|
|
202
|
+
return String(value);
|
|
203
|
+
if (as === "money" && currency) {
|
|
204
|
+
return safely(() => value.toLocaleString("en-US", { style: "currency", currency, maximumFractionDigits: Number.isInteger(value) ? 0 : 2, minimumFractionDigits: Number.isInteger(value) ? 0 : 2 })) ?? formatValue(value, "money", today);
|
|
205
|
+
}
|
|
206
|
+
if (as === "money" || as === "percent")
|
|
207
|
+
return formatValue(value, as, today);
|
|
208
|
+
return value.toLocaleString("en-US", { maximumFractionDigits: 2 });
|
|
209
|
+
}
|
|
210
|
+
const withProblem = (block, problem) => (problem ? { ...block, problem } : block);
|
|
211
|
+
function resolveOne(block, ctx, first) {
|
|
212
|
+
switch (block.t) {
|
|
213
|
+
case "title": {
|
|
214
|
+
const said = say(block.parts, ctx);
|
|
215
|
+
return withProblem({ t: "title", text: said.text }, said.problem);
|
|
216
|
+
}
|
|
217
|
+
case "text": {
|
|
218
|
+
const said = say(block.parts, ctx);
|
|
219
|
+
const tone = toneWord(block.tone, ctx);
|
|
220
|
+
return withProblem({ t: "text", text: said.text, ...(tone ? { tone } : {}) }, said.problem);
|
|
221
|
+
}
|
|
222
|
+
case "badge": {
|
|
223
|
+
const said = say(block.parts, ctx);
|
|
224
|
+
return withProblem({ t: "badge", text: said.text, tone: toneWord(block.tone, ctx) ?? "neutral" }, said.problem);
|
|
225
|
+
}
|
|
226
|
+
case "field": {
|
|
227
|
+
const label = block.label ?? fieldWords(ctx.definition, block.field);
|
|
228
|
+
// About no one record, there is no field to show (the check says so).
|
|
229
|
+
if (!ctx.node)
|
|
230
|
+
return { t: "field", field: block.field, label, text: NOTHING, problem: `"${block.field}" names a field, and these blocks are about no one record` };
|
|
231
|
+
// A computed field is worked out like any expression, under the same budget (FR-83); else an OWN field only: a name on the prototype is not a field of the record.
|
|
232
|
+
const worked = ctx.kinds.get(ctx.node.kind)?.computed?.has(block.field);
|
|
233
|
+
let raw;
|
|
234
|
+
let problem;
|
|
235
|
+
if (worked) {
|
|
236
|
+
const judged = judge({ t: "ident", name: block.field, at: 0 }, ctx);
|
|
237
|
+
if (!judged.ok)
|
|
238
|
+
problem = judged.problem;
|
|
239
|
+
else
|
|
240
|
+
raw = judged.value !== null && typeof judged.value === "object" ? formatValue(judged.value, undefined, ctx.today) : judged.value;
|
|
241
|
+
}
|
|
242
|
+
else
|
|
243
|
+
raw = Object.prototype.hasOwnProperty.call(ctx.node, block.field) ? ctx.node[block.field] : undefined;
|
|
244
|
+
const href = ctx.fields[block.field]?.type === "url" && block.as === undefined ? safeHref(raw) : undefined;
|
|
245
|
+
const text = safely(() => fieldText(block.field, raw, ctx, block.as)) ?? NOTHING;
|
|
246
|
+
return withProblem({ t: "field", field: block.field, label, text, ...(href ? { href } : {}) }, problem);
|
|
247
|
+
}
|
|
248
|
+
case "progress": {
|
|
249
|
+
const value = judge(block.value, ctx);
|
|
250
|
+
const max = judge(block.max, ctx);
|
|
251
|
+
const label = block.label ?? "Progress";
|
|
252
|
+
const problem = !value.ok ? value.problem : !max.ok ? max.problem : undefined;
|
|
253
|
+
if (!(value.ok && max.ok && typeof value.value === "number" && typeof max.value === "number" && Number.isFinite(value.value) && Number.isFinite(max.value) && max.value > 0)) {
|
|
254
|
+
return withProblem({ t: "progress", label, text: NOTHING }, problem);
|
|
255
|
+
}
|
|
256
|
+
return { t: "progress", label, value: value.value, max: max.value, text: `${formatValue(value.value, undefined, ctx.today)} of ${formatValue(max.value, undefined, ctx.today)}` };
|
|
257
|
+
}
|
|
258
|
+
case "group":
|
|
259
|
+
return { t: "group", direction: block.direction, blocks: resolveBlocks(block.blocks, ctx) };
|
|
260
|
+
case "when": {
|
|
261
|
+
// A condition that cannot be judged hides what it guards, like a rule's `when`.
|
|
262
|
+
const judged = judge(block.when, ctx);
|
|
263
|
+
const shown = judged.ok && judged.value === true;
|
|
264
|
+
return withProblem({ t: "when", shown, blocks: shown ? resolveBlocks(block.show, ctx) : [] }, judged.ok ? undefined : judged.problem);
|
|
265
|
+
}
|
|
266
|
+
case "divider":
|
|
267
|
+
return { t: "divider" };
|
|
268
|
+
case "figure":
|
|
269
|
+
return { t: "figure" };
|
|
270
|
+
case "headline": {
|
|
271
|
+
const said = say(block.parts, ctx);
|
|
272
|
+
const level = Math.min(6, Math.max(1, (first ? ctx.firstHeading : undefined) ?? ctx.heading ?? 3));
|
|
273
|
+
return withProblem({ t: "headline", level, text: said.text }, said.problem);
|
|
274
|
+
}
|
|
275
|
+
case "number": {
|
|
276
|
+
const judged = judge(block.value, ctx);
|
|
277
|
+
const text = !judged.ok || judged.value === null || typeof judged.value === "object" ? NOTHING : sayNumber(judged.value, block.as, block.currency, ctx.today);
|
|
278
|
+
return withProblem({ t: "number", text, ...(block.label ? { label: block.label } : {}) }, judged.ok ? undefined : judged.problem);
|
|
279
|
+
}
|
|
280
|
+
case "list":
|
|
281
|
+
return resolveList(block, ctx);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/** Blocks worked out for one record — or for none. Pure: everything they read is in `ctx`. */
|
|
285
|
+
export function resolveBlocks(blocks, ctx) {
|
|
286
|
+
const first = blocks.findIndex((block) => block.t === "headline");
|
|
287
|
+
return blocks.map((block, i) => resolveOne(block, ctx, i === first));
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* A LIST OF RECORDS: the records its expression names — the kinds swept,
|
|
291
|
+
* or a walk from the record (`out('includes')`, `in('answers')`) — in their
|
|
292
|
+
* order, a few, grouped by a choice in its declared order. Read from the
|
|
293
|
+
* graph the context is handed, which for a seat is what that seat may see
|
|
294
|
+
* (FR-55): a record it may not see is not listed, not counted, and opens no
|
|
295
|
+
* group of its own.
|
|
296
|
+
*/
|
|
297
|
+
function resolveList(block, ctx) {
|
|
298
|
+
const headingLevel = Math.min(6, (ctx.heading ?? 3) + 1);
|
|
299
|
+
const judged = judge(block.source, ctx);
|
|
300
|
+
if (!judged.ok)
|
|
301
|
+
return { t: "list", as: block.as, failed: true, members: [], headingLevel, more: 0, problem: judged.problem };
|
|
302
|
+
const value = judged.value;
|
|
303
|
+
let nodes = value instanceof NodeSet ? value.nodes : value !== null && typeof value === "object" && !Array.isArray(value) ? [value] : [];
|
|
304
|
+
if (block.choiceOrder && ctx.schema)
|
|
305
|
+
nodes = inChoiceOrder(nodes, block.choiceOrder, ctx.schema);
|
|
306
|
+
const all = nodes.length;
|
|
307
|
+
nodes = nodes.slice(0, block.limit ?? MAX_LIST_LIMIT);
|
|
308
|
+
const more = block.limit === undefined ? all - nodes.length : 0;
|
|
309
|
+
return {
|
|
310
|
+
t: "list",
|
|
311
|
+
as: block.as,
|
|
312
|
+
failed: false,
|
|
313
|
+
members: nodes,
|
|
314
|
+
...(block.group && ctx.schema && nodes.length > 0 ? { groups: groupsOf(nodes, block.group, ctx.schema) } : {}),
|
|
315
|
+
headingLevel,
|
|
316
|
+
...(nodes.length === 0 && block.empty ? { empty: block.empty } : {}),
|
|
317
|
+
more,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/** A choice field's choices on a kind, in the order they are declared; empty when it is not one. */
|
|
321
|
+
function choicesOf(schema, kind, field) {
|
|
322
|
+
const shape = schema.tryDefinition(kind)?.fields?.shape;
|
|
323
|
+
const spec = shape && Object.prototype.hasOwnProperty.call(shape, field) ? fieldSpecOf(shape[field]) : undefined;
|
|
324
|
+
return spec?.type === "enum" ? (spec.options ?? []) : [];
|
|
325
|
+
}
|
|
326
|
+
const valueOf = (node, field) => (Object.prototype.hasOwnProperty.call(node, field) ? node[field] : undefined);
|
|
327
|
+
/** Records in the order a choice field's choices are declared; a value among none of them last, in the order given. */
|
|
328
|
+
function inChoiceOrder(nodes, field, schema) {
|
|
329
|
+
const rank = (node) => {
|
|
330
|
+
const at = choicesOf(schema, node.kind, field).indexOf(String(valueOf(node, field)));
|
|
331
|
+
return at < 0 ? Number.MAX_SAFE_INTEGER : at;
|
|
332
|
+
};
|
|
333
|
+
return nodes.map((node, i) => ({ node, i, rank: rank(node) })).sort((a, b) => a.rank - b.rank || a.i - b.i).map((one) => one.node);
|
|
334
|
+
}
|
|
335
|
+
const sentenceCase = (words) => words.charAt(0).toUpperCase() + words.slice(1);
|
|
336
|
+
/**
|
|
337
|
+
* The records under a heading per choice, in the declared order; a choice
|
|
338
|
+
* with no record here has no heading at all, so a heading never says that
|
|
339
|
+
* something the reader cannot see exists. A value among no choice goes
|
|
340
|
+
* last, unheaded.
|
|
341
|
+
*/
|
|
342
|
+
function groupsOf(nodes, group, schema) {
|
|
343
|
+
const order = [];
|
|
344
|
+
for (const node of nodes)
|
|
345
|
+
for (const choice of choicesOf(schema, node.kind, group.by))
|
|
346
|
+
if (!order.includes(choice))
|
|
347
|
+
order.push(choice);
|
|
348
|
+
const out = [];
|
|
349
|
+
for (const choice of order) {
|
|
350
|
+
const members = nodes.filter((node) => valueOf(node, group.by) === choice);
|
|
351
|
+
if (members.length === 0)
|
|
352
|
+
continue;
|
|
353
|
+
const definition = schema.tryDefinition(members[0].kind);
|
|
354
|
+
out.push({ value: choice, heading: group.headings[choice] ?? sentenceCase(valueWords(definition, group.by, choice)), members });
|
|
355
|
+
}
|
|
356
|
+
const rest = nodes.filter((node) => !order.includes(String(valueOf(node, group.by))));
|
|
357
|
+
if (rest.length > 0)
|
|
358
|
+
out.push({ value: null, members: rest });
|
|
359
|
+
return out;
|
|
360
|
+
}
|
|
361
|
+
/** Whether a block takes more than one line: a list, a headline or a figure, or a group or condition holding one. */
|
|
362
|
+
export function isTallBlock(block) {
|
|
363
|
+
if (block.t === "list" || block.t === "headline" || block.t === "number")
|
|
364
|
+
return true;
|
|
365
|
+
if (block.t === "group")
|
|
366
|
+
return block.blocks.some(isTallBlock);
|
|
367
|
+
if (block.t === "when")
|
|
368
|
+
return block.show.some(isTallBlock);
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
/** A kind's declared fields in the document's words, read from its schema. */
|
|
372
|
+
export function fieldSpecsOf(schema, kind) {
|
|
373
|
+
const shape = schema.tryDefinition(kind)?.fields?.shape ?? {};
|
|
374
|
+
const read = {};
|
|
375
|
+
for (const [key, field] of Object.entries(shape)) {
|
|
376
|
+
const spec = fieldSpecOf(field);
|
|
377
|
+
if (spec)
|
|
378
|
+
read[key] = spec;
|
|
379
|
+
}
|
|
380
|
+
return read;
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/document/blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/document/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAcL,KAAK,UAAU,EAMhB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgD,KAAK,SAAS,EAAc,MAAM,oBAAoB,CAAC;AAE9G,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,UAAU,EAEf,KAAK,eAAe,EAEpB,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/document/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAcL,KAAK,UAAU,EAMhB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgD,KAAK,SAAS,EAAc,MAAM,oBAAoB,CAAC;AAE9G,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,UAAU,EAEf,KAAK,eAAe,EAEpB,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AAkBrB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;CACrC;AAKD,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,CAoCzH;AA2BD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAW5E;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,GAAG,SAAS,UAAU,EAAE,CAmBxF;AAySD,cAAM,OAAQ,SAAQ,KAAK;CAAG;AAE9B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,GAAG,eAAe,CAc9G;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,GAAG,eAAe,CAgT1H;AAwBD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,CAAC"}
|
package/dist/document/compile.js
CHANGED
|
@@ -9,7 +9,8 @@ import { error, hasErrors, warning } from "./findings.js";
|
|
|
9
9
|
import { DocumentSpec, MAX_DOCUMENT_BYTES, } from "./schema.js";
|
|
10
10
|
import { parseTemplate, renderTemplate, TemplateError } from "./template.js";
|
|
11
11
|
import { upgradeDocument } from "./upgrade.js";
|
|
12
|
-
import { validateViews } from "./views.js";
|
|
12
|
+
import { homeOf, validateViews, viewsOf } from "./views.js";
|
|
13
|
+
import { computedOf, parsedComputed, validateComputed, workedOutAlone } from "./computed.js";
|
|
13
14
|
const BUILTIN_REFS = new Set(["subject", "now", "today"]);
|
|
14
15
|
const SUBJECT_ARG = "id";
|
|
15
16
|
/** Parse and validate without compiling — the document's own sentences, before the framework's. */
|
|
@@ -74,9 +75,11 @@ function edgeIndex(document) {
|
|
|
74
75
|
export function kindShapes(document) {
|
|
75
76
|
const shapes = new Map();
|
|
76
77
|
for (const [kind, spec] of Object.entries(document.kinds)) {
|
|
78
|
+
const computed = parsedComputed(spec);
|
|
77
79
|
shapes.set(kind, {
|
|
78
80
|
fields: new Set(Object.keys(spec.fields)),
|
|
79
81
|
edges: new Map(Object.entries(spec.edges ?? {}).map(([name, e]) => [name, e.cardinality ?? "many"])),
|
|
82
|
+
...(computed ? { computed } : {}),
|
|
80
83
|
});
|
|
81
84
|
}
|
|
82
85
|
return shapes;
|
|
@@ -159,9 +162,11 @@ function validate(document) {
|
|
|
159
162
|
}
|
|
160
163
|
if (spec.lifecycle && !spec.fields[spec.lifecycle.field])
|
|
161
164
|
findings.push(error("lifecycle-field", `${at}.lifecycle.field`, `${kind} has no field "${spec.lifecycle.field}"`));
|
|
165
|
+
// A glance may say a computed field: the surfaces that draw a glance work it out over the seat's graph (FR-83).
|
|
166
|
+
const computedHere = (name) => spec.computed !== undefined && Object.prototype.hasOwnProperty.call(spec.computed, name);
|
|
162
167
|
for (const field of spec.glance ?? []) {
|
|
163
|
-
if (!spec.fields[field])
|
|
164
|
-
findings.push(error("glance-field", `${at}.glance`, `a glance at ${kind} is to say "${field}", and ${kind} has no field called that`, `use one of: ${Object.keys(spec.fields).join(", ")}`));
|
|
168
|
+
if (!spec.fields[field] && !computedHere(field))
|
|
169
|
+
findings.push(error("glance-field", `${at}.glance`, `a glance at ${kind} is to say "${field}", and ${kind} has no field or computed field called that`, `use one of: ${[...Object.keys(spec.fields), ...Object.keys(spec.computed ?? {})].join(", ")}`));
|
|
165
170
|
}
|
|
166
171
|
for (const key of ["label", "describe"]) {
|
|
167
172
|
const source = spec[key];
|
|
@@ -172,8 +177,15 @@ function validate(document) {
|
|
|
172
177
|
if (!part.expr)
|
|
173
178
|
continue;
|
|
174
179
|
for (const name of analyzeExpr(part.expr).names) {
|
|
175
|
-
if (
|
|
176
|
-
|
|
180
|
+
if (spec.fields[name])
|
|
181
|
+
continue;
|
|
182
|
+
// A computed field worked out from the record alone is said like a field; one that reads beyond it cannot be, with no graph in hand.
|
|
183
|
+
if (computedHere(name)) {
|
|
184
|
+
if (!workedOutAlone(spec, name))
|
|
185
|
+
findings.push(error("template-field", `${at}.${key}`, `${kind}'s ${name} is worked out from beyond the record, and a ${key} is said with no graph to read`, `show it in a view instead, or name a computed field worked out from ${kind}'s own fields`));
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
findings.push(error("template-field", `${at}.${key}`, `${kind} has no field "${name}" for its ${key} to show`, key === "label" ? "a label can only show the record's own fields and what they work out" : undefined));
|
|
177
189
|
}
|
|
178
190
|
}
|
|
179
191
|
}
|
|
@@ -191,9 +203,14 @@ function validate(document) {
|
|
|
191
203
|
const subjectKinds = asArray(act.on);
|
|
192
204
|
const effects = effectsOf(act, document);
|
|
193
205
|
if (act.creates && act.on === undefined && act.writes && kinds.has(act.creates)) {
|
|
194
|
-
for (const field of act.writes)
|
|
195
|
-
if (
|
|
206
|
+
for (const field of act.writes) {
|
|
207
|
+
if (document.kinds[act.creates].fields[field])
|
|
208
|
+
continue;
|
|
209
|
+
if (document.kinds[act.creates].computed?.[field] !== undefined)
|
|
210
|
+
findings.push(error("computed-written", `${at}.writes`, `${act.creates}'s ${field} is worked out, not written: no act can set it`, "write the stored fields it is worked out from"));
|
|
211
|
+
else
|
|
196
212
|
findings.push(error("act-field", `${at}.writes`, `${act.creates} has no field "${field}"`));
|
|
213
|
+
}
|
|
197
214
|
}
|
|
198
215
|
if (effects.length === 0)
|
|
199
216
|
findings.push(error("act-empty", at, `"${name}" does nothing`, "give it effects or a shorthand such as sets or creates"));
|
|
@@ -204,10 +221,16 @@ function validate(document) {
|
|
|
204
221
|
if ("create" in effect) {
|
|
205
222
|
if (!kinds.has(effect.create))
|
|
206
223
|
findings.push(error("act-kind", `${where}.create`, `"${effect.create}" is not a kind this document declares`));
|
|
207
|
-
else
|
|
208
|
-
for (const field of Object.keys(effect.set ?? {}))
|
|
209
|
-
if (
|
|
224
|
+
else {
|
|
225
|
+
for (const field of Object.keys(effect.set ?? {})) {
|
|
226
|
+
if (document.kinds[effect.create].fields[field])
|
|
227
|
+
continue;
|
|
228
|
+
if (document.kinds[effect.create].computed?.[field] !== undefined)
|
|
229
|
+
findings.push(error("computed-written", `${where}.set.${field}`, `${effect.create}'s ${field} is worked out, not written: no act can set it`, "set the stored fields it is worked out from"));
|
|
230
|
+
else
|
|
210
231
|
findings.push(error("act-field", `${where}.set.${field}`, `${effect.create} has no field "${field}"`));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
211
234
|
if (effect.as)
|
|
212
235
|
created.set(effect.as, effect.create);
|
|
213
236
|
}
|
|
@@ -224,9 +247,14 @@ function validate(document) {
|
|
|
224
247
|
if (target === "subject" && subjectKinds.length === 0)
|
|
225
248
|
findings.push(error("act-subject", `${at}.on`, `"${name}" changes "$subject" but does not say which kinds it is "on"`));
|
|
226
249
|
for (const field of Object.keys(effect.set)) {
|
|
227
|
-
for (const kind of targetKinds)
|
|
228
|
-
if (kinds.has(kind)
|
|
250
|
+
for (const kind of targetKinds) {
|
|
251
|
+
if (!kinds.has(kind) || document.kinds[kind].fields[field])
|
|
252
|
+
continue;
|
|
253
|
+
if (document.kinds[kind].computed?.[field] !== undefined)
|
|
254
|
+
findings.push(error("computed-written", `${where}.set.${field}`, `${kind}'s ${field} is worked out, not written: no act can set it`, "set the stored fields it is worked out from"));
|
|
255
|
+
else
|
|
229
256
|
findings.push(error("act-field", `${where}.set.${field}`, `${kind} has no field "${field}"`));
|
|
257
|
+
}
|
|
230
258
|
}
|
|
231
259
|
}
|
|
232
260
|
else if ("remove" in effect) {
|
|
@@ -260,7 +288,7 @@ function validate(document) {
|
|
|
260
288
|
for (const n of shape.names) {
|
|
261
289
|
if (rule.over === "graph")
|
|
262
290
|
findings.push(error("rule-name", `${at}.${key}`, `"${n}" means nothing in a rule over the whole graph`, "name a kind in \"over\", or use all('kind')"));
|
|
263
|
-
else if (spec && !spec.fields[n] && !spec.edges?.[n]) {
|
|
291
|
+
else if (spec && !spec.fields[n] && !spec.edges?.[n] && spec.computed?.[n] === undefined) {
|
|
264
292
|
const hyphenated = Object.keys(spec.edges ?? {}).find((e) => e.includes("-") && e.split("-").includes(n));
|
|
265
293
|
findings.push(error("rule-name", `${at}.${key}`, `${rule.over} has no field or relation called "${n}"`, hyphenated ? `"${hyphenated}" reads as a subtraction in a rule; rename the relation to one camelCase word, like "${hyphenated.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())}"` : undefined));
|
|
266
294
|
}
|
|
@@ -305,6 +333,7 @@ function validate(document) {
|
|
|
305
333
|
});
|
|
306
334
|
}
|
|
307
335
|
findings.push(...validateViews(document));
|
|
336
|
+
findings.push(...validateComputed(new Map(Object.entries(document.kinds).map(([kind, spec]) => [kind, { fields: new Set(Object.keys(spec.fields)), edges: new Set(Object.keys(spec.edges ?? {})), computed: computedOf(spec) }])), (kind, name) => `kinds.${kind}.computed.${name}`));
|
|
308
337
|
return findings;
|
|
309
338
|
}
|
|
310
339
|
/*
|
|
@@ -442,6 +471,9 @@ export function compileDocument(raw, options = {}) {
|
|
|
442
471
|
const check = checkApp(app);
|
|
443
472
|
for (const f of check.findings) {
|
|
444
473
|
const finding = { severity: f.severity === "error" ? "error" : f.severity === "warning" ? "warning" : "note", code: `check:${f.code}`, path: frameworkPath(f.where, document), message: f.message, ...(f.fix ? { fix: f.fix } : {}) };
|
|
474
|
+
// The document already said it, at the same path (a blocks lens's words are held by both): once is enough.
|
|
475
|
+
if (compiled.findings.some((said) => said.code === f.code && said.path === finding.path))
|
|
476
|
+
continue;
|
|
445
477
|
findings.push(f.code === "glance-unchosen" ? inDocumentWords(finding, f.where, document) : finding);
|
|
446
478
|
}
|
|
447
479
|
if (hasErrors(findings))
|
|
@@ -475,7 +507,12 @@ export function compileDocumentWithoutCheck(raw, options = {}) {
|
|
|
475
507
|
const labelSource = spec.label ?? (defaultLabelField(spec) ? `{${defaultLabelField(spec)}}` : undefined);
|
|
476
508
|
const labelParts = labelSource ? parseTemplate(labelSource) : undefined;
|
|
477
509
|
const describeParts = spec.describe ? parseTemplate(spec.describe) : undefined;
|
|
478
|
-
const
|
|
510
|
+
const computed = computedOf(spec);
|
|
511
|
+
// A computed field's words are said like a field's: its label, where it has one.
|
|
512
|
+
const labels = Object.fromEntries([
|
|
513
|
+
...Object.entries(spec.fields).filter(([, f]) => f.label).map(([n, f]) => [n, f.label]),
|
|
514
|
+
...[...computed].filter(([, c]) => c.label).map(([n, c]) => [n, c.label]),
|
|
515
|
+
]);
|
|
479
516
|
// Defaults stay out of the zod schema (hydration must not invent values) and ride beside it, for a repair to read.
|
|
480
517
|
const defaults = Object.fromEntries(Object.entries(spec.fields).filter(([, f]) => f.default !== undefined).map(([n, f]) => [n, f.default]));
|
|
481
518
|
const edgeDecls = Object.fromEntries(Object.entries(spec.edges ?? {}).map(([n, e]) => [
|
|
@@ -498,6 +535,7 @@ export function compileDocumentWithoutCheck(raw, options = {}) {
|
|
|
498
535
|
...(describeParts ? { describe: (node) => renderTemplate(describeParts, { node: node, kinds: shapes, today: today() }) } : {}),
|
|
499
536
|
...(spec.lifecycle ? { lifecycle: { field: spec.lifecycle.field, retired: spec.lifecycle.retired } } : {}),
|
|
500
537
|
...(spec.figure ? { figure: spec.figure } : {}),
|
|
538
|
+
...(spec.computed && Object.keys(spec.computed).length > 0 ? { computed: spec.computed } : {}),
|
|
501
539
|
...(Object.keys(labels).length > 0 || spec.glance ? { display: { ...(Object.keys(labels).length > 0 ? { labels } : {}), ...(spec.glance ? { glance: [...spec.glance] } : {}) } } : {}),
|
|
502
540
|
...(Object.keys(defaults).length > 0 ? { defaults } : {}),
|
|
503
541
|
});
|
|
@@ -774,9 +812,13 @@ export function compileDocumentWithoutCheck(raw, options = {}) {
|
|
|
774
812
|
...(brand ? { brand } : {}),
|
|
775
813
|
...(document.modules ? { modules: document.modules } : {}),
|
|
776
814
|
...(document.lenses ? { lenses: document.lenses } : {}),
|
|
815
|
+
// The arrangement is the app's (FR-80): every face reads it beside the places.
|
|
816
|
+
...(document.pages ? { pages: document.pages } : {}),
|
|
777
817
|
...(document.settings ? { settings: document.settings } : {}),
|
|
778
818
|
// The document's views are the declaration's view specs (FR-03): data the framework draws.
|
|
779
|
-
...(
|
|
819
|
+
...(Object.keys(viewsOf(document)).length > 0 ? { viewSpecs: viewsOf(document) } : {}),
|
|
820
|
+
// And its home view, about no one record, is the app's home (FR-81).
|
|
821
|
+
...(homeOf(document) ? { home: homeOf(document) } : {}),
|
|
780
822
|
version: document.version ?? 1,
|
|
781
823
|
};
|
|
782
824
|
// `toDocument(app)` gives this document back, byte for byte.
|