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