Skip to content
Open
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
2 changes: 1 addition & 1 deletion .agents/skills/enable-small-tests/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Turn disabled coverage into small, independently reviewable fixes. Read the repo
- **Use shared test cases, not new per-bug fixtures.** General inputs, especially keyword cases, must run across languages. A newly discovered bug does not by itself justify a new driver, fixture registration, schema, or language-only input list.
- Preserve intended generated naming. Reject “stabilize names” changes whose only purpose is making JSON-versus-schema output text identical. Renaming is justified when the original name actually prevents compilation or runtime behavior, with evidence.
- Modify only relevant code; respect existing abstraction boundaries. No unrelated cleanup, version bumps, or tombstone comments/docs explaining removed behavior.
- Emit new generated functions, definitions, and imports only when the input types or renderer options require them. Validate generated output both with and without that requirement.
- Emit new generated functions, definitions, and imports only when the input types or renderer options require them. Review the generated-output diff for unnecessary helpers, codecs, imports, or renamed types; do not add unit tests solely to assert helper or import presence or absence, or codec definition counts. Keep unit tests for API behavior and meaningful public naming regressions that fixtures cannot express.
- Write descriptions, comments, commits, and summaries tersely. Explain **what and why**, include useful links and validation, and omit praise and conversational history.

## Find candidates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,14 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer {
return ["z.union([", ...arrayIntercalate(", ", children), "])"];
},
(_transformedStringType) => {
if (_transformedStringType.kind === "date") {
return "dateSchema";
}
if (_transformedStringType.kind === "time") {
return "timeSchema";
}
if (_transformedStringType.kind === "date-time") {
return "z.string().pipe(z.coerce.date())";
return "dateTimeSchema";
}
if (_transformedStringType.kind === "uuid") {
return "z.string().uuid()";
Expand Down Expand Up @@ -459,6 +465,22 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer {

protected emitSchemas(): void {
this.ensureBlankLine();
const kinds = this.forEachType((type) => type.kind);
if (kinds.has("date")) {
this.emitLine(
'const dateSchema = z.string().regex(/^\\d{4}-(?:0[1-9]|1[0-2])-(?:[0-2]\\d|3[01])$/).refine(value => (new Date(value + "T00:00:00Z").toJSON() || "").slice(0, 10) === value);',
);
}
if (kinds.has("time")) {
this.emitLine(
"const timeSchema = z.string().regex(/^(?:[01]\\d|2[0-3]):[0-5]\\d:(?:[0-5]\\d|60)(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/i);",
);
}
if (kinds.has("date-time")) {
this.emitLine(
'const dateTimeSchema = z.string().refine(value => z.string().datetime({ offset: true }).safeParse(value.toUpperCase()).success && (new Date(value.slice(0, 10) + "T00:00:00Z").toJSON() || "").slice(0, 10) === value.slice(0, 10)).pipe(z.coerce.date());',
);
}

this.forEachEnum(
"leading-and-interposing",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export class TypeScriptZodTargetLanguage extends TargetLanguage<
const mapping: Map<TransformedStringTypeKind, PrimitiveStringTypeKind> =
new Map();
const dateTimeType = "date-time";
mapping.set("date", "date");
mapping.set("time", "time");
mapping.set("date-time", dateTimeType);
mapping.set("uuid", "uuid");
mapping.set("bool-string", "bool-string");
Expand Down
7 changes: 7 additions & 0 deletions test/inputs/schema/date-time.5.fail.date.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"date": "2023-02-29",
"time": "23:20:50.52Z",
"date-time": "2018-08-13T21:31:01+01:00",
"union-array": ["1985-04-12", "23:20:50.52Z"],
"complex-union-array": ["2018-08-13T21:31:01+00:10", "foo", 123]
}
7 changes: 7 additions & 0 deletions test/inputs/schema/date-time.6.fail.time.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"date": "1985-04-12",
"time": "29:99:99Z",
"date-time": "2018-08-13T21:31:01+01:00",
"union-array": ["1985-04-12", "23:20:50.52Z"],
"complex-union-array": ["2018-08-13T21:31:01+00:10", "foo", 123]
}
2 changes: 2 additions & 0 deletions test/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,8 @@ export const TypeScriptZodLanguage: Language = {
"union",
"no-defaults",
"date-time",
"date",
"time",
"uuid",
"bool-string",
"integer-string",
Expand Down
Loading