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