From 127e94735409d3f9d3ab60e2ce1fb0a3e9cd8aa3 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:00:58 -0800 Subject: [PATCH 1/4] fix: ts schema generation for ignored models and fields --- packages/sdk/src/ts-schema-generator.ts | 26 +++++++++++++++-------- tests/e2e/orm/client-api/ignore.test.ts | 26 +++++++++++++++++++++++ tests/e2e/orm/schemas/basic/schema.zmodel | 25 ++++++++++++++-------- 3 files changed, 59 insertions(+), 18 deletions(-) create mode 100644 tests/e2e/orm/client-api/ignore.test.ts diff --git a/packages/sdk/src/ts-schema-generator.ts b/packages/sdk/src/ts-schema-generator.ts index 7a62e757..62c5efe5 100644 --- a/packages/sdk/src/ts-schema-generator.ts +++ b/packages/sdk/src/ts-schema-generator.ts @@ -296,18 +296,26 @@ export class TsSchemaGenerator { private createModelsObject(model: Model, lite: boolean): ts.Expression { return ts.factory.createObjectLiteralExpression( - model.declarations - .filter((d): d is DataModel => isDataModel(d) && !hasAttribute(d, '@@ignore')) - .map((dm) => ts.factory.createPropertyAssignment(dm.name, this.createDataModelObject(dm, lite))), + this.getAllDataModels(model).map((dm) => + ts.factory.createPropertyAssignment(dm.name, this.createDataModelObject(dm, lite)), + ), true, ); } + private getAllDataModels(model: Model) { + return model.declarations.filter((d): d is DataModel => isDataModel(d) && !hasAttribute(d, '@@ignore')); + } + + private getAllTypeDefs(model: Model) { + return model.declarations.filter((d): d is TypeDef => isTypeDef(d) && !hasAttribute(d, '@@ignore')); + } + private createTypeDefsObject(model: Model, lite: boolean): ts.Expression { return ts.factory.createObjectLiteralExpression( - model.declarations - .filter((d): d is TypeDef => isTypeDef(d)) - .map((td) => ts.factory.createPropertyAssignment(td.name, this.createTypeDefObject(td, lite))), + this.getAllTypeDefs(model).map((td) => + ts.factory.createPropertyAssignment(td.name, this.createTypeDefObject(td, lite)), + ), true, ); } @@ -1337,7 +1345,7 @@ export class TsSchemaGenerator { ); // generate: export type Model = $ModelResult; - const dataModels = model.declarations.filter(isDataModel); + const dataModels = this.getAllDataModels(model); for (const dm of dataModels) { let modelType = ts.factory.createTypeAliasDeclaration( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], @@ -1355,7 +1363,7 @@ export class TsSchemaGenerator { } // generate: export type TypeDef = $TypeDefResult; - const typeDefs = model.declarations.filter(isTypeDef); + const typeDefs = this.getAllTypeDefs(model); for (const td of typeDefs) { let typeDef = ts.factory.createTypeAliasDeclaration( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], @@ -1492,7 +1500,7 @@ export class TsSchemaGenerator { } private generateInputTypes(model: Model, options: TsSchemaGeneratorOptions) { - const dataModels = model.declarations.filter(isDataModel); + const dataModels = this.getAllDataModels(model); const statements: ts.Statement[] = []; // generate: import { SchemaType as $Schema } from './schema'; diff --git a/tests/e2e/orm/client-api/ignore.test.ts b/tests/e2e/orm/client-api/ignore.test.ts new file mode 100644 index 00000000..112b7065 --- /dev/null +++ b/tests/e2e/orm/client-api/ignore.test.ts @@ -0,0 +1,26 @@ +import { createTestClient } from '@zenstackhq/testtools'; +import { describe, it } from 'vitest'; +import { schema } from '../schemas/basic'; +import type { DefaultModelResult } from '@zenstackhq/orm'; + +describe('Ignored models and fields test', () => { + it('correctly ignores fields', async () => { + const db = await createTestClient(schema); + db.user.findFirst({ + // @ts-expect-error + where: { password: 'abc' }, + }); + + const u: DefaultModelResult = {} as any; + // @ts-expect-error + noop(u.password); + }); + + it('correctly ignore models', async () => { + const db = createTestClient(schema); + // @ts-expect-error + db.foo.findFirst(); + }); +}); + +function noop(_value: unknown) {} diff --git a/tests/e2e/orm/schemas/basic/schema.zmodel b/tests/e2e/orm/schemas/basic/schema.zmodel index d3ace0a1..e6e2832b 100644 --- a/tests/e2e/orm/schemas/basic/schema.zmodel +++ b/tests/e2e/orm/schemas/basic/schema.zmodel @@ -19,12 +19,13 @@ type CommonFields { } model User with CommonFields { - email String @unique - name String? - role Role @default(USER) - posts Post[] - profile Profile? - meta Json? + email String @unique + name String? + password String @ignore + role Role @default(USER) + posts Post[] + profile Profile? + meta Json? // Access policies @@allow('all', auth().id == id) @@ -46,9 +47,9 @@ model Post with CommonFields { } model Comment with CommonFields { - content String - post Post? @relation(fields: [postId], references: [id], onUpdate: Cascade, onDelete: Cascade) - postId String? + content String + post Post? @relation(fields: [postId], references: [id], onUpdate: Cascade, onDelete: Cascade) + postId String? } model Profile with CommonFields { @@ -57,3 +58,9 @@ model Profile with CommonFields { user User? @relation(fields: [userId], references: [id], onUpdate: Cascade, onDelete: Cascade) userId String? @unique } + +model Foo { + id String @id + @@ignore +} + From 91f0216b197cf7243f8c9c855ebda7c65e26615d Mon Sep 17 00:00:00 2001 From: Yiming Cao Date: Tue, 25 Nov 2025 18:07:22 -0800 Subject: [PATCH 2/4] Update tests/e2e/orm/client-api/ignore.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/e2e/orm/client-api/ignore.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/orm/client-api/ignore.test.ts b/tests/e2e/orm/client-api/ignore.test.ts index 112b7065..40a22856 100644 --- a/tests/e2e/orm/client-api/ignore.test.ts +++ b/tests/e2e/orm/client-api/ignore.test.ts @@ -17,7 +17,7 @@ describe('Ignored models and fields test', () => { }); it('correctly ignore models', async () => { - const db = createTestClient(schema); + const db = await createTestClient(schema); // @ts-expect-error db.foo.findFirst(); }); From 80fdae4c5cce9e05439ccd25f195fb8ead02869d Mon Sep 17 00:00:00 2001 From: Yiming Cao Date: Tue, 25 Nov 2025 18:07:38 -0800 Subject: [PATCH 3/4] Update tests/e2e/orm/client-api/ignore.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/e2e/orm/client-api/ignore.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/orm/client-api/ignore.test.ts b/tests/e2e/orm/client-api/ignore.test.ts index 40a22856..46815885 100644 --- a/tests/e2e/orm/client-api/ignore.test.ts +++ b/tests/e2e/orm/client-api/ignore.test.ts @@ -16,7 +16,7 @@ describe('Ignored models and fields test', () => { noop(u.password); }); - it('correctly ignore models', async () => { + it('correctly ignores models', async () => { const db = await createTestClient(schema); // @ts-expect-error db.foo.findFirst(); From b91ae3bd827102a6276dee53fd094ac3961db1a1 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:17:05 -0800 Subject: [PATCH 4/4] fix test --- tests/e2e/orm/client-api/ignore.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/e2e/orm/client-api/ignore.test.ts b/tests/e2e/orm/client-api/ignore.test.ts index 112b7065..24f342b8 100644 --- a/tests/e2e/orm/client-api/ignore.test.ts +++ b/tests/e2e/orm/client-api/ignore.test.ts @@ -1,7 +1,7 @@ +import type { DefaultModelResult } from '@zenstackhq/orm'; import { createTestClient } from '@zenstackhq/testtools'; -import { describe, it } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { schema } from '../schemas/basic'; -import type { DefaultModelResult } from '@zenstackhq/orm'; describe('Ignored models and fields test', () => { it('correctly ignores fields', async () => { @@ -11,6 +11,10 @@ describe('Ignored models and fields test', () => { where: { password: 'abc' }, }); + const user = await db.user.create({ data: { email: 'u1@test.com' } }); + // @ts-expect-error + expect(user.password).toBeUndefined(); + const u: DefaultModelResult = {} as any; // @ts-expect-error noop(u.password); @@ -19,7 +23,7 @@ describe('Ignored models and fields test', () => { it('correctly ignore models', async () => { const db = createTestClient(schema); // @ts-expect-error - db.foo.findFirst(); + expect(db.foo).toBeUndefined(); }); });