Skip to content

Commit bca13a7

Browse files
authored
fix(zod): generate optional field as z.optional() rather than z.nullish() to be consistent with Prisma's typing (#1426)
1 parent 3b38311 commit bca13a7

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

packages/schema/src/plugins/zod/utils/schema-gen.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,14 @@ export function makeFieldSchema(field: DataModelField) {
141141
}
142142

143143
if (field.attributes.some(isDefaultWithAuth)) {
144-
// field uses `auth()` in `@default()`, this was transformed into a pseudo default
145-
// value, while compiling to zod we should turn it into an optional field instead
146-
// of `.default()`
147-
schema += '.nullish()';
144+
if (field.type.optional) {
145+
schema += '.nullish()';
146+
} else {
147+
// field uses `auth()` in `@default()`, this was transformed into a pseudo default
148+
// value, while compiling to zod we should turn it into an optional field instead
149+
// of `.default()`
150+
schema += '.optional()';
151+
}
148152
} else {
149153
const schemaDefault = getFieldSchemaDefault(field);
150154
if (schemaDefault !== undefined) {

packages/schema/src/utils/pkg-utils.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type PackageManagers = 'npm' | 'yarn' | 'pnpm';
1313
* @export
1414
* @template e A type parameter that extends boolean
1515
*/
16-
export type FindUp<e extends boolean> = e extends true ? string[] | undefined : string | undefined
16+
export type FindUp<e extends boolean> = e extends true ? string[] | undefined : string | undefined;
1717
/**
1818
* Find and return file paths by searching parent directories based on the given names list and current working directory (cwd) path.
1919
* Optionally return a single path or multiple paths.
@@ -28,7 +28,12 @@ export type FindUp<e extends boolean> = e extends true ? string[] | undefined :
2828
* @param [result=[]] An array of strings representing the accumulated results used in multiple results
2929
* @returns Path(s) to a specific file or folder within the directory or parent directories
3030
*/
31-
export function findUp<e extends boolean = false>(names: string[], cwd: string = process.cwd(), multiple: e = false as e, result: string[] = []): FindUp<e> {
31+
export function findUp<e extends boolean = false>(
32+
names: string[],
33+
cwd: string = process.cwd(),
34+
multiple: e = false as e,
35+
result: string[] = []
36+
): FindUp<e> {
3237
if (!names.some((name) => !!name)) return undefined;
3338
const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
3439
if (multiple == false && target) return path.join(cwd, target) as FindUp<e>;
@@ -38,7 +43,6 @@ export function findUp<e extends boolean = false>(names: string[], cwd: string =
3843
return findUp(names, up, multiple, result);
3944
}
4045

41-
4246
/**
4347
* Find a Node module/file given its name in a specific directory, with a fallback to the current working directory.
4448
* If the name is empty, return undefined.
@@ -54,11 +58,11 @@ export function findNodeModulesFile(name: string, cwd: string = process.cwd()) {
5458
if (!name) return undefined;
5559
try {
5660
// Use require.resolve to find the module/file. The paths option allows specifying the directory to start from.
57-
const resolvedPath = require.resolve(name, { paths: [cwd] })
58-
return resolvedPath
61+
const resolvedPath = require.resolve(name, { paths: [cwd] });
62+
return resolvedPath;
5963
} catch (error) {
6064
// If require.resolve fails to find the module/file, it will throw an error.
61-
return undefined
65+
return undefined;
6266
}
6367
}
6468

@@ -86,7 +90,7 @@ export function installPackage(
8690
projectPath = '.',
8791
exactVersion = true
8892
) {
89-
const manager = pkgManager ?? getPackageManager(projectPath);
93+
const manager = pkgManager ?? getPackageManager(projectPath).packageManager;
9094
console.log(`Installing package "${pkg}@${tag}" with ${manager}`);
9195
switch (manager) {
9296
case 'yarn':
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1378', () => {
4+
it('regression', async () => {
5+
await loadSchema(
6+
`
7+
model User {
8+
id String @id @default(cuid())
9+
todos Todo[]
10+
}
11+
12+
model Todo {
13+
id String @id @default(cuid())
14+
name String @length(3,255)
15+
userId String @default(auth().id)
16+
17+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
18+
@@allow("all", auth() == user)
19+
}
20+
`,
21+
{
22+
extraDependencies: ['zod'],
23+
extraSourceFiles: [
24+
{
25+
name: 'main.ts',
26+
content: `
27+
import { z } from 'zod';
28+
import { PrismaClient } from '@prisma/client';
29+
import { enhance } from '.zenstack/enhance';
30+
import { TodoCreateSchema } from '.zenstack/zod/models';
31+
32+
const prisma = new PrismaClient();
33+
const db = enhance(prisma);
34+
35+
export const onSubmit = async (values: z.infer<typeof TodoCreateSchema>) => {
36+
await db.todo.create({
37+
data: values,
38+
});
39+
};
40+
`,
41+
},
42+
],
43+
compile: true,
44+
}
45+
);
46+
});
47+
});

0 commit comments

Comments
 (0)