From f494abdebecdcfb42198f9eb6bd13d889102a2a1 Mon Sep 17 00:00:00 2001 From: JG Date: Thu, 4 May 2023 21:20:33 +0100 Subject: [PATCH 1/4] feat: perverse blank in zmodel --- .../src/language-server/zmodel-formatter.ts | 4 ++-- .../schema/src/plugins/prisma/prisma-builder.ts | 16 +++++++++++++++- .../tests/generator/prisma-generator.test.ts | 4 ++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/schema/src/language-server/zmodel-formatter.ts b/packages/schema/src/language-server/zmodel-formatter.ts index c9300fa7a..3e3d1f018 100644 --- a/packages/schema/src/language-server/zmodel-formatter.ts +++ b/packages/schema/src/language-server/zmodel-formatter.ts @@ -25,8 +25,8 @@ export class ZModelFormatter extends AbstractFormatter { } else if (ast.isAbstractDeclaration(node)) { const bracesOpen = formatter.keyword('{'); const bracesClose = formatter.keyword('}'); - // this line decide the indent count return by this.getIndent() - formatter.interior(bracesOpen, bracesClose).prepend(Formatting.indent()); + // allow extra blank lines between declarations + formatter.interior(bracesOpen, bracesClose).prepend(Formatting.indent({ allowMore: true })); bracesOpen.prepend(Formatting.oneSpace()); bracesClose.prepend(Formatting.newLine()); } else if (ast.isModel(node)) { diff --git a/packages/schema/src/plugins/prisma/prisma-builder.ts b/packages/schema/src/plugins/prisma/prisma-builder.ts index 3ec0a47ca..7c8d5c357 100644 --- a/packages/schema/src/plugins/prisma/prisma-builder.ts +++ b/packages/schema/src/plugins/prisma/prisma-builder.ts @@ -1,3 +1,5 @@ +//import { AUXILIARY_FIELDS } from '@zenstackhq/sdk'; +import { AUXILIARY_FIELDS } from '@zenstackhq/sdk'; import indentString from './indent-string'; /** @@ -145,10 +147,22 @@ export class Model extends ContainerDeclaration { } toString(): string { + const auxiliaryFields = this.fields.filter((f) => AUXILIARY_FIELDS.includes(f.name)); + const result: any[] = this.fields.filter((f) => !AUXILIARY_FIELDS.includes(f.name)); + + if (auxiliaryFields.length > 0) { + // Add a blank line before the auxiliary fields + result.push('', ...auxiliaryFields); + if (this.attributes.length > 0) { + // Add a blank line before the attributes + result.push(''); + } + } + result.push(...this.attributes); return ( super.toString() + `model ${this.name} {\n` + - indentString([...this.fields, ...this.attributes].map((d) => d.toString()).join('\n')) + + indentString(result.map((d) => d.toString()).join('\n')) + `\n}` ); } diff --git a/packages/schema/tests/generator/prisma-generator.test.ts b/packages/schema/tests/generator/prisma-generator.test.ts index fc4bfe8de..a7bf05fb1 100644 --- a/packages/schema/tests/generator/prisma-generator.test.ts +++ b/packages/schema/tests/generator/prisma-generator.test.ts @@ -300,6 +300,10 @@ describe('Prisma generator test', () => { await getDMMF({ datamodel: content }); expect(content).toContain('@map("myGuardField")'); expect(content).toContain('@map("myTransactionField")'); + expect(content).toContain('value Int\n\n zenstack_guard'); + expect(content).toContain( + 'zenstack_transaction String? @map("myTransactionField")\n\n @@index([zenstack_transaction])' + ); }); it('abstract multi files', async () => { From 8990c93db2c7df12b95828ce1856431e2d8a4d4d Mon Sep 17 00:00:00 2001 From: JG Date: Thu, 4 May 2023 21:44:39 +0100 Subject: [PATCH 2/4] feat: support format generated prisma file --- .../src/plugins/prisma/schema-generator.ts | 5 ++++ .../tests/generator/prisma-generator.test.ts | 30 +++++++++++++++++++ .../tests/generator/prisma/format.prisma | 22 ++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 packages/schema/tests/generator/prisma/format.prisma diff --git a/packages/schema/src/plugins/prisma/schema-generator.ts b/packages/schema/src/plugins/prisma/schema-generator.ts index 5ddc9bd27..17a594377 100644 --- a/packages/schema/src/plugins/prisma/schema-generator.ts +++ b/packages/schema/src/plugins/prisma/schema-generator.ts @@ -100,6 +100,11 @@ export default class PrismaSchemaGenerator { } await writeFile(outFile, this.PRELUDE + prisma.toString()); + if (options.format === true) { + // run 'prisma format' + await execSync(`npx prisma format --schema ${outFile}`); + } + const generateClient = options.generateClient !== false; if (generateClient) { diff --git a/packages/schema/tests/generator/prisma-generator.test.ts b/packages/schema/tests/generator/prisma-generator.test.ts index a7bf05fb1..890fdf519 100644 --- a/packages/schema/tests/generator/prisma-generator.test.ts +++ b/packages/schema/tests/generator/prisma-generator.test.ts @@ -332,4 +332,34 @@ describe('Prisma generator test', () => { const todo = dmmf.datamodel.models.find((m) => m.name === 'Todo'); expect(todo?.documentation?.replace(/\s/g, '')).toBe(`@@allow('read', owner == auth())`.replace(/\s/g, '')); }); + + it('format prisma', async () => { + const model = await loadModel(` + datasource db { + provider = 'postgresql' + url = env('URL') + } + + model Post { + id Int @id() @default(autoincrement()) + title String + content String? + published Boolean @default(false) + @@allow('read', published) + } + `); + + const { name } = tmp.fileSync({ postfix: '.prisma' }); + await new PrismaSchemaGenerator().generate(model, { + provider: '@core/prisma', + schemaPath: 'schema.zmodel', + output: name, + format: true, + }); + + const content = fs.readFileSync(name, 'utf-8'); + const expected = fs.readFileSync(path.join(__dirname, './prisma/format.prisma'), 'utf-8'); + + expect(content).toBe(expected); + }); }); diff --git a/packages/schema/tests/generator/prisma/format.prisma b/packages/schema/tests/generator/prisma/format.prisma new file mode 100644 index 000000000..1eecb4978 --- /dev/null +++ b/packages/schema/tests/generator/prisma/format.prisma @@ -0,0 +1,22 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +datasource db { + provider = "postgresql" + url = env("URL") +} + +/// @@allow('read', published) +model Post { + id Int @id() @default(autoincrement()) + title String + content String? + published Boolean @default(false) + + zenstack_guard Boolean @default(true) + zenstack_transaction String? + + @@index([zenstack_transaction]) +} From 0cb1ac3f9e4018b47c234ff91236e0c01b65ad7a Mon Sep 17 00:00:00 2001 From: JG Date: Thu, 4 May 2023 21:48:16 +0100 Subject: [PATCH 3/4] remove unused comments --- packages/schema/src/plugins/prisma/prisma-builder.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/schema/src/plugins/prisma/prisma-builder.ts b/packages/schema/src/plugins/prisma/prisma-builder.ts index 7c8d5c357..7e5a5ee91 100644 --- a/packages/schema/src/plugins/prisma/prisma-builder.ts +++ b/packages/schema/src/plugins/prisma/prisma-builder.ts @@ -1,4 +1,3 @@ -//import { AUXILIARY_FIELDS } from '@zenstackhq/sdk'; import { AUXILIARY_FIELDS } from '@zenstackhq/sdk'; import indentString from './indent-string'; From c146012297c3d94a95964edbc30549da86c6127b Mon Sep 17 00:00:00 2001 From: JG Date: Thu, 4 May 2023 22:14:22 +0100 Subject: [PATCH 4/4] chore: disable warning --- packages/schema/src/plugins/prisma/prisma-builder.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/schema/src/plugins/prisma/prisma-builder.ts b/packages/schema/src/plugins/prisma/prisma-builder.ts index 7e5a5ee91..ae77b6948 100644 --- a/packages/schema/src/plugins/prisma/prisma-builder.ts +++ b/packages/schema/src/plugins/prisma/prisma-builder.ts @@ -147,6 +147,7 @@ export class Model extends ContainerDeclaration { toString(): string { const auxiliaryFields = this.fields.filter((f) => AUXILIARY_FIELDS.includes(f.name)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const result: any[] = this.fields.filter((f) => !AUXILIARY_FIELDS.includes(f.name)); if (auxiliaryFields.length > 0) {