@@ -716,11 +716,11 @@ class RequestHandler extends APIHandlerBase {
716716 body = SuperJSON . deserialize ( { json : body , meta : body . meta . serialization } ) ;
717717 }
718718
719- let method : 'create' | 'update' | 'upsert' = mode ;
719+ let operation : 'create' | 'update' | 'upsert' = mode ;
720720 let matchFields = [ ] ;
721721
722722 if ( body . meta ?. operation === 'upsert' && body . meta ?. matchFields . length ) {
723- method = 'upsert' ;
723+ operation = 'upsert' ;
724724 matchFields = body . meta . matchFields ;
725725 }
726726
@@ -748,7 +748,7 @@ class RequestHandler extends APIHandlerBase {
748748 }
749749 }
750750
751- return { attributes, relationships : parsed . data . relationships , method , matchFields } ;
751+ return { attributes, relationships : parsed . data . relationships , operation , matchFields } ;
752752 }
753753
754754 private async processCreate (
@@ -764,7 +764,7 @@ class RequestHandler extends APIHandlerBase {
764764 return this . makeUnsupportedModelError ( type ) ;
765765 }
766766
767- const { error, attributes, relationships, method , matchFields } = this . processRequestBody (
767+ const { error, attributes, relationships, operation , matchFields } = this . processRequestBody (
768768 type ,
769769 requestBody ,
770770 zodSchemas ,
@@ -776,55 +776,127 @@ class RequestHandler extends APIHandlerBase {
776776 }
777777
778778 let entity : any ;
779- if ( method === 'upsert' ) {
780- entity = await prisma [ type ] . upsert ( createPayload ) ;
779+ if ( operation === 'upsert' ) {
780+ entity = await this . runUsert ( typeInfo , type , prisma , attributes , relationships , matchFields ) ;
781+ } else if ( operation === 'create' ) {
782+ entity = await this . runCreate ( typeInfo , type , prisma , attributes , relationships ) ;
781783 } else {
782- const createPayload : any = { data : { ...attributes } } ;
784+ return this . makeError ( 'invalidPayload' ) ;
785+ }
786+
787+ return {
788+ status : 201 ,
789+ body : await this . serializeItems ( type , entity ) ,
790+ } ;
791+ }
792+
793+ private async runUsert (
794+ typeInfo : ModelInfo ,
795+ type : string ,
796+ prisma : DbClientContract ,
797+ attributes : any ,
798+ relationships : any ,
799+ matchFields : any [ ]
800+ ) {
801+ const upsertPayload : any = { } ;
802+ upsertPayload . where = matchFields . reduce ( ( acc : any , field : string ) => {
803+ acc [ field ] = attributes [ field ] ?? null ;
804+ return acc ;
805+ } , { } ) ;
806+
807+ upsertPayload . create = { ...attributes } ;
808+ upsertPayload . update = { ...attributes } ;
809+
810+ if ( relationships ) {
811+ for ( const [ key , data ] of Object . entries < any > ( relationships ) ) {
812+ if ( ! data ?. data ) {
813+ return this . makeError ( 'invalidRelationData' ) ;
814+ }
815+
816+ const relationInfo = typeInfo . relationships [ key ] ;
817+ if ( ! relationInfo ) {
818+ return this . makeUnsupportedRelationshipError ( type , key , 400 ) ;
819+ }
783820
784- // turn relationship payload into Prisma connect objects
785- if ( relationships ) {
786- for ( const [ key , data ] of Object . entries < any > ( relationships ) ) {
787- if ( ! data ?. data ) {
821+ if ( relationInfo . isCollection ) {
822+ upsertPayload . create [ key ] = {
823+ connect : enumerate ( data . data ) . map ( ( item : any ) =>
824+ this . makeIdConnect ( relationInfo . idFields , item . id )
825+ ) ,
826+ } ;
827+ upsertPayload . update [ key ] = {
828+ connect : enumerate ( data . data ) . map ( ( item : any ) =>
829+ this . makeIdConnect ( relationInfo . idFields , item . id )
830+ ) ,
831+ } ;
832+ } else {
833+ if ( typeof data . data !== 'object' ) {
788834 return this . makeError ( 'invalidRelationData' ) ;
789835 }
836+ upsertPayload . create [ key ] = {
837+ connect : this . makeIdConnect ( relationInfo . idFields , data . data . id ) ,
838+ } ;
839+ upsertPayload . update [ key ] = {
840+ connect : this . makeIdConnect ( relationInfo . idFields , data . data . id ) ,
841+ } ;
842+ }
843+ }
844+ }
790845
791- const relationInfo = typeInfo . relationships [ key ] ;
792- if ( ! relationInfo ) {
793- return this . makeUnsupportedRelationshipError ( type , key , 400 ) ;
794- }
846+ // include IDs of relation fields so that they can be serialized.
847+ this . includeRelationshipIds ( type , upsertPayload , 'include' ) ;
795848
796- if ( relationInfo . isCollection ) {
797- createPayload . data [ key ] = {
798- connect : enumerate ( data . data ) . map ( ( item : any ) =>
799- this . makeIdConnect ( relationInfo . idFields , item . id )
800- ) ,
801- } ;
802- } else {
803- if ( typeof data . data !== 'object' ) {
804- return this . makeError ( 'invalidRelationData' ) ;
805- }
806- createPayload . data [ key ] = {
807- connect : this . makeIdConnect ( relationInfo . idFields , data . data . id ) ,
808- } ;
809- }
849+ return prisma [ type ] . upsert ( upsertPayload ) ;
850+ }
851+
852+ private async runCreate (
853+ typeInfo : ModelInfo ,
854+ type : string ,
855+ prisma : DbClientContract ,
856+ attributes : any ,
857+ relationships : any
858+ ) {
859+ const createPayload : any = { data : { ...attributes } } ;
860+
861+ // turn relationship payload into Prisma connect objects
862+ if ( relationships ) {
863+ for ( const [ key , data ] of Object . entries < any > ( relationships ) ) {
864+ if ( ! data ?. data ) {
865+ return this . makeError ( 'invalidRelationData' ) ;
866+ }
867+
868+ const relationInfo = typeInfo . relationships [ key ] ;
869+ if ( ! relationInfo ) {
870+ return this . makeUnsupportedRelationshipError ( type , key , 400 ) ;
871+ }
810872
811- // make sure ID fields are included for result serialization
812- createPayload . include = {
813- ...createPayload . include ,
814- [ key ] : { select : { [ this . makePrismaIdKey ( relationInfo . idFields ) ] : true } } ,
873+ if ( relationInfo . isCollection ) {
874+ createPayload . data [ key ] = {
875+ connect : enumerate ( data . data ) . map ( ( item : any ) =>
876+ this . makeIdConnect ( relationInfo . idFields , item . id )
877+ ) ,
878+ } ;
879+ } else {
880+ if ( typeof data . data !== 'object' ) {
881+ return this . makeError ( 'invalidRelationData' ) ;
882+ }
883+ createPayload . data [ key ] = {
884+ connect : this . makeIdConnect ( relationInfo . idFields , data . data . id ) ,
815885 } ;
816886 }
887+
888+ // make sure ID fields are included for result serialization
889+ createPayload . include = {
890+ ...createPayload . include ,
891+ [ key ] : { select : { [ this . makePrismaIdKey ( relationInfo . idFields ) ] : true } } ,
892+ } ;
817893 }
894+ }
818895
819- // include IDs of relation fields so that they can be serialized.
820- this . includeRelationshipIds ( type , createPayload , 'include' ) ;
896+ // include IDs of relation fields so that they can be serialized.
897+ this . includeRelationshipIds ( type , createPayload , 'include' ) ;
821898
822- entity = await prisma [ type ] . create ( createPayload ) ;
823- }
824- return {
825- status : 201 ,
826- body : await this . serializeItems ( type , entity ) ,
827- } ;
899+ return prisma [ type ] . create ( createPayload ) ;
828900 }
829901
830902 private async processRelationshipCRUD (
0 commit comments