@@ -5,10 +5,12 @@ import { ACTIONS_WITH_WRITE_PAYLOAD } from '../../constants';
55import  { 
66    FieldInfo , 
77    NestedWriteVisitor , 
8+     NestedWriteVisitorContext , 
89    PrismaWriteActionType , 
910    clone , 
1011    enumerate , 
1112    getFields , 
13+     getModelInfo , 
1214    getTypeDefInfo , 
1315    requireField , 
1416}  from  '../../cross' ; 
@@ -61,7 +63,7 @@ class DefaultAuthHandler extends DefaultPrismaProxyHandler {
6163    private  async  preprocessWritePayload ( model : string ,  action : PrismaWriteActionType ,  args : any )  { 
6264        const  newArgs  =  clone ( args ) ; 
6365
64-         const  processCreatePayload  =  ( model : string ,  data : any )  =>  { 
66+         const  processCreatePayload  =  ( model : string ,  data : any ,   context :  NestedWriteVisitorContext )  =>  { 
6567            const  fields  =  getFields ( this . options . modelMeta ,  model ) ; 
6668            for  ( const  fieldInfo  of  Object . values ( fields ) )  { 
6769                if  ( fieldInfo . isTypeDef )  { 
@@ -82,24 +84,24 @@ class DefaultAuthHandler extends DefaultPrismaProxyHandler {
8284                const  defaultValue  =  this . getDefaultValue ( fieldInfo ) ; 
8385                if  ( defaultValue  !==  undefined )  { 
8486                    // set field value extracted from `auth()` 
85-                     this . setDefaultValueForModelData ( fieldInfo ,  model ,  data ,  defaultValue ) ; 
87+                     this . setDefaultValueForModelData ( fieldInfo ,  model ,  data ,  defaultValue ,   context ) ; 
8688                } 
8789            } 
8890        } ; 
8991
9092        // visit create payload and set default value to fields using `auth()` in `@default()` 
9193        const  visitor  =  new  NestedWriteVisitor ( this . options . modelMeta ,  { 
92-             create : ( model ,  data )  =>  { 
93-                 processCreatePayload ( model ,  data ) ; 
94+             create : ( model ,  data ,   context )  =>  { 
95+                 processCreatePayload ( model ,  data ,   context ) ; 
9496            } , 
9597
96-             upsert : ( model ,  data )  =>  { 
97-                 processCreatePayload ( model ,  data . create ) ; 
98+             upsert : ( model ,  data ,   context )  =>  { 
99+                 processCreatePayload ( model ,  data . create ,   context ) ; 
98100            } , 
99101
100-             createMany : ( model ,  args )  =>  { 
102+             createMany : ( model ,  args ,   context )  =>  { 
101103                for  ( const  item  of  enumerate ( args . data ) )  { 
102-                     processCreatePayload ( model ,  item ) ; 
104+                     processCreatePayload ( model ,  item ,   context ) ; 
103105                } 
104106            } , 
105107        } ) ; 
@@ -108,42 +110,82 @@ class DefaultAuthHandler extends DefaultPrismaProxyHandler {
108110        return  newArgs ; 
109111    } 
110112
111-     private  setDefaultValueForModelData ( fieldInfo : FieldInfo ,  model : string ,  data : any ,  authDefaultValue : unknown )  { 
112-         if  ( fieldInfo . isForeignKey  &&  fieldInfo . relationField  &&  fieldInfo . relationField  in  data )  { 
113+     private  setDefaultValueForModelData ( 
114+         fieldInfo : FieldInfo , 
115+         model : string , 
116+         data : any , 
117+         authDefaultValue : unknown , 
118+         context : NestedWriteVisitorContext 
119+     )  { 
120+         if  ( fieldInfo . isForeignKey )  { 
121+             // if the field being inspected is a fk field, there are several cases we should not 
122+             // set the default value or should not set directly 
123+ 
113124            // if the field is a fk, and the relation field is already set, we should not override it 
114-             return ; 
115-         } 
125+             if  ( fieldInfo . relationField  &&  fieldInfo . relationField  in  data )  { 
126+                 return ; 
127+             } 
116128
117-         if  ( fieldInfo . isForeignKey  &&  ! isUnsafeMutate ( model ,  data ,  this . options . modelMeta ) )  { 
118-             // if the field is a fk, and the create payload is not unsafe, we need to translate 
119-             // the fk field setting to a `connect` of the corresponding relation field 
120-             const  relFieldName  =  fieldInfo . relationField ; 
121-             if  ( ! relFieldName )  { 
122-                 throw  new  Error ( 
123-                     `Field \`${ fieldInfo . name }  \` is a foreign key field but no corresponding relation field is found` 
129+             if  ( context . field ?. backLink  &&  context . nestingPath . length  >  1 )  { 
130+                 // if the fk field is in a creation context where its implied by the parent, 
131+                 // we should not set the default value, e.g.: 
132+                 // 
133+                 // ``` 
134+                 // parent.create({ data: { child: { create: {}  }  }  }) 
135+                 // ``` 
136+                 // 
137+                 // event if child's fk to parent has a default value, we should not set default 
138+                 // value here 
139+ 
140+                 // fetch parent model from the parent context 
141+                 const  parentModel  =  getModelInfo ( 
142+                     this . options . modelMeta , 
143+                     context . nestingPath [ context . nestingPath . length  -  2 ] . model 
124144                ) ; 
125-             } 
126-             const  relationField  =  requireField ( this . options . modelMeta ,  model ,  relFieldName ) ; 
127145
128-             // construct a `{ connect: { ... }  }` payload 
129-             let  connect  =  data [ relationField . name ] ?. connect ; 
130-             if  ( ! connect )  { 
131-                 connect  =  { } ; 
132-                 data [ relationField . name ]  =  {  connect } ; 
146+                 if  ( parentModel )  { 
147+                     // get the opposite side of the relation for the current create context 
148+                     const  oppositeRelationField  =  requireField ( this . options . modelMeta ,  model ,  context . field . backLink ) ; 
149+                     if  ( parentModel . name  ===  oppositeRelationField . type )  { 
150+                         // if the opposite side matches the parent model, it means we currently in a creation context 
151+                         // that implicitly sets this fk field 
152+                         return ; 
153+                     } 
154+                 } 
133155            } 
134156
135-             // sets the opposite fk field to value `authDefaultValue` 
136-             const  oppositeFkFieldName  =  this . getOppositeFkFieldName ( relationField ,  fieldInfo ) ; 
137-             if  ( ! oppositeFkFieldName )  { 
138-                 throw  new  Error ( 
139-                     `Cannot find opposite foreign key field for \`${ fieldInfo . name }  \` in relation field \`${ relFieldName }  \`` 
140-                 ) ; 
157+             if  ( ! isUnsafeMutate ( model ,  data ,  this . options . modelMeta ) )  { 
158+                 // if the field is a fk, and the create payload is not unsafe, we need to translate 
159+                 // the fk field setting to a `connect` of the corresponding relation field 
160+                 const  relFieldName  =  fieldInfo . relationField ; 
161+                 if  ( ! relFieldName )  { 
162+                     throw  new  Error ( 
163+                         `Field \`${ fieldInfo . name }  \` is a foreign key field but no corresponding relation field is found` 
164+                     ) ; 
165+                 } 
166+                 const  relationField  =  requireField ( this . options . modelMeta ,  model ,  relFieldName ) ; 
167+ 
168+                 // construct a `{ connect: { ... }  }` payload 
169+                 let  connect  =  data [ relationField . name ] ?. connect ; 
170+                 if  ( ! connect )  { 
171+                     connect  =  { } ; 
172+                     data [ relationField . name ]  =  {  connect } ; 
173+                 } 
174+ 
175+                 // sets the opposite fk field to value `authDefaultValue` 
176+                 const  oppositeFkFieldName  =  this . getOppositeFkFieldName ( relationField ,  fieldInfo ) ; 
177+                 if  ( ! oppositeFkFieldName )  { 
178+                     throw  new  Error ( 
179+                         `Cannot find opposite foreign key field for \`${ fieldInfo . name }  \` in relation field \`${ relFieldName }  \`` 
180+                     ) ; 
181+                 } 
182+                 connect [ oppositeFkFieldName ]  =  authDefaultValue ; 
183+                 return ; 
141184            } 
142-             connect [ oppositeFkFieldName ]  =  authDefaultValue ; 
143-         }  else  { 
144-             // set default value directly 
145-             data [ fieldInfo . name ]  =  authDefaultValue ; 
146185        } 
186+ 
187+         // set default value directly 
188+         data [ fieldInfo . name ]  =  authDefaultValue ; 
147189    } 
148190
149191    private  getOppositeFkFieldName ( relationField : FieldInfo ,  fieldInfo : FieldInfo )  { 
0 commit comments