1
+ import { ReadonlyDeep } from '@prisma/generator-helper' ;
1
2
import { DELEGATE_AUX_RELATION_PREFIX } from '@zenstackhq/runtime' ;
2
3
import {
3
4
PluginError ,
@@ -6,8 +7,10 @@ import {
6
7
getAuthDecl ,
7
8
getDataModelAndTypeDefs ,
8
9
getDataModels ,
10
+ getForeignKeyFields ,
9
11
getLiteral ,
10
12
getRelationField ,
13
+ hasAttribute ,
11
14
isDelegateModel ,
12
15
isDiscriminatorField ,
13
16
normalizedRelative ,
@@ -311,7 +314,8 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara
311
314
// make a bunch of typing fixes to the generated prisma client
312
315
await this . processClientTypes ( path . join ( this . outDir , LOGICAL_CLIENT_GENERATION_PATH ) ) ;
313
316
314
- const dmmf = await getDMMF ( { datamodel : fs . readFileSync ( logicalPrismaFile , { encoding : 'utf-8' } ) } ) ;
317
+ // get the dmmf of the logical prisma schema
318
+ const dmmf = await this . getLogicalDMMF ( logicalPrismaFile ) ;
315
319
316
320
try {
317
321
// clean up temp schema
@@ -329,6 +333,56 @@ export function enhance(prisma: any, context?: EnhancementContext<${authTypePara
329
333
} ;
330
334
}
331
335
336
+ private async getLogicalDMMF ( logicalPrismaFile : string ) {
337
+ const dmmf = await getDMMF ( { datamodel : fs . readFileSync ( logicalPrismaFile , { encoding : 'utf-8' } ) } ) ;
338
+
339
+ // make necessary fixes
340
+
341
+ // fields that use `auth()` in `@default` are not handled by Prisma so in the DMMF
342
+ // they may be incorrectly represented as required, we need to fix that for input types
343
+ // also, if a FK field is of such case, its corresponding relation field should be optional
344
+ const createInputPattern = new RegExp ( `^(.+?)(Unchecked)?Create.*Input$` ) ;
345
+ for ( const inputType of dmmf . schema . inputObjectTypes . prisma ) {
346
+ const match = inputType . name . match ( createInputPattern ) ;
347
+ const modelName = match ?. [ 1 ] ;
348
+ if ( modelName ) {
349
+ const dataModel = this . model . declarations . find (
350
+ ( d ) : d is DataModel => isDataModel ( d ) && d . name === modelName
351
+ ) ;
352
+ if ( dataModel ) {
353
+ for ( const field of inputType . fields ) {
354
+ if ( field . isRequired && this . shouldBeOptional ( field , dataModel ) ) {
355
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
356
+ ( field as any ) . isRequired = false ;
357
+ }
358
+ }
359
+ }
360
+ }
361
+ }
362
+ return dmmf ;
363
+ }
364
+
365
+ private shouldBeOptional ( field : ReadonlyDeep < DMMF . SchemaArg > , dataModel : DataModel ) {
366
+ const dmField = dataModel . fields . find ( ( f ) => f . name === field . name ) ;
367
+ if ( ! dmField ) {
368
+ return false ;
369
+ }
370
+
371
+ if ( hasAttribute ( dmField , '@default' ) ) {
372
+ return true ;
373
+ }
374
+
375
+ if ( isDataModel ( dmField . type . reference ?. ref ) ) {
376
+ // if FK field should be optional, the relation field should too
377
+ const fkFields = getForeignKeyFields ( dmField ) ;
378
+ if ( fkFields . length > 0 && fkFields . every ( ( f ) => hasAttribute ( f , '@default' ) ) ) {
379
+ return true ;
380
+ }
381
+ }
382
+
383
+ return false ;
384
+ }
385
+
332
386
private getPrismaClientGeneratorName ( model : Model ) {
333
387
for ( const generator of model . declarations . filter ( isGeneratorDecl ) ) {
334
388
if (
0 commit comments