Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(delegate): several generation issues #1417

Merged
merged 2 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 46 additions & 41 deletions packages/schema/src/plugins/enhancer/enhance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,54 +214,59 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara

// calculate a relative output path to output the logical prisma client into enhancer's output dir
const prismaClientOutDir = path.join(path.relative(zmodelDir, this.outDir), LOGICAL_CLIENT_GENERATION_PATH);
try {
await prismaGenerator.generate({
provider: '@internal', // doesn't matter
schemaPath: this.options.schemaPath,
output: logicalPrismaFile,
overrideClientGenerationPath: prismaClientOutDir,
mode: 'logical',
});
await prismaGenerator.generate({
provider: '@internal', // doesn't matter
schemaPath: this.options.schemaPath,
output: logicalPrismaFile,
overrideClientGenerationPath: prismaClientOutDir,
mode: 'logical',
});

// generate the prisma client
// generate the prisma client

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

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

try {
// run 'prisma generate'
await execPackage(generateCmd, { stdio: 'ignore' });
} catch {
await trackPrismaSchemaError(logicalPrismaFile);
try {
// run 'prisma generate'
await execPackage(generateCmd, { stdio: 'ignore' });
// run 'prisma generate' again with output to the console
await execPackage(generateCmd);
} catch {
await trackPrismaSchemaError(logicalPrismaFile);
try {
// run 'prisma generate' again with output to the console
await execPackage(generateCmd);
} catch {
// noop
}
throw new PluginError(name, `Failed to run "prisma generate" on logical schema: ${logicalPrismaFile}`);
// noop
}
throw new PluginError(name, `Failed to run "prisma generate" on logical schema: ${logicalPrismaFile}`);
}

// make a bunch of typing fixes to the generated prisma client
await this.processClientTypes(path.join(this.outDir, LOGICAL_CLIENT_GENERATION_PATH));

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

return {
prismaSchema: logicalPrismaFile,
// load the dmmf of the logical prisma schema
dmmf: await getDMMF({ datamodel: fs.readFileSync(logicalPrismaFile, { encoding: 'utf-8' }) }),
};
} finally {
try {
// clean up temp schema
if (fs.existsSync(logicalPrismaFile)) {
fs.rmSync(logicalPrismaFile);
}
} catch {
// ignore errors
}

return {
prismaSchema: logicalPrismaFile,
// load the dmmf of the logical prisma schema
dmmf,
};
}

private getPrismaClientGeneratorName(model: Model) {
Expand All @@ -287,12 +292,12 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara
this.model.declarations
.filter((d): d is DataModel => isDelegateModel(d))
.forEach((dm) => {
delegateInfo.push([
dm,
this.model.declarations.filter(
(d): d is DataModel => isDataModel(d) && d.superTypes.some((s) => s.ref === dm)
),
]);
const concreteModels = this.model.declarations.filter(
(d): d is DataModel => isDataModel(d) && d.superTypes.some((s) => s.ref === dm)
);
if (concreteModels.length > 0) {
delegateInfo.push([dm, concreteModels]);
}
});

// transform index.d.ts and save it into a new file (better perf than in-line editing)
Expand Down
5 changes: 5 additions & 0 deletions packages/schema/src/plugins/prisma/schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ export class PrismaSchemaGenerator {
// for the given model, find relation fields of delegate model type, find all concrete models
// of the delegate model and generate an auxiliary opposite relation field to each of them
decl.fields.forEach((f) => {
// don't process fields inherited from a delegate model
if (f.$inheritedFrom && isDelegateModel(f.$inheritedFrom)) {
return;
}

const fieldType = f.type.reference?.ref;
if (!isDataModel(fieldType)) {
return;
Expand Down
22 changes: 22 additions & 0 deletions tests/regression/tests/issue-1415.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { loadSchema } from '@zenstackhq/testtools';

describe('issue 1415', () => {
it('regression', async () => {
await loadSchema(
`
model User {
id String @id @default(cuid())
prices Price[]
}

model Price {
id String @id @default(cuid())
owner User @relation(fields: [ownerId], references: [id])
ownerId String @default(auth().id)
priceType String
@@delegate(priceType)
}
`
);
});
});
37 changes: 37 additions & 0 deletions tests/regression/tests/issue-1416.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { loadSchema } from '@zenstackhq/testtools';

describe('issue 1416', () => {
it('regression', async () => {
await loadSchema(
`
model User {
id String @id @default(cuid())
role String
}

model Price {
id String @id @default(nanoid(6))
entity Entity? @relation(fields: [entityId], references: [id])
entityId String?
priceType String
@@delegate(priceType)
}

model MyPrice extends Price {
foo String
}

model Entity {
id String @id @default(nanoid(6))
price Price[]
type String
@@delegate(type)
}

model MyEntity extends Entity {
foo String
}
`
);
});
});
Loading