Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions .github/scripts/gen-settings-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
*
* plain (strip) objects -> OPENED: the additionalProperties: false zod emits is deleted, since GitHub-bound bodies
* must accept future fields; only strictObject declarations stay closed, like the runtime
* url strings -> UNFORMATTED: the format: "uri" z.url() emits is deleted, since ajv judges it by RFC 3986
* and refuses hosts, paths, and spaces that the runtime's new URL() rule accepts
* date strings -> UNFORMATTED: the format: "date" / "date-time" z.iso emits is deleted too, since ajv-formats
* rounds long fractional seconds into an invalid :60; zod's pattern beside it stays and is the grammar
* format keywords -> DELETED: every format zod emits goes, whether ajv-formats judges it by a grammar the runtime
* does not share ("uri" refuses non-ASCII hosts and spaces new URL() takes; "date-time" rounds
* a long fractional second into an invalid :60) or JSON Schema does not define it at all
* ("includes", from zod 4.6.0's folding of string checks); zod's pattern beside it stays and is the grammar
* defaulted keys -> OPTIONAL: io: "input" describes the file, not the parsed output, so a key the slice
* fills at parse (a ruleset's target) stays out of required and keeps its default keyword
* root layout -> zod's own, passed through verbatim
Expand All @@ -27,7 +27,6 @@ const ROOT = join(import.meta.dir, "..", "..");

interface ZodDefView {
type?: string;
format?: string;
catchall?: unknown;
}

Expand All @@ -42,14 +41,10 @@ const generated = z.toJSONSchema(SettingsFile, {
if (def.type === "object" && def.catchall === undefined) {
delete json.additionalProperties;
}
// z.url() parses with new URL(), which takes a non-ASCII host or path and a space; ajv's format: "uri" refuses all
// three, so the keyword goes and the runtime alone judges the URL (the string stays typed and described).
if (def.type === "string" && def.format === "url") {
delete json.format;
}
// z.iso.date()/datetime() emit a pattern that is the runtime's grammar plus a format keyword; ajv-formats parses a
// long fractional second as a number and rounds it into an invalid :60, refusing what the runtime accepts.
if (def.type === "string" && (def.format === "date" || def.format === "datetime")) {
// The published schema carries no format keyword, so this covers ajv-formats grammars the runtime does not share
// ("uri", "date-time") and names JSON Schema never defined, such as the format: "includes" zod 4.6.0 (#6554) emits
// for .includes() since it copies every string_format check's name; zod's pattern beside it stays as the grammar.
if ("format" in json) {
delete json.format;
}
// z.record's propertyNames: {type: "string"} is a no-op in JSON (keys are always strings).
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.11/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.15/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
Loading
Loading