55    getAttributeArg , 
66    getAuthModel , 
77    getDataModels , 
8+     getLiteral , 
89    isDelegateModel , 
910    type  PluginOptions , 
1011}  from  '@zenstackhq/sdk' ; 
@@ -14,12 +15,14 @@ import {
1415    ReferenceExpr , 
1516    isArrayExpr , 
1617    isDataModel , 
18+     isGeneratorDecl , 
1719    isReferenceExpr , 
1820    type  Model , 
1921}  from  '@zenstackhq/sdk/ast' ; 
20- import  {  getDMMF ,  getPrismaClientImportSpec ,  type  DMMF  }  from  '@zenstackhq/sdk/prisma' ; 
22+ import  {  getDMMF ,  getPrismaClientImportSpec ,  getPrismaVersion ,   type  DMMF  }  from  '@zenstackhq/sdk/prisma' ; 
2123import  fs  from  'fs' ; 
2224import  path  from  'path' ; 
25+ import  semver  from  'semver' ; 
2326import  { 
2427    FunctionDeclarationStructure , 
2528    InterfaceDeclaration , 
@@ -42,6 +45,8 @@ import { generateAuthType } from './auth-type-generator';
4245// information of delegate models and their sub models 
4346type  DelegateInfo  =  [ DataModel ,  DataModel [ ] ] [ ] ; 
4447
48+ const  LOGICAL_CLIENT_GENERATION_PATH  =  './.logical-prisma-client' ; 
49+ 
4550export  class  EnhancerGenerator  { 
4651    constructor ( 
4752        private  readonly  model : Model , 
@@ -60,7 +65,7 @@ export class EnhancerGenerator {
6065            // schema contains delegate models, need to generate a logical prisma schema 
6166            const  result  =  await  this . generateLogicalPrisma ( ) ; 
6267
63-             logicalPrismaClientDir  =  './.logical-prisma-client' ; 
68+             logicalPrismaClientDir  =  LOGICAL_CLIENT_GENERATION_PATH ; 
6469            dmmf  =  result . dmmf ; 
6570
6671            // create a reexport of the logical prisma client 
@@ -190,40 +195,76 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara
190195
191196    private  async  generateLogicalPrisma ( )  { 
192197        const  prismaGenerator  =  new  PrismaSchemaGenerator ( this . model ) ; 
193-         const  prismaClientOutDir  =  './.logical-prisma-client' ; 
194-         const  logicalPrismaFile  =  path . join ( this . outDir ,  'logical.prisma' ) ; 
195-         await  prismaGenerator . generate ( { 
196-             provider : '@internal' ,  // doesn't matter 
197-             schemaPath : this . options . schemaPath , 
198-             output : logicalPrismaFile , 
199-             overrideClientGenerationPath : prismaClientOutDir , 
200-             mode : 'logical' , 
201-         } ) ; 
202198
203-         // generate the prisma client 
204-         const  generateCmd  =  `prisma generate --schema "${ logicalPrismaFile }  ; 
199+         // dir of the zmodel file 
200+         const  zmodelDir  =  path . dirname ( this . options . schemaPath ) ; 
201+ 
202+         // generate a temp logical prisma schema in zmodel's dir 
203+         const  logicalPrismaFile  =  path . join ( zmodelDir ,  `logical-${ Date . now ( ) }  ) ; 
204+ 
205+         // calculate a relative output path to output the logical prisma client into enhancer's output dir 
206+         const  prismaClientOutDir  =  path . join ( path . relative ( zmodelDir ,  this . outDir ) ,  LOGICAL_CLIENT_GENERATION_PATH ) ; 
205207        try  { 
206-             // run 'prisma generate' 
207-             await  execPackage ( generateCmd ,  {  stdio : 'ignore'  } ) ; 
208-         }  catch  { 
209-             await  trackPrismaSchemaError ( logicalPrismaFile ) ; 
208+             await  prismaGenerator . generate ( { 
209+                 provider : '@internal' ,  // doesn't matter 
210+                 schemaPath : this . options . schemaPath , 
211+                 output : logicalPrismaFile , 
212+                 overrideClientGenerationPath : prismaClientOutDir , 
213+                 mode : 'logical' , 
214+             } ) ; 
215+ 
216+             // generate the prisma client 
217+ 
218+             // only run prisma client generator for the logical schema 
219+             const  prismaClientGeneratorName  =  this . getPrismaClientGeneratorName ( this . model ) ; 
220+             let  generateCmd  =  `prisma generate --schema "${ logicalPrismaFile } ${ prismaClientGeneratorName }  ; 
221+ 
222+             const  prismaVersion  =  getPrismaVersion ( ) ; 
223+             if  ( ! prismaVersion  ||  semver . gte ( prismaVersion ,  '5.2.0' ) )  { 
224+                 // add --no-engine to reduce generation size if the prisma version supports 
225+                 generateCmd  +=  ' --no-engine' ; 
226+             } 
227+ 
210228            try  { 
211-                 // run 'prisma generate' again with output to the console  
212-                 await  execPackage ( generateCmd ) ; 
229+                 // run 'prisma generate' 
230+                 await  execPackage ( generateCmd ,   {   stdio :  'ignore'   } ) ; 
213231            }  catch  { 
214-                 // noop 
232+                 await  trackPrismaSchemaError ( logicalPrismaFile ) ; 
233+                 try  { 
234+                     // run 'prisma generate' again with output to the console 
235+                     await  execPackage ( generateCmd ) ; 
236+                 }  catch  { 
237+                     // noop 
238+                 } 
239+                 throw  new  PluginError ( name ,  `Failed to run "prisma generate" on logical schema: ${ logicalPrismaFile }  ) ; 
215240            } 
216-             throw  new  PluginError ( name ,  `Failed to run "prisma generate" on logical schema: ${ logicalPrismaFile }  ) ; 
217-         } 
218241
219-         // make a bunch of typing fixes to the generated prisma client 
220-         await  this . processClientTypes ( path . join ( this . outDir ,  prismaClientOutDir ) ) ; 
242+             // make a bunch of typing fixes to the generated prisma client 
243+             await  this . processClientTypes ( path . join ( this . outDir ,  LOGICAL_CLIENT_GENERATION_PATH ) ) ; 
244+ 
245+             return  { 
246+                 prismaSchema : logicalPrismaFile , 
247+                 // load the dmmf of the logical prisma schema 
248+                 dmmf : await  getDMMF ( {  datamodel : fs . readFileSync ( logicalPrismaFile ,  {  encoding : 'utf-8'  } )  } ) , 
249+             } ; 
250+         }  finally  { 
251+             if  ( fs . existsSync ( logicalPrismaFile ) )  { 
252+                 fs . rmSync ( logicalPrismaFile ) ; 
253+             } 
254+         } 
255+     } 
221256
222-         return  { 
223-             prismaSchema : logicalPrismaFile , 
224-             // load the dmmf of the logical prisma schema 
225-             dmmf : await  getDMMF ( {  datamodel : fs . readFileSync ( logicalPrismaFile ,  {  encoding : 'utf-8'  } )  } ) , 
226-         } ; 
257+     private  getPrismaClientGeneratorName ( model : Model )  { 
258+         for  ( const  generator  of  model . declarations . filter ( isGeneratorDecl ) )  { 
259+             if  ( 
260+                 generator . fields . some ( 
261+                     ( f )  =>  f . name  ===  'provider'  &&  getLiteral < string > ( f . value )  ===  'prisma-client-js' 
262+                 ) 
263+             )  { 
264+                 return  generator . name ; 
265+             } 
266+         } 
267+         throw  new  PluginError ( name ,  `Cannot find prisma-client-js generator in the schema` ) ; 
227268    } 
228269
229270    private  async  processClientTypes ( prismaClientDir : string )  { 
0 commit comments