@@ -3,7 +3,7 @@ import { print } from 'graphql'
3
3
import { Anyware } from '../../lib/anyware/__.js'
4
4
import { type StandardScalarVariables } from '../../lib/graphql.js'
5
5
import { parseExecutionResult } from '../../lib/graphqlHTTP.js'
6
- import { CONTENT_TYPE_GQL } from '../../lib/http.js'
6
+ import { CONTENT_TYPE_GQL , CONTENT_TYPE_JSON } from '../../lib/http.js'
7
7
import { casesExhausted } from '../../lib/prelude.js'
8
8
import { execute } from '../0_functions/execute.js'
9
9
import type { Schema } from '../1_Schema/__.js'
@@ -104,6 +104,9 @@ type RequestInput = {
104
104
}
105
105
106
106
export type HookDefExchange = {
107
+ slots : {
108
+ fetch : typeof fetch
109
+ }
107
110
input :
108
111
& InterfaceInput
109
112
& TransportInput <
@@ -186,14 +189,16 @@ export const anyware = Anyware.create<HookSequence, HookMap, ExecutionResult>({
186
189
187
190
switch ( input . transport ) {
188
191
case `http` : {
192
+ const body = slots . body ( {
193
+ query : document ,
194
+ variables,
195
+ operationName : `todo` ,
196
+ } )
197
+
189
198
return {
190
199
...input ,
191
200
url : input . schema ,
192
- body : slots . body ( {
193
- query : document ,
194
- variables,
195
- operationName : `todo` ,
196
- } ) ,
201
+ body,
197
202
}
198
203
}
199
204
case `memory` : {
@@ -215,12 +220,19 @@ export const anyware = Anyware.create<HookSequence, HookMap, ExecutionResult>({
215
220
}
216
221
case `http` : {
217
222
const headers = new Headers ( input . headers )
218
- headers . append ( `accept` , CONTENT_TYPE_GQL )
223
+ // @see https://graphql.github.io/graphql-over-http/draft/#sec-Accept
224
+ headers . set ( `accept` , CONTENT_TYPE_GQL )
225
+ // @see https://graphql.github.io/graphql-over-http/draft/#sec-POST
226
+ // todo if body is something else, say upload extension turns it into a FormData, then fetch will automatically set the content-type header.
227
+ // ... however we should not rely on that behavior, and instead error here if there is no content type header and we cannot infer it here?
228
+ if ( typeof input . body === `string` ) {
229
+ headers . set ( `content-type` , CONTENT_TYPE_JSON )
230
+ }
219
231
return {
220
232
...input ,
221
233
request : {
222
234
url : input . url ,
223
- body : input . body , // JSON.stringify({ query, variables, operationName }),
235
+ body : input . body ,
224
236
method : `POST` ,
225
237
headers,
226
238
} ,
@@ -230,36 +242,43 @@ export const anyware = Anyware.create<HookSequence, HookMap, ExecutionResult>({
230
242
throw casesExhausted ( input )
231
243
}
232
244
} ,
233
- exchange : async ( { input } ) => {
234
- switch ( input . transport ) {
235
- case `http` : {
236
- const response = await fetch (
237
- new Request ( input . request . url , {
238
- method : input . request . method ,
239
- headers : input . request . headers ,
240
- body : input . request . body ,
241
- } ) ,
242
- )
243
- return {
244
- ...input ,
245
- response,
245
+ exchange : {
246
+ slots : {
247
+ fetch : ( request ) => {
248
+ return fetch ( request )
249
+ } ,
250
+ } ,
251
+ run : async ( { input, slots } ) => {
252
+ switch ( input . transport ) {
253
+ case `http` : {
254
+ const response = await slots . fetch (
255
+ new Request ( input . request . url , {
256
+ method : input . request . method ,
257
+ headers : input . request . headers ,
258
+ body : input . request . body ,
259
+ } ) ,
260
+ )
261
+ return {
262
+ ...input ,
263
+ response,
264
+ }
246
265
}
247
- }
248
- case `memory` : {
249
- const result = await execute ( {
250
- schema : input . schema ,
251
- document : input . query ,
252
- variables : input . variables ,
253
- operationName : input . operationName ,
254
- } )
255
- return {
256
- ... input ,
257
- result ,
266
+ case `memory` : {
267
+ const result = await execute ( {
268
+ schema : input . schema ,
269
+ document : input . query ,
270
+ variables : input . variables ,
271
+ operationName : input . operationName ,
272
+ } )
273
+ return {
274
+ ... input ,
275
+ result ,
276
+ }
258
277
}
278
+ default :
279
+ throw casesExhausted ( input )
259
280
}
260
- default :
261
- throw casesExhausted ( input )
262
- }
281
+ } ,
263
282
} ,
264
283
unpack : async ( { input } ) => {
265
284
switch ( input . transport ) {
0 commit comments