@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.
Files changed (35) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/dist/declarations/src/index.d.ts +3 -1
  3. package/dist/declarations/src/initSchema.d.ts +46 -15
  4. package/dist/declarations/src/initVal.d.ts +108 -0
  5. package/dist/declarations/src/render.d.ts +5 -4
  6. package/dist/declarations/src/schema/array.d.ts +65 -0
  7. package/dist/declarations/src/schema/boolean.d.ts +44 -0
  8. package/dist/declarations/src/schema/code.d.ts +63 -0
  9. package/dist/declarations/src/schema/color.d.ts +54 -0
  10. package/dist/declarations/src/schema/date.d.ts +64 -2
  11. package/dist/declarations/src/schema/datetime.d.ts +87 -2
  12. package/dist/declarations/src/schema/discriminatedUnion.d.ts +166 -0
  13. package/dist/declarations/src/schema/enum.d.ts +122 -0
  14. package/dist/declarations/src/schema/file.d.ts +77 -0
  15. package/dist/declarations/src/schema/image.d.ts +102 -0
  16. package/dist/declarations/src/schema/index.d.ts +42 -2
  17. package/dist/declarations/src/schema/keyOf.d.ts +50 -0
  18. package/dist/declarations/src/schema/literal.d.ts +46 -0
  19. package/dist/declarations/src/schema/number.d.ts +58 -0
  20. package/dist/declarations/src/schema/object.d.ts +63 -0
  21. package/dist/declarations/src/schema/record.d.ts +136 -0
  22. package/dist/declarations/src/schema/richtext.d.ts +78 -0
  23. package/dist/declarations/src/schema/route.d.ts +44 -0
  24. package/dist/declarations/src/schema/string.d.ts +99 -0
  25. package/dist/declarations/src/schema/union.d.ts +54 -91
  26. package/dist/{index-a3846321.cjs.prod.js → index-6db78f3c.cjs.prod.js} +1953 -449
  27. package/dist/{index-daa122af.cjs.dev.js → index-b41b638f.cjs.dev.js} +1953 -449
  28. package/dist/{index-915dd675.esm.js → index-cd25c2dc.esm.js} +1952 -449
  29. package/dist/valbuild-core.cjs.dev.js +3 -2
  30. package/dist/valbuild-core.cjs.prod.js +3 -2
  31. package/dist/valbuild-core.esm.js +1 -1
  32. package/package.json +1 -1
  33. package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
  34. package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
  35. package/patch/dist/valbuild-core-patch.esm.js +2 -2
@@ -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 { SerializedUnionSchema } from "./union.js";
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 | SerializedUnionSchema | SerializedRichTextSchema | SerializedRecordSchema | SerializedKeyOfSchema | SerializedFileSchema | SerializedDateSchema | SerializedDateTimeSchema | SerializedColorSchema | SerializedCodeSchema | SerializedRouteSchema | SerializedSettingsSchema | SerializedImageSchema;
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;
@@ -50,7 +50,52 @@ export declare class ObjectSchema<Props extends ObjectSchemaProps, Src extends O
50
50
  private readonly renderInput;
51
51
  private readonly previewInput;
52
52
  constructor(items: Props, 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
65
+ * .object({ street: s.string(), city: s.string() })
66
+ * .describe("Where the office is — shown on the contact page");
67
+ * export default c.define("/example.val.ts", schema, {
68
+ * street: "Torggata 1",
69
+ * city: "Oslo",
70
+ * });
71
+ */
53
72
  describe(description: string | null): ObjectSchema<Props, Src>;
73
+ /**
74
+ * Add a custom validation rule to this field.
75
+ *
76
+ * The function is called with the field's value and returns `false` when the
77
+ * value is fine, or a STRING with the message to show when it is not. Call it
78
+ * more than once to add more rules — they all run, and every message is
79
+ * reported.
80
+ *
81
+ * Write the check as a ternary, not as `ok || "message"`: that returns `true`
82
+ * when the value is fine, and `true` is not one of the two answers.
83
+ *
84
+ * Validation runs in the Studio as you type, in `npx val validate` and
85
+ * before a publish.
86
+ *
87
+ * An object validator is the place for a rule that spans FIELDS — one field
88
+ * validated on its own belongs on that field's schema, where the error lands
89
+ * on the field itself.
90
+ *
91
+ * @example
92
+ * const schema = s
93
+ * .object({ from: s.number(), to: s.number() })
94
+ * .validate((val) =>
95
+ * val.from <= val.to ? false : "'from' must not be after 'to'",
96
+ * );
97
+ * export default c.define("/example.val.ts", schema, { from: 1, to: 4 });
98
+ */
54
99
  validate(validationFunction: (src: Src) => false | string): ObjectSchema<Props, Src>;
55
100
  protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
56
101
  protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
@@ -64,12 +109,30 @@ export declare class ObjectSchema<Props extends ObjectSchemaProps, Src extends O
64
109
  * instead of a preview row that navigates to it.
65
110
  *
66
111
  * Static configuration, not a callback — see `render.ts`.
112
+ *
113
+ * @example
114
+ * // A page builder: each row edits the object in place, instead of
115
+ * // navigating to it.
116
+ * const block = s
117
+ * .object({ heading: s.string(), body: s.string() })
118
+ * .render({ as: "inline" });
119
+ * export default c.define("/example.val.ts", s.array(block), [
120
+ * { heading: "Hello", body: "World" },
121
+ * ]);
67
122
  */
68
123
  render(input: FieldRender): ObjectSchema<Props, Src>;
69
124
  /**
70
125
  * How this VALUE is shown where a preview of it is needed — a row in a
71
126
  * sortable list, a reference dropdown, a search hit. Never how the field
72
127
  * itself is edited (that is `render`). See `preview.ts`.
128
+ *
129
+ * @example
130
+ * const author = s
131
+ * .object({ name: s.string(), role: s.string() })
132
+ * .preview(({ val }) => ({ title: val.name, subtitle: val.role }));
133
+ * export default c.define("/example.val.ts", s.array(author), [
134
+ * { name: "Ada", role: "Engineer" },
135
+ * ]);
73
136
  */
74
137
  preview(select: ItemPreviewInput<Src>): ObjectSchema<Props, Src>;
75
138
  protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;