Skip to content

Commit be3f72f

Browse files
committed
refactor enhancer generation logic
1 parent 85f8e1c commit be3f72f

File tree

3 files changed

+461
-189
lines changed

3 files changed

+461
-189
lines changed

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

Lines changed: 103 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { DELEGATE_AUX_RELATION_PREFIX } from '@zenstackhq/runtime';
2+
import { invariant, upperCaseFirst } from '@zenstackhq/runtime/local-helpers';
23
import {
34
PluginError,
45
getAttribute,
@@ -26,7 +27,6 @@ import {
2627
type Model,
2728
} from '@zenstackhq/sdk/ast';
2829
import { getDMMF, getPrismaClientImportSpec, getPrismaVersion, type DMMF } from '@zenstackhq/sdk/prisma';
29-
import { invariant, upperCaseFirst } from '@zenstackhq/runtime/local-helpers';
3030
import fs from 'fs';
3131
import path from 'path';
3232
import semver from 'semver';
@@ -105,56 +105,122 @@ export class EnhancerGenerator {
105105
}
106106

107107
async generate(): Promise<{ dmmf: DMMF.Document | undefined; newPrismaClientDtsPath: string | undefined }> {
108-
let dmmf: DMMF.Document | undefined;
108+
if (this.isNewPrismaClientGenerator) {
109+
// "prisma-client" generator
110+
return this.generateForNewClientGenerator();
111+
} else {
112+
// "prisma-client-js" generator
113+
return this.generateForOldClientGenerator();
114+
}
115+
}
109116

117+
// logic for "prisma-client" generator
118+
private async generateForNewClientGenerator() {
119+
const needsLogicalClient = this.needsLogicalClient;
110120
const prismaImport = getPrismaClientImportSpec(this.outDir, this.options);
111-
let prismaTypesFixed = false;
112-
let resultPrismaBaseImport = prismaImport;
113-
let resultPrismaClientImport = prismaImport;
121+
let resultPrismaBaseImport = path.dirname(prismaImport); // get to the parent folder of "client"
122+
let dmmf: DMMF.Document | undefined;
114123

115-
if (this.needsLogicalClient) {
116-
prismaTypesFixed = true;
124+
if (needsLogicalClient) {
125+
// use logical client, note we use the parent of "client" folder here too
117126
resultPrismaBaseImport = LOGICAL_CLIENT_GENERATION_PATH;
118-
if (this.isNewPrismaClientGenerator) {
119-
resultPrismaClientImport = `${LOGICAL_CLIENT_GENERATION_PATH}/client`;
120-
}
121127
const result = await this.generateLogicalPrisma();
122128
dmmf = result.dmmf;
123129
}
124130

125-
const modelsTsContent = this.isNewPrismaClientGenerator
126-
? `export * from '${resultPrismaBaseImport}/models';\nexport * from './json-types';`
127-
: `export * from '${resultPrismaBaseImport}';`;
128-
131+
// `models.ts` for exporting model types
132+
const modelsTsContent = [
133+
`export * from '${resultPrismaBaseImport}/models';`,
134+
`export * from './json-types';`,
135+
].join('\n');
129136
const modelsTs = this.project.createSourceFile(path.join(this.outDir, 'models.ts'), modelsTsContent, {
130137
overwrite: true,
131138
});
132139
this.saveSourceFile(modelsTs);
133140

134-
if (this.isNewPrismaClientGenerator) {
135-
const enumsTs = this.project.createSourceFile(path.join(this.outDir, 'enums.ts'), `export * from '${resultPrismaBaseImport}/enums';`, {
141+
// `enums.ts` for exporting enums
142+
const enumsTs = this.project.createSourceFile(
143+
path.join(this.outDir, 'enums.ts'),
144+
`export * from '${resultPrismaBaseImport}/enums';`,
145+
{
136146
overwrite: true,
137-
});
138-
this.saveSourceFile(enumsTs);
147+
}
148+
);
149+
this.saveSourceFile(enumsTs);
139150

140-
const clientTs = this.project.createSourceFile(path.join(this.outDir, 'client.ts'), `export * from '${resultPrismaClientImport}';`, {
151+
// `client.ts` for exporting `PrismaClient` and `Prisma` namespace
152+
const clientTs = this.project.createSourceFile(
153+
path.join(this.outDir, 'client.ts'),
154+
`export * from '${resultPrismaBaseImport}/client';`,
155+
{
141156
overwrite: true,
142-
});
143-
this.saveSourceFile(clientTs);
157+
}
158+
);
159+
this.saveSourceFile(clientTs);
160+
161+
// `enhance.ts` and `enhance-edge.ts`
162+
for (const target of ['node', 'edge'] as const) {
163+
this.generateEnhance(prismaImport, `${resultPrismaBaseImport}/client`, needsLogicalClient, target);
144164
}
145165

166+
return {
167+
// logical dmmf if there is one
168+
dmmf,
169+
// new client generator doesn't have a barrel .d.ts file
170+
newPrismaClientDtsPath: undefined,
171+
};
172+
}
173+
174+
// logic for "prisma-client-js" generator
175+
private async generateForOldClientGenerator() {
176+
const needsLogicalClient = this.needsLogicalClient;
177+
const prismaImport = getPrismaClientImportSpec(this.outDir, this.options);
178+
let resultPrismaClientImport = prismaImport;
179+
let dmmf: DMMF.Document | undefined;
180+
181+
if (needsLogicalClient) {
182+
// redirect `PrismaClient` import to the logical client
183+
resultPrismaClientImport = LOGICAL_CLIENT_GENERATION_PATH;
184+
const result = await this.generateLogicalPrisma();
185+
dmmf = result.dmmf;
186+
}
187+
188+
// `models.ts` for exporting model types
189+
const modelsTsContent = `export * from '${resultPrismaClientImport}';`;
190+
const modelsTs = this.project.createSourceFile(path.join(this.outDir, 'models.ts'), modelsTsContent, {
191+
overwrite: true,
192+
});
193+
this.saveSourceFile(modelsTs);
194+
195+
// `enhance.ts` and `enhance-edge.ts`
196+
for (const target of ['node', 'edge'] as const) {
197+
this.generateEnhance(prismaImport, resultPrismaClientImport, needsLogicalClient, target);
198+
}
199+
200+
return {
201+
// logical dmmf if there is one
202+
dmmf,
203+
newPrismaClientDtsPath: needsLogicalClient
204+
? path.resolve(this.outDir, LOGICAL_CLIENT_GENERATION_PATH, 'index.d.ts')
205+
: undefined,
206+
};
207+
}
208+
209+
private generateEnhance(
210+
prismaImport: string,
211+
prismaClientImport: string,
212+
needsLogicalClient: boolean,
213+
target: 'node' | 'edge'
214+
) {
146215
const authDecl = getAuthDecl(getDataModelAndTypeDefs(this.model));
147216
const authTypes = authDecl ? generateAuthType(this.model, authDecl) : '';
148217
const authTypeParam = authDecl ? `auth.${authDecl.name}` : 'AuthUser';
149-
150218
const checkerTypes = this.generatePermissionChecker ? generateCheckerType(this.model) : '';
151219

152-
for (const target of ['node', 'edge']) {
153-
// generate separate `enhance()` for node and edge runtime
154-
const outFile = target === 'node' ? 'enhance.ts' : 'enhance-edge.ts';
155-
const enhanceTs = this.project.createSourceFile(
156-
path.join(this.outDir, outFile),
157-
`/* eslint-disable */
220+
const outFile = target === 'node' ? 'enhance.ts' : 'enhance-edge.ts';
221+
const enhanceTs = this.project.createSourceFile(
222+
path.join(this.outDir, outFile),
223+
`/* eslint-disable */
158224
import { type EnhancementContext, type EnhancementOptions, type ZodSchemas, type AuthUser } from '@zenstackhq/runtime';
159225
import { createEnhancement } from '@zenstackhq/runtime/enhancements/${target}';
160226
import modelMeta from './model-meta';
@@ -166,8 +232,8 @@ ${
166232
}
167233
168234
${
169-
prismaTypesFixed
170-
? this.createLogicalPrismaImports(prismaImport, resultPrismaClientImport, target)
235+
needsLogicalClient
236+
? this.createLogicalPrismaImports(prismaImport, prismaClientImport, target)
171237
: this.createSimplePrismaImports(prismaImport, target)
172238
}
173239
@@ -176,23 +242,15 @@ ${authTypes}
176242
${checkerTypes}
177243
178244
${
179-
prismaTypesFixed
245+
needsLogicalClient
180246
? this.createLogicalPrismaEnhanceFunction(authTypeParam)
181247
: this.createSimplePrismaEnhanceFunction(authTypeParam)
182248
}
183249
`,
184-
{ overwrite: true }
185-
);
186-
187-
this.saveSourceFile(enhanceTs);
188-
}
250+
{ overwrite: true }
251+
);
189252

190-
return {
191-
dmmf,
192-
newPrismaClientDtsPath: prismaTypesFixed
193-
? path.resolve(this.outDir, LOGICAL_CLIENT_GENERATION_PATH, 'index.d.ts')
194-
: undefined,
195-
};
253+
this.saveSourceFile(enhanceTs);
196254
}
197255

198256
private getZodImport() {
@@ -222,7 +280,7 @@ ${
222280
return normalizedRelative(this.outDir, zodAbsPath);
223281
}
224282

225-
private createSimplePrismaImports(prismaImport: string, target: string) {
283+
private createSimplePrismaImports(prismaImport: string, target: string | undefined) {
226284
const prismaTargetImport = target === 'edge' ? `${prismaImport}/edge` : prismaImport;
227285

228286
return `import { Prisma, type PrismaClient } from '${prismaTargetImport}';
@@ -253,10 +311,10 @@ export function enhance<DbClient extends object>(prisma: DbClient, context?: Enh
253311
`;
254312
}
255313

256-
private createLogicalPrismaImports(prismaImport: string, prismaClientImport: string, target: string) {
314+
private createLogicalPrismaImports(prismaImport: string, prismaClientImport: string, target: string | undefined) {
257315
const prismaTargetImport = target === 'edge' ? `${prismaImport}/edge` : prismaImport;
258316
const runtimeLibraryImport = this.isNewPrismaClientGenerator
259-
? // new generator has these typed only in "@prisma/client"
317+
? // new generator has these types only in "@prisma/client"
260318
'@prisma/client/runtime/library'
261319
: // old generator has these types generated with the client
262320
`${prismaImport}/runtime/library`;

0 commit comments

Comments
 (0)