@@ -716,6 +716,14 @@ class RequestHandler extends APIHandlerBase {
716716 body = SuperJSON . deserialize ( { json : body , meta : body . meta . serialization } ) ;
717717 }
718718
719+ let method : 'create' | 'update' | 'upsert' = mode ;
720+ let matchFields = [ ] ;
721+
722+ if ( body . meta ?. operation === 'upsert' && body . meta ?. matchFields . length ) {
723+ method = 'upsert' ;
724+ matchFields = body . meta . matchFields ;
725+ }
726+
719727 const parsed = this . createUpdatePayloadSchema . parse ( body ) ;
720728 const attributes : any = parsed . data . attributes ;
721729
@@ -740,7 +748,7 @@ class RequestHandler extends APIHandlerBase {
740748 }
741749 }
742750
743- return { attributes, relationships : parsed . data . relationships } ;
751+ return { attributes, relationships : parsed . data . relationships , method , matchFields } ;
744752 }
745753
746754 private async processCreate (
@@ -756,53 +764,63 @@ class RequestHandler extends APIHandlerBase {
756764 return this . makeUnsupportedModelError ( type ) ;
757765 }
758766
759- const { error, attributes, relationships } = this . processRequestBody ( type , requestBody , zodSchemas , 'create' ) ;
767+ const { error, attributes, relationships, method, matchFields } = this . processRequestBody (
768+ type ,
769+ requestBody ,
770+ zodSchemas ,
771+ 'create'
772+ ) ;
760773
761774 if ( error ) {
762775 return error ;
763776 }
764777
765- const createPayload : any = { data : { ...attributes } } ;
778+ let entity : any ;
779+ if ( method === 'upsert' ) {
780+ entity = await prisma [ type ] . upsert ( createPayload ) ;
781+ } else {
782+ const createPayload : any = { data : { ...attributes } } ;
766783
767- // turn relationship payload into Prisma connect objects
768- if ( relationships ) {
769- for ( const [ key , data ] of Object . entries < any > ( relationships ) ) {
770- if ( ! data ?. data ) {
771- return this . makeError ( 'invalidRelationData' ) ;
772- }
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 ) {
788+ return this . makeError ( 'invalidRelationData' ) ;
789+ }
773790
774- const relationInfo = typeInfo . relationships [ key ] ;
775- if ( ! relationInfo ) {
776- return this . makeUnsupportedRelationshipError ( type , key , 400 ) ;
777- }
791+ const relationInfo = typeInfo . relationships [ key ] ;
792+ if ( ! relationInfo ) {
793+ return this . makeUnsupportedRelationshipError ( type , key , 400 ) ;
794+ }
778795
779- if ( relationInfo . isCollection ) {
780- createPayload . data [ key ] = {
781- connect : enumerate ( data . data ) . map ( ( item : any ) =>
782- this . makeIdConnect ( relationInfo . idFields , item . id )
783- ) ,
784- } ;
785- } else {
786- if ( typeof data . data !== 'object' ) {
787- return this . makeError ( 'invalidRelationData' ) ;
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+ } ;
788809 }
789- createPayload . data [ key ] = {
790- connect : this . makeIdConnect ( relationInfo . idFields , data . data . id ) ,
810+
811+ // make sure ID fields are included for result serialization
812+ createPayload . include = {
813+ ...createPayload . include ,
814+ [ key ] : { select : { [ this . makePrismaIdKey ( relationInfo . idFields ) ] : true } } ,
791815 } ;
792816 }
793-
794- // make sure ID fields are included for result serialization
795- createPayload . include = {
796- ...createPayload . include ,
797- [ key ] : { select : { [ this . makePrismaIdKey ( relationInfo . idFields ) ] : true } } ,
798- } ;
799817 }
800- }
801818
802- // include IDs of relation fields so that they can be serialized.
803- this . includeRelationshipIds ( type , createPayload , 'include' ) ;
819+ // include IDs of relation fields so that they can be serialized.
820+ this . includeRelationshipIds ( type , createPayload , 'include' ) ;
804821
805- const entity = await prisma [ type ] . create ( createPayload ) ;
822+ entity = await prisma [ type ] . create ( createPayload ) ;
823+ }
806824 return {
807825 status : 201 ,
808826 body : await this . serializeItems ( type , entity ) ,
0 commit comments