Skip to content

Commit 1793122

Browse files
committed
fix(models): use implementAsync for async z.function occurrences
1 parent 4ef657f commit 1793122

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

packages/models/src/lib/implementation/function.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,49 @@
11
import { z } from 'zod/v4';
22
import type { $ZodFunction } from 'zod/v4/core';
33

4+
// https://zod.dev/v4/changelog?id=zfunction
5+
// https://github.com/colinhacks/zod/issues/4143#issuecomment-2931729793
46
// https://github.com/matejchalk/zod2md?tab=readme-ov-file#function-schemas
5-
export function convertZodFunctionToSchema<T extends $ZodFunction>(factory: T) {
7+
8+
/**
9+
* Converts Zod v4 function factory (returned by `z.function`) to Zod schema.
10+
*
11+
* Supports asynchronous functions. For synchronous functions, you can use {@link convertSyncZodFunctionToSchema}.
12+
*
13+
* @param factory `z.function({ input: [...], output: ... })`
14+
* @returns Zod schema with compile-time and runtime validations.
15+
*/
16+
export function convertAsyncZodFunctionToSchema<T extends $ZodFunction>(
17+
factory: T,
18+
) {
19+
return z
20+
.custom()
21+
.transform((arg, ctx) => {
22+
if (typeof arg !== 'function') {
23+
ctx.addIssue(`Expected function, received ${typeof arg}`);
24+
return z.NEVER;
25+
}
26+
return factory.implementAsync(arg as Parameters<T['implementAsync']>[0]);
27+
})
28+
.meta({
29+
// enables zod2md to include function signature in docs
30+
$ZodFunction: factory,
31+
});
32+
}
33+
34+
/**
35+
* Converts Zod v4 function factory (returned by `z.function`) to Zod schema.
36+
*
37+
* **IMPORTANT!** Use for synchronous functions only. For asynchronous functions use {@link convertAsyncZodFunctionToSchema}.
38+
*
39+
* @throws `Encountered Promise during synchronous parse. Use .parseAsync() instead.` if used with async functions.
40+
*
41+
* @param factory `z.function({ input: [...], output: ... })`
42+
* @returns Zod schema with compile-time and runtime validations.
43+
*/
44+
export function convertSyncZodFunctionToSchema<T extends $ZodFunction>(
45+
factory: T,
46+
) {
647
return z
748
.custom()
849
.transform((arg, ctx) => {

packages/models/src/lib/runner-config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { z } from 'zod/v4';
22
import { auditOutputsSchema } from './audit-output.js';
3-
import { convertZodFunctionToSchema } from './implementation/function.js';
3+
import { convertAsyncZodFunctionToSchema } from './implementation/function.js';
44
import { filePathSchema } from './implementation/schemas.js';
55

6-
export const outputTransformSchema = convertZodFunctionToSchema(
6+
export const outputTransformSchema = convertAsyncZodFunctionToSchema(
77
z.function({
88
input: [z.unknown()],
99
output: z.union([auditOutputsSchema, z.promise(auditOutputsSchema)]),
@@ -23,7 +23,7 @@ export const runnerConfigSchema = z
2323

2424
export type RunnerConfig = z.infer<typeof runnerConfigSchema>;
2525

26-
export const runnerFunctionSchema = convertZodFunctionToSchema(
26+
export const runnerFunctionSchema = convertAsyncZodFunctionToSchema(
2727
z.function({
2828
output: z.union([auditOutputsSchema, z.promise(auditOutputsSchema)]),
2929
}),

0 commit comments

Comments
 (0)