@fuaran-ui/ops 0.21.0 → 0.23.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/dist/index.cjs +1114 -141
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +209 -6
- package/dist/index.d.ts +209 -6
- package/dist/index.js +1102 -143
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FORM_FIELD_KIND_NAMES, NODE_KIND_GROUPS, defaults, controlValueDefaults, MAX_NODE_DEPTH, MAX_NODES,
|
|
1
|
+
import { FORM_FIELD_KIND_NAMES, NODE_KIND_GROUPS, defaults, controlValueDefaults, MAX_DOCUMENT_BYTES, MAX_NODE_DEPTH, MAX_NODES, MAX_JSON_DEPTH, MAX_ARRAY_LENGTH, MAX_STRING_LENGTH, narrows, admitAll, NODE_KIND_NAMES, admits, policyHint, MAX_EXPR_NODES, projectSelectionField } from '@fuaran-ui/schema';
|
|
2
2
|
|
|
3
3
|
// src/encode.ts
|
|
4
4
|
var assertNever = (x) => {
|
|
@@ -384,9 +384,12 @@ var binding = (b, staticEnc = objValue) => {
|
|
|
384
384
|
}
|
|
385
385
|
case "Computed":
|
|
386
386
|
return caseObj("Computed", [["fn", CLOSURE]]);
|
|
387
|
-
//
|
|
387
|
+
// Phase 765 — the INSTANT is never on the wire: it is host-furnished at
|
|
388
|
+
// resolve time. Phase 1533 — the declared GRAIN is, and only when it is not
|
|
389
|
+
// the `Second` default, so a grain-less `Now` is the same bytes it has
|
|
390
|
+
// always been.
|
|
388
391
|
case "Now":
|
|
389
|
-
return caseObj("Now", []);
|
|
392
|
+
return caseObj("Now", b.grain !== void 0 ? [["grain", str(b.grain)]] : []);
|
|
390
393
|
case "I18n": {
|
|
391
394
|
const fields = [];
|
|
392
395
|
if (b.args !== void 0) {
|
|
@@ -398,14 +401,18 @@ var binding = (b, staticEnc = objValue) => {
|
|
|
398
401
|
fields.push(["key", str(b.key)]);
|
|
399
402
|
return caseObj("I18n", fields);
|
|
400
403
|
}
|
|
401
|
-
case "Local":
|
|
402
|
-
|
|
404
|
+
case "Local": {
|
|
405
|
+
const localFields = [
|
|
403
406
|
["flushOn", flushTrigger(b.local.flushOn)],
|
|
404
407
|
["format", CLOSURE],
|
|
405
408
|
["initialFrom", binding(b.local.initialFrom, staticEnc)],
|
|
406
|
-
["onCommit", CLOSURE],
|
|
407
409
|
["parse", CLOSURE]
|
|
408
|
-
]
|
|
410
|
+
];
|
|
411
|
+
if (b.local.codec !== void 0) localFields.push(["codec", formatIntent(b.local.codec)]);
|
|
412
|
+
if (b.local.commitTo !== void 0) localFields.push(["commitTo", str(b.local.commitTo)]);
|
|
413
|
+
if (b.local.onCommit !== void 0) localFields.push(["onCommit", CLOSURE]);
|
|
414
|
+
return caseObj("Local", localFields);
|
|
415
|
+
}
|
|
409
416
|
case "Format":
|
|
410
417
|
return caseObj("Format", [
|
|
411
418
|
["format", formatIntent(b.format)],
|
|
@@ -435,6 +442,22 @@ var binding = (b, staticEnc = objValue) => {
|
|
|
435
442
|
]
|
|
436
443
|
]);
|
|
437
444
|
}
|
|
445
|
+
case "Expr": {
|
|
446
|
+
const exprParams = b.params !== void 0 && b.params.length > 0 ? [
|
|
447
|
+
[
|
|
448
|
+
"params",
|
|
449
|
+
jArray(
|
|
450
|
+
b.params.map(
|
|
451
|
+
(p) => jObject([
|
|
452
|
+
["from", binding(p.from)],
|
|
453
|
+
["name", str(p.name)]
|
|
454
|
+
])
|
|
455
|
+
)
|
|
456
|
+
)
|
|
457
|
+
]
|
|
458
|
+
] : [];
|
|
459
|
+
return caseObj("Expr", [["expr", colExpr(b.expr)], ...exprParams]);
|
|
460
|
+
}
|
|
438
461
|
case "Invoke":
|
|
439
462
|
return caseObj("Invoke", [
|
|
440
463
|
["args", invokeArgs(b.args)],
|
|
@@ -464,8 +487,11 @@ var action = (a) => {
|
|
|
464
487
|
["channel", str(a.channel)],
|
|
465
488
|
["payload", jsonValue(a.payload)]
|
|
466
489
|
]);
|
|
467
|
-
case "Navigate":
|
|
468
|
-
|
|
490
|
+
case "Navigate": {
|
|
491
|
+
const fields = [["route", textSource(a.route)]];
|
|
492
|
+
if (a.target !== "Self") fields.push(["target", str(a.target)]);
|
|
493
|
+
return caseObj("Navigate", fields);
|
|
494
|
+
}
|
|
469
495
|
case "SetState": {
|
|
470
496
|
const fields = [["key", str(a.key)]];
|
|
471
497
|
if (a.value !== void 0) fields.push(["value", jsonValue(a.value)]);
|
|
@@ -485,6 +511,15 @@ var action = (a) => {
|
|
|
485
511
|
return caseObj("WriteToClipboard", [["text", textSource(a.text)]]);
|
|
486
512
|
case "Print":
|
|
487
513
|
return caseObj("Print", []);
|
|
514
|
+
case "Confirm": {
|
|
515
|
+
const fields = [];
|
|
516
|
+
if (a.onCancel !== void 0) fields.push(["onCancel", action(a.onCancel)]);
|
|
517
|
+
fields.push(["onConfirm", action(a.onConfirm)]);
|
|
518
|
+
fields.push(["prompt", textSource(a.prompt)]);
|
|
519
|
+
return caseObj("Confirm", fields);
|
|
520
|
+
}
|
|
521
|
+
case "Focus":
|
|
522
|
+
return caseObj("Focus", [["nodeId", str(a.nodeId)]]);
|
|
488
523
|
case "ReadFileBody":
|
|
489
524
|
return caseObj("ReadFileBody", [
|
|
490
525
|
["encoding", str(a.encoding)],
|
|
@@ -559,6 +594,10 @@ var formatIntent = (f) => {
|
|
|
559
594
|
["style", str(f.style)],
|
|
560
595
|
["unit", str(f.unit)]
|
|
561
596
|
]);
|
|
597
|
+
// Phase 1533 — `unit` omitted when absent: its absence is the
|
|
598
|
+
// auto-selection request, not a default that could be spelled out.
|
|
599
|
+
case "Since":
|
|
600
|
+
return caseObj("Since", f.unit !== void 0 ? [["unit", str(f.unit)]] : []);
|
|
562
601
|
default:
|
|
563
602
|
return assertNever(f);
|
|
564
603
|
}
|
|
@@ -1341,15 +1380,34 @@ var gridSpec = (s) => {
|
|
|
1341
1380
|
}
|
|
1342
1381
|
return jObject(fields);
|
|
1343
1382
|
};
|
|
1383
|
+
var chartAnnotationX = (a) => a.kind === "Category" ? caseObj("Category", [["key", str(a.key)]]) : caseObj("Date", [["iso", str(a.iso)]]);
|
|
1384
|
+
var chartAnnotationRange = (r) => r.kind === "ValueRange" ? caseObj("ValueRange", [
|
|
1385
|
+
["from", num(r.from)],
|
|
1386
|
+
["to", num(r.to)]
|
|
1387
|
+
]) : caseObj("XRange", [
|
|
1388
|
+
["from", chartAnnotationX(r.from)],
|
|
1389
|
+
["to", chartAnnotationX(r.to)]
|
|
1390
|
+
]);
|
|
1391
|
+
var chartAnnotation = (a) => {
|
|
1392
|
+
const label = a.label !== void 0 ? [["label", textSource(a.label)]] : [];
|
|
1393
|
+
switch (a.kind) {
|
|
1394
|
+
case "ReferenceLine":
|
|
1395
|
+
return caseObj("ReferenceLine", [["value", num(a.value)], ...label]);
|
|
1396
|
+
case "EventMarker":
|
|
1397
|
+
return caseObj("EventMarker", [["at", chartAnnotationX(a.at)], ...label]);
|
|
1398
|
+
default:
|
|
1399
|
+
return caseObj("RangeBand", [["range", chartAnnotationRange(a.range)], ...label]);
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1344
1402
|
var chartSpec = (s) => {
|
|
1345
1403
|
const fields = [
|
|
1346
1404
|
["kind", str(s.kind)],
|
|
1347
1405
|
// fuaran#665 — rows are a typed Static payload now, not the opaque residual.
|
|
1348
1406
|
["source", binding(s.source, staticRowSeq)],
|
|
1349
|
-
["stacked", bool(s.stacked)],
|
|
1350
1407
|
["xField", str(s.xField)],
|
|
1351
1408
|
["yFields", jArray(s.yFields.map(str))]
|
|
1352
1409
|
];
|
|
1410
|
+
if (s.stacked) fields.push(["stacked", bool(s.stacked)]);
|
|
1353
1411
|
if (s.title !== void 0) fields.push(["title", textSource(s.title)]);
|
|
1354
1412
|
if (s.valueFormat !== void 0) fields.push(["valueFormat", formatIntent(s.valueFormat)]);
|
|
1355
1413
|
if (s.xTitle !== void 0) fields.push(["xTitle", textSource(s.xTitle)]);
|
|
@@ -1358,6 +1416,8 @@ var chartSpec = (s) => {
|
|
|
1358
1416
|
if (s.legendPosition !== void 0) fields.push(["legendPosition", str(s.legendPosition)]);
|
|
1359
1417
|
if (s.dataLabels !== void 0) fields.push(["dataLabels", str(s.dataLabels)]);
|
|
1360
1418
|
if (s.xScale !== void 0) fields.push(["xScale", str(s.xScale)]);
|
|
1419
|
+
if (s.annotations !== void 0)
|
|
1420
|
+
fields.push(["annotations", jArray(s.annotations.map(chartAnnotation))]);
|
|
1361
1421
|
if (s.onPointClick !== void 0) fields.push(["onPointClick", CLOSURE]);
|
|
1362
1422
|
return jObject(fields);
|
|
1363
1423
|
};
|
|
@@ -1640,10 +1700,14 @@ var nodeKind = (k) => {
|
|
|
1640
1700
|
[
|
|
1641
1701
|
"cases",
|
|
1642
1702
|
jArray(
|
|
1703
|
+
// Phase 1535 — exactly one of `match` and `when` is present, so
|
|
1704
|
+
// exactly one is emitted. `jObject` sorts, so the pair's relative
|
|
1705
|
+
// order here is immaterial.
|
|
1643
1706
|
k.spec.cases.map(
|
|
1644
1707
|
(c) => jObject([
|
|
1645
1708
|
["child", node(c.child)],
|
|
1646
|
-
["match", str(c.match)]
|
|
1709
|
+
...c.match !== void 0 ? [["match", str(c.match)]] : [],
|
|
1710
|
+
...c.when !== void 0 ? [["when", binding(c.when, bool)]] : []
|
|
1647
1711
|
])
|
|
1648
1712
|
)
|
|
1649
1713
|
)
|
|
@@ -1738,6 +1802,7 @@ var node = (n) => {
|
|
|
1738
1802
|
if (!isDefaultStyle(n.style)) fields.push(["style", semanticStyle(n.style)]);
|
|
1739
1803
|
if (n.accessibility !== void 0) fields.push(["accessibility", accessibility(n.accessibility)]);
|
|
1740
1804
|
if (n.tooltip !== void 0) fields.push(["tooltip", textSource(n.tooltip)]);
|
|
1805
|
+
if (n.visible !== void 0) fields.push(["visible", binding(n.visible, bool)]);
|
|
1741
1806
|
return jObject(fields);
|
|
1742
1807
|
};
|
|
1743
1808
|
var treeOp = (op) => {
|
|
@@ -2893,6 +2958,51 @@ var substituteListParams = (listEnv, pipeline) => pipeline.map((t) => {
|
|
|
2893
2958
|
return t;
|
|
2894
2959
|
}
|
|
2895
2960
|
});
|
|
2961
|
+
|
|
2962
|
+
// src/localCodec.ts
|
|
2963
|
+
var identityFormat = (v) => {
|
|
2964
|
+
if (v === null || v === void 0) return "";
|
|
2965
|
+
if (typeof v === "string") return v;
|
|
2966
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
2967
|
+
if (typeof v === "number") {
|
|
2968
|
+
if (Number.isNaN(v)) return "NaN";
|
|
2969
|
+
if (v === Infinity) return "Infinity";
|
|
2970
|
+
if (v === -Infinity) return "-Infinity";
|
|
2971
|
+
return formatFiniteDouble(v);
|
|
2972
|
+
}
|
|
2973
|
+
return String(v);
|
|
2974
|
+
};
|
|
2975
|
+
var tryNumberText = (text) => {
|
|
2976
|
+
const s = text.replace(/^[ \t\n\r]+|[ \t\n\r]+$/g, "");
|
|
2977
|
+
if (!/^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(s)) return void 0;
|
|
2978
|
+
const v = Number(s);
|
|
2979
|
+
return Number.isFinite(v) ? v : void 0;
|
|
2980
|
+
};
|
|
2981
|
+
var scalarOfText = (text) => {
|
|
2982
|
+
if (text === "true") return true;
|
|
2983
|
+
if (text === "false") return false;
|
|
2984
|
+
return tryNumberText(text);
|
|
2985
|
+
};
|
|
2986
|
+
var fixedText = (decimals, v) => {
|
|
2987
|
+
if (!Number.isFinite(v)) return identityFormat(v);
|
|
2988
|
+
const d = decimals < 0 ? 0 : Math.trunc(decimals);
|
|
2989
|
+
const neg = v < 0;
|
|
2990
|
+
const scaled = Math.floor(Math.abs(v) * Math.pow(10, d) + 0.5);
|
|
2991
|
+
const whole = formatFiniteDouble(scaled);
|
|
2992
|
+
const body = d === 0 ? whole : (() => {
|
|
2993
|
+
const padded = whole.length <= d ? "0".repeat(d + 1 - whole.length) + whole : whole;
|
|
2994
|
+
return padded.slice(0, padded.length - d) + "." + padded.slice(padded.length - d);
|
|
2995
|
+
})();
|
|
2996
|
+
return neg && scaled !== 0 ? "-" + body : body;
|
|
2997
|
+
};
|
|
2998
|
+
var numberText = (decimals, v) => decimals !== void 0 && typeof v === "number" ? fixedText(decimals, v) : identityFormat(v);
|
|
2999
|
+
var WireSurvivabilityError = class extends Error {
|
|
3000
|
+
constructor(message) {
|
|
3001
|
+
super(message);
|
|
3002
|
+
this.name = "WireSurvivabilityError";
|
|
3003
|
+
}
|
|
3004
|
+
};
|
|
3005
|
+
var DECODED_COMPUTED_MESSAGE = "Binding.Computed has no wire projection (decoded from a '<closure>' sentinel) \u2014 use Binding.Expr / Transform / State";
|
|
2896
3006
|
var peek = (s) => s.pos < s.text.length ? s.text[s.pos] : " ";
|
|
2897
3007
|
var advance = (s) => {
|
|
2898
3008
|
s.pos += 1;
|
|
@@ -2923,51 +3033,94 @@ var expectChar = (s, ch) => {
|
|
|
2923
3033
|
return fail(s, `expected '${ch}' but found '${peek(s)}'`);
|
|
2924
3034
|
};
|
|
2925
3035
|
var HEX_DIGIT = /[0-9a-fA-F]/;
|
|
3036
|
+
var HIGH_SURROGATE_FIRST = 55296;
|
|
3037
|
+
var HIGH_SURROGATE_LAST = 56319;
|
|
3038
|
+
var LOW_SURROGATE_FIRST = 56320;
|
|
3039
|
+
var LOW_SURROGATE_LAST = 57343;
|
|
2926
3040
|
var parseStringRaw = (s) => {
|
|
2927
3041
|
const open = expectChar(s, '"');
|
|
2928
3042
|
if (!open.ok) return open;
|
|
2929
3043
|
let out = "";
|
|
3044
|
+
let codePoints = 0;
|
|
3045
|
+
let pendingHigh = false;
|
|
3046
|
+
const append = (unit) => {
|
|
3047
|
+
const code = unit.charCodeAt(0);
|
|
3048
|
+
const isHigh = code >= HIGH_SURROGATE_FIRST && code <= HIGH_SURROGATE_LAST;
|
|
3049
|
+
const isLow = code >= LOW_SURROGATE_FIRST && code <= LOW_SURROGATE_LAST;
|
|
3050
|
+
if (isHigh) {
|
|
3051
|
+
if (pendingHigh) {
|
|
3052
|
+
return {
|
|
3053
|
+
message: "unpaired high surrogate: it must be followed by a low surrogate",
|
|
3054
|
+
offset: s.pos
|
|
3055
|
+
};
|
|
3056
|
+
}
|
|
3057
|
+
pendingHigh = true;
|
|
3058
|
+
codePoints += 1;
|
|
3059
|
+
} else if (isLow) {
|
|
3060
|
+
if (!pendingHigh) {
|
|
3061
|
+
return {
|
|
3062
|
+
message: "unpaired low surrogate: it must be preceded by a high surrogate",
|
|
3063
|
+
offset: s.pos
|
|
3064
|
+
};
|
|
3065
|
+
}
|
|
3066
|
+
pendingHigh = false;
|
|
3067
|
+
} else if (pendingHigh) {
|
|
3068
|
+
return {
|
|
3069
|
+
message: "unpaired high surrogate: it must be followed by a low surrogate",
|
|
3070
|
+
offset: s.pos
|
|
3071
|
+
};
|
|
3072
|
+
} else {
|
|
3073
|
+
codePoints += 1;
|
|
3074
|
+
}
|
|
3075
|
+
if (codePoints > MAX_STRING_LENGTH) {
|
|
3076
|
+
return {
|
|
3077
|
+
message: `string is longer than the wire limit MAX_STRING_LENGTH = ${MAX_STRING_LENGTH}`,
|
|
3078
|
+
offset: s.pos,
|
|
3079
|
+
limit: true
|
|
3080
|
+
};
|
|
3081
|
+
}
|
|
3082
|
+
out += unit;
|
|
3083
|
+
return void 0;
|
|
3084
|
+
};
|
|
2930
3085
|
for (; ; ) {
|
|
2931
3086
|
if (s.pos >= s.text.length) return fail(s, "unterminated string");
|
|
2932
3087
|
const c = s.text[s.pos];
|
|
2933
3088
|
advance(s);
|
|
2934
3089
|
if (c === '"') {
|
|
3090
|
+
if (pendingHigh) {
|
|
3091
|
+
return fail(s, "unpaired high surrogate at the end of a string");
|
|
3092
|
+
}
|
|
2935
3093
|
return { ok: true, value: out };
|
|
2936
3094
|
}
|
|
2937
|
-
if (out.length > MAX_STRING_LENGTH) {
|
|
2938
|
-
return failLimit(
|
|
2939
|
-
s,
|
|
2940
|
-
`string is longer than the wire limit MAX_STRING_LENGTH = ${MAX_STRING_LENGTH}`
|
|
2941
|
-
);
|
|
2942
|
-
}
|
|
2943
3095
|
if (c === "\\") {
|
|
2944
3096
|
if (s.pos >= s.text.length) return fail(s, "unterminated escape");
|
|
2945
3097
|
const esc = s.text[s.pos];
|
|
2946
3098
|
advance(s);
|
|
3099
|
+
let unit;
|
|
2947
3100
|
switch (esc) {
|
|
2948
3101
|
case '"':
|
|
2949
|
-
|
|
3102
|
+
unit = '"';
|
|
2950
3103
|
break;
|
|
2951
3104
|
case "\\":
|
|
2952
|
-
|
|
3105
|
+
unit = "\\";
|
|
2953
3106
|
break;
|
|
2954
3107
|
case "/":
|
|
2955
|
-
|
|
3108
|
+
unit = "/";
|
|
2956
3109
|
break;
|
|
2957
3110
|
case "b":
|
|
2958
|
-
|
|
3111
|
+
unit = "\b";
|
|
2959
3112
|
break;
|
|
2960
3113
|
case "f":
|
|
2961
|
-
|
|
3114
|
+
unit = "\f";
|
|
2962
3115
|
break;
|
|
2963
3116
|
case "n":
|
|
2964
|
-
|
|
3117
|
+
unit = "\n";
|
|
2965
3118
|
break;
|
|
2966
3119
|
case "r":
|
|
2967
|
-
|
|
3120
|
+
unit = "\r";
|
|
2968
3121
|
break;
|
|
2969
3122
|
case "t":
|
|
2970
|
-
|
|
3123
|
+
unit = " ";
|
|
2971
3124
|
break;
|
|
2972
3125
|
case "u": {
|
|
2973
3126
|
if (s.pos + 4 > s.text.length) return fail(s, "incomplete \\u escape");
|
|
@@ -2976,26 +3129,58 @@ var parseStringRaw = (s) => {
|
|
|
2976
3129
|
return fail(s, `invalid \\u escape '${hex}'`);
|
|
2977
3130
|
}
|
|
2978
3131
|
s.pos += 4;
|
|
2979
|
-
|
|
3132
|
+
unit = String.fromCharCode(parseInt(hex, 16));
|
|
2980
3133
|
break;
|
|
2981
3134
|
}
|
|
2982
3135
|
default:
|
|
2983
3136
|
return fail(s, `unknown escape '\\${esc}'`);
|
|
2984
3137
|
}
|
|
3138
|
+
const bad = append(unit);
|
|
3139
|
+
if (bad) return { ok: false, error: bad };
|
|
3140
|
+
} else if (c.charCodeAt(0) < 32) {
|
|
3141
|
+
return fail(
|
|
3142
|
+
s,
|
|
3143
|
+
`raw control character U+${c.charCodeAt(0).toString(16).padStart(4, "0").toUpperCase()} in a string must be escaped`
|
|
3144
|
+
);
|
|
2985
3145
|
} else {
|
|
2986
|
-
|
|
3146
|
+
const bad = append(c);
|
|
3147
|
+
if (bad) return { ok: false, error: bad };
|
|
2987
3148
|
}
|
|
2988
3149
|
}
|
|
2989
3150
|
};
|
|
2990
3151
|
var isNumberChar = (c) => c === "-" || c === "+" || c === "." || c === "e" || c === "E" || c >= "0" && c <= "9";
|
|
3152
|
+
var isRfc8259Number = (slice) => {
|
|
3153
|
+
const n = slice.length;
|
|
3154
|
+
let i = 0;
|
|
3155
|
+
const digit = (k) => k < n && slice[k] >= "0" && slice[k] <= "9";
|
|
3156
|
+
if (i < n && slice[i] === "-") i += 1;
|
|
3157
|
+
if (!digit(i)) return false;
|
|
3158
|
+
if (slice[i] === "0") {
|
|
3159
|
+
i += 1;
|
|
3160
|
+
} else {
|
|
3161
|
+
while (digit(i)) i += 1;
|
|
3162
|
+
}
|
|
3163
|
+
if (i < n && slice[i] === ".") {
|
|
3164
|
+
i += 1;
|
|
3165
|
+
if (!digit(i)) return false;
|
|
3166
|
+
while (digit(i)) i += 1;
|
|
3167
|
+
}
|
|
3168
|
+
if (i < n && (slice[i] === "e" || slice[i] === "E")) {
|
|
3169
|
+
i += 1;
|
|
3170
|
+
if (i < n && (slice[i] === "+" || slice[i] === "-")) i += 1;
|
|
3171
|
+
if (!digit(i)) return false;
|
|
3172
|
+
while (digit(i)) i += 1;
|
|
3173
|
+
}
|
|
3174
|
+
return i === n;
|
|
3175
|
+
};
|
|
2991
3176
|
var parseNumberRaw = (s) => {
|
|
2992
3177
|
const start = s.pos;
|
|
2993
3178
|
while (s.pos < s.text.length && isNumberChar(s.text[s.pos])) {
|
|
2994
3179
|
advance(s);
|
|
2995
3180
|
}
|
|
2996
3181
|
const slice = s.text.substring(start, s.pos);
|
|
2997
|
-
if (slice
|
|
2998
|
-
return fail(s, `
|
|
3182
|
+
if (!isRfc8259Number(slice)) {
|
|
3183
|
+
return fail(s, `'${slice}' is not a JSON number (RFC 8259 grammar)`);
|
|
2999
3184
|
}
|
|
3000
3185
|
const n = Number(slice);
|
|
3001
3186
|
if (Number.isNaN(n)) {
|
|
@@ -3082,6 +3267,10 @@ var parseObjectValue = (s) => {
|
|
|
3082
3267
|
`object has more members than the wire limit MAX_ARRAY_LENGTH = ${MAX_ARRAY_LENGTH}`
|
|
3083
3268
|
);
|
|
3084
3269
|
}
|
|
3270
|
+
if (fields.has(keyR.value)) {
|
|
3271
|
+
s.depth -= 1;
|
|
3272
|
+
return fail(s, `duplicate object member '${keyR.value}'`);
|
|
3273
|
+
}
|
|
3085
3274
|
fields.set(keyR.value, valR.value);
|
|
3086
3275
|
skipWs(s);
|
|
3087
3276
|
const c = peek(s);
|
|
@@ -3141,13 +3330,52 @@ var parseArrayValue = (s) => {
|
|
|
3141
3330
|
}
|
|
3142
3331
|
}
|
|
3143
3332
|
};
|
|
3333
|
+
var documentBytes = (input) => {
|
|
3334
|
+
if (input.length > MAX_DOCUMENT_BYTES) return input.length;
|
|
3335
|
+
if (input.length <= MAX_DOCUMENT_BYTES / 3) return input.length;
|
|
3336
|
+
let total = 0;
|
|
3337
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
3338
|
+
const c = input.charCodeAt(i);
|
|
3339
|
+
if (c < 128) {
|
|
3340
|
+
total += 1;
|
|
3341
|
+
} else if (c < 2048) {
|
|
3342
|
+
total += 2;
|
|
3343
|
+
} else if (c >= HIGH_SURROGATE_FIRST && c <= HIGH_SURROGATE_LAST && i + 1 < input.length) {
|
|
3344
|
+
total += 4;
|
|
3345
|
+
i += 1;
|
|
3346
|
+
} else {
|
|
3347
|
+
total += 3;
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
return total;
|
|
3351
|
+
};
|
|
3144
3352
|
var parse = (input) => {
|
|
3353
|
+
const bytes = documentBytes(input);
|
|
3354
|
+
if (bytes > MAX_DOCUMENT_BYTES) {
|
|
3355
|
+
return {
|
|
3356
|
+
ok: false,
|
|
3357
|
+
error: {
|
|
3358
|
+
message: `document of ${bytes} UTF-8 bytes exceeds the wire limit MAX_DOCUMENT_BYTES = ${MAX_DOCUMENT_BYTES}`,
|
|
3359
|
+
offset: 0,
|
|
3360
|
+
limit: true
|
|
3361
|
+
}
|
|
3362
|
+
};
|
|
3363
|
+
}
|
|
3145
3364
|
const s = { text: input, pos: 0, depth: 0 };
|
|
3146
3365
|
skipWs(s);
|
|
3147
3366
|
if (s.pos >= s.text.length) {
|
|
3148
3367
|
return { ok: false, error: { message: "input is empty", offset: 0 } };
|
|
3149
3368
|
}
|
|
3150
|
-
|
|
3369
|
+
const value = parseValue(s);
|
|
3370
|
+
if (!value.ok) return value;
|
|
3371
|
+
skipWs(s);
|
|
3372
|
+
if (s.pos < s.text.length) {
|
|
3373
|
+
return fail(
|
|
3374
|
+
s,
|
|
3375
|
+
`unexpected content after the root value ('${s.text[s.pos]}'); a wire artefact is a single JSON document`
|
|
3376
|
+
);
|
|
3377
|
+
}
|
|
3378
|
+
return value;
|
|
3151
3379
|
};
|
|
3152
3380
|
var field = (fields, key) => fields.get(key);
|
|
3153
3381
|
|
|
@@ -3192,9 +3420,31 @@ var requireFloat = (path, jRaw) => {
|
|
|
3192
3420
|
}
|
|
3193
3421
|
return wrongType(path, "JSON number (or 'NaN' / 'Infinity' / '-Infinity' sentinel string)");
|
|
3194
3422
|
};
|
|
3423
|
+
var INT32_MIN = -2147483648;
|
|
3424
|
+
var INT32_MAX = 2147483647;
|
|
3425
|
+
var isInt32Slot = (n) => Number.isFinite(n) && Number.isInteger(n) && n >= INT32_MIN && n <= INT32_MAX;
|
|
3195
3426
|
var requireInt = (path, jRaw) => {
|
|
3196
3427
|
const j = unwrapStaticEnvelope(jRaw);
|
|
3197
|
-
|
|
3428
|
+
if (j.kind !== "JNumber") return wrongType(path, "JSON number (integer)");
|
|
3429
|
+
if (!Number.isFinite(j.value)) {
|
|
3430
|
+
return wrongType(
|
|
3431
|
+
path,
|
|
3432
|
+
"JSON number (a finite 32-bit integer; the non-finite sentinels are a float slot's, not an integer slot's)"
|
|
3433
|
+
);
|
|
3434
|
+
}
|
|
3435
|
+
if (!Number.isInteger(j.value)) {
|
|
3436
|
+
return wrongType(
|
|
3437
|
+
path,
|
|
3438
|
+
"JSON number (a 32-bit integer; a fractional value is not truncated at an integer slot)"
|
|
3439
|
+
);
|
|
3440
|
+
}
|
|
3441
|
+
if (!isInt32Slot(j.value)) {
|
|
3442
|
+
return wrongType(
|
|
3443
|
+
path,
|
|
3444
|
+
"JSON number (a 32-bit integer; the value is outside the range this slot can hold)"
|
|
3445
|
+
);
|
|
3446
|
+
}
|
|
3447
|
+
return ok(j.value);
|
|
3198
3448
|
};
|
|
3199
3449
|
var requireArray = (path, j) => j.kind === "JArray" ? ok(j.items) : wrongType(path, "JSON array");
|
|
3200
3450
|
var tryField = (fields, key) => fields.get(key);
|
|
@@ -3353,6 +3603,7 @@ var decodeHeadingVariant = (p, j) => {
|
|
|
3353
3603
|
var decodeImageVariant = (p, j) => bareEnum(p, j, ["Default", "Avatar", "Rounded"], "ImageVariant");
|
|
3354
3604
|
var decodeImageFit = (p, j) => bareEnum(p, j, ["Natural", "Cover", "Contain"], "ImageFit");
|
|
3355
3605
|
var decodeModalityKind = (p, j) => bareEnum(p, j, ["Modal", "Popover"], "ModalityKind");
|
|
3606
|
+
var decodeNavigateTarget = (p, j) => bareEnum(p, j, ["Self", "Blank"], "NavigateTarget");
|
|
3356
3607
|
var decodeImageAspect = (p, j) => bareEnum(
|
|
3357
3608
|
p,
|
|
3358
3609
|
j,
|
|
@@ -3430,6 +3681,149 @@ var decodeChartKind = (p, j) => bareEnum(p, j, ["Line", "Bar", "Area", "Pie", "S
|
|
|
3430
3681
|
var decodeChartLegendPosition = (p, j) => bareEnum(p, j, ["Top", "Right", "Bottom", "None"], "ChartLegendPosition");
|
|
3431
3682
|
var decodeChartDataLabels = (p, j) => bareEnum(p, j, ["Off", "Ends"], "ChartDataLabels");
|
|
3432
3683
|
var decodeChartXScale = (p, j) => bareEnum(p, j, ["Category", "Temporal"], "ChartXScale");
|
|
3684
|
+
var annotationIsLeapYear = (y) => y % 4 === 0 && y % 100 !== 0 || y % 400 === 0;
|
|
3685
|
+
var annotationDaysInMonth = (y, m) => m === 2 ? annotationIsLeapYear(y) ? 29 : 28 : m === 4 || m === 6 || m === 9 || m === 11 ? 30 : 31;
|
|
3686
|
+
var isCanonicalIsoDay = (text) => {
|
|
3687
|
+
if (text.length < 10) return false;
|
|
3688
|
+
if (text[4] !== "-" || text[7] !== "-") return false;
|
|
3689
|
+
if (text.length > 10 && text[10] !== "T") return false;
|
|
3690
|
+
const digits = (start, len) => {
|
|
3691
|
+
let acc = 0;
|
|
3692
|
+
for (let k = start; k < start + len; k += 1) {
|
|
3693
|
+
const c = text.charCodeAt(k);
|
|
3694
|
+
if (c < 48 || c > 57) return void 0;
|
|
3695
|
+
acc = acc * 10 + (c - 48);
|
|
3696
|
+
}
|
|
3697
|
+
return acc;
|
|
3698
|
+
};
|
|
3699
|
+
const y = digits(0, 4);
|
|
3700
|
+
const m = digits(5, 2);
|
|
3701
|
+
const d = digits(8, 2);
|
|
3702
|
+
if (y === void 0 || m === void 0 || d === void 0) return false;
|
|
3703
|
+
return m >= 1 && m <= 12 && d >= 1 && d <= annotationDaysInMonth(y, m);
|
|
3704
|
+
};
|
|
3705
|
+
var decodeChartAnnotationX = (path, j) => {
|
|
3706
|
+
const fo = requireObject(path, j);
|
|
3707
|
+
if (!fo.ok) return fo;
|
|
3708
|
+
const f = fo.value;
|
|
3709
|
+
const disc = requireDiscriminator(path, f);
|
|
3710
|
+
if (!disc.ok) return disc;
|
|
3711
|
+
switch (disc.value) {
|
|
3712
|
+
case "Category": {
|
|
3713
|
+
const key = reqField(path, f, "key", "category key (the band's own label)", requireString);
|
|
3714
|
+
if (!key.ok) return key;
|
|
3715
|
+
return ok({ kind: "Category", key: key.value });
|
|
3716
|
+
}
|
|
3717
|
+
case "Date": {
|
|
3718
|
+
const iso = reqField(path, f, "iso", "ISO-8601 date (YYYY-MM-DD)", requireString);
|
|
3719
|
+
if (!iso.ok) return iso;
|
|
3720
|
+
if (!isCanonicalIsoDay(iso.value))
|
|
3721
|
+
return wrongType(
|
|
3722
|
+
`${path}.iso`,
|
|
3723
|
+
"a canonical ISO-8601 date (YYYY-MM-DD, optionally followed by a time) naming a real calendar day \u2014 an event marker\u2019s date is the address it is drawn at, and an unreadable one would place the marker at 1970-01-01 and drag the axis back with it"
|
|
3724
|
+
);
|
|
3725
|
+
return ok({ kind: "Date", iso: iso.value });
|
|
3726
|
+
}
|
|
3727
|
+
default:
|
|
3728
|
+
return unknownDuCase(path, disc.value, "Category, Date");
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3731
|
+
var decodeChartAnnotationRange = (path, j) => {
|
|
3732
|
+
const finite = (slot, v) => {
|
|
3733
|
+
const r = requireFloat(`${path}.${slot}`, v);
|
|
3734
|
+
if (!r.ok) return r;
|
|
3735
|
+
return Number.isFinite(r.value) ? r : wrongType(
|
|
3736
|
+
`${path}.${slot}`,
|
|
3737
|
+
"a FINITE JSON number \u2014 a range band's end names a place on the value axis, and NaN / Infinity names none; give the value in the axis's own units, or drop the annotation"
|
|
3738
|
+
);
|
|
3739
|
+
};
|
|
3740
|
+
const fo = requireObject(path, j);
|
|
3741
|
+
if (!fo.ok) return fo;
|
|
3742
|
+
const f = fo.value;
|
|
3743
|
+
const disc = requireDiscriminator(path, f);
|
|
3744
|
+
if (!disc.ok) return disc;
|
|
3745
|
+
switch (disc.value) {
|
|
3746
|
+
case "ValueRange": {
|
|
3747
|
+
const fromJ = requireField(path, f, "from", "range-band lower value (a finite JSON number)");
|
|
3748
|
+
if (!fromJ.ok) return fromJ;
|
|
3749
|
+
const from = finite("from", fromJ.value);
|
|
3750
|
+
if (!from.ok) return from;
|
|
3751
|
+
const toJ = requireField(path, f, "to", "range-band upper value (a finite JSON number)");
|
|
3752
|
+
if (!toJ.ok) return toJ;
|
|
3753
|
+
const to = finite("to", toJ.value);
|
|
3754
|
+
if (!to.ok) return to;
|
|
3755
|
+
if (from.value > to.value)
|
|
3756
|
+
return wrongType(
|
|
3757
|
+
path,
|
|
3758
|
+
"an ORDERED pair \u2014 a range band runs from its lower value to its upper one, and this pair runs backwards; swapping the ends silently would draw a band the author did not describe"
|
|
3759
|
+
);
|
|
3760
|
+
return ok({ kind: "ValueRange", from: from.value, to: to.value });
|
|
3761
|
+
}
|
|
3762
|
+
case "XRange": {
|
|
3763
|
+
const fromJ = requireField(
|
|
3764
|
+
path,
|
|
3765
|
+
f,
|
|
3766
|
+
"from",
|
|
3767
|
+
"range-band lower x address (a ChartAnnotationX)"
|
|
3768
|
+
);
|
|
3769
|
+
if (!fromJ.ok) return fromJ;
|
|
3770
|
+
const from = decodeChartAnnotationX(`${path}.from`, fromJ.value);
|
|
3771
|
+
if (!from.ok) return from;
|
|
3772
|
+
const toJ = requireField(path, f, "to", "range-band upper x address (a ChartAnnotationX)");
|
|
3773
|
+
if (!toJ.ok) return toJ;
|
|
3774
|
+
const to = decodeChartAnnotationX(`${path}.to`, toJ.value);
|
|
3775
|
+
if (!to.ok) return to;
|
|
3776
|
+
if (from.value.kind === "Date" && to.value.kind === "Date" && from.value.iso > to.value.iso)
|
|
3777
|
+
return wrongType(
|
|
3778
|
+
path,
|
|
3779
|
+
"an ORDERED pair \u2014 a range band runs from its earlier date to its later one, and this pair runs backwards; swapping the ends silently would draw a band the author did not describe"
|
|
3780
|
+
);
|
|
3781
|
+
return ok({ kind: "XRange", from: from.value, to: to.value });
|
|
3782
|
+
}
|
|
3783
|
+
default:
|
|
3784
|
+
return unknownDuCase(path, disc.value, "ValueRange, XRange");
|
|
3785
|
+
}
|
|
3786
|
+
};
|
|
3787
|
+
var decodeChartAnnotation = (path, j) => {
|
|
3788
|
+
const fo = requireObject(path, j);
|
|
3789
|
+
if (!fo.ok) return fo;
|
|
3790
|
+
const f = fo.value;
|
|
3791
|
+
const disc = requireDiscriminator(path, f);
|
|
3792
|
+
if (!disc.ok) return disc;
|
|
3793
|
+
const label = optField(path, f, "label", decodeTextSource);
|
|
3794
|
+
if (!label.ok) return label;
|
|
3795
|
+
const withLabel = label.value !== void 0 ? { label: label.value } : {};
|
|
3796
|
+
switch (disc.value) {
|
|
3797
|
+
case "ReferenceLine": {
|
|
3798
|
+
const valueJ = requireField(path, f, "value", "reference-line value (a finite JSON number)");
|
|
3799
|
+
if (!valueJ.ok) return valueJ;
|
|
3800
|
+
const value = requireFloat(`${path}.value`, valueJ.value);
|
|
3801
|
+
if (!value.ok) return value;
|
|
3802
|
+
if (!Number.isFinite(value.value))
|
|
3803
|
+
return wrongType(
|
|
3804
|
+
`${path}.value`,
|
|
3805
|
+
"a FINITE JSON number \u2014 a reference line names a place on the value axis, and NaN / Infinity names none; give the value in the axis's own units, or drop the annotation"
|
|
3806
|
+
);
|
|
3807
|
+
return ok({ kind: "ReferenceLine", value: value.value, ...withLabel });
|
|
3808
|
+
}
|
|
3809
|
+
case "EventMarker": {
|
|
3810
|
+
const atJ = requireField(path, f, "at", "event-marker x address (a ChartAnnotationX)");
|
|
3811
|
+
if (!atJ.ok) return atJ;
|
|
3812
|
+
const at = decodeChartAnnotationX(`${path}.at`, atJ.value);
|
|
3813
|
+
if (!at.ok) return at;
|
|
3814
|
+
return ok({ kind: "EventMarker", at: at.value, ...withLabel });
|
|
3815
|
+
}
|
|
3816
|
+
case "RangeBand": {
|
|
3817
|
+
const rangeJ = requireField(path, f, "range", "range-band pair (a ChartAnnotationRange)");
|
|
3818
|
+
if (!rangeJ.ok) return rangeJ;
|
|
3819
|
+
const range = decodeChartAnnotationRange(`${path}.range`, rangeJ.value);
|
|
3820
|
+
if (!range.ok) return range;
|
|
3821
|
+
return ok({ kind: "RangeBand", range: range.value, ...withLabel });
|
|
3822
|
+
}
|
|
3823
|
+
default:
|
|
3824
|
+
return unknownDuCase(path, disc.value, "ReferenceLine, EventMarker, RangeBand");
|
|
3825
|
+
}
|
|
3826
|
+
};
|
|
3433
3827
|
var decodeFileReadEncoding = (p, j) => bareEnum(p, j, ["Text", "Base64", "DataUrl"], "FileReadEncoding");
|
|
3434
3828
|
var decodeAriaRole = (p, j) => {
|
|
3435
3829
|
if (j.kind !== "JString") return wrongType(p, "JSON string (ARIA role)");
|
|
@@ -3444,6 +3838,7 @@ var decodeRelativeTimeUnit = (p, j) => bareEnum(
|
|
|
3444
3838
|
["Second", "Minute", "Hour", "Day", "Week", "Month", "Year"],
|
|
3445
3839
|
"RelativeTimeUnit"
|
|
3446
3840
|
);
|
|
3841
|
+
var decodeTimeGrain = (p, j) => bareEnum(p, j, ["Second", "Minute", "Hour", "Day"], "TimeGrain");
|
|
3447
3842
|
var decodeCellFormat = (path, j) => {
|
|
3448
3843
|
const fo = requireObject(path, j);
|
|
3449
3844
|
if (!fo.ok) return fo;
|
|
@@ -3543,11 +3938,17 @@ var decodeFormat = (path, j) => {
|
|
|
3543
3938
|
if (!style.ok) return style;
|
|
3544
3939
|
return ok({ kind: "Duration", unit: unit.value, style: style.value });
|
|
3545
3940
|
}
|
|
3941
|
+
case "Since": {
|
|
3942
|
+
const u = tryField(f, "unit");
|
|
3943
|
+
if (u === void 0) return ok({ kind: "Since" });
|
|
3944
|
+
const r = decodeRelativeTimeUnit(`${path}.unit`, u);
|
|
3945
|
+
return r.ok ? ok({ kind: "Since", unit: r.value }) : r;
|
|
3946
|
+
}
|
|
3546
3947
|
default:
|
|
3547
3948
|
return unknownDuCase(
|
|
3548
3949
|
path,
|
|
3549
3950
|
d.value,
|
|
3550
|
-
"Number | Currency | Percent | Date | RelativeTime | Duration"
|
|
3951
|
+
"Number | Currency | Percent | Date | RelativeTime | Duration | Since"
|
|
3551
3952
|
);
|
|
3552
3953
|
}
|
|
3553
3954
|
};
|
|
@@ -3701,7 +4102,13 @@ var cFieldAliased = (f, canonical, alias) => {
|
|
|
3701
4102
|
};
|
|
3702
4103
|
var cStr = (j) => j.kind === "JString" ? cok(j.value) : cerr("malformed: expected string, got " + astKind(j));
|
|
3703
4104
|
var cArr = (j) => j.kind === "JArray" ? cok(j.items) : cerr("malformed: expected array, got " + astKind(j));
|
|
3704
|
-
var cInt = (j) =>
|
|
4105
|
+
var cInt = (j) => {
|
|
4106
|
+
if (j.kind !== "JNumber") return cerr("malformed: expected int, got " + astKind(j));
|
|
4107
|
+
if (!isInt32Slot(j.value)) {
|
|
4108
|
+
return cerr(`malformed: expected a 32-bit integer, got ${j.value}`);
|
|
4109
|
+
}
|
|
4110
|
+
return cok(j.value);
|
|
4111
|
+
};
|
|
3705
4112
|
var cMapM = (xs, fn) => {
|
|
3706
4113
|
const out = [];
|
|
3707
4114
|
for (const x of xs) {
|
|
@@ -3732,7 +4139,7 @@ var decodeCellLit = (j) => {
|
|
|
3732
4139
|
if (v === void 0) return mismatch;
|
|
3733
4140
|
switch (t) {
|
|
3734
4141
|
case "Int":
|
|
3735
|
-
return v.kind === "JNumber" ? cok({ kind: "Int", value:
|
|
4142
|
+
return v.kind === "JNumber" && isInt32Slot(v.value) ? cok({ kind: "Int", value: v.value }) : mismatch;
|
|
3736
4143
|
case "Float":
|
|
3737
4144
|
return v.kind === "JNumber" ? cok({ kind: "Float", value: v.value }) : mismatch;
|
|
3738
4145
|
case "Bool":
|
|
@@ -4435,6 +4842,137 @@ var decodeInvokeArgs = (path, j) => {
|
|
|
4435
4842
|
return ok({ addr: addr.value, value: value.value });
|
|
4436
4843
|
});
|
|
4437
4844
|
};
|
|
4845
|
+
var exprAdmissible = (root) => {
|
|
4846
|
+
let count = 0;
|
|
4847
|
+
let sawCol = false;
|
|
4848
|
+
const walk = (e) => {
|
|
4849
|
+
count += 1;
|
|
4850
|
+
if (sawCol || count > MAX_EXPR_NODES) return;
|
|
4851
|
+
switch (e.kind) {
|
|
4852
|
+
case "col":
|
|
4853
|
+
sawCol = true;
|
|
4854
|
+
return;
|
|
4855
|
+
case "lit":
|
|
4856
|
+
case "param":
|
|
4857
|
+
return;
|
|
4858
|
+
case "binary":
|
|
4859
|
+
walk(e.left);
|
|
4860
|
+
walk(e.right);
|
|
4861
|
+
return;
|
|
4862
|
+
case "not":
|
|
4863
|
+
case "cast":
|
|
4864
|
+
case "isNull":
|
|
4865
|
+
walk(e.expr);
|
|
4866
|
+
return;
|
|
4867
|
+
case "coalesce":
|
|
4868
|
+
e.exprs.forEach(walk);
|
|
4869
|
+
return;
|
|
4870
|
+
case "apply":
|
|
4871
|
+
e.args.forEach(walk);
|
|
4872
|
+
return;
|
|
4873
|
+
case "case":
|
|
4874
|
+
for (const c of e.cases) {
|
|
4875
|
+
walk(c.when);
|
|
4876
|
+
walk(c.then);
|
|
4877
|
+
}
|
|
4878
|
+
walk(e.else);
|
|
4879
|
+
return;
|
|
4880
|
+
case "in":
|
|
4881
|
+
walk(e.expr);
|
|
4882
|
+
e.items.forEach(walk);
|
|
4883
|
+
return;
|
|
4884
|
+
case "inParam":
|
|
4885
|
+
walk(e.expr);
|
|
4886
|
+
return;
|
|
4887
|
+
}
|
|
4888
|
+
};
|
|
4889
|
+
walk(root);
|
|
4890
|
+
if (sawCol) return "col";
|
|
4891
|
+
if (count > MAX_EXPR_NODES) return "limit";
|
|
4892
|
+
return "ok";
|
|
4893
|
+
};
|
|
4894
|
+
var colExprParamNames = (root) => {
|
|
4895
|
+
const seen = [];
|
|
4896
|
+
const push = (n) => {
|
|
4897
|
+
if (!seen.includes(n)) seen.push(n);
|
|
4898
|
+
};
|
|
4899
|
+
const walk = (e) => {
|
|
4900
|
+
switch (e.kind) {
|
|
4901
|
+
case "col":
|
|
4902
|
+
case "lit":
|
|
4903
|
+
return;
|
|
4904
|
+
case "param":
|
|
4905
|
+
push(e.name);
|
|
4906
|
+
return;
|
|
4907
|
+
case "binary":
|
|
4908
|
+
walk(e.left);
|
|
4909
|
+
walk(e.right);
|
|
4910
|
+
return;
|
|
4911
|
+
case "not":
|
|
4912
|
+
case "cast":
|
|
4913
|
+
case "isNull":
|
|
4914
|
+
walk(e.expr);
|
|
4915
|
+
return;
|
|
4916
|
+
case "coalesce":
|
|
4917
|
+
e.exprs.forEach(walk);
|
|
4918
|
+
return;
|
|
4919
|
+
case "apply":
|
|
4920
|
+
e.args.forEach(walk);
|
|
4921
|
+
return;
|
|
4922
|
+
case "case":
|
|
4923
|
+
for (const c of e.cases) {
|
|
4924
|
+
walk(c.when);
|
|
4925
|
+
walk(c.then);
|
|
4926
|
+
}
|
|
4927
|
+
walk(e.else);
|
|
4928
|
+
return;
|
|
4929
|
+
case "in":
|
|
4930
|
+
walk(e.expr);
|
|
4931
|
+
e.items.forEach(walk);
|
|
4932
|
+
return;
|
|
4933
|
+
case "inParam":
|
|
4934
|
+
walk(e.expr);
|
|
4935
|
+
push(e.param);
|
|
4936
|
+
return;
|
|
4937
|
+
}
|
|
4938
|
+
};
|
|
4939
|
+
walk(root);
|
|
4940
|
+
return seen;
|
|
4941
|
+
};
|
|
4942
|
+
var decodeExprParams = (path, f) => {
|
|
4943
|
+
const paramsField = tryField(f, "params");
|
|
4944
|
+
if (paramsField === void 0) return ok(void 0);
|
|
4945
|
+
if (paramsField.kind === "JObject") {
|
|
4946
|
+
const entries = [...paramsField.fields.entries()].sort(
|
|
4947
|
+
([a], [b]) => a < b ? -1 : a > b ? 1 : 0
|
|
4948
|
+
);
|
|
4949
|
+
const out = [];
|
|
4950
|
+
for (const [name, v] of entries) {
|
|
4951
|
+
const from = decodeBinding(`${path}.params.${name}.from`, v);
|
|
4952
|
+
if (!from.ok) return from;
|
|
4953
|
+
out.push({ name, from: from.value });
|
|
4954
|
+
}
|
|
4955
|
+
return ok(out);
|
|
4956
|
+
}
|
|
4957
|
+
const arr = requireArray(`${path}.params`, paramsField);
|
|
4958
|
+
if (!arr.ok) return arr;
|
|
4959
|
+
return traverseIndexed(arr.value, (_i, el) => {
|
|
4960
|
+
const po = requireObject(`${path}.params[]`, el);
|
|
4961
|
+
if (!po.ok) return po;
|
|
4962
|
+
const name = reqField(`${path}.params[]`, po.value, "name", "param name string", requireString);
|
|
4963
|
+
if (!name.ok) return name;
|
|
4964
|
+
const from = reqFieldAliased(
|
|
4965
|
+
`${path}.params[]`,
|
|
4966
|
+
po.value,
|
|
4967
|
+
"from",
|
|
4968
|
+
["value"],
|
|
4969
|
+
"param source Binding",
|
|
4970
|
+
decodeBinding
|
|
4971
|
+
);
|
|
4972
|
+
if (!from.ok) return from;
|
|
4973
|
+
return ok({ name: name.value, from: from.value });
|
|
4974
|
+
});
|
|
4975
|
+
};
|
|
4438
4976
|
var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), placeholder = OPAQUE2) => {
|
|
4439
4977
|
if (j.kind === "JArray" || j.kind === "JString" || j.kind === "JNumber" || j.kind === "JBool") {
|
|
4440
4978
|
const parsed = parseStatic(path, j);
|
|
@@ -4533,14 +5071,23 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4533
5071
|
return ok({ kind: "State", key: key.value, defaultValue });
|
|
4534
5072
|
}
|
|
4535
5073
|
case "Computed":
|
|
4536
|
-
return ok({
|
|
5074
|
+
return ok({
|
|
5075
|
+
kind: "Computed",
|
|
5076
|
+
compute: () => {
|
|
5077
|
+
throw new WireSurvivabilityError(DECODED_COMPUTED_MESSAGE);
|
|
5078
|
+
}
|
|
5079
|
+
});
|
|
4537
5080
|
// The projection decodes to the IDENTITY (the Phase 427 Selection fix
|
|
4538
5081
|
// replayed): the host-furnished instant is already the wire-shaped string,
|
|
4539
5082
|
// so a decoded reader receives it as-is. A value-discarding placeholder
|
|
4540
5083
|
// here would make every decoded `Now` resolve to nothing even when the
|
|
4541
5084
|
// host furnishes the instant.
|
|
4542
|
-
case "Now":
|
|
4543
|
-
|
|
5085
|
+
case "Now": {
|
|
5086
|
+
const g = tryField(f, "grain");
|
|
5087
|
+
if (g === void 0) return ok({ kind: "Now", project: (iso) => iso });
|
|
5088
|
+
const r = decodeTimeGrain(`${path}.grain`, g);
|
|
5089
|
+
return r.ok ? ok({ kind: "Now", project: (iso) => iso, grain: r.value }) : r;
|
|
5090
|
+
}
|
|
4544
5091
|
case "I18n": {
|
|
4545
5092
|
const key = reqField(path, f, "key", "i18n key string", requireString);
|
|
4546
5093
|
if (!key.ok) return key;
|
|
@@ -4555,6 +5102,37 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4555
5102
|
return ok(b);
|
|
4556
5103
|
}
|
|
4557
5104
|
case "Local": {
|
|
5105
|
+
const codecJ = tryField(f, "codec");
|
|
5106
|
+
let codec;
|
|
5107
|
+
if (codecJ !== void 0) {
|
|
5108
|
+
const c = decodeFormat(`${path}.codec`, codecJ);
|
|
5109
|
+
if (!c.ok) return c;
|
|
5110
|
+
if (c.value.kind !== "Number") {
|
|
5111
|
+
return makeError(
|
|
5112
|
+
"WRONG_TYPE",
|
|
5113
|
+
`${path}.codec`,
|
|
5114
|
+
"Binding.Local 'codec' must be a Format case with a total, locale-independent inverse \u2014 only 'Number' has one",
|
|
5115
|
+
'use {"$type":"Number","decimals":2}, or drop the codec and let the buffer use the identity; a locale-rendered format (Currency / Date / RelativeTime / Since / Duration) cannot be parsed back from what the reader typed'
|
|
5116
|
+
);
|
|
5117
|
+
}
|
|
5118
|
+
codec = c.value;
|
|
5119
|
+
}
|
|
5120
|
+
const onCommitPresent = tryField(f, "onCommit") !== void 0;
|
|
5121
|
+
const commitToJ = tryField(f, "commitTo");
|
|
5122
|
+
let commitTo;
|
|
5123
|
+
if (commitToJ !== void 0) {
|
|
5124
|
+
if (onCommitPresent) {
|
|
5125
|
+
return makeError(
|
|
5126
|
+
"WRONG_TYPE",
|
|
5127
|
+
`${path}.commitTo`,
|
|
5128
|
+
"Binding.Local carries both 'onCommit' and 'commitTo' \u2014 exactly one commit destination is allowed",
|
|
5129
|
+
"either onCommit (a host closure, which crosses the wire only as the closure sentinel) or commitTo (the State key the flush writes); a decoding host can honour only the second, so keeping both makes the same document commit to two different places depending on who read it"
|
|
5130
|
+
);
|
|
5131
|
+
}
|
|
5132
|
+
const ct = requireString(`${path}.commitTo`, commitToJ);
|
|
5133
|
+
if (!ct.ok) return ct;
|
|
5134
|
+
commitTo = ct.value;
|
|
5135
|
+
}
|
|
4558
5136
|
const initial = reqField(
|
|
4559
5137
|
path,
|
|
4560
5138
|
f,
|
|
@@ -4566,15 +5144,35 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4566
5144
|
const flushJ = tryField(f, "flushOn");
|
|
4567
5145
|
const flush = flushJ === void 0 ? ok({ kind: "OnBlur" }) : decodeLocalFlushTrigger(`${path}.flushOn`, flushJ);
|
|
4568
5146
|
if (!flush.ok) return flush;
|
|
4569
|
-
const
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
5147
|
+
const refusalOf = (raw) => `Binding.Local: '${raw}' is not a value this field accepts`;
|
|
5148
|
+
const identityParse = (raw) => {
|
|
5149
|
+
const asText = parseStatic(`${path}.parse`, { kind: "JString", value: raw });
|
|
5150
|
+
if (asText.ok) return { ok: true, value: asText.value };
|
|
5151
|
+
const scalar = scalarOfText(raw);
|
|
5152
|
+
if (scalar === void 0) return { ok: false, error: refusalOf(raw) };
|
|
5153
|
+
const asScalar = parseStatic(
|
|
5154
|
+
`${path}.parse`,
|
|
5155
|
+
typeof scalar === "number" ? { kind: "JNumber", value: scalar } : { kind: "JBool", value: scalar }
|
|
5156
|
+
);
|
|
5157
|
+
return asScalar.ok ? { ok: true, value: asScalar.value } : { ok: false, error: refusalOf(raw) };
|
|
4577
5158
|
};
|
|
5159
|
+
const decimals = codec !== void 0 && codec.kind === "Number" ? codec.decimals : void 0;
|
|
5160
|
+
const codecParse = (raw) => {
|
|
5161
|
+
const n = tryNumberText(raw);
|
|
5162
|
+
if (n === void 0) return { ok: false, error: refusalOf(raw) };
|
|
5163
|
+
const parsed = parseStatic(`${path}.parse`, { kind: "JNumber", value: n });
|
|
5164
|
+
return parsed.ok ? { ok: true, value: parsed.value } : { ok: false, error: refusalOf(raw) };
|
|
5165
|
+
};
|
|
5166
|
+
const local = {
|
|
5167
|
+
initialFrom: initial.value,
|
|
5168
|
+
flushOn: flush.value,
|
|
5169
|
+
format: codec !== void 0 ? (v) => numberText(decimals, v) : (v) => identityFormat(v),
|
|
5170
|
+
parse: codec !== void 0 ? codecParse : identityParse,
|
|
5171
|
+
...onCommitPresent ? { onCommit: () => void 0 } : {},
|
|
5172
|
+
...codec !== void 0 ? { codec } : {},
|
|
5173
|
+
...commitTo !== void 0 ? { commitTo } : {}
|
|
5174
|
+
};
|
|
5175
|
+
const b = { kind: "Local", local };
|
|
4578
5176
|
return ok(b);
|
|
4579
5177
|
}
|
|
4580
5178
|
case "Format": {
|
|
@@ -4646,52 +5244,9 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4646
5244
|
}
|
|
4647
5245
|
const pipe = decodePipelineCore(pipeJ.value);
|
|
4648
5246
|
if (!pipe.ok) return makeError("WRONG_TYPE", `${path}.pipeline`, pipe.error);
|
|
4649
|
-
const
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
const entries = [...paramsField.fields.entries()].sort(
|
|
4653
|
-
([a], [b2]) => a < b2 ? -1 : a > b2 ? 1 : 0
|
|
4654
|
-
);
|
|
4655
|
-
const out = [];
|
|
4656
|
-
let coerceErr;
|
|
4657
|
-
for (const [name, v] of entries) {
|
|
4658
|
-
const from = decodeBinding(`${path}.params.${name}.from`, v);
|
|
4659
|
-
if (!from.ok) {
|
|
4660
|
-
coerceErr = from;
|
|
4661
|
-
break;
|
|
4662
|
-
}
|
|
4663
|
-
out.push({ name, from: from.value });
|
|
4664
|
-
}
|
|
4665
|
-
if (coerceErr !== void 0) return coerceErr;
|
|
4666
|
-
params = out;
|
|
4667
|
-
} else if (paramsField !== void 0) {
|
|
4668
|
-
const arr = requireArray(`${path}.params`, paramsField);
|
|
4669
|
-
if (!arr.ok) return arr;
|
|
4670
|
-
const decoded = traverseIndexed(arr.value, (_i, el) => {
|
|
4671
|
-
const po = requireObject(`${path}.params[]`, el);
|
|
4672
|
-
if (!po.ok) return po;
|
|
4673
|
-
const name = reqField(
|
|
4674
|
-
`${path}.params[]`,
|
|
4675
|
-
po.value,
|
|
4676
|
-
"name",
|
|
4677
|
-
"param name string",
|
|
4678
|
-
requireString
|
|
4679
|
-
);
|
|
4680
|
-
if (!name.ok) return name;
|
|
4681
|
-
const from = reqFieldAliased(
|
|
4682
|
-
`${path}.params[]`,
|
|
4683
|
-
po.value,
|
|
4684
|
-
"from",
|
|
4685
|
-
["value"],
|
|
4686
|
-
"param source Binding",
|
|
4687
|
-
decodeBinding
|
|
4688
|
-
);
|
|
4689
|
-
if (!from.ok) return from;
|
|
4690
|
-
return ok({ name: name.value, from: from.value });
|
|
4691
|
-
});
|
|
4692
|
-
if (!decoded.ok) return decoded;
|
|
4693
|
-
params = decoded.value;
|
|
4694
|
-
}
|
|
5247
|
+
const paramsR = decodeExprParams(path, f);
|
|
5248
|
+
if (!paramsR.ok) return paramsR;
|
|
5249
|
+
const params = paramsR.value;
|
|
4695
5250
|
const b = {
|
|
4696
5251
|
kind: "Transform",
|
|
4697
5252
|
source,
|
|
@@ -4700,6 +5255,47 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4700
5255
|
};
|
|
4701
5256
|
return ok(b);
|
|
4702
5257
|
}
|
|
5258
|
+
case "Expr": {
|
|
5259
|
+
const exprJ = requireField(path, f, "expr", "ColExpr object");
|
|
5260
|
+
if (!exprJ.ok) return exprJ;
|
|
5261
|
+
const expr = decodeColExprCore(exprJ.value);
|
|
5262
|
+
if (!expr.ok) return makeError("WRONG_TYPE", `${path}.expr`, expr.error);
|
|
5263
|
+
const verdict = exprAdmissible(expr.value);
|
|
5264
|
+
if (verdict === "col") {
|
|
5265
|
+
return makeError(
|
|
5266
|
+
"WRONG_TYPE",
|
|
5267
|
+
`${path}.expr`,
|
|
5268
|
+
"a `col` reference is not admitted inside an Expr binding \u2014 an Expr evaluates against its params alone and has no row for a column name to read. Use `Binding.Transform`, whose source supplies the frame, and put the column expression in a `derive` step",
|
|
5269
|
+
"a ColExpr over `param` / `lit` / operators only (no `col`)"
|
|
5270
|
+
);
|
|
5271
|
+
}
|
|
5272
|
+
if (verdict === "limit") {
|
|
5273
|
+
return makeError(
|
|
5274
|
+
"LIMIT_EXCEEDED",
|
|
5275
|
+
`${path}.expr`,
|
|
5276
|
+
`expression exceeds the maximum of ${MAX_EXPR_NODES} expression nodes (WIRE_FORMAT 21)`,
|
|
5277
|
+
`at most ${MAX_EXPR_NODES} ColExpr nodes in one Expr binding`
|
|
5278
|
+
);
|
|
5279
|
+
}
|
|
5280
|
+
const exprParams = decodeExprParams(path, f);
|
|
5281
|
+
if (!exprParams.ok) return exprParams;
|
|
5282
|
+
const bound = new Set((exprParams.value ?? []).map((p) => p.name));
|
|
5283
|
+
const missing = colExprParamNames(expr.value).filter((n) => !bound.has(n));
|
|
5284
|
+
if (missing.length > 0) {
|
|
5285
|
+
return makeError(
|
|
5286
|
+
"WRONG_TYPE",
|
|
5287
|
+
`${path}.expr`,
|
|
5288
|
+
`the expression reads param(s) ${missing.map((n) => `'${n}'`).join(", ")} that this binding's \`params\` does not bind \u2014 an Expr has no rows and no filter to prune, so an unbound param has no value to take; add a params entry naming each, or drop the reference`,
|
|
5289
|
+
'{"$type":"Expr","expr":{\u2026},"params":[{"name":"<name>","from":<Binding>}]}'
|
|
5290
|
+
);
|
|
5291
|
+
}
|
|
5292
|
+
const b = {
|
|
5293
|
+
kind: "Expr",
|
|
5294
|
+
expr: expr.value,
|
|
5295
|
+
...exprParams.value !== void 0 ? { params: exprParams.value } : {}
|
|
5296
|
+
};
|
|
5297
|
+
return ok(b);
|
|
5298
|
+
}
|
|
4703
5299
|
case "Invoke": {
|
|
4704
5300
|
const cid = reqField(path, f, "capabilityId", "capability id string", requireString);
|
|
4705
5301
|
if (!cid.ok) return cid;
|
|
@@ -5043,10 +5639,14 @@ var decodeAction = (path, j) => {
|
|
|
5043
5639
|
f,
|
|
5044
5640
|
"route",
|
|
5045
5641
|
["href", "url", "to"],
|
|
5046
|
-
"route
|
|
5047
|
-
|
|
5642
|
+
"route TextSource",
|
|
5643
|
+
decodeTextSource
|
|
5048
5644
|
);
|
|
5049
|
-
|
|
5645
|
+
if (!r.ok) return r;
|
|
5646
|
+
const targetJ = tryField(f, "target");
|
|
5647
|
+
const target = targetJ === void 0 ? ok("Self") : decodeNavigateTarget(`${path}.target`, targetJ);
|
|
5648
|
+
if (!target.ok) return target;
|
|
5649
|
+
return ok({ kind: "Navigate", route: r.value, target: target.value });
|
|
5050
5650
|
}
|
|
5051
5651
|
case "SetState": {
|
|
5052
5652
|
const key = reqField(path, f, "key", "state key string", requireString);
|
|
@@ -5116,6 +5716,51 @@ var decodeAction = (path, j) => {
|
|
|
5116
5716
|
}
|
|
5117
5717
|
return ok({ kind: "Print" });
|
|
5118
5718
|
}
|
|
5719
|
+
case "Confirm": {
|
|
5720
|
+
const nestedConfirmPath = (p, a) => {
|
|
5721
|
+
if (a.kind === "Confirm") return p;
|
|
5722
|
+
if (a.kind === "Chain") {
|
|
5723
|
+
for (let i = 0; i < a.actions.length; i++) {
|
|
5724
|
+
const found = nestedConfirmPath(`${p}.ops[${i}]`, a.actions[i]);
|
|
5725
|
+
if (found !== void 0) return found;
|
|
5726
|
+
}
|
|
5727
|
+
}
|
|
5728
|
+
return void 0;
|
|
5729
|
+
};
|
|
5730
|
+
const prompt = reqField(path, f, "prompt", "confirm prompt TextSource", decodeTextSource);
|
|
5731
|
+
if (!prompt.ok) return prompt;
|
|
5732
|
+
const confirmJ = requireField(path, f, "onConfirm", "Action to dispatch on acceptance");
|
|
5733
|
+
if (!confirmJ.ok) return confirmJ;
|
|
5734
|
+
const onConfirm = decodeAction(`${path}.onConfirm`, confirmJ.value);
|
|
5735
|
+
if (!onConfirm.ok) return onConfirm;
|
|
5736
|
+
const nestedInConfirm = nestedConfirmPath(`${path}.onConfirm`, onConfirm.value);
|
|
5737
|
+
if (nestedInConfirm !== void 0)
|
|
5738
|
+
return wrongType(
|
|
5739
|
+
nestedInConfirm,
|
|
5740
|
+
"any action but Confirm \u2014 confirmation is bounded at one question (WIRE_FORMAT.md \xA73.6.22)"
|
|
5741
|
+
);
|
|
5742
|
+
const cancelJ = f.get("onCancel");
|
|
5743
|
+
if (cancelJ === void 0)
|
|
5744
|
+
return ok({ kind: "Confirm", prompt: prompt.value, onConfirm: onConfirm.value });
|
|
5745
|
+
const onCancel = decodeAction(`${path}.onCancel`, cancelJ);
|
|
5746
|
+
if (!onCancel.ok) return onCancel;
|
|
5747
|
+
const nestedInCancel = nestedConfirmPath(`${path}.onCancel`, onCancel.value);
|
|
5748
|
+
if (nestedInCancel !== void 0)
|
|
5749
|
+
return wrongType(
|
|
5750
|
+
nestedInCancel,
|
|
5751
|
+
"any action but Confirm \u2014 confirmation is bounded at one question (WIRE_FORMAT.md \xA73.6.22)"
|
|
5752
|
+
);
|
|
5753
|
+
return ok({
|
|
5754
|
+
kind: "Confirm",
|
|
5755
|
+
prompt: prompt.value,
|
|
5756
|
+
onConfirm: onConfirm.value,
|
|
5757
|
+
onCancel: onCancel.value
|
|
5758
|
+
});
|
|
5759
|
+
}
|
|
5760
|
+
case "Focus": {
|
|
5761
|
+
const r = reqField(path, f, "nodeId", "NodeId string of the node to focus", requireString);
|
|
5762
|
+
return r.ok ? ok({ kind: "Focus", nodeId: r.value }) : r;
|
|
5763
|
+
}
|
|
5119
5764
|
case "ReadFileBody": {
|
|
5120
5765
|
const fileId = reqField(path, f, "fileRef", "FileRef id string", requireString);
|
|
5121
5766
|
if (!fileId.ok) return fileId;
|
|
@@ -7103,6 +7748,18 @@ var decodeChartSpec = (path, j) => {
|
|
|
7103
7748
|
if (!dataLabels.ok) return dataLabels;
|
|
7104
7749
|
const xScale = optField(path, f, "xScale", decodeChartXScale);
|
|
7105
7750
|
if (!xScale.ok) return xScale;
|
|
7751
|
+
const annotationsJ = tryField(f, "annotations");
|
|
7752
|
+
let annotations;
|
|
7753
|
+
if (annotationsJ !== void 0) {
|
|
7754
|
+
const arr2 = requireArray(`${path}.annotations`, annotationsJ);
|
|
7755
|
+
if (!arr2.ok) return arr2;
|
|
7756
|
+
const decoded = traverseIndexed(
|
|
7757
|
+
arr2.value,
|
|
7758
|
+
(i, item) => decodeChartAnnotation(`${path}.annotations[${i}]`, item)
|
|
7759
|
+
);
|
|
7760
|
+
if (!decoded.ok) return decoded;
|
|
7761
|
+
annotations = decoded.value;
|
|
7762
|
+
}
|
|
7106
7763
|
const hasPointClick = tryField(f, "onPointClick") !== void 0;
|
|
7107
7764
|
const stacked = optField(path, f, "stacked", requireBool);
|
|
7108
7765
|
if (!stacked.ok) return stacked;
|
|
@@ -7120,6 +7777,7 @@ var decodeChartSpec = (path, j) => {
|
|
|
7120
7777
|
...legendPosition.value !== void 0 ? { legendPosition: legendPosition.value } : {},
|
|
7121
7778
|
...dataLabels.value !== void 0 ? { dataLabels: dataLabels.value } : {},
|
|
7122
7779
|
...xScale.value !== void 0 ? { xScale: xScale.value } : {},
|
|
7780
|
+
...annotations !== void 0 ? { annotations } : {},
|
|
7123
7781
|
...hasPointClick ? { onPointClick: () => placeholderAction } : {}
|
|
7124
7782
|
});
|
|
7125
7783
|
};
|
|
@@ -7818,11 +8476,29 @@ var decodeNodeKind = (path, j) => {
|
|
|
7818
8476
|
const cp = `${path}.cases[${i}]`;
|
|
7819
8477
|
const co = requireObject(cp, item);
|
|
7820
8478
|
if (!co.ok) return co;
|
|
7821
|
-
const
|
|
7822
|
-
|
|
8479
|
+
const mJ = tryField(co.value, "match");
|
|
8480
|
+
const wJ = tryField(co.value, "when");
|
|
8481
|
+
if (mJ !== void 0 && wJ !== void 0)
|
|
8482
|
+
return wrongType(
|
|
8483
|
+
`${cp}.when`,
|
|
8484
|
+
"either 'match' (a literal string compared against the switch's `on` selector) or 'when' (a Binding<bool> predicate evaluated at render time, needing no selector); remove one"
|
|
8485
|
+
);
|
|
8486
|
+
if (mJ === void 0 && wJ === void 0)
|
|
8487
|
+
return missingField(
|
|
8488
|
+
cp,
|
|
8489
|
+
"match",
|
|
8490
|
+
"a literal string under 'match' (compared against the switch's `on` selector), or a Binding<bool> under 'when' (a predicate evaluated at render time)"
|
|
8491
|
+
);
|
|
7823
8492
|
const c = reqField(cp, co.value, "child", "Switch case child Node", decodeNodeAst);
|
|
7824
8493
|
if (!c.ok) return c;
|
|
7825
|
-
|
|
8494
|
+
if (mJ !== void 0) {
|
|
8495
|
+
const m = requireString(`${cp}.match`, mJ);
|
|
8496
|
+
if (!m.ok) return m;
|
|
8497
|
+
return ok({ match: m.value, child: c.value });
|
|
8498
|
+
}
|
|
8499
|
+
const w = decodeBindingBool(`${cp}.when`, wJ);
|
|
8500
|
+
if (!w.ok) return w;
|
|
8501
|
+
return ok({ when: w.value, child: c.value });
|
|
7826
8502
|
});
|
|
7827
8503
|
if (!cases.ok) return cases;
|
|
7828
8504
|
const def = reqField(path, f, "default", "Switch default Node", decodeNodeAst);
|
|
@@ -8168,13 +8844,16 @@ var decodeNodeAstInner = (path, j) => {
|
|
|
8168
8844
|
if (!accessibility2.ok) return accessibility2;
|
|
8169
8845
|
const tooltip = optField(path, f, "tooltip", decodeTextSource);
|
|
8170
8846
|
if (!tooltip.ok) return tooltip;
|
|
8847
|
+
const visible = optField(path, f, "visible", decodeBindingBool);
|
|
8848
|
+
if (!visible.ok) return visible;
|
|
8171
8849
|
return ok({
|
|
8172
8850
|
id: idStr.value,
|
|
8173
8851
|
kind: kind.value,
|
|
8174
8852
|
state: state.value,
|
|
8175
8853
|
style: style.value,
|
|
8176
8854
|
...accessibility2.value !== void 0 ? { accessibility: accessibility2.value } : {},
|
|
8177
|
-
...tooltip.value !== void 0 ? { tooltip: tooltip.value } : {}
|
|
8855
|
+
...tooltip.value !== void 0 ? { tooltip: tooltip.value } : {},
|
|
8856
|
+
...visible.value !== void 0 ? { visible: visible.value } : {}
|
|
8178
8857
|
});
|
|
8179
8858
|
};
|
|
8180
8859
|
var decodeTreeOpAst = (path, j) => {
|
|
@@ -8383,10 +9062,238 @@ var decodeOp = (json, policy) => {
|
|
|
8383
9062
|
resetWalk(policy);
|
|
8384
9063
|
return decodeTreeOpAst("$", parsed.value);
|
|
8385
9064
|
};
|
|
9065
|
+
var decodeOps = (json, policy) => {
|
|
9066
|
+
const parsed = parse(json);
|
|
9067
|
+
if (!parsed.ok) return parseFailure(parsed.error);
|
|
9068
|
+
resetWalk(policy);
|
|
9069
|
+
const entries = parsed.value.kind === "JArray" ? parsed.value.items : [parsed.value];
|
|
9070
|
+
const ops = [];
|
|
9071
|
+
for (let i = 0; i < entries.length; i += 1) {
|
|
9072
|
+
const path = parsed.value.kind === "JArray" ? `$[${i}]` : "$";
|
|
9073
|
+
const decoded = decodeTreeOpAst(path, entries[i]);
|
|
9074
|
+
if (!decoded.ok) return decoded;
|
|
9075
|
+
ops.push(decoded.value);
|
|
9076
|
+
}
|
|
9077
|
+
return ok(ops);
|
|
9078
|
+
};
|
|
9079
|
+
|
|
9080
|
+
// src/capabilityDecl.ts
|
|
9081
|
+
var dok2 = (value) => ({ ok: true, value });
|
|
9082
|
+
var derr2 = (error) => ({ ok: false, error });
|
|
9083
|
+
var HOST_WIRE = {
|
|
9084
|
+
Pure: "pure",
|
|
9085
|
+
ReadsHost: "readsHost",
|
|
9086
|
+
WritesHost: "writesHost"
|
|
9087
|
+
};
|
|
9088
|
+
var DETERMINISM_WIRE = {
|
|
9089
|
+
Deterministic: "deterministic",
|
|
9090
|
+
Clock: "clock",
|
|
9091
|
+
Random: "random",
|
|
9092
|
+
Network: "network"
|
|
9093
|
+
};
|
|
9094
|
+
var PLACEMENT_WIRE = {
|
|
9095
|
+
BuildTime: "buildTime",
|
|
9096
|
+
Server: "server",
|
|
9097
|
+
ClientDeclarative: "clientDeclarative",
|
|
9098
|
+
ClientIsland: "clientIsland",
|
|
9099
|
+
Precomputed: "precomputed"
|
|
9100
|
+
};
|
|
9101
|
+
var SPACE_WIRE = {
|
|
9102
|
+
IntRange: "intRange",
|
|
9103
|
+
FloatRange: "floatRange",
|
|
9104
|
+
StringLen: "stringLen",
|
|
9105
|
+
Enum: "enum",
|
|
9106
|
+
AnyString: "anyString"
|
|
9107
|
+
};
|
|
9108
|
+
var ISLANDS = ["pyodide", "fable", "js"];
|
|
9109
|
+
var invert = (m) => Object.fromEntries(Object.entries(m).map(([k, v]) => [v, k]));
|
|
9110
|
+
var HOST_OF = invert(HOST_WIRE);
|
|
9111
|
+
var DETERMINISM_OF = invert(DETERMINISM_WIRE);
|
|
9112
|
+
var PLACEMENT_OF = invert(PLACEMENT_WIRE);
|
|
9113
|
+
var SPACE_OF = invert(SPACE_WIRE);
|
|
9114
|
+
var spaceJson = (s) => {
|
|
9115
|
+
switch (s.kind) {
|
|
9116
|
+
case "IntRange":
|
|
9117
|
+
return caseObj(SPACE_WIRE[s.kind], [
|
|
9118
|
+
["min", num(s.min)],
|
|
9119
|
+
["max", num(s.max)]
|
|
9120
|
+
]);
|
|
9121
|
+
case "FloatRange":
|
|
9122
|
+
return caseObj(SPACE_WIRE[s.kind], [
|
|
9123
|
+
["min", num(s.min)],
|
|
9124
|
+
["max", num(s.max)]
|
|
9125
|
+
]);
|
|
9126
|
+
case "StringLen":
|
|
9127
|
+
return caseObj(SPACE_WIRE[s.kind], [
|
|
9128
|
+
["min", num(s.minLen)],
|
|
9129
|
+
["max", num(s.maxLen)]
|
|
9130
|
+
]);
|
|
9131
|
+
case "Enum":
|
|
9132
|
+
return caseObj(SPACE_WIRE[s.kind], [["values", jArray(s.choices.map(str))]]);
|
|
9133
|
+
case "AnyString":
|
|
9134
|
+
return caseObj(SPACE_WIRE[s.kind], []);
|
|
9135
|
+
}
|
|
9136
|
+
};
|
|
9137
|
+
var entryJson = (e) => {
|
|
9138
|
+
const fields = [
|
|
9139
|
+
["addr", str(e.addr)],
|
|
9140
|
+
["name", str(e.name)],
|
|
9141
|
+
["kind", str(e.kind)],
|
|
9142
|
+
["required", bool(e.required)]
|
|
9143
|
+
];
|
|
9144
|
+
if (e.space !== void 0) fields.push(["space", spaceJson(e.space)]);
|
|
9145
|
+
if (e.slotKind !== void 0) fields.push(["slotKind", str(e.slotKind)]);
|
|
9146
|
+
return jObject(fields);
|
|
9147
|
+
};
|
|
9148
|
+
var placementJson = (p) => p.kind === "ClientIsland" ? caseObj(PLACEMENT_WIRE[p.kind], [["island", str(p.island)]]) : caseObj(PLACEMENT_WIRE[p.kind], []);
|
|
9149
|
+
var signatureJson = (sg) => jObject([
|
|
9150
|
+
["name", str(sg.name)],
|
|
9151
|
+
[
|
|
9152
|
+
"effect",
|
|
9153
|
+
jObject([
|
|
9154
|
+
["host", str(HOST_WIRE[sg.effect.hostEffect])],
|
|
9155
|
+
["determinism", str(DETERMINISM_WIRE[sg.effect.determinism])]
|
|
9156
|
+
])
|
|
9157
|
+
],
|
|
9158
|
+
["holes", jArray(sg.holes.map(entryJson))]
|
|
9159
|
+
]);
|
|
9160
|
+
var encodeCapabilityDeclaration = (cap) => caseObj("capability", [
|
|
9161
|
+
["id", str(cap.id)],
|
|
9162
|
+
["signature", signatureJson(cap.signature)],
|
|
9163
|
+
["determinism", str(DETERMINISM_WIRE[cap.determinism])],
|
|
9164
|
+
["placement", placementJson(cap.placement)]
|
|
9165
|
+
]);
|
|
9166
|
+
var DeclError = class extends Error {
|
|
9167
|
+
};
|
|
9168
|
+
var fail2 = (message) => {
|
|
9169
|
+
throw new DeclError(message);
|
|
9170
|
+
};
|
|
9171
|
+
var asObject = (v, what) => typeof v !== "object" || v === null || Array.isArray(v) ? fail2(`${what} is not an object`) : v;
|
|
9172
|
+
var strAt = (o, k) => {
|
|
9173
|
+
const v = o[k];
|
|
9174
|
+
return typeof v === "string" ? v : fail2(`missing or non-string field: ${k}`);
|
|
9175
|
+
};
|
|
9176
|
+
var numAt = (o, k) => {
|
|
9177
|
+
const v = o[k];
|
|
9178
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fail2(`missing or non-finite numeric field: ${k}`);
|
|
9179
|
+
};
|
|
9180
|
+
var spaceOf = (raw) => {
|
|
9181
|
+
const o = asObject(raw, "value-space");
|
|
9182
|
+
const tag = strAt(o, "$type");
|
|
9183
|
+
const kind = SPACE_OF[tag];
|
|
9184
|
+
switch (kind) {
|
|
9185
|
+
case "IntRange":
|
|
9186
|
+
return { kind, min: numAt(o, "min"), max: numAt(o, "max") };
|
|
9187
|
+
case "FloatRange":
|
|
9188
|
+
return { kind, min: numAt(o, "min"), max: numAt(o, "max") };
|
|
9189
|
+
case "StringLen":
|
|
9190
|
+
return { kind, minLen: numAt(o, "min"), maxLen: numAt(o, "max") };
|
|
9191
|
+
case "Enum": {
|
|
9192
|
+
const values = o["values"];
|
|
9193
|
+
if (!Array.isArray(values) || values.some((x) => typeof x !== "string"))
|
|
9194
|
+
fail2("enum values must be a string array");
|
|
9195
|
+
return { kind, choices: values };
|
|
9196
|
+
}
|
|
9197
|
+
case "AnyString":
|
|
9198
|
+
return { kind };
|
|
9199
|
+
default:
|
|
9200
|
+
return fail2(
|
|
9201
|
+
`unknown value-space kind: ${tag}; expected one of: ${Object.values(SPACE_WIRE).join(", ")}`
|
|
9202
|
+
);
|
|
9203
|
+
}
|
|
9204
|
+
};
|
|
9205
|
+
var entryOf = (raw) => {
|
|
9206
|
+
const o = asObject(raw, "signature hole");
|
|
9207
|
+
if ("actionEffect" in o) {
|
|
9208
|
+
fail2(
|
|
9209
|
+
"this host's signature entry carries no action-effect axis, so a hole declaring `actionEffect` cannot round-trip"
|
|
9210
|
+
);
|
|
9211
|
+
}
|
|
9212
|
+
const kind = strAt(o, "kind");
|
|
9213
|
+
if (kind !== "value" && kind !== "slot" && kind !== "repeat")
|
|
9214
|
+
fail2(`unknown hole kind: ${kind}; expected one of: value, slot, repeat`);
|
|
9215
|
+
const required = o["required"];
|
|
9216
|
+
if (typeof required !== "boolean") fail2("missing or non-boolean field: required");
|
|
9217
|
+
return {
|
|
9218
|
+
addr: strAt(o, "addr"),
|
|
9219
|
+
name: strAt(o, "name"),
|
|
9220
|
+
kind,
|
|
9221
|
+
required,
|
|
9222
|
+
..."space" in o ? { space: spaceOf(o["space"]) } : {},
|
|
9223
|
+
..."slotKind" in o ? { slotKind: strAt(o, "slotKind") } : {}
|
|
9224
|
+
};
|
|
9225
|
+
};
|
|
9226
|
+
var placementOf = (raw) => {
|
|
9227
|
+
const o = asObject(raw, "placement");
|
|
9228
|
+
const tag = strAt(o, "$type");
|
|
9229
|
+
const kind = PLACEMENT_OF[tag];
|
|
9230
|
+
if (kind === void 0)
|
|
9231
|
+
fail2(`unknown placement: ${tag}; expected one of: ${Object.values(PLACEMENT_WIRE).join(", ")}`);
|
|
9232
|
+
if (kind === "ClientIsland") {
|
|
9233
|
+
const island = strAt(o, "island");
|
|
9234
|
+
if (!ISLANDS.includes(island))
|
|
9235
|
+
fail2(`unknown island kind: ${island}; expected one of: ${ISLANDS.join(", ")}`);
|
|
9236
|
+
return { kind, island };
|
|
9237
|
+
}
|
|
9238
|
+
return { kind };
|
|
9239
|
+
};
|
|
9240
|
+
var declarationOf = (json) => {
|
|
9241
|
+
let parsed;
|
|
9242
|
+
try {
|
|
9243
|
+
parsed = JSON.parse(json);
|
|
9244
|
+
} catch {
|
|
9245
|
+
return fail2("capability declaration is not well-formed JSON");
|
|
9246
|
+
}
|
|
9247
|
+
const o = asObject(parsed, "capability declaration");
|
|
9248
|
+
const tag = o["$type"];
|
|
9249
|
+
if (tag !== void 0 && tag !== "capability")
|
|
9250
|
+
fail2(`not a capability declaration: $type '${String(tag)}'`);
|
|
9251
|
+
const sigObj = asObject(o["signature"], "signature");
|
|
9252
|
+
const effectObj = asObject(sigObj["effect"], "effect");
|
|
9253
|
+
const hostTag = strAt(effectObj, "host");
|
|
9254
|
+
const hostEffect = HOST_OF[hostTag];
|
|
9255
|
+
if (hostEffect === void 0)
|
|
9256
|
+
fail2(
|
|
9257
|
+
`unknown host effect: ${hostTag}; expected one of: ${Object.values(HOST_WIRE).join(", ")}`
|
|
9258
|
+
);
|
|
9259
|
+
const detTag = strAt(effectObj, "determinism");
|
|
9260
|
+
const determinism = DETERMINISM_OF[detTag];
|
|
9261
|
+
if (determinism === void 0)
|
|
9262
|
+
fail2(
|
|
9263
|
+
`unknown determinism: ${detTag}; expected one of: ${Object.values(DETERMINISM_WIRE).join(", ")}`
|
|
9264
|
+
);
|
|
9265
|
+
const holes = sigObj["holes"];
|
|
9266
|
+
if (!Array.isArray(holes)) fail2("missing or non-array field: holes");
|
|
9267
|
+
const signature = {
|
|
9268
|
+
name: strAt(sigObj, "name"),
|
|
9269
|
+
holes: holes.map(entryOf),
|
|
9270
|
+
effect: { hostEffect, determinism }
|
|
9271
|
+
};
|
|
9272
|
+
const wireTag = strAt(o, "determinism");
|
|
9273
|
+
const expectedTag = DETERMINISM_WIRE[determinism];
|
|
9274
|
+
if (wireTag !== expectedTag)
|
|
9275
|
+
fail2(
|
|
9276
|
+
`capability determinism disagrees with signature effect: wire '${wireTag}' vs signature '${expectedTag}'`
|
|
9277
|
+
);
|
|
9278
|
+
return {
|
|
9279
|
+
id: strAt(o, "id"),
|
|
9280
|
+
signature,
|
|
9281
|
+
determinism,
|
|
9282
|
+
placement: placementOf(o["placement"])
|
|
9283
|
+
};
|
|
9284
|
+
};
|
|
9285
|
+
var decodeCapabilityDeclaration = (json) => {
|
|
9286
|
+
try {
|
|
9287
|
+
return dok2(declarationOf(json));
|
|
9288
|
+
} catch (e) {
|
|
9289
|
+
if (e instanceof DeclError) return derr2(e.message);
|
|
9290
|
+
throw e;
|
|
9291
|
+
}
|
|
9292
|
+
};
|
|
8386
9293
|
|
|
8387
9294
|
// src/apply.ts
|
|
8388
9295
|
var ok2 = (value) => ({ ok: true, value });
|
|
8389
|
-
var
|
|
9296
|
+
var fail3 = (code, message, batchIndex) => ({
|
|
8390
9297
|
ok: false,
|
|
8391
9298
|
error: batchIndex === void 0 ? { code, message } : { code, message, batchIndex }
|
|
8392
9299
|
});
|
|
@@ -9223,22 +10130,22 @@ var applyOne = (op, root, telem) => {
|
|
|
9223
10130
|
case "EditNode": {
|
|
9224
10131
|
const updatedTree = mapNode(op.target, (n) => ({ ...n, kind: op.newKind }), root);
|
|
9225
10132
|
if (updatedTree === void 0)
|
|
9226
|
-
return
|
|
10133
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9227
10134
|
telem.push({ op: "EditNode", targetId: op.target });
|
|
9228
10135
|
return ok2(updatedTree);
|
|
9229
10136
|
}
|
|
9230
10137
|
case "UpdateProp": {
|
|
9231
10138
|
const parsed = parsePath(op.path);
|
|
9232
10139
|
if (!parsed.ok)
|
|
9233
|
-
return
|
|
10140
|
+
return fail3("PathInvalid", `Path '${op.path}' is structurally invalid: ${parsed.error}.`);
|
|
9234
10141
|
const targetNode = findNode(op.target, root);
|
|
9235
10142
|
if (targetNode === void 0)
|
|
9236
|
-
return
|
|
10143
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9237
10144
|
const segs = parsed.value;
|
|
9238
10145
|
const finish = (kind) => {
|
|
9239
10146
|
const newTree = mapNode(op.target, (n) => ({ ...n, kind }), root);
|
|
9240
10147
|
if (newTree === void 0)
|
|
9241
|
-
return
|
|
10148
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9242
10149
|
telem.push({ op: "UpdateProp", targetId: op.target });
|
|
9243
10150
|
return ok2(newTree);
|
|
9244
10151
|
};
|
|
@@ -9248,14 +10155,14 @@ var applyOne = (op, root, telem) => {
|
|
|
9248
10155
|
case "updated":
|
|
9249
10156
|
return finish(outcome2.kind);
|
|
9250
10157
|
case "unknownField":
|
|
9251
|
-
return
|
|
10158
|
+
return fail3("FieldNotFound", `Field '${op.path}' not found on node '${op.target}'.`);
|
|
9252
10159
|
case "notSupported":
|
|
9253
|
-
return
|
|
10160
|
+
return fail3(
|
|
9254
10161
|
"PathNotSupportedYet",
|
|
9255
10162
|
`Path '${op.path}' on node '${op.target}' is not yet supported by the apply engine.`
|
|
9256
10163
|
);
|
|
9257
10164
|
case "typeMismatch":
|
|
9258
|
-
return
|
|
10165
|
+
return fail3(
|
|
9259
10166
|
"KindMismatch",
|
|
9260
10167
|
`UpdateProp value for '${op.path}' on node '${op.target}' does not match the field's expected type: ${outcome2.detail}`
|
|
9261
10168
|
);
|
|
@@ -9267,27 +10174,27 @@ var applyOne = (op, root, telem) => {
|
|
|
9267
10174
|
case "updated":
|
|
9268
10175
|
return finish(outcome.kind);
|
|
9269
10176
|
case "missingIndex":
|
|
9270
|
-
return
|
|
10177
|
+
return fail3(
|
|
9271
10178
|
"PathInvalid",
|
|
9272
10179
|
`Field '${outcome.listField}' on node '${op.target}' is a list \u2014 address an element with a 0-based index (the list has ${outcome.count} element(s)).`
|
|
9273
10180
|
);
|
|
9274
10181
|
case "indexOutOfRange":
|
|
9275
|
-
return
|
|
10182
|
+
return fail3(
|
|
9276
10183
|
"PositionOutOfRange",
|
|
9277
10184
|
`Index ${outcome.requested} is out of range for '${outcome.listField}' on node '${op.target}' (${outcome.count === 0 ? "the list is empty" : `valid: 0..${outcome.count - 1}`}).`
|
|
9278
10185
|
);
|
|
9279
10186
|
case "fieldNotFound":
|
|
9280
|
-
return
|
|
10187
|
+
return fail3(
|
|
9281
10188
|
"FieldNotFound",
|
|
9282
10189
|
`Field '${outcome.segment}' (in path '${op.path}') not found on node '${op.target}'. Available at this segment: ${outcome.available.join(", ")}.`
|
|
9283
10190
|
);
|
|
9284
10191
|
case "notSupported":
|
|
9285
|
-
return
|
|
10192
|
+
return fail3(
|
|
9286
10193
|
"PathNotSupportedYet",
|
|
9287
10194
|
`Path '${op.path}' on node '${op.target}' is not yet supported by the apply engine.`
|
|
9288
10195
|
);
|
|
9289
10196
|
case "typeMismatch":
|
|
9290
|
-
return
|
|
10197
|
+
return fail3(
|
|
9291
10198
|
"KindMismatch",
|
|
9292
10199
|
`UpdateProp value for '${op.path}' on node '${op.target}' does not match the field's expected type: ${outcome.detail}`
|
|
9293
10200
|
);
|
|
@@ -9297,20 +10204,20 @@ var applyOne = (op, root, telem) => {
|
|
|
9297
10204
|
case "ReplaceBinding": {
|
|
9298
10205
|
const targetNode = findNode(op.target, root);
|
|
9299
10206
|
if (targetNode === void 0)
|
|
9300
|
-
return
|
|
10207
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9301
10208
|
const newKind = replaceBinding(op.slot, op.binding, targetNode.kind);
|
|
9302
10209
|
if (newKind === void 0)
|
|
9303
|
-
return
|
|
10210
|
+
return fail3("SlotNotFound", `Binding slot '${op.slot}' not found on node '${op.target}'.`);
|
|
9304
10211
|
const newTree = mapNode(op.target, (n) => ({ ...n, kind: newKind }), root);
|
|
9305
10212
|
if (newTree === void 0)
|
|
9306
|
-
return
|
|
10213
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9307
10214
|
telem.push({ op: "ReplaceBinding", targetId: op.target });
|
|
9308
10215
|
return ok2(newTree);
|
|
9309
10216
|
}
|
|
9310
10217
|
case "UpdateStyle": {
|
|
9311
10218
|
const newTree = mapNode(op.target, (n) => ({ ...n, style: op.style }), root);
|
|
9312
10219
|
if (newTree === void 0)
|
|
9313
|
-
return
|
|
10220
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9314
10221
|
telem.push({ op: "UpdateStyle", targetId: op.target });
|
|
9315
10222
|
return ok2(newTree);
|
|
9316
10223
|
}
|
|
@@ -9321,39 +10228,39 @@ var applyOne = (op, root, telem) => {
|
|
|
9321
10228
|
root
|
|
9322
10229
|
);
|
|
9323
10230
|
if (newTree === void 0)
|
|
9324
|
-
return
|
|
10231
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9325
10232
|
telem.push({ op: "UpdateState", targetId: op.target });
|
|
9326
10233
|
return ok2(newTree);
|
|
9327
10234
|
}
|
|
9328
10235
|
case "InsertChild": {
|
|
9329
10236
|
const parent = findNode(op.parentId, root);
|
|
9330
10237
|
if (parent === void 0)
|
|
9331
|
-
return
|
|
10238
|
+
return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
|
|
9332
10239
|
const children = layoutChildren(parent);
|
|
9333
10240
|
if (children === void 0)
|
|
9334
|
-
return
|
|
10241
|
+
return fail3(
|
|
9335
10242
|
"ChildlessKind",
|
|
9336
10243
|
`Node '${op.parentId}' (kind=${parent.kind.kind}) has no children field \u2014 only Layout kinds accept structural child ops.`
|
|
9337
10244
|
);
|
|
9338
10245
|
const existing = new Set(allNodeIds(root));
|
|
9339
10246
|
const duplicate = allNodeIds(op.child).find((id) => existing.has(id));
|
|
9340
10247
|
if (duplicate !== void 0)
|
|
9341
|
-
return
|
|
10248
|
+
return fail3(
|
|
9342
10249
|
"DuplicateNodeId",
|
|
9343
10250
|
`NodeId '${duplicate}' is already present in the tree; ids must be unique.`
|
|
9344
10251
|
);
|
|
9345
10252
|
const newChildren = [...children, op.child];
|
|
9346
10253
|
const newTree = mapNode(op.parentId, (n) => withLayoutChildren(n, newChildren), root);
|
|
9347
10254
|
if (newTree === void 0)
|
|
9348
|
-
return
|
|
10255
|
+
return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
|
|
9349
10256
|
telem.push({ op: "InsertChild", targetId: op.parentId });
|
|
9350
10257
|
return ok2(newTree);
|
|
9351
10258
|
}
|
|
9352
10259
|
case "RemoveNode": {
|
|
9353
|
-
if (idOf(root) === op.target) return
|
|
10260
|
+
if (idOf(root) === op.target) return fail3("KindMismatch", "Cannot RemoveNode the root.");
|
|
9354
10261
|
const parent = findLayoutParent(op.target, root);
|
|
9355
10262
|
if (parent === void 0)
|
|
9356
|
-
return
|
|
10263
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9357
10264
|
const children = layoutChildren(parent);
|
|
9358
10265
|
const newTree = mapNode(
|
|
9359
10266
|
idOf(parent),
|
|
@@ -9364,26 +10271,26 @@ var applyOne = (op, root, telem) => {
|
|
|
9364
10271
|
root
|
|
9365
10272
|
);
|
|
9366
10273
|
if (newTree === void 0)
|
|
9367
|
-
return
|
|
10274
|
+
return fail3("ParentNotFound", `Parent node '${idOf(parent)}' not found in tree.`);
|
|
9368
10275
|
telem.push({ op: "RemoveNode", targetId: op.target });
|
|
9369
10276
|
return ok2(newTree);
|
|
9370
10277
|
}
|
|
9371
10278
|
case "MoveNode": {
|
|
9372
10279
|
if (op.target === op.newParentId)
|
|
9373
|
-
return
|
|
10280
|
+
return fail3("KindMismatch", "Cannot move a node into itself.");
|
|
9374
10281
|
if (isAncestor(op.target, op.newParentId, root))
|
|
9375
|
-
return
|
|
10282
|
+
return fail3(
|
|
9376
10283
|
"KindMismatch",
|
|
9377
10284
|
"Cannot move a node into its own descendant (would create a cycle)."
|
|
9378
10285
|
);
|
|
9379
10286
|
const moving = findNode(op.target, root);
|
|
9380
10287
|
if (moving === void 0)
|
|
9381
|
-
return
|
|
10288
|
+
return fail3("NodeNotFound", `Node '${op.target}' not found in tree.`);
|
|
9382
10289
|
const newParent = findNode(op.newParentId, root);
|
|
9383
10290
|
if (newParent === void 0)
|
|
9384
|
-
return
|
|
10291
|
+
return fail3("ParentNotFound", `Parent node '${op.newParentId}' not found in tree.`);
|
|
9385
10292
|
if (layoutChildren(newParent) === void 0)
|
|
9386
|
-
return
|
|
10293
|
+
return fail3(
|
|
9387
10294
|
"ChildlessKind",
|
|
9388
10295
|
`Node '${op.newParentId}' (kind=${newParent.kind.kind}) has no children field.`
|
|
9389
10296
|
);
|
|
@@ -9401,10 +10308,10 @@ var applyOne = (op, root, telem) => {
|
|
|
9401
10308
|
case "ReorderChildren": {
|
|
9402
10309
|
const parent = findNode(op.parentId, root);
|
|
9403
10310
|
if (parent === void 0)
|
|
9404
|
-
return
|
|
10311
|
+
return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
|
|
9405
10312
|
const children = layoutChildren(parent);
|
|
9406
10313
|
if (children === void 0)
|
|
9407
|
-
return
|
|
10314
|
+
return fail3(
|
|
9408
10315
|
"ChildlessKind",
|
|
9409
10316
|
`Node '${op.parentId}' (kind=${parent.kind.kind}) has no children field.`
|
|
9410
10317
|
);
|
|
@@ -9412,7 +10319,7 @@ var applyOne = (op, root, telem) => {
|
|
|
9412
10319
|
const sortedCurrent = [...currentIds].sort();
|
|
9413
10320
|
const sortedNew = [...op.newOrder].map((x) => x).sort();
|
|
9414
10321
|
if (sortedCurrent.length !== sortedNew.length || sortedCurrent.some((id, i) => id !== sortedNew[i]))
|
|
9415
|
-
return
|
|
10322
|
+
return fail3(
|
|
9416
10323
|
"OrderingMismatch",
|
|
9417
10324
|
`ReorderChildren for '${op.parentId}' did not list exactly the current child ids.`
|
|
9418
10325
|
);
|
|
@@ -9420,7 +10327,7 @@ var applyOne = (op, root, telem) => {
|
|
|
9420
10327
|
const reordered = op.newOrder.map((id) => byId.get(id)).filter((c) => c !== void 0);
|
|
9421
10328
|
const newTree = mapNode(op.parentId, (n) => withLayoutChildren(n, reordered), root);
|
|
9422
10329
|
if (newTree === void 0)
|
|
9423
|
-
return
|
|
10330
|
+
return fail3("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
|
|
9424
10331
|
telem.push({ op: "ReorderChildren", targetId: op.parentId });
|
|
9425
10332
|
return ok2(newTree);
|
|
9426
10333
|
}
|
|
@@ -9445,7 +10352,7 @@ var applyOne = (op, root, telem) => {
|
|
|
9445
10352
|
return ok2(state);
|
|
9446
10353
|
}
|
|
9447
10354
|
}
|
|
9448
|
-
return
|
|
10355
|
+
return fail3("KindMismatch", "unreachable apply branch");
|
|
9449
10356
|
};
|
|
9450
10357
|
var apply = (tree, op) => {
|
|
9451
10358
|
const telem = [];
|
|
@@ -9768,11 +10675,20 @@ var isPureAddition = (baseIds, headIds) => {
|
|
|
9768
10675
|
return survive.length === baseIds.length && survive.every((v, i) => v === baseIds[i]) && headKept.length === baseIds.length && headKept.every((v, i) => v === baseIds[i]);
|
|
9769
10676
|
};
|
|
9770
10677
|
var eqOpt = (x, y) => (x ?? null) === (y ?? null);
|
|
9771
|
-
var
|
|
10678
|
+
var refusal = (nodeId, facet, cls, base, aValue, bValue) => ({
|
|
10679
|
+
nodeId,
|
|
10680
|
+
facet,
|
|
10681
|
+
class: cls,
|
|
10682
|
+
base,
|
|
10683
|
+
a: { value: aValue },
|
|
10684
|
+
b: { value: bValue },
|
|
10685
|
+
primacyHeld: false
|
|
10686
|
+
});
|
|
10687
|
+
var pickField = (conflicts, nodeId, facet, dflt, baseV, aV, bV) => {
|
|
9772
10688
|
const aCh = !eqOpt(aV, baseV);
|
|
9773
10689
|
const bCh = !eqOpt(bV, baseV);
|
|
9774
10690
|
if (aCh && bCh && !eqOpt(aV, bV)) {
|
|
9775
|
-
conflicts.push(
|
|
10691
|
+
conflicts.push(refusal(nodeId, facet, "ConcurrentEdit", baseV ?? dflt, aV ?? dflt, bV ?? dflt));
|
|
9776
10692
|
return baseV;
|
|
9777
10693
|
}
|
|
9778
10694
|
if (aCh) return aV;
|
|
@@ -9783,7 +10699,7 @@ var pickCanonical = (conflicts, nodeId, facet, baseC, aC, bC) => {
|
|
|
9783
10699
|
const aCh = aC !== baseC;
|
|
9784
10700
|
const bCh = bC !== baseC;
|
|
9785
10701
|
if (aCh && bCh && aC !== bC) {
|
|
9786
|
-
conflicts.push(
|
|
10702
|
+
conflicts.push(refusal(nodeId, facet, "ConcurrentEdit", baseC, aC, bC));
|
|
9787
10703
|
return 0;
|
|
9788
10704
|
}
|
|
9789
10705
|
if (aCh) return 1;
|
|
@@ -9794,18 +10710,28 @@ var mergeStyle = (conflicts, id, base, a, b) => {
|
|
|
9794
10710
|
const bs = base.style;
|
|
9795
10711
|
const as_ = a.style;
|
|
9796
10712
|
const bsB = b.style;
|
|
9797
|
-
const
|
|
9798
|
-
const
|
|
10713
|
+
const d = defaults.style;
|
|
10714
|
+
const tone = pickField(conflicts, id, "style.tone", d.tone, bs.tone, as_.tone, bsB.tone);
|
|
10715
|
+
const weight = pickField(
|
|
10716
|
+
conflicts,
|
|
10717
|
+
id,
|
|
10718
|
+
"style.weight",
|
|
10719
|
+
d.weight,
|
|
10720
|
+
bs.weight,
|
|
10721
|
+
as_.weight,
|
|
10722
|
+
bsB.weight
|
|
10723
|
+
);
|
|
9799
10724
|
const emphasis = pickField(
|
|
9800
10725
|
conflicts,
|
|
9801
10726
|
id,
|
|
9802
10727
|
"style.emphasis",
|
|
10728
|
+
d.emphasis,
|
|
9803
10729
|
bs.emphasis,
|
|
9804
10730
|
as_.emphasis,
|
|
9805
10731
|
bsB.emphasis
|
|
9806
10732
|
);
|
|
9807
|
-
const role = pickField(conflicts, id, "style.role", bs.role, as_.role, bsB.role);
|
|
9808
|
-
const voice = pickField(conflicts, id, "style.voice", bs.voice, as_.voice, bsB.voice);
|
|
10733
|
+
const role = pickField(conflicts, id, "style.role", d.role, bs.role, as_.role, bsB.role);
|
|
10734
|
+
const voice = pickField(conflicts, id, "style.voice", d.voice, bs.voice, as_.voice, bsB.voice);
|
|
9809
10735
|
const style = { tone, weight, emphasis };
|
|
9810
10736
|
return {
|
|
9811
10737
|
...style,
|
|
@@ -9861,8 +10787,15 @@ var merge3 = (conflicts, base, aOpt, bOpt) => {
|
|
|
9861
10787
|
const bc = baseMap.get(cid);
|
|
9862
10788
|
if (bc !== void 0) return merge3(conflicts, bc, aMap.get(cid), bMap.get(cid));
|
|
9863
10789
|
const ac = aMap.get(cid);
|
|
9864
|
-
if (ac !== void 0) return ac;
|
|
9865
10790
|
const bb = bMap.get(cid);
|
|
10791
|
+
if (ac !== void 0 && bb !== void 0) {
|
|
10792
|
+
const acC = encodeNode(ac);
|
|
10793
|
+
const bcC = encodeNode(bb);
|
|
10794
|
+
if (acC === bcC) return ac;
|
|
10795
|
+
conflicts.push(refusal(cid, "insert", "ConcurrentEdit", "", acC, bcC));
|
|
10796
|
+
return ordinal(acC, bcC) <= 0 ? ac : bb;
|
|
10797
|
+
}
|
|
10798
|
+
if (ac !== void 0) return ac;
|
|
9866
10799
|
if (bb !== void 0) return bb;
|
|
9867
10800
|
throw new Error(`merge3: child id ${cid} vanished`);
|
|
9868
10801
|
};
|
|
@@ -9873,6 +10806,8 @@ var merge3 = (conflicts, base, aOpt, bOpt) => {
|
|
|
9873
10806
|
mergedChildren = aIds.map(recurseChild);
|
|
9874
10807
|
} else if (!aStruct && bStruct) {
|
|
9875
10808
|
mergedChildren = bIds.map(recurseChild);
|
|
10809
|
+
} else if (JSON.stringify(aIds) === JSON.stringify(bIds)) {
|
|
10810
|
+
mergedChildren = aIds.map(recurseChild);
|
|
9876
10811
|
} else {
|
|
9877
10812
|
const baseSet = new Set(baseIds);
|
|
9878
10813
|
const aNew = aIds.filter((i) => !baseSet.has(i));
|
|
@@ -9884,7 +10819,16 @@ var merge3 = (conflicts, base, aOpt, bOpt) => {
|
|
|
9884
10819
|
const newIds = [.../* @__PURE__ */ new Set([...aNew, ...bNew])].sort(ordinal);
|
|
9885
10820
|
mergedChildren = [...survivors, ...newIds.map(recurseChild)];
|
|
9886
10821
|
} else {
|
|
9887
|
-
conflicts.push(
|
|
10822
|
+
conflicts.push(
|
|
10823
|
+
refusal(
|
|
10824
|
+
id,
|
|
10825
|
+
"children",
|
|
10826
|
+
"ReorderVsStructural",
|
|
10827
|
+
baseIds.join(","),
|
|
10828
|
+
aIds.join(","),
|
|
10829
|
+
bIds.join(",")
|
|
10830
|
+
)
|
|
10831
|
+
);
|
|
9888
10832
|
mergedChildren = baseIds.map(recurseChild);
|
|
9889
10833
|
}
|
|
9890
10834
|
}
|
|
@@ -9896,6 +10840,21 @@ var merge3Way = (base, a, b) => {
|
|
|
9896
10840
|
const merged = merge3(conflicts, base, a, b);
|
|
9897
10841
|
return conflicts.length === 0 ? { ok: true, tree: merged } : { ok: false, conflicts };
|
|
9898
10842
|
};
|
|
10843
|
+
var sortConflictsCanonical = (conflicts) => [...conflicts].sort((x, y) => ordinal(x.nodeId, y.nodeId) || ordinal(x.facet, y.facet));
|
|
10844
|
+
var escapeJson = (s) => {
|
|
10845
|
+
let out = '"';
|
|
10846
|
+
for (const ch of s) {
|
|
10847
|
+
if (ch === '"') out += '\\"';
|
|
10848
|
+
else if (ch === "\\") out += "\\\\";
|
|
10849
|
+
else if (ch < " ") out += `\\u${ch.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
10850
|
+
else out += ch;
|
|
10851
|
+
}
|
|
10852
|
+
return out + '"';
|
|
10853
|
+
};
|
|
10854
|
+
var encodeSide = (side) => `{"tag":${side.tag === void 0 ? "null" : escapeJson(side.tag)},"value":${escapeJson(side.value)}}`;
|
|
10855
|
+
var encodeMergeEnvelope = (conflicts) => "[" + sortConflictsCanonical(conflicts).map(
|
|
10856
|
+
(c) => `{"a":${encodeSide(c.a)},"b":${encodeSide(c.b)},"base":${escapeJson(c.base)},"class":${escapeJson(c.class)},"facet":${escapeJson(c.facet)},"nodeId":${escapeJson(c.nodeId)},"primacyHeld":${c.primacyHeld ? "true" : "false"}}`
|
|
10857
|
+
).join(",") + "]";
|
|
9899
10858
|
|
|
9900
10859
|
// src/versioning.ts
|
|
9901
10860
|
var renderProfile = (p) => `${p.name}@${p.major}.${p.minor}`;
|
|
@@ -10783,6 +11742,6 @@ var withStateSeeds = (tree, sources) => {
|
|
|
10783
11742
|
return { ...sources, state: { ...seeds, ...sources.state ?? {} } };
|
|
10784
11743
|
};
|
|
10785
11744
|
|
|
10786
|
-
export { ELICITATION_KEY, ELICITATION_VERSION, HOST_RESERVED_PREFIX, PAYLOAD_KEY, PROFILE_KEY, REQUIRED_PROFILE_KEY, apply, canPlace, cellString, coerce, collectStateSeeds, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, derivedFreshIds, duplicateOp, duplicateOpWith, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope2 as encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, liveValueToTable, merge3Way, moveOp, negotiate, negotiateEnvelope, noResolve, nudgeOp, parse, pasteOp, pasteOpWith, pipelineParams, placeOp, reencodeNode, renderAstCanonical, renderProfile, sequentialFreshIds, stepParams, substituteListParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument, withStateSeeds };
|
|
11745
|
+
export { DECODED_COMPUTED_MESSAGE, ELICITATION_KEY, ELICITATION_VERSION, HOST_RESERVED_PREFIX, PAYLOAD_KEY, PROFILE_KEY, REQUIRED_PROFILE_KEY, WireSurvivabilityError, apply, canPlace, cellString, coerce, collectStateSeeds, coreV1, decodeCapabilityDeclaration, decodeDagRecord, decodeDataSource, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeOps, decodePipelineCore as decodePipeline, decodeTolerant, derivedFreshIds, duplicateOp, duplicateOpWith, encodeCapabilityDeclaration, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope2 as encodeEnvelope, encodeMergeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, fixedText, identityFormat, field as jsonField, liveValueToTable, merge3Way, moveOp, negotiate, negotiateEnvelope, noResolve, nudgeOp, numberText, parse, pasteOp, pasteOpWith, pipelineParams, placeOp, reencodeNode, renderAstCanonical, renderProfile, scalarOfText, sequentialFreshIds, sortConflictsCanonical, stepParams, substituteListParams, tryNumberText, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument, withStateSeeds };
|
|
10787
11746
|
//# sourceMappingURL=index.js.map
|
|
10788
11747
|
//# sourceMappingURL=index.js.map
|