Skip to content

Commit

Permalink
fix: prisma schema generation issue with calling attribute function w…
Browse files Browse the repository at this point in the history
…ith literal (#930)
  • Loading branch information
ymc9 authored Jan 3, 2024
1 parent cdd0f55 commit 91fe8e7
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 18 deletions.
11 changes: 2 additions & 9 deletions packages/schema/src/plugins/prisma/prisma-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,17 +304,10 @@ export class FunctionCall {
}

export class FunctionCallArg {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
constructor(public name: string | undefined, public value: any) {}
constructor(public name: string | undefined, public value: string) {}

toString(): string {
const val =
this.value === null || this.value === undefined
? 'null'
: typeof this.value === 'string'
? `"${this.value}"`
: this.value.toString();
return this.name ? `${this.name}: ${val}` : val;
return this.name ? `${this.name}: ${this.value}` : this.value;
}
}

Expand Down
19 changes: 13 additions & 6 deletions packages/schema/src/plugins/prisma/schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import {
isArrayExpr,
isInvocationExpr,
isLiteralExpr,
isNullExpr,
isReferenceExpr,
isStringLiteral,
LiteralExpr,
Model,
NumberLiteral,
Expand All @@ -35,6 +37,7 @@ import {
PluginOptions,
resolved,
resolvePath,
ZModelCodeGenerator,
} from '@zenstackhq/sdk';
import fs from 'fs';
import { writeFile } from 'fs/promises';
Expand All @@ -45,6 +48,7 @@ import { name } from '.';
import { getStringLiteral } from '../../language-server/validator/utils';
import telemetry from '../../telemetry';
import { execSync } from '../../utils/exec-utils';
import { getPackageJson } from '../../utils/pkg-utils';
import {
ModelFieldType,
AttributeArg as PrismaAttributeArg,
Expand All @@ -62,8 +66,6 @@ import {
PassThroughAttribute as PrismaPassThroughAttribute,
SimpleField,
} from './prisma-builder';
import { ZModelCodeGenerator } from '@zenstackhq/sdk';
import { getPackageJson } from '../../utils/pkg-utils';

const MODEL_PASSTHROUGH_ATTR = '@@prisma.passthrough';
const FIELD_PASSTHROUGH_ATTR = '@prisma.passthrough';
Expand Down Expand Up @@ -377,10 +379,15 @@ export default class PrismaSchemaGenerator {
return new PrismaFunctionCall(
resolved(node.function).name,
node.args.map((arg) => {
if (!isLiteralExpr(arg.value)) {
throw new PluginError(name, 'Function call argument must be literal');
}
return new PrismaFunctionCallArg(arg.name, arg.value.value);
const val = match(arg.value)
.when(isStringLiteral, (v) => `"${v.value}"`)
.when(isLiteralExpr, (v) => v.value.toString())
.when(isNullExpr, () => 'null')
.otherwise(() => {
throw new PluginError(name, 'Function call argument must be literal or null');
});

return new PrismaFunctionCallArg(arg.name, val);
})
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/tests/generator/prisma-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('Prisma Builder Tests', () => {
undefined,
new AttributeArgValue(
'FunctionCall',
new FunctionCall('dbgenerated', [new FunctionCallArg(undefined, 'timestamp_id()')])
new FunctionCall('dbgenerated', [new FunctionCallArg(undefined, '"timestamp_id()"')])
)
),
]),
Expand Down
32 changes: 32 additions & 0 deletions packages/schema/tests/generator/prisma-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,38 @@ describe('Prisma generator test', () => {
expect(content).toContain('unsupported Unsupported("foo")');
});

it('attribute function', async () => {
const model = await loadModel(`
datasource db {
provider = 'postgresql'
url = env('DATABASE_URL')
}
model User {
id String @id @default(nanoid(6))
x String @default(nanoid())
y String @default(dbgenerated("gen_random_uuid()"))
}
`);

const { name } = tmp.fileSync({ postfix: '.prisma' });
await new PrismaSchemaGenerator().generate(model, {
name: 'Prisma',
provider: '@core/prisma',
schemaPath: 'schema.zmodel',
output: name,
generateClient: false,
});

const content = fs.readFileSync(name, 'utf-8');
// "nanoid()" is only available in later versions of Prisma
await getDMMF({ datamodel: content }, '5.0.0');

expect(content).toContain('@default(nanoid(6))');
expect(content).toContain('@default(nanoid())');
expect(content).toContain('@default(dbgenerated("gen_random_uuid()"))');
});

it('triple slash comments', async () => {
const model = await loadModel(`
datasource db {
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/src/prisma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ export type GetDMMFOptions = {
/**
* Loads Prisma DMMF with appropriate version
*/
export function getDMMF(options: GetDMMFOptions): Promise<DMMF.Document> {
const prismaVersion = getPrismaVersion();
export function getDMMF(options: GetDMMFOptions, defaultPrismaVersion?: string): Promise<DMMF.Document> {
const prismaVersion = getPrismaVersion() ?? defaultPrismaVersion;
if (prismaVersion && semver.gte(prismaVersion, '5.0.0')) {
const _getDMMF = require('@prisma/internals-v5').getDMMF;
return _getDMMF(options);
Expand Down

0 comments on commit 91fe8e7

Please sign in to comment.