1-
21import { type Component } from "solid-js" ;
32import {
43 deserializeJSONStream ,
54 deserializeJSStream ,
65 // serializeToJSONStream,
76 serializeToJSONString ,
87} from "./serialization" ;
8+ import { BODY_FORMAL_FILE , BODY_FORMAT_KEY , BodyFormat } from "./server-functions-shared" ;
99
1010let INSTANCE = 0 ;
1111
@@ -25,38 +25,122 @@ function createRequest(
2525 } ,
2626 } ) ;
2727}
28+
29+ function getHeadersAndBody ( body : any ) : {
30+ headers ?: HeadersInit ;
31+ body : BodyInit ;
32+ } | undefined {
33+ switch ( true ) {
34+ case typeof body === "string" :
35+ return {
36+ headers : {
37+ "Content-Type" : "text/plain" ,
38+ [ BODY_FORMAT_KEY ] : BodyFormat . String ,
39+ } ,
40+ body,
41+ } ;
42+ case body instanceof FormData :
43+ return {
44+ headers : {
45+ "Content-Type" : "multipart/form-data" ,
46+ [ BODY_FORMAT_KEY ] : BodyFormat . FormData ,
47+ } ,
48+ body,
49+ } ;
50+ case body instanceof URLSearchParams :
51+ return {
52+ headers : {
53+ "Content-Type" : "application/x-www-form-urlencoded" ,
54+ [ BODY_FORMAT_KEY ] : BodyFormat . URLSearchParams ,
55+ } ,
56+ body,
57+ } ;
58+ case body instanceof Blob :
59+ return {
60+ headers : {
61+ [ BODY_FORMAT_KEY ] : BodyFormat . Blob ,
62+ } ,
63+ body,
64+ } ;
65+ case body instanceof File : {
66+ const formData = new FormData ( ) ;
67+ formData . append ( BODY_FORMAL_FILE , body , body . name ) ;
68+ return {
69+ headers : {
70+ [ BODY_FORMAT_KEY ] : BodyFormat . File ,
71+ } ,
72+ body : new FormData ( ) ,
73+ } ;
74+ }
75+ case body instanceof ArrayBuffer :
76+ return {
77+ headers : {
78+ [ BODY_FORMAT_KEY ] : BodyFormat . ArrayBuffer ,
79+ } ,
80+ body,
81+ } ;
82+ case body instanceof Uint8Array :
83+ return {
84+ headers : {
85+ [ BODY_FORMAT_KEY ] : BodyFormat . Uint8Array ,
86+ } ,
87+ body : new Uint8Array ( body ) ,
88+ } ;
89+ default :
90+ return undefined ;
91+ }
92+ }
93+
94+ async function initializeResponse (
95+ base : string ,
96+ id : string ,
97+ instance : string ,
98+ options : RequestInit ,
99+ args : any [ ] ,
100+ ) {
101+ // No args, skip serialization
102+ if ( args . length === 0 ) {
103+ return createRequest ( base , id , instance , options ) ;
104+ }
105+ // For single arguments, we can directly encode as body
106+ if ( args . length === 1 ) {
107+ const body = args [ 0 ] ;
108+ const result = getHeadersAndBody ( body ) ;
109+ if ( result ) {
110+ return createRequest ( base , id , instance , {
111+ ...options ,
112+ body : result . body ,
113+ headers : {
114+ ...options . headers ,
115+ ...result . headers ,
116+ } ,
117+ } ) ;
118+ }
119+ }
120+ // Fallback to seroval
121+ return createRequest ( base , id , instance , {
122+ ...options ,
123+ // TODO(Alexis): move to serializeToJSONStream
124+ body : await serializeToJSONString ( args ) ,
125+ // duplex: 'half',
126+ // body: serializeToJSONStream(args),
127+ headers : {
128+ ...options . headers ,
129+ "Content-Type" : "text/plain" ,
130+ [ BODY_FORMAT_KEY ] : BodyFormat . Seroval ,
131+ } ,
132+ } ) ;
133+ }
134+
28135async function fetchServerFunction (
29136 base : string ,
30137 id : string ,
31138 options : Omit < RequestInit , "body" > ,
32139 args : any [ ] ,
33140) {
34141 const instance = `server-fn:${ INSTANCE ++ } ` ;
35- const response = await ( args . length === 0
36- ? createRequest ( base , id , instance , options )
37- : args . length === 1 && args [ 0 ] instanceof FormData
38- ? createRequest ( base , id , instance , { ...options , body : args [ 0 ] } )
39- : args . length === 1 && args [ 0 ] instanceof URLSearchParams
40- ? createRequest ( base , id , instance , {
41- ...options ,
42- body : args [ 0 ] ,
43- headers : {
44- ...options . headers ,
45- "Content-Type" : "application/x-www-form-urlencoded" ,
46- } ,
47- } )
48- : createRequest ( base , id , instance , {
49- ...options ,
50- // TODO(Alexis): move to serializeToJSONStream
51- body : await serializeToJSONString ( args ) ,
52- // duplex: 'half',
53- // body: serializeToJSONStream(args),
54- headers : {
55- ...options . headers ,
56- "x-serialized" : "true" ,
57- "Content-Type" : "text/plain"
58- } ,
59- } ) ) ;
142+
143+ const response = await initializeResponse ( base , id , instance , options , args ) ;
60144
61145 if (
62146 response . headers . has ( "Location" ) ||
@@ -82,7 +166,7 @@ async function fetchServerFunction(
82166 result = await clone . text ( ) ;
83167 } else if ( contentType ?. startsWith ( "application/json" ) ) {
84168 result = await clone . json ( ) ;
85- } else if ( response . headers . get ( 'x-serialized' ) ) {
169+ } else if ( response . headers . get ( BODY_FORMAT_KEY ) ) {
86170 if ( import . meta. env . SEROVAL_MODE === "js" ) {
87171 result = await deserializeJSStream ( instance , clone ) ;
88172 } else {
0 commit comments