Skip to content

Commit ac4d85e

Browse files
authored
Merge pull request #4568 from bayasdev/encode-params
2 parents 6353756 + a989ed9 commit ac4d85e

File tree

5 files changed

+298
-72
lines changed

5 files changed

+298
-72
lines changed

packages/rtk-query-codegen-openapi/src/generate.ts

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export async function generateApi(
8888
filterEndpoints,
8989
endpointOverrides,
9090
unionUndefined,
91+
encodeParams = false,
9192
flattenArg = false,
9293
useEnumType = false,
9394
mergeReadWriteOnly = false,
@@ -356,7 +357,7 @@ export async function generateApi(
356357
type: isQuery ? 'query' : 'mutation',
357358
Response: ResponseTypeName,
358359
QueryArg,
359-
queryFn: generateQueryFn({ operationDefinition, queryArg, isQuery, isFlatArg }),
360+
queryFn: generateQueryFn({ operationDefinition, queryArg, isQuery, isFlatArg, encodeParams }),
360361
extraEndpointsProps: isQuery
361362
? generateQueryEndpointProps({ operationDefinition })
362363
: generateMutationEndpointProps({ operationDefinition }),
@@ -369,11 +370,13 @@ export async function generateApi(
369370
queryArg,
370371
isFlatArg,
371372
isQuery,
373+
encodeParams,
372374
}: {
373375
operationDefinition: OperationDefinition;
374376
queryArg: QueryArgDefinitions;
375377
isFlatArg: boolean;
376378
isQuery: boolean;
379+
encodeParams: boolean;
377380
}) {
378381
const { path, verb } = operationDefinition;
379382

@@ -386,21 +389,24 @@ export async function generateApi(
386389
}
387390

388391
function createObjectLiteralProperty(parameters: QueryArgDefinition[], propertyName: string) {
389-
return parameters.length === 0
390-
? undefined
391-
: factory.createPropertyAssignment(
392-
factory.createIdentifier(propertyName),
393-
factory.createObjectLiteralExpression(
394-
parameters.map(
395-
(param) =>
396-
createPropertyAssignment(
397-
param.originalName,
398-
isFlatArg ? rootObject : accessProperty(rootObject, param.name)
399-
),
400-
true
401-
)
402-
)
403-
);
392+
if (parameters.length === 0) return undefined;
393+
394+
const properties = parameters.map((param) => {
395+
const value = isFlatArg ? rootObject : accessProperty(rootObject, param.name);
396+
return createPropertyAssignment(
397+
param.originalName,
398+
encodeParams && param.param?.in === 'query'
399+
? factory.createCallExpression(factory.createIdentifier('encodeURIComponent'), undefined, [
400+
factory.createCallExpression(factory.createIdentifier('String'), undefined, [value]),
401+
])
402+
: value
403+
);
404+
});
405+
406+
return factory.createPropertyAssignment(
407+
factory.createIdentifier(propertyName),
408+
factory.createObjectLiteralExpression(properties, true)
409+
);
404410
}
405411

406412
return factory.createArrowFunction(
@@ -416,7 +422,7 @@ export async function generateApi(
416422
[
417423
factory.createPropertyAssignment(
418424
factory.createIdentifier('url'),
419-
generatePathExpression(path, pickParams('path'), rootObject, isFlatArg)
425+
generatePathExpression(path, pickParams('path'), rootObject, isFlatArg, encodeParams)
420426
),
421427
isQuery && verb.toUpperCase() === 'GET'
422428
? undefined
@@ -463,7 +469,8 @@ function generatePathExpression(
463469
path: string,
464470
pathParameters: QueryArgDefinition[],
465471
rootObject: ts.Identifier,
466-
isFlatArg: boolean
472+
isFlatArg: boolean,
473+
encodeParams: boolean
467474
) {
468475
const expressions: Array<[string, string]> = [];
469476

@@ -479,14 +486,20 @@ function generatePathExpression(
479486
return expressions.length
480487
? factory.createTemplateExpression(
481488
factory.createTemplateHead(head),
482-
expressions.map(([prop, literal], index) =>
483-
factory.createTemplateSpan(
484-
isFlatArg ? rootObject : accessProperty(rootObject, prop),
489+
expressions.map(([prop, literal], index) => {
490+
const value = isFlatArg ? rootObject : accessProperty(rootObject, prop);
491+
const encodedValue = encodeParams
492+
? factory.createCallExpression(factory.createIdentifier('encodeURIComponent'), undefined, [
493+
factory.createCallExpression(factory.createIdentifier('String'), undefined, [value]),
494+
])
495+
: value;
496+
return factory.createTemplateSpan(
497+
encodedValue,
485498
index === expressions.length - 1
486499
? factory.createTemplateTail(literal)
487500
: factory.createTemplateMiddle(literal)
488-
)
489-
)
501+
);
502+
})
490503
)
491504
: factory.createNoSubstitutionTemplateLiteral(head);
492505
}

packages/rtk-query-codegen-openapi/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ export interface CommonOptions {
6262
* @see https://redux-toolkit.js.org/rtk-query/usage/code-generation for more information
6363
*/
6464
tag?: boolean;
65+
/**
66+
* defaults to false
67+
* `true` will add `encodeURIComponent` to the generated query params
68+
*/
69+
encodeParams?: boolean;
6570
/**
6671
* defaults to false
6772
* `true` will "flatten" the arg so that you can do things like `useGetEntityById(1)` instead of `useGetEntityById({ entityId: 1 })`

packages/rtk-query-codegen-openapi/test/__snapshots__/cli.test.ts.snap

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,20 @@ const injectedRtkApi = api.injectEndpoints({
1111
query: (queryArg) => ({ url: \`/pet\`, method: 'POST', body: queryArg.pet }),
1212
}),
1313
findPetsByStatus: build.query<FindPetsByStatusApiResponse, FindPetsByStatusApiArg>({
14-
query: (queryArg) => ({ url: \`/pet/findByStatus\`, params: { status: queryArg.status } }),
14+
query: (queryArg) => ({
15+
url: \`/pet/findByStatus\`,
16+
params: {
17+
status: queryArg.status,
18+
},
19+
}),
1520
}),
1621
findPetsByTags: build.query<FindPetsByTagsApiResponse, FindPetsByTagsApiArg>({
17-
query: (queryArg) => ({ url: \`/pet/findByTags\`, params: { tags: queryArg.tags } }),
22+
query: (queryArg) => ({
23+
url: \`/pet/findByTags\`,
24+
params: {
25+
tags: queryArg.tags,
26+
},
27+
}),
1828
}),
1929
getPetById: build.query<GetPetByIdApiResponse, GetPetByIdApiArg>({
2030
query: (queryArg) => ({ url: \`/pet/\${queryArg.petId}\` }),
@@ -23,18 +33,29 @@ const injectedRtkApi = api.injectEndpoints({
2333
query: (queryArg) => ({
2434
url: \`/pet/\${queryArg.petId}\`,
2535
method: 'POST',
26-
params: { name: queryArg.name, status: queryArg.status },
36+
params: {
37+
name: queryArg.name,
38+
status: queryArg.status,
39+
},
2740
}),
2841
}),
2942
deletePet: build.mutation<DeletePetApiResponse, DeletePetApiArg>({
30-
query: (queryArg) => ({ url: \`/pet/\${queryArg.petId}\`, method: 'DELETE', headers: { api_key: queryArg.apiKey } }),
43+
query: (queryArg) => ({
44+
url: \`/pet/\${queryArg.petId}\`,
45+
method: 'DELETE',
46+
headers: {
47+
api_key: queryArg.apiKey,
48+
},
49+
}),
3150
}),
3251
uploadFile: build.mutation<UploadFileApiResponse, UploadFileApiArg>({
3352
query: (queryArg) => ({
3453
url: \`/pet/\${queryArg.petId}/uploadImage\`,
3554
method: 'POST',
3655
body: queryArg.body,
37-
params: { additionalMetadata: queryArg.additionalMetadata },
56+
params: {
57+
additionalMetadata: queryArg.additionalMetadata,
58+
},
3859
}),
3960
}),
4061
getInventory: build.query<GetInventoryApiResponse, GetInventoryApiArg>({
@@ -58,7 +79,10 @@ const injectedRtkApi = api.injectEndpoints({
5879
loginUser: build.query<LoginUserApiResponse, LoginUserApiArg>({
5980
query: (queryArg) => ({
6081
url: \`/user/login\`,
61-
params: { username: queryArg.username, password: queryArg.password },
82+
params: {
83+
username: queryArg.username,
84+
password: queryArg.password,
85+
},
6286
}),
6387
}),
6488
logoutUser: build.query<LogoutUserApiResponse, LogoutUserApiArg>({
@@ -234,10 +258,20 @@ const injectedRtkApi = api.injectEndpoints({
234258
query: (queryArg) => ({ url: \`/pet\`, method: 'POST', body: queryArg.pet }),
235259
}),
236260
findPetsByStatus: build.query<FindPetsByStatusApiResponse, FindPetsByStatusApiArg>({
237-
query: (queryArg) => ({ url: \`/pet/findByStatus\`, params: { status: queryArg.status } }),
261+
query: (queryArg) => ({
262+
url: \`/pet/findByStatus\`,
263+
params: {
264+
status: queryArg.status,
265+
},
266+
}),
238267
}),
239268
findPetsByTags: build.query<FindPetsByTagsApiResponse, FindPetsByTagsApiArg>({
240-
query: (queryArg) => ({ url: \`/pet/findByTags\`, params: { tags: queryArg.tags } }),
269+
query: (queryArg) => ({
270+
url: \`/pet/findByTags\`,
271+
params: {
272+
tags: queryArg.tags,
273+
},
274+
}),
241275
}),
242276
getPetById: build.query<GetPetByIdApiResponse, GetPetByIdApiArg>({
243277
query: (queryArg) => ({ url: \`/pet/\${queryArg.petId}\` }),
@@ -246,18 +280,29 @@ const injectedRtkApi = api.injectEndpoints({
246280
query: (queryArg) => ({
247281
url: \`/pet/\${queryArg.petId}\`,
248282
method: 'POST',
249-
params: { name: queryArg.name, status: queryArg.status },
283+
params: {
284+
name: queryArg.name,
285+
status: queryArg.status,
286+
},
250287
}),
251288
}),
252289
deletePet: build.mutation<DeletePetApiResponse, DeletePetApiArg>({
253-
query: (queryArg) => ({ url: \`/pet/\${queryArg.petId}\`, method: 'DELETE', headers: { api_key: queryArg.apiKey } }),
290+
query: (queryArg) => ({
291+
url: \`/pet/\${queryArg.petId}\`,
292+
method: 'DELETE',
293+
headers: {
294+
api_key: queryArg.apiKey,
295+
},
296+
}),
254297
}),
255298
uploadFile: build.mutation<UploadFileApiResponse, UploadFileApiArg>({
256299
query: (queryArg) => ({
257300
url: \`/pet/\${queryArg.petId}/uploadImage\`,
258301
method: 'POST',
259302
body: queryArg.body,
260-
params: { additionalMetadata: queryArg.additionalMetadata },
303+
params: {
304+
additionalMetadata: queryArg.additionalMetadata,
305+
},
261306
}),
262307
}),
263308
getInventory: build.query<GetInventoryApiResponse, GetInventoryApiArg>({
@@ -281,7 +326,10 @@ const injectedRtkApi = api.injectEndpoints({
281326
loginUser: build.query<LoginUserApiResponse, LoginUserApiArg>({
282327
query: (queryArg) => ({
283328
url: \`/user/login\`,
284-
params: { username: queryArg.username, password: queryArg.password },
329+
params: {
330+
username: queryArg.username,
331+
password: queryArg.password,
332+
},
285333
}),
286334
}),
287335
logoutUser: build.query<LogoutUserApiResponse, LogoutUserApiArg>({

0 commit comments

Comments
 (0)