@valbuild/core 0.125.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 +115 -0
- package/dist/declarations/src/index.d.ts +3 -1
- 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/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-a3846321.cjs.prod.js → index-6db78f3c.cjs.prod.js} +1953 -449
- package/dist/{index-daa122af.cjs.dev.js → index-b41b638f.cjs.dev.js} +1953 -449
- package/dist/{index-915dd675.esm.js → index-cd25c2dc.esm.js} +1952 -449
- package/dist/valbuild-core.cjs.dev.js +3 -2
- package/dist/valbuild-core.cjs.prod.js +3 -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
|
@@ -50,7 +50,47 @@ export declare class ColorSchema<Src extends string | null> extends Schema<Src>
|
|
|
50
50
|
private readonly renderInput;
|
|
51
51
|
private readonly previewInput;
|
|
52
52
|
constructor(options?: ColorOptions | undefined, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
53
|
+
/**
|
|
54
|
+
* Describe this field.
|
|
55
|
+
*
|
|
56
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
57
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
58
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
59
|
+
* assistant and the MCP tools read.
|
|
60
|
+
*
|
|
61
|
+
* Pass `null` to clear a description set earlier.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* const schema = s.color().describe("Background of the hero section");
|
|
65
|
+
* export default c.define(
|
|
66
|
+
* "/example.val.ts",
|
|
67
|
+
* schema,
|
|
68
|
+
* "hsl(217.22 91.22% 59.8%)",
|
|
69
|
+
* );
|
|
70
|
+
*/
|
|
53
71
|
describe(description: string | null): ColorSchema<Src>;
|
|
72
|
+
/**
|
|
73
|
+
* Add a custom validation rule to this field.
|
|
74
|
+
*
|
|
75
|
+
* The function is called with the field's value and returns `false` when the
|
|
76
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
77
|
+
* more than once to add more rules — they all run, and every message is
|
|
78
|
+
* reported.
|
|
79
|
+
*
|
|
80
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
81
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
82
|
+
*
|
|
83
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
84
|
+
* before a publish.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const schema = s
|
|
88
|
+
* .color({ format: "hex" })
|
|
89
|
+
* .validate((val) =>
|
|
90
|
+
* val === val.toLowerCase() ? false : "Write hex in lower case",
|
|
91
|
+
* );
|
|
92
|
+
* export default c.define("/example.val.ts", schema, "#3b82f6");
|
|
93
|
+
*/
|
|
54
94
|
validate(validationFunction: (src: Src) => false | string): ColorSchema<Src>;
|
|
55
95
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
56
96
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
@@ -64,12 +104,26 @@ export declare class ColorSchema<Src extends string | null> extends Schema<Src>
|
|
|
64
104
|
* instead of a preview row that navigates to it.
|
|
65
105
|
*
|
|
66
106
|
* Static configuration, not a callback — see `render.ts`.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const schema = s.array(s.color().render({ as: "inline" }));
|
|
110
|
+
* export default c.define("/example.val.ts", schema, [
|
|
111
|
+
* "hsl(217.22 91.22% 59.8%)",
|
|
112
|
+
* ]);
|
|
67
113
|
*/
|
|
68
114
|
render(input: FieldRender): ColorSchema<Src>;
|
|
69
115
|
/**
|
|
70
116
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
71
117
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
72
118
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* const schema = s.array(
|
|
122
|
+
* s.color().preview(({ val }) => ({ title: val })),
|
|
123
|
+
* );
|
|
124
|
+
* export default c.define("/example.val.ts", schema, [
|
|
125
|
+
* "hsl(217.22 91.22% 59.8%)",
|
|
126
|
+
* ]);
|
|
73
127
|
*/
|
|
74
128
|
preview(select: ItemPreviewInput<Src>): ColorSchema<Src>;
|
|
75
129
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -9,14 +9,14 @@ type DateOptions = {
|
|
|
9
9
|
* Validate that the date is this date or after (inclusive).
|
|
10
10
|
*
|
|
11
11
|
* @example
|
|
12
|
-
* 2021-01-01
|
|
12
|
+
* "2021-01-01"
|
|
13
13
|
*/
|
|
14
14
|
from?: string;
|
|
15
15
|
/**
|
|
16
16
|
* Validate that the date is this date or before (inclusive).
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
|
-
* 2021-01-01
|
|
19
|
+
* "2021-01-01"
|
|
20
20
|
*/
|
|
21
21
|
to?: string;
|
|
22
22
|
};
|
|
@@ -43,11 +43,63 @@ export declare class DateSchema<Src extends string | null> extends Schema<Src> {
|
|
|
43
43
|
private readonly renderInput;
|
|
44
44
|
private readonly previewInput;
|
|
45
45
|
constructor(options?: DateOptions | undefined, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
46
|
+
/**
|
|
47
|
+
* Describe this field.
|
|
48
|
+
*
|
|
49
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
50
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
51
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
52
|
+
* assistant and the MCP tools read.
|
|
53
|
+
*
|
|
54
|
+
* Pass `null` to clear a description set earlier.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const schema = s.date().describe("First day the campaign is live");
|
|
58
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
59
|
+
*/
|
|
46
60
|
describe(description: string | null): DateSchema<Src>;
|
|
61
|
+
/**
|
|
62
|
+
* Add a custom validation rule to this field.
|
|
63
|
+
*
|
|
64
|
+
* The function is called with the field's value and returns `false` when the
|
|
65
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
66
|
+
* more than once to add more rules — they all run, and every message is
|
|
67
|
+
* reported.
|
|
68
|
+
*
|
|
69
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
70
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
71
|
+
*
|
|
72
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
73
|
+
* before a publish.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const schema = s.date().validate((val) =>
|
|
77
|
+
* val >= "2025-01-01" ? false : "Must be in 2025 or later",
|
|
78
|
+
* );
|
|
79
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
80
|
+
*/
|
|
47
81
|
validate(validationFunction: (src: Src) => false | string): DateSchema<Src>;
|
|
48
82
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
49
83
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
84
|
+
/**
|
|
85
|
+
* Validate that the date is this date or after (inclusive).
|
|
86
|
+
*
|
|
87
|
+
* Written as `YYYY-MM-DD`, the same shape the value has.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const schema = s.date().from("2025-01-01");
|
|
91
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
92
|
+
*/
|
|
50
93
|
from(from: string): DateSchema<Src>;
|
|
94
|
+
/**
|
|
95
|
+
* Validate that the date is this date or before (inclusive).
|
|
96
|
+
*
|
|
97
|
+
* Written as `YYYY-MM-DD`, the same shape the value has.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const schema = s.date().from("2025-01-01").to("2025-12-31");
|
|
101
|
+
* export default c.define("/example.val.ts", schema, "2025-06-01");
|
|
102
|
+
*/
|
|
51
103
|
to(to: string): DateSchema<Src>;
|
|
52
104
|
nullable(): DateSchema<Src | null>;
|
|
53
105
|
readonly(isReadonly?: boolean): DateSchema<Src>;
|
|
@@ -59,12 +111,22 @@ export declare class DateSchema<Src extends string | null> extends Schema<Src> {
|
|
|
59
111
|
* instead of a preview row that navigates to it.
|
|
60
112
|
*
|
|
61
113
|
* Static configuration, not a callback — see `render.ts`.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* const schema = s.array(s.date().render({ as: "inline" }));
|
|
117
|
+
* export default c.define("/example.val.ts", schema, ["2025-06-01"]);
|
|
62
118
|
*/
|
|
63
119
|
render(input: FieldRender): DateSchema<Src>;
|
|
64
120
|
/**
|
|
65
121
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
66
122
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
67
123
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* const schema = s.array(
|
|
127
|
+
* s.date().preview(({ val }) => ({ title: val })),
|
|
128
|
+
* );
|
|
129
|
+
* export default c.define("/example.val.ts", schema, ["2025-06-01"]);
|
|
68
130
|
*/
|
|
69
131
|
preview(select: ItemPreviewInput<Src>): DateSchema<Src>;
|
|
70
132
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -11,7 +11,7 @@ type DateTimeOptions = {
|
|
|
11
11
|
* Accepts any ISO 8601 datetime string parseable by `Date.parse`.
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
|
-
* 2021-01-01T00:00:00Z
|
|
14
|
+
* "2021-01-01T00:00:00Z"
|
|
15
15
|
*/
|
|
16
16
|
from?: string;
|
|
17
17
|
/**
|
|
@@ -20,7 +20,7 @@ type DateTimeOptions = {
|
|
|
20
20
|
* Accepts any ISO 8601 datetime string parseable by `Date.parse`.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
|
-
* 2021-12-31T23:59:59Z
|
|
23
|
+
* "2021-12-31T23:59:59Z"
|
|
24
24
|
*/
|
|
25
25
|
to?: string;
|
|
26
26
|
};
|
|
@@ -47,11 +47,82 @@ export declare class DateTimeSchema<Src extends string | null> extends Schema<Sr
|
|
|
47
47
|
private readonly renderInput;
|
|
48
48
|
private readonly previewInput;
|
|
49
49
|
constructor(options?: DateTimeOptions | undefined, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
50
|
+
/**
|
|
51
|
+
* Describe this field.
|
|
52
|
+
*
|
|
53
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
54
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
55
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
56
|
+
* assistant and the MCP tools read.
|
|
57
|
+
*
|
|
58
|
+
* Pass `null` to clear a description set earlier.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* const schema = s.datetime().describe("When the article goes live");
|
|
62
|
+
* export default c.define(
|
|
63
|
+
* "/example.val.ts",
|
|
64
|
+
* schema,
|
|
65
|
+
* "2025-06-01T09:00:00.000Z",
|
|
66
|
+
* );
|
|
67
|
+
*/
|
|
50
68
|
describe(description: string | null): DateTimeSchema<Src>;
|
|
69
|
+
/**
|
|
70
|
+
* Add a custom validation rule to this field.
|
|
71
|
+
*
|
|
72
|
+
* The function is called with the field's value and returns `false` when the
|
|
73
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
74
|
+
* more than once to add more rules — they all run, and every message is
|
|
75
|
+
* reported.
|
|
76
|
+
*
|
|
77
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
78
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
79
|
+
*
|
|
80
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
81
|
+
* before a publish.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* const schema = s.datetime().validate((val) =>
|
|
85
|
+
* val.endsWith("Z") ? false : "Must be in UTC",
|
|
86
|
+
* );
|
|
87
|
+
* export default c.define(
|
|
88
|
+
* "/example.val.ts",
|
|
89
|
+
* schema,
|
|
90
|
+
* "2025-06-01T09:00:00.000Z",
|
|
91
|
+
* );
|
|
92
|
+
*/
|
|
51
93
|
validate(validationFunction: (src: Src) => false | string): DateTimeSchema<Src>;
|
|
52
94
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
53
95
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
96
|
+
/**
|
|
97
|
+
* Validate that the datetime is this datetime or after (inclusive).
|
|
98
|
+
*
|
|
99
|
+
* Any ISO 8601 datetime string `Date.parse` understands.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const schema = s.datetime().from("2025-01-01T00:00:00Z");
|
|
103
|
+
* export default c.define(
|
|
104
|
+
* "/example.val.ts",
|
|
105
|
+
* schema,
|
|
106
|
+
* "2025-06-01T09:00:00.000Z",
|
|
107
|
+
* );
|
|
108
|
+
*/
|
|
54
109
|
from(from: string): DateTimeSchema<Src>;
|
|
110
|
+
/**
|
|
111
|
+
* Validate that the datetime is this datetime or before (inclusive).
|
|
112
|
+
*
|
|
113
|
+
* Any ISO 8601 datetime string `Date.parse` understands.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* const schema = s
|
|
117
|
+
* .datetime()
|
|
118
|
+
* .from("2025-01-01T00:00:00Z")
|
|
119
|
+
* .to("2025-12-31T23:59:59Z");
|
|
120
|
+
* export default c.define(
|
|
121
|
+
* "/example.val.ts",
|
|
122
|
+
* schema,
|
|
123
|
+
* "2025-06-01T09:00:00.000Z",
|
|
124
|
+
* );
|
|
125
|
+
*/
|
|
55
126
|
to(to: string): DateTimeSchema<Src>;
|
|
56
127
|
nullable(): DateTimeSchema<Src | null>;
|
|
57
128
|
readonly(isReadonly?: boolean): DateTimeSchema<Src>;
|
|
@@ -63,12 +134,26 @@ export declare class DateTimeSchema<Src extends string | null> extends Schema<Sr
|
|
|
63
134
|
* instead of a preview row that navigates to it.
|
|
64
135
|
*
|
|
65
136
|
* Static configuration, not a callback — see `render.ts`.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const schema = s.array(s.datetime().render({ as: "inline" }));
|
|
140
|
+
* export default c.define("/example.val.ts", schema, [
|
|
141
|
+
* "2025-06-01T09:00:00.000Z",
|
|
142
|
+
* ]);
|
|
66
143
|
*/
|
|
67
144
|
render(input: FieldRender): DateTimeSchema<Src>;
|
|
68
145
|
/**
|
|
69
146
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
70
147
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
71
148
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* const schema = s.array(
|
|
152
|
+
* s.datetime().preview(({ val }) => ({ title: val })),
|
|
153
|
+
* );
|
|
154
|
+
* export default c.define("/example.val.ts", schema, [
|
|
155
|
+
* "2025-06-01T09:00:00.000Z",
|
|
156
|
+
* ]);
|
|
72
157
|
*/
|
|
73
158
|
preview(select: ItemPreviewInput<Src>): DateTimeSchema<Src>;
|
|
74
159
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { CustomValidateFunction, Schema, SchemaAssertResult } from "./index.js";
|
|
2
|
+
import { ItemPreviewInput, PreviewItem, ReifiedPreview, PreviewScope } from "../preview.js";
|
|
3
|
+
import { FieldRender } from "../render.js";
|
|
4
|
+
import { SelectorSource } from "../selector/index.js";
|
|
5
|
+
import { SourceObject } from "../source/index.js";
|
|
6
|
+
import { ModuleFilePath, SourcePath } from "../val/index.js";
|
|
7
|
+
import { SerializedObjectSchema } from "./object.js";
|
|
8
|
+
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
9
|
+
export type SerializedDiscriminatedUnionSchema = {
|
|
10
|
+
type: "discriminated-union";
|
|
11
|
+
/** Static layout config, carried whole in the serialized schema — see `render.ts`. */
|
|
12
|
+
render?: FieldRender;
|
|
13
|
+
/** Set when this schema declares a `preview`. The closure itself cannot serialize. */
|
|
14
|
+
preview?: true;
|
|
15
|
+
/** The name of the field every variant tags itself with. */
|
|
16
|
+
key: string;
|
|
17
|
+
items: SerializedObjectSchema[];
|
|
18
|
+
opt: boolean;
|
|
19
|
+
customValidate?: boolean;
|
|
20
|
+
readonly?: boolean;
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
description?: string;
|
|
23
|
+
};
|
|
24
|
+
/** The variant objects a discriminated union on `Key` may be built from. */
|
|
25
|
+
export type DiscriminatedUnionItem<Key extends string> = Schema<SourceObject & {
|
|
26
|
+
[k in Key]: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* At least one variant, so a union with none cannot be written.
|
|
30
|
+
*
|
|
31
|
+
* Everything downstream reads the first one where it needs any — `emptyOf`
|
|
32
|
+
* takes `items[0]` for the value a new entry starts as — and a union with
|
|
33
|
+
* nothing to select is not a thing an author means. `s.enum` says the same
|
|
34
|
+
* about its values.
|
|
35
|
+
*/
|
|
36
|
+
export type DiscriminatedUnionItems<Key extends string> = [
|
|
37
|
+
DiscriminatedUnionItem<Key>,
|
|
38
|
+
...DiscriminatedUnionItem<Key>[]
|
|
39
|
+
];
|
|
40
|
+
/** The source type a discriminated union over `T` accepts. */
|
|
41
|
+
export type DiscriminatedUnionSourceOf<Key extends string, T extends DiscriminatedUnionItem<Key>[]> = T extends Schema<infer S>[] ? S extends SelectorSource ? S : never : never;
|
|
42
|
+
/**
|
|
43
|
+
* One of several object shapes, told apart by a tag field.
|
|
44
|
+
*
|
|
45
|
+
* Every variant is an object with `key` set to a distinct `s.literal(...)`, and
|
|
46
|
+
* the value of that field decides which variant a value is. Unlike
|
|
47
|
+
* {@link EnumSchema} this is a CONTAINER: the variant's fields are the fields
|
|
48
|
+
* being edited, and everything that walks the schema tree has to descend
|
|
49
|
+
* through the matching variant.
|
|
50
|
+
*/
|
|
51
|
+
export declare class DiscriminatedUnionSchema<Key extends string, T extends DiscriminatedUnionItem<Key>[], Src extends DiscriminatedUnionSourceOf<Key, T> | null> extends Schema<Src> {
|
|
52
|
+
private readonly key;
|
|
53
|
+
private readonly items;
|
|
54
|
+
private readonly opt;
|
|
55
|
+
private readonly customValidateFunctions;
|
|
56
|
+
private readonly isReadonly;
|
|
57
|
+
private readonly isHidden;
|
|
58
|
+
private readonly description?;
|
|
59
|
+
private readonly renderInput;
|
|
60
|
+
private readonly previewInput;
|
|
61
|
+
constructor(key: Key, items: T, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
62
|
+
/**
|
|
63
|
+
* Describe this field.
|
|
64
|
+
*
|
|
65
|
+
* The description is shown next to the field's label in the Val editor, so it is
|
|
66
|
+
* where you say what an editor needs to know but the field name cannot carry. It
|
|
67
|
+
* also travels in the serialized schema, which is what the AI assistant and the
|
|
68
|
+
* MCP tools read.
|
|
69
|
+
*
|
|
70
|
+
* Pass `null` to clear a description set earlier.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
74
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
75
|
+
* const schema = s
|
|
76
|
+
* .discriminatedUnion("type", hero, text)
|
|
77
|
+
* .describe("What this section of the page is");
|
|
78
|
+
* export default c.define("/example.val.ts", schema, {
|
|
79
|
+
* type: "hero",
|
|
80
|
+
* title: "Hello",
|
|
81
|
+
* });
|
|
82
|
+
*/
|
|
83
|
+
describe(description: string | null): DiscriminatedUnionSchema<Key, T, Src>;
|
|
84
|
+
/**
|
|
85
|
+
* Add a custom validation rule to this field.
|
|
86
|
+
*
|
|
87
|
+
* The function is called with the field's value and returns `false` when the
|
|
88
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
89
|
+
* more than once to add more rules — they all run, and every message is
|
|
90
|
+
* reported.
|
|
91
|
+
*
|
|
92
|
+
* Validation runs in the Studio as you type, in `npx val validate` and before a
|
|
93
|
+
* publish.
|
|
94
|
+
*
|
|
95
|
+
* The function is given the whole value, whichever variant it took. A rule
|
|
96
|
+
* that only concerns one variant belongs on that variant's object schema.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
100
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
101
|
+
* const schema = s
|
|
102
|
+
* .discriminatedUnion("type", hero, text)
|
|
103
|
+
* .validate((val) =>
|
|
104
|
+
* val.type === "hero" && !val.title ? "A hero needs a title" : false,
|
|
105
|
+
* );
|
|
106
|
+
* export default c.define("/example.val.ts", schema, {
|
|
107
|
+
* type: "hero",
|
|
108
|
+
* title: "Hello",
|
|
109
|
+
* });
|
|
110
|
+
*/
|
|
111
|
+
validate(validationFunction: (src: Src) => false | string): DiscriminatedUnionSchema<Key, T, Src>;
|
|
112
|
+
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
113
|
+
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
114
|
+
nullable(): DiscriminatedUnionSchema<Key, T, Src | null>;
|
|
115
|
+
readonly(isReadonly?: boolean): DiscriminatedUnionSchema<Key, T, Src>;
|
|
116
|
+
hidden(isHidden?: boolean): DiscriminatedUnionSchema<Key, T, Src>;
|
|
117
|
+
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
118
|
+
/**
|
|
119
|
+
* The variant schema a value takes. `null` when the value matches none of
|
|
120
|
+
* them — a structural error `executeValidate` already reports.
|
|
121
|
+
*/
|
|
122
|
+
private matchedVariant;
|
|
123
|
+
/**
|
|
124
|
+
* How this field is laid out in the editor when it is the item of an array
|
|
125
|
+
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
126
|
+
* instead of a preview row that navigates to it.
|
|
127
|
+
*
|
|
128
|
+
* Static configuration, not a callback — see `render.ts`.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // A page builder: the row draws the tag selector and the matched
|
|
132
|
+
* // variant's fields.
|
|
133
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
134
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
135
|
+
* const block = s.discriminatedUnion("type", hero, text).render({ as: "inline" });
|
|
136
|
+
* export default c.define("/example.val.ts", s.array(block), [
|
|
137
|
+
* { type: "hero", title: "Hello" },
|
|
138
|
+
* ]);
|
|
139
|
+
*/
|
|
140
|
+
render(input: FieldRender): DiscriminatedUnionSchema<Key, T, Src>;
|
|
141
|
+
/**
|
|
142
|
+
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
143
|
+
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
144
|
+
* itself is edited (that is `render`). See `preview.ts`.
|
|
145
|
+
*
|
|
146
|
+
* Without one of its own, a discriminated union previews as the VARIANT the
|
|
147
|
+
* value takes — declare `preview` on the member objects and the union
|
|
148
|
+
* dispatches.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* const hero = s.object({ type: s.literal("hero"), title: s.string() });
|
|
152
|
+
* const text = s.object({ type: s.literal("text"), body: s.string() });
|
|
153
|
+
* const block = s
|
|
154
|
+
* .discriminatedUnion("type", hero, text)
|
|
155
|
+
* .preview(({ val }) => ({ title: val.type }));
|
|
156
|
+
* export default c.define("/example.val.ts", s.array(block), [
|
|
157
|
+
* { type: "hero", title: "Hello" },
|
|
158
|
+
* ]);
|
|
159
|
+
*/
|
|
160
|
+
preview(select: ItemPreviewInput<Src>): DiscriminatedUnionSchema<Key, T, Src>;
|
|
161
|
+
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
162
|
+
protected declaresItemPreview(): boolean;
|
|
163
|
+
protected executeSerialize(): SerializedDiscriminatedUnionSchema;
|
|
164
|
+
protected executePreview(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: PreviewScope): ReifiedPreview;
|
|
165
|
+
}
|
|
166
|
+
export declare const discriminatedUnion: <Key extends string, T extends DiscriminatedUnionItems<Key>>(key: Key, ...objects: T) => DiscriminatedUnionSchema<Key, T, DiscriminatedUnionSourceOf<Key, T>>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { CustomValidateFunction, Schema, SchemaAssertResult } from "./index.js";
|
|
2
|
+
import { ItemPreviewInput, PreviewItem, ReifiedPreview } from "../preview.js";
|
|
3
|
+
import { FieldRender } from "../render.js";
|
|
4
|
+
import { SourcePath } from "../val/index.js";
|
|
5
|
+
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
6
|
+
export type SerializedEnumSchema = {
|
|
7
|
+
type: "enum";
|
|
8
|
+
/** Static layout config, carried whole in the serialized schema — see `render.ts`. */
|
|
9
|
+
render?: FieldRender;
|
|
10
|
+
/** Set when this schema declares a `preview`. The closure itself cannot serialize. */
|
|
11
|
+
preview?: true;
|
|
12
|
+
/**
|
|
13
|
+
* Every value this field may take, in declaration order — which is the order
|
|
14
|
+
* the editor's dropdown offers them in.
|
|
15
|
+
*/
|
|
16
|
+
values: string[];
|
|
17
|
+
opt: boolean;
|
|
18
|
+
customValidate?: boolean;
|
|
19
|
+
readonly?: boolean;
|
|
20
|
+
hidden?: boolean;
|
|
21
|
+
description?: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* One of a fixed set of strings.
|
|
25
|
+
*
|
|
26
|
+
* The values are the schema — there are no member schemas to descend into, so
|
|
27
|
+
* this is a LEAF, like `s.string()` with a closed domain. That is the whole
|
|
28
|
+
* difference from {@link DiscriminatedUnionSchema}, and the reason the two are
|
|
29
|
+
* separate: everything that walks a schema tree has to recurse into a
|
|
30
|
+
* discriminated union's variants and must not try to recurse into these.
|
|
31
|
+
*/
|
|
32
|
+
export declare class EnumSchema<Src extends string | null> extends Schema<Src> {
|
|
33
|
+
private readonly values;
|
|
34
|
+
private readonly opt;
|
|
35
|
+
private readonly customValidateFunctions;
|
|
36
|
+
private readonly isReadonly;
|
|
37
|
+
private readonly isHidden;
|
|
38
|
+
private readonly description?;
|
|
39
|
+
private readonly renderInput;
|
|
40
|
+
private readonly previewInput;
|
|
41
|
+
constructor(values: readonly string[], opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
42
|
+
/**
|
|
43
|
+
* Describe this field.
|
|
44
|
+
*
|
|
45
|
+
* The description is shown next to the field's label in the Val editor, so it is
|
|
46
|
+
* where you say what an editor needs to know but the field name cannot carry. It
|
|
47
|
+
* also travels in the serialized schema, which is what the AI assistant and the
|
|
48
|
+
* MCP tools read.
|
|
49
|
+
*
|
|
50
|
+
* Pass `null` to clear a description set earlier.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* const schema = s
|
|
54
|
+
* .enum("draft", "published")
|
|
55
|
+
* .describe("Only published pages are built");
|
|
56
|
+
* export default c.define("/example.val.ts", schema, "draft");
|
|
57
|
+
*/
|
|
58
|
+
describe(description: string | null): EnumSchema<Src>;
|
|
59
|
+
/**
|
|
60
|
+
* Add a custom validation rule to this field.
|
|
61
|
+
*
|
|
62
|
+
* The function is called with the field's value and returns `false` when the
|
|
63
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
64
|
+
* more than once to add more rules — they all run, and every message is
|
|
65
|
+
* reported.
|
|
66
|
+
*
|
|
67
|
+
* Validation runs in the Studio as you type, in `npx val validate` and before a
|
|
68
|
+
* publish.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* const schema = s
|
|
72
|
+
* .enum("draft", "published")
|
|
73
|
+
* .validate((val) =>
|
|
74
|
+
* val === "published" ? "Publishing is frozen this week" : false,
|
|
75
|
+
* );
|
|
76
|
+
* export default c.define("/example.val.ts", schema, "draft");
|
|
77
|
+
*/
|
|
78
|
+
validate(validationFunction: (src: Src) => false | string): EnumSchema<Src>;
|
|
79
|
+
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
80
|
+
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
81
|
+
nullable(): EnumSchema<Src | null>;
|
|
82
|
+
readonly(isReadonly?: boolean): EnumSchema<Src>;
|
|
83
|
+
hidden(isHidden?: boolean): EnumSchema<Src>;
|
|
84
|
+
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
85
|
+
/**
|
|
86
|
+
* How this field is laid out in the editor when it is the item of an array
|
|
87
|
+
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
88
|
+
* instead of a preview row that navigates to it.
|
|
89
|
+
*
|
|
90
|
+
* Static configuration, not a callback — see `render.ts`.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* const schema = s.array(
|
|
94
|
+
* s.enum("draft", "published").render({ as: "inline" }),
|
|
95
|
+
* );
|
|
96
|
+
* export default c.define("/example.val.ts", schema, ["draft"]);
|
|
97
|
+
*/
|
|
98
|
+
render(input: FieldRender): EnumSchema<Src>;
|
|
99
|
+
/**
|
|
100
|
+
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
101
|
+
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
102
|
+
* itself is edited (that is `render`). See `preview.ts`.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* const schema = s.array(
|
|
106
|
+
* s.enum("draft", "published").preview(({ val }) => ({ title: val })),
|
|
107
|
+
* );
|
|
108
|
+
* export default c.define("/example.val.ts", schema, ["draft"]);
|
|
109
|
+
*/
|
|
110
|
+
preview(select: ItemPreviewInput<Src>): EnumSchema<Src>;
|
|
111
|
+
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
112
|
+
protected declaresItemPreview(): boolean;
|
|
113
|
+
protected executeSerialize(): SerializedEnumSchema;
|
|
114
|
+
protected executePreview(): ReifiedPreview;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Define a string that must be one of a fixed set of values.
|
|
118
|
+
*
|
|
119
|
+
* Named `enumSchema` rather than `enum` because `enum` is a reserved word and
|
|
120
|
+
* cannot be a binding name; it is exposed as `s.enum`.
|
|
121
|
+
*/
|
|
122
|
+
export declare const enumSchema: <T extends string>(...values: [T, ...T[]]) => EnumSchema<T>;
|