Skip to content

Commit 194fccc

Browse files
PagebakersAlan-Cha
authored andcommitted
fix: graphql-upload types
1 parent a320b3f commit 194fccc

File tree

3 files changed

+117
-71
lines changed

3 files changed

+117
-71
lines changed

packages/openapi-to-graphql/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
},
105105
"devDependencies": {
106106
"@types/deep-equal": "^1.0.1",
107-
"@types/graphql-upload": "^8.0.7",
107+
"@types/graphql-upload": "^15.0.2",
108108
"@types/jest": "^27.1.5",
109109
"@types/node": "^16.3.3",
110110
"@types/url-join": "^4.0.1",

packages/openapi-to-graphql/src/resolver_builder.ts

Lines changed: 108 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { SubscriptionContext } from './types/graphql'
1515
import { PreprocessingData } from './types/preprocessing_data'
1616
import { RequestOptions, FileUploadOptions } from './types/options'
1717
import crossFetch from 'cross-fetch'
18-
import { FileUpload } from 'graphql-upload'
18+
import { FileUpload } from 'graphql-upload/Upload'
1919

2020
// Imports:
2121
import stream from 'stream'
@@ -349,10 +349,16 @@ function inferLinkArguments<TSource, TContext, TArgs>({
349349
resolveData,
350350
source,
351351
args
352-
}: inferLinkArgumentsParam<TSource, TContext, TArgs>) {
352+
}: inferLinkArgumentsParam<TSource, TContext, TArgs>) {
353353
if (typeof value === 'object') {
354354
return Object.entries(value).reduce((acc, [key, value]) => {
355-
acc[key] = inferLinkArguments({paramName, value, resolveData, source, args})
355+
acc[key] = inferLinkArguments({
356+
paramName,
357+
value,
358+
resolveData,
359+
source,
360+
args
361+
})
356362
return acc
357363
}, {})
358364
}
@@ -361,13 +367,22 @@ function inferLinkArguments<TSource, TContext, TArgs>({
361367
return value
362368
} else if (value.search(/{|}/) === -1) {
363369
return isRuntimeExpression(value)
364-
? resolveRuntimeExpression(paramName, value, resolveData, source, args)
365-
: value
370+
? resolveRuntimeExpression(paramName, value, resolveData, source, args)
371+
: value
366372
} else {
367373
// Replace link parameters with appropriate values
368374
const linkParams = value.match(/{([^}]*)}/g)
369375
linkParams.forEach((linkParam) => {
370-
value = value.replace(linkParam, resolveRuntimeExpression(paramName, linkParam.substring(1, linkParam.length - 1), resolveData, source, args))
376+
value = value.replace(
377+
linkParam,
378+
resolveRuntimeExpression(
379+
paramName,
380+
linkParam.substring(1, linkParam.length - 1),
381+
resolveData,
382+
source,
383+
args
384+
)
385+
)
371386
})
372387
return value
373388
}
@@ -493,7 +508,13 @@ export function getResolver<TSource, TContext, TArgs extends object>({
493508

494509
let value = argsFromLink[paramName]
495510

496-
args[saneParamName] = inferLinkArguments({paramName, value, resolveData, source, args})
511+
args[saneParamName] = inferLinkArguments({
512+
paramName,
513+
value,
514+
resolveData,
515+
source,
516+
args
517+
})
497518
}
498519

499520
// Stored used parameters to future requests:
@@ -595,51 +616,64 @@ export function getResolver<TSource, TContext, TArgs extends object>({
595616
} else if (operation.payloadContentType === 'multipart/form-data') {
596617
form = new FormData(fileUploadOptions)
597618

598-
const formFieldsPayloadEntries = Object.entries(args[sanePayloadName]);
599-
600-
(await Promise.all(formFieldsPayloadEntries.map(([_, v]) => v)))
601-
.forEach((fieldValue, idx) => {
602-
const fieldName = formFieldsPayloadEntries[idx][0]
603-
604-
if (typeof fieldValue === 'object' && Boolean((fieldValue as Partial<FileUpload>).createReadStream)) {
605-
const uploadingFile = fieldValue as FileUpload
606-
const originalFileStream = uploadingFile.createReadStream()
607-
const filePassThrough = new stream.PassThrough()
619+
const formFieldsPayloadEntries = Object.entries(args[sanePayloadName])
608620

609-
originalFileStream.on('readable', function () {
610-
let data
621+
;(
622+
await Promise.all(formFieldsPayloadEntries.map(([_, v]) => v))
623+
).forEach((fieldValue, idx) => {
624+
const fieldName = formFieldsPayloadEntries[idx][0]
611625

612-
while (data = this.read()) {
613-
const canReadNext = filePassThrough.write(data)
614-
if (!canReadNext) {
615-
this.pause()
616-
filePassThrough.once('drain', () => this.resume())
617-
}
618-
}
619-
})
626+
if (
627+
typeof fieldValue === 'object' &&
628+
Boolean((fieldValue as Partial<FileUpload>).createReadStream)
629+
) {
630+
const uploadingFile = fieldValue as FileUpload
631+
const originalFileStream = uploadingFile.createReadStream()
632+
const filePassThrough = new stream.PassThrough()
633+
634+
originalFileStream.on('readable', function () {
635+
let data
636+
637+
while ((data = this.read())) {
638+
const canReadNext = filePassThrough.write(data)
639+
if (!canReadNext) {
640+
this.pause()
641+
filePassThrough.once('drain', () => this.resume())
642+
}
643+
}
644+
})
620645

621-
originalFileStream.on('error', () => {
622-
uploadLog('Encountered an error while uploading the file %s', uploadingFile.filename)
623-
})
646+
originalFileStream.on('error', () => {
647+
uploadLog(
648+
'Encountered an error while uploading the file %s',
649+
uploadingFile.filename
650+
)
651+
})
624652

625-
originalFileStream.on('end', () => {
626-
uploadLog('Upload for received file %s completed', uploadingFile.filename)
627-
filePassThrough.end()
628-
})
653+
originalFileStream.on('end', () => {
654+
uploadLog(
655+
'Upload for received file %s completed',
656+
uploadingFile.filename
657+
)
658+
filePassThrough.end()
659+
})
629660

630-
uploadLog('Queuing upload for received file %s', uploadingFile.filename)
661+
uploadLog(
662+
'Queuing upload for received file %s',
663+
uploadingFile.filename
664+
)
631665

632-
form.append(fieldName, filePassThrough, {
633-
filename: uploadingFile.filename,
634-
contentType: uploadingFile.mimetype
635-
})
636-
} else if (typeof fieldValue !== 'string') {
637-
// Handle all other primitives that aren't strings as strings the way the web server would expect it
638-
form.append(fieldName, JSON.stringify(fieldValue))
639-
} else {
640-
form.append(fieldName, fieldValue)
641-
}
666+
form.append(fieldName, filePassThrough, {
667+
filename: uploadingFile.filename,
668+
contentType: uploadingFile.mimetype
642669
})
670+
} else if (typeof fieldValue !== 'string') {
671+
// Handle all other primitives that aren't strings as strings the way the web server would expect it
672+
form.append(fieldName, JSON.stringify(fieldValue))
673+
} else {
674+
form.append(fieldName, fieldValue)
675+
}
676+
})
643677

644678
rawPayload = form
645679
} else {
@@ -772,7 +806,10 @@ export function getResolver<TSource, TContext, TArgs extends object>({
772806
} else {
773807
httpLog(`${response.status} - ${Oas3Tools.trim(body, 100)}`)
774808

775-
if (response.headers.get('content-type') && operation.responseContentType) {
809+
if (
810+
response.headers.get('content-type') &&
811+
operation.responseContentType
812+
) {
776813
/**
777814
* Throw warning if the non-application/json content does not
778815
* match the OAS.
@@ -903,7 +940,7 @@ export function getResolver<TSource, TContext, TArgs extends object>({
903940
) {
904941
let arraySaneData = saneData
905942

906-
if ('limit' in args && typeof(args['limit']) === 'number') {
943+
if ('limit' in args && typeof args['limit'] === 'number') {
907944
const limit = args['limit'] as number
908945

909946
if (limit >= 0) {
@@ -1211,7 +1248,9 @@ function resolveRuntimeExpression(
12111248

12121249
// CASE: parameter in previous header parameter
12131250
} else if (runtimeExpression.startsWith('$request.header')) {
1214-
return resolveData.usedRequestOptions.headers[runtimeExpression.split('header.')[1]]
1251+
return resolveData.usedRequestOptions.headers[
1252+
runtimeExpression.split('header.')[1]
1253+
]
12151254
}
12161255
} else if (runtimeExpression.startsWith('$response.')) {
12171256
/**
@@ -1339,7 +1378,11 @@ function graphQLErrorWithExtensions(
13391378
* Replaces the path parameter in the given path with values in the given args.
13401379
* Furthermore adds the query parameters for a request.
13411380
*/
1342-
export function extractRequestDataFromArgs<TSource, TContext, TArgs extends object>(
1381+
export function extractRequestDataFromArgs<
1382+
TSource,
1383+
TContext,
1384+
TArgs extends object
1385+
>(
13431386
path: string,
13441387
parameters: ParameterObject[],
13451388
args: TArgs, // NOTE: argument keys are sanitized!
@@ -1371,18 +1414,28 @@ export function extractRequestDataFromArgs<TSource, TContext, TArgs extends obje
13711414
// Query parameters
13721415
case 'query':
13731416
// setting param style as form assumes explode is true by default
1374-
if (param.style === 'form' && typeof args[saneParamName] === 'object') {
1417+
if (
1418+
param.style === 'form' &&
1419+
typeof args[saneParamName] === 'object'
1420+
) {
13751421
if (param.explode === false) {
1376-
qs[param.name] = Object.entries(args[saneParamName]).reduce((acc, val) => {
1377-
acc += val.join(',')
1378-
return acc
1379-
}, '')
1422+
qs[param.name] = Object.entries(args[saneParamName]).reduce(
1423+
(acc, val) => {
1424+
acc += val.join(',')
1425+
return acc
1426+
},
1427+
''
1428+
)
13801429
} else {
13811430
Object.entries(args[saneParamName]).forEach(([key, value]) => {
13821431
qs[key] = value
13831432
})
13841433
}
1385-
} else if (Array.isArray(args[saneParamName]) && param.style === 'form' && param.explode !== false) {
1434+
} else if (
1435+
Array.isArray(args[saneParamName]) &&
1436+
param.style === 'form' &&
1437+
param.explode !== false
1438+
) {
13861439
qs[param.name] = args[saneParamName].join(',')
13871440
} else {
13881441
qs[param.name] = args[saneParamName]

yarn.lock

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -979,15 +979,15 @@ __metadata:
979979
languageName: node
980980
linkType: hard
981981

982-
"@types/graphql-upload@npm:^8.0.7":
983-
version: 8.0.12
984-
resolution: "@types/graphql-upload@npm:8.0.12"
982+
"@types/graphql-upload@npm:^15.0.2":
983+
version: 15.0.2
984+
resolution: "@types/graphql-upload@npm:15.0.2"
985985
dependencies:
986986
"@types/express": "*"
987987
"@types/koa": "*"
988988
fs-capacitor: ^8.0.0
989989
graphql: 0.13.1 - 16
990-
checksum: 394d5e05f4d5a205dc53f66670af28de73bc73b0910e68907e6d01348caeeb27478621cfdb238a71668f0cca7347ed362c2f1a68266da4b823707dc4daba92ee
990+
checksum: 3e88a03082ce1e1de39b414a096fbd47cf1f97b6027c93cc71a216229bdfb248f54f1afc209e970e1ae3856153c20cf40d458febe348b287be237f62ea84ffc0
991991
languageName: node
992992
linkType: hard
993993

@@ -4762,14 +4762,7 @@ __metadata:
47624762
languageName: node
47634763
linkType: hard
47644764

4765-
"graphql@npm:0.13.1 - 16":
4766-
version: 15.8.0
4767-
resolution: "graphql@npm:15.8.0"
4768-
checksum: 423325271db8858428641b9aca01699283d1fe5b40ef6d4ac622569ecca927019fce8196208b91dd1d8eb8114f00263fe661d241d0eb40c10e5bfd650f86ec5e
4769-
languageName: node
4770-
linkType: hard
4771-
4772-
"graphql@npm:^16.5.0":
4765+
"graphql@npm:0.13.1 - 16, graphql@npm:^16.5.0":
47734766
version: 16.6.0
47744767
resolution: "graphql@npm:16.6.0"
47754768
checksum: bf1d9e3c1938ce3c1a81e909bd3ead1ae4707c577f91cff1ca2eca474bfbc7873d5d7b942e1e9777ff5a8304421dba57a4b76d7a29eb19de8711cb70e3c2415e
@@ -7439,7 +7432,7 @@ __metadata:
74397432
resolution: "openapi-to-graphql@workspace:packages/openapi-to-graphql"
74407433
dependencies:
74417434
"@types/deep-equal": ^1.0.1
7442-
"@types/graphql-upload": ^8.0.7
7435+
"@types/graphql-upload": ^15.0.2
74437436
"@types/jest": ^27.1.5
74447437
"@types/node": ^16.3.3
74457438
"@types/url-join": ^4.0.1
@@ -9946,11 +9939,11 @@ __metadata:
99469939

99479940
"typescript@patch:typescript@^4.3.4#~builtin<compat/typescript>":
99489941
version: 4.9.5
9949-
resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::version=4.9.5&hash=ad5954"
9942+
resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::version=4.9.5&hash=23ec76"
99509943
bin:
99519944
tsc: bin/tsc
99529945
tsserver: bin/tsserver
9953-
checksum: 8f6260acc86b56bfdda6004bc53f32ea548f543e8baef7071c8e34d29d292f3e375c8416556c8de10b24deef6933cd1c16a8233dc84a3dd43a13a13265d0faab
9946+
checksum: ab417a2f398380c90a6cf5a5f74badd17866adf57f1165617d6a551f059c3ba0a3e4da0d147b3ac5681db9ac76a303c5876394b13b3de75fdd5b1eaa06181c9d
99549947
languageName: node
99559948
linkType: hard
99569949

0 commit comments

Comments
 (0)