@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
|
@@ -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>;
|
|
@@ -37,8 +37,71 @@ export declare class FileSchema<Src extends FileSource | null> extends Schema<Sr
|
|
|
37
37
|
private readonly renderInput;
|
|
38
38
|
private readonly previewInput;
|
|
39
39
|
constructor(options?: FileOptions | undefined, opt?: boolean, isRemote?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], moduleMetadata?: Record<ModulePath, Record<string, FilesEntryMetadata>>, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
40
|
+
/**
|
|
41
|
+
* Describe this field.
|
|
42
|
+
*
|
|
43
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
44
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
45
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
46
|
+
* assistant and the MCP tools read.
|
|
47
|
+
*
|
|
48
|
+
* Pass `null` to clear a description set earlier.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const schema = s.file().describe("The PDF offered for download");
|
|
52
|
+
* export default c.define("/example.val.ts", schema, {
|
|
53
|
+
* path: "/public/val/example.pdf",
|
|
54
|
+
* mimeType: "application/pdf",
|
|
55
|
+
* });
|
|
56
|
+
*/
|
|
40
57
|
describe(description: string | null): FileSchema<Src>;
|
|
58
|
+
/**
|
|
59
|
+
* Store the file on Val's remote content host instead of in your repository.
|
|
60
|
+
*
|
|
61
|
+
* The bytes still go into the patch store when the file is uploaded — the
|
|
62
|
+
* push to the remote host happens at publish. What changes is where the
|
|
63
|
+
* published file lives: `path` becomes a remote URL rather than a path under
|
|
64
|
+
* `/public`, so the repository does not grow with every upload.
|
|
65
|
+
*
|
|
66
|
+
* The `path` of a remote file is a URL on the content host, and it is not
|
|
67
|
+
* something to write by hand: upload the file in the Studio, or write a
|
|
68
|
+
* local path and let `npx val validate --fix` upload it and rewrite the
|
|
69
|
+
* `path` to the ref below.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* const schema = s.file({ accept: "application/pdf" }).remote();
|
|
73
|
+
* export default c.define("/example.val.ts", schema, {
|
|
74
|
+
* path: "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/example.pdf",
|
|
75
|
+
* mimeType: "application/pdf",
|
|
76
|
+
* });
|
|
77
|
+
*/
|
|
41
78
|
remote(): FileSchema<Src>;
|
|
79
|
+
/**
|
|
80
|
+
* Add a custom validation rule to this field.
|
|
81
|
+
*
|
|
82
|
+
* The function is called with the field's value and returns `false` when the
|
|
83
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
84
|
+
* more than once to add more rules — they all run, and every message is
|
|
85
|
+
* reported.
|
|
86
|
+
*
|
|
87
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
88
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
89
|
+
*
|
|
90
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
91
|
+
* before a publish.
|
|
92
|
+
*
|
|
93
|
+
* The second argument carries the `path` of the field being validated, for
|
|
94
|
+
* when the message needs to say where the problem is.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* const schema = s.file().validate((val) =>
|
|
98
|
+
* val.path.endsWith(".pdf") ? false : "Must be a PDF",
|
|
99
|
+
* );
|
|
100
|
+
* export default c.define("/example.val.ts", schema, {
|
|
101
|
+
* path: "/public/val/example.pdf",
|
|
102
|
+
* mimeType: "application/pdf",
|
|
103
|
+
* });
|
|
104
|
+
*/
|
|
42
105
|
validate(validationFunction: CustomValidateFunction<Src>): FileSchema<Src>;
|
|
43
106
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
44
107
|
/**
|
|
@@ -57,12 +120,26 @@ export declare class FileSchema<Src extends FileSource | null> extends Schema<Sr
|
|
|
57
120
|
* instead of a preview row that navigates to it.
|
|
58
121
|
*
|
|
59
122
|
* Static configuration, not a callback — see `render.ts`.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* const schema = s.array(s.file().render({ as: "inline" }));
|
|
126
|
+
* export default c.define("/example.val.ts", schema, [
|
|
127
|
+
* { path: "/public/val/example.pdf", mimeType: "application/pdf" },
|
|
128
|
+
* ]);
|
|
60
129
|
*/
|
|
61
130
|
render(input: FieldRender): FileSchema<Src>;
|
|
62
131
|
/**
|
|
63
132
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
64
133
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
65
134
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* const schema = s.array(
|
|
138
|
+
* s.file().preview(({ val }) => ({ title: val.path })),
|
|
139
|
+
* );
|
|
140
|
+
* export default c.define("/example.val.ts", schema, [
|
|
141
|
+
* { path: "/public/val/example.pdf", mimeType: "application/pdf" },
|
|
142
|
+
* ]);
|
|
66
143
|
*/
|
|
67
144
|
preview(select: ItemPreviewInput<Src>): FileSchema<Src>;
|
|
68
145
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -82,8 +82,82 @@ export declare class ImageSchema<Src extends ImageSource | null> extends Schema<
|
|
|
82
82
|
private readonly renderInput;
|
|
83
83
|
private readonly previewInput;
|
|
84
84
|
constructor(options?: ImageOptions | undefined, opt?: boolean, isRemote?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], moduleMetadata?: Record<ModulePath, Record<string, ImagesEntryMetadata>>, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
85
|
+
/**
|
|
86
|
+
* Describe this field.
|
|
87
|
+
*
|
|
88
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
89
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
90
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
91
|
+
* assistant and the MCP tools read.
|
|
92
|
+
*
|
|
93
|
+
* Pass `null` to clear a description set earlier.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* const schema = s
|
|
97
|
+
* .image()
|
|
98
|
+
* .describe("Shown at the top of the page, 16:9 works best");
|
|
99
|
+
* export default c.define("/example.val.ts", schema, {
|
|
100
|
+
* path: "/public/val/example.png",
|
|
101
|
+
* width: 100,
|
|
102
|
+
* height: 100,
|
|
103
|
+
* mimeType: "image/png",
|
|
104
|
+
* });
|
|
105
|
+
*/
|
|
85
106
|
describe(description: string | null): ImageSchema<Src>;
|
|
107
|
+
/**
|
|
108
|
+
* Store the image on Val's remote content host instead of in your repository.
|
|
109
|
+
*
|
|
110
|
+
* The bytes still go into the patch store when the image is uploaded — the
|
|
111
|
+
* push to the remote host happens at publish. What changes is where the
|
|
112
|
+
* published image lives: `path` becomes a remote URL rather than a path
|
|
113
|
+
* under `/public`, so the repository does not grow with every upload.
|
|
114
|
+
*
|
|
115
|
+
* The `path` of a remote image is a URL on the content host, and it is not
|
|
116
|
+
* something to write by hand: upload the image in the Studio, or write a
|
|
117
|
+
* local path and let `npx val validate --fix` upload it and rewrite the
|
|
118
|
+
* `path` to the ref below.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* const schema = s
|
|
122
|
+
* .image({ accept: "image/webp", directory: "/public/val/images" })
|
|
123
|
+
* .remote();
|
|
124
|
+
* export default c.define("/example.val.ts", schema, {
|
|
125
|
+
* 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",
|
|
126
|
+
* width: 100,
|
|
127
|
+
* height: 100,
|
|
128
|
+
* mimeType: "image/webp",
|
|
129
|
+
* });
|
|
130
|
+
*/
|
|
86
131
|
remote(): ImageSchema<Src>;
|
|
132
|
+
/**
|
|
133
|
+
* Add a custom validation rule to this field.
|
|
134
|
+
*
|
|
135
|
+
* The function is called with the field's value and returns `false` when the
|
|
136
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
137
|
+
* more than once to add more rules — they all run, and every message is
|
|
138
|
+
* reported.
|
|
139
|
+
*
|
|
140
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
141
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
142
|
+
*
|
|
143
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
144
|
+
* before a publish.
|
|
145
|
+
*
|
|
146
|
+
* The second argument carries the `path` of the field being validated, for
|
|
147
|
+
* when the message needs to say where the problem is.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* const schema = s.image().validate((val) =>
|
|
151
|
+
* val.alt ? false : "Every image needs alt text",
|
|
152
|
+
* );
|
|
153
|
+
* export default c.define("/example.val.ts", schema, {
|
|
154
|
+
* path: "/public/val/example.png",
|
|
155
|
+
* width: 100,
|
|
156
|
+
* height: 100,
|
|
157
|
+
* mimeType: "image/png",
|
|
158
|
+
* alt: "An example",
|
|
159
|
+
* });
|
|
160
|
+
*/
|
|
87
161
|
validate(validationFunction: CustomValidateFunction<Src>): ImageSchema<Src>;
|
|
88
162
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
89
163
|
/**
|
|
@@ -102,12 +176,40 @@ export declare class ImageSchema<Src extends ImageSource | null> extends Schema<
|
|
|
102
176
|
* instead of a preview row that navigates to it.
|
|
103
177
|
*
|
|
104
178
|
* Static configuration, not a callback — see `render.ts`.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* const schema = s.array(s.image().render({ as: "inline" }));
|
|
182
|
+
* export default c.define("/example.val.ts", schema, [
|
|
183
|
+
* {
|
|
184
|
+
* path: "/public/val/example.png",
|
|
185
|
+
* width: 100,
|
|
186
|
+
* height: 100,
|
|
187
|
+
* mimeType: "image/png",
|
|
188
|
+
* },
|
|
189
|
+
* ]);
|
|
105
190
|
*/
|
|
106
191
|
render(input: FieldRender): ImageSchema<Src>;
|
|
107
192
|
/**
|
|
108
193
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
109
194
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
110
195
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* const schema = s.array(
|
|
199
|
+
* s.image().preview(({ val }) => ({
|
|
200
|
+
* title: val.alt ?? "Image",
|
|
201
|
+
* image: val,
|
|
202
|
+
* })),
|
|
203
|
+
* );
|
|
204
|
+
* export default c.define("/example.val.ts", schema, [
|
|
205
|
+
* {
|
|
206
|
+
* path: "/public/val/example.png",
|
|
207
|
+
* width: 100,
|
|
208
|
+
* height: 100,
|
|
209
|
+
* mimeType: "image/png",
|
|
210
|
+
* alt: "An example",
|
|
211
|
+
* },
|
|
212
|
+
* ]);
|
|
111
213
|
*/
|
|
112
214
|
preview(select: ItemPreviewInput<Src>): ImageSchema<Src>;
|
|
113
215
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -11,7 +11,8 @@ import { SerializedObjectSchema } from "./object.js";
|
|
|
11
11
|
import { SerializedRecordSchema } from "./record.js";
|
|
12
12
|
import { SerializedRichTextSchema } from "./richtext.js";
|
|
13
13
|
import { RawString, SerializedStringSchema } from "./string.js";
|
|
14
|
-
import {
|
|
14
|
+
import { SerializedDiscriminatedUnionSchema } from "./discriminatedUnion.js";
|
|
15
|
+
import { SerializedEnumSchema } from "./enum.js";
|
|
15
16
|
import { SerializedCodeSchema } from "./code.js";
|
|
16
17
|
import { SerializedColorSchema } from "./color.js";
|
|
17
18
|
import { SerializedDateSchema } from "./date.js";
|
|
@@ -22,7 +23,7 @@ import { ValidationError, ValidationErrors } from "./validation/ValidationError.
|
|
|
22
23
|
import { FileSource } from "../source/media.js";
|
|
23
24
|
import { GenericRichTextSourceNode, RichTextSource } from "../source/richtext.js";
|
|
24
25
|
import { ReifiedPreview, PreviewScope, PreviewItem } from "../preview.js";
|
|
25
|
-
export type SerializedSchema = SerializedStringSchema | SerializedLiteralSchema | SerializedBooleanSchema | SerializedNumberSchema | SerializedObjectSchema | SerializedArraySchema |
|
|
26
|
+
export type SerializedSchema = SerializedStringSchema | SerializedLiteralSchema | SerializedBooleanSchema | SerializedNumberSchema | SerializedObjectSchema | SerializedArraySchema | SerializedDiscriminatedUnionSchema | SerializedEnumSchema | SerializedRichTextSchema | SerializedRecordSchema | SerializedKeyOfSchema | SerializedFileSchema | SerializedDateSchema | SerializedDateTimeSchema | SerializedColorSchema | SerializedCodeSchema | SerializedRouteSchema | SerializedSettingsSchema | SerializedImageSchema;
|
|
26
27
|
type Primitives = number | string | boolean | null | FileSource;
|
|
27
28
|
export type AssertError = {
|
|
28
29
|
message: string;
|
|
@@ -92,6 +93,25 @@ export declare abstract class Schema<Src extends SelectorSource> {
|
|
|
92
93
|
* For example, if you have an object schema, you must assert each key / value pair manually.
|
|
93
94
|
*/
|
|
94
95
|
protected abstract executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
96
|
+
/**
|
|
97
|
+
* Allow `null` as a value for this field.
|
|
98
|
+
*
|
|
99
|
+
* The editor gets a way to clear the field, and the type of the source
|
|
100
|
+
* widens to include `null` — so consuming code has to handle it.
|
|
101
|
+
*
|
|
102
|
+
* Declare `.validate(...)` AFTER `.nullable()`: on most schema types a
|
|
103
|
+
* validator added before it is not carried over.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* const schema = s.object({
|
|
107
|
+
* title: s.string(),
|
|
108
|
+
* subtitle: s.string().nullable(),
|
|
109
|
+
* });
|
|
110
|
+
* export default c.define("/example.val.ts", schema, {
|
|
111
|
+
* title: "Hello",
|
|
112
|
+
* subtitle: null,
|
|
113
|
+
* });
|
|
114
|
+
*/
|
|
95
115
|
abstract nullable(): Schema<Src | null>;
|
|
96
116
|
/**
|
|
97
117
|
* Mark this field as read-only in the Val editor.
|
|
@@ -102,6 +122,16 @@ export declare abstract class Schema<Src extends SelectorSource> {
|
|
|
102
122
|
* The flag defaults to `true`, so `.readonly()` and `.readonly(true)` are the
|
|
103
123
|
* same thing. `.readonly(false)` leaves the field editable, which is what a
|
|
104
124
|
* schema is anyway - pass it when the decision comes from a variable.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* const schema = s.object({
|
|
128
|
+
* id: s.string().readonly(),
|
|
129
|
+
* title: s.string(),
|
|
130
|
+
* });
|
|
131
|
+
* export default c.define("/example.val.ts", schema, {
|
|
132
|
+
* id: "generated-by-the-build",
|
|
133
|
+
* title: "Hello",
|
|
134
|
+
* });
|
|
105
135
|
*/
|
|
106
136
|
abstract readonly(isReadonly?: boolean): Schema<Src>;
|
|
107
137
|
/**
|
|
@@ -113,6 +143,16 @@ export declare abstract class Schema<Src extends SelectorSource> {
|
|
|
113
143
|
* The flag defaults to `true`, so `.hidden()` and `.hidden(true)` are the
|
|
114
144
|
* same thing. `.hidden(false)` leaves the field visible, which is what a
|
|
115
145
|
* schema is anyway - pass it when the decision comes from a variable.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* const schema = s.object({
|
|
149
|
+
* title: s.string(),
|
|
150
|
+
* internalNotes: s.string().hidden(),
|
|
151
|
+
* });
|
|
152
|
+
* export default c.define("/example.val.ts", schema, {
|
|
153
|
+
* title: "Hello",
|
|
154
|
+
* internalNotes: "Not shown in the editor",
|
|
155
|
+
* });
|
|
116
156
|
*/
|
|
117
157
|
abstract hidden(isHidden?: boolean): Schema<Src>;
|
|
118
158
|
protected abstract executeSerialize(): SerializedSchema;
|
|
@@ -42,7 +42,45 @@ export declare class KeyOfSchema<Sel extends GenericSelector<SourceObject>, Src
|
|
|
42
42
|
private readonly renderInput;
|
|
43
43
|
private readonly previewInput;
|
|
44
44
|
constructor(schema?: SerializedRefSchema | undefined, sourcePath?: SourcePath | undefined, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
45
|
+
/**
|
|
46
|
+
* Describe this field.
|
|
47
|
+
*
|
|
48
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
49
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
50
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
51
|
+
* assistant and the MCP tools read.
|
|
52
|
+
*
|
|
53
|
+
* Pass `null` to clear a description set earlier.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
57
|
+
* const schema = s.keyOf(authorsVal).describe("Who wrote this post");
|
|
58
|
+
* export default c.define("/example.val.ts", schema, "ada");
|
|
59
|
+
*/
|
|
45
60
|
describe(description: string | null): KeyOfSchema<Sel, 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
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
77
|
+
* const schema = s
|
|
78
|
+
* .keyOf(authorsVal)
|
|
79
|
+
* .validate((val) =>
|
|
80
|
+
* val === "placeholder" ? "Pick a real author" : false,
|
|
81
|
+
* );
|
|
82
|
+
* export default c.define("/example.val.ts", schema, "ada");
|
|
83
|
+
*/
|
|
46
84
|
validate(validationFunction: (src: Src) => false | string): KeyOfSchema<Sel, Src>;
|
|
47
85
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
48
86
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
@@ -56,12 +94,24 @@ export declare class KeyOfSchema<Sel extends GenericSelector<SourceObject>, Src
|
|
|
56
94
|
* instead of a preview row that navigates to it.
|
|
57
95
|
*
|
|
58
96
|
* Static configuration, not a callback — see `render.ts`.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
100
|
+
* const schema = s.array(s.keyOf(authorsVal).render({ as: "inline" }));
|
|
101
|
+
* export default c.define("/example.val.ts", schema, ["ada"]);
|
|
59
102
|
*/
|
|
60
103
|
render(input: FieldRender): KeyOfSchema<Sel, Src>;
|
|
61
104
|
/**
|
|
62
105
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
63
106
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
64
107
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* import authorsVal from "./authors.val"; // a record module
|
|
111
|
+
* const schema = s.array(
|
|
112
|
+
* s.keyOf(authorsVal).preview(({ val }) => ({ title: val })),
|
|
113
|
+
* );
|
|
114
|
+
* export default c.define("/example.val.ts", schema, ["ada"]);
|
|
65
115
|
*/
|
|
66
116
|
preview(select: ItemPreviewInput<Src>): KeyOfSchema<Sel, Src>;
|
|
67
117
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -26,7 +26,43 @@ export declare class LiteralSchema<Src extends string | null> extends Schema<Src
|
|
|
26
26
|
private readonly renderInput;
|
|
27
27
|
private readonly previewInput;
|
|
28
28
|
constructor(value: string, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
29
|
+
/**
|
|
30
|
+
* Describe this field.
|
|
31
|
+
*
|
|
32
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
33
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
34
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
35
|
+
* assistant and the MCP tools read.
|
|
36
|
+
*
|
|
37
|
+
* Pass `null` to clear a description set earlier.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const schema = s
|
|
41
|
+
* .literal("hero")
|
|
42
|
+
* .describe("The block type — it identifies the variant");
|
|
43
|
+
* export default c.define("/example.val.ts", schema, "hero");
|
|
44
|
+
*/
|
|
29
45
|
describe(description: string | null): LiteralSchema<Src>;
|
|
46
|
+
/**
|
|
47
|
+
* Add a custom validation rule to this field.
|
|
48
|
+
*
|
|
49
|
+
* The function is called with the field's value and returns `false` when the
|
|
50
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
51
|
+
* more than once to add more rules — they all run, and every message is
|
|
52
|
+
* reported.
|
|
53
|
+
*
|
|
54
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
55
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
56
|
+
*
|
|
57
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
58
|
+
* before a publish.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* const schema = s.literal("hero").validate((val) =>
|
|
62
|
+
* val === "hero" ? false : "Unknown block type",
|
|
63
|
+
* );
|
|
64
|
+
* export default c.define("/example.val.ts", schema, "hero");
|
|
65
|
+
*/
|
|
30
66
|
validate(validationFunction: (src: Src) => false | string): LiteralSchema<Src>;
|
|
31
67
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
32
68
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
@@ -40,12 +76,22 @@ export declare class LiteralSchema<Src extends string | null> extends Schema<Src
|
|
|
40
76
|
* instead of a preview row that navigates to it.
|
|
41
77
|
*
|
|
42
78
|
* Static configuration, not a callback — see `render.ts`.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* const schema = s.array(s.literal("hero").render({ as: "inline" }));
|
|
82
|
+
* export default c.define("/example.val.ts", schema, ["hero"]);
|
|
43
83
|
*/
|
|
44
84
|
render(input: FieldRender): LiteralSchema<Src>;
|
|
45
85
|
/**
|
|
46
86
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
47
87
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
48
88
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const schema = s.array(
|
|
92
|
+
* s.literal("hero").preview(({ val }) => ({ title: val })),
|
|
93
|
+
* );
|
|
94
|
+
* export default c.define("/example.val.ts", schema, ["hero"]);
|
|
49
95
|
*/
|
|
50
96
|
preview(select: ItemPreviewInput<Src>): LiteralSchema<Src>;
|
|
51
97
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -30,14 +30,62 @@ export declare class NumberSchema<Src extends number | null> extends Schema<Src>
|
|
|
30
30
|
private readonly renderInput;
|
|
31
31
|
private readonly previewInput;
|
|
32
32
|
constructor(options?: NumberOptions | undefined, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
33
|
+
/**
|
|
34
|
+
* Describe this field.
|
|
35
|
+
*
|
|
36
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
37
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
38
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
39
|
+
* assistant and the MCP tools read.
|
|
40
|
+
*
|
|
41
|
+
* Pass `null` to clear a description set earlier.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const schema = s.number().describe("How many columns the grid uses");
|
|
45
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
46
|
+
*/
|
|
33
47
|
describe(description: string | null): NumberSchema<Src>;
|
|
48
|
+
/**
|
|
49
|
+
* Add a custom validation rule to this field.
|
|
50
|
+
*
|
|
51
|
+
* The function is called with the field's value and returns `false` when the
|
|
52
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
53
|
+
* more than once to add more rules — they all run, and every message is
|
|
54
|
+
* reported.
|
|
55
|
+
*
|
|
56
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
57
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
58
|
+
*
|
|
59
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
60
|
+
* before a publish.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const schema = s.number().validate((val) =>
|
|
64
|
+
* Number.isInteger(val) ? false : "Must be a whole number",
|
|
65
|
+
* );
|
|
66
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
67
|
+
*/
|
|
34
68
|
validate(validationFunction: (src: Src) => false | string): NumberSchema<Src>;
|
|
35
69
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
36
70
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
37
71
|
nullable(): NumberSchema<Src | null>;
|
|
38
72
|
readonly(isReadonly?: boolean): NumberSchema<Src>;
|
|
39
73
|
hidden(isHidden?: boolean): NumberSchema<Src>;
|
|
74
|
+
/**
|
|
75
|
+
* Validate that the number is at most `max` (inclusive).
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* const schema = s.number().max(4);
|
|
79
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
80
|
+
*/
|
|
40
81
|
max(max: number): NumberSchema<Src>;
|
|
82
|
+
/**
|
|
83
|
+
* Validate that the number is at least `min` (inclusive).
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* const schema = s.number().min(1).max(4);
|
|
87
|
+
* export default c.define("/example.val.ts", schema, 3);
|
|
88
|
+
*/
|
|
41
89
|
min(min: number): NumberSchema<Src>;
|
|
42
90
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
43
91
|
/**
|
|
@@ -46,12 +94,22 @@ export declare class NumberSchema<Src extends number | null> extends Schema<Src>
|
|
|
46
94
|
* instead of a preview row that navigates to it.
|
|
47
95
|
*
|
|
48
96
|
* Static configuration, not a callback — see `render.ts`.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const schema = s.array(s.number().render({ as: "inline" }));
|
|
100
|
+
* export default c.define("/example.val.ts", schema, [1, 2]);
|
|
49
101
|
*/
|
|
50
102
|
render(input: FieldRender): NumberSchema<Src>;
|
|
51
103
|
/**
|
|
52
104
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
53
105
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
54
106
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const schema = s.array(
|
|
110
|
+
* s.number().preview(({ val }) => ({ title: String(val) })),
|
|
111
|
+
* );
|
|
112
|
+
* export default c.define("/example.val.ts", schema, [1, 2]);
|
|
55
113
|
*/
|
|
56
114
|
preview(select: ItemPreviewInput<Src>): NumberSchema<Src>;
|
|
57
115
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|