Skip to content

Commit c13adc6

Browse files
committed
fix(core): keep composed schemas on Zod 4
1 parent 6774f6c commit c13adc6

6 files changed

Lines changed: 79 additions & 5 deletions

File tree

packages/core/src/v3/schemas/reports.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
22

33
// Shared contract for `GET /api/v1/reports/:key`: the period grammar and the `format=json` body.
44
// The view model is semantic, not a UI tree: reasons are codes the renderer resolves to prose.

packages/core/src/v3/schemas/scheduleWindow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
22

33
export const MAX_ABSOLUTE_SCHEDULE_WINDOW_SECONDS = 24 * 60 * 60;
44

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { build } from "esbuild";
2+
import { createRequire } from "node:module";
3+
import { dirname, resolve } from "node:path";
4+
import { fileURLToPath } from "node:url";
5+
import { describe, expect, it } from "vitest";
6+
7+
const require = createRequire(import.meta.url);
8+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
9+
10+
describe("schema composition compatibility", () => {
11+
it("parses Zod 4 parent schemas when the root Zod export resolves to Zod 3", async () => {
12+
const result = await build({
13+
stdin: {
14+
contents: `
15+
import { ScheduleMetadata, WebhookMetadata } from "./src/v3/schemas/schemas.ts";
16+
import { WebhookResource } from "./src/v3/schemas/resources.ts";
17+
18+
const verifierArtifact = {
19+
kind: "preset",
20+
preset: "stripe",
21+
config: { scheme: "shared-secret", placement: "header" },
22+
};
23+
const routingTarget = { type: "task", taskId: "my-task" };
24+
25+
export const parsed = {
26+
schedule: ScheduleMetadata.parse({
27+
cron: "0 0 * * *",
28+
timezone: "UTC",
29+
window: "10%",
30+
}),
31+
metadata: WebhookMetadata.parse({
32+
id: "my-webhook",
33+
source: "stripe",
34+
verifierArtifact,
35+
routingTarget,
36+
}),
37+
resource: WebhookResource.parse({
38+
id: "my-webhook",
39+
filePath: "src/trigger.ts",
40+
source: "stripe",
41+
verifierArtifact,
42+
routingTarget,
43+
}),
44+
};
45+
`,
46+
loader: "ts",
47+
resolveDir: packageRoot,
48+
},
49+
bundle: true,
50+
format: "esm",
51+
platform: "node",
52+
target: "node20",
53+
write: false,
54+
plugins: [
55+
{
56+
name: "resolve-root-zod-to-v3",
57+
setup(build) {
58+
build.onResolve({ filter: /^zod$/ }, () => ({ path: require.resolve("zod/v3") }));
59+
},
60+
},
61+
],
62+
});
63+
64+
const bundledModule = await import(
65+
`data:text/javascript;base64,${Buffer.from(result.outputFiles[0].text).toString("base64")}`
66+
);
67+
68+
expect(bundledModule.parsed).toMatchObject({
69+
schedule: { window: "10%" },
70+
metadata: { id: "my-webhook" },
71+
resource: { id: "my-webhook" },
72+
});
73+
});
74+
});

packages/core/src/v3/schemas/webhookApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
22
// Reuse the source-side enum (provider | integrator | either) rather than redefining it.
33
import { WebhookSecretProvisioning } from "./webhookConfig.js";
44

packages/core/src/v3/schemas/webhookConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
22

33
// Ingress webhook verification config. Kept in a LEAF module (imports only `z`) so it
44
// can be consumed by resources.ts / schemas.ts without dragging in the alert-webhook

packages/core/src/v3/schemas/webhookFilter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
22

33
// Webhook delivery filter: server-side predicate gating routing. LEAF module (imports only `z`).
44

0 commit comments

Comments
 (0)