Skip to content

Commit 153dd4f

Browse files
authored
fix(delegate): several generation issues (#1417)
1 parent 00250ea commit 153dd4f

File tree

4 files changed

+110
-41
lines changed

4 files changed

+110
-41
lines changed

packages/schema/src/plugins/enhancer/enhance/index.ts

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -214,54 +214,59 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara
214214

215215
// calculate a relative output path to output the logical prisma client into enhancer's output dir
216216
const prismaClientOutDir = path.join(path.relative(zmodelDir, this.outDir), LOGICAL_CLIENT_GENERATION_PATH);
217-
try {
218-
await prismaGenerator.generate({
219-
provider: '@internal', // doesn't matter
220-
schemaPath: this.options.schemaPath,
221-
output: logicalPrismaFile,
222-
overrideClientGenerationPath: prismaClientOutDir,
223-
mode: 'logical',
224-
});
217+
await prismaGenerator.generate({
218+
provider: '@internal', // doesn't matter
219+
schemaPath: this.options.schemaPath,
220+
output: logicalPrismaFile,
221+
overrideClientGenerationPath: prismaClientOutDir,
222+
mode: 'logical',
223+
});
225224

226-
// generate the prisma client
225+
// generate the prisma client
227226

228-
// only run prisma client generator for the logical schema
229-
const prismaClientGeneratorName = this.getPrismaClientGeneratorName(this.model);
230-
let generateCmd = `prisma generate --schema "${logicalPrismaFile}" --generator=${prismaClientGeneratorName}`;
227+
// only run prisma client generator for the logical schema
228+
const prismaClientGeneratorName = this.getPrismaClientGeneratorName(this.model);
229+
let generateCmd = `prisma generate --schema "${logicalPrismaFile}" --generator=${prismaClientGeneratorName}`;
231230

232-
const prismaVersion = getPrismaVersion();
233-
if (!prismaVersion || semver.gte(prismaVersion, '5.2.0')) {
234-
// add --no-engine to reduce generation size if the prisma version supports
235-
generateCmd += ' --no-engine';
236-
}
231+
const prismaVersion = getPrismaVersion();
232+
if (!prismaVersion || semver.gte(prismaVersion, '5.2.0')) {
233+
// add --no-engine to reduce generation size if the prisma version supports
234+
generateCmd += ' --no-engine';
235+
}
237236

237+
try {
238+
// run 'prisma generate'
239+
await execPackage(generateCmd, { stdio: 'ignore' });
240+
} catch {
241+
await trackPrismaSchemaError(logicalPrismaFile);
238242
try {
239-
// run 'prisma generate'
240-
await execPackage(generateCmd, { stdio: 'ignore' });
243+
// run 'prisma generate' again with output to the console
244+
await execPackage(generateCmd);
241245
} catch {
242-
await trackPrismaSchemaError(logicalPrismaFile);
243-
try {
244-
// run 'prisma generate' again with output to the console
245-
await execPackage(generateCmd);
246-
} catch {
247-
// noop
248-
}
249-
throw new PluginError(name, `Failed to run "prisma generate" on logical schema: ${logicalPrismaFile}`);
246+
// noop
250247
}
248+
throw new PluginError(name, `Failed to run "prisma generate" on logical schema: ${logicalPrismaFile}`);
249+
}
250+
251+
// make a bunch of typing fixes to the generated prisma client
252+
await this.processClientTypes(path.join(this.outDir, LOGICAL_CLIENT_GENERATION_PATH));
251253

252-
// make a bunch of typing fixes to the generated prisma client
253-
await this.processClientTypes(path.join(this.outDir, LOGICAL_CLIENT_GENERATION_PATH));
254+
const dmmf = await getDMMF({ datamodel: fs.readFileSync(logicalPrismaFile, { encoding: 'utf-8' }) });
254255

255-
return {
256-
prismaSchema: logicalPrismaFile,
257-
// load the dmmf of the logical prisma schema
258-
dmmf: await getDMMF({ datamodel: fs.readFileSync(logicalPrismaFile, { encoding: 'utf-8' }) }),
259-
};
260-
} finally {
256+
try {
257+
// clean up temp schema
261258
if (fs.existsSync(logicalPrismaFile)) {
262259
fs.rmSync(logicalPrismaFile);
263260
}
261+
} catch {
262+
// ignore errors
264263
}
264+
265+
return {
266+
prismaSchema: logicalPrismaFile,
267+
// load the dmmf of the logical prisma schema
268+
dmmf,
269+
};
265270
}
266271

267272
private getPrismaClientGeneratorName(model: Model) {
@@ -287,12 +292,12 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara
287292
this.model.declarations
288293
.filter((d): d is DataModel => isDelegateModel(d))
289294
.forEach((dm) => {
290-
delegateInfo.push([
291-
dm,
292-
this.model.declarations.filter(
293-
(d): d is DataModel => isDataModel(d) && d.superTypes.some((s) => s.ref === dm)
294-
),
295-
]);
295+
const concreteModels = this.model.declarations.filter(
296+
(d): d is DataModel => isDataModel(d) && d.superTypes.some((s) => s.ref === dm)
297+
);
298+
if (concreteModels.length > 0) {
299+
delegateInfo.push([dm, concreteModels]);
300+
}
296301
});
297302

298303
// transform index.d.ts and save it into a new file (better perf than in-line editing)

packages/schema/src/plugins/prisma/schema-generator.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,11 @@ export class PrismaSchemaGenerator {
374374
// for the given model, find relation fields of delegate model type, find all concrete models
375375
// of the delegate model and generate an auxiliary opposite relation field to each of them
376376
decl.fields.forEach((f) => {
377+
// don't process fields inherited from a delegate model
378+
if (f.$inheritedFrom && isDelegateModel(f.$inheritedFrom)) {
379+
return;
380+
}
381+
377382
const fieldType = f.type.reference?.ref;
378383
if (!isDataModel(fieldType)) {
379384
return;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1415', () => {
4+
it('regression', async () => {
5+
await loadSchema(
6+
`
7+
model User {
8+
id String @id @default(cuid())
9+
prices Price[]
10+
}
11+
12+
model Price {
13+
id String @id @default(cuid())
14+
owner User @relation(fields: [ownerId], references: [id])
15+
ownerId String @default(auth().id)
16+
priceType String
17+
@@delegate(priceType)
18+
}
19+
`
20+
);
21+
});
22+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1416', () => {
4+
it('regression', async () => {
5+
await loadSchema(
6+
`
7+
model User {
8+
id String @id @default(cuid())
9+
role String
10+
}
11+
12+
model Price {
13+
id String @id @default(nanoid(6))
14+
entity Entity? @relation(fields: [entityId], references: [id])
15+
entityId String?
16+
priceType String
17+
@@delegate(priceType)
18+
}
19+
20+
model MyPrice extends Price {
21+
foo String
22+
}
23+
24+
model Entity {
25+
id String @id @default(nanoid(6))
26+
price Price[]
27+
type String
28+
@@delegate(type)
29+
}
30+
31+
model MyEntity extends Entity {
32+
foo String
33+
}
34+
`
35+
);
36+
});
37+
});

0 commit comments

Comments
 (0)