@valbuild/shared 0.125.0 → 0.127.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 CHANGED
@@ -1,5 +1,255 @@
1
1
  # @valbuild/shared
2
2
 
3
+ ## 0.127.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#608](https://github.com/valbuild/val/pull/608) [`7fa8699`](https://github.com/valbuild/val/commit/7fa869974bc895af992a7d5c18b76253636d7d65) Thanks [@freekh](https://github.com/freekh)! - A record whose schema declares its keys now holds every one of them.
8
+
9
+ Two key schemas enumerate their keys: `s.locale()`, whose set is the project's
10
+ `locales.available`, and a union of literals. For those, the keys are part of the
11
+ schema, so a missing one is a hole in the content rather than content nobody has
12
+ written yet — and validation now says so, naming what is missing.
13
+
14
+ ```typescript
15
+ s.record(s.locale(), s.object({ title: s.string() }));
16
+ // Missing key: 'nb-NO'. This record's keys are declared by its schema, so
17
+ // every one of them is an entry — an entry nobody has written yet is null,
18
+ // not absent.
19
+ ```
20
+
21
+ **An entry nobody has written yet is `null`.** Not an absent key: a null entry is
22
+ data you can count, filter and see in a diff, and it means half-translated
23
+ content stays _valid_ rather than blocking a publish. The value type of such a
24
+ record widens by `null` to match, so writing one in a `.val.ts` type-checks:
25
+
26
+ ```typescript
27
+ c.define(
28
+ "/content/jacket.val.ts",
29
+ s.record(s.locale(), s.object({ title: s.string() })),
30
+ {
31
+ "en-US": { title: "Winter jacket" },
32
+ "nb-NO": null, // nobody has translated this yet
33
+ },
34
+ );
35
+ ```
36
+
37
+ **This changes `s.record(s.union(...), item)`**, and closes a gap that was
38
+ already there: `s.record(s.union(s.literal("a"), s.literal("b")), item)` types as
39
+ `Record<"a" | "b", T>`, so TypeScript demanded both keys while the validator only
40
+ checked the ones present. It now checks them too, and — as above — accepts `null`
41
+ for an entry that has not been filled in. If you have such a record with keys
42
+ missing, validation will report them; adding the keys with `null` values is the
43
+ fix, and creating one from the Studio does it for you.
44
+
45
+ `emptyOf` creates these records with every key already in them rather than
46
+ empty, since an empty one is already missing keys. In the Studio use the
47
+ `useEmptyOf()` hook rather than importing `emptyOf` directly: a locale record's
48
+ keys are in the settings module, and the hook is what has read it.
49
+
50
+ - [#608](https://github.com/valbuild/val/pull/608) [`5b7fe05`](https://github.com/valbuild/val/commit/5b7fe05cec6365f9cd1de9ba31e65ed4a87edb63) Thanks [@freekh](https://github.com/freekh)! - `s.locale()`: one of the project's languages.
51
+
52
+ The languages themselves are declared in the settings module (`locales.available`);
53
+ this says that a value is one of them.
54
+
55
+ ```typescript
56
+ // a field: everything in this entry is in this language
57
+ s.record(s.string(), s.object({ locale: s.locale(), title: s.string() }));
58
+
59
+ // a key: one entry per language
60
+ s.record(s.locale(), s.object({ title: s.string() }));
61
+ ```
62
+
63
+ Every locale in content is checked against the project's list, the way `keyOf`
64
+ and `route` are checked against what they point at. An undeclared language names
65
+ the ones the project has; a project that has declared none is told to declare
66
+ them rather than told the value is wrong.
67
+
68
+ A locale is stored as the tag itself — the value in content is `nb-NO`, and a
69
+ record keyed by `s.locale()` has `nb-NO` as its key. Spelling one differently
70
+ where it is stored (`/no/…` as a URL segment) is a real need and is deliberately
71
+ not in this release: it changes what is accepted as well as what is shown, so it
72
+ is being designed on its own rather than folded in here.
73
+
74
+ A locale is **never stega encoded**: it ends up in `<html lang>`, in `hreflang`
75
+ and in `Intl` constructors, none of which survive invisible characters.
76
+
77
+ `assistant.translation` joins the settings module alongside `context` and `tone`
78
+ — a note per language, keyed by language, so only the target language's rules are
79
+ sent when translating into it.
80
+
81
+ - [#608](https://github.com/valbuild/val/pull/608) [`88262ac`](https://github.com/valbuild/val/commit/88262ac8db068650a664981ef73556457d87741a) Thanks [@freekh](https://github.com/freekh)! - Locale scopes: a subtree in one language, and one function that answers which.
82
+
83
+ A **locale scope** is content governed by a single language. Two things open one
84
+ today (a third, locale segments in routes, follows):
85
+
86
+ ```typescript
87
+ // a locale field: this object and everything below it is in one language
88
+ s.object({ locale: s.locale(), title: s.string(), body: s.richtext() });
89
+
90
+ // a locale-keyed record: each entry is in the language its key names
91
+ s.record(s.locale(), s.object({ title: s.string() }));
92
+ ```
93
+
94
+ **A scope may not contain another scope**, and an object may have only one
95
+ locale field. Both are reported as schema errors, naming what to move:
96
+
97
+ ```
98
+ An object can be in one language, so it can have one locale field.
99
+ Found 'locale', 'language'.
100
+
101
+ Everything here is already in one language, so 'byLanguage' cannot set
102
+ another. Move the locale-keyed record out of this object, or take the outer
103
+ one away.
104
+ ```
105
+
106
+ A scope three levels deep is reported once, by the scope immediately enclosing
107
+ it, rather than by every ancestor.
108
+
109
+ The rule is **validated rather than typed**. Expressing "no scope below this
110
+ one" as a type constraint means threading it through every schema class's type
111
+ parameter, and the errors a recursive constraint like that produces name the
112
+ whole tree — an unrelated typo in a `.val.ts` would print pages.
113
+
114
+ `localeAt(path, snapshot)` (from `@valbuild/shared/internal`) answers which
115
+ language governs a path, and is the one implementation of that question, so the
116
+ Studio, the server and the validation worker cannot disagree. It returns the
117
+ tag, which is what `<html lang>`, `Intl` and `locales.available` all want.
118
+
119
+ It answers `null` where no scope governs the path, where the project has
120
+ declared no languages, and where a locale field holds something that is not one
121
+ of them — validation is already reporting the last, and guessing would put a
122
+ language in `<html lang>` that nobody chose.
123
+
124
+ ### Patch Changes
125
+
126
+ - Updated dependencies [[`7fa8699`](https://github.com/valbuild/val/commit/7fa869974bc895af992a7d5c18b76253636d7d65), [`5b7fe05`](https://github.com/valbuild/val/commit/5b7fe05cec6365f9cd1de9ba31e65ed4a87edb63), [`88262ac`](https://github.com/valbuild/val/commit/88262ac8db068650a664981ef73556457d87741a), [`7072e07`](https://github.com/valbuild/val/commit/7072e07623c953a09ac14388ae22dada0b431ce3), [`29811c3`](https://github.com/valbuild/val/commit/29811c3f8c7e001a950e6f4833af6888e6a4efea)]:
127
+ - @valbuild/core@0.127.0
128
+
129
+ ## 0.126.0
130
+
131
+ ### Minor Changes
132
+
133
+ - [#652](https://github.com/valbuild/val/pull/652) [`f2fe70d`](https://github.com/valbuild/val/commit/f2fe70dab2b65000dfaf289f09c70b4a8291467a) Thanks [@freekh](https://github.com/freekh)! - `s.union` is now `s.discriminatedUnion` and `s.enum`.
134
+
135
+ `s.union` did two unrelated jobs and worked out which one you meant from its
136
+ first argument: a string key meant a tagged union of objects, literal schemas
137
+ meant a set of allowed strings. Those are now two schemas with two names.
138
+
139
+ ```ts
140
+ // A fixed set of strings — presents as a dropdown
141
+ s.enum("primary", "secondary", "ghost"); // Schema<"primary" | "secondary" | "ghost">
142
+
143
+ // One of several object shapes, told apart by a tag field
144
+ s.discriminatedUnion(
145
+ "type",
146
+ s.object({ type: s.literal("hero"), heading: s.string() }),
147
+ s.object({ type: s.literal("quote"), text: s.string() }),
148
+ );
149
+ ```
150
+
151
+ `s.enum` takes the strings directly, so the `s.literal(...)` wrapper is gone.
152
+
153
+ **`s.union` still works** — it is deprecated, and it builds exactly the schema
154
+ above, so nothing has to change today:
155
+
156
+ ```ts
157
+ s.union(s.literal("one"), s.literal("two")); // → s.enum("one", "two")
158
+ s.union("type", pageA, pageB); // → s.discriminatedUnion("type", pageA, pageB)
159
+ ```
160
+
161
+ The two are different kinds of node, and that is the reason for the split. A
162
+ discriminated union is a container: the selected variant's fields are the fields
163
+ being edited, and everything that walks a schema descends through it. An enum is
164
+ a leaf — a string with a closed domain — so nothing recurses into it. Told apart
165
+ only by the shape of `key`, every consumer had to re-derive which one it was
166
+ holding; each now has its own serialized type (`"discriminated-union"` and
167
+ `"enum"`) and Val Studio has a field per kind rather than one field that
168
+ branches.
169
+
170
+ Two behaviour changes fall out of the split, both of them fixes:
171
+
172
+ - A value that is not a string at all now fails an enum's validation with a
173
+ type error. `s.union` of literals only ever checked the value against its
174
+ literals when the value WAS a string, so a number or an object where an enum
175
+ was declared validated clean.
176
+ - An enum field now shows its validation errors in Val Studio where the field
177
+ is opened on its own — the module editor and the canvas's fields column — and
178
+ gets the compact error layout inside an inline list row. It is a leaf now, so
179
+ it goes through the same error rendering as every other leaf field; the string
180
+ union bypassed it and showed nothing in those places.
181
+
182
+ Several latent crashes in the old `s.union` are fixed on the way past, all of
183
+ them cases where it threw a `TypeError` instead of reporting:
184
+
185
+ - A required discriminated union holding `null` now reports a type error rather
186
+ than throwing, and resolving a path underneath a nullable one that is `null`
187
+ gives the error the API promises instead of a crash.
188
+ - `s.literal("")` is a legal discriminator tag, and `s.enum("")` a legal value.
189
+ Both used to be treated as absent by a truthiness check — in path resolution,
190
+ in stega encoding, and in the message that lists a union's valid tags. The
191
+ editor's dropdowns handle them too: an empty value is reserved by the select
192
+ component and had to be mapped around.
193
+ - A variant that omits the discriminator entirely is now reported as the schema
194
+ error it is, instead of throwing while the check looked for it.
195
+ - An enum's value is now indexed for search, like every other string leaf. The
196
+ old string union was never indexed at all, so searching for one of its values
197
+ could not find the field.
198
+ - A nullable discriminated union set to `null` no longer renders a spinner that
199
+ never resolves.
200
+
201
+ `s.discriminatedUnion` also requires at least one variant, as `s.enum` requires
202
+ at least one value: a union with nothing to select is not a thing to write, and
203
+ everything downstream reads the first variant where it needs any.
204
+
205
+ If you read serialized schemas yourself, that is the breaking part: `type` is no
206
+ longer `"union"`, an enum carries `values: string[]` instead of a `key` plus
207
+ `items` of literal schemas, and `UnionSchema` is no longer a class.
208
+ `SerializedUnionSchema`, `SerializedStringUnionSchema`,
209
+ `SerializedObjectUnionSchema` and `UnionSchema` remain as deprecated type
210
+ aliases.
211
+
212
+ ### Patch Changes
213
+
214
+ - [#664](https://github.com/valbuild/val/pull/664) [`5bfd630`](https://github.com/valbuild/val/commit/5bfd630b63dee2189e238f20fe72ecc5537160f7) Thanks [@freekh](https://github.com/freekh)! - Show the git message on deployments Val did not publish
215
+
216
+ The deploy feed could only name a publish when Val itself had made the commit:
217
+ the message came off Val's own `ValCommit`, and every other deployment — a
218
+ developer's push, a merged pull request, a revert — showed a seven-character
219
+ sha. On most projects those are the majority, so "what went out at 14:02?" had
220
+ no answer in the Studio.
221
+
222
+ A deployment can now carry its own `commitMessage`, which the Studio uses
223
+ wherever there is no Val commit to prefer. It is optional and nullable, so a
224
+ content service that does not report messages is unaffected — those publishes
225
+ keep showing the short sha, exactly as before.
226
+
227
+ Deployment rows also show only the subject line of a message now. A git message
228
+ is a subject, a blank line and a body, and the rows are one truncated line — so
229
+ a real push arrived as "Subject The body went on like this…". The classic
230
+ Draft changes view still has the whole message in its tooltip.
231
+
232
+ - [#659](https://github.com/valbuild/val/pull/659) [`ccbcda6`](https://github.com/valbuild/val/commit/ccbcda60b3e3c465071229ae1ba28ac735483e63) Thanks [@freekh](https://github.com/freekh)! - Discarding changes now clears the validation errors, previews and search results
233
+ that were computed from them.
234
+
235
+ A discard that removed a module's last pending change announced itself only as
236
+ a "drop", and the stores that keep validation results, previews and the search
237
+ index listened only for changes being applied. So after discarding, the Studio
238
+ kept showing the errors and previews of the discarded edit until something else
239
+ touched the module.
240
+
241
+ Fields that reference another module's keys (`s.keyOf(...)` and `s.route()`)
242
+ also follow that module now. Renaming a page and then discarding the rename left
243
+ every `keyOf` field pointing at it reporting that the key does not exist — about
244
+ a key that was back — because the module holding the reference had not changed
245
+ and was never re-checked. The validation store now tracks which records a
246
+ module's errors resolve against and re-checks it when their keys change, and only
247
+ then: editing content inside a referenced page does not re-validate its
248
+ referrers.
249
+
250
+ - Updated dependencies [[`f2fe70d`](https://github.com/valbuild/val/commit/f2fe70dab2b65000dfaf289f09c70b4a8291467a), [`171208a`](https://github.com/valbuild/val/commit/171208a20177e68ed5a8b1a6fdaabfe893a6aa5f)]:
251
+ - @valbuild/core@0.126.0
252
+
3
253
  ## 0.125.0
4
254
 
5
255
  ### Minor Changes
@@ -443,6 +443,14 @@ export declare const Api: {
443
443
  createdAt: z.ZodString;
444
444
  commitMessage: z.ZodNullable<z.ZodString>;
445
445
  }, z.core.$strip>>;
446
+ deployments: z.ZodOptional<z.ZodArray<z.ZodObject<{
447
+ deploymentId: z.ZodString;
448
+ deploymentState: z.ZodString;
449
+ commitSha: z.ZodString;
450
+ updatedAt: z.ZodString;
451
+ createdAt: z.ZodString;
452
+ commitMessage: z.ZodOptional<z.ZodNullable<z.ZodString>>;
453
+ }, z.core.$strip>>>;
446
454
  config: z.ZodObject<{
447
455
  project: z.ZodOptional<z.ZodString>;
448
456
  root: z.ZodOptional<z.ZodString>;
@@ -940,7 +948,7 @@ export declare const Api: {
940
948
  message: z.ZodString;
941
949
  value: z.ZodOptional<z.ZodUnknown>;
942
950
  fatal: z.ZodOptional<z.ZodBoolean>;
943
- fixes: z.ZodOptional<z.ZodArray<z.ZodType<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "external:upload", unknown, z.core.$ZodTypeInternals<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "external:upload", unknown>>>>;
951
+ fixes: z.ZodOptional<z.ZodArray<z.ZodType<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "record:fill-keys" | "external:upload", unknown, z.core.$ZodTypeInternals<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "record:fill-keys" | "external:upload", unknown>>>>;
944
952
  }, z.core.$strip>>>>;
945
953
  }, z.core.$strip>>;
946
954
  }, z.core.$strip>;
@@ -1,4 +1,5 @@
1
1
  import type { SerializedSchema, Source } from "@valbuild/core";
2
+ import { type EmptyOfContext } from "../emptyOf.js";
2
3
  import { type BuildResult } from "./aiImageToolPatches.js";
3
4
  export declare function buildDuplicatePatch(args: {
4
5
  sourcePath: string[];
@@ -6,7 +7,7 @@ export declare function buildDuplicatePatch(args: {
6
7
  }, moduleSchema: SerializedSchema, moduleSource: Source | undefined): BuildResult;
7
8
  export declare function buildEmptyAtPathPatch(args: {
8
9
  destinationPath: string[];
9
- }, moduleSchema: SerializedSchema, moduleSource: Source | undefined): BuildResult;
10
+ }, moduleSchema: SerializedSchema, moduleSource: Source | undefined, context?: EmptyOfContext): BuildResult;
10
11
  /**
11
12
  * What kind of container a path points at.
12
13
  *
@@ -1,2 +1,25 @@
1
1
  import { SerializedSchema, Json } from "@valbuild/core";
2
- export declare function emptyOf(schema: SerializedSchema): Json;
2
+ /**
3
+ * What `emptyOf` cannot read off a serialized schema.
4
+ *
5
+ * The project's languages, and which one is being worked in. Neither is in the
6
+ * schema: a locale-keyed record has one entry per language and the languages
7
+ * are declared in the settings module, and "which language am I writing" is a
8
+ * fact about the editor, not about the content. Optional throughout: a caller
9
+ * that has no context gets an empty record and an unset locale, which
10
+ * validation then reports, rather than wrong ones.
11
+ */
12
+ export type EmptyOfContext = {
13
+ /** `locales.available` from the settings module. */
14
+ locales?: string[];
15
+ /**
16
+ * The one language being worked in, where the editor has narrowed to one.
17
+ *
18
+ * A new `s.locale()` field is created already set to it. Someone filtered to
19
+ * Norwegian is writing Norwegian, and a new item that defaulted to unset
20
+ * would fail validation and vanish from the list they are looking at, in
21
+ * that order.
22
+ */
23
+ selectedLocale?: string;
24
+ };
25
+ export declare function emptyOf(schema: SerializedSchema, context?: EmptyOfContext): Json;
@@ -16,6 +16,7 @@ export * from "./parseRoutePattern.js";
16
16
  export * from "./getNextAppRouterSourceFolder.js";
17
17
  export * from "./routeValidation.js";
18
18
  export * from "./resolveSchemaSourceFixes.js";
19
+ export * from "./localeAt.js";
19
20
  export * from "./getErrorMessageFromUnknownJson.js";
20
21
  export * from "./zod/SerializedSchema.js";
21
22
  export * from "./valCanvasProtocol.js";
@@ -0,0 +1,19 @@
1
+ import { type SourcePath } from "@valbuild/core";
2
+ import { type SchemaSourceSnapshot } from "./resolveSchemaSourceFixes.js";
3
+ /**
4
+ * Which of the project's languages governs a path, or `null` for none.
5
+ *
6
+ * THE question the whole feature turns on. A locale scope is a subtree in one
7
+ * language, and three things open one: a `locale` field on an object, a record
8
+ * keyed by `s.locale()`, and a locale segment in a segmented key. Once this can
9
+ * be answered from the schema and the source alone, everything downstream falls
10
+ * out of it — the Studio's locale filter, deep links, `<html lang>`, and knowing
11
+ * what to translate from and into.
12
+ *
13
+ * One implementation, so the Studio, the server and the validation worker cannot
14
+ * disagree about what language a piece of content is in.
15
+ *
16
+ * `null` means no scope governs the path — which is the answer for most content
17
+ * in most projects, and for every project that has not declared any languages.
18
+ */
19
+ export declare function localeAt(path: SourcePath, snapshot: SchemaSourceSnapshot): string | null;
@@ -1,4 +1,4 @@
1
- import { type Json, type ModuleFilePath, type SerializedSchema, type SourcePath, type ValidationError } from "@valbuild/core";
1
+ import { type Json, type ModuleFilePath, type SerializedSchema, type SourcePath, type ValidationError, type ValidationFix } from "@valbuild/core";
2
2
  export type SchemaSourceSnapshot = {
3
3
  schemas: Record<ModuleFilePath, SerializedSchema>;
4
4
  sources: Record<ModuleFilePath, Json>;
@@ -14,6 +14,28 @@ export declare function findSimilar(key: string, targets: string[]): {
14
14
  target: string;
15
15
  distance: number;
16
16
  }[];
17
+ /**
18
+ * The record a `keyof:check-keys` error resolves against — the value and the
19
+ * schema at the error's `sourcePath`.
20
+ *
21
+ * Exported for the one consumer that has to know what a resolution DEPENDED
22
+ * on rather than what it concluded: `ValidationStore` re-reads the keys here
23
+ * to decide whether a change to the referenced module can have moved the
24
+ * answer. Keep this and {@link checkKeyIsValid} reading the same record, or the
25
+ * store will invalidate on one record and the resolution answer from another.
26
+ */
27
+ export declare function getKeyOfRecordAt(sourcePath: SourcePath, snapshot: SchemaSourceSnapshot): {
28
+ source: unknown;
29
+ schema: SerializedSchema | undefined;
30
+ };
31
+ /**
32
+ * The languages the project declares, from its settings module.
33
+ *
34
+ * Empty where there is no settings module, no `locales` section, or nothing in
35
+ * it — all of which mean the same thing: this project has not said it is
36
+ * translated.
37
+ */
38
+ export declare function declaredLocales(snapshot: SchemaSourceSnapshot): string[];
17
39
  export type ResolvedFix = {
18
40
  status: "resolved";
19
41
  } | {
@@ -21,20 +43,47 @@ export type ResolvedFix = {
21
43
  error: ValidationError;
22
44
  };
23
45
  /**
24
- * Resolves a single `keyof:check-keys` or `router:check-route` error against
25
- * the given schema/source snapshot. Returns:
46
+ * The fixes {@link resolveSchemaSourceFixForError} answers for.
47
+ *
48
+ * A marker error carrying one of these is NOT a message: it says "ask the whole
49
+ * project about this" and carries the value to ask with, because the schema
50
+ * that raised it can only see its own module. Left unresolved, what a user sees
51
+ * is the marker's own placeholder text — "should typically be processed by Val
52
+ * internally … version mismatch" — which is alarming and says nothing.
53
+ *
54
+ * A list rather than a check per call site: every caller that resolves some of
55
+ * these has to resolve all of them, and the two that leaked did so by adding a
56
+ * fix here and not to a condition somewhere else.
57
+ */
58
+ export declare const SCHEMA_SOURCE_FIXES: ValidationFix[];
59
+ /** Whether an error is a marker only the whole project can answer. */
60
+ export declare function isSchemaSourceFixError(error: ValidationError): boolean;
61
+ /**
62
+ * The record a `keyof:check-keys` error resolves against, or null for any other
63
+ * error — including a malformed marker, which
64
+ * {@link resolveSchemaSourceFixForError} reports and this has nothing to say
65
+ * about.
66
+ *
67
+ * For a consumer that needs to know what the resolution READS, not what it
68
+ * concludes: `ValidationStore` keeps this per validated module, so that a change
69
+ * to the referenced record can invalidate the module holding the reference.
70
+ */
71
+ export declare function keyOfRecordPath(error: ValidationError): SourcePath | null;
72
+ /**
73
+ * Resolves a single marker error (see {@link SCHEMA_SOURCE_FIXES}) against the
74
+ * given schema/source snapshot. Returns:
26
75
  * - null if the error is not one of these fixes (caller should pass through)
27
- * - { status: "resolved" } if the referenced key/route is valid (drop error)
76
+ * - { status: "resolved" } if the reference is valid (drop error)
28
77
  * - { status: "remaining"; error } if invalid (rewritten error to surface)
29
78
  */
30
79
  export declare function resolveSchemaSourceFixForError(error: ValidationError, snapshot: SchemaSourceSnapshot): ResolvedFix | null;
31
80
  /**
32
81
  * Apply schema/source fix resolution across a map of validation errors.
33
82
  *
34
- * Errors with `keyof:check-keys` or `router:check-route` are resolved against
35
- * the in-memory schema/source snapshot — valid references drop the error,
36
- * invalid ones are rewritten with a "did you mean…" message and have their
37
- * `fixes` cleared (so downstream code reports them as plain validation errors).
83
+ * Errors carrying one of {@link SCHEMA_SOURCE_FIXES} are resolved against the
84
+ * in-memory schema/source snapshot — valid references drop the error, invalid
85
+ * ones are rewritten with a "did you mean…" message and have their `fixes`
86
+ * cleared (so downstream code reports them as plain validation errors).
38
87
  * All other errors pass through untouched.
39
88
  *
40
89
  * Source paths with no remaining errors are removed from the result.
@@ -1,12 +1,13 @@
1
1
  import { z } from "zod";
2
- import { type SerializedSchema as SerializedSchemaT, type SerializedStringSchema as SerializedStringSchemaT, type SerializedLiteralSchema as SerializedLiteralSchemaT, type SerializedBooleanSchema as SerializedBooleanSchemaT, type SerializedNumberSchema as SerializedNumberSchemaT, type SerializedObjectSchema as SerializedObjectSchemaT, type SerializedArraySchema as SerializedArraySchemaT, type SerializedUnionSchema as SerializedUnionSchemaT, type SerializedRichTextSchema as SerializedRichTextSchemaT, type SerializedRichTextOptions as SerializedRichTextOptionsT, type SerializedRecordSchema as SerializedRecordSchemaT, type SerializedKeyOfSchema as SerializedKeyOfSchemaT, type SerializedRouteSchema as SerializedRouteSchemaT, type SerializedFileSchema as SerializedFileSchemaT, type SerializedDateSchema as SerializedDateSchemaT, type SerializedDateTimeSchema as SerializedDateTimeSchemaT, type SerializedColorSchema as SerializedColorSchemaT, type SerializedCodeSchema as SerializedCodeSchemaT, type SerializedImageSchema as SerializedImageSchemaT, type SerializedSettingsSchema as SerializedSettingsSchemaT } from "@valbuild/core";
2
+ import { type SerializedSchema as SerializedSchemaT, type SerializedStringSchema as SerializedStringSchemaT, type SerializedLiteralSchema as SerializedLiteralSchemaT, type SerializedBooleanSchema as SerializedBooleanSchemaT, type SerializedNumberSchema as SerializedNumberSchemaT, type SerializedObjectSchema as SerializedObjectSchemaT, type SerializedArraySchema as SerializedArraySchemaT, type SerializedDiscriminatedUnionSchema as SerializedDiscriminatedUnionSchemaT, type SerializedEnumSchema as SerializedEnumSchemaT, type SerializedRichTextSchema as SerializedRichTextSchemaT, type SerializedRichTextOptions as SerializedRichTextOptionsT, type SerializedRecordSchema as SerializedRecordSchemaT, type SerializedKeyOfSchema as SerializedKeyOfSchemaT, type SerializedLocaleSchema as SerializedLocaleSchemaT, type SerializedRouteSchema as SerializedRouteSchemaT, type SerializedFileSchema as SerializedFileSchemaT, type SerializedDateSchema as SerializedDateSchemaT, type SerializedDateTimeSchema as SerializedDateTimeSchemaT, type SerializedColorSchema as SerializedColorSchemaT, type SerializedCodeSchema as SerializedCodeSchemaT, type SerializedImageSchema as SerializedImageSchemaT, type SerializedSettingsSchema as SerializedSettingsSchemaT } from "@valbuild/core";
3
3
  export declare const SerializedStringSchema: z.ZodType<SerializedStringSchemaT>;
4
4
  export declare const SerializedLiteralSchema: z.ZodType<SerializedLiteralSchemaT>;
5
5
  export declare const SerializedBooleanSchema: z.ZodType<SerializedBooleanSchemaT>;
6
6
  export declare const SerializedNumberSchema: z.ZodType<SerializedNumberSchemaT>;
7
7
  export declare const SerializedObjectSchema: z.ZodType<SerializedObjectSchemaT>;
8
8
  export declare const SerializedArraySchema: z.ZodType<SerializedArraySchemaT>;
9
- export declare const SerializedUnionSchema: z.ZodType<SerializedUnionSchemaT>;
9
+ export declare const SerializedDiscriminatedUnionSchema: z.ZodType<SerializedDiscriminatedUnionSchemaT>;
10
+ export declare const SerializedEnumSchema: z.ZodType<SerializedEnumSchemaT>;
10
11
  export declare const ImageEncodeOption: z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
11
12
  type: z.ZodLiteral<"webp">;
12
13
  quality: z.ZodOptional<z.ZodNumber>;
@@ -72,6 +73,7 @@ export declare const CodeOptions: z.ZodObject<{
72
73
  }>>;
73
74
  }, z.core.$strip>;
74
75
  export declare const SerializedCodeSchema: z.ZodType<SerializedCodeSchemaT>;
76
+ export declare const SerializedLocaleSchema: z.ZodType<SerializedLocaleSchemaT>;
75
77
  export declare const SerializedRouteSchema: z.ZodType<SerializedRouteSchemaT>;
76
78
  export declare const SerializedSettingsSchema: z.ZodType<SerializedSettingsSchemaT>;
77
79
  export declare const SerializedSchema: z.ZodType<SerializedSchemaT>;
@@ -5,5 +5,6 @@ export declare const ValDeployment: z.ZodObject<{
5
5
  commitSha: z.ZodString;
6
6
  updatedAt: z.ZodString;
7
7
  createdAt: z.ZodString;
8
+ commitMessage: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8
9
  }, z.core.$strip>;
9
10
  export type ValDeployment = z.infer<typeof ValDeployment>;