@cruba/crubal 0.0.0-stage → 0.2.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.
Files changed (99) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +97 -2
  3. package/dist/bin/crubal.d.ts +2 -0
  4. package/dist/bin/crubal.js +103 -0
  5. package/dist/bin/crubal.js.map +1 -0
  6. package/dist/src/access.d.ts +126 -0
  7. package/dist/src/access.js +517 -0
  8. package/dist/src/access.js.map +1 -0
  9. package/dist/src/arrival.d.ts +55 -0
  10. package/dist/src/arrival.js +124 -0
  11. package/dist/src/arrival.js.map +1 -0
  12. package/dist/src/browser.d.ts +10 -0
  13. package/dist/src/browser.js +13 -0
  14. package/dist/src/browser.js.map +1 -0
  15. package/dist/src/bundle.d.ts +66 -0
  16. package/dist/src/bundle.js +753 -0
  17. package/dist/src/bundle.js.map +1 -0
  18. package/dist/src/canonical.d.ts +6 -0
  19. package/dist/src/canonical.js +47 -0
  20. package/dist/src/canonical.js.map +1 -0
  21. package/dist/src/conditions.d.ts +28 -0
  22. package/dist/src/conditions.js +216 -0
  23. package/dist/src/conditions.js.map +1 -0
  24. package/dist/src/corpus.d.ts +8 -0
  25. package/dist/src/corpus.js +1207 -0
  26. package/dist/src/corpus.js.map +1 -0
  27. package/dist/src/defs.d.ts +151 -0
  28. package/dist/src/defs.js +611 -0
  29. package/dist/src/defs.js.map +1 -0
  30. package/dist/src/dictionary.d.ts +65 -0
  31. package/dist/src/dictionary.js +557 -0
  32. package/dist/src/dictionary.js.map +1 -0
  33. package/dist/src/exchange.d.ts +236 -0
  34. package/dist/src/exchange.js +1035 -0
  35. package/dist/src/exchange.js.map +1 -0
  36. package/dist/src/forms.d.ts +16 -0
  37. package/dist/src/forms.js +169 -0
  38. package/dist/src/forms.js.map +1 -0
  39. package/dist/src/index.d.ts +27 -0
  40. package/dist/src/index.js +29 -0
  41. package/dist/src/index.js.map +1 -0
  42. package/dist/src/lex.d.ts +21 -0
  43. package/dist/src/lex.js +142 -0
  44. package/dist/src/lex.js.map +1 -0
  45. package/dist/src/lifecycle.d.ts +84 -0
  46. package/dist/src/lifecycle.js +415 -0
  47. package/dist/src/lifecycle.js.map +1 -0
  48. package/dist/src/log.d.ts +78 -0
  49. package/dist/src/log.js +506 -0
  50. package/dist/src/log.js.map +1 -0
  51. package/dist/src/migrate.d.ts +111 -0
  52. package/dist/src/migrate.js +286 -0
  53. package/dist/src/migrate.js.map +1 -0
  54. package/dist/src/model.d.ts +68 -0
  55. package/dist/src/model.js +188 -0
  56. package/dist/src/model.js.map +1 -0
  57. package/dist/src/packages.d.ts +69 -0
  58. package/dist/src/packages.js +232 -0
  59. package/dist/src/packages.js.map +1 -0
  60. package/dist/src/print-text.d.ts +7 -0
  61. package/dist/src/print-text.js +216 -0
  62. package/dist/src/print-text.js.map +1 -0
  63. package/dist/src/publish.d.ts +27 -0
  64. package/dist/src/publish.js +275 -0
  65. package/dist/src/publish.js.map +1 -0
  66. package/dist/src/read-text.d.ts +10 -0
  67. package/dist/src/read-text.js +385 -0
  68. package/dist/src/read-text.js.map +1 -0
  69. package/dist/src/records.d.ts +31 -0
  70. package/dist/src/records.js +72 -0
  71. package/dist/src/records.js.map +1 -0
  72. package/dist/src/review.d.ts +22 -0
  73. package/dist/src/review.js +198 -0
  74. package/dist/src/review.js.map +1 -0
  75. package/dist/src/rules.d.ts +96 -0
  76. package/dist/src/rules.js +611 -0
  77. package/dist/src/rules.js.map +1 -0
  78. package/dist/src/schedule.d.ts +24 -0
  79. package/dist/src/schedule.js +126 -0
  80. package/dist/src/schedule.js.map +1 -0
  81. package/dist/src/std-packages.d.ts +9 -0
  82. package/dist/src/std-packages.js +268 -0
  83. package/dist/src/std-packages.js.map +1 -0
  84. package/dist/src/store.d.ts +164 -0
  85. package/dist/src/store.js +538 -0
  86. package/dist/src/store.js.map +1 -0
  87. package/dist/src/tree.d.ts +35 -0
  88. package/dist/src/tree.js +159 -0
  89. package/dist/src/tree.js.map +1 -0
  90. package/dist/src/units-table.d.ts +1 -0
  91. package/dist/src/units-table.js +200 -0
  92. package/dist/src/units-table.js.map +1 -0
  93. package/dist/src/units.d.ts +42 -0
  94. package/dist/src/units.js +98 -0
  95. package/dist/src/units.js.map +1 -0
  96. package/dist/src/views.d.ts +216 -0
  97. package/dist/src/views.js +761 -0
  98. package/dist/src/views.js.map +1 -0
  99. package/package.json +60 -4
@@ -0,0 +1,198 @@
1
+ // review.ts: review decisions as writes (spec 9.5, 10.4, 11.9, 14.7; docs/design/completion.md A). A
2
+ // decision is one entry: the `review` write that records it, and the writes it causes: a `define` of the
3
+ // facet, contract or units extension it changed, a value made current from a suggestion or a held bag, a
4
+ // suggestion denied. Nothing here replays or runs; a store does that after the entry lands.
5
+ import { contractJson } from "./bundle.js";
6
+ import { facetJson } from "./dictionary.js";
7
+ import { split } from "./lifecycle.js";
8
+ import { CrubalError } from "./tree.js";
9
+ import { extendUnits } from "./units.js";
10
+ const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
11
+ /** The units extension as text, for the units table (11.9). */
12
+ export function unitsExtensionText(measures) {
13
+ return measures
14
+ .map((m) => {
15
+ const lines = [`measure: ${m.measure}`];
16
+ for (const k of ["dimension", "factor", "offset", "rounding", "uncefact"])
17
+ if (m[k] !== undefined)
18
+ lines.push(` ${k}: ${m[k]}`);
19
+ if (Array.isArray(m.spellings) && m.spellings.length)
20
+ lines.push(` spellings: ${m.spellings.join(", ")}`);
21
+ return lines.join("\n");
22
+ })
23
+ .join("\n");
24
+ }
25
+ /**
26
+ * Apply a decision to the draft and return the writes the entry carries beyond what the draft shows:
27
+ * the review write and any define. Throws a CrubalError for a decision that can't be made.
28
+ */
29
+ export function decide(d, store, defs) {
30
+ const review = { ...d };
31
+ const key = d.key;
32
+ if (key.startsWith("facet:")) {
33
+ const f = defs.dict.facets.get(key.slice(6));
34
+ if (!f)
35
+ throw new CrubalError(`${key}: no such facet`);
36
+ const next = { ...f, values: f.values ? f.values.map((v) => ({ ...v, aliases: [...v.aliases] })) : f.values, aliases: [...f.aliases] };
37
+ if (d.decision === "add value") {
38
+ if (!next.values)
39
+ throw new CrubalError(`${key} isn't a choice`);
40
+ if (next.values.some((v) => v.value === d.value))
41
+ throw new CrubalError(`${d.value} is already a value of ${f.key}`);
42
+ next.values.push({ value: String(d.value), aliases: [] });
43
+ }
44
+ else if (d.decision === "add alias") {
45
+ if (!next.values)
46
+ throw new CrubalError(`${key} isn't a choice`);
47
+ const v = next.values.find((x) => x.value === d.value);
48
+ if (!v)
49
+ throw new CrubalError(`${d.value} is not a value of ${f.key}`);
50
+ v.aliases.push(String(d.alias));
51
+ }
52
+ else if (d.decision !== "reject")
53
+ throw new CrubalError(`${key}: ${d.decision} isn't a decision`);
54
+ if (d.decision === "reject")
55
+ return [{ review }];
56
+ defs.dict.facets.set(f.key, next);
57
+ return [{ review }, { define: facetJson(next) }];
58
+ }
59
+ if (key.startsWith("contract:")) {
60
+ const c = defs.contracts.get(key.slice(9));
61
+ if (!c)
62
+ throw new CrubalError(`${key}: no such contract`);
63
+ const next = { ...c, reads: c.reads.map((m) => ({ ...m, values: [...m.values] })), ignore: [...c.ignore] };
64
+ const field = String(d.field);
65
+ if (d.decision === "map") {
66
+ if (!defs.dict.facets.has(String(d.to)) && !String(d.to).includes(":"))
67
+ throw new CrubalError(`${d.to} isn't a facet`);
68
+ next.reads.push({ from: field, to: String(d.to), values: [], line: c.line, valueLines: [] });
69
+ }
70
+ else if (d.decision === "map value") {
71
+ const m = next.reads.find((x) => x.from === field);
72
+ if (!m)
73
+ throw new CrubalError(`${c.name} doesn't read ${field}`);
74
+ m.values.push([String(d.theirs), String(d.ours)]);
75
+ }
76
+ else if (d.decision === "ignore")
77
+ next.ignore.push(field);
78
+ else
79
+ throw new CrubalError(`${key}: ${d.decision} isn't a decision`);
80
+ defs.contracts.set(c.name, next);
81
+ return [{ review }, { define: contractJson(next) }];
82
+ }
83
+ if (key.startsWith("unit:")) {
84
+ const spelling = key.slice(5);
85
+ const measures = [...(defs.units ?? [])];
86
+ if (d.decision === "alias") {
87
+ const have = measures.find((m) => m.measure === d.unit);
88
+ if (have)
89
+ have.spellings = [...(have.spellings ?? []), spelling];
90
+ else
91
+ measures.push({ measure: String(d.unit), spellings: [spelling] });
92
+ }
93
+ else if (d.decision === "new unit") {
94
+ const m = { measure: String(d.unit), dimension: String(d.dimension), factor: String(d.factor), spellings: [spelling] };
95
+ if (d.offset !== undefined)
96
+ m.offset = String(d.offset);
97
+ measures.push(m);
98
+ }
99
+ else if (d.decision === "not a unit")
100
+ return [{ review }];
101
+ else
102
+ throw new CrubalError(`${key}: ${d.decision} isn't a decision`);
103
+ defs.units = measures;
104
+ extendUnits(unitsExtensionText(measures));
105
+ const writes = [{ review }, { define: { units: "extension", measures } }];
106
+ // The facets that accept the unit from now on (4.2 `accepts`), each a define of its own.
107
+ for (const key of Array.isArray(d.accepts) ? d.accepts : []) {
108
+ const f = defs.dict.facets.get(key);
109
+ if (!f)
110
+ throw new CrubalError(`${key} isn't a facet`);
111
+ if (!f.unit)
112
+ throw new CrubalError(`${key} has no unit to accept ${d.unit} into`);
113
+ const unit = String(d.unit);
114
+ if (f.accepts.includes(unit))
115
+ continue;
116
+ const next = { ...f, accepts: [...f.accepts, unit] };
117
+ defs.dict.facets.set(key, next);
118
+ writes.push({ define: facetJson(next) });
119
+ }
120
+ return writes;
121
+ }
122
+ if (key === "suggestion") {
123
+ const r = store.records.get(String(d.record));
124
+ if (!r)
125
+ throw new CrubalError(`no record ${d.record}`);
126
+ const address = String(d.address);
127
+ const list = r.suggestions?.[address] ?? [];
128
+ const pick = d.value === undefined ? list[0] : list.find((s) => JSON.stringify(s.value) === JSON.stringify(d.value));
129
+ if (!pick)
130
+ throw new CrubalError(`${r.id} has no suggestion at ${address}${d.value !== undefined ? ` with that value` : ""}`);
131
+ const rest = list.filter((s) => s !== pick);
132
+ const suggestions = { ...(r.suggestions ?? {}) };
133
+ if (rest.length)
134
+ suggestions[address] = rest;
135
+ else
136
+ delete suggestions[address];
137
+ const next = { ...r, suggestions };
138
+ if (!Object.keys(suggestions).length)
139
+ delete next.suggestions;
140
+ if (d.decision === "accept") {
141
+ // The value with its original source (14.7).
142
+ const source = { origin: String(pick.origin ?? "reported"), via: String(pick.via ?? "") };
143
+ if (typeof pick.owner === "string")
144
+ source.owner = pick.owner;
145
+ next.values = { ...r.values, [address]: pick.value };
146
+ next.sources = { ...(r.sources ?? {}), [address]: source };
147
+ }
148
+ else if (d.decision !== "deny")
149
+ throw new CrubalError(`suggestion: ${d.decision} isn't a decision`);
150
+ store.records.set(r.id, next);
151
+ return [{ review: { ...review, value: pick.value, ...(d.decision === "deny" ? { denied: true } : {}) } }];
152
+ }
153
+ if (key === "held") {
154
+ const r = store.records.get(String(d.record));
155
+ if (!r)
156
+ throw new CrubalError(`no record ${d.record}`);
157
+ const address = String(d.address);
158
+ const h = r.held?.[address];
159
+ if (!h)
160
+ throw new CrubalError(`${r.id} holds nothing at ${address}`);
161
+ const held = { ...(r.held ?? {}) };
162
+ delete held[address];
163
+ const next = { ...r, held };
164
+ if (!Object.keys(held).length)
165
+ delete next.held;
166
+ if (d.decision === "value") {
167
+ const value = d.value === undefined ? h.value : d.value;
168
+ next.values = { ...r.values, [address]: value };
169
+ next.sources = { ...(r.sources ?? {}), [address]: (isObj(h.source) ? h.source : { origin: "declared", via: "review" }) };
170
+ }
171
+ else if (d.decision !== "drop")
172
+ throw new CrubalError(`held: ${d.decision} isn't a decision`);
173
+ store.records.set(r.id, next);
174
+ return [{ review }];
175
+ }
176
+ if (key.startsWith("split:")) {
177
+ const record = key.slice(6);
178
+ // The decision closes the item it answers: the same record, address and value (openItems).
179
+ if (review.record === undefined)
180
+ review.record = record;
181
+ if (d.decision === "not a version")
182
+ return [{ review }];
183
+ if (d.decision !== "split")
184
+ throw new CrubalError(`${key}: ${d.decision} isn't a decision`);
185
+ const instances = Array.isArray(d.instances) ? d.instances : [];
186
+ const values = typeof d.address === "string" && d.value !== undefined ? { [d.address]: d.value } : {};
187
+ split(store, record, String(d.into), { children: instances, values }, { origin: "observed", via: String(d.via ?? "review") });
188
+ return [{ review }];
189
+ }
190
+ throw new CrubalError(`${key}: not a review item kind a decision applies to here`);
191
+ }
192
+ /** The review items still open: every item without a decision that no later decision names. */
193
+ export function openItems(items) {
194
+ const identity = (it) => JSON.stringify(["key", "record", "address", "run", "ref", "field", "value", "step"].map((k) => it[k] ?? null));
195
+ const decided = new Set(items.filter((it) => it.decision !== undefined).map(identity));
196
+ return items.filter((it) => it.decision === undefined && !decided.has(identity(it)));
197
+ }
198
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { type Expr } from "./conditions.ts";
2
+ import type { Dictionary, Facet } from "./defs.ts";
3
+ import type { Json, JsonObject, Record } from "./model.ts";
4
+ import type { RecordSet } from "./records.ts";
5
+ export type Strength = "must" | "should" | "suggest";
6
+ export type Rule = {
7
+ name: string;
8
+ line: number;
9
+ for: string;
10
+ when: Expr | null;
11
+ whenText: string;
12
+ thenText: string;
13
+ then: Expr | null;
14
+ strength: Strength;
15
+ because?: string;
16
+ version?: string;
17
+ /** A production: `key is <value | template | aggregate>`. */
18
+ produces?: {
19
+ key: string;
20
+ kind: "fill" | "template" | "rollup";
21
+ right: string;
22
+ };
23
+ /** Where it came from when it was expanded from a shortcut. */
24
+ shortcut?: boolean;
25
+ };
26
+ /** Read `rule:` blocks from definition text. */
27
+ export declare function readRules(source: string): Rule[];
28
+ /** The rules a facet's shortcut settings expand to (4.4). */
29
+ export declare function shortcutRules(dict: Dictionary): Rule[];
30
+ /** Check a rule set (6.8). Throws the first problem. */
31
+ export declare function checkRules(rules: Rule[], dict: Dictionary): void;
32
+ export type Result = {
33
+ record: string;
34
+ result: string;
35
+ address?: string;
36
+ value?: Json;
37
+ rule?: string;
38
+ };
39
+ export declare class Engine {
40
+ readonly dict: Dictionary;
41
+ readonly rules: Rule[];
42
+ /** The moment `now` means in conditions; unset means the clock's. */
43
+ now?: string;
44
+ private store;
45
+ private order;
46
+ /** The records a global rule reads (6.6), when the engine runs inside a store; else its own cache. */
47
+ private readonly records?;
48
+ constructor(dict: Dictionary, rules: Rule[], records?: () => RecordSet);
49
+ /** The values a record reads: its own over everything above it (1.7). */
50
+ effective(rec: Record): JsonObject;
51
+ private applies;
52
+ /** Whether any rollup here reads a lower level (`count of unit::…`): then a child's write concerns its ancestors. */
53
+ get readsLowerLevels(): boolean;
54
+ /** The chain up from a record along `of`, nearest first. */
55
+ ancestorsOf(id: string): string[];
56
+ private recordOf;
57
+ /** The records at a lower level under a record, along `of`, merged ones left out. */
58
+ private descendants;
59
+ /**
60
+ * Run the productions again for a record as it stands (6.4: recomputed whenever what it reads changes):
61
+ * what a store calls on the ancestors of a changed record, and on a record a plain write touched.
62
+ */
63
+ reproduce(id: string): Result[];
64
+ /** Where a produced key may be stored: the top of its chain, or a level where it varies. */
65
+ private storesAt;
66
+ private states;
67
+ /** A path a check tests, for reporting. */
68
+ private pathOf;
69
+ /** `is unique` compares records of the same level, and never one archived as merged (6.6). */
70
+ private uniqueClash;
71
+ /** Keep a record as it stands, without running the rules: how a store keeps the engine in step (7.4). */
72
+ put(rec: Record): void;
73
+ /** A record as the engine last left it: its values with what the rules produced, and the keys held. */
74
+ get(id: string): {
75
+ rec: Record;
76
+ produced: Set<string>;
77
+ held: Set<string>;
78
+ } | undefined;
79
+ /**
80
+ * Would this write break a `must` rule on a value it touches (6.2)? Nothing is stored. Intake uses it to
81
+ * park such a value as a contradiction citing the rule (9.3) instead of landing it.
82
+ */
83
+ probe(incoming: Record): Result | null;
84
+ /** Write a record (a create, or values merged onto one already stored). Returns its results. */
85
+ write(incoming: Record): Result[];
86
+ private layered;
87
+ /** A value's plain text in a template: the value itself, never quoted, without detail. */
88
+ private text;
89
+ /** A template (6.4.1): `{a}`, `{a ?? b}`, `{a?}`, `{{`, `}}`. Nothing when a needed value is empty. */
90
+ template(right: string, vals: JsonObject): string | undefined;
91
+ /** A rollup over parts (`worst of parts[*].condition`) or over a lower level (`count of unit::cashierfuId`). */
92
+ rollup(right: string, rec: Record): Json | undefined;
93
+ /** Completeness (6.9): asked facets with a value ÷ asked facets, per record and per part. */
94
+ completeness(rec: Record): Result[];
95
+ }
96
+ export type { Facet };