@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
|
@@ -108,7 +108,48 @@ RO extends boolean = false> extends Schema<Src> {
|
|
|
108
108
|
* sites.
|
|
109
109
|
*/
|
|
110
110
|
externalLabel?: string | null);
|
|
111
|
+
/**
|
|
112
|
+
* Describe this field.
|
|
113
|
+
*
|
|
114
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
115
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
116
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
117
|
+
* assistant and the MCP tools read.
|
|
118
|
+
*
|
|
119
|
+
* Pass `null` to clear a description set earlier.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* const schema = s
|
|
123
|
+
* .record(s.string())
|
|
124
|
+
* .describe("Button labels, keyed by locale");
|
|
125
|
+
* export default c.define("/example.val.ts", schema, { en: "Read more" });
|
|
126
|
+
*/
|
|
111
127
|
describe(description: string | null): RecordSchema<T, K, Src>;
|
|
128
|
+
/**
|
|
129
|
+
* Add a custom validation rule to this field.
|
|
130
|
+
*
|
|
131
|
+
* The function is called with the field's value and returns `false` when the
|
|
132
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
133
|
+
* more than once to add more rules — they all run, and every message is
|
|
134
|
+
* reported.
|
|
135
|
+
*
|
|
136
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
137
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
138
|
+
*
|
|
139
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
140
|
+
* before a publish.
|
|
141
|
+
*
|
|
142
|
+
* The function is given the whole record. To validate one entry, put a
|
|
143
|
+
* `.validate(...)` on the ITEM schema instead — that reports the error on
|
|
144
|
+
* the entry's own row, and on a `.jsonValues()` record it does not force
|
|
145
|
+
* every entry to be loaded.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* const schema = s.record(s.string()).validate((val) =>
|
|
149
|
+
* "en" in val ? false : "There has to be an 'en' entry",
|
|
150
|
+
* );
|
|
151
|
+
* export default c.define("/example.val.ts", schema, { en: "Read more" });
|
|
152
|
+
*/
|
|
112
153
|
validate(validationFunction: (src: Src) => false | string): RecordSchema<T, K, Src>;
|
|
113
154
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
114
155
|
private isRemoteUrl;
|
|
@@ -128,10 +169,55 @@ RO extends boolean = false> extends Schema<Src> {
|
|
|
128
169
|
* must come BEFORE `.external()`: afterwards the value is a `Schema`, and
|
|
129
170
|
* there is no `.readonly()` left to call — which is the error the compiler
|
|
130
171
|
* gives, and a clearer one than a runtime throw.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* const schema = s.record(s.string()).readonly();
|
|
175
|
+
* export default c.define("/example.val.ts", schema, { en: "Read more" });
|
|
131
176
|
*/
|
|
132
177
|
readonly<B extends boolean = true>(isReadonly?: B): RecordSchema<T, K, Src, B>;
|
|
133
178
|
hidden(isHidden?: boolean): RecordSchema<T, K, Src>;
|
|
179
|
+
/**
|
|
180
|
+
* Turn this record into a page router: its keys are route paths of your
|
|
181
|
+
* application, and they are validated against the router's conventions.
|
|
182
|
+
*
|
|
183
|
+
* `s.router(router, item)` builds the same thing in one call and is what
|
|
184
|
+
* most code should use — this is for adding a router to a record that
|
|
185
|
+
* already exists.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* import { nextAppRouter } from "../val.config";
|
|
189
|
+
* const schema = s
|
|
190
|
+
* .record(s.object({ title: s.string() }))
|
|
191
|
+
* .router(nextAppRouter);
|
|
192
|
+
* export default c.define("/app/[slug]/page.val.ts", schema, {
|
|
193
|
+
* "/a-page-slug": { title: "First Page" },
|
|
194
|
+
* });
|
|
195
|
+
*/
|
|
134
196
|
router(router: ValRouter): RecordSchema<T, K, Src>;
|
|
197
|
+
/**
|
|
198
|
+
* Allow the files in this gallery to be stored on Val's remote content host
|
|
199
|
+
* instead of in your repository.
|
|
200
|
+
*
|
|
201
|
+
* For `s.images()` and `s.files()`, which are records of media. Remote is off
|
|
202
|
+
* until this is called.
|
|
203
|
+
*
|
|
204
|
+
* Each entry is then keyed by its URL on the content host rather than by a
|
|
205
|
+
* path under `/public`. That key is not something to write by hand: upload
|
|
206
|
+
* in the Studio, or add a local path and let `npx val validate --fix`
|
|
207
|
+
* upload it and rewrite the key.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* const schema = s.images({ directory: "/public/val/images" }).remote();
|
|
211
|
+
* export default c.define("/content/images.val.ts", schema, {
|
|
212
|
+
* "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/images/hero.webp":
|
|
213
|
+
* {
|
|
214
|
+
* width: 1920,
|
|
215
|
+
* height: 1080,
|
|
216
|
+
* mimeType: "image/webp",
|
|
217
|
+
* alt: "Hero image",
|
|
218
|
+
* },
|
|
219
|
+
* });
|
|
220
|
+
*/
|
|
135
221
|
remote(): RecordSchema<T, K, Src>;
|
|
136
222
|
/**
|
|
137
223
|
* Store each entry's value in its own lazily-loaded `*.val.json` file instead
|
|
@@ -146,6 +232,20 @@ RO extends boolean = false> extends Schema<Src> {
|
|
|
146
232
|
* nested inside an object/array/record is rejected at startup with a module
|
|
147
233
|
* error, because the single-entry fetch endpoint, the Studio's content
|
|
148
234
|
* substitution and content validation are all root-only.
|
|
235
|
+
*
|
|
236
|
+
* Must come BEFORE `.validate()` and `.preview()`: those are typed against
|
|
237
|
+
* the un-lazy source shape, so a validator or preview declared first cannot
|
|
238
|
+
* be carried over, and declaring one first throws rather than silently
|
|
239
|
+
* dropping it.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* import { nextAppRouter } from "../val.config";
|
|
243
|
+
* const schema = s
|
|
244
|
+
* .router(nextAppRouter, s.object({ title: s.string(), body: s.string() }))
|
|
245
|
+
* .jsonValues();
|
|
246
|
+
* export default c.define("/app/support/[slug]/page.val.ts", schema, {
|
|
247
|
+
* "/support/faq": c.json(() => import("./content/faq.val.json")),
|
|
248
|
+
* });
|
|
149
249
|
*/
|
|
150
250
|
jsonValues(): RecordSchema<T, K, JsonValuesRecordSrc<T, K>>;
|
|
151
251
|
/**
|
|
@@ -166,6 +266,19 @@ RO extends boolean = false> extends Schema<Src> {
|
|
|
166
266
|
* nested external record would leave a hole in the middle of a module's
|
|
167
267
|
* source, and the Studio, patching and validation all assume a module's
|
|
168
268
|
* source is complete apart from its entries.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* const schema = s.record(s.object({ title: s.string() })).external("posts");
|
|
272
|
+
* export default c.define("/content/posts.val.ts", schema, c.external());
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* // A read-only external record: `.readonly()` must come FIRST, because
|
|
276
|
+
* // afterwards there is no `.readonly()` left on the type to call.
|
|
277
|
+
* const schema = s
|
|
278
|
+
* .record(s.object({ title: s.string() }))
|
|
279
|
+
* .readonly()
|
|
280
|
+
* .external("posts");
|
|
281
|
+
* export default c.define("/content/posts.val.ts", schema, c.external());
|
|
169
282
|
*/
|
|
170
283
|
external<L extends string>(label: L): RecordSchema<T, K, ExternalRecordSrc<SelectorOfSchema<T>, L, RO>, RO>;
|
|
171
284
|
/**
|
|
@@ -197,6 +310,25 @@ RO extends boolean = false> extends Schema<Src> {
|
|
|
197
310
|
* is the item of another container, in search, in references. What its
|
|
198
311
|
* entries show is the ITEM schema's `preview`, not this. Never how the field
|
|
199
312
|
* is edited (that is `render`). See `preview.ts`.
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* // The preview of the RECORD, for where it is an item of something else.
|
|
316
|
+
* // What its own rows show is the ITEM schema's preview — see below.
|
|
317
|
+
* const labels = s.record(s.string()).preview(({ val }) => ({
|
|
318
|
+
* title: `${Object.keys(val).length} locales`,
|
|
319
|
+
* }));
|
|
320
|
+
* export default c.define("/example.val.ts", s.array(labels), [
|
|
321
|
+
* { en: "Read more" },
|
|
322
|
+
* ]);
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* // Rows of a record come from the ITEM's preview, not the record's:
|
|
326
|
+
* const author = s
|
|
327
|
+
* .object({ name: s.string(), role: s.string() })
|
|
328
|
+
* .preview(({ val }) => ({ title: val.name, subtitle: val.role }));
|
|
329
|
+
* export default c.define("/example.val.ts", s.record(author), {
|
|
330
|
+
* ada: { name: "Ada", role: "Engineer" },
|
|
331
|
+
* });
|
|
200
332
|
*/
|
|
201
333
|
preview(select: ItemPreviewInput<Src>): RecordSchema<T, K, Src>;
|
|
202
334
|
/**
|
|
@@ -205,6 +337,10 @@ RO extends boolean = false> extends Schema<Src> {
|
|
|
205
337
|
* instead of a preview row that navigates to it.
|
|
206
338
|
*
|
|
207
339
|
* Static configuration, not a callback — see `render.ts`.
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* const schema = s.array(s.record(s.string()).render({ as: "inline" }));
|
|
343
|
+
* export default c.define("/example.val.ts", schema, [{ en: "Read more" }]);
|
|
208
344
|
*/
|
|
209
345
|
render(input: FieldRender): RecordSchema<T, K, Src>;
|
|
210
346
|
}
|
|
@@ -31,9 +31,71 @@ export declare class RichTextSchema<O extends RichTextOptions, Src extends RichT
|
|
|
31
31
|
private readonly renderInput;
|
|
32
32
|
private readonly previewInput;
|
|
33
33
|
constructor(options: O & ValidationOptions, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
34
|
+
/**
|
|
35
|
+
* Describe this field.
|
|
36
|
+
*
|
|
37
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
38
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
39
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
40
|
+
* assistant and the MCP tools read.
|
|
41
|
+
*
|
|
42
|
+
* Pass `null` to clear a description set earlier.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const schema = s.richtext().describe("The body of the article");
|
|
46
|
+
* export default c.define("/example.val.ts", schema, [
|
|
47
|
+
* { tag: "p", children: ["Hello"] },
|
|
48
|
+
* ]);
|
|
49
|
+
*/
|
|
34
50
|
describe(description: string | null): RichTextSchema<O, Src>;
|
|
51
|
+
/**
|
|
52
|
+
* Validate that the rich text holds at most `max` characters.
|
|
53
|
+
*
|
|
54
|
+
* Counted over the TEXT, not the markup: tags, attributes and the structure
|
|
55
|
+
* of the document do not add to it.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const schema = s.richtext().maxLength(280);
|
|
59
|
+
* export default c.define("/example.val.ts", schema, [
|
|
60
|
+
* { tag: "p", children: ["Hello"] },
|
|
61
|
+
* ]);
|
|
62
|
+
*/
|
|
35
63
|
maxLength(max: number): RichTextSchema<O, Src>;
|
|
64
|
+
/**
|
|
65
|
+
* Validate that the rich text holds at least `min` characters.
|
|
66
|
+
*
|
|
67
|
+
* Counted over the TEXT, not the markup: tags, attributes and the structure
|
|
68
|
+
* of the document do not add to it.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* const schema = s.richtext().minLength(20).maxLength(280);
|
|
72
|
+
* export default c.define("/example.val.ts", schema, [
|
|
73
|
+
* { tag: "p", children: ["Long enough to clear the minimum length."] },
|
|
74
|
+
* ]);
|
|
75
|
+
*/
|
|
36
76
|
minLength(min: number): RichTextSchema<O, Src>;
|
|
77
|
+
/**
|
|
78
|
+
* Add a custom validation rule to this field.
|
|
79
|
+
*
|
|
80
|
+
* The function is called with the field's value and returns `false` when the
|
|
81
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
82
|
+
* more than once to add more rules — they all run, and every message is
|
|
83
|
+
* reported.
|
|
84
|
+
*
|
|
85
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
86
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
87
|
+
*
|
|
88
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
89
|
+
* before a publish.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* const schema = s.richtext().validate((val) =>
|
|
93
|
+
* val.length > 0 ? false : "Write something",
|
|
94
|
+
* );
|
|
95
|
+
* export default c.define("/example.val.ts", schema, [
|
|
96
|
+
* { tag: "p", children: ["Hello"] },
|
|
97
|
+
* ]);
|
|
98
|
+
*/
|
|
37
99
|
validate(validationFunction: (src: Src) => false | string): RichTextSchema<O, Src>;
|
|
38
100
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
39
101
|
private internalValidate;
|
|
@@ -49,12 +111,28 @@ export declare class RichTextSchema<O extends RichTextOptions, Src extends RichT
|
|
|
49
111
|
* instead of a preview row that navigates to it.
|
|
50
112
|
*
|
|
51
113
|
* Static configuration, not a callback — see `render.ts`.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* const schema = s.array(s.richtext().render({ as: "inline" }));
|
|
117
|
+
* export default c.define("/example.val.ts", schema, [
|
|
118
|
+
* [{ tag: "p", children: ["Hello"] }],
|
|
119
|
+
* ]);
|
|
52
120
|
*/
|
|
53
121
|
render(input: FieldRender): RichTextSchema<O, Src>;
|
|
54
122
|
/**
|
|
55
123
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
56
124
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
57
125
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* const schema = s.array(
|
|
129
|
+
* s.richtext().preview(({ val }) => ({
|
|
130
|
+
* title: val.length > 0 ? "Rich text" : "Empty",
|
|
131
|
+
* })),
|
|
132
|
+
* );
|
|
133
|
+
* export default c.define("/example.val.ts", schema, [
|
|
134
|
+
* [{ tag: "p", children: ["Hello"] }],
|
|
135
|
+
* ]);
|
|
58
136
|
*/
|
|
59
137
|
preview(select: ItemPreviewInput<Src>): RichTextSchema<O, Src>;
|
|
60
138
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -40,6 +40,20 @@ export declare class RouteSchema<Src extends string | null> extends Schema<Src>
|
|
|
40
40
|
private readonly renderInput;
|
|
41
41
|
private readonly previewInput;
|
|
42
42
|
constructor(options?: RouteOptions | undefined, opt?: boolean, customValidateFunctions?: ((src: Src) => false | string)[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
43
|
+
/**
|
|
44
|
+
* Describe this field.
|
|
45
|
+
*
|
|
46
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
47
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
48
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
49
|
+
* assistant and the MCP tools read.
|
|
50
|
+
*
|
|
51
|
+
* Pass `null` to clear a description set earlier.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* const schema = s.route().describe("Where the button goes");
|
|
55
|
+
* export default c.define("/example.val.ts", schema, "/a-page-slug");
|
|
56
|
+
*/
|
|
43
57
|
describe(description: string | null): RouteSchema<Src>;
|
|
44
58
|
/**
|
|
45
59
|
* Specify a pattern for which routes are allowed.
|
|
@@ -67,6 +81,26 @@ export declare class RouteSchema<Src extends string | null> extends Schema<Src>
|
|
|
67
81
|
* s.route().include(/^\/api\//).exclude(/^\/api\/internal\//) // API routes except internal
|
|
68
82
|
*/
|
|
69
83
|
exclude(pattern: RegExp): RouteSchema<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
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
93
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
94
|
+
*
|
|
95
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
96
|
+
* before a publish.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const schema = s.route().validate((val) =>
|
|
100
|
+
* val.endsWith("/") ? "Leave off the trailing slash" : false,
|
|
101
|
+
* );
|
|
102
|
+
* export default c.define("/example.val.ts", schema, "/a-page-slug");
|
|
103
|
+
*/
|
|
70
104
|
validate(validationFunction: (src: Src) => false | string): RouteSchema<Src>;
|
|
71
105
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
72
106
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
@@ -80,12 +114,22 @@ export declare class RouteSchema<Src extends string | null> extends Schema<Src>
|
|
|
80
114
|
* instead of a preview row that navigates to it.
|
|
81
115
|
*
|
|
82
116
|
* Static configuration, not a callback — see `render.ts`.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* const schema = s.array(s.route().render({ as: "inline" }));
|
|
120
|
+
* export default c.define("/example.val.ts", schema, ["/a-page-slug"]);
|
|
83
121
|
*/
|
|
84
122
|
render(input: FieldRender): RouteSchema<Src>;
|
|
85
123
|
/**
|
|
86
124
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
87
125
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
88
126
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const schema = s.array(
|
|
130
|
+
* s.route().preview(({ val }) => ({ title: val })),
|
|
131
|
+
* );
|
|
132
|
+
* export default c.define("/example.val.ts", schema, ["/a-page-slug"]);
|
|
89
133
|
*/
|
|
90
134
|
preview(select: ItemPreviewInput<Src>): RouteSchema<Src>;
|
|
91
135
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -66,24 +66,113 @@ export declare class StringSchema<Src extends string | null> extends Schema<Src>
|
|
|
66
66
|
private readonly previewInput;
|
|
67
67
|
private readonly isMultiline;
|
|
68
68
|
constructor(options?: StringOptions | undefined, opt?: boolean, isRaw?: boolean, customValidateFunctions?: ((src: Src) => false | string)[], renderInput?: FieldRender | null, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, previewInput?: ItemPreviewInput<Src> | null, isMultiline?: boolean);
|
|
69
|
+
/**
|
|
70
|
+
* Describe this field.
|
|
71
|
+
*
|
|
72
|
+
* The description is shown next to the field's label in the Val editor, so
|
|
73
|
+
* it is where you say what an editor needs to know but the field name cannot
|
|
74
|
+
* carry. It also travels in the serialized schema, which is what the AI
|
|
75
|
+
* assistant and the MCP tools read.
|
|
76
|
+
*
|
|
77
|
+
* Pass `null` to clear a description set earlier.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* const schema = s
|
|
81
|
+
* .string()
|
|
82
|
+
* .describe("Shown in the browser tab and in search results");
|
|
83
|
+
* export default c.define("/example.val.ts", schema, "Hello");
|
|
84
|
+
*/
|
|
69
85
|
describe(description: string | null): StringSchema<Src>;
|
|
70
86
|
/**
|
|
71
87
|
* @deprecated Use `minLength` instead
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const schema = s.string().minLength(2);
|
|
91
|
+
* export default c.define("/example.val.ts", schema, "Hi");
|
|
72
92
|
*/
|
|
73
93
|
min(minLength: number): StringSchema<Src>;
|
|
94
|
+
/**
|
|
95
|
+
* Validate that the string is at least `minLength` characters long.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* const schema = s.string().minLength(2);
|
|
99
|
+
* export default c.define("/example.val.ts", schema, "Hi");
|
|
100
|
+
*/
|
|
74
101
|
minLength(minLength: number): StringSchema<Src>;
|
|
75
102
|
/**
|
|
76
103
|
* @deprecated Use `maxLength` instead
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* const schema = s.string().maxLength(60);
|
|
107
|
+
* export default c.define("/example.val.ts", schema, "A title that fits");
|
|
77
108
|
*/
|
|
78
109
|
max(maxLength: number): StringSchema<Src>;
|
|
110
|
+
/**
|
|
111
|
+
* Validate that the string is at most `maxLength` characters long.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* const schema = s.string().maxLength(60);
|
|
115
|
+
* export default c.define("/example.val.ts", schema, "A title that fits");
|
|
116
|
+
*/
|
|
79
117
|
maxLength(maxLength: number): StringSchema<Src>;
|
|
118
|
+
/**
|
|
119
|
+
* Validate that the string matches `regexp`.
|
|
120
|
+
*
|
|
121
|
+
* `message` is what the editor is shown when it does not match. Without one
|
|
122
|
+
* the error names the pattern, which is rarely what a non-developer needs.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* const schema = s
|
|
126
|
+
* .string()
|
|
127
|
+
* .regexp(/^[a-z0-9-]+$/, "Lower case letters, digits and dashes only");
|
|
128
|
+
* export default c.define("/example.val.ts", schema, "my-slug");
|
|
129
|
+
*/
|
|
80
130
|
regexp(regexp: RegExp, message?: string): StringSchema<Src>;
|
|
131
|
+
/**
|
|
132
|
+
* Add a custom validation rule to this field.
|
|
133
|
+
*
|
|
134
|
+
* The function is called with the field's value and returns `false` when the
|
|
135
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
136
|
+
* more than once to add more rules — they all run, and every message is
|
|
137
|
+
* reported.
|
|
138
|
+
*
|
|
139
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
140
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
141
|
+
*
|
|
142
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
143
|
+
* before a publish.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const schema = s.string().validate((val) =>
|
|
147
|
+
* val.trim() === val ? false : "Must not start or end with a space",
|
|
148
|
+
* );
|
|
149
|
+
* export default c.define("/example.val.ts", schema, "Hello");
|
|
150
|
+
*/
|
|
81
151
|
validate(validationFunction: (src: Src) => false | string): StringSchema<Src>;
|
|
82
152
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
83
153
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
84
154
|
nullable(): StringSchema<Src | null>;
|
|
85
155
|
readonly(isReadonly?: boolean): StringSchema<Src>;
|
|
86
156
|
hidden(isHidden?: boolean): StringSchema<Src>;
|
|
157
|
+
/**
|
|
158
|
+
* Do not stega encode this string.
|
|
159
|
+
*
|
|
160
|
+
* Val normally encodes an invisible pointer back to the source into every
|
|
161
|
+
* string it hands your app, which is what makes click-to-edit work. A raw
|
|
162
|
+
* string is handed over exactly as written — use it wherever the value is
|
|
163
|
+
* not rendered as visible text: a slug, a class name, an `id`, a URL,
|
|
164
|
+
* anything parsed or compared.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* const schema = s.object({
|
|
168
|
+
* title: s.string(),
|
|
169
|
+
* slug: s.string().raw(),
|
|
170
|
+
* });
|
|
171
|
+
* export default c.define("/example.val.ts", schema, {
|
|
172
|
+
* title: "Hello",
|
|
173
|
+
* slug: "hello",
|
|
174
|
+
* });
|
|
175
|
+
*/
|
|
87
176
|
raw(): StringSchema<Src extends null ? RawString | null : RawString>;
|
|
88
177
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
89
178
|
protected executeSerialize(): SerializedSchema;
|
|
@@ -107,12 +196,22 @@ export declare class StringSchema<Src extends string | null> extends Schema<Src>
|
|
|
107
196
|
*
|
|
108
197
|
* Static configuration, not a callback — see `render.ts`. What a CONTAINER
|
|
109
198
|
* shows for its items is a `preview`, which is a different thing entirely.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* const schema = s.array(s.string().render({ as: "inline" }));
|
|
202
|
+
* export default c.define("/example.val.ts", schema, ["First", "Second"]);
|
|
110
203
|
*/
|
|
111
204
|
render(input: FieldRender): StringSchema<Src>;
|
|
112
205
|
/**
|
|
113
206
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
114
207
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
115
208
|
* itself is edited (that is `render`). See `preview.ts`.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* const schema = s.array(
|
|
212
|
+
* s.string().preview(({ val }) => ({ title: val })),
|
|
213
|
+
* );
|
|
214
|
+
* export default c.define("/example.val.ts", schema, ["First", "Second"]);
|
|
116
215
|
*/
|
|
117
216
|
preview(select: ItemPreviewInput<Src>): StringSchema<Src>;
|
|
118
217
|
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
@@ -1,93 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ItemPreviewInput, PreviewItem, ReifiedPreview, PreviewScope } from "../preview.js";
|
|
3
|
-
import { FieldRender } from "../render.js";
|
|
1
|
+
import { Schema } from "./index.js";
|
|
4
2
|
import { SelectorSource } from "../selector/index.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
nullable(): UnionSchema<Key, T, Src | null>;
|
|
59
|
-
readonly(isReadonly?: boolean): UnionSchema<Key, T, Src>;
|
|
60
|
-
hidden(isHidden?: boolean): UnionSchema<Key, T, Src>;
|
|
61
|
-
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
62
|
-
/**
|
|
63
|
-
* The variant schema a value takes, for a TAGGED union (string `key`). `null`
|
|
64
|
-
* for a literal union (its variants are leaves with nothing to descend into) or
|
|
65
|
-
* when the value matches none of them — a structural error `executeValidate`
|
|
66
|
-
* already reports.
|
|
67
|
-
*/
|
|
68
|
-
private matchedVariant;
|
|
69
|
-
/**
|
|
70
|
-
* How this field is laid out in the editor when it is the item of an array
|
|
71
|
-
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
72
|
-
* instead of a preview row that navigates to it.
|
|
73
|
-
*
|
|
74
|
-
* Static configuration, not a callback — see `render.ts`.
|
|
75
|
-
*/
|
|
76
|
-
render(input: FieldRender): UnionSchema<Key, T, Src>;
|
|
77
|
-
/**
|
|
78
|
-
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
79
|
-
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
80
|
-
* itself is edited (that is `render`). See `preview.ts`.
|
|
81
|
-
*
|
|
82
|
-
* Without one of its own, a tagged union previews as the VARIANT the value
|
|
83
|
-
* takes — declare `preview` on the member objects and the union dispatches.
|
|
84
|
-
*/
|
|
85
|
-
preview(select: ItemPreviewInput<Src>): UnionSchema<Key, T, Src>;
|
|
86
|
-
protected executePreviewItem(src: NonNullable<Src>): PreviewItem | null;
|
|
87
|
-
protected declaresItemPreview(): boolean;
|
|
88
|
-
protected executeSerialize(): SerializedSchema;
|
|
89
|
-
constructor(key: Key, items: T, opt?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, renderInput?: FieldRender | null, previewInput?: ItemPreviewInput<Src> | null);
|
|
90
|
-
protected executePreview(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: PreviewScope): ReifiedPreview;
|
|
91
|
-
}
|
|
92
|
-
export declare const union: <Key extends string | Schema<string>, T extends Schema<Key extends string ? SourceObject & { [k in Key]: string; } : Key extends Schema<string> ? string : unknown>[]>(key: Key, ...objects: T) => UnionSchema<Key, T, SourceOf<Key, T>>;
|
|
3
|
+
import { DiscriminatedUnionItems, DiscriminatedUnionSchema, DiscriminatedUnionSourceOf, SerializedDiscriminatedUnionSchema } from "./discriminatedUnion.js";
|
|
4
|
+
import { EnumSchema, SerializedEnumSchema } from "./enum.js";
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated Use {@link SerializedDiscriminatedUnionSchema} or
|
|
7
|
+
* {@link SerializedEnumSchema}. A serialized union is now one or the other,
|
|
8
|
+
* distinguished by `type` rather than by the shape of `key`.
|
|
9
|
+
*/
|
|
10
|
+
export type SerializedUnionSchema = SerializedDiscriminatedUnionSchema | SerializedEnumSchema;
|
|
11
|
+
/** @deprecated Use {@link SerializedEnumSchema}. */
|
|
12
|
+
export type SerializedStringUnionSchema = SerializedEnumSchema;
|
|
13
|
+
/** @deprecated Use {@link SerializedDiscriminatedUnionSchema}. */
|
|
14
|
+
export type SerializedObjectUnionSchema = SerializedDiscriminatedUnionSchema;
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated There is no single union schema class any more: name
|
|
17
|
+
* {@link DiscriminatedUnionSchema} or {@link EnumSchema}. The type parameters
|
|
18
|
+
* are kept so existing annotations still compile, but only `Src` is used.
|
|
19
|
+
*/
|
|
20
|
+
export type UnionSchema<_Key = unknown, _T = unknown, Src extends SelectorSource = SelectorSource> = Schema<Src>;
|
|
21
|
+
/**
|
|
22
|
+
* The value type of a list of literal schemas — how `s.union` typed a union of
|
|
23
|
+
* literals. Inferred from `Schema<infer S>` rather than `LiteralSchema<infer S>`
|
|
24
|
+
* because a `LiteralSchema` is invariant in its source (its custom validate
|
|
25
|
+
* functions put it in a parameter position), so `LiteralSchema<"a">` is not
|
|
26
|
+
* assignable to `LiteralSchema<"a" | "b">`.
|
|
27
|
+
*/
|
|
28
|
+
type EnumSourceOf<T extends Schema<string>[]> = T extends Schema<infer S>[] ? S extends string ? S : never : never;
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated Use `s.discriminatedUnion(key, ...objects)` for a tagged union of
|
|
31
|
+
* objects, or `s.enum("a", "b")` for one of a fixed set of strings.
|
|
32
|
+
*
|
|
33
|
+
* One thing does NOT survive the literal form: an enum's values are strings,
|
|
34
|
+
* so a member literal's own `.validate()` and `.describe()` are dropped rather
|
|
35
|
+
* than carried over. `s.union(s.literal("a").validate(...), ...)` ran that
|
|
36
|
+
* validator as part of deciding whether the value matched; `s.enum` has no
|
|
37
|
+
* member to run. A validator on a single-valued literal could only accept or
|
|
38
|
+
* reject that one value, which the enum's own value list already decides — but
|
|
39
|
+
* if you rely on one, keep it by validating the enum itself.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // was: s.union("type", s.object({ type: s.literal("a"), a: s.string() }))
|
|
43
|
+
* const schema = s.discriminatedUnion(
|
|
44
|
+
* "type",
|
|
45
|
+
* s.object({ type: s.literal("a"), a: s.string() }),
|
|
46
|
+
* );
|
|
47
|
+
* export default c.define("/example.val.ts", schema, { type: "a", a: "one" });
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // was: s.union(s.literal("a"), s.literal("b"))
|
|
51
|
+
* const schema = s.enum("a", "b");
|
|
52
|
+
* export default c.define("/example.val.ts", schema, "a");
|
|
53
|
+
*/
|
|
54
|
+
export declare function union<Key extends string, T extends DiscriminatedUnionItems<Key>>(key: Key, ...objects: T): DiscriminatedUnionSchema<Key, T, DiscriminatedUnionSourceOf<Key, T>>;
|
|
55
|
+
export declare function union<T extends Schema<string>[]>(...literals: T): EnumSchema<EnumSourceOf<T>>;
|
|
93
56
|
export {};
|