@valbuild/core 0.124.0 → 0.126.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/CHANGELOG.md +196 -0
- package/dist/declarations/src/getSourcePathFromRoute.d.ts +12 -3
- package/dist/declarations/src/index.d.ts +7 -3
- package/dist/declarations/src/initSchema.d.ts +46 -15
- package/dist/declarations/src/initVal.d.ts +108 -0
- package/dist/declarations/src/render.d.ts +5 -4
- package/dist/declarations/src/router.d.ts +45 -0
- package/dist/declarations/src/schema/array.d.ts +65 -0
- package/dist/declarations/src/schema/boolean.d.ts +44 -0
- package/dist/declarations/src/schema/code.d.ts +63 -0
- package/dist/declarations/src/schema/color.d.ts +54 -0
- package/dist/declarations/src/schema/date.d.ts +64 -2
- package/dist/declarations/src/schema/datetime.d.ts +87 -2
- package/dist/declarations/src/schema/discriminatedUnion.d.ts +166 -0
- package/dist/declarations/src/schema/enum.d.ts +122 -0
- package/dist/declarations/src/schema/file.d.ts +77 -0
- package/dist/declarations/src/schema/image.d.ts +102 -0
- package/dist/declarations/src/schema/index.d.ts +42 -2
- package/dist/declarations/src/schema/keyOf.d.ts +50 -0
- package/dist/declarations/src/schema/literal.d.ts +46 -0
- package/dist/declarations/src/schema/number.d.ts +58 -0
- package/dist/declarations/src/schema/object.d.ts +63 -0
- package/dist/declarations/src/schema/record.d.ts +136 -0
- package/dist/declarations/src/schema/richtext.d.ts +78 -0
- package/dist/declarations/src/schema/route.d.ts +44 -0
- package/dist/declarations/src/schema/string.d.ts +99 -0
- package/dist/declarations/src/schema/union.d.ts +54 -91
- package/dist/{index-22a40d42.cjs.prod.js → index-6db78f3c.cjs.prod.js} +2161 -423
- package/dist/{index-fcd087bd.cjs.dev.js → index-b41b638f.cjs.dev.js} +2161 -423
- package/dist/{index-9c14df37.esm.js → index-cd25c2dc.esm.js} +2155 -423
- package/dist/valbuild-core.cjs.dev.js +8 -2
- package/dist/valbuild-core.cjs.prod.js +8 -2
- package/dist/valbuild-core.esm.js +1 -1
- package/package.json +1 -1
- package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
- package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
- package/patch/dist/valbuild-core-patch.esm.js +2 -2
|
@@ -462,6 +462,23 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
462
462
|
_this.isMultiline = isMultiline;
|
|
463
463
|
return _this;
|
|
464
464
|
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Describe this field.
|
|
468
|
+
*
|
|
469
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
470
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
471
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
472
|
+
* assistant and the MCP tools read.
|
|
473
|
+
*
|
|
474
|
+
* Pass `null` to clear a description set earlier.
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* const schema = s
|
|
478
|
+
* .string()
|
|
479
|
+
* .describe("Shown in the browser tab and in search results");
|
|
480
|
+
* export default c.define("/example.val.ts", schema, "Hello");
|
|
481
|
+
*/
|
|
465
482
|
_inherits(StringSchema, _Schema);
|
|
466
483
|
return _createClass(StringSchema, [{
|
|
467
484
|
key: "describe",
|
|
@@ -471,12 +488,24 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
471
488
|
|
|
472
489
|
/**
|
|
473
490
|
* @deprecated Use `minLength` instead
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* const schema = s.string().minLength(2);
|
|
494
|
+
* export default c.define("/example.val.ts", schema, "Hi");
|
|
474
495
|
*/
|
|
475
496
|
}, {
|
|
476
497
|
key: "min",
|
|
477
498
|
value: function min(minLength) {
|
|
478
499
|
return this.minLength(minLength);
|
|
479
500
|
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Validate that the string is at least `minLength` characters long.
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* const schema = s.string().minLength(2);
|
|
507
|
+
* export default c.define("/example.val.ts", schema, "Hi");
|
|
508
|
+
*/
|
|
480
509
|
}, {
|
|
481
510
|
key: "minLength",
|
|
482
511
|
value: function minLength(_minLength) {
|
|
@@ -487,12 +516,24 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
487
516
|
|
|
488
517
|
/**
|
|
489
518
|
* @deprecated Use `maxLength` instead
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* const schema = s.string().maxLength(60);
|
|
522
|
+
* export default c.define("/example.val.ts", schema, "A title that fits");
|
|
490
523
|
*/
|
|
491
524
|
}, {
|
|
492
525
|
key: "max",
|
|
493
526
|
value: function max(maxLength) {
|
|
494
527
|
return this.maxLength(maxLength);
|
|
495
528
|
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Validate that the string is at most `maxLength` characters long.
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* const schema = s.string().maxLength(60);
|
|
535
|
+
* export default c.define("/example.val.ts", schema, "A title that fits");
|
|
536
|
+
*/
|
|
496
537
|
}, {
|
|
497
538
|
key: "maxLength",
|
|
498
539
|
value: function maxLength(_maxLength) {
|
|
@@ -500,6 +541,19 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
500
541
|
maxLength: _maxLength
|
|
501
542
|
}), this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, this.isReadonly, this.isHidden, this.description, this.previewInput, this.isMultiline);
|
|
502
543
|
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Validate that the string matches `regexp`.
|
|
547
|
+
*
|
|
548
|
+
* `message` is what the editor is shown when it does not match. Without one
|
|
549
|
+
* the error names the pattern, which is rarely what a non-developer needs.
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* const schema = s
|
|
553
|
+
* .string()
|
|
554
|
+
* .regexp(/^[a-z0-9-]+$/, "Lower case letters, digits and dashes only");
|
|
555
|
+
* export default c.define("/example.val.ts", schema, "my-slug");
|
|
556
|
+
*/
|
|
503
557
|
}, {
|
|
504
558
|
key: "regexp",
|
|
505
559
|
value: function regexp(_regexp, message) {
|
|
@@ -508,6 +562,27 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
508
562
|
regExpMessage: message
|
|
509
563
|
}), this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, this.isReadonly, this.isHidden, this.description, this.previewInput, this.isMultiline);
|
|
510
564
|
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Add a custom validation rule to this field.
|
|
568
|
+
*
|
|
569
|
+
* The function is called with the field's value and returns `false` when the
|
|
570
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
571
|
+
* more than once to add more rules — they all run, and every message is
|
|
572
|
+
* reported.
|
|
573
|
+
*
|
|
574
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
575
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
576
|
+
*
|
|
577
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
578
|
+
* before a publish.
|
|
579
|
+
*
|
|
580
|
+
* @example
|
|
581
|
+
* const schema = s.string().validate((val) =>
|
|
582
|
+
* val.trim() === val ? false : "Must not start or end with a space",
|
|
583
|
+
* );
|
|
584
|
+
* export default c.define("/example.val.ts", schema, "Hello");
|
|
585
|
+
*/
|
|
511
586
|
}, {
|
|
512
587
|
key: "validate",
|
|
513
588
|
value: function validate(validationFunction) {
|
|
@@ -598,6 +673,26 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
598
673
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
599
674
|
return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, this.isReadonly, isHidden, this.description, this.previewInput, this.isMultiline);
|
|
600
675
|
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Do not stega encode this string.
|
|
679
|
+
*
|
|
680
|
+
* Val normally encodes an invisible pointer back to the source into every
|
|
681
|
+
* string it hands your app, which is what makes click-to-edit work. A raw
|
|
682
|
+
* string is handed over exactly as written — use it wherever the value is
|
|
683
|
+
* not rendered as visible text: a slug, a class name, an `id`, a URL,
|
|
684
|
+
* anything parsed or compared.
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* const schema = s.object({
|
|
688
|
+
* title: s.string(),
|
|
689
|
+
* slug: s.string().raw(),
|
|
690
|
+
* });
|
|
691
|
+
* export default c.define("/example.val.ts", schema, {
|
|
692
|
+
* title: "Hello",
|
|
693
|
+
* slug: "hello",
|
|
694
|
+
* });
|
|
695
|
+
*/
|
|
601
696
|
}, {
|
|
602
697
|
key: "raw",
|
|
603
698
|
value: function raw() {
|
|
@@ -663,6 +758,10 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
663
758
|
*
|
|
664
759
|
* Static configuration, not a callback — see `render.ts`. What a CONTAINER
|
|
665
760
|
* shows for its items is a `preview`, which is a different thing entirely.
|
|
761
|
+
*
|
|
762
|
+
* @example
|
|
763
|
+
* const schema = s.array(s.string().render({ as: "inline" }));
|
|
764
|
+
* export default c.define("/example.val.ts", schema, ["First", "Second"]);
|
|
666
765
|
*/
|
|
667
766
|
}, {
|
|
668
767
|
key: "render",
|
|
@@ -674,6 +773,12 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
|
|
|
674
773
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
675
774
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
676
775
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* const schema = s.array(
|
|
779
|
+
* s.string().preview(({ val }) => ({ title: val })),
|
|
780
|
+
* );
|
|
781
|
+
* export default c.define("/example.val.ts", schema, ["First", "Second"]);
|
|
677
782
|
*/
|
|
678
783
|
}, {
|
|
679
784
|
key: "preview",
|
|
@@ -734,12 +839,59 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
|
|
|
734
839
|
_this.previewInput = previewInput;
|
|
735
840
|
return _this;
|
|
736
841
|
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Describe this field.
|
|
845
|
+
*
|
|
846
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
847
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
848
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
849
|
+
* assistant and the MCP tools read.
|
|
850
|
+
*
|
|
851
|
+
* Pass `null` to clear a description set earlier.
|
|
852
|
+
*
|
|
853
|
+
* @example
|
|
854
|
+
* const schema = s
|
|
855
|
+
* .object({ street: s.string(), city: s.string() })
|
|
856
|
+
* .describe("Where the office is — shown on the contact page");
|
|
857
|
+
* export default c.define("/example.val.ts", schema, {
|
|
858
|
+
* street: "Torggata 1",
|
|
859
|
+
* city: "Oslo",
|
|
860
|
+
* });
|
|
861
|
+
*/
|
|
737
862
|
_inherits(ObjectSchema, _Schema);
|
|
738
863
|
return _createClass(ObjectSchema, [{
|
|
739
864
|
key: "describe",
|
|
740
865
|
value: function describe(description) {
|
|
741
866
|
return new ObjectSchema(this.items, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
742
867
|
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Add a custom validation rule to this field.
|
|
871
|
+
*
|
|
872
|
+
* The function is called with the field's value and returns `false` when the
|
|
873
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
874
|
+
* more than once to add more rules — they all run, and every message is
|
|
875
|
+
* reported.
|
|
876
|
+
*
|
|
877
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
878
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
879
|
+
*
|
|
880
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
881
|
+
* before a publish.
|
|
882
|
+
*
|
|
883
|
+
* An object validator is the place for a rule that spans FIELDS — one field
|
|
884
|
+
* validated on its own belongs on that field's schema, where the error lands
|
|
885
|
+
* on the field itself.
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* const schema = s
|
|
889
|
+
* .object({ from: s.number(), to: s.number() })
|
|
890
|
+
* .validate((val) =>
|
|
891
|
+
* val.from <= val.to ? false : "'from' must not be after 'to'",
|
|
892
|
+
* );
|
|
893
|
+
* export default c.define("/example.val.ts", schema, { from: 1, to: 4 });
|
|
894
|
+
*/
|
|
743
895
|
}, {
|
|
744
896
|
key: "validate",
|
|
745
897
|
value: function validate(validationFunction) {
|
|
@@ -892,6 +1044,16 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
|
|
|
892
1044
|
* instead of a preview row that navigates to it.
|
|
893
1045
|
*
|
|
894
1046
|
* Static configuration, not a callback — see `render.ts`.
|
|
1047
|
+
*
|
|
1048
|
+
* @example
|
|
1049
|
+
* // A page builder: each row edits the object in place, instead of
|
|
1050
|
+
* // navigating to it.
|
|
1051
|
+
* const block = s
|
|
1052
|
+
* .object({ heading: s.string(), body: s.string() })
|
|
1053
|
+
* .render({ as: "inline" });
|
|
1054
|
+
* export default c.define("/example.val.ts", s.array(block), [
|
|
1055
|
+
* { heading: "Hello", body: "World" },
|
|
1056
|
+
* ]);
|
|
895
1057
|
*/
|
|
896
1058
|
}, {
|
|
897
1059
|
key: "render",
|
|
@@ -903,6 +1065,14 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
|
|
|
903
1065
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
904
1066
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
905
1067
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
1068
|
+
*
|
|
1069
|
+
* @example
|
|
1070
|
+
* const author = s
|
|
1071
|
+
* .object({ name: s.string(), role: s.string() })
|
|
1072
|
+
* .preview(({ val }) => ({ title: val.name, subtitle: val.role }));
|
|
1073
|
+
* export default c.define("/example.val.ts", s.array(author), [
|
|
1074
|
+
* { name: "Ada", role: "Engineer" },
|
|
1075
|
+
* ]);
|
|
906
1076
|
*/
|
|
907
1077
|
}, {
|
|
908
1078
|
key: "preview",
|
|
@@ -1005,12 +1175,54 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
|
|
|
1005
1175
|
_this.renderInput = renderInput;
|
|
1006
1176
|
return _this;
|
|
1007
1177
|
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Describe this field.
|
|
1181
|
+
*
|
|
1182
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
1183
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
1184
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
1185
|
+
* assistant and the MCP tools read.
|
|
1186
|
+
*
|
|
1187
|
+
* Pass `null` to clear a description set earlier.
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* const schema = s
|
|
1191
|
+
* .array(s.string())
|
|
1192
|
+
* .describe("Bullet points shown under the heading");
|
|
1193
|
+
* export default c.define("/example.val.ts", schema, ["First", "Second"]);
|
|
1194
|
+
*/
|
|
1008
1195
|
_inherits(ArraySchema, _Schema);
|
|
1009
1196
|
return _createClass(ArraySchema, [{
|
|
1010
1197
|
key: "describe",
|
|
1011
1198
|
value: function describe(description) {
|
|
1012
1199
|
return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.previewInput, this.renderInput);
|
|
1013
1200
|
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Add a custom validation rule to this field.
|
|
1204
|
+
*
|
|
1205
|
+
* The function is called with the field's value and returns `false` when the
|
|
1206
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
1207
|
+
* more than once to add more rules — they all run, and every message is
|
|
1208
|
+
* reported.
|
|
1209
|
+
*
|
|
1210
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
1211
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
1212
|
+
*
|
|
1213
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
1214
|
+
* before a publish.
|
|
1215
|
+
*
|
|
1216
|
+
* The function is given the whole array. To validate one item, put a
|
|
1217
|
+
* `.validate(...)` on the ITEM schema instead — that reports the error on
|
|
1218
|
+
* the item's own row.
|
|
1219
|
+
*
|
|
1220
|
+
* @example
|
|
1221
|
+
* const schema = s.array(s.string()).validate((val) =>
|
|
1222
|
+
* val.length <= 3 ? false : "At most 3 items",
|
|
1223
|
+
* );
|
|
1224
|
+
* export default c.define("/example.val.ts", schema, ["First", "Second"]);
|
|
1225
|
+
*/
|
|
1014
1226
|
}, {
|
|
1015
1227
|
key: "validate",
|
|
1016
1228
|
value: function validate(validationFunction) {
|
|
@@ -1218,6 +1430,25 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
|
|
|
1218
1430
|
* is the item of another container, in search, in references. What its rows
|
|
1219
1431
|
* show is the ITEM schema's `preview`, not this. Never how the field is
|
|
1220
1432
|
* edited (that is `render`). See `preview.ts`.
|
|
1433
|
+
*
|
|
1434
|
+
* @example
|
|
1435
|
+
* // The preview of the ARRAY, for where it is an item of something else.
|
|
1436
|
+
* // What its own rows show is the ITEM schema's preview — see below.
|
|
1437
|
+
* const tags = s.array(s.string()).preview(({ val }) => ({
|
|
1438
|
+
* title: `${val.length} tags`,
|
|
1439
|
+
* }));
|
|
1440
|
+
* export default c.define("/example.val.ts", s.record(tags), {
|
|
1441
|
+
* "a-post": ["news", "release"],
|
|
1442
|
+
* });
|
|
1443
|
+
*
|
|
1444
|
+
* @example
|
|
1445
|
+
* // Rows of an array come from the ITEM's preview, not the array's:
|
|
1446
|
+
* const author = s
|
|
1447
|
+
* .object({ name: s.string(), role: s.string() })
|
|
1448
|
+
* .preview(({ val }) => ({ title: val.name, subtitle: val.role }));
|
|
1449
|
+
* export default c.define("/example.val.ts", s.array(author), [
|
|
1450
|
+
* { name: "Ada", role: "Engineer" },
|
|
1451
|
+
* ]);
|
|
1221
1452
|
*/
|
|
1222
1453
|
}, {
|
|
1223
1454
|
key: "preview",
|
|
@@ -1231,6 +1462,12 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
|
|
|
1231
1462
|
* instead of a preview row that navigates to it.
|
|
1232
1463
|
*
|
|
1233
1464
|
* Static configuration, not a callback — see `render.ts`.
|
|
1465
|
+
*
|
|
1466
|
+
* @example
|
|
1467
|
+
* const schema = s.record(s.array(s.string()).render({ as: "inline" }));
|
|
1468
|
+
* export default c.define("/example.val.ts", schema, {
|
|
1469
|
+
* "a-post": ["news", "release"],
|
|
1470
|
+
* });
|
|
1234
1471
|
*/
|
|
1235
1472
|
}, {
|
|
1236
1473
|
key: "render",
|
|
@@ -1265,12 +1502,50 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1265
1502
|
_this.previewInput = previewInput;
|
|
1266
1503
|
return _this;
|
|
1267
1504
|
}
|
|
1505
|
+
|
|
1506
|
+
/**
|
|
1507
|
+
* Describe this field.
|
|
1508
|
+
*
|
|
1509
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
1510
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
1511
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
1512
|
+
* assistant and the MCP tools read.
|
|
1513
|
+
*
|
|
1514
|
+
* Pass `null` to clear a description set earlier.
|
|
1515
|
+
*
|
|
1516
|
+
* @example
|
|
1517
|
+
* const schema = s
|
|
1518
|
+
* .literal("hero")
|
|
1519
|
+
* .describe("The block type — it identifies the variant");
|
|
1520
|
+
* export default c.define("/example.val.ts", schema, "hero");
|
|
1521
|
+
*/
|
|
1268
1522
|
_inherits(LiteralSchema, _Schema);
|
|
1269
1523
|
return _createClass(LiteralSchema, [{
|
|
1270
1524
|
key: "describe",
|
|
1271
1525
|
value: function describe(description) {
|
|
1272
1526
|
return new LiteralSchema(this.value, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
1273
1527
|
}
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* Add a custom validation rule to this field.
|
|
1531
|
+
*
|
|
1532
|
+
* The function is called with the field's value and returns `false` when the
|
|
1533
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
1534
|
+
* more than once to add more rules — they all run, and every message is
|
|
1535
|
+
* reported.
|
|
1536
|
+
*
|
|
1537
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
1538
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
1539
|
+
*
|
|
1540
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
1541
|
+
* before a publish.
|
|
1542
|
+
*
|
|
1543
|
+
* @example
|
|
1544
|
+
* const schema = s.literal("hero").validate((val) =>
|
|
1545
|
+
* val === "hero" ? false : "Unknown block type",
|
|
1546
|
+
* );
|
|
1547
|
+
* export default c.define("/example.val.ts", schema, "hero");
|
|
1548
|
+
*/
|
|
1274
1549
|
}, {
|
|
1275
1550
|
key: "validate",
|
|
1276
1551
|
value: function validate(validationFunction) {
|
|
@@ -1365,6 +1640,10 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1365
1640
|
* instead of a preview row that navigates to it.
|
|
1366
1641
|
*
|
|
1367
1642
|
* Static configuration, not a callback — see `render.ts`.
|
|
1643
|
+
*
|
|
1644
|
+
* @example
|
|
1645
|
+
* const schema = s.array(s.literal("hero").render({ as: "inline" }));
|
|
1646
|
+
* export default c.define("/example.val.ts", schema, ["hero"]);
|
|
1368
1647
|
*/
|
|
1369
1648
|
}, {
|
|
1370
1649
|
key: "render",
|
|
@@ -1376,6 +1655,12 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1376
1655
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
1377
1656
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
1378
1657
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
1658
|
+
*
|
|
1659
|
+
* @example
|
|
1660
|
+
* const schema = s.array(
|
|
1661
|
+
* s.literal("hero").preview(({ val }) => ({ title: val })),
|
|
1662
|
+
* );
|
|
1663
|
+
* export default c.define("/example.val.ts", schema, ["hero"]);
|
|
1379
1664
|
*/
|
|
1380
1665
|
}, {
|
|
1381
1666
|
key: "preview",
|
|
@@ -1424,8 +1709,30 @@ var literal = function literal(value) {
|
|
|
1424
1709
|
return new LiteralSchema(value);
|
|
1425
1710
|
};
|
|
1426
1711
|
|
|
1427
|
-
|
|
1428
|
-
|
|
1712
|
+
/** The variant objects a discriminated union on `Key` may be built from. */
|
|
1713
|
+
|
|
1714
|
+
/**
|
|
1715
|
+
* At least one variant, so a union with none cannot be written.
|
|
1716
|
+
*
|
|
1717
|
+
* Everything downstream reads the first one where it needs any — `emptyOf`
|
|
1718
|
+
* takes `items[0]` for the value a new entry starts as — and a union with
|
|
1719
|
+
* nothing to select is not a thing an author means. `s.enum` says the same
|
|
1720
|
+
* about its values.
|
|
1721
|
+
*/
|
|
1722
|
+
|
|
1723
|
+
/** The source type a discriminated union over `T` accepts. */
|
|
1724
|
+
|
|
1725
|
+
/**
|
|
1726
|
+
* One of several object shapes, told apart by a tag field.
|
|
1727
|
+
*
|
|
1728
|
+
* Every variant is an object with `key` set to a distinct `s.literal(...)`, and
|
|
1729
|
+
* the value of that field decides which variant a value is. Unlike
|
|
1730
|
+
* {@link EnumSchema} this is a CONTAINER: the variant's fields are the fields
|
|
1731
|
+
* being edited, and everything that walks the schema tree has to descend
|
|
1732
|
+
* through the matching variant.
|
|
1733
|
+
*/
|
|
1734
|
+
var DiscriminatedUnionSchema = /*#__PURE__*/function (_Schema) {
|
|
1735
|
+
function DiscriminatedUnionSchema(key, items) {
|
|
1429
1736
|
var _this;
|
|
1430
1737
|
var opt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
1431
1738
|
var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
@@ -1434,8 +1741,8 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1434
1741
|
var description = arguments.length > 6 ? arguments[6] : undefined;
|
|
1435
1742
|
var renderInput = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
|
|
1436
1743
|
var previewInput = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
|
|
1437
|
-
_classCallCheck(this,
|
|
1438
|
-
_this = _callSuper(this,
|
|
1744
|
+
_classCallCheck(this, DiscriminatedUnionSchema);
|
|
1745
|
+
_this = _callSuper(this, DiscriminatedUnionSchema);
|
|
1439
1746
|
_this.key = key;
|
|
1440
1747
|
_this.items = items;
|
|
1441
1748
|
_this.opt = opt;
|
|
@@ -1447,16 +1754,66 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1447
1754
|
_this.previewInput = previewInput;
|
|
1448
1755
|
return _this;
|
|
1449
1756
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1757
|
+
|
|
1758
|
+
/**
|
|
1759
|
+
* Describe this field.
|
|
1760
|
+
*
|
|
1761
|
+
* The description is shown next to the field's label in the Val editor, so it is
|
|
1762
|
+
* where you say what an editor needs to know but the field name cannot carry. It
|
|
1763
|
+
* also travels in the serialized schema, which is what the AI assistant and the
|
|
1764
|
+
* MCP tools read.
|
|
1765
|
+
*
|
|
1766
|
+
* Pass `null` to clear a description set earlier.
|
|
1767
|
+
*
|
|
1768
|
+
* @example
|
|
1769
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
1770
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
1771
|
+
* const schema = s
|
|
1772
|
+
* .discriminatedUnion("type", hero, text)
|
|
1773
|
+
* .describe("What this section of the page is");
|
|
1774
|
+
* export default c.define("/example.val.ts", schema, {
|
|
1775
|
+
* type: "hero",
|
|
1776
|
+
* title: "Hello",
|
|
1777
|
+
* });
|
|
1778
|
+
*/
|
|
1779
|
+
_inherits(DiscriminatedUnionSchema, _Schema);
|
|
1780
|
+
return _createClass(DiscriminatedUnionSchema, [{
|
|
1452
1781
|
key: "describe",
|
|
1453
1782
|
value: function describe(description) {
|
|
1454
|
-
return new
|
|
1783
|
+
return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
1455
1784
|
}
|
|
1785
|
+
|
|
1786
|
+
/**
|
|
1787
|
+
* Add a custom validation rule to this field.
|
|
1788
|
+
*
|
|
1789
|
+
* The function is called with the field's value and returns `false` when the
|
|
1790
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
1791
|
+
* more than once to add more rules — they all run, and every message is
|
|
1792
|
+
* reported.
|
|
1793
|
+
*
|
|
1794
|
+
* Validation runs in the Studio as you type, in `npx val validate` and before a
|
|
1795
|
+
* publish.
|
|
1796
|
+
*
|
|
1797
|
+
* The function is given the whole value, whichever variant it took. A rule
|
|
1798
|
+
* that only concerns one variant belongs on that variant's object schema.
|
|
1799
|
+
*
|
|
1800
|
+
* @example
|
|
1801
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
1802
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
1803
|
+
* const schema = s
|
|
1804
|
+
* .discriminatedUnion("type", hero, text)
|
|
1805
|
+
* .validate((val) =>
|
|
1806
|
+
* val.type === "hero" && !val.title ? "A hero needs a title" : false,
|
|
1807
|
+
* );
|
|
1808
|
+
* export default c.define("/example.val.ts", schema, {
|
|
1809
|
+
* type: "hero",
|
|
1810
|
+
* title: "Hello",
|
|
1811
|
+
* });
|
|
1812
|
+
*/
|
|
1456
1813
|
}, {
|
|
1457
1814
|
key: "validate",
|
|
1458
1815
|
value: function validate(validationFunction) {
|
|
1459
|
-
return new
|
|
1816
|
+
return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions.concat(validationFunction), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
1460
1817
|
}
|
|
1461
1818
|
}, {
|
|
1462
1819
|
key: "executeValidate",
|
|
@@ -1464,142 +1821,135 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1464
1821
|
var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
1465
1822
|
path: path
|
|
1466
1823
|
});
|
|
1824
|
+
/**
|
|
1825
|
+
* A structural error at this path, unless the custom validators already
|
|
1826
|
+
* reported — in which case theirs are the answer and this one is dropped.
|
|
1827
|
+
* Faithful to what `s.union` did; changing it is a separate decision.
|
|
1828
|
+
*/
|
|
1829
|
+
var structural = function structural(error) {
|
|
1830
|
+
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [error]);
|
|
1831
|
+
};
|
|
1467
1832
|
var unknownSrc = src;
|
|
1468
1833
|
if (this.opt && unknownSrc === null) {
|
|
1469
1834
|
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
|
|
1470
1835
|
}
|
|
1471
1836
|
if (!this.key) {
|
|
1472
|
-
return
|
|
1473
|
-
message: "Missing required first argument in union",
|
|
1837
|
+
return structural({
|
|
1838
|
+
message: "Missing required first argument in discriminated union",
|
|
1474
1839
|
schemaError: true
|
|
1475
|
-
}
|
|
1840
|
+
});
|
|
1476
1841
|
}
|
|
1477
1842
|
var key = this.key;
|
|
1478
1843
|
if (!Array.isArray(this.items)) {
|
|
1479
|
-
return
|
|
1480
|
-
message: "A union schema must take more than 1 schema arguments",
|
|
1844
|
+
return structural({
|
|
1845
|
+
message: "A discriminated union schema must take more than 1 schema arguments",
|
|
1481
1846
|
schemaError: true
|
|
1482
|
-
}
|
|
1847
|
+
});
|
|
1483
1848
|
}
|
|
1484
|
-
if (typeof key
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
})) {
|
|
1489
|
-
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
1490
|
-
message: "Key is a string, so all schema items must be objects",
|
|
1491
|
-
schemaError: true
|
|
1492
|
-
}]));
|
|
1493
|
-
}
|
|
1494
|
-
var objectSchemas = this.items;
|
|
1495
|
-
var serializedSchemas = objectSchemas.map(function (schema) {
|
|
1496
|
-
return schema["executeSerialize"]();
|
|
1849
|
+
if (typeof key !== "string") {
|
|
1850
|
+
return structural({
|
|
1851
|
+
message: "The key of a discriminated union must be a string",
|
|
1852
|
+
schemaError: true
|
|
1497
1853
|
});
|
|
1498
|
-
|
|
1499
|
-
|
|
1854
|
+
}
|
|
1855
|
+
if (this.items.some(function (item) {
|
|
1856
|
+
return !(item instanceof ObjectSchema);
|
|
1857
|
+
})) {
|
|
1858
|
+
return structural({
|
|
1859
|
+
message: "All schema items of a discriminated union must be objects",
|
|
1860
|
+
schemaError: true
|
|
1500
1861
|
});
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1862
|
+
}
|
|
1863
|
+
var objectSchemas = this.items;
|
|
1864
|
+
var serializedSchemas = objectSchemas.map(function (schema) {
|
|
1865
|
+
return schema["executeSerialize"]();
|
|
1866
|
+
});
|
|
1867
|
+
// `items[key]?` — a variant that OMITS the discriminator is exactly what
|
|
1868
|
+
// this check exists to report, so it must not throw while finding it.
|
|
1869
|
+
var illegalSchemas = serializedSchemas.filter(function (schema) {
|
|
1870
|
+
var _schema$items$key;
|
|
1871
|
+
return !(schema.type === "object") || ((_schema$items$key = schema.items[key]) === null || _schema$items$key === void 0 ? void 0 : _schema$items$key.type) !== "literal";
|
|
1872
|
+
});
|
|
1873
|
+
if (illegalSchemas.length > 0) {
|
|
1874
|
+
return structural({
|
|
1875
|
+
message: "All schema items must be objects with a key: ".concat(key, " that is a literal schema. Found: ").concat(JSON.stringify(illegalSchemas, null, 2)),
|
|
1876
|
+
schemaError: true
|
|
1510
1877
|
});
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
typeError: true
|
|
1521
|
-
}]));
|
|
1522
|
-
}
|
|
1523
|
-
var objectSrc = unknownSrc;
|
|
1524
|
-
if (objectSrc[key] === undefined) {
|
|
1525
|
-
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
1526
|
-
message: "Missing required key: ".concat(key),
|
|
1527
|
-
typeError: true
|
|
1528
|
-
}]));
|
|
1529
|
-
}
|
|
1530
|
-
var foundSchemaLiterals = [];
|
|
1531
|
-
var _iterator = _createForOfIteratorHelper(serializedObjectSchemas),
|
|
1532
|
-
_step;
|
|
1533
|
-
try {
|
|
1534
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1535
|
-
var schema = _step.value;
|
|
1536
|
-
var schemaKey = schema.items[key];
|
|
1537
|
-
if (schemaKey.type === "literal") {
|
|
1538
|
-
if (!foundSchemaLiterals.includes(schemaKey.value)) {
|
|
1539
|
-
foundSchemaLiterals.push(schemaKey.value);
|
|
1540
|
-
} else {
|
|
1541
|
-
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
1542
|
-
message: "Found duplicate key in schema: ".concat(schemaKey.value),
|
|
1543
|
-
schemaError: true
|
|
1544
|
-
}]));
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1548
|
-
} catch (err) {
|
|
1549
|
-
_iterator.e(err);
|
|
1550
|
-
} finally {
|
|
1551
|
-
_iterator.f();
|
|
1552
|
-
}
|
|
1553
|
-
var objectSchemaAtKey = objectSchemas.find(function (schema) {
|
|
1554
|
-
return !schema["items"][key]["executeValidate"](path, objectSrc[key]);
|
|
1878
|
+
}
|
|
1879
|
+
var serializedObjectSchemas = serializedSchemas;
|
|
1880
|
+
var optionalLiterals = serializedObjectSchemas.filter(function (schema) {
|
|
1881
|
+
return schema.items[key].opt;
|
|
1882
|
+
});
|
|
1883
|
+
if (optionalLiterals.length > 1) {
|
|
1884
|
+
return structural({
|
|
1885
|
+
message: "Schema cannot have an optional keys: ".concat(key),
|
|
1886
|
+
schemaError: true
|
|
1555
1887
|
});
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
return !item["executeValidate"](path, unknownSrc);
|
|
1590
|
-
});
|
|
1591
|
-
if (!isMatch) {
|
|
1592
|
-
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
1593
|
-
message: "Union must match one of the following: ".concat(literalItems.map(function (item) {
|
|
1594
|
-
return "\"".concat(item["value"], "\"");
|
|
1595
|
-
}).join(", "))
|
|
1596
|
-
}]));
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
// `typeof null === "object"`, so null has to be named separately or it
|
|
1891
|
+
// reaches `objectSrc[key]` below and throws instead of reporting.
|
|
1892
|
+
if (unknownSrc === null || _typeof(unknownSrc) !== "object") {
|
|
1893
|
+
return structural({
|
|
1894
|
+
message: "Expected an object, got ".concat(unknownSrc === null ? "null" : _typeof(unknownSrc)),
|
|
1895
|
+
typeError: true
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
var objectSrc = unknownSrc;
|
|
1899
|
+
if (objectSrc[key] === undefined) {
|
|
1900
|
+
return structural({
|
|
1901
|
+
message: "Missing required key: ".concat(key),
|
|
1902
|
+
typeError: true
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
var foundSchemaLiterals = [];
|
|
1906
|
+
var _iterator = _createForOfIteratorHelper(serializedObjectSchemas),
|
|
1907
|
+
_step;
|
|
1908
|
+
try {
|
|
1909
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1910
|
+
var schema = _step.value;
|
|
1911
|
+
var schemaKey = schema.items[key];
|
|
1912
|
+
if (schemaKey.type === "literal") {
|
|
1913
|
+
if (!foundSchemaLiterals.includes(schemaKey.value)) {
|
|
1914
|
+
foundSchemaLiterals.push(schemaKey.value);
|
|
1915
|
+
} else {
|
|
1916
|
+
return structural({
|
|
1917
|
+
message: "Found duplicate key in schema: ".concat(schemaKey.value),
|
|
1918
|
+
schemaError: true
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1597
1921
|
}
|
|
1598
1922
|
}
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1923
|
+
} catch (err) {
|
|
1924
|
+
_iterator.e(err);
|
|
1925
|
+
} finally {
|
|
1926
|
+
_iterator.f();
|
|
1927
|
+
}
|
|
1928
|
+
var objectSchemaAtKey = objectSchemas.find(function (schema) {
|
|
1929
|
+
return !schema["items"][key]["executeValidate"](path, objectSrc[key]);
|
|
1930
|
+
});
|
|
1931
|
+
if (!objectSchemaAtKey) {
|
|
1932
|
+
var keyPath = createValPathOfItem(path, key);
|
|
1933
|
+
if (!keyPath) {
|
|
1934
|
+
throw new Error("Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(key));
|
|
1935
|
+
}
|
|
1936
|
+
return _defineProperty({}, keyPath, [{
|
|
1937
|
+
message: "Invalid key: \"".concat(key, "\". Value was: \"").concat(objectSrc[key], "\". Valid values: ").concat(serializedObjectSchemas.map(function (schema) {
|
|
1938
|
+
var keySchema = schema.items[key];
|
|
1939
|
+
// The TYPE is the whole test: `s.literal("")` is a valid
|
|
1940
|
+
// discriminator, and a truthiness check threw on it here.
|
|
1941
|
+
if (keySchema.type === "literal") {
|
|
1942
|
+
return "\"".concat(keySchema.value, "\"");
|
|
1943
|
+
} else {
|
|
1944
|
+
// should not happen here, we already checked this
|
|
1945
|
+
throw new Error("Expected literal schema, got ".concat(JSON.stringify(keySchema, null, 2)));
|
|
1946
|
+
}
|
|
1947
|
+
}).join(", "))
|
|
1948
|
+
}]);
|
|
1949
|
+
}
|
|
1950
|
+
var error = objectSchemaAtKey["executeValidate"](path, objectSrc);
|
|
1951
|
+
if (error) {
|
|
1952
|
+
return error;
|
|
1603
1953
|
}
|
|
1604
1954
|
return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
|
|
1605
1955
|
}
|
|
@@ -1621,11 +1971,11 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1621
1971
|
}])
|
|
1622
1972
|
};
|
|
1623
1973
|
}
|
|
1624
|
-
if (!this.key) {
|
|
1974
|
+
if (typeof this.key !== "string" || !this.key) {
|
|
1625
1975
|
return {
|
|
1626
1976
|
success: false,
|
|
1627
1977
|
errors: _defineProperty({}, path, [{
|
|
1628
|
-
message: "Missing required first argument in union schema",
|
|
1978
|
+
message: "Missing required first argument in discriminated union schema",
|
|
1629
1979
|
schemaError: true
|
|
1630
1980
|
}])
|
|
1631
1981
|
};
|
|
@@ -1634,135 +1984,68 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1634
1984
|
return {
|
|
1635
1985
|
success: false,
|
|
1636
1986
|
errors: _defineProperty({}, path, [{
|
|
1637
|
-
message: "The schema of this value is wrong.
|
|
1987
|
+
message: "The schema of this value is wrong. A discriminated union must have an array of object schemas",
|
|
1638
1988
|
schemaError: true
|
|
1639
1989
|
}])
|
|
1640
1990
|
};
|
|
1641
1991
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
errors[path] = [{
|
|
1662
|
-
message: "Expected 'string', got '".concat(_typeof(src), "'"),
|
|
1663
|
-
typeError: true
|
|
1664
|
-
}];
|
|
1665
|
-
continue;
|
|
1666
|
-
}
|
|
1667
|
-
var res = itemSchema["executeAssert"](path, src);
|
|
1668
|
-
if (res.success) {
|
|
1669
|
-
success = true;
|
|
1670
|
-
break;
|
|
1671
|
-
} else {
|
|
1672
|
-
for (var _i = 0, _Object$entries = Object.entries(res.errors); _i < _Object$entries.length; _i++) {
|
|
1673
|
-
var _errors5;
|
|
1674
|
-
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
1675
|
-
_key = _Object$entries$_i[0],
|
|
1676
|
-
value = _Object$entries$_i[1];
|
|
1677
|
-
if (!errors[_key]) {
|
|
1678
|
-
errors[_key] = [];
|
|
1679
|
-
}
|
|
1680
|
-
(_errors5 = errors[_key]).push.apply(_errors5, _toConsumableArray(value));
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
} catch (err) {
|
|
1685
|
-
_iterator2.e(err);
|
|
1686
|
-
} finally {
|
|
1687
|
-
_iterator2.f();
|
|
1688
|
-
}
|
|
1689
|
-
if (!success) {
|
|
1690
|
-
return {
|
|
1691
|
-
success: false,
|
|
1692
|
-
errors: errors
|
|
1693
|
-
};
|
|
1694
|
-
}
|
|
1695
|
-
return {
|
|
1696
|
-
success: true,
|
|
1697
|
-
data: src
|
|
1698
|
-
};
|
|
1699
|
-
} else if (typeof this.key === "string") {
|
|
1700
|
-
var _success = false;
|
|
1701
|
-
var _errors6 = {};
|
|
1702
|
-
var _iterator3 = _createForOfIteratorHelper(this.items),
|
|
1703
|
-
_step3;
|
|
1704
|
-
try {
|
|
1705
|
-
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1706
|
-
var _itemSchema = _step3.value;
|
|
1707
|
-
var _res = _itemSchema["executeAssert"](path, src);
|
|
1708
|
-
if (_res.success) {
|
|
1709
|
-
_success = true;
|
|
1710
|
-
break;
|
|
1711
|
-
} else {
|
|
1712
|
-
for (var _i2 = 0, _Object$entries2 = Object.entries(_res.errors); _i2 < _Object$entries2.length; _i2++) {
|
|
1713
|
-
var _errors7;
|
|
1714
|
-
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
1715
|
-
_key2 = _Object$entries2$_i[0],
|
|
1716
|
-
_value = _Object$entries2$_i[1];
|
|
1717
|
-
if (!_errors6[_key2]) {
|
|
1718
|
-
_errors6[_key2] = [];
|
|
1719
|
-
}
|
|
1720
|
-
(_errors7 = _errors6[_key2]).push.apply(_errors7, _toConsumableArray(_value)); // by appending all type errors, we most likely get a lot of duplicate errors. Currently we believe this is correct though, but should probably be handled in when showing the errors to users
|
|
1992
|
+
var success = false;
|
|
1993
|
+
var errors = {};
|
|
1994
|
+
var _iterator2 = _createForOfIteratorHelper(this.items),
|
|
1995
|
+
_step2;
|
|
1996
|
+
try {
|
|
1997
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1998
|
+
var itemSchema = _step2.value;
|
|
1999
|
+
var res = itemSchema["executeAssert"](path, src);
|
|
2000
|
+
if (res.success) {
|
|
2001
|
+
success = true;
|
|
2002
|
+
break;
|
|
2003
|
+
} else {
|
|
2004
|
+
for (var _i = 0, _Object$entries = Object.entries(res.errors); _i < _Object$entries.length; _i++) {
|
|
2005
|
+
var _errors4;
|
|
2006
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
2007
|
+
_key = _Object$entries$_i[0],
|
|
2008
|
+
value = _Object$entries$_i[1];
|
|
2009
|
+
if (!errors[_key]) {
|
|
2010
|
+
errors[_key] = [];
|
|
1721
2011
|
}
|
|
2012
|
+
(_errors4 = errors[_key]).push.apply(_errors4, _toConsumableArray(value)); // by appending all type errors, we most likely get a lot of duplicate errors. Currently we believe this is correct though, but should probably be handled in when showing the errors to users
|
|
1722
2013
|
}
|
|
1723
2014
|
}
|
|
1724
|
-
} catch (err) {
|
|
1725
|
-
_iterator3.e(err);
|
|
1726
|
-
} finally {
|
|
1727
|
-
_iterator3.f();
|
|
1728
2015
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
return {
|
|
1736
|
-
success: true,
|
|
1737
|
-
data: src
|
|
1738
|
-
};
|
|
1739
|
-
} else {
|
|
2016
|
+
} catch (err) {
|
|
2017
|
+
_iterator2.e(err);
|
|
2018
|
+
} finally {
|
|
2019
|
+
_iterator2.f();
|
|
2020
|
+
}
|
|
2021
|
+
if (!success) {
|
|
1740
2022
|
return {
|
|
1741
2023
|
success: false,
|
|
1742
|
-
errors:
|
|
1743
|
-
message: "The schema of this value is wrong. Schema is neither a union of literals nor a tagged union (of objects)",
|
|
1744
|
-
schemaError: true
|
|
1745
|
-
}])
|
|
2024
|
+
errors: errors
|
|
1746
2025
|
};
|
|
1747
2026
|
}
|
|
2027
|
+
return {
|
|
2028
|
+
success: true,
|
|
2029
|
+
data: src
|
|
2030
|
+
};
|
|
1748
2031
|
}
|
|
1749
2032
|
}, {
|
|
1750
2033
|
key: "nullable",
|
|
1751
2034
|
value: function nullable() {
|
|
1752
2035
|
// Explicit type args: `previewInput` would otherwise pin inference to `Src`.
|
|
1753
|
-
return new
|
|
2036
|
+
return new DiscriminatedUnionSchema(this.key, this.items, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
1754
2037
|
}
|
|
1755
2038
|
}, {
|
|
1756
2039
|
key: "readonly",
|
|
1757
2040
|
value: function readonly() {
|
|
1758
2041
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
1759
|
-
return new
|
|
2042
|
+
return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
1760
2043
|
}
|
|
1761
2044
|
}, {
|
|
1762
2045
|
key: "hidden",
|
|
1763
2046
|
value: function hidden() {
|
|
1764
2047
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
1765
|
-
return new
|
|
2048
|
+
return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
|
|
1766
2049
|
}
|
|
1767
2050
|
}, {
|
|
1768
2051
|
key: "executeCustomValidateAt",
|
|
@@ -1770,10 +2053,10 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1770
2053
|
var errors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
1771
2054
|
path: path
|
|
1772
2055
|
});
|
|
1773
|
-
// A
|
|
1774
|
-
// stops here and a variant's OWN validator would
|
|
1775
|
-
// into the variant this value takes — the union
|
|
1776
|
-
// which one that is.
|
|
2056
|
+
// A discriminated union's variants share the union's path, so
|
|
2057
|
+
// `Internal.resolvePath` stops here and a variant's OWN validator would
|
|
2058
|
+
// never be reached. Dispatch into the variant this value takes — the union
|
|
2059
|
+
// is the only node that knows which one that is.
|
|
1777
2060
|
var matched = this.matchedVariant(src);
|
|
1778
2061
|
if (matched) {
|
|
1779
2062
|
errors.push.apply(errors, _toConsumableArray(matched["executeCustomValidateAt"](path, src)));
|
|
@@ -1782,10 +2065,8 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1782
2065
|
}
|
|
1783
2066
|
|
|
1784
2067
|
/**
|
|
1785
|
-
* The variant schema a value takes
|
|
1786
|
-
*
|
|
1787
|
-
* when the value matches none of them — a structural error `executeValidate`
|
|
1788
|
-
* already reports.
|
|
2068
|
+
* The variant schema a value takes. `null` when the value matches none of
|
|
2069
|
+
* them — a structural error `executeValidate` already reports.
|
|
1789
2070
|
*/
|
|
1790
2071
|
}, {
|
|
1791
2072
|
key: "matchedVariant",
|
|
@@ -1802,11 +2083,11 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1802
2083
|
return null;
|
|
1803
2084
|
}
|
|
1804
2085
|
var objectSchemas = this.items;
|
|
1805
|
-
var
|
|
1806
|
-
|
|
2086
|
+
var _iterator3 = _createForOfIteratorHelper(objectSchemas),
|
|
2087
|
+
_step3;
|
|
1807
2088
|
try {
|
|
1808
|
-
for (
|
|
1809
|
-
var item =
|
|
2089
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
2090
|
+
var item = _step3.value;
|
|
1810
2091
|
if (!(item instanceof ObjectSchema)) {
|
|
1811
2092
|
continue;
|
|
1812
2093
|
}
|
|
@@ -1816,9 +2097,9 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1816
2097
|
}
|
|
1817
2098
|
}
|
|
1818
2099
|
} catch (err) {
|
|
1819
|
-
|
|
2100
|
+
_iterator3.e(err);
|
|
1820
2101
|
} finally {
|
|
1821
|
-
|
|
2102
|
+
_iterator3.f();
|
|
1822
2103
|
}
|
|
1823
2104
|
return null;
|
|
1824
2105
|
}
|
|
@@ -1829,11 +2110,21 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1829
2110
|
* instead of a preview row that navigates to it.
|
|
1830
2111
|
*
|
|
1831
2112
|
* Static configuration, not a callback — see `render.ts`.
|
|
2113
|
+
*
|
|
2114
|
+
* @example
|
|
2115
|
+
* // A page builder: the row draws the tag selector and the matched
|
|
2116
|
+
* // variant's fields.
|
|
2117
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
2118
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
2119
|
+
* const block = s.discriminatedUnion("type", hero, text).render({ as: "inline" });
|
|
2120
|
+
* export default c.define("/example.val.ts", s.array(block), [
|
|
2121
|
+
* { type: "hero", title: "Hello" },
|
|
2122
|
+
* ]);
|
|
1832
2123
|
*/
|
|
1833
2124
|
}, {
|
|
1834
2125
|
key: "render",
|
|
1835
2126
|
value: function render(input) {
|
|
1836
|
-
return new
|
|
2127
|
+
return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
|
|
1837
2128
|
}
|
|
1838
2129
|
|
|
1839
2130
|
/**
|
|
@@ -1841,13 +2132,24 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1841
2132
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
1842
2133
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
1843
2134
|
*
|
|
1844
|
-
* Without one of its own, a
|
|
1845
|
-
* takes — declare `preview` on the member objects and the union
|
|
2135
|
+
* Without one of its own, a discriminated union previews as the VARIANT the
|
|
2136
|
+
* value takes — declare `preview` on the member objects and the union
|
|
2137
|
+
* dispatches.
|
|
2138
|
+
*
|
|
2139
|
+
* @example
|
|
2140
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
2141
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
2142
|
+
* const block = s
|
|
2143
|
+
* .discriminatedUnion("type", hero, text)
|
|
2144
|
+
* .preview(({ val }) => ({ title: val.type }));
|
|
2145
|
+
* export default c.define("/example.val.ts", s.array(block), [
|
|
2146
|
+
* { type: "hero", title: "Hello" },
|
|
2147
|
+
* ]);
|
|
1846
2148
|
*/
|
|
1847
2149
|
}, {
|
|
1848
2150
|
key: "preview",
|
|
1849
2151
|
value: function preview(select) {
|
|
1850
|
-
return new
|
|
2152
|
+
return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
|
|
1851
2153
|
}
|
|
1852
2154
|
}, {
|
|
1853
2155
|
key: "executePreviewItem",
|
|
@@ -1878,34 +2180,19 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1878
2180
|
}, {
|
|
1879
2181
|
key: "executeSerialize",
|
|
1880
2182
|
value: function executeSerialize() {
|
|
1881
|
-
var _this$
|
|
1882
|
-
if (typeof this.key === "string") {
|
|
1883
|
-
var _this$renderInput, _this$customValidateF;
|
|
1884
|
-
return {
|
|
1885
|
-
type: "union",
|
|
1886
|
-
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
1887
|
-
preview: this.previewInput ? true : undefined,
|
|
1888
|
-
key: this.key,
|
|
1889
|
-
items: this.items.map(function (o) {
|
|
1890
|
-
return o["executeSerialize"]();
|
|
1891
|
-
}),
|
|
1892
|
-
opt: this.opt,
|
|
1893
|
-
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
1894
|
-
readonly: this.isReadonly,
|
|
1895
|
-
hidden: this.isHidden,
|
|
1896
|
-
description: this.description
|
|
1897
|
-
};
|
|
1898
|
-
}
|
|
2183
|
+
var _this$renderInput, _this$customValidateF;
|
|
1899
2184
|
return {
|
|
1900
|
-
type: "union",
|
|
1901
|
-
render: (_this$
|
|
2185
|
+
type: "discriminated-union",
|
|
2186
|
+
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
1902
2187
|
preview: this.previewInput ? true : undefined,
|
|
1903
|
-
key: this.key
|
|
2188
|
+
key: this.key,
|
|
2189
|
+
// Every item is an ObjectSchema — `executeValidate` reports a schema
|
|
2190
|
+
// error for anything else, but the type of `T` cannot say so.
|
|
1904
2191
|
items: this.items.map(function (o) {
|
|
1905
2192
|
return o["executeSerialize"]();
|
|
1906
2193
|
}),
|
|
1907
2194
|
opt: this.opt,
|
|
1908
|
-
customValidate: this.customValidateFunctions && ((_this$
|
|
2195
|
+
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
1909
2196
|
readonly: this.isReadonly,
|
|
1910
2197
|
hidden: this.isHidden,
|
|
1911
2198
|
description: this.description
|
|
@@ -1918,48 +2205,46 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
|
|
|
1918
2205
|
if (src === null) {
|
|
1919
2206
|
return res;
|
|
1920
2207
|
}
|
|
1921
|
-
if (this.key instanceof LiteralSchema) {
|
|
1922
|
-
return res;
|
|
1923
|
-
}
|
|
1924
2208
|
var unionKey = this.key;
|
|
1925
|
-
if (typeof unionKey
|
|
1926
|
-
var thisSchema = this.items.find(
|
|
1927
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1928
|
-
function (item) {
|
|
1929
|
-
if (item instanceof ObjectSchema) {
|
|
1930
|
-
var itemKey = item["items"][unionKey];
|
|
1931
|
-
if (itemKey instanceof LiteralSchema) {
|
|
1932
|
-
return _typeof(src) === "object" && unionKey in src && itemKey["value"] === src[unionKey];
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
return false;
|
|
1936
|
-
});
|
|
1937
|
-
if (thisSchema) {
|
|
1938
|
-
var itemResult = thisSchema["executePreview"](sourcePath, src, scope);
|
|
1939
|
-
for (var keyS in itemResult) {
|
|
1940
|
-
var _key3 = keyS;
|
|
1941
|
-
res[_key3] = itemResult[_key3];
|
|
1942
|
-
}
|
|
1943
|
-
return res;
|
|
1944
|
-
}
|
|
2209
|
+
if (typeof unionKey !== "string") {
|
|
1945
2210
|
res[sourcePath] = {
|
|
1946
2211
|
status: "error",
|
|
1947
|
-
message: "
|
|
2212
|
+
message: "The schema of this value is wrong. Expected the key of a discriminated union to be a string. Got: '".concat(JSON.stringify(unionKey, null, 2), "'")
|
|
1948
2213
|
};
|
|
2214
|
+
return res;
|
|
2215
|
+
}
|
|
2216
|
+
var thisSchema = this.items.find(
|
|
2217
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2218
|
+
function (item) {
|
|
2219
|
+
if (item instanceof ObjectSchema) {
|
|
2220
|
+
var itemKey = item["items"][unionKey];
|
|
2221
|
+
if (itemKey instanceof LiteralSchema) {
|
|
2222
|
+
return _typeof(src) === "object" && unionKey in src && itemKey["value"] === src[unionKey];
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
return false;
|
|
2226
|
+
});
|
|
2227
|
+
if (thisSchema) {
|
|
2228
|
+
var itemResult = thisSchema["executePreview"](sourcePath, src, scope);
|
|
2229
|
+
for (var keyS in itemResult) {
|
|
2230
|
+
var _key2 = keyS;
|
|
2231
|
+
res[_key2] = itemResult[_key2];
|
|
2232
|
+
}
|
|
2233
|
+
return res;
|
|
1949
2234
|
}
|
|
1950
2235
|
res[sourcePath] = {
|
|
1951
2236
|
status: "error",
|
|
1952
|
-
message: "
|
|
2237
|
+
message: "Could not find a matching (object) schema for the discriminated union key: ".concat(unionKey)
|
|
1953
2238
|
};
|
|
1954
2239
|
return res;
|
|
1955
2240
|
}
|
|
1956
2241
|
}]);
|
|
1957
2242
|
}(Schema);
|
|
1958
|
-
var
|
|
1959
|
-
for (var _len = arguments.length, objects = new Array(_len > 1 ? _len - 1 : 0),
|
|
1960
|
-
objects[
|
|
2243
|
+
var discriminatedUnion = function discriminatedUnion(key) {
|
|
2244
|
+
for (var _len = arguments.length, objects = new Array(_len > 1 ? _len - 1 : 0), _key3 = 1; _key3 < _len; _key3++) {
|
|
2245
|
+
objects[_key3 - 1] = arguments[_key3];
|
|
1961
2246
|
}
|
|
1962
|
-
return new
|
|
2247
|
+
return new DiscriminatedUnionSchema(key, objects);
|
|
1963
2248
|
};
|
|
1964
2249
|
|
|
1965
2250
|
var RegEx$1 = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
@@ -2930,17 +3215,94 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
|
|
|
2930
3215
|
_this.previewInput = previewInput;
|
|
2931
3216
|
return _this;
|
|
2932
3217
|
}
|
|
3218
|
+
|
|
3219
|
+
/**
|
|
3220
|
+
* Describe this field.
|
|
3221
|
+
*
|
|
3222
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
3223
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
3224
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
3225
|
+
* assistant and the MCP tools read.
|
|
3226
|
+
*
|
|
3227
|
+
* Pass `null` to clear a description set earlier.
|
|
3228
|
+
*
|
|
3229
|
+
* @example
|
|
3230
|
+
* const schema = s
|
|
3231
|
+
* .image()
|
|
3232
|
+
* .describe("Shown at the top of the page, 16:9 works best");
|
|
3233
|
+
* export default c.define("/example.val.ts", schema, {
|
|
3234
|
+
* path: "/public/val/example.png",
|
|
3235
|
+
* width: 100,
|
|
3236
|
+
* height: 100,
|
|
3237
|
+
* mimeType: "image/png",
|
|
3238
|
+
* });
|
|
3239
|
+
*/
|
|
2933
3240
|
_inherits(ImageSchema, _Schema);
|
|
2934
3241
|
return _createClass(ImageSchema, [{
|
|
2935
3242
|
key: "describe",
|
|
2936
3243
|
value: function describe(description) {
|
|
2937
3244
|
return new ImageSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
2938
3245
|
}
|
|
3246
|
+
|
|
3247
|
+
/**
|
|
3248
|
+
* Store the image on Val's remote content host instead of in your repository.
|
|
3249
|
+
*
|
|
3250
|
+
* The bytes still go into the patch store when the image is uploaded — the
|
|
3251
|
+
* push to the remote host happens at publish. What changes is where the
|
|
3252
|
+
* published image lives: `path` becomes a remote URL rather than a path
|
|
3253
|
+
* under `/public`, so the repository does not grow with every upload.
|
|
3254
|
+
*
|
|
3255
|
+
* The `path` of a remote image is a URL on the content host, and it is not
|
|
3256
|
+
* something to write by hand: upload the image in the Studio, or write a
|
|
3257
|
+
* local path and let `npx val validate --fix` upload it and rewrite the
|
|
3258
|
+
* `path` to the ref below.
|
|
3259
|
+
*
|
|
3260
|
+
* @example
|
|
3261
|
+
* const schema = s
|
|
3262
|
+
* .image({ accept: "image/webp", directory: "/public/val/images" })
|
|
3263
|
+
* .remote();
|
|
3264
|
+
* export default c.define("/example.val.ts", schema, {
|
|
3265
|
+
* path: "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/images/example.webp",
|
|
3266
|
+
* width: 100,
|
|
3267
|
+
* height: 100,
|
|
3268
|
+
* mimeType: "image/webp",
|
|
3269
|
+
* });
|
|
3270
|
+
*/
|
|
2939
3271
|
}, {
|
|
2940
3272
|
key: "remote",
|
|
2941
3273
|
value: function remote() {
|
|
2942
3274
|
return new ImageSchema(this.options, this.opt, true, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
2943
3275
|
}
|
|
3276
|
+
|
|
3277
|
+
/**
|
|
3278
|
+
* Add a custom validation rule to this field.
|
|
3279
|
+
*
|
|
3280
|
+
* The function is called with the field's value and returns `false` when the
|
|
3281
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
3282
|
+
* more than once to add more rules — they all run, and every message is
|
|
3283
|
+
* reported.
|
|
3284
|
+
*
|
|
3285
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
3286
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
3287
|
+
*
|
|
3288
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
3289
|
+
* before a publish.
|
|
3290
|
+
*
|
|
3291
|
+
* The second argument carries the `path` of the field being validated, for
|
|
3292
|
+
* when the message needs to say where the problem is.
|
|
3293
|
+
*
|
|
3294
|
+
* @example
|
|
3295
|
+
* const schema = s.image().validate((val) =>
|
|
3296
|
+
* val.alt ? false : "Every image needs alt text",
|
|
3297
|
+
* );
|
|
3298
|
+
* export default c.define("/example.val.ts", schema, {
|
|
3299
|
+
* path: "/public/val/example.png",
|
|
3300
|
+
* width: 100,
|
|
3301
|
+
* height: 100,
|
|
3302
|
+
* mimeType: "image/png",
|
|
3303
|
+
* alt: "An example",
|
|
3304
|
+
* });
|
|
3305
|
+
*/
|
|
2944
3306
|
}, {
|
|
2945
3307
|
key: "validate",
|
|
2946
3308
|
value: function validate(validationFunction) {
|
|
@@ -3158,6 +3520,17 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3158
3520
|
* instead of a preview row that navigates to it.
|
|
3159
3521
|
*
|
|
3160
3522
|
* Static configuration, not a callback — see `render.ts`.
|
|
3523
|
+
*
|
|
3524
|
+
* @example
|
|
3525
|
+
* const schema = s.array(s.image().render({ as: "inline" }));
|
|
3526
|
+
* export default c.define("/example.val.ts", schema, [
|
|
3527
|
+
* {
|
|
3528
|
+
* path: "/public/val/example.png",
|
|
3529
|
+
* width: 100,
|
|
3530
|
+
* height: 100,
|
|
3531
|
+
* mimeType: "image/png",
|
|
3532
|
+
* },
|
|
3533
|
+
* ]);
|
|
3161
3534
|
*/
|
|
3162
3535
|
}, {
|
|
3163
3536
|
key: "render",
|
|
@@ -3169,6 +3542,23 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3169
3542
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
3170
3543
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
3171
3544
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
3545
|
+
*
|
|
3546
|
+
* @example
|
|
3547
|
+
* const schema = s.array(
|
|
3548
|
+
* s.image().preview(({ val }) => ({
|
|
3549
|
+
* title: val.alt ?? "Image",
|
|
3550
|
+
* image: val,
|
|
3551
|
+
* })),
|
|
3552
|
+
* );
|
|
3553
|
+
* export default c.define("/example.val.ts", schema, [
|
|
3554
|
+
* {
|
|
3555
|
+
* path: "/public/val/example.png",
|
|
3556
|
+
* width: 100,
|
|
3557
|
+
* height: 100,
|
|
3558
|
+
* mimeType: "image/png",
|
|
3559
|
+
* alt: "An example",
|
|
3560
|
+
* },
|
|
3561
|
+
* ]);
|
|
3172
3562
|
*/
|
|
3173
3563
|
}, {
|
|
3174
3564
|
key: "preview",
|
|
@@ -3265,6 +3655,21 @@ var RouteSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3265
3655
|
_this.previewInput = previewInput;
|
|
3266
3656
|
return _this;
|
|
3267
3657
|
}
|
|
3658
|
+
|
|
3659
|
+
/**
|
|
3660
|
+
* Describe this field.
|
|
3661
|
+
*
|
|
3662
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
3663
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
3664
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
3665
|
+
* assistant and the MCP tools read.
|
|
3666
|
+
*
|
|
3667
|
+
* Pass `null` to clear a description set earlier.
|
|
3668
|
+
*
|
|
3669
|
+
* @example
|
|
3670
|
+
* const schema = s.route().describe("Where the button goes");
|
|
3671
|
+
* export default c.define("/example.val.ts", schema, "/a-page-slug");
|
|
3672
|
+
*/
|
|
3268
3673
|
_inherits(RouteSchema, _Schema);
|
|
3269
3674
|
return _createClass(RouteSchema, [{
|
|
3270
3675
|
key: "describe",
|
|
@@ -3311,6 +3716,27 @@ var RouteSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3311
3716
|
exclude: pattern
|
|
3312
3717
|
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
3313
3718
|
}
|
|
3719
|
+
|
|
3720
|
+
/**
|
|
3721
|
+
* Add a custom validation rule to this field.
|
|
3722
|
+
*
|
|
3723
|
+
* The function is called with the field's value and returns `false` when the
|
|
3724
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
3725
|
+
* more than once to add more rules — they all run, and every message is
|
|
3726
|
+
* reported.
|
|
3727
|
+
*
|
|
3728
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
3729
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
3730
|
+
*
|
|
3731
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
3732
|
+
* before a publish.
|
|
3733
|
+
*
|
|
3734
|
+
* @example
|
|
3735
|
+
* const schema = s.route().validate((val) =>
|
|
3736
|
+
* val.endsWith("/") ? "Leave off the trailing slash" : false,
|
|
3737
|
+
* );
|
|
3738
|
+
* export default c.define("/example.val.ts", schema, "/a-page-slug");
|
|
3739
|
+
*/
|
|
3314
3740
|
}, {
|
|
3315
3741
|
key: "validate",
|
|
3316
3742
|
value: function validate(validationFunction) {
|
|
@@ -3397,6 +3823,10 @@ var RouteSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3397
3823
|
* instead of a preview row that navigates to it.
|
|
3398
3824
|
*
|
|
3399
3825
|
* Static configuration, not a callback — see `render.ts`.
|
|
3826
|
+
*
|
|
3827
|
+
* @example
|
|
3828
|
+
* const schema = s.array(s.route().render({ as: "inline" }));
|
|
3829
|
+
* export default c.define("/example.val.ts", schema, ["/a-page-slug"]);
|
|
3400
3830
|
*/
|
|
3401
3831
|
}, {
|
|
3402
3832
|
key: "render",
|
|
@@ -3408,6 +3838,12 @@ var RouteSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3408
3838
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
3409
3839
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
3410
3840
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
3841
|
+
*
|
|
3842
|
+
* @example
|
|
3843
|
+
* const schema = s.array(
|
|
3844
|
+
* s.route().preview(({ val }) => ({ title: val })),
|
|
3845
|
+
* );
|
|
3846
|
+
* export default c.define("/example.val.ts", schema, ["/a-page-slug"]);
|
|
3411
3847
|
*/
|
|
3412
3848
|
}, {
|
|
3413
3849
|
key: "preview",
|
|
@@ -3488,12 +3924,42 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3488
3924
|
_this.previewInput = previewInput;
|
|
3489
3925
|
return _this;
|
|
3490
3926
|
}
|
|
3927
|
+
|
|
3928
|
+
/**
|
|
3929
|
+
* Describe this field.
|
|
3930
|
+
*
|
|
3931
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
3932
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
3933
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
3934
|
+
* assistant and the MCP tools read.
|
|
3935
|
+
*
|
|
3936
|
+
* Pass `null` to clear a description set earlier.
|
|
3937
|
+
*
|
|
3938
|
+
* @example
|
|
3939
|
+
* const schema = s.richtext().describe("The body of the article");
|
|
3940
|
+
* export default c.define("/example.val.ts", schema, [
|
|
3941
|
+
* { tag: "p", children: ["Hello"] },
|
|
3942
|
+
* ]);
|
|
3943
|
+
*/
|
|
3491
3944
|
_inherits(RichTextSchema, _Schema);
|
|
3492
3945
|
return _createClass(RichTextSchema, [{
|
|
3493
3946
|
key: "describe",
|
|
3494
3947
|
value: function describe(description) {
|
|
3495
3948
|
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
3496
3949
|
}
|
|
3950
|
+
|
|
3951
|
+
/**
|
|
3952
|
+
* Validate that the rich text holds at most `max` characters.
|
|
3953
|
+
*
|
|
3954
|
+
* Counted over the TEXT, not the markup: tags, attributes and the structure
|
|
3955
|
+
* of the document do not add to it.
|
|
3956
|
+
*
|
|
3957
|
+
* @example
|
|
3958
|
+
* const schema = s.richtext().maxLength(280);
|
|
3959
|
+
* export default c.define("/example.val.ts", schema, [
|
|
3960
|
+
* { tag: "p", children: ["Hello"] },
|
|
3961
|
+
* ]);
|
|
3962
|
+
*/
|
|
3497
3963
|
}, {
|
|
3498
3964
|
key: "maxLength",
|
|
3499
3965
|
value: function maxLength(max) {
|
|
@@ -3501,6 +3967,19 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3501
3967
|
maxLength: max
|
|
3502
3968
|
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
3503
3969
|
}
|
|
3970
|
+
|
|
3971
|
+
/**
|
|
3972
|
+
* Validate that the rich text holds at least `min` characters.
|
|
3973
|
+
*
|
|
3974
|
+
* Counted over the TEXT, not the markup: tags, attributes and the structure
|
|
3975
|
+
* of the document do not add to it.
|
|
3976
|
+
*
|
|
3977
|
+
* @example
|
|
3978
|
+
* const schema = s.richtext().minLength(20).maxLength(280);
|
|
3979
|
+
* export default c.define("/example.val.ts", schema, [
|
|
3980
|
+
* { tag: "p", children: ["Long enough to clear the minimum length."] },
|
|
3981
|
+
* ]);
|
|
3982
|
+
*/
|
|
3504
3983
|
}, {
|
|
3505
3984
|
key: "minLength",
|
|
3506
3985
|
value: function minLength(min) {
|
|
@@ -3508,6 +3987,29 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3508
3987
|
minLength: min
|
|
3509
3988
|
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
3510
3989
|
}
|
|
3990
|
+
|
|
3991
|
+
/**
|
|
3992
|
+
* Add a custom validation rule to this field.
|
|
3993
|
+
*
|
|
3994
|
+
* The function is called with the field's value and returns `false` when the
|
|
3995
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
3996
|
+
* more than once to add more rules — they all run, and every message is
|
|
3997
|
+
* reported.
|
|
3998
|
+
*
|
|
3999
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
4000
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
4001
|
+
*
|
|
4002
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
4003
|
+
* before a publish.
|
|
4004
|
+
*
|
|
4005
|
+
* @example
|
|
4006
|
+
* const schema = s.richtext().validate((val) =>
|
|
4007
|
+
* val.length > 0 ? false : "Write something",
|
|
4008
|
+
* );
|
|
4009
|
+
* export default c.define("/example.val.ts", schema, [
|
|
4010
|
+
* { tag: "p", children: ["Hello"] },
|
|
4011
|
+
* ]);
|
|
4012
|
+
*/
|
|
3511
4013
|
}, {
|
|
3512
4014
|
key: "validate",
|
|
3513
4015
|
value: function validate(validationFunction) {
|
|
@@ -3983,6 +4485,12 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3983
4485
|
* instead of a preview row that navigates to it.
|
|
3984
4486
|
*
|
|
3985
4487
|
* Static configuration, not a callback — see `render.ts`.
|
|
4488
|
+
*
|
|
4489
|
+
* @example
|
|
4490
|
+
* const schema = s.array(s.richtext().render({ as: "inline" }));
|
|
4491
|
+
* export default c.define("/example.val.ts", schema, [
|
|
4492
|
+
* [{ tag: "p", children: ["Hello"] }],
|
|
4493
|
+
* ]);
|
|
3986
4494
|
*/
|
|
3987
4495
|
}, {
|
|
3988
4496
|
key: "render",
|
|
@@ -3994,6 +4502,16 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
3994
4502
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
3995
4503
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
3996
4504
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
4505
|
+
*
|
|
4506
|
+
* @example
|
|
4507
|
+
* const schema = s.array(
|
|
4508
|
+
* s.richtext().preview(({ val }) => ({
|
|
4509
|
+
* title: val.length > 0 ? "Rich text" : "Empty",
|
|
4510
|
+
* })),
|
|
4511
|
+
* );
|
|
4512
|
+
* export default c.define("/example.val.ts", schema, [
|
|
4513
|
+
* [{ tag: "p", children: ["Hello"] }],
|
|
4514
|
+
* ]);
|
|
3997
4515
|
*/
|
|
3998
4516
|
}, {
|
|
3999
4517
|
key: "preview",
|
|
@@ -4502,12 +5020,55 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4502
5020
|
_this.externalLabel = externalLabel;
|
|
4503
5021
|
return _this;
|
|
4504
5022
|
}
|
|
5023
|
+
|
|
5024
|
+
/**
|
|
5025
|
+
* Describe this field.
|
|
5026
|
+
*
|
|
5027
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
5028
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
5029
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
5030
|
+
* assistant and the MCP tools read.
|
|
5031
|
+
*
|
|
5032
|
+
* Pass `null` to clear a description set earlier.
|
|
5033
|
+
*
|
|
5034
|
+
* @example
|
|
5035
|
+
* const schema = s
|
|
5036
|
+
* .record(s.string())
|
|
5037
|
+
* .describe("Button labels, keyed by locale");
|
|
5038
|
+
* export default c.define("/example.val.ts", schema, { en: "Read more" });
|
|
5039
|
+
*/
|
|
4505
5040
|
_inherits(RecordSchema, _Schema);
|
|
4506
5041
|
return _createClass(RecordSchema, [{
|
|
4507
5042
|
key: "describe",
|
|
4508
5043
|
value: function describe(description) {
|
|
4509
5044
|
return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
|
|
4510
5045
|
}
|
|
5046
|
+
|
|
5047
|
+
/**
|
|
5048
|
+
* Add a custom validation rule to this field.
|
|
5049
|
+
*
|
|
5050
|
+
* The function is called with the field's value and returns `false` when the
|
|
5051
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
5052
|
+
* more than once to add more rules — they all run, and every message is
|
|
5053
|
+
* reported.
|
|
5054
|
+
*
|
|
5055
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
5056
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
5057
|
+
*
|
|
5058
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
5059
|
+
* before a publish.
|
|
5060
|
+
*
|
|
5061
|
+
* The function is given the whole record. To validate one entry, put a
|
|
5062
|
+
* `.validate(...)` on the ITEM schema instead — that reports the error on
|
|
5063
|
+
* the entry's own row, and on a `.jsonValues()` record it does not force
|
|
5064
|
+
* every entry to be loaded.
|
|
5065
|
+
*
|
|
5066
|
+
* @example
|
|
5067
|
+
* const schema = s.record(s.string()).validate((val) =>
|
|
5068
|
+
* "en" in val ? false : "There has to be an 'en' entry",
|
|
5069
|
+
* );
|
|
5070
|
+
* export default c.define("/example.val.ts", schema, { en: "Read more" });
|
|
5071
|
+
*/
|
|
4511
5072
|
}, {
|
|
4512
5073
|
key: "validate",
|
|
4513
5074
|
value: function validate(validationFunction) {
|
|
@@ -4869,6 +5430,10 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4869
5430
|
* must come BEFORE `.external()`: afterwards the value is a `Schema`, and
|
|
4870
5431
|
* there is no `.readonly()` left to call — which is the error the compiler
|
|
4871
5432
|
* gives, and a clearer one than a runtime throw.
|
|
5433
|
+
*
|
|
5434
|
+
* @example
|
|
5435
|
+
* const schema = s.record(s.string()).readonly();
|
|
5436
|
+
* export default c.define("/example.val.ts", schema, { en: "Read more" });
|
|
4872
5437
|
*/
|
|
4873
5438
|
}, {
|
|
4874
5439
|
key: "readonly",
|
|
@@ -4882,11 +5447,54 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4882
5447
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4883
5448
|
return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
|
|
4884
5449
|
}
|
|
5450
|
+
|
|
5451
|
+
/**
|
|
5452
|
+
* Turn this record into a page router: its keys are route paths of your
|
|
5453
|
+
* application, and they are validated against the router's conventions.
|
|
5454
|
+
*
|
|
5455
|
+
* `s.router(router, item)` builds the same thing in one call and is what
|
|
5456
|
+
* most code should use — this is for adding a router to a record that
|
|
5457
|
+
* already exists.
|
|
5458
|
+
*
|
|
5459
|
+
* @example
|
|
5460
|
+
* import { nextAppRouter } from "../val.config";
|
|
5461
|
+
* const schema = s
|
|
5462
|
+
* .record(s.object({ title: s.string() }))
|
|
5463
|
+
* .router(nextAppRouter);
|
|
5464
|
+
* export default c.define("/app/[slug]/page.val.ts", schema, {
|
|
5465
|
+
* "/a-page-slug": { title: "First Page" },
|
|
5466
|
+
* });
|
|
5467
|
+
*/
|
|
4885
5468
|
}, {
|
|
4886
5469
|
key: "router",
|
|
4887
5470
|
value: function router(_router) {
|
|
4888
5471
|
return new RecordSchema(this.item, this.opt, this.customValidateFunctions, _router, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
|
|
4889
5472
|
}
|
|
5473
|
+
|
|
5474
|
+
/**
|
|
5475
|
+
* Allow the files in this gallery to be stored on Val's remote content host
|
|
5476
|
+
* instead of in your repository.
|
|
5477
|
+
*
|
|
5478
|
+
* For `s.images()` and `s.files()`, which are records of media. Remote is off
|
|
5479
|
+
* until this is called.
|
|
5480
|
+
*
|
|
5481
|
+
* Each entry is then keyed by its URL on the content host rather than by a
|
|
5482
|
+
* path under `/public`. That key is not something to write by hand: upload
|
|
5483
|
+
* in the Studio, or add a local path and let `npx val validate --fix`
|
|
5484
|
+
* upload it and rewrite the key.
|
|
5485
|
+
*
|
|
5486
|
+
* @example
|
|
5487
|
+
* const schema = s.images({ directory: "/public/val/images" }).remote();
|
|
5488
|
+
* export default c.define("/content/images.val.ts", schema, {
|
|
5489
|
+
* "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/images/hero.webp":
|
|
5490
|
+
* {
|
|
5491
|
+
* width: 1920,
|
|
5492
|
+
* height: 1080,
|
|
5493
|
+
* mimeType: "image/webp",
|
|
5494
|
+
* alt: "Hero image",
|
|
5495
|
+
* },
|
|
5496
|
+
* });
|
|
5497
|
+
*/
|
|
4890
5498
|
}, {
|
|
4891
5499
|
key: "remote",
|
|
4892
5500
|
value: function remote() {
|
|
@@ -4908,6 +5516,20 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4908
5516
|
* nested inside an object/array/record is rejected at startup with a module
|
|
4909
5517
|
* error, because the single-entry fetch endpoint, the Studio's content
|
|
4910
5518
|
* substitution and content validation are all root-only.
|
|
5519
|
+
*
|
|
5520
|
+
* Must come BEFORE `.validate()` and `.preview()`: those are typed against
|
|
5521
|
+
* the un-lazy source shape, so a validator or preview declared first cannot
|
|
5522
|
+
* be carried over, and declaring one first throws rather than silently
|
|
5523
|
+
* dropping it.
|
|
5524
|
+
*
|
|
5525
|
+
* @example
|
|
5526
|
+
* import { nextAppRouter } from "../val.config";
|
|
5527
|
+
* const schema = s
|
|
5528
|
+
* .router(nextAppRouter, s.object({ title: s.string(), body: s.string() }))
|
|
5529
|
+
* .jsonValues();
|
|
5530
|
+
* export default c.define("/app/support/[slug]/page.val.ts", schema, {
|
|
5531
|
+
* "/support/faq": c.json(() => import("./content/faq.val.json")),
|
|
5532
|
+
* });
|
|
4911
5533
|
*/
|
|
4912
5534
|
}, {
|
|
4913
5535
|
key: "jsonValues",
|
|
@@ -4955,6 +5577,19 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4955
5577
|
* nested external record would leave a hole in the middle of a module's
|
|
4956
5578
|
* source, and the Studio, patching and validation all assume a module's
|
|
4957
5579
|
* source is complete apart from its entries.
|
|
5580
|
+
*
|
|
5581
|
+
* @example
|
|
5582
|
+
* const schema = s.record(s.object({ title: s.string() })).external("posts");
|
|
5583
|
+
* export default c.define("/content/posts.val.ts", schema, c.external());
|
|
5584
|
+
*
|
|
5585
|
+
* @example
|
|
5586
|
+
* // A read-only external record: `.readonly()` must come FIRST, because
|
|
5587
|
+
* // afterwards there is no `.readonly()` left on the type to call.
|
|
5588
|
+
* const schema = s
|
|
5589
|
+
* .record(s.object({ title: s.string() }))
|
|
5590
|
+
* .readonly()
|
|
5591
|
+
* .external("posts");
|
|
5592
|
+
* export default c.define("/content/posts.val.ts", schema, c.external());
|
|
4958
5593
|
*/
|
|
4959
5594
|
}, {
|
|
4960
5595
|
key: "external",
|
|
@@ -5214,6 +5849,25 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5214
5849
|
* is the item of another container, in search, in references. What its
|
|
5215
5850
|
* entries show is the ITEM schema's `preview`, not this. Never how the field
|
|
5216
5851
|
* is edited (that is `render`). See `preview.ts`.
|
|
5852
|
+
*
|
|
5853
|
+
* @example
|
|
5854
|
+
* // The preview of the RECORD, for where it is an item of something else.
|
|
5855
|
+
* // What its own rows show is the ITEM schema's preview — see below.
|
|
5856
|
+
* const labels = s.record(s.string()).preview(({ val }) => ({
|
|
5857
|
+
* title: `${Object.keys(val).length} locales`,
|
|
5858
|
+
* }));
|
|
5859
|
+
* export default c.define("/example.val.ts", s.array(labels), [
|
|
5860
|
+
* { en: "Read more" },
|
|
5861
|
+
* ]);
|
|
5862
|
+
*
|
|
5863
|
+
* @example
|
|
5864
|
+
* // Rows of a record come from the ITEM's preview, not the record's:
|
|
5865
|
+
* const author = s
|
|
5866
|
+
* .object({ name: s.string(), role: s.string() })
|
|
5867
|
+
* .preview(({ val }) => ({ title: val.name, subtitle: val.role }));
|
|
5868
|
+
* export default c.define("/example.val.ts", s.record(author), {
|
|
5869
|
+
* ada: { name: "Ada", role: "Engineer" },
|
|
5870
|
+
* });
|
|
5217
5871
|
*/
|
|
5218
5872
|
}, {
|
|
5219
5873
|
key: "preview",
|
|
@@ -5227,6 +5881,10 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5227
5881
|
* instead of a preview row that navigates to it.
|
|
5228
5882
|
*
|
|
5229
5883
|
* Static configuration, not a callback — see `render.ts`.
|
|
5884
|
+
*
|
|
5885
|
+
* @example
|
|
5886
|
+
* const schema = s.array(s.record(s.string()).render({ as: "inline" }));
|
|
5887
|
+
* export default c.define("/example.val.ts", schema, [{ en: "Read more" }]);
|
|
5230
5888
|
*/
|
|
5231
5889
|
}, {
|
|
5232
5890
|
key: "render",
|
|
@@ -5355,12 +6013,48 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5355
6013
|
_this.previewInput = previewInput;
|
|
5356
6014
|
return _this;
|
|
5357
6015
|
}
|
|
6016
|
+
|
|
6017
|
+
/**
|
|
6018
|
+
* Describe this field.
|
|
6019
|
+
*
|
|
6020
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
6021
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
6022
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
6023
|
+
* assistant and the MCP tools read.
|
|
6024
|
+
*
|
|
6025
|
+
* Pass `null` to clear a description set earlier.
|
|
6026
|
+
*
|
|
6027
|
+
* @example
|
|
6028
|
+
* const schema = s.boolean().describe("Show this item in the main menu");
|
|
6029
|
+
* export default c.define("/example.val.ts", schema, true);
|
|
6030
|
+
*/
|
|
5358
6031
|
_inherits(BooleanSchema, _Schema);
|
|
5359
6032
|
return _createClass(BooleanSchema, [{
|
|
5360
6033
|
key: "describe",
|
|
5361
6034
|
value: function describe(description) {
|
|
5362
6035
|
return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
5363
6036
|
}
|
|
6037
|
+
|
|
6038
|
+
/**
|
|
6039
|
+
* Add a custom validation rule to this field.
|
|
6040
|
+
*
|
|
6041
|
+
* The function is called with the field's value and returns `false` when the
|
|
6042
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
6043
|
+
* more than once to add more rules — they all run, and every message is
|
|
6044
|
+
* reported.
|
|
6045
|
+
*
|
|
6046
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
6047
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
6048
|
+
*
|
|
6049
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
6050
|
+
* before a publish.
|
|
6051
|
+
*
|
|
6052
|
+
* @example
|
|
6053
|
+
* const schema = s.boolean().validate((val) =>
|
|
6054
|
+
* val === true ? false : "This has to be on for now",
|
|
6055
|
+
* );
|
|
6056
|
+
* export default c.define("/example.val.ts", schema, true);
|
|
6057
|
+
*/
|
|
5364
6058
|
}, {
|
|
5365
6059
|
key: "validate",
|
|
5366
6060
|
value: function validate(validationFunction) {
|
|
@@ -5443,6 +6137,10 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5443
6137
|
* instead of a preview row that navigates to it.
|
|
5444
6138
|
*
|
|
5445
6139
|
* Static configuration, not a callback — see `render.ts`.
|
|
6140
|
+
*
|
|
6141
|
+
* @example
|
|
6142
|
+
* const schema = s.array(s.boolean().render({ as: "inline" }));
|
|
6143
|
+
* export default c.define("/example.val.ts", schema, [true, false]);
|
|
5446
6144
|
*/
|
|
5447
6145
|
}, {
|
|
5448
6146
|
key: "render",
|
|
@@ -5454,6 +6152,12 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5454
6152
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
5455
6153
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
5456
6154
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
6155
|
+
*
|
|
6156
|
+
* @example
|
|
6157
|
+
* const schema = s.array(
|
|
6158
|
+
* s.boolean().preview(({ val }) => ({ title: val ? "On" : "Off" })),
|
|
6159
|
+
* );
|
|
6160
|
+
* export default c.define("/example.val.ts", schema, [true, false]);
|
|
5457
6161
|
*/
|
|
5458
6162
|
}, {
|
|
5459
6163
|
key: "preview",
|
|
@@ -5812,10 +6516,8 @@ function isArraySchema(schema) {
|
|
|
5812
6516
|
// );
|
|
5813
6517
|
// }
|
|
5814
6518
|
|
|
5815
|
-
function
|
|
5816
|
-
|
|
5817
|
-
) {
|
|
5818
|
-
return schema instanceof UnionSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "union";
|
|
6519
|
+
function isDiscriminatedUnionSchema(schema) {
|
|
6520
|
+
return schema instanceof DiscriminatedUnionSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "discriminated-union";
|
|
5819
6521
|
}
|
|
5820
6522
|
function isRichTextSchema(schema) {
|
|
5821
6523
|
return schema instanceof RichTextSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "richtext";
|
|
@@ -5921,27 +6623,18 @@ function resolvePath(path, valModule, schema) {
|
|
|
5921
6623
|
source: resolvedSource
|
|
5922
6624
|
}
|
|
5923
6625
|
};
|
|
5924
|
-
} else if (
|
|
5925
|
-
var _key = resolvedSchema.key;
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
if (!Number.isNaN(Number(p))) {
|
|
5931
|
-
return p;
|
|
5932
|
-
} else {
|
|
5933
|
-
return JSON.stringify(p);
|
|
5934
|
-
}
|
|
5935
|
-
}).join("."),
|
|
5936
|
-
// TODO: create a function generate path from parts (not sure if this always works)
|
|
5937
|
-
schema: resolvedSchema,
|
|
5938
|
-
source: resolvedSource
|
|
5939
|
-
}
|
|
5940
|
-
};
|
|
6626
|
+
} else if (isDiscriminatedUnionSchema(resolvedSchema)) {
|
|
6627
|
+
var _key = resolvedSchema instanceof DiscriminatedUnionSchema ? resolvedSchema["key"] : resolvedSchema.key;
|
|
6628
|
+
// A nullable union holding `null` has no variant to descend into, and
|
|
6629
|
+
// `null[key]` throws before any of the reporting below can run.
|
|
6630
|
+
if (resolvedSource === null || _typeof(resolvedSource) !== "object") {
|
|
6631
|
+
throw Error("Schema type error: expected discriminated union source to be an object, but got ".concat(resolvedSource === null ? "null" : _typeof(resolvedSource), " in path: ").concat(path));
|
|
5941
6632
|
}
|
|
5942
6633
|
var keyValue = resolvedSource[_key];
|
|
5943
|
-
|
|
5944
|
-
|
|
6634
|
+
// `undefined`, not falsy: `s.literal("")` is a legal tag, and a variant
|
|
6635
|
+
// carrying it was reported as a missing key.
|
|
6636
|
+
if (keyValue === undefined) {
|
|
6637
|
+
throw Error("Invalid path: discriminated union source ".concat(resolvedSchema, " did not have required key ").concat(_key, " in path: ").concat(path));
|
|
5945
6638
|
}
|
|
5946
6639
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5947
6640
|
var schemaOfUnionKey = resolvedSchema.items.find(
|
|
@@ -5951,7 +6644,7 @@ function resolvePath(path, valModule, schema) {
|
|
|
5951
6644
|
return (child === null || child === void 0 || (_child$items = child.items) === null || _child$items === void 0 || (_child$items = _child$items[_key]) === null || _child$items === void 0 ? void 0 : _child$items.value) === keyValue;
|
|
5952
6645
|
});
|
|
5953
6646
|
if (!schemaOfUnionKey) {
|
|
5954
|
-
throw Error("Invalid path: union schema ".concat(resolvedSchema, " did not have a child object with ").concat(_key, " of value ").concat(keyValue, " in path: ").concat(path));
|
|
6647
|
+
throw Error("Invalid path: discriminated union schema ".concat(resolvedSchema, " did not have a child object with ").concat(_key, " of value ").concat(keyValue, " in path: ").concat(path));
|
|
5955
6648
|
}
|
|
5956
6649
|
resolvedSchema = schemaOfUnionKey.items[part];
|
|
5957
6650
|
resolvedSource = resolvedSource[part];
|
|
@@ -6171,31 +6864,25 @@ function safeResolvePath(path, valModule, schema) {
|
|
|
6171
6864
|
source: resolvedSource
|
|
6172
6865
|
}
|
|
6173
6866
|
};
|
|
6174
|
-
} else if (
|
|
6175
|
-
var _key2 = resolvedSchema.key;
|
|
6176
|
-
|
|
6867
|
+
} else if (isDiscriminatedUnionSchema(resolvedSchema)) {
|
|
6868
|
+
var _key2 = resolvedSchema instanceof DiscriminatedUnionSchema ? resolvedSchema["key"] : resolvedSchema.key;
|
|
6869
|
+
// See the note in `resolvePath`: a null union has no variant to descend
|
|
6870
|
+
// into, and this API promises a structured error rather than a throw.
|
|
6871
|
+
if (resolvedSource === null || _typeof(resolvedSource) !== "object") {
|
|
6177
6872
|
return {
|
|
6178
6873
|
v: {
|
|
6179
|
-
status: "
|
|
6180
|
-
|
|
6181
|
-
if (!Number.isNaN(Number(p))) {
|
|
6182
|
-
return p;
|
|
6183
|
-
} else {
|
|
6184
|
-
return JSON.stringify(p);
|
|
6185
|
-
}
|
|
6186
|
-
}).join("."),
|
|
6187
|
-
// TODO: create a function generate path from parts (not sure if this always works)
|
|
6188
|
-
schema: resolvedSchema,
|
|
6189
|
-
source: resolvedSource
|
|
6874
|
+
status: "error",
|
|
6875
|
+
message: "Schema type error: expected discriminated union source to be an object, but got ".concat(resolvedSource === null ? "null" : _typeof(resolvedSource), " in path: ").concat(path)
|
|
6190
6876
|
}
|
|
6191
6877
|
};
|
|
6192
6878
|
}
|
|
6193
6879
|
var keyValue = resolvedSource[_key2];
|
|
6194
|
-
|
|
6880
|
+
// See the note in `resolvePath`: an empty-string tag is a present key.
|
|
6881
|
+
if (keyValue === undefined) {
|
|
6195
6882
|
return {
|
|
6196
6883
|
v: {
|
|
6197
6884
|
status: "error",
|
|
6198
|
-
message: "Invalid path: union source ".concat(resolvedSchema, " did not have required key ").concat(_key2, " in path: ").concat(path)
|
|
6885
|
+
message: "Invalid path: discriminated union source ".concat(resolvedSchema, " did not have required key ").concat(_key2, " in path: ").concat(path)
|
|
6199
6886
|
}
|
|
6200
6887
|
};
|
|
6201
6888
|
}
|
|
@@ -6210,7 +6897,7 @@ function safeResolvePath(path, valModule, schema) {
|
|
|
6210
6897
|
return {
|
|
6211
6898
|
v: {
|
|
6212
6899
|
status: "error",
|
|
6213
|
-
message: "Invalid path: union schema ".concat(resolvedSchema, " did not have a child object with ").concat(_key2, " of value ").concat(keyValue, " in path: ").concat(path)
|
|
6900
|
+
message: "Invalid path: discriminated union schema ".concat(resolvedSchema, " did not have a child object with ").concat(_key2, " of value ").concat(keyValue, " in path: ").concat(path)
|
|
6214
6901
|
}
|
|
6215
6902
|
};
|
|
6216
6903
|
}
|
|
@@ -6347,12 +7034,48 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6347
7034
|
_this.previewInput = previewInput;
|
|
6348
7035
|
return _this;
|
|
6349
7036
|
}
|
|
7037
|
+
|
|
7038
|
+
/**
|
|
7039
|
+
* Describe this field.
|
|
7040
|
+
*
|
|
7041
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
7042
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
7043
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
7044
|
+
* assistant and the MCP tools read.
|
|
7045
|
+
*
|
|
7046
|
+
* Pass `null` to clear a description set earlier.
|
|
7047
|
+
*
|
|
7048
|
+
* @example
|
|
7049
|
+
* const schema = s.number().describe("How many columns the grid uses");
|
|
7050
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
7051
|
+
*/
|
|
6350
7052
|
_inherits(NumberSchema, _Schema);
|
|
6351
7053
|
return _createClass(NumberSchema, [{
|
|
6352
7054
|
key: "describe",
|
|
6353
7055
|
value: function describe(description) {
|
|
6354
7056
|
return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
6355
7057
|
}
|
|
7058
|
+
|
|
7059
|
+
/**
|
|
7060
|
+
* Add a custom validation rule to this field.
|
|
7061
|
+
*
|
|
7062
|
+
* The function is called with the field's value and returns `false` when the
|
|
7063
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
7064
|
+
* more than once to add more rules — they all run, and every message is
|
|
7065
|
+
* reported.
|
|
7066
|
+
*
|
|
7067
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
7068
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
7069
|
+
*
|
|
7070
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
7071
|
+
* before a publish.
|
|
7072
|
+
*
|
|
7073
|
+
* @example
|
|
7074
|
+
* const schema = s.number().validate((val) =>
|
|
7075
|
+
* Number.isInteger(val) ? false : "Must be a whole number",
|
|
7076
|
+
* );
|
|
7077
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
7078
|
+
*/
|
|
6356
7079
|
}, {
|
|
6357
7080
|
key: "validate",
|
|
6358
7081
|
value: function validate(validationFunction) {
|
|
@@ -6440,6 +7163,14 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6440
7163
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
6441
7164
|
return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
|
|
6442
7165
|
}
|
|
7166
|
+
|
|
7167
|
+
/**
|
|
7168
|
+
* Validate that the number is at most `max` (inclusive).
|
|
7169
|
+
*
|
|
7170
|
+
* @example
|
|
7171
|
+
* const schema = s.number().max(4);
|
|
7172
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
7173
|
+
*/
|
|
6443
7174
|
}, {
|
|
6444
7175
|
key: "max",
|
|
6445
7176
|
value: function max(_max) {
|
|
@@ -6447,6 +7178,14 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6447
7178
|
max: _max
|
|
6448
7179
|
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
6449
7180
|
}
|
|
7181
|
+
|
|
7182
|
+
/**
|
|
7183
|
+
* Validate that the number is at least `min` (inclusive).
|
|
7184
|
+
*
|
|
7185
|
+
* @example
|
|
7186
|
+
* const schema = s.number().min(1).max(4);
|
|
7187
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
7188
|
+
*/
|
|
6450
7189
|
}, {
|
|
6451
7190
|
key: "min",
|
|
6452
7191
|
value: function min(_min) {
|
|
@@ -6468,6 +7207,10 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6468
7207
|
* instead of a preview row that navigates to it.
|
|
6469
7208
|
*
|
|
6470
7209
|
* Static configuration, not a callback — see `render.ts`.
|
|
7210
|
+
*
|
|
7211
|
+
* @example
|
|
7212
|
+
* const schema = s.array(s.number().render({ as: "inline" }));
|
|
7213
|
+
* export default c.define("/example.val.ts", schema, [1, 2]);
|
|
6471
7214
|
*/
|
|
6472
7215
|
}, {
|
|
6473
7216
|
key: "render",
|
|
@@ -6479,6 +7222,12 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6479
7222
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
6480
7223
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
6481
7224
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
7225
|
+
*
|
|
7226
|
+
* @example
|
|
7227
|
+
* const schema = s.array(
|
|
7228
|
+
* s.number().preview(({ val }) => ({ title: String(val) })),
|
|
7229
|
+
* );
|
|
7230
|
+
* export default c.define("/example.val.ts", schema, [1, 2]);
|
|
6482
7231
|
*/
|
|
6483
7232
|
}, {
|
|
6484
7233
|
key: "preview",
|
|
@@ -6521,11 +7270,363 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6521
7270
|
value: function executePreview() {
|
|
6522
7271
|
return {};
|
|
6523
7272
|
}
|
|
6524
|
-
}]);
|
|
6525
|
-
}(Schema);
|
|
6526
|
-
var number = function number(options) {
|
|
6527
|
-
return new NumberSchema(options);
|
|
6528
|
-
};
|
|
7273
|
+
}]);
|
|
7274
|
+
}(Schema);
|
|
7275
|
+
var number = function number(options) {
|
|
7276
|
+
return new NumberSchema(options);
|
|
7277
|
+
};
|
|
7278
|
+
|
|
7279
|
+
/**
|
|
7280
|
+
* One of a fixed set of strings.
|
|
7281
|
+
*
|
|
7282
|
+
* The values are the schema — there are no member schemas to descend into, so
|
|
7283
|
+
* this is a LEAF, like `s.string()` with a closed domain. That is the whole
|
|
7284
|
+
* difference from {@link DiscriminatedUnionSchema}, and the reason the two are
|
|
7285
|
+
* separate: everything that walks a schema tree has to recurse into a
|
|
7286
|
+
* discriminated union's variants and must not try to recurse into these.
|
|
7287
|
+
*/
|
|
7288
|
+
var EnumSchema = /*#__PURE__*/function (_Schema) {
|
|
7289
|
+
function EnumSchema(values) {
|
|
7290
|
+
var _this;
|
|
7291
|
+
var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
7292
|
+
var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
7293
|
+
var isReadonly = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
7294
|
+
var isHidden = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
7295
|
+
var description = arguments.length > 5 ? arguments[5] : undefined;
|
|
7296
|
+
var renderInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
|
|
7297
|
+
var previewInput = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
|
|
7298
|
+
_classCallCheck(this, EnumSchema);
|
|
7299
|
+
_this = _callSuper(this, EnumSchema);
|
|
7300
|
+
_this.values = values;
|
|
7301
|
+
_this.opt = opt;
|
|
7302
|
+
_this.customValidateFunctions = customValidateFunctions;
|
|
7303
|
+
_this.isReadonly = isReadonly;
|
|
7304
|
+
_this.isHidden = isHidden;
|
|
7305
|
+
_this.description = description;
|
|
7306
|
+
_this.renderInput = renderInput;
|
|
7307
|
+
_this.previewInput = previewInput;
|
|
7308
|
+
return _this;
|
|
7309
|
+
}
|
|
7310
|
+
|
|
7311
|
+
/**
|
|
7312
|
+
* Describe this field.
|
|
7313
|
+
*
|
|
7314
|
+
* The description is shown next to the field's label in the Val editor, so it is
|
|
7315
|
+
* where you say what an editor needs to know but the field name cannot carry. It
|
|
7316
|
+
* also travels in the serialized schema, which is what the AI assistant and the
|
|
7317
|
+
* MCP tools read.
|
|
7318
|
+
*
|
|
7319
|
+
* Pass `null` to clear a description set earlier.
|
|
7320
|
+
*
|
|
7321
|
+
* @example
|
|
7322
|
+
* const schema = s
|
|
7323
|
+
* .enum("draft", "published")
|
|
7324
|
+
* .describe("Only published pages are built");
|
|
7325
|
+
* export default c.define("/example.val.ts", schema, "draft");
|
|
7326
|
+
*/
|
|
7327
|
+
_inherits(EnumSchema, _Schema);
|
|
7328
|
+
return _createClass(EnumSchema, [{
|
|
7329
|
+
key: "describe",
|
|
7330
|
+
value: function describe(description) {
|
|
7331
|
+
return new EnumSchema(this.values, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
7332
|
+
}
|
|
7333
|
+
|
|
7334
|
+
/**
|
|
7335
|
+
* Add a custom validation rule to this field.
|
|
7336
|
+
*
|
|
7337
|
+
* The function is called with the field's value and returns `false` when the
|
|
7338
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
7339
|
+
* more than once to add more rules — they all run, and every message is
|
|
7340
|
+
* reported.
|
|
7341
|
+
*
|
|
7342
|
+
* Validation runs in the Studio as you type, in `npx val validate` and before a
|
|
7343
|
+
* publish.
|
|
7344
|
+
*
|
|
7345
|
+
* @example
|
|
7346
|
+
* const schema = s
|
|
7347
|
+
* .enum("draft", "published")
|
|
7348
|
+
* .validate((val) =>
|
|
7349
|
+
* val === "published" ? "Publishing is frozen this week" : false,
|
|
7350
|
+
* );
|
|
7351
|
+
* export default c.define("/example.val.ts", schema, "draft");
|
|
7352
|
+
*/
|
|
7353
|
+
}, {
|
|
7354
|
+
key: "validate",
|
|
7355
|
+
value: function validate(validationFunction) {
|
|
7356
|
+
return new EnumSchema(this.values, this.opt, this.customValidateFunctions.concat(validationFunction), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
7357
|
+
}
|
|
7358
|
+
}, {
|
|
7359
|
+
key: "executeValidate",
|
|
7360
|
+
value: function executeValidate(path, src) {
|
|
7361
|
+
var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
7362
|
+
path: path
|
|
7363
|
+
});
|
|
7364
|
+
// The custom validators always report, whatever the structural answer is.
|
|
7365
|
+
var errors = customValidationErrors;
|
|
7366
|
+
var unknownSrc = src;
|
|
7367
|
+
if (this.opt && (unknownSrc === null || unknownSrc === undefined)) {
|
|
7368
|
+
return errors.length > 0 ? _defineProperty({}, path, errors) : false;
|
|
7369
|
+
}
|
|
7370
|
+
if (!Array.isArray(this.values) || this.values.length === 0) {
|
|
7371
|
+
errors.push({
|
|
7372
|
+
message: "An enum schema must have at least one value",
|
|
7373
|
+
schemaError: true
|
|
7374
|
+
});
|
|
7375
|
+
} else if (typeof unknownSrc !== "string") {
|
|
7376
|
+
errors.push({
|
|
7377
|
+
message: "Expected 'string', got '".concat(unknownSrc === null ? "null" : _typeof(unknownSrc), "'"),
|
|
7378
|
+
value: src,
|
|
7379
|
+
typeError: true
|
|
7380
|
+
});
|
|
7381
|
+
} else if (!this.values.includes(unknownSrc)) {
|
|
7382
|
+
errors.push({
|
|
7383
|
+
message: "Value must be one of the following: ".concat(this.values.map(function (value) {
|
|
7384
|
+
return "\"".concat(value, "\"");
|
|
7385
|
+
}).join(", ")),
|
|
7386
|
+
value: src
|
|
7387
|
+
});
|
|
7388
|
+
}
|
|
7389
|
+
return errors.length > 0 ? _defineProperty({}, path, errors) : false;
|
|
7390
|
+
}
|
|
7391
|
+
}, {
|
|
7392
|
+
key: "executeAssert",
|
|
7393
|
+
value: function executeAssert(path, src) {
|
|
7394
|
+
if (this.opt && src === null) {
|
|
7395
|
+
return {
|
|
7396
|
+
success: true,
|
|
7397
|
+
data: src
|
|
7398
|
+
};
|
|
7399
|
+
}
|
|
7400
|
+
var errors = {};
|
|
7401
|
+
if (typeof src !== "string") {
|
|
7402
|
+
errors[path] = [{
|
|
7403
|
+
message: "Expected 'string', got '".concat(src === null ? "null" : _typeof(src), "'"),
|
|
7404
|
+
typeError: true
|
|
7405
|
+
}];
|
|
7406
|
+
return {
|
|
7407
|
+
success: false,
|
|
7408
|
+
errors: errors
|
|
7409
|
+
};
|
|
7410
|
+
}
|
|
7411
|
+
if (!Array.isArray(this.values) || this.values.length === 0) {
|
|
7412
|
+
errors[path] = [{
|
|
7413
|
+
message: "An enum schema must have at least one value",
|
|
7414
|
+
schemaError: true
|
|
7415
|
+
}];
|
|
7416
|
+
return {
|
|
7417
|
+
success: false,
|
|
7418
|
+
errors: errors
|
|
7419
|
+
};
|
|
7420
|
+
}
|
|
7421
|
+
if (!this.values.includes(src)) {
|
|
7422
|
+
errors[path] = [{
|
|
7423
|
+
message: "Expected one of ".concat(this.values.map(function (value) {
|
|
7424
|
+
return "'".concat(value, "'");
|
|
7425
|
+
}).join(", "), ", got '").concat(src, "'"),
|
|
7426
|
+
typeError: true
|
|
7427
|
+
}];
|
|
7428
|
+
return {
|
|
7429
|
+
success: false,
|
|
7430
|
+
errors: errors
|
|
7431
|
+
};
|
|
7432
|
+
}
|
|
7433
|
+
return {
|
|
7434
|
+
success: true,
|
|
7435
|
+
data: src
|
|
7436
|
+
};
|
|
7437
|
+
}
|
|
7438
|
+
}, {
|
|
7439
|
+
key: "nullable",
|
|
7440
|
+
value: function nullable() {
|
|
7441
|
+
// Explicit type args: `previewInput` would otherwise pin inference to `Src`.
|
|
7442
|
+
return new EnumSchema(this.values, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
7443
|
+
}
|
|
7444
|
+
}, {
|
|
7445
|
+
key: "readonly",
|
|
7446
|
+
value: function readonly() {
|
|
7447
|
+
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
7448
|
+
return new EnumSchema(this.values, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
7449
|
+
}
|
|
7450
|
+
}, {
|
|
7451
|
+
key: "hidden",
|
|
7452
|
+
value: function hidden() {
|
|
7453
|
+
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
7454
|
+
return new EnumSchema(this.values, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
|
|
7455
|
+
}
|
|
7456
|
+
}, {
|
|
7457
|
+
key: "executeCustomValidateAt",
|
|
7458
|
+
value: function executeCustomValidateAt(path, src) {
|
|
7459
|
+
return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
7460
|
+
path: path
|
|
7461
|
+
});
|
|
7462
|
+
}
|
|
7463
|
+
|
|
7464
|
+
/**
|
|
7465
|
+
* How this field is laid out in the editor when it is the item of an array
|
|
7466
|
+
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
7467
|
+
* instead of a preview row that navigates to it.
|
|
7468
|
+
*
|
|
7469
|
+
* Static configuration, not a callback — see `render.ts`.
|
|
7470
|
+
*
|
|
7471
|
+
* @example
|
|
7472
|
+
* const schema = s.array(
|
|
7473
|
+
* s.enum("draft", "published").render({ as: "inline" }),
|
|
7474
|
+
* );
|
|
7475
|
+
* export default c.define("/example.val.ts", schema, ["draft"]);
|
|
7476
|
+
*/
|
|
7477
|
+
}, {
|
|
7478
|
+
key: "render",
|
|
7479
|
+
value: function render(input) {
|
|
7480
|
+
return new EnumSchema(this.values, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
|
|
7481
|
+
}
|
|
7482
|
+
|
|
7483
|
+
/**
|
|
7484
|
+
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
7485
|
+
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
7486
|
+
* itself is edited (that is `render`). See `preview.ts`.
|
|
7487
|
+
*
|
|
7488
|
+
* @example
|
|
7489
|
+
* const schema = s.array(
|
|
7490
|
+
* s.enum("draft", "published").preview(({ val }) => ({ title: val })),
|
|
7491
|
+
* );
|
|
7492
|
+
* export default c.define("/example.val.ts", schema, ["draft"]);
|
|
7493
|
+
*/
|
|
7494
|
+
}, {
|
|
7495
|
+
key: "preview",
|
|
7496
|
+
value: function preview(select) {
|
|
7497
|
+
return new EnumSchema(this.values, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
|
|
7498
|
+
}
|
|
7499
|
+
}, {
|
|
7500
|
+
key: "executePreviewItem",
|
|
7501
|
+
value: function executePreviewItem(src) {
|
|
7502
|
+
if (this.previewInput === null) {
|
|
7503
|
+
return null;
|
|
7504
|
+
}
|
|
7505
|
+
return this.previewInput({
|
|
7506
|
+
val: src
|
|
7507
|
+
});
|
|
7508
|
+
}
|
|
7509
|
+
}, {
|
|
7510
|
+
key: "declaresItemPreview",
|
|
7511
|
+
value: function declaresItemPreview() {
|
|
7512
|
+
return this.previewInput !== null;
|
|
7513
|
+
}
|
|
7514
|
+
}, {
|
|
7515
|
+
key: "executeSerialize",
|
|
7516
|
+
value: function executeSerialize() {
|
|
7517
|
+
var _this$renderInput, _this$customValidateF;
|
|
7518
|
+
return {
|
|
7519
|
+
type: "enum",
|
|
7520
|
+
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
7521
|
+
preview: this.previewInput ? true : undefined,
|
|
7522
|
+
values: _toConsumableArray(this.values),
|
|
7523
|
+
opt: this.opt,
|
|
7524
|
+
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
7525
|
+
readonly: this.isReadonly,
|
|
7526
|
+
hidden: this.isHidden,
|
|
7527
|
+
description: this.description
|
|
7528
|
+
};
|
|
7529
|
+
}
|
|
7530
|
+
}, {
|
|
7531
|
+
key: "executePreview",
|
|
7532
|
+
value: function executePreview() {
|
|
7533
|
+
// A leaf: nothing below it to preview.
|
|
7534
|
+
return {};
|
|
7535
|
+
}
|
|
7536
|
+
}]);
|
|
7537
|
+
}(Schema);
|
|
7538
|
+
|
|
7539
|
+
/**
|
|
7540
|
+
* Define a string that must be one of a fixed set of values.
|
|
7541
|
+
*
|
|
7542
|
+
* Named `enumSchema` rather than `enum` because `enum` is a reserved word and
|
|
7543
|
+
* cannot be a binding name; it is exposed as `s.enum`.
|
|
7544
|
+
*/
|
|
7545
|
+
var enumSchema = function enumSchema() {
|
|
7546
|
+
for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
7547
|
+
values[_key] = arguments[_key];
|
|
7548
|
+
}
|
|
7549
|
+
return new EnumSchema(values);
|
|
7550
|
+
};
|
|
7551
|
+
|
|
7552
|
+
/**
|
|
7553
|
+
* @deprecated Use {@link SerializedDiscriminatedUnionSchema} or
|
|
7554
|
+
* {@link SerializedEnumSchema}. A serialized union is now one or the other,
|
|
7555
|
+
* distinguished by `type` rather than by the shape of `key`.
|
|
7556
|
+
*/
|
|
7557
|
+
|
|
7558
|
+
/** @deprecated Use {@link SerializedEnumSchema}. */
|
|
7559
|
+
|
|
7560
|
+
/** @deprecated Use {@link SerializedDiscriminatedUnionSchema}. */
|
|
7561
|
+
|
|
7562
|
+
/**
|
|
7563
|
+
* @deprecated There is no single union schema class any more: name
|
|
7564
|
+
* {@link DiscriminatedUnionSchema} or {@link EnumSchema}. The type parameters
|
|
7565
|
+
* are kept so existing annotations still compile, but only `Src` is used.
|
|
7566
|
+
*/
|
|
7567
|
+
|
|
7568
|
+
/**
|
|
7569
|
+
* The value type of a list of literal schemas — how `s.union` typed a union of
|
|
7570
|
+
* literals. Inferred from `Schema<infer S>` rather than `LiteralSchema<infer S>`
|
|
7571
|
+
* because a `LiteralSchema` is invariant in its source (its custom validate
|
|
7572
|
+
* functions put it in a parameter position), so `LiteralSchema<"a">` is not
|
|
7573
|
+
* assignable to `LiteralSchema<"a" | "b">`.
|
|
7574
|
+
*/
|
|
7575
|
+
|
|
7576
|
+
/**
|
|
7577
|
+
* @deprecated Use `s.discriminatedUnion(key, ...objects)` for a tagged union of
|
|
7578
|
+
* objects, or `s.enum("a", "b")` for one of a fixed set of strings.
|
|
7579
|
+
*
|
|
7580
|
+
* One thing does NOT survive the literal form: an enum's values are strings,
|
|
7581
|
+
* so a member literal's own `.validate()` and `.describe()` are dropped rather
|
|
7582
|
+
* than carried over. `s.union(s.literal("a").validate(...), ...)` ran that
|
|
7583
|
+
* validator as part of deciding whether the value matched; `s.enum` has no
|
|
7584
|
+
* member to run. A validator on a single-valued literal could only accept or
|
|
7585
|
+
* reject that one value, which the enum's own value list already decides — but
|
|
7586
|
+
* if you rely on one, keep it by validating the enum itself.
|
|
7587
|
+
*
|
|
7588
|
+
* @example
|
|
7589
|
+
* // was: s.union("type", s.object({ type: s.literal("a"), a: s.string() }))
|
|
7590
|
+
* const schema = s.discriminatedUnion(
|
|
7591
|
+
* "type",
|
|
7592
|
+
* s.object({ type: s.literal("a"), a: s.string() }),
|
|
7593
|
+
* );
|
|
7594
|
+
* export default c.define("/example.val.ts", schema, { type: "a", a: "one" });
|
|
7595
|
+
*
|
|
7596
|
+
* @example
|
|
7597
|
+
* // was: s.union(s.literal("a"), s.literal("b"))
|
|
7598
|
+
* const schema = s.enum("a", "b");
|
|
7599
|
+
* export default c.define("/example.val.ts", schema, "a");
|
|
7600
|
+
*/
|
|
7601
|
+
|
|
7602
|
+
function union(keyOrFirstLiteral) {
|
|
7603
|
+
for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
7604
|
+
rest[_key - 1] = arguments[_key];
|
|
7605
|
+
}
|
|
7606
|
+
if (typeof keyOrFirstLiteral === "string") {
|
|
7607
|
+
return new DiscriminatedUnionSchema(keyOrFirstLiteral, rest);
|
|
7608
|
+
}
|
|
7609
|
+
// A literal union is an enum: the values ARE the schema, so the literals are
|
|
7610
|
+
// flattened into them. `key` was only ever the first member.
|
|
7611
|
+
var literals = [keyOrFirstLiteral].concat(rest);
|
|
7612
|
+
var values = [];
|
|
7613
|
+
var _iterator = _createForOfIteratorHelper(literals),
|
|
7614
|
+
_step;
|
|
7615
|
+
try {
|
|
7616
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
7617
|
+
var literal = _step.value;
|
|
7618
|
+
if (!(literal instanceof LiteralSchema)) {
|
|
7619
|
+
throw new Error("s.union: expected either a string key followed by object schemas, or literal schemas. Got: ".concat(JSON.stringify(literal)));
|
|
7620
|
+
}
|
|
7621
|
+
values.push(literal["value"]);
|
|
7622
|
+
}
|
|
7623
|
+
} catch (err) {
|
|
7624
|
+
_iterator.e(err);
|
|
7625
|
+
} finally {
|
|
7626
|
+
_iterator.f();
|
|
7627
|
+
}
|
|
7628
|
+
return new EnumSchema(values);
|
|
7629
|
+
}
|
|
6529
7630
|
|
|
6530
7631
|
var KeyOfSchema = /*#__PURE__*/function (_Schema) {
|
|
6531
7632
|
function KeyOfSchema(schema, sourcePath) {
|
|
@@ -6550,12 +7651,52 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6550
7651
|
_this.previewInput = previewInput;
|
|
6551
7652
|
return _this;
|
|
6552
7653
|
}
|
|
7654
|
+
|
|
7655
|
+
/**
|
|
7656
|
+
* Describe this field.
|
|
7657
|
+
*
|
|
7658
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
7659
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
7660
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
7661
|
+
* assistant and the MCP tools read.
|
|
7662
|
+
*
|
|
7663
|
+
* Pass `null` to clear a description set earlier.
|
|
7664
|
+
*
|
|
7665
|
+
* @example
|
|
7666
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
7667
|
+
* const schema = s.keyOf(authorsVal).describe("Who wrote this post");
|
|
7668
|
+
* export default c.define("/example.val.ts", schema, "ada");
|
|
7669
|
+
*/
|
|
6553
7670
|
_inherits(KeyOfSchema, _Schema);
|
|
6554
7671
|
return _createClass(KeyOfSchema, [{
|
|
6555
7672
|
key: "describe",
|
|
6556
7673
|
value: function describe(description) {
|
|
6557
7674
|
return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
6558
7675
|
}
|
|
7676
|
+
|
|
7677
|
+
/**
|
|
7678
|
+
* Add a custom validation rule to this field.
|
|
7679
|
+
*
|
|
7680
|
+
* The function is called with the field's value and returns `false` when the
|
|
7681
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
7682
|
+
* more than once to add more rules — they all run, and every message is
|
|
7683
|
+
* reported.
|
|
7684
|
+
*
|
|
7685
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
7686
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
7687
|
+
*
|
|
7688
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
7689
|
+
* before a publish.
|
|
7690
|
+
*
|
|
7691
|
+
* @example
|
|
7692
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
7693
|
+
* const schema = s
|
|
7694
|
+
* .keyOf(authorsVal)
|
|
7695
|
+
* .validate((val) =>
|
|
7696
|
+
* val === "placeholder" ? "Pick a real author" : false,
|
|
7697
|
+
* );
|
|
7698
|
+
* export default c.define("/example.val.ts", schema, "ada");
|
|
7699
|
+
*/
|
|
6559
7700
|
}, {
|
|
6560
7701
|
key: "validate",
|
|
6561
7702
|
value: function validate(validationFunction) {
|
|
@@ -6717,6 +7858,11 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6717
7858
|
* instead of a preview row that navigates to it.
|
|
6718
7859
|
*
|
|
6719
7860
|
* Static configuration, not a callback — see `render.ts`.
|
|
7861
|
+
*
|
|
7862
|
+
* @example
|
|
7863
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
7864
|
+
* const schema = s.array(s.keyOf(authorsVal).render({ as: "inline" }));
|
|
7865
|
+
* export default c.define("/example.val.ts", schema, ["ada"]);
|
|
6720
7866
|
*/
|
|
6721
7867
|
}, {
|
|
6722
7868
|
key: "render",
|
|
@@ -6728,6 +7874,13 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6728
7874
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
6729
7875
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
6730
7876
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
7877
|
+
*
|
|
7878
|
+
* @example
|
|
7879
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
7880
|
+
* const schema = s.array(
|
|
7881
|
+
* s.keyOf(authorsVal).preview(({ val }) => ({ title: val })),
|
|
7882
|
+
* );
|
|
7883
|
+
* export default c.define("/example.val.ts", schema, ["ada"]);
|
|
6731
7884
|
*/
|
|
6732
7885
|
}, {
|
|
6733
7886
|
key: "preview",
|
|
@@ -6844,17 +7997,83 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6844
7997
|
_this.previewInput = previewInput;
|
|
6845
7998
|
return _this;
|
|
6846
7999
|
}
|
|
8000
|
+
|
|
8001
|
+
/**
|
|
8002
|
+
* Describe this field.
|
|
8003
|
+
*
|
|
8004
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
8005
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
8006
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
8007
|
+
* assistant and the MCP tools read.
|
|
8008
|
+
*
|
|
8009
|
+
* Pass `null` to clear a description set earlier.
|
|
8010
|
+
*
|
|
8011
|
+
* @example
|
|
8012
|
+
* const schema = s.file().describe("The PDF offered for download");
|
|
8013
|
+
* export default c.define("/example.val.ts", schema, {
|
|
8014
|
+
* path: "/public/val/example.pdf",
|
|
8015
|
+
* mimeType: "application/pdf",
|
|
8016
|
+
* });
|
|
8017
|
+
*/
|
|
6847
8018
|
_inherits(FileSchema, _Schema);
|
|
6848
8019
|
return _createClass(FileSchema, [{
|
|
6849
8020
|
key: "describe",
|
|
6850
8021
|
value: function describe(description) {
|
|
6851
8022
|
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
6852
8023
|
}
|
|
8024
|
+
|
|
8025
|
+
/**
|
|
8026
|
+
* Store the file on Val's remote content host instead of in your repository.
|
|
8027
|
+
*
|
|
8028
|
+
* The bytes still go into the patch store when the file is uploaded — the
|
|
8029
|
+
* push to the remote host happens at publish. What changes is where the
|
|
8030
|
+
* published file lives: `path` becomes a remote URL rather than a path under
|
|
8031
|
+
* `/public`, so the repository does not grow with every upload.
|
|
8032
|
+
*
|
|
8033
|
+
* The `path` of a remote file is a URL on the content host, and it is not
|
|
8034
|
+
* something to write by hand: upload the file in the Studio, or write a
|
|
8035
|
+
* local path and let `npx val validate --fix` upload it and rewrite the
|
|
8036
|
+
* `path` to the ref below.
|
|
8037
|
+
*
|
|
8038
|
+
* @example
|
|
8039
|
+
* const schema = s.file({ accept: "application/pdf" }).remote();
|
|
8040
|
+
* export default c.define("/example.val.ts", schema, {
|
|
8041
|
+
* path: "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/example.pdf",
|
|
8042
|
+
* mimeType: "application/pdf",
|
|
8043
|
+
* });
|
|
8044
|
+
*/
|
|
6853
8045
|
}, {
|
|
6854
8046
|
key: "remote",
|
|
6855
8047
|
value: function remote() {
|
|
6856
8048
|
return new FileSchema(this.options, this.opt, true, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
6857
8049
|
}
|
|
8050
|
+
|
|
8051
|
+
/**
|
|
8052
|
+
* Add a custom validation rule to this field.
|
|
8053
|
+
*
|
|
8054
|
+
* The function is called with the field's value and returns `false` when the
|
|
8055
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
8056
|
+
* more than once to add more rules — they all run, and every message is
|
|
8057
|
+
* reported.
|
|
8058
|
+
*
|
|
8059
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
8060
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
8061
|
+
*
|
|
8062
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
8063
|
+
* before a publish.
|
|
8064
|
+
*
|
|
8065
|
+
* The second argument carries the `path` of the field being validated, for
|
|
8066
|
+
* when the message needs to say where the problem is.
|
|
8067
|
+
*
|
|
8068
|
+
* @example
|
|
8069
|
+
* const schema = s.file().validate((val) =>
|
|
8070
|
+
* val.path.endsWith(".pdf") ? false : "Must be a PDF",
|
|
8071
|
+
* );
|
|
8072
|
+
* export default c.define("/example.val.ts", schema, {
|
|
8073
|
+
* path: "/public/val/example.pdf",
|
|
8074
|
+
* mimeType: "application/pdf",
|
|
8075
|
+
* });
|
|
8076
|
+
*/
|
|
6858
8077
|
}, {
|
|
6859
8078
|
key: "validate",
|
|
6860
8079
|
value: function validate(validationFunction) {
|
|
@@ -7061,6 +8280,12 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7061
8280
|
* instead of a preview row that navigates to it.
|
|
7062
8281
|
*
|
|
7063
8282
|
* Static configuration, not a callback — see `render.ts`.
|
|
8283
|
+
*
|
|
8284
|
+
* @example
|
|
8285
|
+
* const schema = s.array(s.file().render({ as: "inline" }));
|
|
8286
|
+
* export default c.define("/example.val.ts", schema, [
|
|
8287
|
+
* { path: "/public/val/example.pdf", mimeType: "application/pdf" },
|
|
8288
|
+
* ]);
|
|
7064
8289
|
*/
|
|
7065
8290
|
}, {
|
|
7066
8291
|
key: "render",
|
|
@@ -7072,6 +8297,14 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7072
8297
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
7073
8298
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
7074
8299
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
8300
|
+
*
|
|
8301
|
+
* @example
|
|
8302
|
+
* const schema = s.array(
|
|
8303
|
+
* s.file().preview(({ val }) => ({ title: val.path })),
|
|
8304
|
+
* );
|
|
8305
|
+
* export default c.define("/example.val.ts", schema, [
|
|
8306
|
+
* { path: "/public/val/example.pdf", mimeType: "application/pdf" },
|
|
8307
|
+
* ]);
|
|
7075
8308
|
*/
|
|
7076
8309
|
}, {
|
|
7077
8310
|
key: "preview",
|
|
@@ -7205,12 +8438,48 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7205
8438
|
_this.previewInput = previewInput;
|
|
7206
8439
|
return _this;
|
|
7207
8440
|
}
|
|
8441
|
+
|
|
8442
|
+
/**
|
|
8443
|
+
* Describe this field.
|
|
8444
|
+
*
|
|
8445
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
8446
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
8447
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
8448
|
+
* assistant and the MCP tools read.
|
|
8449
|
+
*
|
|
8450
|
+
* Pass `null` to clear a description set earlier.
|
|
8451
|
+
*
|
|
8452
|
+
* @example
|
|
8453
|
+
* const schema = s.date().describe("First day the campaign is live");
|
|
8454
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
8455
|
+
*/
|
|
7208
8456
|
_inherits(DateSchema, _Schema);
|
|
7209
8457
|
return _createClass(DateSchema, [{
|
|
7210
8458
|
key: "describe",
|
|
7211
8459
|
value: function describe(description) {
|
|
7212
8460
|
return new DateSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
7213
8461
|
}
|
|
8462
|
+
|
|
8463
|
+
/**
|
|
8464
|
+
* Add a custom validation rule to this field.
|
|
8465
|
+
*
|
|
8466
|
+
* The function is called with the field's value and returns `false` when the
|
|
8467
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
8468
|
+
* more than once to add more rules — they all run, and every message is
|
|
8469
|
+
* reported.
|
|
8470
|
+
*
|
|
8471
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
8472
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
8473
|
+
*
|
|
8474
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
8475
|
+
* before a publish.
|
|
8476
|
+
*
|
|
8477
|
+
* @example
|
|
8478
|
+
* const schema = s.date().validate((val) =>
|
|
8479
|
+
* val >= "2025-01-01" ? false : "Must be in 2025 or later",
|
|
8480
|
+
* );
|
|
8481
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
8482
|
+
*/
|
|
7214
8483
|
}, {
|
|
7215
8484
|
key: "validate",
|
|
7216
8485
|
value: function validate(validationFunction) {
|
|
@@ -7298,6 +8567,16 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7298
8567
|
data: src
|
|
7299
8568
|
};
|
|
7300
8569
|
}
|
|
8570
|
+
|
|
8571
|
+
/**
|
|
8572
|
+
* Validate that the date is this date or after (inclusive).
|
|
8573
|
+
*
|
|
8574
|
+
* Written as `YYYY-MM-DD`, the same shape the value has.
|
|
8575
|
+
*
|
|
8576
|
+
* @example
|
|
8577
|
+
* const schema = s.date().from("2025-01-01");
|
|
8578
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
8579
|
+
*/
|
|
7301
8580
|
}, {
|
|
7302
8581
|
key: "from",
|
|
7303
8582
|
value: function from(_from) {
|
|
@@ -7305,6 +8584,16 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7305
8584
|
from: _from
|
|
7306
8585
|
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
7307
8586
|
}
|
|
8587
|
+
|
|
8588
|
+
/**
|
|
8589
|
+
* Validate that the date is this date or before (inclusive).
|
|
8590
|
+
*
|
|
8591
|
+
* Written as `YYYY-MM-DD`, the same shape the value has.
|
|
8592
|
+
*
|
|
8593
|
+
* @example
|
|
8594
|
+
* const schema = s.date().from("2025-01-01").to("2025-12-31");
|
|
8595
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
8596
|
+
*/
|
|
7308
8597
|
}, {
|
|
7309
8598
|
key: "to",
|
|
7310
8599
|
value: function to(_to) {
|
|
@@ -7343,6 +8632,10 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7343
8632
|
* instead of a preview row that navigates to it.
|
|
7344
8633
|
*
|
|
7345
8634
|
* Static configuration, not a callback — see `render.ts`.
|
|
8635
|
+
*
|
|
8636
|
+
* @example
|
|
8637
|
+
* const schema = s.array(s.date().render({ as: "inline" }));
|
|
8638
|
+
* export default c.define("/example.val.ts", schema, ["2025-06-01"]);
|
|
7346
8639
|
*/
|
|
7347
8640
|
}, {
|
|
7348
8641
|
key: "render",
|
|
@@ -7354,6 +8647,12 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7354
8647
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
7355
8648
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
7356
8649
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
8650
|
+
*
|
|
8651
|
+
* @example
|
|
8652
|
+
* const schema = s.array(
|
|
8653
|
+
* s.date().preview(({ val }) => ({ title: val })),
|
|
8654
|
+
* );
|
|
8655
|
+
* export default c.define("/example.val.ts", schema, ["2025-06-01"]);
|
|
7357
8656
|
*/
|
|
7358
8657
|
}, {
|
|
7359
8658
|
key: "preview",
|
|
@@ -7424,12 +8723,56 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7424
8723
|
_this.previewInput = previewInput;
|
|
7425
8724
|
return _this;
|
|
7426
8725
|
}
|
|
8726
|
+
|
|
8727
|
+
/**
|
|
8728
|
+
* Describe this field.
|
|
8729
|
+
*
|
|
8730
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
8731
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
8732
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
8733
|
+
* assistant and the MCP tools read.
|
|
8734
|
+
*
|
|
8735
|
+
* Pass `null` to clear a description set earlier.
|
|
8736
|
+
*
|
|
8737
|
+
* @example
|
|
8738
|
+
* const schema = s.datetime().describe("When the article goes live");
|
|
8739
|
+
* export default c.define(
|
|
8740
|
+
* "/example.val.ts",
|
|
8741
|
+
* schema,
|
|
8742
|
+
* "2025-06-01T09:00:00.000Z",
|
|
8743
|
+
* );
|
|
8744
|
+
*/
|
|
7427
8745
|
_inherits(DateTimeSchema, _Schema);
|
|
7428
8746
|
return _createClass(DateTimeSchema, [{
|
|
7429
8747
|
key: "describe",
|
|
7430
8748
|
value: function describe(description) {
|
|
7431
8749
|
return new DateTimeSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
7432
8750
|
}
|
|
8751
|
+
|
|
8752
|
+
/**
|
|
8753
|
+
* Add a custom validation rule to this field.
|
|
8754
|
+
*
|
|
8755
|
+
* The function is called with the field's value and returns `false` when the
|
|
8756
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
8757
|
+
* more than once to add more rules — they all run, and every message is
|
|
8758
|
+
* reported.
|
|
8759
|
+
*
|
|
8760
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
8761
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
8762
|
+
*
|
|
8763
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
8764
|
+
* before a publish.
|
|
8765
|
+
*
|
|
8766
|
+
* @example
|
|
8767
|
+
* const schema = s.datetime().validate((val) =>
|
|
8768
|
+
* val.endsWith("Z") ? false : "Must be in UTC",
|
|
8769
|
+
* );
|
|
8770
|
+
* export default c.define(
|
|
8771
|
+
* "/example.val.ts",
|
|
8772
|
+
* schema,
|
|
8773
|
+
* "2025-06-01T09:00:00.000Z",
|
|
8774
|
+
* );
|
|
8775
|
+
*/
|
|
7433
8776
|
}, {
|
|
7434
8777
|
key: "validate",
|
|
7435
8778
|
value: function validate(validationFunction) {
|
|
@@ -7549,6 +8892,20 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7549
8892
|
data: src
|
|
7550
8893
|
};
|
|
7551
8894
|
}
|
|
8895
|
+
|
|
8896
|
+
/**
|
|
8897
|
+
* Validate that the datetime is this datetime or after (inclusive).
|
|
8898
|
+
*
|
|
8899
|
+
* Any ISO 8601 datetime string `Date.parse` understands.
|
|
8900
|
+
*
|
|
8901
|
+
* @example
|
|
8902
|
+
* const schema = s.datetime().from("2025-01-01T00:00:00Z");
|
|
8903
|
+
* export default c.define(
|
|
8904
|
+
* "/example.val.ts",
|
|
8905
|
+
* schema,
|
|
8906
|
+
* "2025-06-01T09:00:00.000Z",
|
|
8907
|
+
* );
|
|
8908
|
+
*/
|
|
7552
8909
|
}, {
|
|
7553
8910
|
key: "from",
|
|
7554
8911
|
value: function from(_from) {
|
|
@@ -7556,6 +8913,23 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7556
8913
|
from: _from
|
|
7557
8914
|
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
|
|
7558
8915
|
}
|
|
8916
|
+
|
|
8917
|
+
/**
|
|
8918
|
+
* Validate that the datetime is this datetime or before (inclusive).
|
|
8919
|
+
*
|
|
8920
|
+
* Any ISO 8601 datetime string `Date.parse` understands.
|
|
8921
|
+
*
|
|
8922
|
+
* @example
|
|
8923
|
+
* const schema = s
|
|
8924
|
+
* .datetime()
|
|
8925
|
+
* .from("2025-01-01T00:00:00Z")
|
|
8926
|
+
* .to("2025-12-31T23:59:59Z");
|
|
8927
|
+
* export default c.define(
|
|
8928
|
+
* "/example.val.ts",
|
|
8929
|
+
* schema,
|
|
8930
|
+
* "2025-06-01T09:00:00.000Z",
|
|
8931
|
+
* );
|
|
8932
|
+
*/
|
|
7559
8933
|
}, {
|
|
7560
8934
|
key: "to",
|
|
7561
8935
|
value: function to(_to) {
|
|
@@ -7594,6 +8968,12 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7594
8968
|
* instead of a preview row that navigates to it.
|
|
7595
8969
|
*
|
|
7596
8970
|
* Static configuration, not a callback — see `render.ts`.
|
|
8971
|
+
*
|
|
8972
|
+
* @example
|
|
8973
|
+
* const schema = s.array(s.datetime().render({ as: "inline" }));
|
|
8974
|
+
* export default c.define("/example.val.ts", schema, [
|
|
8975
|
+
* "2025-06-01T09:00:00.000Z",
|
|
8976
|
+
* ]);
|
|
7597
8977
|
*/
|
|
7598
8978
|
}, {
|
|
7599
8979
|
key: "render",
|
|
@@ -7605,6 +8985,14 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7605
8985
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
7606
8986
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
7607
8987
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
8988
|
+
*
|
|
8989
|
+
* @example
|
|
8990
|
+
* const schema = s.array(
|
|
8991
|
+
* s.datetime().preview(({ val }) => ({ title: val })),
|
|
8992
|
+
* );
|
|
8993
|
+
* export default c.define("/example.val.ts", schema, [
|
|
8994
|
+
* "2025-06-01T09:00:00.000Z",
|
|
8995
|
+
* ]);
|
|
7608
8996
|
*/
|
|
7609
8997
|
}, {
|
|
7610
8998
|
key: "preview",
|
|
@@ -7689,12 +9077,59 @@ var CodeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7689
9077
|
_this.previewInput = previewInput;
|
|
7690
9078
|
return _this;
|
|
7691
9079
|
}
|
|
9080
|
+
|
|
9081
|
+
/**
|
|
9082
|
+
* Describe this field.
|
|
9083
|
+
*
|
|
9084
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
9085
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
9086
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
9087
|
+
* assistant and the MCP tools read.
|
|
9088
|
+
*
|
|
9089
|
+
* Pass `null` to clear a description set earlier.
|
|
9090
|
+
*
|
|
9091
|
+
* @example
|
|
9092
|
+
* const schema = s
|
|
9093
|
+
* .code({ language: "css" })
|
|
9094
|
+
* .describe("Injected into the page head — keep it small");
|
|
9095
|
+
* export default c.define(
|
|
9096
|
+
* "/example.val.ts",
|
|
9097
|
+
* schema,
|
|
9098
|
+
* ".hero { color: red; }",
|
|
9099
|
+
* );
|
|
9100
|
+
*/
|
|
7692
9101
|
_inherits(CodeSchema, _Schema);
|
|
7693
9102
|
return _createClass(CodeSchema, [{
|
|
7694
9103
|
key: "describe",
|
|
7695
9104
|
value: function describe(description) {
|
|
7696
9105
|
return new CodeSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
7697
9106
|
}
|
|
9107
|
+
|
|
9108
|
+
/**
|
|
9109
|
+
* Add a custom validation rule to this field.
|
|
9110
|
+
*
|
|
9111
|
+
* The function is called with the field's value and returns `false` when the
|
|
9112
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
9113
|
+
* more than once to add more rules — they all run, and every message is
|
|
9114
|
+
* reported.
|
|
9115
|
+
*
|
|
9116
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
9117
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
9118
|
+
*
|
|
9119
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
9120
|
+
* before a publish.
|
|
9121
|
+
*
|
|
9122
|
+
* @example
|
|
9123
|
+
* const schema = s.code({ language: "json" }).validate((val) => {
|
|
9124
|
+
* try {
|
|
9125
|
+
* JSON.parse(val);
|
|
9126
|
+
* return false;
|
|
9127
|
+
* } catch {
|
|
9128
|
+
* return "Must be valid JSON";
|
|
9129
|
+
* }
|
|
9130
|
+
* });
|
|
9131
|
+
* export default c.define("/example.val.ts", schema, '{ "a": 1 }');
|
|
9132
|
+
*/
|
|
7698
9133
|
}, {
|
|
7699
9134
|
key: "validate",
|
|
7700
9135
|
value: function validate(validationFunction) {
|
|
@@ -7774,6 +9209,14 @@ var CodeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7774
9209
|
* instead of a preview row that navigates to it.
|
|
7775
9210
|
*
|
|
7776
9211
|
* Static configuration, not a callback — see `render.ts`.
|
|
9212
|
+
*
|
|
9213
|
+
* @example
|
|
9214
|
+
* const schema = s.array(
|
|
9215
|
+
* s.code({ language: "css" }).render({ as: "inline" }),
|
|
9216
|
+
* );
|
|
9217
|
+
* export default c.define("/example.val.ts", schema, [
|
|
9218
|
+
* ".hero { color: red; }",
|
|
9219
|
+
* ]);
|
|
7777
9220
|
*/
|
|
7778
9221
|
}, {
|
|
7779
9222
|
key: "render",
|
|
@@ -7785,6 +9228,16 @@ var CodeSchema = /*#__PURE__*/function (_Schema) {
|
|
|
7785
9228
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
7786
9229
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
7787
9230
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
9231
|
+
*
|
|
9232
|
+
* @example
|
|
9233
|
+
* const schema = s.array(
|
|
9234
|
+
* s.code({ language: "css" }).preview(({ val }) => ({
|
|
9235
|
+
* title: val.split("\n")[0],
|
|
9236
|
+
* })),
|
|
9237
|
+
* );
|
|
9238
|
+
* export default c.define("/example.val.ts", schema, [
|
|
9239
|
+
* ".hero { color: red; }",
|
|
9240
|
+
* ]);
|
|
7788
9241
|
*/
|
|
7789
9242
|
}, {
|
|
7790
9243
|
key: "preview",
|
|
@@ -8335,12 +9788,54 @@ var ColorSchema = /*#__PURE__*/function (_Schema) {
|
|
|
8335
9788
|
_this.previewInput = previewInput;
|
|
8336
9789
|
return _this;
|
|
8337
9790
|
}
|
|
9791
|
+
|
|
9792
|
+
/**
|
|
9793
|
+
* Describe this field.
|
|
9794
|
+
*
|
|
9795
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
9796
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
9797
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
9798
|
+
* assistant and the MCP tools read.
|
|
9799
|
+
*
|
|
9800
|
+
* Pass `null` to clear a description set earlier.
|
|
9801
|
+
*
|
|
9802
|
+
* @example
|
|
9803
|
+
* const schema = s.color().describe("Background of the hero section");
|
|
9804
|
+
* export default c.define(
|
|
9805
|
+
* "/example.val.ts",
|
|
9806
|
+
* schema,
|
|
9807
|
+
* "hsl(217.22 91.22% 59.8%)",
|
|
9808
|
+
* );
|
|
9809
|
+
*/
|
|
8338
9810
|
_inherits(ColorSchema, _Schema);
|
|
8339
9811
|
return _createClass(ColorSchema, [{
|
|
8340
9812
|
key: "describe",
|
|
8341
9813
|
value: function describe(description) {
|
|
8342
9814
|
return new ColorSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
|
|
8343
9815
|
}
|
|
9816
|
+
|
|
9817
|
+
/**
|
|
9818
|
+
* Add a custom validation rule to this field.
|
|
9819
|
+
*
|
|
9820
|
+
* The function is called with the field's value and returns `false` when the
|
|
9821
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
9822
|
+
* more than once to add more rules — they all run, and every message is
|
|
9823
|
+
* reported.
|
|
9824
|
+
*
|
|
9825
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
9826
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
9827
|
+
*
|
|
9828
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
9829
|
+
* before a publish.
|
|
9830
|
+
*
|
|
9831
|
+
* @example
|
|
9832
|
+
* const schema = s
|
|
9833
|
+
* .color({ format: "hex" })
|
|
9834
|
+
* .validate((val) =>
|
|
9835
|
+
* val === val.toLowerCase() ? false : "Write hex in lower case",
|
|
9836
|
+
* );
|
|
9837
|
+
* export default c.define("/example.val.ts", schema, "#3b82f6");
|
|
9838
|
+
*/
|
|
8344
9839
|
}, {
|
|
8345
9840
|
key: "validate",
|
|
8346
9841
|
value: function validate(validationFunction) {
|
|
@@ -8462,6 +9957,12 @@ var ColorSchema = /*#__PURE__*/function (_Schema) {
|
|
|
8462
9957
|
* instead of a preview row that navigates to it.
|
|
8463
9958
|
*
|
|
8464
9959
|
* Static configuration, not a callback — see `render.ts`.
|
|
9960
|
+
*
|
|
9961
|
+
* @example
|
|
9962
|
+
* const schema = s.array(s.color().render({ as: "inline" }));
|
|
9963
|
+
* export default c.define("/example.val.ts", schema, [
|
|
9964
|
+
* "hsl(217.22 91.22% 59.8%)",
|
|
9965
|
+
* ]);
|
|
8465
9966
|
*/
|
|
8466
9967
|
}, {
|
|
8467
9968
|
key: "render",
|
|
@@ -8473,6 +9974,14 @@ var ColorSchema = /*#__PURE__*/function (_Schema) {
|
|
|
8473
9974
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
8474
9975
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
8475
9976
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
9977
|
+
*
|
|
9978
|
+
* @example
|
|
9979
|
+
* const schema = s.array(
|
|
9980
|
+
* s.color().preview(({ val }) => ({ title: val })),
|
|
9981
|
+
* );
|
|
9982
|
+
* export default c.define("/example.val.ts", schema, [
|
|
9983
|
+
* "hsl(217.22 91.22% 59.8%)",
|
|
9984
|
+
* ]);
|
|
8476
9985
|
*/
|
|
8477
9986
|
}, {
|
|
8478
9987
|
key: "preview",
|
|
@@ -8601,6 +10110,8 @@ function initSchema() {
|
|
|
8601
10110
|
array: array,
|
|
8602
10111
|
object: object,
|
|
8603
10112
|
number: number,
|
|
10113
|
+
discriminatedUnion: discriminatedUnion,
|
|
10114
|
+
"enum": enumSchema,
|
|
8604
10115
|
union: union,
|
|
8605
10116
|
// oneOf,
|
|
8606
10117
|
richtext: richtext,
|
|
@@ -9519,32 +11030,26 @@ function hasRemoteFileSchema(schema) {
|
|
|
9519
11030
|
}
|
|
9520
11031
|
}
|
|
9521
11032
|
return false;
|
|
9522
|
-
} else if (schema.type === "union") {
|
|
9523
|
-
var
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
_step;
|
|
9532
|
-
try {
|
|
9533
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
9534
|
-
var item = _step.value;
|
|
9535
|
-
var _hasRemoteFile = hasRemoteFileSchema(item);
|
|
9536
|
-
if (_hasRemoteFile) {
|
|
9537
|
-
return true;
|
|
9538
|
-
}
|
|
11033
|
+
} else if (schema.type === "discriminated-union") {
|
|
11034
|
+
var _iterator = _createForOfIteratorHelper(schema.items),
|
|
11035
|
+
_step;
|
|
11036
|
+
try {
|
|
11037
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
11038
|
+
var item = _step.value;
|
|
11039
|
+
var _hasRemoteFile = hasRemoteFileSchema(item);
|
|
11040
|
+
if (_hasRemoteFile) {
|
|
11041
|
+
return true;
|
|
9539
11042
|
}
|
|
9540
|
-
} catch (err) {
|
|
9541
|
-
_iterator.e(err);
|
|
9542
|
-
} finally {
|
|
9543
|
-
_iterator.f();
|
|
9544
11043
|
}
|
|
11044
|
+
} catch (err) {
|
|
11045
|
+
_iterator.e(err);
|
|
11046
|
+
} finally {
|
|
11047
|
+
_iterator.f();
|
|
9545
11048
|
}
|
|
9546
11049
|
return false;
|
|
9547
|
-
} else if (schema.type === "boolean" ||
|
|
11050
|
+
} else if (schema.type === "boolean" ||
|
|
11051
|
+
// An enum's values are strings, so there is nothing to look inside.
|
|
11052
|
+
schema.type === "enum" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "dateTime" || schema.type === "color" || schema.type === "code" || schema.type === "keyOf" || schema.type === "route") {
|
|
9548
11053
|
return false;
|
|
9549
11054
|
} else {
|
|
9550
11055
|
var exhaustiveCheck = schema;
|
|
@@ -9598,27 +11103,25 @@ function hasMediaSchema(schema) {
|
|
|
9598
11103
|
}
|
|
9599
11104
|
}
|
|
9600
11105
|
return false;
|
|
9601
|
-
} else if (schema.type === "union") {
|
|
9602
|
-
var
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
if (hasMediaSchema(item)) {
|
|
9610
|
-
return true;
|
|
9611
|
-
}
|
|
11106
|
+
} else if (schema.type === "discriminated-union") {
|
|
11107
|
+
var _iterator2 = _createForOfIteratorHelper(schema.items),
|
|
11108
|
+
_step2;
|
|
11109
|
+
try {
|
|
11110
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
11111
|
+
var item = _step2.value;
|
|
11112
|
+
if (hasMediaSchema(item)) {
|
|
11113
|
+
return true;
|
|
9612
11114
|
}
|
|
9613
|
-
} catch (err) {
|
|
9614
|
-
_iterator2.e(err);
|
|
9615
|
-
} finally {
|
|
9616
|
-
_iterator2.f();
|
|
9617
11115
|
}
|
|
11116
|
+
} catch (err) {
|
|
11117
|
+
_iterator2.e(err);
|
|
11118
|
+
} finally {
|
|
11119
|
+
_iterator2.f();
|
|
9618
11120
|
}
|
|
9619
|
-
// A string union's items are literals, so there is nothing to look inside.
|
|
9620
11121
|
return false;
|
|
9621
|
-
} else if (schema.type === "boolean" ||
|
|
11122
|
+
} else if (schema.type === "boolean" ||
|
|
11123
|
+
// An enum's values are strings, so there is nothing to look inside.
|
|
11124
|
+
schema.type === "enum" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "dateTime" || schema.type === "color" || schema.type === "code" || schema.type === "keyOf" || schema.type === "route" ||
|
|
9622
11125
|
// A settings module holds the assistant's configuration, not content, and
|
|
9623
11126
|
// nothing in it is media.
|
|
9624
11127
|
schema.type === "settings") {
|
|
@@ -9908,7 +11411,7 @@ function deserializeSchema(serialized) {
|
|
|
9908
11411
|
return schema;
|
|
9909
11412
|
}
|
|
9910
11413
|
function deserializeSchemaImpl(serialized) {
|
|
9911
|
-
var _serialized$options, _serialized$options2, _serialized$render, _serialized$multiline, _serialized$render2, _serialized$render3, _serialized$render4, _serialized$render5, _serialized$render6, _serialized$render7, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue, _serialized$
|
|
11414
|
+
var _serialized$options, _serialized$options2, _serialized$render, _serialized$multiline, _serialized$render2, _serialized$render3, _serialized$render4, _serialized$render5, _serialized$render6, _serialized$render7, _serialized$render8, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue, _serialized$render0, _serialized$external, _serialized$render1, _serialized$render11, _serialized$render12, _serialized$render13, _serialized$render14, _serialized$render15, _serialized$render16;
|
|
9912
11415
|
switch (serialized.type) {
|
|
9913
11416
|
case "string":
|
|
9914
11417
|
return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
|
|
@@ -9942,23 +11445,22 @@ function deserializeSchemaImpl(serialized) {
|
|
|
9942
11445
|
return new ArraySchema(deserializeSchema(serialized.item), serialized.opt, [], false, false, serialized.description,
|
|
9943
11446
|
// The preview closure cannot survive serialization; the render can.
|
|
9944
11447
|
null, (_serialized$render6 = serialized.render) !== null && _serialized$render6 !== void 0 ? _serialized$render6 : null);
|
|
9945
|
-
case "union":
|
|
9946
|
-
return new
|
|
9947
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9948
|
-
deserializeSchema(serialized.key),
|
|
9949
|
-
// TODO: we do not really need any here - right?
|
|
11448
|
+
case "discriminated-union":
|
|
11449
|
+
return new DiscriminatedUnionSchema(serialized.key,
|
|
9950
11450
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9951
11451
|
serialized.items.map(deserializeSchema),
|
|
9952
11452
|
// TODO: we do not really need any here - right?
|
|
9953
11453
|
serialized.opt, [], false, false, serialized.description, (_serialized$render7 = serialized.render) !== null && _serialized$render7 !== void 0 ? _serialized$render7 : null);
|
|
11454
|
+
case "enum":
|
|
11455
|
+
return new EnumSchema(serialized.values, serialized.opt, [], false, false, serialized.description, (_serialized$render8 = serialized.render) !== null && _serialized$render8 !== void 0 ? _serialized$render8 : null);
|
|
9954
11456
|
case "richtext":
|
|
9955
11457
|
{
|
|
9956
|
-
var _serialized$options3, _serialized$options4, _serialized$options5, _serialized$options6, _serialized$
|
|
11458
|
+
var _serialized$options3, _serialized$options4, _serialized$options5, _serialized$options6, _serialized$render9;
|
|
9957
11459
|
var deserializedOptions = _objectSpread2(_objectSpread2({}, serialized.options || {}), {}, {
|
|
9958
11460
|
a: _typeof((_serialized$options3 = serialized.options) === null || _serialized$options3 === void 0 ? void 0 : _serialized$options3.a) === "object" ? deserializeSchema(serialized.options.a) : (_serialized$options4 = serialized.options) === null || _serialized$options4 === void 0 ? void 0 : _serialized$options4.a,
|
|
9959
11461
|
img: _typeof((_serialized$options5 = serialized.options) === null || _serialized$options5 === void 0 ? void 0 : _serialized$options5.img) === "object" ? deserializeSchema(serialized.options.img) : (_serialized$options6 = serialized.options) === null || _serialized$options6 === void 0 ? void 0 : _serialized$options6.img
|
|
9960
11462
|
});
|
|
9961
|
-
return new RichTextSchema(deserializedOptions, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11463
|
+
return new RichTextSchema(deserializedOptions, serialized.opt, [], false, false, serialized.description, (_serialized$render9 = serialized.render) !== null && _serialized$render9 !== void 0 ? _serialized$render9 : null);
|
|
9962
11464
|
}
|
|
9963
11465
|
case "record":
|
|
9964
11466
|
return new RecordSchema(deserializeSchema(serialized.item), serialized.opt, [], null, serialized.key ? deserializeSchema(serialized.key) : null, serialized.mediaType ? {
|
|
@@ -9969,33 +11471,33 @@ function deserializeSchemaImpl(serialized) {
|
|
|
9969
11471
|
altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
|
|
9970
11472
|
} : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
|
|
9971
11473
|
// The preview closure cannot survive serialization; the render can.
|
|
9972
|
-
null, (_serialized$
|
|
11474
|
+
null, (_serialized$render0 = serialized.render) !== null && _serialized$render0 !== void 0 ? _serialized$render0 : null, // The external label is static data, so it survives serialization and
|
|
9973
11475
|
// must be carried back: a deserialized schema that forgot it would walk
|
|
9974
11476
|
// an external record as if its entries were local.
|
|
9975
11477
|
(_serialized$external = serialized.external) !== null && _serialized$external !== void 0 ? _serialized$external : null);
|
|
9976
11478
|
case "keyOf":
|
|
9977
|
-
return new KeyOfSchema(serialized.schema, serialized.path, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11479
|
+
return new KeyOfSchema(serialized.schema, serialized.path, serialized.opt, [], false, false, serialized.description, (_serialized$render1 = serialized.render) !== null && _serialized$render1 !== void 0 ? _serialized$render1 : null);
|
|
9978
11480
|
case "route":
|
|
9979
11481
|
{
|
|
9980
|
-
var _serialized$
|
|
11482
|
+
var _serialized$render10;
|
|
9981
11483
|
var routeOptions = serialized.options ? {
|
|
9982
11484
|
include: serialized.options.include ? new RegExp(serialized.options.include.source, serialized.options.include.flags) : undefined,
|
|
9983
11485
|
exclude: serialized.options.exclude ? new RegExp(serialized.options.exclude.source, serialized.options.exclude.flags) : undefined
|
|
9984
11486
|
} : undefined;
|
|
9985
|
-
return new RouteSchema(routeOptions, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11487
|
+
return new RouteSchema(routeOptions, serialized.opt, [], false, false, serialized.description, (_serialized$render10 = serialized.render) !== null && _serialized$render10 !== void 0 ? _serialized$render10 : null);
|
|
9986
11488
|
}
|
|
9987
11489
|
case "file":
|
|
9988
|
-
return new FileSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$
|
|
11490
|
+
return new FileSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$render11 = serialized.render) !== null && _serialized$render11 !== void 0 ? _serialized$render11 : null);
|
|
9989
11491
|
case "image":
|
|
9990
|
-
return new ImageSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$
|
|
11492
|
+
return new ImageSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$render12 = serialized.render) !== null && _serialized$render12 !== void 0 ? _serialized$render12 : null);
|
|
9991
11493
|
case "date":
|
|
9992
|
-
return new DateSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11494
|
+
return new DateSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render13 = serialized.render) !== null && _serialized$render13 !== void 0 ? _serialized$render13 : null);
|
|
9993
11495
|
case "dateTime":
|
|
9994
|
-
return new DateTimeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11496
|
+
return new DateTimeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render14 = serialized.render) !== null && _serialized$render14 !== void 0 ? _serialized$render14 : null);
|
|
9995
11497
|
case "color":
|
|
9996
|
-
return new ColorSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11498
|
+
return new ColorSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render15 = serialized.render) !== null && _serialized$render15 !== void 0 ? _serialized$render15 : null);
|
|
9997
11499
|
case "code":
|
|
9998
|
-
return new CodeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$
|
|
11500
|
+
return new CodeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render16 = serialized.render) !== null && _serialized$render16 !== void 0 ? _serialized$render16 : null);
|
|
9999
11501
|
default:
|
|
10000
11502
|
{
|
|
10001
11503
|
var exhaustiveCheck = serialized;
|
|
@@ -10204,10 +11706,11 @@ function previewScope(paths) {
|
|
|
10204
11706
|
* question, and a disagreement between them is a row you can edit in place but
|
|
10205
11707
|
* that "add" navigates away from.
|
|
10206
11708
|
*
|
|
10207
|
-
* A
|
|
10208
|
-
* ANY of its variants does. A page-builder list is
|
|
10209
|
-
* block, block, ...))` and the natural
|
|
10210
|
-
* blocks, one per block type — the union
|
|
11709
|
+
* A discriminated union counts as inline when the union itself declares it OR
|
|
11710
|
+
* when ANY of its variants does. A page-builder list is
|
|
11711
|
+
* `s.array(s.discriminatedUnion("type", block, block, ...))` and the natural
|
|
11712
|
+
* place to write the render is on the blocks, one per block type — the union
|
|
11713
|
+
* is a dispatch, not something the
|
|
10211
11714
|
* author thinks of as the field. `some` rather than `every` because the row
|
|
10212
11715
|
* draws the union's own editor (the tag selector plus the matched variant's
|
|
10213
11716
|
* fields), which handles every variant either way: with `every`, adding one
|
|
@@ -10224,7 +11727,7 @@ function isInlineRender(schema) {
|
|
|
10224
11727
|
if (((_schema$render = schema.render) === null || _schema$render === void 0 ? void 0 : _schema$render.as) === "inline") {
|
|
10225
11728
|
return true;
|
|
10226
11729
|
}
|
|
10227
|
-
if (schema.type === "union") {
|
|
11730
|
+
if (schema.type === "discriminated-union") {
|
|
10228
11731
|
return schema.items.some(function (item) {
|
|
10229
11732
|
var _item$render;
|
|
10230
11733
|
return ((_item$render = item.render) === null || _item$render === void 0 ? void 0 : _item$render.as) === "inline";
|
|
@@ -10449,23 +11952,190 @@ function parseNextJsRoutePattern(moduleFilePath) {
|
|
|
10449
11952
|
return [];
|
|
10450
11953
|
}
|
|
10451
11954
|
|
|
11955
|
+
/**
|
|
11956
|
+
* Parse a TanStack Router route pattern out of a Val module file path.
|
|
11957
|
+
*
|
|
11958
|
+
* TanStack Router's file conventions are not Next's, so this is a different
|
|
11959
|
+
* parser rather than a flag on the one above. A Val module for a route lives
|
|
11960
|
+
* beside the route file and is named the same way — `routes/posts.$postId.tsx`
|
|
11961
|
+
* is served content by `routes/posts.$postId.val.ts` — so the pattern is the
|
|
11962
|
+
* file path with the conventions applied:
|
|
11963
|
+
*
|
|
11964
|
+
* - `.` and `/` both separate segments (`posts.$postId.val.ts` and
|
|
11965
|
+
* `posts/$postId.val.ts` are the same route)
|
|
11966
|
+
* - `$param` is a dynamic segment, `$` on its own is a splat
|
|
11967
|
+
* - `index` is the directory's own route and contributes no segment
|
|
11968
|
+
* - `route` is a layout for the directory, likewise
|
|
11969
|
+
* - `(group)` folders and `_pathless` layout segments are not in the URL
|
|
11970
|
+
* - a trailing `_` on a segment opts out of nesting and is not in the URL
|
|
11971
|
+
*
|
|
11972
|
+
* The result is expressed in the SAME vocabulary the Next parser uses
|
|
11973
|
+
* (`[param]`, `[...param]`), because everything downstream — validation, the
|
|
11974
|
+
* sitemap, the key inputs in the Studio — is written against that vocabulary
|
|
11975
|
+
* and there is no reason for two.
|
|
11976
|
+
*
|
|
11977
|
+
* - /src/routes/posts.$postId.val.ts -> ["posts", "[postId]"]
|
|
11978
|
+
* - /routes/posts/$postId.val.ts -> ["posts", "[postId]"]
|
|
11979
|
+
* - /src/routes/index.val.ts -> []
|
|
11980
|
+
* - /src/routes/files.$.val.ts -> ["files", "[..._splat]"]
|
|
11981
|
+
* - /src/routes/(app)/_layout.about.val.ts -> ["about"]
|
|
11982
|
+
*/
|
|
11983
|
+
function parseTanStackRoutePattern(moduleFilePath) {
|
|
11984
|
+
var segments = tanStackRouteSegments(moduleFilePath);
|
|
11985
|
+
if (segments === null) {
|
|
11986
|
+
return [];
|
|
11987
|
+
}
|
|
11988
|
+
return segments;
|
|
11989
|
+
}
|
|
11990
|
+
|
|
11991
|
+
/**
|
|
11992
|
+
* The segments, or `null` when the path is not a TanStack route module at all.
|
|
11993
|
+
*
|
|
11994
|
+
* Distinct from `parseTanStackRoutePattern`'s empty array, which is a real
|
|
11995
|
+
* answer: the root route `/` has no segments.
|
|
11996
|
+
*/
|
|
11997
|
+
function tanStackRouteSegments(moduleFilePath) {
|
|
11998
|
+
if (!moduleFilePath || typeof moduleFilePath !== "string") {
|
|
11999
|
+
return null;
|
|
12000
|
+
}
|
|
12001
|
+
var match = moduleFilePath.match(/^(?:\/src)?\/routes\/(.+)\.val\.[tj]sx?$/);
|
|
12002
|
+
if (!match) {
|
|
12003
|
+
return null;
|
|
12004
|
+
}
|
|
12005
|
+
return tanStackSegmentsOfRoutePath(match[1]);
|
|
12006
|
+
}
|
|
12007
|
+
|
|
12008
|
+
/**
|
|
12009
|
+
* The URL segments of a TanStack route path, given relative to `routes/`.
|
|
12010
|
+
*
|
|
12011
|
+
* Exported because the Studio derives the same pattern from the same file path
|
|
12012
|
+
* and must not disagree with validation about what a route is.
|
|
12013
|
+
*/
|
|
12014
|
+
function tanStackSegmentsOfRoutePath(routePath) {
|
|
12015
|
+
// `.` is a separator exactly like `/`, so flatten both before looking at any
|
|
12016
|
+
// segment: `posts/$postId.edit` and `posts.$postId.edit` are one route.
|
|
12017
|
+
var rawSegments = routePath.split("/").flatMap(function (part) {
|
|
12018
|
+
return part.split(".");
|
|
12019
|
+
}).filter(function (part) {
|
|
12020
|
+
return part !== "";
|
|
12021
|
+
});
|
|
12022
|
+
var segments = [];
|
|
12023
|
+
var _iterator3 = _createForOfIteratorHelper(rawSegments),
|
|
12024
|
+
_step3;
|
|
12025
|
+
try {
|
|
12026
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
12027
|
+
var rawSegment = _step3.value;
|
|
12028
|
+
// A route group: a folder that organises files without appearing in the URL.
|
|
12029
|
+
if (rawSegment.startsWith("(") && rawSegment.endsWith(")")) {
|
|
12030
|
+
continue;
|
|
12031
|
+
}
|
|
12032
|
+
// A pathless layout route. `_layout` nests its children without adding a
|
|
12033
|
+
// segment; `index`/`route` are the directory's own route and its layout.
|
|
12034
|
+
if (rawSegment.startsWith("_")) {
|
|
12035
|
+
continue;
|
|
12036
|
+
}
|
|
12037
|
+
if (rawSegment === "index" || rawSegment === "route") {
|
|
12038
|
+
continue;
|
|
12039
|
+
}
|
|
12040
|
+
// A trailing `_` opts the segment out of layout nesting; the URL keeps the
|
|
12041
|
+
// name without it.
|
|
12042
|
+
var segment = rawSegment.endsWith("_") ? rawSegment.slice(0, -1) : rawSegment;
|
|
12043
|
+
if (segment === "$") {
|
|
12044
|
+
// A splat. Named `_splat` because that is the param name TanStack gives
|
|
12045
|
+
// it, so `useValRoute(pageVal, params)` can be handed the route's own
|
|
12046
|
+
// params object unchanged.
|
|
12047
|
+
segments.push("[..._splat]");
|
|
12048
|
+
continue;
|
|
12049
|
+
}
|
|
12050
|
+
if (segment.startsWith("$")) {
|
|
12051
|
+
segments.push("[".concat(segment.slice(1), "]"));
|
|
12052
|
+
continue;
|
|
12053
|
+
}
|
|
12054
|
+
segments.push(segment);
|
|
12055
|
+
}
|
|
12056
|
+
} catch (err) {
|
|
12057
|
+
_iterator3.e(err);
|
|
12058
|
+
} finally {
|
|
12059
|
+
_iterator3.f();
|
|
12060
|
+
}
|
|
12061
|
+
return segments;
|
|
12062
|
+
}
|
|
12063
|
+
|
|
12064
|
+
/**
|
|
12065
|
+
* The router for a TanStack Router (and TanStack Start) app.
|
|
12066
|
+
*
|
|
12067
|
+
* Like `nextAppRouter` this does not belong in core — it is here for the same
|
|
12068
|
+
* reason that one is: the serialized schema carries only a router id, so the
|
|
12069
|
+
* thing that turns an id back into a validator has to be somewhere every
|
|
12070
|
+
* consumer can reach.
|
|
12071
|
+
*/
|
|
12072
|
+
var tanstackRouter = {
|
|
12073
|
+
getRouterId: function getRouterId() {
|
|
12074
|
+
return "tanstack-router";
|
|
12075
|
+
},
|
|
12076
|
+
validate: function validate(moduleFilePath, urlPaths) {
|
|
12077
|
+
var routePattern = parseTanStackRoutePattern(moduleFilePath);
|
|
12078
|
+
var errors = [];
|
|
12079
|
+
var _iterator4 = _createForOfIteratorHelper(urlPaths),
|
|
12080
|
+
_step4;
|
|
12081
|
+
try {
|
|
12082
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
12083
|
+
var urlPath = _step4.value;
|
|
12084
|
+
var validation = validateUrlAgainstPattern(urlPath, routePattern);
|
|
12085
|
+
if (!validation.isValid) {
|
|
12086
|
+
errors.push({
|
|
12087
|
+
error: {
|
|
12088
|
+
message: "URL path \"".concat(urlPath, "\" does not match the route pattern for \"").concat(moduleFilePath, "\""),
|
|
12089
|
+
urlPath: urlPath,
|
|
12090
|
+
expectedPath: validation.expectedPath || null
|
|
12091
|
+
}
|
|
12092
|
+
});
|
|
12093
|
+
}
|
|
12094
|
+
}
|
|
12095
|
+
} catch (err) {
|
|
12096
|
+
_iterator4.e(err);
|
|
12097
|
+
} finally {
|
|
12098
|
+
_iterator4.f();
|
|
12099
|
+
}
|
|
12100
|
+
return errors;
|
|
12101
|
+
}
|
|
12102
|
+
};
|
|
12103
|
+
|
|
12104
|
+
/**
|
|
12105
|
+
* The routers whose keys are URL paths of THIS site, and how to read the route
|
|
12106
|
+
* pattern a module of each serves.
|
|
12107
|
+
*
|
|
12108
|
+
* Keyed by router id because that is all a serialized schema carries. A router
|
|
12109
|
+
* that is not in here — `external-url-router` today — has keys that are URLs of
|
|
12110
|
+
* somewhere else, so matching this site's pathname against them is meaningless
|
|
12111
|
+
* rather than merely unsupported.
|
|
12112
|
+
*/
|
|
12113
|
+
var PAGE_ROUTE_PATTERN_PARSERS = {
|
|
12114
|
+
"next-app-router": parseNextJsRoutePattern,
|
|
12115
|
+
"tanstack-router": parseTanStackRoutePattern
|
|
12116
|
+
};
|
|
12117
|
+
|
|
10452
12118
|
/**
|
|
10453
12119
|
* Given a URL pathname (e.g. "/blogs/blog-1") and all serialized module schemas,
|
|
10454
|
-
* finds the
|
|
10455
|
-
* and the source path for that route's content.
|
|
12120
|
+
* finds the page-router module that serves that route and returns the module
|
|
12121
|
+
* file path and the source path for that route's content.
|
|
10456
12122
|
*
|
|
10457
12123
|
* External routers (e.g. external-url-router) are intentionally skipped.
|
|
10458
|
-
* Returns null if no
|
|
12124
|
+
* Returns null if no page-router module matches the pathname.
|
|
10459
12125
|
*/
|
|
10460
12126
|
function getSourcePathFromRoute(pathname, schemas) {
|
|
10461
12127
|
for (var _i = 0, _arr = Object.entries(schemas); _i < _arr.length; _i++) {
|
|
10462
12128
|
var _arr$_i = _slicedToArray(_arr[_i], 2),
|
|
10463
12129
|
moduleFilePath = _arr$_i[0],
|
|
10464
12130
|
schema = _arr$_i[1];
|
|
10465
|
-
if (schema.type !== "record" || schema.router
|
|
12131
|
+
if (schema.type !== "record" || !schema.router) {
|
|
10466
12132
|
continue;
|
|
10467
12133
|
}
|
|
10468
|
-
var
|
|
12134
|
+
var parseRoutePattern = PAGE_ROUTE_PATTERN_PARSERS[schema.router];
|
|
12135
|
+
if (!parseRoutePattern) {
|
|
12136
|
+
continue;
|
|
12137
|
+
}
|
|
12138
|
+
var routePattern = parseRoutePattern(moduleFilePath);
|
|
10469
12139
|
var _validateUrlAgainstPa = validateUrlAgainstPattern(pathname, routePattern),
|
|
10470
12140
|
isValid = _validateUrlAgainstPa.isValid;
|
|
10471
12141
|
if (isValid) {
|
|
@@ -10480,20 +12150,81 @@ function getSourcePathFromRoute(pathname, schemas) {
|
|
|
10480
12150
|
return null;
|
|
10481
12151
|
}
|
|
10482
12152
|
|
|
12153
|
+
/**
|
|
12154
|
+
* Whether a router id is one whose keys are routes of this site.
|
|
12155
|
+
*
|
|
12156
|
+
* The same question `getSourcePathFromRoute` asks, exported because the Studio
|
|
12157
|
+
* asks it too — a page router gets the sitemap and the "Pages" menu, an
|
|
12158
|
+
* external one gets a flat list of URLs — and the two must not disagree about
|
|
12159
|
+
* which is which.
|
|
12160
|
+
*/
|
|
12161
|
+
function isPageRouter(routerId) {
|
|
12162
|
+
return routerId in PAGE_ROUTE_PATTERN_PARSERS;
|
|
12163
|
+
}
|
|
12164
|
+
|
|
12165
|
+
var corePackageJson = {
|
|
12166
|
+
name: "@valbuild/core",
|
|
12167
|
+
version: "0.126.0",
|
|
12168
|
+
"private": false,
|
|
12169
|
+
description: "Val - supercharged hard-coded content",
|
|
12170
|
+
repository: {
|
|
12171
|
+
type: "git",
|
|
12172
|
+
url: "git+https://github.com/valbuild/val.git"
|
|
12173
|
+
},
|
|
12174
|
+
scripts: {
|
|
12175
|
+
typecheck: "tsc --noEmit",
|
|
12176
|
+
test: "jest",
|
|
12177
|
+
"analyze-trace": "npx tsc -p tsconfig.json --skipLibCheck --generateTrace trace; npx -p @typescript/analyze-trace analyze-trace trace; npx speedscope trace/trace.json"
|
|
12178
|
+
},
|
|
12179
|
+
main: "dist/valbuild-core.cjs.js",
|
|
12180
|
+
module: "dist/valbuild-core.esm.js",
|
|
12181
|
+
exports: {
|
|
12182
|
+
".": {
|
|
12183
|
+
module: "./dist/valbuild-core.esm.js",
|
|
12184
|
+
"default": "./dist/valbuild-core.cjs.js"
|
|
12185
|
+
},
|
|
12186
|
+
"./fp": {
|
|
12187
|
+
module: "./fp/dist/valbuild-core-fp.esm.js",
|
|
12188
|
+
"default": "./fp/dist/valbuild-core-fp.cjs.js"
|
|
12189
|
+
},
|
|
12190
|
+
"./patch": {
|
|
12191
|
+
module: "./patch/dist/valbuild-core-patch.esm.js",
|
|
12192
|
+
"default": "./patch/dist/valbuild-core-patch.cjs.js"
|
|
12193
|
+
},
|
|
12194
|
+
"./package.json": "./package.json"
|
|
12195
|
+
},
|
|
12196
|
+
types: "dist/valbuild-core.cjs.d.ts",
|
|
12197
|
+
preconstruct: {
|
|
12198
|
+
entrypoints: [
|
|
12199
|
+
"./index.ts",
|
|
12200
|
+
"./fp/index.ts",
|
|
12201
|
+
"./patch/index.ts"
|
|
12202
|
+
],
|
|
12203
|
+
exports: true
|
|
12204
|
+
},
|
|
12205
|
+
devDependencies: {
|
|
12206
|
+
typescript: "^6.0.3"
|
|
12207
|
+
},
|
|
12208
|
+
dependencies: {
|
|
12209
|
+
"ts-toolbelt": "^9.6.0"
|
|
12210
|
+
},
|
|
12211
|
+
files: [
|
|
12212
|
+
"CHANGELOG.md",
|
|
12213
|
+
"dist",
|
|
12214
|
+
"fp/dist",
|
|
12215
|
+
"fp/package.json",
|
|
12216
|
+
"patch/dist",
|
|
12217
|
+
"patch/package.json"
|
|
12218
|
+
]
|
|
12219
|
+
};
|
|
12220
|
+
|
|
10483
12221
|
var ModuleFilePathSep = "?p=";
|
|
10484
12222
|
var FATAL_ERROR_TYPES = ["no-schema", "no-source", "invalid-id", "no-module", "invalid-patch"];
|
|
10485
12223
|
var DEFAULT_CONTENT_HOST = "https://content.val.build";
|
|
10486
12224
|
var DEFAULT_APP_HOST = "https://admin.val.build";
|
|
10487
12225
|
var Internal = {
|
|
10488
12226
|
VERSION: {
|
|
10489
|
-
core:
|
|
10490
|
-
try {
|
|
10491
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
10492
|
-
return require("../package.json").version;
|
|
10493
|
-
} catch (_unused) {
|
|
10494
|
-
return null;
|
|
10495
|
-
}
|
|
10496
|
-
}()
|
|
12227
|
+
core: corePackageJson.version
|
|
10497
12228
|
},
|
|
10498
12229
|
mediaUrl: mediaUrl,
|
|
10499
12230
|
resolveMedia: resolveMedia,
|
|
@@ -10510,6 +12241,7 @@ var Internal = {
|
|
|
10510
12241
|
splitModuleFilePathAndModulePath: splitModuleFilePathAndModulePath,
|
|
10511
12242
|
joinModuleFilePathAndModulePath: joinModuleFilePathAndModulePath,
|
|
10512
12243
|
nextAppRouter: nextAppRouter,
|
|
12244
|
+
tanstackRouter: tanstackRouter,
|
|
10513
12245
|
externalPageRouter: externalPageRouter,
|
|
10514
12246
|
color: {
|
|
10515
12247
|
parseColor: parseColor,
|
|
@@ -10598,9 +12330,9 @@ var Internal = {
|
|
|
10598
12330
|
function tryJsonParse(str) {
|
|
10599
12331
|
try {
|
|
10600
12332
|
return JSON.parse(str);
|
|
10601
|
-
} catch (
|
|
12333
|
+
} catch (_unused) {
|
|
10602
12334
|
return str;
|
|
10603
12335
|
}
|
|
10604
12336
|
}
|
|
10605
12337
|
|
|
10606
|
-
export { ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D, COLOR_FORMATS as E, FATAL_ERROR_TYPES as F, GenericSelector as G, DEFAULT_COLOR_FORMAT as H, Internal as I, DateTimeSchema as J, KeyOfSchema as K, RouteSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, RichTextSchema as Q, RecordSchema as R, Schema as S,
|
|
12338
|
+
export { parseNextJsRoutePattern as $, ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D, COLOR_FORMATS as E, FATAL_ERROR_TYPES as F, GenericSelector as G, DEFAULT_COLOR_FORMAT as H, Internal as I, DateTimeSchema as J, KeyOfSchema as K, RouteSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, RichTextSchema as Q, RecordSchema as R, Schema as S, DiscriminatedUnionSchema as T, EnumSchema as U, VAL_EXTENSION as V, LiteralSchema as W, deserializeSchema as X, previewScope as Y, isInlineRender as Z, _typeof as _, _slicedToArray as a, parseTanStackRoutePattern as a0, tanStackSegmentsOfRoutePath as a1, validateUrlAgainstPattern as a2, getSourcePathFromRoute as a3, isPageRouter as a4, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, extractValModules as f, computeValModuleShas as g, hasRemoteFileSchema as h, initVal as i, hasMediaSchema as j, DEFAULT_VAL_REMOTE_HOST as k, derefPatch as l, modules as m, StringSchema as n, ImageSchema as o, FileSchema as p, DateSchema as q, SettingsSchema as r, splitModuleFilePathAndModulePath as s, ASSISTANT_SETTINGS_MAX_LENGTH as t, assistantAvailability as u, SETTINGS_MODULE_CONVENTION as v, isRootModuleFilePath as w, resolveSettingsModule as x, CodeSchema as y, CODE_LANGUAGES as z };
|