@cruba/crubal 0.0.0-stage → 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 +202 -0
- package/README.md +69 -2
- package/dist/bin/crubal.d.ts +2 -0
- package/dist/bin/crubal.js +37 -0
- package/dist/bin/crubal.js.map +1 -0
- package/dist/src/browser.d.ts +10 -0
- package/dist/src/browser.js +13 -0
- package/dist/src/browser.js.map +1 -0
- package/dist/src/canonical.d.ts +6 -0
- package/dist/src/canonical.js +47 -0
- package/dist/src/canonical.js.map +1 -0
- package/dist/src/conditions.d.ts +22 -0
- package/dist/src/conditions.js +175 -0
- package/dist/src/conditions.js.map +1 -0
- package/dist/src/corpus.d.ts +8 -0
- package/dist/src/corpus.js +673 -0
- package/dist/src/corpus.js.map +1 -0
- package/dist/src/defs.d.ts +116 -0
- package/dist/src/defs.js +530 -0
- package/dist/src/defs.js.map +1 -0
- package/dist/src/dictionary.d.ts +50 -0
- package/dist/src/dictionary.js +498 -0
- package/dist/src/dictionary.js.map +1 -0
- package/dist/src/exchange.d.ts +45 -0
- package/dist/src/exchange.js +321 -0
- package/dist/src/exchange.js.map +1 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.js +17 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lex.d.ts +21 -0
- package/dist/src/lex.js +142 -0
- package/dist/src/lex.js.map +1 -0
- package/dist/src/migrate.d.ts +88 -0
- package/dist/src/migrate.js +191 -0
- package/dist/src/migrate.js.map +1 -0
- package/dist/src/model.d.ts +36 -0
- package/dist/src/model.js +32 -0
- package/dist/src/model.js.map +1 -0
- package/dist/src/packages.d.ts +25 -0
- package/dist/src/packages.js +98 -0
- package/dist/src/packages.js.map +1 -0
- package/dist/src/print-text.d.ts +7 -0
- package/dist/src/print-text.js +194 -0
- package/dist/src/print-text.js.map +1 -0
- package/dist/src/read-text.d.ts +8 -0
- package/dist/src/read-text.js +317 -0
- package/dist/src/read-text.js.map +1 -0
- package/dist/src/rules.d.ts +64 -0
- package/dist/src/rules.js +486 -0
- package/dist/src/rules.js.map +1 -0
- package/dist/src/store.d.ts +133 -0
- package/dist/src/store.js +396 -0
- package/dist/src/store.js.map +1 -0
- package/dist/src/tree.d.ts +32 -0
- package/dist/src/tree.js +123 -0
- package/dist/src/tree.js.map +1 -0
- package/dist/src/units.d.ts +4 -0
- package/dist/src/units.js +37 -0
- package/dist/src/units.js.map +1 -0
- package/dist/src/views.d.ts +114 -0
- package/dist/src/views.js +436 -0
- package/dist/src/views.js.map +1 -0
- package/package.json +58 -4
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
// store.ts: the Store level (spec chapters 8 and 9). Hash-linked logs (8.5), intake through a receive
|
|
2
|
+
// contract with raw bytes kept (9.1–9.4), landing values by the trust order with alternatives (8.4),
|
|
3
|
+
// matching parts before minting rows (9.2), and evidence validation with independence and vetoes (9.7).
|
|
4
|
+
import { createHash, createPublicKey, verify } from "node:crypto";
|
|
5
|
+
import { serialize } from "./canonical.js";
|
|
6
|
+
import { readClassLine } from "./defs.js";
|
|
7
|
+
import { checkScalar, foldKey, foldValue } from "./dictionary.js";
|
|
8
|
+
import { splitTop } from "./lex.js";
|
|
9
|
+
import { readUnder } from "./read-text.js";
|
|
10
|
+
import { CrubalError, readTree } from "./tree.js";
|
|
11
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
12
|
+
// ─── Logs (8.5) ──────────────────────────────────────────────────────────────
|
|
13
|
+
export function sha256(text) {
|
|
14
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
15
|
+
}
|
|
16
|
+
/** An entry's hash: SHA-256 of its canonical form without `sig`; a redacted entry's hash is what it carries. */
|
|
17
|
+
export function entryHash(entry) {
|
|
18
|
+
if (typeof entry.redacted === "string")
|
|
19
|
+
return entry.redacted.replace(/^sha256:/, "");
|
|
20
|
+
const { sig: _sig, ...rest } = entry;
|
|
21
|
+
return sha256(serialize(rest));
|
|
22
|
+
}
|
|
23
|
+
/** Does `sig` (base64url) verify over the entry's hash bytes with the owner's Ed25519 key? */
|
|
24
|
+
export function verifySig(entry, owner, keys) {
|
|
25
|
+
const k = keys[owner];
|
|
26
|
+
if (!k || k.alg !== "Ed25519" || typeof entry.sig !== "string")
|
|
27
|
+
return false;
|
|
28
|
+
const key = createPublicKey({ key: { kty: "OKP", crv: "Ed25519", x: k.public }, format: "jwk" });
|
|
29
|
+
return verify(null, Buffer.from(entryHash(entry), "hex"), key, Buffer.from(entry.sig, "base64url"));
|
|
30
|
+
}
|
|
31
|
+
/** Check a chain's links, and, when the owner's key is known, every entry's signature (8.5). */
|
|
32
|
+
export function verifyChain(entries, keys) {
|
|
33
|
+
let owner = "";
|
|
34
|
+
for (let i = 0; i < entries.length; i++) {
|
|
35
|
+
const e = entries[i];
|
|
36
|
+
if (i > 0 && e.prev !== `sha256:${entryHash(entries[i - 1])}`)
|
|
37
|
+
return { valid: false, "breaks-at": String(e.log), reason: "link" };
|
|
38
|
+
if (typeof e.owner === "string")
|
|
39
|
+
owner = e.owner;
|
|
40
|
+
if (keys?.[owner] && !verifySig(e, owner, keys))
|
|
41
|
+
return { valid: false, "breaks-at": String(e.log), reason: "signature" };
|
|
42
|
+
}
|
|
43
|
+
return { valid: true };
|
|
44
|
+
}
|
|
45
|
+
function readMap(lines) {
|
|
46
|
+
return lines.map((l) => {
|
|
47
|
+
const [from, to] = splitArrow(l.text, l.line);
|
|
48
|
+
const values = l.children.map((c) => splitArrow(c.text, c.line).map(unq));
|
|
49
|
+
return { from, to, values, line: l.line, valueLines: l.children.map((c) => c.line) };
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function splitArrow(text, line) {
|
|
53
|
+
const at = text.indexOf(" -> ");
|
|
54
|
+
if (at < 0)
|
|
55
|
+
throw new CrubalError(`a map line is "from -> to": ${text}`, line);
|
|
56
|
+
return [text.slice(0, at).trim(), text.slice(at + 4).trim()];
|
|
57
|
+
}
|
|
58
|
+
const unq = (s) => (s.startsWith('"') ? JSON.parse(s) : s);
|
|
59
|
+
/** Read `contract:` blocks. */
|
|
60
|
+
export function readContracts(source) {
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const node of readTree(source)) {
|
|
63
|
+
if (node.kind !== "pair" || node.key !== "contract")
|
|
64
|
+
continue;
|
|
65
|
+
const c = {
|
|
66
|
+
name: node.value.trim(),
|
|
67
|
+
kind: "receive",
|
|
68
|
+
origin: "",
|
|
69
|
+
reads: [],
|
|
70
|
+
writes: [],
|
|
71
|
+
ignore: [],
|
|
72
|
+
keepRaw: [],
|
|
73
|
+
absorb: true,
|
|
74
|
+
lands: "value",
|
|
75
|
+
line: node.line,
|
|
76
|
+
needs: [],
|
|
77
|
+
gives: [],
|
|
78
|
+
parts: {},
|
|
79
|
+
partLines: {},
|
|
80
|
+
};
|
|
81
|
+
for (const p of node.children) {
|
|
82
|
+
if (!p.key)
|
|
83
|
+
continue;
|
|
84
|
+
c.partLines[p.key] = p.line;
|
|
85
|
+
const list = () => splitTop(p.value, ",", p.line).filter(Boolean);
|
|
86
|
+
if (p.key === "needs") {
|
|
87
|
+
c.needs = p.value ? splitTop(p.value, ",", p.line).map((t) => readClassLine(t, p.line)) : p.children.map((l) => readClassLine(l.text, l.line));
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (p.key === "gives")
|
|
91
|
+
c.gives = list();
|
|
92
|
+
else if (p.key === "who")
|
|
93
|
+
c.who = p.value;
|
|
94
|
+
else if (p.key === "when")
|
|
95
|
+
c.when = p.value;
|
|
96
|
+
else if (p.key === "from")
|
|
97
|
+
c.from = p.value;
|
|
98
|
+
else if (p.key === "to")
|
|
99
|
+
c.to = p.value;
|
|
100
|
+
else if (p.key === "mode")
|
|
101
|
+
c.mode = p.value;
|
|
102
|
+
else if (p.key === "undo")
|
|
103
|
+
c.undo = p.value;
|
|
104
|
+
if (p.key === "kind")
|
|
105
|
+
c.kind = p.value;
|
|
106
|
+
else if (p.key === "origin")
|
|
107
|
+
c.origin = p.value;
|
|
108
|
+
else if (p.key === "prefix")
|
|
109
|
+
c.prefix = p.value;
|
|
110
|
+
else if (p.key === "reads")
|
|
111
|
+
c.reads = readMap(p.children);
|
|
112
|
+
else if (p.key === "writes")
|
|
113
|
+
c.writes = readMap(p.children);
|
|
114
|
+
else if (p.key === "ignore")
|
|
115
|
+
c.ignore = list();
|
|
116
|
+
else if (p.key === "keep-raw")
|
|
117
|
+
c.keepRaw = list();
|
|
118
|
+
else if (p.key === "absorb")
|
|
119
|
+
c.absorb = p.value !== "no";
|
|
120
|
+
else if (p.key === "lands")
|
|
121
|
+
c.lands = p.value;
|
|
122
|
+
if (!["kind", "origin", "prefix", "reads", "writes", "ignore", "keep-raw", "absorb", "lands", "gives", "who", "when", "from", "to", "mode", "undo"].includes(p.key))
|
|
123
|
+
c.parts[p.key] = p.value;
|
|
124
|
+
}
|
|
125
|
+
if (!c.origin)
|
|
126
|
+
c.origin = c.kind === "form" ? "declared" : "reported";
|
|
127
|
+
if (c.keepRaw.length && !c.prefix)
|
|
128
|
+
throw new CrubalError(`${c.name} keeps raw fields, so it needs a prefix`, c.line);
|
|
129
|
+
out.push(c);
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
/** Split a field path into names: `aspects."Run Time"` → ["aspects", "Run Time"]. */
|
|
134
|
+
export function fieldPath(path) {
|
|
135
|
+
const out = [];
|
|
136
|
+
let cur = "";
|
|
137
|
+
let quoted = false;
|
|
138
|
+
for (let i = 0; i < path.length; i++) {
|
|
139
|
+
const ch = path[i];
|
|
140
|
+
if (ch === '"') {
|
|
141
|
+
quoted = !quoted;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (ch === "." && !quoted) {
|
|
145
|
+
out.push(cur);
|
|
146
|
+
cur = "";
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
cur += ch;
|
|
150
|
+
}
|
|
151
|
+
out.push(cur);
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
/** Write a payload's field name as a path segment, quoted when it isn't a plain name. */
|
|
155
|
+
function segment(name) {
|
|
156
|
+
return /^[A-Za-z_]\w*$/.test(name) ? name : JSON.stringify(name);
|
|
157
|
+
}
|
|
158
|
+
function leaves(obj, prefix = "") {
|
|
159
|
+
if (!isObj(obj))
|
|
160
|
+
return [[prefix, obj]];
|
|
161
|
+
return Object.entries(obj).flatMap(([k, v]) => {
|
|
162
|
+
const p = prefix ? `${prefix}.${segment(k)}` : segment(k);
|
|
163
|
+
return isObj(v) ? leaves(v, p) : [[p, v]];
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function samePath(a, b) {
|
|
167
|
+
return serialize(fieldPath(a)) === serialize(fieldPath(b));
|
|
168
|
+
}
|
|
169
|
+
/** Fold one raw value through the map's value map, the aliases and the shapes, then check it (9.2). */
|
|
170
|
+
function foldIn(f, raw, map, dict) {
|
|
171
|
+
let text = typeof raw === "string" ? raw : serialize(raw);
|
|
172
|
+
const vm = map?.values.find(([theirs]) => theirs === text);
|
|
173
|
+
if (vm)
|
|
174
|
+
text = vm[1];
|
|
175
|
+
const read = readUnder(f, text, dict) ?? text;
|
|
176
|
+
const value = foldValue(f, read, dict);
|
|
177
|
+
const items = Array.isArray(value) ? value : [value];
|
|
178
|
+
const checks = items.map((i) => checkScalar(f, i).outcome);
|
|
179
|
+
const outcome = checks.includes("contradiction") ? "contradiction" : checks.includes("new") ? "new" : "absorbed";
|
|
180
|
+
return { value, outcome };
|
|
181
|
+
}
|
|
182
|
+
/** Keep a payload's exact bytes (3.8): as text when they are valid UTF-8, otherwise as base64. */
|
|
183
|
+
export function rawOf(bytes, type) {
|
|
184
|
+
const hash = createHash("sha256").update(bytes).digest("hex");
|
|
185
|
+
try {
|
|
186
|
+
return { type, sha256: hash, body: new TextDecoder("utf-8", { fatal: true }).decode(bytes) };
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return { type, sha256: hash, base64: Buffer.from(bytes).toString("base64") };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Replay an intake record from its kept bytes under the current contract (9.6); earlier outcomes stay. */
|
|
193
|
+
export function replay(intake, c, dict) {
|
|
194
|
+
const again = receive(c, intake.raw.body, intake.for, dict, intake.intake);
|
|
195
|
+
const replays = [...(intake.replays ?? []), { outcomes: again.outcomes, contract: c.name }];
|
|
196
|
+
return { ...intake, replays };
|
|
197
|
+
}
|
|
198
|
+
/** Review by key across every intake record (9.5), and candidate facets proposed by recurrence. */
|
|
199
|
+
export function reviewByKey(intakes, recur = 5) {
|
|
200
|
+
const groups = new Map();
|
|
201
|
+
for (const i of intakes) {
|
|
202
|
+
for (const o of i.outcomes) {
|
|
203
|
+
if (o.outcome !== "unknown" && o.outcome !== "new")
|
|
204
|
+
continue;
|
|
205
|
+
const key = o.to ?? o.from;
|
|
206
|
+
const g = groups.get(key) ?? { objects: new Set(), values: new Set(), outcome: o.outcome };
|
|
207
|
+
g.objects.add(i.for);
|
|
208
|
+
if (o.value !== undefined)
|
|
209
|
+
g.values.add(serialize(o.value));
|
|
210
|
+
groups.set(key, g);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const rows = [...groups.entries()].sort((a, b) => b[1].objects.size - a[1].objects.size || a[0].localeCompare(b[0]));
|
|
214
|
+
return {
|
|
215
|
+
"by-key": rows.map(([key, g]) => ({ key, objects: g.objects.size, values: g.values.size, outcome: g.outcome })),
|
|
216
|
+
// Only keys no facet holds become candidate facets; a facet's new values go to vocabulary review.
|
|
217
|
+
proposals: rows.filter(([, g]) => g.outcome === "unknown" && g.objects.size >= recur).map(([key, g]) => ({ key, objects: g.objects.size, state: "candidate" })),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/** Receive a raw payload through a contract: every field gets exactly one outcome. The bytes are kept. */
|
|
221
|
+
export function receive(c, body, forRecord, dict, intakeId = "I-1") {
|
|
222
|
+
const payload = JSON.parse(body);
|
|
223
|
+
const outcomes = [];
|
|
224
|
+
for (const [path, raw] of leaves(payload)) {
|
|
225
|
+
if (!c.absorb || c.ignore.some((i) => samePath(i, path))) {
|
|
226
|
+
outcomes.push({ from: path, outcome: "ignored" });
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const map = c.reads.find((m) => samePath(m.from, path));
|
|
230
|
+
if (map) {
|
|
231
|
+
const f = dict.facets.get(map.to);
|
|
232
|
+
if (!f) {
|
|
233
|
+
outcomes.push({ from: path, to: map.to, outcome: "unknown", value: raw });
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const { value, outcome } = foldIn(f, raw, map, dict);
|
|
237
|
+
outcomes.push({ from: path, to: map.to, outcome, value, ...(outcome === "contradiction" ? { cites: { type: f.key } } : {}) });
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (c.keepRaw.some((k) => samePath(k, path))) {
|
|
241
|
+
const name = fieldPath(path).at(-1);
|
|
242
|
+
if (!/^[A-Za-z_]\w*$/.test(name))
|
|
243
|
+
throw new CrubalError(`the raw field ${path} needs a map line: ${name} isn't a key name`, c.line);
|
|
244
|
+
outcomes.push({ from: path, to: `${c.prefix}:${name}`, outcome: "unknown", value: raw });
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
outcomes.push({ from: path, outcome: "unknown" });
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
intake: intakeId,
|
|
251
|
+
contract: c.name,
|
|
252
|
+
for: forRecord,
|
|
253
|
+
raw: { type: "application/json", sha256: sha256(body), body },
|
|
254
|
+
outcomes,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
// ─── Landing values: trust and alternatives (8.4, 9.3) ───────────────────────
|
|
258
|
+
const DEFAULT_TRUST = ["person", "observed", "declared", "reported", "derived"];
|
|
259
|
+
function matchAt(who, order) {
|
|
260
|
+
const hits = [who.person ? "person" : "", who.contract ?? "", who.source.owner ?? "", who.source.origin].filter(Boolean);
|
|
261
|
+
const at = order.findIndex((e) => hits.includes(e));
|
|
262
|
+
return at;
|
|
263
|
+
}
|
|
264
|
+
/** A source's rank under a facet's order then the package's (lower wins). */
|
|
265
|
+
function rank(who, trust, facetOrder = []) {
|
|
266
|
+
const f = matchAt(who, facetOrder);
|
|
267
|
+
if (f >= 0)
|
|
268
|
+
return f;
|
|
269
|
+
const p = matchAt(who, trust);
|
|
270
|
+
return facetOrder.length + (p >= 0 ? p : trust.length);
|
|
271
|
+
}
|
|
272
|
+
function sourceAt(r, address) {
|
|
273
|
+
return r.sources?.[address] ?? r.sources?.["*"];
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Land an intake record's outcomes on a record. Absorbed and conflicting values go through the trust
|
|
277
|
+
* order: the winner is current, the loser is kept as an alternative. Equal values are agreement.
|
|
278
|
+
*/
|
|
279
|
+
export function land(r, intake, source, trust = DEFAULT_TRUST, facetTrust = new Map()) {
|
|
280
|
+
const order = trust.length ? trust : DEFAULT_TRUST;
|
|
281
|
+
const incoming = { source, ...(intake.contract ? { contract: intake.contract } : {}) };
|
|
282
|
+
const out = {
|
|
283
|
+
...r,
|
|
284
|
+
values: { ...r.values },
|
|
285
|
+
sources: { ...(r.sources ?? {}) },
|
|
286
|
+
};
|
|
287
|
+
for (const o of intake.outcomes) {
|
|
288
|
+
if (!o.to || o.value === undefined || !["absorbed", "conflict", "new"].includes(o.outcome))
|
|
289
|
+
continue;
|
|
290
|
+
const current = out.values[o.to];
|
|
291
|
+
if (current === undefined || (isObj(current) && current.$empty === "unknown")) {
|
|
292
|
+
out.values[o.to] = o.value;
|
|
293
|
+
out.sources[o.to] = source;
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (serialize(current) === serialize(o.value))
|
|
297
|
+
continue; // agreement: the current source stays
|
|
298
|
+
const was = sourceAt(out, o.to);
|
|
299
|
+
const fo = facetTrust.get(o.to) ?? [];
|
|
300
|
+
const incomingWins = rank(incoming, order, fo) < rank({ source: was }, order, fo);
|
|
301
|
+
const loser = incomingWins ? { value: current, origin: was.origin, via: was.via } : { value: o.value, origin: source.origin, via: source.via };
|
|
302
|
+
if (incomingWins) {
|
|
303
|
+
out.values[o.to] = o.value;
|
|
304
|
+
out.sources[o.to] = source;
|
|
305
|
+
}
|
|
306
|
+
out.alternatives = { ...(out.alternatives ?? {}) };
|
|
307
|
+
out.alternatives[o.to] = [...(out.alternatives[o.to] ?? []), loser];
|
|
308
|
+
}
|
|
309
|
+
return out;
|
|
310
|
+
}
|
|
311
|
+
/** Bind incoming parts to existing ones: by the slot's match child, else review, else a new row. */
|
|
312
|
+
export function matchParts(r, incoming, dict) {
|
|
313
|
+
const slots = (r.wears ?? []).flatMap((w) => dict.classes.get(w)?.parts ?? []);
|
|
314
|
+
const existing = (r.parts ?? []).filter(isObj).map((p) => ({ p, matched: false }));
|
|
315
|
+
const result = new Map(existing.map(({ p }) => [String(p.$row), { $row: p.$row }]));
|
|
316
|
+
const review = [];
|
|
317
|
+
const minted = [];
|
|
318
|
+
const keys = existing.map(({ p }) => String(p.$row));
|
|
319
|
+
const mint = () => {
|
|
320
|
+
const m = keys.map((k) => k.match(/^(\D+)(\d+)$/)).find(Boolean);
|
|
321
|
+
const prefix = m?.[1] ?? "r";
|
|
322
|
+
let n = Math.max(0, ...keys.map((k) => Number(k.match(/(\d+)$/)?.[1] ?? 0))) + 1;
|
|
323
|
+
while (keys.includes(`${prefix}${n}`))
|
|
324
|
+
n++;
|
|
325
|
+
keys.push(`${prefix}${n}`);
|
|
326
|
+
return `${prefix}${n}`;
|
|
327
|
+
};
|
|
328
|
+
for (const inc of incoming) {
|
|
329
|
+
const slot = slots.find((s) => s.slot === inc.slot);
|
|
330
|
+
const inSlot = existing.filter(({ p }) => Array.isArray(p.wears) && slot && p.wears.includes(slot.wears));
|
|
331
|
+
const by = slot?.match;
|
|
332
|
+
const want = by && typeof inc[by] === "string" ? foldKey(inc[by]) : null;
|
|
333
|
+
const hit = want ? inSlot.find(({ p, matched }) => !matched && isObj(p.values) && foldKey(String(p.values[by] ?? "")) === want) : undefined;
|
|
334
|
+
const label = String(by ? inc[by] : inc.slot);
|
|
335
|
+
if (hit) {
|
|
336
|
+
hit.matched = true;
|
|
337
|
+
result.set(String(hit.p.$row), { $row: hit.p.$row, matched: by, from: label });
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
const could = inSlot.filter((x) => !x.matched);
|
|
341
|
+
if (could.length) {
|
|
342
|
+
const names = could.map(({ p }) => String(p.$row)).join(", ");
|
|
343
|
+
review.push({ address: "parts", from: label, reason: `could be the same part as ${names} (${inc.slot}); not matched by ${by ?? "identity"}` });
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
minted.push({ $row: mint(), new: true, from: label });
|
|
347
|
+
}
|
|
348
|
+
return { parts: [...result.values(), ...minted], review };
|
|
349
|
+
}
|
|
350
|
+
/** Validate a value from observations: independent witnesses for and against, vetoes, and the state. */
|
|
351
|
+
export function validate(r, address, observations, confirmAt = 2, splitAt = 3) {
|
|
352
|
+
const current = serialize(r.values[address] ?? "");
|
|
353
|
+
const mine = observations.filter((o) => o.supports === r.id && o.address === address);
|
|
354
|
+
const witness = (o) => `${o.on}|${o["evidence-type"] ?? ""}`;
|
|
355
|
+
const forW = new Set();
|
|
356
|
+
const againstW = new Set();
|
|
357
|
+
const vetoes = [];
|
|
358
|
+
const against = new Map();
|
|
359
|
+
for (const o of mine) {
|
|
360
|
+
if (o.veto !== undefined) {
|
|
361
|
+
if (serialize(o.veto) === current)
|
|
362
|
+
vetoes.push(o);
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
if (serialize(o.value) === current)
|
|
366
|
+
forW.add(witness(o));
|
|
367
|
+
else {
|
|
368
|
+
againstW.add(witness(o));
|
|
369
|
+
const k = serialize(o.value);
|
|
370
|
+
const g = against.get(k) ?? { value: o.value, instances: new Set() };
|
|
371
|
+
g.instances.add(o.on);
|
|
372
|
+
against.set(k, g);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const out = {
|
|
376
|
+
record: r.id,
|
|
377
|
+
address,
|
|
378
|
+
"witnesses-for": forW.size,
|
|
379
|
+
"witnesses-against": againstW.size,
|
|
380
|
+
vetoes: vetoes.length,
|
|
381
|
+
};
|
|
382
|
+
if (vetoes.length) {
|
|
383
|
+
out.state = "contradicted";
|
|
384
|
+
out.cites = { veto: vetoes[0].obs };
|
|
385
|
+
}
|
|
386
|
+
else if (againstW.size)
|
|
387
|
+
out.state = "contradicted";
|
|
388
|
+
else if (forW.size >= confirmAt)
|
|
389
|
+
out.state = "confirmed";
|
|
390
|
+
else
|
|
391
|
+
out.state = "unobserved";
|
|
392
|
+
out.alternatives = [...against.values()].map((g) => ({ value: g.value, origin: "observed" }));
|
|
393
|
+
out["split-proposed"] = [...against.values()].some((g) => g.instances.size >= splitAt);
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare class CrubalError extends Error {
|
|
2
|
+
readonly line: number | undefined;
|
|
3
|
+
constructor(message: string, line?: number);
|
|
4
|
+
}
|
|
5
|
+
export type Node = {
|
|
6
|
+
/** "pair" is `key: value` or `key:`; "item" is a `- ` list item; "line" is anything else. */
|
|
7
|
+
kind: "pair" | "item" | "line";
|
|
8
|
+
/** The key of a pair; null otherwise. */
|
|
9
|
+
key: string | null;
|
|
10
|
+
/** The text after the separator (pair), after `- ` (item, when it isn't a pair), or the whole line. */
|
|
11
|
+
value: string;
|
|
12
|
+
/** The line's whole text, comment and indentation removed. */
|
|
13
|
+
text: string;
|
|
14
|
+
line: number;
|
|
15
|
+
/** The column the line's text starts at. */
|
|
16
|
+
indent: number;
|
|
17
|
+
children: Node[];
|
|
18
|
+
};
|
|
19
|
+
/** Remove a `//` comment that starts the line or follows white space, outside quotes. */
|
|
20
|
+
export declare function stripComment(line: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Split a line into a pair at the separator (spec 2.1): the first `: ` (colon then space), or a colon at
|
|
23
|
+
* the end of the line. A colon inside quotes never separates.
|
|
24
|
+
*/
|
|
25
|
+
export declare function splitPair(text: string): {
|
|
26
|
+
key: string;
|
|
27
|
+
value: string;
|
|
28
|
+
} | null;
|
|
29
|
+
/** The lines inside a node, as written: each with its indentation relative to the first, comments removed. */
|
|
30
|
+
export declare function innerText(node: Node): string;
|
|
31
|
+
/** Read text into a tree of nodes. */
|
|
32
|
+
export declare function readTree(source: string): Node[];
|
package/dist/src/tree.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// tree.ts: the text form's lines (spec chapter 2.1), read into a tree of nodes without knowing what any
|
|
2
|
+
// key means. Comments are stripped, tabs in indentation are refused, and a line belongs inside the nearest
|
|
3
|
+
// earlier line that is indented less.
|
|
4
|
+
export class CrubalError extends Error {
|
|
5
|
+
line;
|
|
6
|
+
constructor(message, line) {
|
|
7
|
+
super(line ? `line ${line}: ${message}` : message);
|
|
8
|
+
this.name = "CrubalError";
|
|
9
|
+
this.line = line;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Remove a `//` comment that starts the line or follows white space, outside quotes. */
|
|
13
|
+
export function stripComment(line) {
|
|
14
|
+
let quoted = false;
|
|
15
|
+
for (let i = 0; i < line.length; i++) {
|
|
16
|
+
const ch = line[i];
|
|
17
|
+
if (quoted && ch === "\\") {
|
|
18
|
+
i++;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (ch === '"')
|
|
22
|
+
quoted = !quoted;
|
|
23
|
+
if (!quoted && ch === "/" && line[i + 1] === "/" && (i === 0 || /\s/.test(line[i - 1] ?? ""))) {
|
|
24
|
+
return line.slice(0, i).trimEnd();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return line.trimEnd();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Split a line into a pair at the separator (spec 2.1): the first `: ` (colon then space), or a colon at
|
|
31
|
+
* the end of the line. A colon inside quotes never separates.
|
|
32
|
+
*/
|
|
33
|
+
export function splitPair(text) {
|
|
34
|
+
let quoted = false;
|
|
35
|
+
for (let i = 0; i < text.length; i++) {
|
|
36
|
+
const ch = text[i];
|
|
37
|
+
if (quoted && ch === "\\") {
|
|
38
|
+
i++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (ch === '"')
|
|
42
|
+
quoted = !quoted;
|
|
43
|
+
if (quoted || ch !== ":")
|
|
44
|
+
continue;
|
|
45
|
+
if (i === text.length - 1)
|
|
46
|
+
return i > 0 ? { key: text.slice(0, i), value: "" } : null;
|
|
47
|
+
if (text[i + 1] === " ") {
|
|
48
|
+
const key = text.slice(0, i);
|
|
49
|
+
if (!key || /\s/.test(key))
|
|
50
|
+
return null;
|
|
51
|
+
return { key, value: text.slice(i + 2).trim() };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function lineNode(body, line, indent) {
|
|
57
|
+
const pair = splitPair(body);
|
|
58
|
+
if (pair)
|
|
59
|
+
return { kind: "pair", key: pair.key, value: pair.value, text: body, line, indent, children: [] };
|
|
60
|
+
return { kind: "line", key: null, value: body, text: body, line, indent, children: [] };
|
|
61
|
+
}
|
|
62
|
+
/** The lines inside a node, as written: each with its indentation relative to the first, comments removed. */
|
|
63
|
+
export function innerText(node) {
|
|
64
|
+
const lines = [];
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
const walk = (n) => {
|
|
67
|
+
for (const c of n.children) {
|
|
68
|
+
if (!seen.has(c.line)) {
|
|
69
|
+
seen.add(c.line);
|
|
70
|
+
lines.push({ indent: c.indent, text: c.text, line: c.line });
|
|
71
|
+
}
|
|
72
|
+
walk(c);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
walk(node);
|
|
76
|
+
lines.sort((a, b) => a.line - b.line);
|
|
77
|
+
const base = lines[0]?.indent ?? 0;
|
|
78
|
+
return lines.map((l) => " ".repeat(Math.max(0, l.indent - base)) + l.text).join("\n");
|
|
79
|
+
}
|
|
80
|
+
/** Read text into a tree of nodes. */
|
|
81
|
+
export function readTree(source) {
|
|
82
|
+
const root = { kind: "line", key: null, value: "", text: "", line: 0, indent: -1, children: [] };
|
|
83
|
+
const stack = [{ node: root, indent: -1 }];
|
|
84
|
+
const lines = source.replace(/^/, "").split(/\r?\n/);
|
|
85
|
+
lines.forEach((raw, i) => {
|
|
86
|
+
const line = i + 1;
|
|
87
|
+
if (/^ *\t/.test(raw))
|
|
88
|
+
throw new CrubalError("indent with spaces, not tabs", line);
|
|
89
|
+
const stripped = stripComment(raw);
|
|
90
|
+
if (!stripped.trim())
|
|
91
|
+
return;
|
|
92
|
+
let indent = stripped.length - stripped.trimStart().length;
|
|
93
|
+
let body = stripped.trim();
|
|
94
|
+
while (stack.length > 1 && (stack.at(-1)?.indent ?? -1) >= indent)
|
|
95
|
+
stack.pop();
|
|
96
|
+
const parent = stack.at(-1)?.node ?? root;
|
|
97
|
+
if (body === "-" || body.startsWith("- ")) {
|
|
98
|
+
const item = { kind: "item", key: null, value: "", text: body, line, indent, children: [] };
|
|
99
|
+
parent.children.push(item);
|
|
100
|
+
stack.push({ node: item, indent });
|
|
101
|
+
const rest = body.slice(1).trimStart();
|
|
102
|
+
if (!rest)
|
|
103
|
+
return;
|
|
104
|
+
// The item's own text: a pair starts the item's first child, so lines indented to its column join
|
|
105
|
+
// the same item; anything else is the item's value.
|
|
106
|
+
indent += stripped.trimStart().indexOf(rest, 1);
|
|
107
|
+
body = rest;
|
|
108
|
+
const first = lineNode(body, line, indent);
|
|
109
|
+
if (first.kind === "line" || body.startsWith("[")) {
|
|
110
|
+
item.value = body;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
item.children.push(first);
|
|
114
|
+
stack.push({ node: first, indent });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const node = lineNode(body, line, indent);
|
|
118
|
+
parent.children.push(node);
|
|
119
|
+
stack.push({ node, indent });
|
|
120
|
+
});
|
|
121
|
+
return root.children;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The real unit a spelling names, or null. */
|
|
2
|
+
export declare function unitOf(spelling: string): string | null;
|
|
3
|
+
/** Convert an amount between units of one dimension, rounded to `places` (default: up to 6). */
|
|
4
|
+
export declare function convert(amount: string, from: string, to: string, places?: number): string | null;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// units.ts: a starter units table, standing in for the standard units package (spec chapter 11.1,
|
|
2
|
+
// `crubal.com/units`) until it is published. Each unit has a dimension and a factor to the dimension's base.
|
|
3
|
+
const TABLE = {
|
|
4
|
+
s: { dimension: "time", factor: 1, spellings: ["sec", "secs", "second", "seconds"] },
|
|
5
|
+
min: { dimension: "time", factor: 60, spellings: ["MIN.", "mins", "minute", "minutes"] },
|
|
6
|
+
h: { dimension: "time", factor: 3600, spellings: ["hr", "hrs", "hour", "hours"] },
|
|
7
|
+
mm: { dimension: "length", factor: 0.001, spellings: [] },
|
|
8
|
+
cm: { dimension: "length", factor: 0.01, spellings: [] },
|
|
9
|
+
m: { dimension: "length", factor: 1, spellings: [] },
|
|
10
|
+
in: { dimension: "length", factor: 0.0254, spellings: ["inch", "inches", '"'] },
|
|
11
|
+
ft: { dimension: "length", factor: 0.3048, spellings: ["foot", "feet"] },
|
|
12
|
+
g: { dimension: "mass", factor: 0.001, spellings: [] },
|
|
13
|
+
kg: { dimension: "mass", factor: 1, spellings: [] },
|
|
14
|
+
oz: { dimension: "mass", factor: 0.028349523125, spellings: [] },
|
|
15
|
+
lb: { dimension: "mass", factor: 0.45359237, spellings: ["lbs", "pound", "pounds"] },
|
|
16
|
+
};
|
|
17
|
+
/** The real unit a spelling names, or null. */
|
|
18
|
+
export function unitOf(spelling) {
|
|
19
|
+
if (TABLE[spelling])
|
|
20
|
+
return spelling;
|
|
21
|
+
const lower = spelling.toLowerCase();
|
|
22
|
+
for (const [u, def] of Object.entries(TABLE))
|
|
23
|
+
if (def.spellings.some((s) => s.toLowerCase() === lower))
|
|
24
|
+
return u;
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
/** Convert an amount between units of one dimension, rounded to `places` (default: up to 6). */
|
|
28
|
+
export function convert(amount, from, to, places) {
|
|
29
|
+
const a = TABLE[from];
|
|
30
|
+
const b = TABLE[to];
|
|
31
|
+
if (!a || !b || a.dimension !== b.dimension)
|
|
32
|
+
return null;
|
|
33
|
+
const v = (Number(amount) * a.factor) / b.factor;
|
|
34
|
+
const fixed = v.toFixed(places ?? 6);
|
|
35
|
+
return places === undefined ? String(Number(fixed)) : fixed;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=units.js.map
|