Skip to content

Commit 2017e62

Browse files
committed
fix(delegate): don't generate both "@@Schema" attributes from base and sub models
1 parent 3ee50d3 commit 2017e62

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ import {
1616
ModelImport,
1717
TypeDef,
1818
} from '@zenstackhq/language/ast';
19-
import { getAttribute, getInheritanceChain, getRecursiveBases, isDelegateModel, isFromStdlib } from '@zenstackhq/sdk';
19+
import {
20+
getAttribute,
21+
getInheritanceChain,
22+
getRecursiveBases,
23+
hasAttribute,
24+
isDelegateModel,
25+
isFromStdlib,
26+
} from '@zenstackhq/sdk';
2027
import {
2128
AstNode,
2229
copyAstNode,
@@ -96,6 +103,9 @@ function filterBaseAttribute(forModel: DataModel, base: DataModel, attr: DataMod
96103
// uninheritable attributes for delegate inheritance (they reference fields from the base)
97104
const uninheritableFromDelegateAttributes = ['@@unique', '@@index', '@@fulltext'];
98105

106+
// attributes that are inherited but can be overridden
107+
const overrideAttributes = ['@@schema'];
108+
99109
if (uninheritableAttributes.includes(attr.decl.$refText)) {
100110
return false;
101111
}
@@ -109,6 +119,11 @@ function filterBaseAttribute(forModel: DataModel, base: DataModel, attr: DataMod
109119
return false;
110120
}
111121

122+
if (hasAttribute(forModel, attr.decl.$refText) && overrideAttributes.includes(attr.decl.$refText)) {
123+
// don't inherit an attribute if it's overridden in the sub model
124+
return false;
125+
}
126+
112127
return true;
113128
}
114129

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
import fs from 'fs';
3+
4+
describe('issue 1647', () => {
5+
it('inherits @@schema by default', async () => {
6+
const { projectDir } = await loadSchema(
7+
`
8+
datasource db {
9+
provider = 'postgresql'
10+
url = env('DATABASE_URL')
11+
schemas = ['public', 'post']
12+
}
13+
14+
generator client {
15+
provider = 'prisma-client-js'
16+
previewFeatures = ['multiSchema']
17+
}
18+
19+
model Asset {
20+
id Int @id
21+
type String
22+
@@delegate(type)
23+
@@schema('public')
24+
}
25+
26+
model Post extends Asset {
27+
title String
28+
}
29+
`,
30+
{ addPrelude: false, pushDb: false, getPrismaOnly: true }
31+
);
32+
33+
const prismaSchema = fs.readFileSync(`${projectDir}/prisma/schema.prisma`, 'utf-8');
34+
expect(prismaSchema.split('\n').filter((l) => l.includes('@@schema("public")'))).toHaveLength(2);
35+
});
36+
it('respects sub model @@schema overrides', async () => {
37+
const { projectDir } = await loadSchema(
38+
`
39+
datasource db {
40+
provider = 'postgresql'
41+
url = env('DATABASE_URL')
42+
schemas = ['public', 'post']
43+
}
44+
45+
generator client {
46+
provider = 'prisma-client-js'
47+
previewFeatures = ['multiSchema']
48+
}
49+
50+
model Asset {
51+
id Int @id
52+
type String
53+
@@delegate(type)
54+
@@schema('public')
55+
}
56+
57+
model Post extends Asset {
58+
title String
59+
@@schema('post')
60+
}
61+
`,
62+
{ addPrelude: false, pushDb: false, getPrismaOnly: true }
63+
);
64+
65+
const prismaSchema = fs.readFileSync(`${projectDir}/prisma/schema.prisma`, 'utf-8');
66+
expect(prismaSchema.split('\n').filter((l) => l.includes('@@schema("public")'))).toHaveLength(1);
67+
expect(prismaSchema.split('\n').filter((l) => l.includes('@@schema("post")'))).toHaveLength(1);
68+
});
69+
});

0 commit comments

Comments
 (0)