Skip to content

Commit 2d43692

Browse files
authored
feat: Support multiple levels inheritance (#863)
1 parent 0ca4670 commit 2d43692

File tree

4 files changed

+113
-12
lines changed

4 files changed

+113
-12
lines changed

packages/schema/src/language-server/zmodel-scope.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,31 @@ export class ZModelScopeComputation extends DefaultScopeComputation {
7373
if (decl.$type === 'DataModel') {
7474
const dataModel = decl as DataModel;
7575
dataModel.$resolvedFields = [...dataModel.fields];
76-
dataModel.superTypes.forEach((superType) => {
77-
const superTypeDecl = superType.ref;
78-
if (superTypeDecl) {
79-
superTypeDecl.fields.forEach((field) => {
80-
const cloneField = Object.assign({}, field);
81-
cloneField.$isInherited = true;
82-
const mutable = cloneField as Mutable<AstNode>;
83-
// update container
84-
mutable.$container = dataModel;
85-
dataModel.$resolvedFields.push(cloneField);
86-
});
87-
}
76+
this.getRecursiveSuperTypes(dataModel).forEach((superType) => {
77+
superType.fields.forEach((field) => {
78+
const cloneField = Object.assign({}, field);
79+
cloneField.$isInherited = true;
80+
const mutable = cloneField as Mutable<AstNode>;
81+
// update container
82+
mutable.$container = dataModel;
83+
dataModel.$resolvedFields.push(cloneField);
84+
});
8885
});
8986
}
9087
});
9188
}
89+
90+
private getRecursiveSuperTypes(dataModel: DataModel): DataModel[] {
91+
const result: DataModel[] = [];
92+
dataModel.superTypes.forEach((superType) => {
93+
const superTypeDecl = superType.ref;
94+
if (superTypeDecl) {
95+
result.push(superTypeDecl);
96+
result.push(...this.getRecursiveSuperTypes(superTypeDecl));
97+
}
98+
});
99+
return result;
100+
}
92101
}
93102

94103
export class ZModelScopeProvider extends DefaultScopeProvider {

packages/schema/tests/generator/prisma-generator.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,46 @@ describe('Prisma generator test', () => {
355355
expect(todo?.documentation?.replace(/\s/g, '')).toBe(`@@allow('read', owner == auth())`.replace(/\s/g, ''));
356356
});
357357

358+
it('multiple level inheritance', async () => {
359+
const model = await loadModel(`
360+
datasource db {
361+
provider = 'postgresql'
362+
url = env('URL')
363+
}
364+
365+
abstract model Base {
366+
id String @id @default(cuid())
367+
368+
createdAt DateTime @default(now())
369+
updatedAt DateTime @updatedAt
370+
}
371+
372+
abstract model BaseDeletable extends Base {
373+
deleted Boolean @default(false) @omit
374+
375+
@@deny('read', deleted)
376+
}
377+
378+
model Test1 extends BaseDeletable {
379+
@@allow('all', true)
380+
}
381+
`);
382+
383+
const { name } = tmp.fileSync({ postfix: '.prisma' });
384+
await new PrismaSchemaGenerator().generate(model, {
385+
name: 'Prisma',
386+
provider: '@core/prisma',
387+
schemaPath: 'schema.zmodel',
388+
output: name,
389+
format: true,
390+
});
391+
392+
const content = fs.readFileSync(name, 'utf-8');
393+
const expected = fs.readFileSync(path.join(__dirname, './prisma/multi-level-inheritance.prisma'), 'utf-8');
394+
395+
expect(content).toBe(expected);
396+
});
397+
358398
it('format prisma', async () => {
359399
const model = await loadModel(`
360400
datasource db {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////////
2+
// DO NOT MODIFY THIS FILE //
3+
// This file is automatically generated by ZenStack CLI and should not be manually updated. //
4+
//////////////////////////////////////////////////////////////////////////////////////////////
5+
6+
datasource db {
7+
provider = "postgresql"
8+
url = env("URL")
9+
}
10+
11+
/// @@deny('read', deleted)
12+
/// @@allow('all', true)
13+
model Test1 {
14+
id String @id() @default(cuid())
15+
createdAt DateTime @default(now())
16+
updatedAt DateTime @updatedAt()
17+
/// @omit
18+
deleted Boolean @default(false)
19+
}

packages/schema/tests/schema/abstract.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,37 @@ describe('Abstract Schema Tests', () => {
2828
model Foo extends Base {}
2929
`);
3030
});
31+
32+
it('multiple level inheritance', async () => {
33+
await loadModel(`
34+
datasource db {
35+
provider = 'postgresql'
36+
url = env('DATABASE_URL')
37+
}
38+
39+
generator js {
40+
provider = 'prisma-client-js'
41+
}
42+
43+
abstract model Base1 {
44+
id String @id @default(cuid())
45+
}
46+
47+
abstract model Base2 extends Base1 {
48+
fieldA String
49+
}
50+
51+
model A extends Base2 {
52+
field String
53+
b B[]
54+
}
55+
56+
model B {
57+
id String @id @default(cuid())
58+
a A @relation(fields: [aId], references: [id])
59+
aId String
60+
}
61+
62+
`);
63+
});
3164
});

0 commit comments

Comments
 (0)