@valbuild/core 0.117.0 → 0.121.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 +135 -0
- package/dist/declarations/src/index.d.ts +3 -0
- package/dist/declarations/src/initSchema.d.ts +27 -0
- package/dist/declarations/src/initVal.d.ts +11 -8
- package/dist/declarations/src/schema/array.d.ts +2 -2
- package/dist/declarations/src/schema/boolean.d.ts +2 -2
- package/dist/declarations/src/schema/code.d.ts +2 -2
- package/dist/declarations/src/schema/color.d.ts +2 -2
- package/dist/declarations/src/schema/date.d.ts +2 -2
- package/dist/declarations/src/schema/datetime.d.ts +2 -2
- package/dist/declarations/src/schema/file.d.ts +2 -2
- package/dist/declarations/src/schema/image.d.ts +2 -2
- package/dist/declarations/src/schema/index.d.ts +12 -3
- package/dist/declarations/src/schema/keyOf.d.ts +2 -2
- package/dist/declarations/src/schema/literal.d.ts +2 -2
- package/dist/declarations/src/schema/number.d.ts +2 -2
- package/dist/declarations/src/schema/object.d.ts +2 -2
- package/dist/declarations/src/schema/record.d.ts +2 -2
- package/dist/declarations/src/schema/richtext.d.ts +3 -3
- package/dist/declarations/src/schema/route.d.ts +2 -2
- package/dist/declarations/src/schema/settings.d.ts +102 -0
- package/dist/declarations/src/schema/string.d.ts +2 -2
- package/dist/declarations/src/schema/union.d.ts +2 -2
- package/dist/declarations/src/selector/index.d.ts +3 -2
- package/dist/declarations/src/settingsModule.d.ts +60 -0
- package/dist/declarations/src/source/index.d.ts +2 -1
- package/dist/declarations/src/source/richtext.d.ts +57 -67
- package/dist/declarations/src/source/settings.d.ts +94 -0
- package/dist/{index-b8004eea.esm.js → index-5fe6fb98.esm.js} +767 -266
- package/dist/{index-941877c6.cjs.prod.js → index-61237991.cjs.prod.js} +772 -265
- package/dist/{index-0ba5047e.cjs.dev.js → index-9860179f.cjs.dev.js} +772 -265
- package/dist/valbuild-core.cjs.dev.js +7 -1
- package/dist/valbuild-core.cjs.prod.js +7 -1
- 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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,140 @@
|
|
|
1
1
|
# @valbuild/core
|
|
2
2
|
|
|
3
|
+
## 0.121.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#605](https://github.com/valbuild/val/pull/605) [`6794d29`](https://github.com/valbuild/val/commit/6794d2980bc81284ab7f2cc667f01cc21c9e3a79) Thanks [@freekh](https://github.com/freekh)! - `s.settings()`: the project's settings, as content.
|
|
8
|
+
|
|
9
|
+
A settings module is one per project, at the root of the content tree:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// settings.val.ts
|
|
13
|
+
export default c.define("/settings.val.ts", s.settings(), {});
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Register it in `val.modules.ts` like any other module, and it shows up in the
|
|
17
|
+
Studio under the cog at the foot of the left rail. Everything in it is content:
|
|
18
|
+
it is edited as a draft, it appears in the publish diff, and it is the same for
|
|
19
|
+
everyone working on the project.
|
|
20
|
+
|
|
21
|
+
Every key is optional, at every level, so `{}` is a complete settings module —
|
|
22
|
+
and stays one as sections are added. What it holds today is the assistant:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
export default c.define("/settings.val.ts", s.settings(), {
|
|
26
|
+
assistant: {
|
|
27
|
+
enabled: true,
|
|
28
|
+
context: "A CMS for developers, run by a team of four in Oslo.",
|
|
29
|
+
tone: "Plain and direct. British English, sentence case in headings.",
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`context` is background the assistant would otherwise guess at; `tone` is how it
|
|
35
|
+
should write when it writes content. Both are sent with every message it makes.
|
|
36
|
+
|
|
37
|
+
`enabled` decides whether editors have an assistant, and it has **three** states
|
|
38
|
+
rather than two:
|
|
39
|
+
|
|
40
|
+
- `true` — they do.
|
|
41
|
+
- `false` — they do not, and every trace of it goes: no button in the top bar,
|
|
42
|
+
no row in the quick actions, no panel, nothing sent.
|
|
43
|
+
- unset — nobody has decided. The assistant is still **shown**, and asks to be
|
|
44
|
+
turned on before it is used. Hiding an assistant nobody has decided about
|
|
45
|
+
means nobody discovers it; quietly enabling one means a project starts sending
|
|
46
|
+
its content to a model because it did not know to say no.
|
|
47
|
+
|
|
48
|
+
A project with no settings module at all has an assistant, as before: there is
|
|
49
|
+
nowhere to record a decision, and nowhere for the prompt to write the answer.
|
|
50
|
+
|
|
51
|
+
**Breaking: `ai.chat` is gone from `val.config.ts`.** Whether the assistant is
|
|
52
|
+
available is a decision about the project's content, made by the people who edit
|
|
53
|
+
it, so it moved to settings — turning the chat on used to take a developer, a
|
|
54
|
+
deploy and a code review of a boolean. Remove the whole block:
|
|
55
|
+
|
|
56
|
+
```diff
|
|
57
|
+
const { s, c, val, config } = initVal({
|
|
58
|
+
- ai: {
|
|
59
|
+
- chat: {
|
|
60
|
+
- experimental: { enable: true },
|
|
61
|
+
- suggestions: ["Summarize", "Fix typos at this page"],
|
|
62
|
+
- title: "Ask me anything",
|
|
63
|
+
- description: "Val can answer questions about the content.",
|
|
64
|
+
- },
|
|
65
|
+
- },
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`experimental.enable` becomes `assistant.enabled` in the settings module.
|
|
70
|
+
`suggestions`, `title` and `description` are removed with nothing replacing
|
|
71
|
+
them: the assistant now opens with its own copy. A project that had the chat
|
|
72
|
+
enabled and wants it to stay on for everyone should write
|
|
73
|
+
`assistant: { enabled: true }` — otherwise editors are offered it and asked.
|
|
74
|
+
|
|
75
|
+
`ai.commitMessages` stays in `val.config.ts`, and is unaffected.
|
|
76
|
+
|
|
77
|
+
Two settings modules, or one in a subdirectory, is a module error: the dev
|
|
78
|
+
server refuses to serve sources, `npx val validate` reports it against the file,
|
|
79
|
+
and the Studio says so rather than picking one.
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- [#607](https://github.com/valbuild/val/pull/607) [`2bcbee1`](https://github.com/valbuild/val/commit/2bcbee1be682c2bbd5b7bc7d152ddd4204162fd2) Thanks [@freekh](https://github.com/freekh)! - `.readonly()` and `.hidden()` now take the flag as an argument, so a schema can
|
|
84
|
+
decide these from a variable instead of only from whether the call was written at
|
|
85
|
+
all:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
s.string().readonly(!canEdit);
|
|
89
|
+
s.image().hidden(hideMedia);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The argument defaults to `true`, so `.readonly()` and `.readonly(true)` are the
|
|
93
|
+
same thing and nothing about existing schemas changes. Passing `false` leaves the
|
|
94
|
+
field editable or visible, which is also what a schema is without the call - it
|
|
95
|
+
is there so the flag can come from a variable.
|
|
96
|
+
|
|
97
|
+
## 0.120.0
|
|
98
|
+
|
|
99
|
+
### Minor Changes
|
|
100
|
+
|
|
101
|
+
- [#589](https://github.com/valbuild/val/pull/589) [`c2d3c0e`](https://github.com/valbuild/val/commit/c2d3c0e6c2010c0a94c725d9dbaa618998773e8a) Thanks [@freekh](https://github.com/freekh)! - **Breaking:** `s.richtext()` options are flat.
|
|
102
|
+
|
|
103
|
+
The `style`, `block` and `inline` groups are gone — every option is a key of its
|
|
104
|
+
own. The names are unchanged, so updating a schema is only a matter of removing
|
|
105
|
+
the wrappers:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
// before
|
|
109
|
+
s.richtext({
|
|
110
|
+
style: { bold: true, italic: true },
|
|
111
|
+
block: { h1: true, ul: true },
|
|
112
|
+
inline: { a: true, img: s.image() },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// after
|
|
116
|
+
s.richtext({
|
|
117
|
+
bold: true,
|
|
118
|
+
italic: true,
|
|
119
|
+
h1: true,
|
|
120
|
+
ul: true,
|
|
121
|
+
a: true,
|
|
122
|
+
img: s.image(),
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The groups never carried any meaning the option names did not already have, and
|
|
127
|
+
they cost something real: an option name and its `ValRichText` theme key were
|
|
128
|
+
spelled differently (`block.h1` vs `theme.h1`), so the type that keeps a theme
|
|
129
|
+
exhaustive had to restate all thirteen options by hand. It is now a mapped type
|
|
130
|
+
over the options themselves — which also fixes an inconsistency in it: enabling
|
|
131
|
+
links with a schema (`a: s.route()`) rather than `a: true` now requires an `a`
|
|
132
|
+
key in the theme, the way `img` always has.
|
|
133
|
+
|
|
134
|
+
`ValRichText` themes were already flat and are unchanged. The serialized schema
|
|
135
|
+
that the server sends the Studio is flat too, so a project must not mix
|
|
136
|
+
`@valbuild/*` versions across this release.
|
|
137
|
+
|
|
3
138
|
## 0.117.0
|
|
4
139
|
|
|
5
140
|
### Patch Changes
|
|
@@ -50,6 +50,9 @@ export { type SerializedBooleanSchema, BooleanSchema } from "./schema/boolean.js
|
|
|
50
50
|
export { type SerializedImageSchema, ImageSchema } from "./schema/image.js";
|
|
51
51
|
export { type SerializedFileSchema, FileSchema } from "./schema/file.js";
|
|
52
52
|
export { type SerializedDateSchema, DateSchema } from "./schema/date.js";
|
|
53
|
+
export { type SerializedSettingsSchema, SettingsSchema, } from "./schema/settings.js";
|
|
54
|
+
export { type SettingsSource, type AssistantSettingsSource, type AssistantAvailability, ASSISTANT_SETTINGS_MAX_LENGTH, assistantAvailability, } from "./source/settings.js";
|
|
55
|
+
export { type ResolvedSettingsModule, SETTINGS_MODULE_CONVENTION, isRootModuleFilePath, resolveSettingsModule, } from "./settingsModule.js";
|
|
53
56
|
export { type SerializedColorSchema, type ColorOptions, ColorSchema, } from "./schema/color.js";
|
|
54
57
|
export { type SerializedCodeSchema, type CodeOptions, type CodeLanguage, CodeSchema, CODE_LANGUAGES, } from "./schema/code.js";
|
|
55
58
|
export { type ColorFormat, type ParsedColor, COLOR_FORMATS, DEFAULT_COLOR_FORMAT, } from "./schema/colorFormat.js";
|
|
@@ -18,6 +18,7 @@ import { color } from "./schema/color.js";
|
|
|
18
18
|
import { route } from "./schema/route.js";
|
|
19
19
|
import { router } from "./schema/router.js";
|
|
20
20
|
import { images } from "./schema/images.js";
|
|
21
|
+
import { settings } from "./schema/settings.js";
|
|
21
22
|
export type InitSchema = {
|
|
22
23
|
/**
|
|
23
24
|
* Define a string.
|
|
@@ -299,6 +300,31 @@ export type InitSchema = {
|
|
|
299
300
|
* ```
|
|
300
301
|
*/
|
|
301
302
|
readonly files: typeof files;
|
|
303
|
+
/**
|
|
304
|
+
* Define the project's settings.
|
|
305
|
+
*
|
|
306
|
+
* One per project, at the root of the content tree — a module file path with
|
|
307
|
+
* no directory segment, `/settings.val.ts` by convention. Every section is
|
|
308
|
+
* optional, so `{}` is a complete settings module and stays one as sections
|
|
309
|
+
* are added.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```typescript
|
|
313
|
+
* export default c.define("/settings.val.ts", s.settings(), {});
|
|
314
|
+
* ```
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```typescript
|
|
318
|
+
* export default c.define("/settings.val.ts", s.settings(), {
|
|
319
|
+
* assistant: {
|
|
320
|
+
* enabled: true,
|
|
321
|
+
* context: "A CMS for developers. British English throughout.",
|
|
322
|
+
* tone: "Plain and direct. Sentence case in headings.",
|
|
323
|
+
* },
|
|
324
|
+
* });
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
readonly settings: typeof settings;
|
|
302
328
|
};
|
|
303
329
|
export declare function initSchema(): {
|
|
304
330
|
string: <T extends string>(options?: Record<string, never>) => import("./index.js").StringSchema<T>;
|
|
@@ -349,4 +375,5 @@ export declare function initSchema(): {
|
|
|
349
375
|
mimeType: string;
|
|
350
376
|
alt: string | null;
|
|
351
377
|
}>, import("./schema/index.js").Schema<string>, Record<string, import("./schema/images.js").ImagesEntryMetadata>>;
|
|
378
|
+
settings: typeof settings;
|
|
352
379
|
};
|
|
@@ -20,17 +20,20 @@ export type ValConfig = {
|
|
|
20
20
|
gitBranch?: string;
|
|
21
21
|
defaultTheme?: "dark" | "light";
|
|
22
22
|
ai?: {
|
|
23
|
+
/**
|
|
24
|
+
* The AI commit-message summariser.
|
|
25
|
+
*
|
|
26
|
+
* Still config, and deliberately: it is about how the repository is
|
|
27
|
+
* written to rather than about the content, and it is getting settings of
|
|
28
|
+
* its own. The ASSISTANT is not here — it is `s.settings()`, under
|
|
29
|
+
* `assistant.enabled`, because whether editors have a chat is a decision
|
|
30
|
+
* about the
|
|
31
|
+
* project's content, made by the people who edit it, and published like any
|
|
32
|
+
* other content change.
|
|
33
|
+
*/
|
|
23
34
|
commitMessages?: {
|
|
24
35
|
disabled?: boolean;
|
|
25
36
|
};
|
|
26
|
-
chat?: {
|
|
27
|
-
experimental?: {
|
|
28
|
-
enable?: boolean;
|
|
29
|
-
};
|
|
30
|
-
suggestions?: string[];
|
|
31
|
-
title?: string;
|
|
32
|
-
description?: string;
|
|
33
|
-
};
|
|
34
37
|
};
|
|
35
38
|
};
|
|
36
39
|
export type InitVal = {
|
|
@@ -43,8 +43,8 @@ export declare class ArraySchema<T extends Schema<SelectorSource>, Src extends S
|
|
|
43
43
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
44
44
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
45
45
|
nullable(): ArraySchema<T, Src | null>;
|
|
46
|
-
readonly(): ArraySchema<T, Src>;
|
|
47
|
-
hidden(): ArraySchema<T, Src>;
|
|
46
|
+
readonly(isReadonly?: boolean): ArraySchema<T, Src>;
|
|
47
|
+
hidden(isHidden?: boolean): ArraySchema<T, Src>;
|
|
48
48
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
49
49
|
protected executeSerialize(): SerializedArraySchema;
|
|
50
50
|
protected executePreview(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: PreviewScope): ReifiedPreview;
|
|
@@ -29,8 +29,8 @@ export declare class BooleanSchema<Src extends boolean | null> extends Schema<Sr
|
|
|
29
29
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
30
30
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
31
31
|
nullable(): BooleanSchema<Src | null>;
|
|
32
|
-
readonly(): BooleanSchema<Src>;
|
|
33
|
-
hidden(): BooleanSchema<Src>;
|
|
32
|
+
readonly(isReadonly?: boolean): BooleanSchema<Src>;
|
|
33
|
+
hidden(isHidden?: boolean): BooleanSchema<Src>;
|
|
34
34
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
35
35
|
/**
|
|
36
36
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -61,8 +61,8 @@ export declare class CodeSchema<Src extends string | null> extends Schema<Src> {
|
|
|
61
61
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
62
62
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
63
63
|
nullable(): CodeSchema<Src | null>;
|
|
64
|
-
readonly(): CodeSchema<Src>;
|
|
65
|
-
hidden(): CodeSchema<Src>;
|
|
64
|
+
readonly(isReadonly?: boolean): CodeSchema<Src>;
|
|
65
|
+
hidden(isHidden?: boolean): CodeSchema<Src>;
|
|
66
66
|
/**
|
|
67
67
|
* How this field is laid out in the editor when it is the item of an array
|
|
68
68
|
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
@@ -56,8 +56,8 @@ export declare class ColorSchema<Src extends string | null> extends Schema<Src>
|
|
|
56
56
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
57
57
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
58
58
|
nullable(): ColorSchema<Src | null>;
|
|
59
|
-
readonly(): ColorSchema<Src>;
|
|
60
|
-
hidden(): ColorSchema<Src>;
|
|
59
|
+
readonly(isReadonly?: boolean): ColorSchema<Src>;
|
|
60
|
+
hidden(isHidden?: boolean): ColorSchema<Src>;
|
|
61
61
|
/**
|
|
62
62
|
* How this field is laid out in the editor when it is the item of an array
|
|
63
63
|
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
@@ -50,8 +50,8 @@ export declare class DateSchema<Src extends string | null> extends Schema<Src> {
|
|
|
50
50
|
from(from: string): DateSchema<Src>;
|
|
51
51
|
to(to: string): DateSchema<Src>;
|
|
52
52
|
nullable(): DateSchema<Src | null>;
|
|
53
|
-
readonly(): DateSchema<Src>;
|
|
54
|
-
hidden(): DateSchema<Src>;
|
|
53
|
+
readonly(isReadonly?: boolean): DateSchema<Src>;
|
|
54
|
+
hidden(isHidden?: boolean): DateSchema<Src>;
|
|
55
55
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
56
56
|
/**
|
|
57
57
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -54,8 +54,8 @@ export declare class DateTimeSchema<Src extends string | null> extends Schema<Sr
|
|
|
54
54
|
from(from: string): DateTimeSchema<Src>;
|
|
55
55
|
to(to: string): DateTimeSchema<Src>;
|
|
56
56
|
nullable(): DateTimeSchema<Src | null>;
|
|
57
|
-
readonly(): DateTimeSchema<Src>;
|
|
58
|
-
hidden(): DateTimeSchema<Src>;
|
|
57
|
+
readonly(isReadonly?: boolean): DateTimeSchema<Src>;
|
|
58
|
+
hidden(isHidden?: boolean): DateTimeSchema<Src>;
|
|
59
59
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
60
60
|
/**
|
|
61
61
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -48,8 +48,8 @@ export declare class FileSchema<Src extends FileSource | null> extends Schema<Sr
|
|
|
48
48
|
private galleryEntries;
|
|
49
49
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
50
50
|
nullable(): FileSchema<Src | null>;
|
|
51
|
-
readonly(): FileSchema<Src>;
|
|
52
|
-
hidden(): FileSchema<Src>;
|
|
51
|
+
readonly(isReadonly?: boolean): FileSchema<Src>;
|
|
52
|
+
hidden(isHidden?: boolean): FileSchema<Src>;
|
|
53
53
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
54
54
|
/**
|
|
55
55
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -93,8 +93,8 @@ export declare class ImageSchema<Src extends ImageSource | null> extends Schema<
|
|
|
93
93
|
private galleryEntries;
|
|
94
94
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
95
95
|
nullable(): ImageSchema<Src | null>;
|
|
96
|
-
readonly(): ImageSchema<Src>;
|
|
97
|
-
hidden(): ImageSchema<Src>;
|
|
96
|
+
readonly(isReadonly?: boolean): ImageSchema<Src>;
|
|
97
|
+
hidden(isHidden?: boolean): ImageSchema<Src>;
|
|
98
98
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
99
99
|
/**
|
|
100
100
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -17,11 +17,12 @@ import { SerializedColorSchema } from "./color.js";
|
|
|
17
17
|
import { SerializedDateSchema } from "./date.js";
|
|
18
18
|
import { SerializedDateTimeSchema } from "./datetime.js";
|
|
19
19
|
import { SerializedRouteSchema } from "./route.js";
|
|
20
|
+
import { SerializedSettingsSchema } from "./settings.js";
|
|
20
21
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
21
22
|
import { FileSource } from "../source/media.js";
|
|
22
23
|
import { GenericRichTextSourceNode, RichTextSource } from "../source/richtext.js";
|
|
23
24
|
import { ReifiedPreview, PreviewScope, PreviewItem } from "../preview.js";
|
|
24
|
-
export type SerializedSchema = SerializedStringSchema | SerializedLiteralSchema | SerializedBooleanSchema | SerializedNumberSchema | SerializedObjectSchema | SerializedArraySchema | SerializedUnionSchema | SerializedRichTextSchema | SerializedRecordSchema | SerializedKeyOfSchema | SerializedFileSchema | SerializedDateSchema | SerializedDateTimeSchema | SerializedColorSchema | SerializedCodeSchema | SerializedRouteSchema | SerializedImageSchema;
|
|
25
|
+
export type SerializedSchema = SerializedStringSchema | SerializedLiteralSchema | SerializedBooleanSchema | SerializedNumberSchema | SerializedObjectSchema | SerializedArraySchema | SerializedUnionSchema | SerializedRichTextSchema | SerializedRecordSchema | SerializedKeyOfSchema | SerializedFileSchema | SerializedDateSchema | SerializedDateTimeSchema | SerializedColorSchema | SerializedCodeSchema | SerializedRouteSchema | SerializedSettingsSchema | SerializedImageSchema;
|
|
25
26
|
type Primitives = number | string | boolean | null | FileSource;
|
|
26
27
|
export type AssertError = {
|
|
27
28
|
message: string;
|
|
@@ -97,15 +98,23 @@ export declare abstract class Schema<Src extends SelectorSource> {
|
|
|
97
98
|
*
|
|
98
99
|
* This is a UI-only flag: the field is rendered disabled in the editor, but
|
|
99
100
|
* the value is not otherwise validated or enforced differently.
|
|
101
|
+
*
|
|
102
|
+
* The flag defaults to `true`, so `.readonly()` and `.readonly(true)` are the
|
|
103
|
+
* same thing. `.readonly(false)` leaves the field editable, which is what a
|
|
104
|
+
* schema is anyway - pass it when the decision comes from a variable.
|
|
100
105
|
*/
|
|
101
|
-
abstract readonly(): Schema<Src>;
|
|
106
|
+
abstract readonly(isReadonly?: boolean): Schema<Src>;
|
|
102
107
|
/**
|
|
103
108
|
* Hide this field from the Val editor.
|
|
104
109
|
*
|
|
105
110
|
* This is a UI-only flag: the field is not rendered in the editor, but the
|
|
106
111
|
* value is still stored, validated and serialized as normal.
|
|
112
|
+
*
|
|
113
|
+
* The flag defaults to `true`, so `.hidden()` and `.hidden(true)` are the
|
|
114
|
+
* same thing. `.hidden(false)` leaves the field visible, which is what a
|
|
115
|
+
* schema is anyway - pass it when the decision comes from a variable.
|
|
107
116
|
*/
|
|
108
|
-
abstract hidden(): Schema<Src>;
|
|
117
|
+
abstract hidden(isHidden?: boolean): Schema<Src>;
|
|
109
118
|
protected abstract executeSerialize(): SerializedSchema;
|
|
110
119
|
/**
|
|
111
120
|
* @param scope Which paths the caller needs a preview for. Absent means the
|
|
@@ -47,8 +47,8 @@ export declare class KeyOfSchema<Sel extends GenericSelector<SourceObject>, Src
|
|
|
47
47
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
48
48
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
49
49
|
nullable(): KeyOfSchema<Sel, Src | null>;
|
|
50
|
-
readonly(): KeyOfSchema<Sel, Src>;
|
|
51
|
-
hidden(): KeyOfSchema<Sel, Src>;
|
|
50
|
+
readonly(isReadonly?: boolean): KeyOfSchema<Sel, Src>;
|
|
51
|
+
hidden(isHidden?: boolean): KeyOfSchema<Sel, Src>;
|
|
52
52
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
53
53
|
/**
|
|
54
54
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -31,8 +31,8 @@ export declare class LiteralSchema<Src extends string | null> extends Schema<Src
|
|
|
31
31
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
32
32
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
33
33
|
nullable(): LiteralSchema<Src | null>;
|
|
34
|
-
readonly(): LiteralSchema<Src>;
|
|
35
|
-
hidden(): LiteralSchema<Src>;
|
|
34
|
+
readonly(isReadonly?: boolean): LiteralSchema<Src>;
|
|
35
|
+
hidden(isHidden?: boolean): LiteralSchema<Src>;
|
|
36
36
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
37
37
|
/**
|
|
38
38
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -35,8 +35,8 @@ export declare class NumberSchema<Src extends number | null> extends Schema<Src>
|
|
|
35
35
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
36
36
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
37
37
|
nullable(): NumberSchema<Src | null>;
|
|
38
|
-
readonly(): NumberSchema<Src>;
|
|
39
|
-
hidden(): NumberSchema<Src>;
|
|
38
|
+
readonly(isReadonly?: boolean): NumberSchema<Src>;
|
|
39
|
+
hidden(isHidden?: boolean): NumberSchema<Src>;
|
|
40
40
|
max(max: number): NumberSchema<Src>;
|
|
41
41
|
min(min: number): NumberSchema<Src>;
|
|
42
42
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
@@ -55,8 +55,8 @@ export declare class ObjectSchema<Props extends ObjectSchemaProps, Src extends O
|
|
|
55
55
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
56
56
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
57
57
|
nullable(): ObjectSchema<Props, Src | null>;
|
|
58
|
-
readonly(): ObjectSchema<Props, Src>;
|
|
59
|
-
hidden(): ObjectSchema<Props, Src>;
|
|
58
|
+
readonly(isReadonly?: boolean): ObjectSchema<Props, Src>;
|
|
59
|
+
hidden(isHidden?: boolean): ObjectSchema<Props, Src>;
|
|
60
60
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
61
61
|
/**
|
|
62
62
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -84,8 +84,8 @@ export declare class RecordSchema<T extends Schema<SelectorSource>, K extends Sc
|
|
|
84
84
|
private validateMediaMimeType;
|
|
85
85
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
86
86
|
nullable(): RecordSchema<T, K, Src | null>;
|
|
87
|
-
readonly(): RecordSchema<T, K, Src>;
|
|
88
|
-
hidden(): RecordSchema<T, K, Src>;
|
|
87
|
+
readonly(isReadonly?: boolean): RecordSchema<T, K, Src>;
|
|
88
|
+
hidden(isHidden?: boolean): RecordSchema<T, K, Src>;
|
|
89
89
|
router(router: ValRouter): RecordSchema<T, K, Src>;
|
|
90
90
|
remote(): RecordSchema<T, K, Src>;
|
|
91
91
|
/**
|
|
@@ -15,7 +15,7 @@ export type SerializedRichTextSchema = {
|
|
|
15
15
|
/** Set when this schema declares a `preview`. The closure itself cannot serialize. */
|
|
16
16
|
preview?: true;
|
|
17
17
|
opt: boolean;
|
|
18
|
-
options?: SerializedRichTextOptions
|
|
18
|
+
options?: SerializedRichTextOptions;
|
|
19
19
|
customValidate?: boolean;
|
|
20
20
|
readonly?: boolean;
|
|
21
21
|
hidden?: boolean;
|
|
@@ -40,8 +40,8 @@ export declare class RichTextSchema<O extends RichTextOptions, Src extends RichT
|
|
|
40
40
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
41
41
|
private recursiveAssert;
|
|
42
42
|
nullable(): RichTextSchema<O, Src | null>;
|
|
43
|
-
readonly(): RichTextSchema<O, Src>;
|
|
44
|
-
hidden(): RichTextSchema<O, Src>;
|
|
43
|
+
readonly(isReadonly?: boolean): RichTextSchema<O, Src>;
|
|
44
|
+
hidden(isHidden?: boolean): RichTextSchema<O, Src>;
|
|
45
45
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
46
46
|
/**
|
|
47
47
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -71,8 +71,8 @@ export declare class RouteSchema<Src extends string | null> extends Schema<Src>
|
|
|
71
71
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
72
72
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
73
73
|
nullable(): RouteSchema<Src | null>;
|
|
74
|
-
readonly(): RouteSchema<Src>;
|
|
75
|
-
hidden(): RouteSchema<Src>;
|
|
74
|
+
readonly(isReadonly?: boolean): RouteSchema<Src>;
|
|
75
|
+
hidden(isHidden?: boolean): RouteSchema<Src>;
|
|
76
76
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
77
77
|
/**
|
|
78
78
|
* How this field is laid out in the editor when it is the item of an array
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Schema, SchemaAssertResult, SerializedSchema } from "./index.js";
|
|
2
|
+
import { PreviewScope, ReifiedPreview } from "../preview.js";
|
|
3
|
+
import { FieldRender } from "../render.js";
|
|
4
|
+
import { SelectorSource } from "../selector/index.js";
|
|
5
|
+
import { SettingsSource } from "../source/settings.js";
|
|
6
|
+
import { ModuleFilePath, SourcePath } from "../val/index.js";
|
|
7
|
+
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
8
|
+
export type SerializedSettingsSchema = {
|
|
9
|
+
type: "settings";
|
|
10
|
+
/**
|
|
11
|
+
* The sections this settings schema knows about, keyed by name.
|
|
12
|
+
*
|
|
13
|
+
* Carried in full rather than reconstructed from the Val version, so a Studio
|
|
14
|
+
* that predates a section still deserializes the schema (it renders what it
|
|
15
|
+
* recognises and leaves the rest alone) instead of failing on an unknown
|
|
16
|
+
* shape.
|
|
17
|
+
*/
|
|
18
|
+
items: Record<string, SerializedSchema>;
|
|
19
|
+
opt: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Present in the shape, never set by `s.settings()`.
|
|
22
|
+
*
|
|
23
|
+
* `render` and `preview` say how a value is drawn where it is an ITEM of an
|
|
24
|
+
* array or a record, and `customValidate` marks a user's `validate` closure. A
|
|
25
|
+
* settings module is not an item, and `s.settings()` takes no arguments to
|
|
26
|
+
* declare any of the three with — so nothing writes them.
|
|
27
|
+
*
|
|
28
|
+
* They are declared anyway, and with their real types rather than `never`, for
|
|
29
|
+
* two reasons: reading `schema.render` off a `SerializedSchema` has to stay
|
|
30
|
+
* legal (`isInlineRender` does exactly that), and a `?: never` member is typed
|
|
31
|
+
* `undefined`, which makes the whole `SerializedSchema` union stop being
|
|
32
|
+
* assignable to `Json` — and serialized schemas travel to the Studio and to
|
|
33
|
+
* the MCP tools as JSON.
|
|
34
|
+
*/
|
|
35
|
+
render?: FieldRender;
|
|
36
|
+
preview?: true;
|
|
37
|
+
customValidate?: boolean;
|
|
38
|
+
readonly?: boolean;
|
|
39
|
+
hidden?: boolean;
|
|
40
|
+
description?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* An object whose keys are all optional: absent means unset.
|
|
44
|
+
*
|
|
45
|
+
* Both the settings module itself and each of its sections are this. See
|
|
46
|
+
* {@link SettingsSource} for why settings cannot be an object schema, and
|
|
47
|
+
* {@link settings} for what a settings module holds.
|
|
48
|
+
*
|
|
49
|
+
* There is no `describe`, `validate`, `render` or `preview` on purpose: the
|
|
50
|
+
* shape is Val's, not the schema author's — `s.settings()` takes no arguments —
|
|
51
|
+
* and the Studio renders each section with a UI built for it.
|
|
52
|
+
*/
|
|
53
|
+
export declare class SettingsSchema<Src extends {
|
|
54
|
+
[key: string]: SelectorSource;
|
|
55
|
+
} | null> extends Schema<Src> {
|
|
56
|
+
private readonly items;
|
|
57
|
+
private readonly opt;
|
|
58
|
+
private readonly isReadonly;
|
|
59
|
+
private readonly isHidden;
|
|
60
|
+
private readonly description?;
|
|
61
|
+
constructor(items: Record<string, Schema<SelectorSource>>, opt?: boolean, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined);
|
|
62
|
+
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
63
|
+
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
64
|
+
nullable(): SettingsSchema<Src | null>;
|
|
65
|
+
readonly(): SettingsSchema<Src>;
|
|
66
|
+
hidden(): SettingsSchema<Src>;
|
|
67
|
+
protected executeCustomValidateAt(): ValidationError[];
|
|
68
|
+
protected executeSerialize(): SerializedSchema;
|
|
69
|
+
protected executePreview(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: PreviewScope): ReifiedPreview;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Define the project's settings.
|
|
73
|
+
*
|
|
74
|
+
* One settings module per project, at the root of the content tree — a module
|
|
75
|
+
* file path with no directory segment, `/settings.val.ts` by convention:
|
|
76
|
+
*
|
|
77
|
+
* ```typescript
|
|
78
|
+
* export default c.define("/settings.val.ts", s.settings(), {});
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* Every section is optional, so `{}` is a complete settings module and stays
|
|
82
|
+
* one as sections are added. Fill in what the project needs:
|
|
83
|
+
*
|
|
84
|
+
* ```typescript
|
|
85
|
+
* export default c.define("/settings.val.ts", s.settings(), {
|
|
86
|
+
* assistant: {
|
|
87
|
+
* enabled: true,
|
|
88
|
+
* context: "Val is a CMS for developers. British English, and 'Val' is never 'VAL'.",
|
|
89
|
+
* tone: "Plain and direct. No exclamation marks, sentence case in headings.",
|
|
90
|
+
* },
|
|
91
|
+
* });
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* The Studio edits it under the cog at the foot of the left rail, and the
|
|
95
|
+
* assistant is told `assistant.context` and `assistant.tone` on every message.
|
|
96
|
+
*
|
|
97
|
+
* `s.settings()` takes no arguments: the shape is Val's, which is what lets the
|
|
98
|
+
* Studio render a UI built for each field rather than a generic form. A
|
|
99
|
+
* project's own global content — a site name, social links — belongs in a
|
|
100
|
+
* module of its own.
|
|
101
|
+
*/
|
|
102
|
+
export declare function settings(): SettingsSchema<SettingsSource>;
|
|
@@ -82,8 +82,8 @@ export declare class StringSchema<Src extends string | null> extends Schema<Src>
|
|
|
82
82
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
83
83
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
84
84
|
nullable(): StringSchema<Src | null>;
|
|
85
|
-
readonly(): StringSchema<Src>;
|
|
86
|
-
hidden(): StringSchema<Src>;
|
|
85
|
+
readonly(isReadonly?: boolean): StringSchema<Src>;
|
|
86
|
+
hidden(isHidden?: boolean): StringSchema<Src>;
|
|
87
87
|
raw(): StringSchema<Src extends null ? RawString | null : RawString>;
|
|
88
88
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
89
89
|
protected executeSerialize(): SerializedSchema;
|
|
@@ -56,8 +56,8 @@ export declare class UnionSchema<Key extends string | Schema<string>, T extends
|
|
|
56
56
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
57
57
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
58
58
|
nullable(): UnionSchema<Key, T, Src | null>;
|
|
59
|
-
readonly(): UnionSchema<Key, T, Src>;
|
|
60
|
-
hidden(): UnionSchema<Key, T, Src>;
|
|
59
|
+
readonly(isReadonly?: boolean): UnionSchema<Key, T, Src>;
|
|
60
|
+
hidden(isHidden?: boolean): UnionSchema<Key, T, Src>;
|
|
61
61
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
62
62
|
/**
|
|
63
63
|
* The variant schema a value takes, for a TAGGED union (string `key`). `null`
|
|
@@ -12,10 +12,11 @@ import { MediaSource } from "../source/media.js";
|
|
|
12
12
|
import { AllRichTextOptions, RichTextSource } from "../source/richtext.js";
|
|
13
13
|
import { RichTextSelector } from "./richtext.js";
|
|
14
14
|
import { JsonSource } from "../source/json.js";
|
|
15
|
-
|
|
15
|
+
import { SettingsSource } from "../source/settings.js";
|
|
16
|
+
export type Selector<T extends Source> = Source extends T ? GenericSelector<T> : T extends MediaSource ? GenericSelector<T> : T extends JsonSource ? GenericSelector<JsonSource> : T extends RichTextSource<infer O> ? RichTextSelector<O> : T extends SourceObject ? ObjectSelector<T> : T extends SourceArray ? ArraySelector<T> : T extends SettingsSource ? GenericSelector<T> : T extends string ? StringSelector<T> : T extends number ? NumberSelector<T> : T extends boolean ? BooleanSelector<T> : T extends null ? PrimitiveSelector<null> : never;
|
|
16
17
|
export type SelectorSource = SourcePrimitive | undefined | readonly SelectorSource[] | {
|
|
17
18
|
[key: string]: SelectorSource;
|
|
18
|
-
} | MediaSource | JsonSource | RichTextSource<AllRichTextOptions> | GenericSelector<Source>;
|
|
19
|
+
} | MediaSource | JsonSource | SettingsSource | RichTextSource<AllRichTextOptions> | GenericSelector<Source>;
|
|
19
20
|
/**
|
|
20
21
|
* @internal
|
|
21
22
|
*/
|