typedapi-client-helpers 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/README.md +376 -48
- package/dist/cjs/utils/buildQuery.js +16 -4
- package/dist/cjs/utils/buildQuery.js.map +1 -1
- package/dist/esm/utils/buildQuery.js +15 -4
- package/dist/esm/utils/buildQuery.js.map +1 -1
- package/dist/types/utils/buildQuery.d.ts +8 -0
- package/dist/types/utils/buildQuery.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/openapi-generator/index.mjs +1 -1
- package/scripts/openapi-generator/method-template.mjs +220 -57
- package/scripts/openapi-generator/openapi-utils.mjs +412 -411
- package/scripts/openapi-generator/schema.mjs +476 -42
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Builds a typed query object from filter form values
|
|
2
|
+
* Builds a typed query object from filter form values without adding pagination or sorting.
|
|
3
3
|
*
|
|
4
4
|
* Empty filter values are ignored.
|
|
5
5
|
* List filters are converted item by item.
|
|
6
6
|
* `OptionValue` lists send their `value` fields instead of the display names.
|
|
7
7
|
*/
|
|
8
|
-
export function
|
|
9
|
-
|
|
8
|
+
export function buildFilterQuery(filters) {
|
|
9
|
+
return filters.reduce((queryResult, filter) => {
|
|
10
10
|
const { filterName, filterNameMax, type, value, maxValue, isAList } = filter;
|
|
11
11
|
if (isEmptyValue(value) && isEmptyValue(maxValue)) {
|
|
12
12
|
return queryResult;
|
|
@@ -28,11 +28,22 @@ export function buildQuery(filters, page = 1, pageSize = 100, sortBy = null, sor
|
|
|
28
28
|
if (filterNameMax && !isEmptyValue(maxValue)) {
|
|
29
29
|
const convertedMaxValue = convertType(type, maxValue);
|
|
30
30
|
if (convertedMaxValue !== null) {
|
|
31
|
-
queryResult[filterNameMax] =
|
|
31
|
+
queryResult[filterNameMax] =
|
|
32
|
+
convertedMaxValue;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
return queryResult;
|
|
35
36
|
}, {});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Builds a typed query object from filter form values, pagination, and sorting.
|
|
40
|
+
*
|
|
41
|
+
* Empty filter values are ignored.
|
|
42
|
+
* List filters are converted item by item.
|
|
43
|
+
* `OptionValue` lists send their `value` fields instead of the display names.
|
|
44
|
+
*/
|
|
45
|
+
export function buildQuery(filters, page = 1, pageSize = 100, sortBy = null, sortDirection) {
|
|
46
|
+
const query = buildFilterQuery(filters);
|
|
36
47
|
query.pageNumber = page;
|
|
37
48
|
if (pageSize > 0) {
|
|
38
49
|
query.pageSize = pageSize;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildQuery.js","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"buildQuery.js","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,14 @@ import { FilterFormValues } from "../interfaces/Filter";
|
|
|
5
5
|
* APIs often expose sort direction as either a string enum or numeric enum, so both are supported.
|
|
6
6
|
*/
|
|
7
7
|
export type SortDirection = number | string;
|
|
8
|
+
/**
|
|
9
|
+
* Builds a typed query object from filter form values without adding pagination or sorting.
|
|
10
|
+
*
|
|
11
|
+
* Empty filter values are ignored.
|
|
12
|
+
* List filters are converted item by item.
|
|
13
|
+
* `OptionValue` lists send their `value` fields instead of the display names.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildFilterQuery<TQuery>(filters: FilterFormValues<TQuery>[]): Partial<TQuery>;
|
|
8
16
|
/**
|
|
9
17
|
* Builds a typed query object from filter form values, pagination, and sorting.
|
|
10
18
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EACpD,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,EACnC,IAAI,SAAI,EACR,QAAQ,SAAM,EACd,MAAM,GAAE,MAAM,UAAU,GAAG,IAAW,EACtC,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"buildQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/buildQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EACrC,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,GAClC,OAAO,CAAC,MAAM,CAAC,CAyCjB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EACpD,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,EACnC,IAAI,SAAI,EACR,QAAQ,SAAM,EACd,MAAM,GAAE,MAAM,UAAU,GAAG,IAAW,EACtC,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@ export async function generateApi(options) {
|
|
|
19
19
|
const source = fs.readFileSync(inputPath, "utf8");
|
|
20
20
|
const openApi = JSON.parse(source);
|
|
21
21
|
|
|
22
|
-
validateOpenApiDocument(openApi, { supportedContractVersion:
|
|
22
|
+
validateOpenApiDocument(openApi, { supportedContractVersion: 2 });
|
|
23
23
|
const operations = collectOperations(openApi, {
|
|
24
24
|
generateMissingOperationIds: Boolean(options.generateMissingOperationIds),
|
|
25
25
|
methodNameStyle: options.methodNameStyle ?? "operationId",
|
|
@@ -9,22 +9,38 @@ function createImport(names, from, typeOnly = false) {
|
|
|
9
9
|
const cleanNames = unique(names).sort((a, b) => a.localeCompare(b));
|
|
10
10
|
if (cleanNames.length === 0) return "";
|
|
11
11
|
const keyword = typeOnly ? "import type" : "import";
|
|
12
|
-
if (cleanNames.length <= 3)
|
|
12
|
+
if (cleanNames.length <= 3)
|
|
13
|
+
return `${keyword} { ${cleanNames.join(", ")} } from ${JSON.stringify(from)};`;
|
|
13
14
|
return `${keyword} {\n${cleanNames.map((name) => ` ${name},`).join("\n")}\n} from ${JSON.stringify(from)};`;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
function isPrimitiveType(type) {
|
|
17
|
-
return /^(void|any|unknown|string|number|boolean|Blob|File|Record<)/.test(
|
|
18
|
+
return /^(void|any|unknown|string|number|boolean|Blob|File|Record<)/.test(
|
|
19
|
+
type,
|
|
20
|
+
);
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
function extractTopLevelTypeNames(type) {
|
|
21
|
-
const withoutLiterals = String(type ?? "").replace(
|
|
24
|
+
const withoutLiterals = String(type ?? "").replace(
|
|
25
|
+
/"(?:\\.|[^"])*"|'(?:\\.|[^'])*'/g,
|
|
26
|
+
"",
|
|
27
|
+
);
|
|
22
28
|
const matches = withoutLiterals.match(/\b[A-Z][A-Za-z0-9_]*\b/g) ?? [];
|
|
23
29
|
return matches.filter(
|
|
24
|
-
(name) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
(name) =>
|
|
31
|
+
![
|
|
32
|
+
"Array",
|
|
33
|
+
"Record",
|
|
34
|
+
"Promise",
|
|
35
|
+
"HttpResponse",
|
|
36
|
+
"Blob",
|
|
37
|
+
"File",
|
|
38
|
+
"ApiResult",
|
|
39
|
+
"RequestParams",
|
|
40
|
+
"FormData",
|
|
41
|
+
"ApiClientError",
|
|
42
|
+
"ApiHttpError",
|
|
43
|
+
].includes(name),
|
|
28
44
|
);
|
|
29
45
|
}
|
|
30
46
|
|
|
@@ -38,10 +54,11 @@ function parameterValueExpression(sourceExpression, parameter) {
|
|
|
38
54
|
|
|
39
55
|
function parameterObjectExpression(sourceExpression, parameters) {
|
|
40
56
|
const properties = parameters.map(
|
|
41
|
-
(parameter) =>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
(parameter) =>
|
|
58
|
+
`${JSON.stringify(parameter.name)}: ${parameterValueExpression(
|
|
59
|
+
sourceExpression,
|
|
60
|
+
parameter,
|
|
61
|
+
)}`,
|
|
45
62
|
);
|
|
46
63
|
return properties.length <= 2
|
|
47
64
|
? `{ ${properties.join(", ")} }`
|
|
@@ -73,7 +90,9 @@ function pathExpression(routePath, pathParams, inputName = "input") {
|
|
|
73
90
|
if (parts.length === 0) return JSON.stringify(routePath);
|
|
74
91
|
|
|
75
92
|
return parts
|
|
76
|
-
.map((part) =>
|
|
93
|
+
.map((part) =>
|
|
94
|
+
/^"/.test(part) ? part.slice(1, -1).replace(/`/g, "\\`") : `\${${part}}`,
|
|
95
|
+
)
|
|
77
96
|
.join("")
|
|
78
97
|
.replace(/^/, "`")
|
|
79
98
|
.replace(/$/, "`");
|
|
@@ -83,22 +102,31 @@ function requestFormat(responseContentType, responseType) {
|
|
|
83
102
|
if (responseType === "void" || !responseContentType) return undefined;
|
|
84
103
|
if (responseContentType.includes("json")) return "json";
|
|
85
104
|
if (responseContentType.startsWith("text/")) return "text";
|
|
86
|
-
if (
|
|
105
|
+
if (
|
|
106
|
+
responseContentType === "application/octet-stream" ||
|
|
107
|
+
responseType === "Blob"
|
|
108
|
+
)
|
|
109
|
+
return "blob";
|
|
87
110
|
return undefined;
|
|
88
111
|
}
|
|
89
112
|
|
|
90
113
|
function contentTypeEnum(contentType) {
|
|
91
114
|
switch (contentType) {
|
|
92
|
-
case "application/json":
|
|
93
|
-
|
|
94
|
-
case "
|
|
95
|
-
|
|
96
|
-
case "
|
|
97
|
-
|
|
115
|
+
case "application/json":
|
|
116
|
+
return "ContentType.Json";
|
|
117
|
+
case "application/vnd.api+json":
|
|
118
|
+
return "ContentType.JsonApi";
|
|
119
|
+
case "multipart/form-data":
|
|
120
|
+
return "ContentType.FormData";
|
|
121
|
+
case "application/x-www-form-urlencoded":
|
|
122
|
+
return "ContentType.UrlEncoded";
|
|
123
|
+
case "text/plain":
|
|
124
|
+
return "ContentType.Text";
|
|
125
|
+
default:
|
|
126
|
+
return contentType?.includes("json") ? "ContentType.Json" : undefined;
|
|
98
127
|
}
|
|
99
128
|
}
|
|
100
129
|
|
|
101
|
-
|
|
102
130
|
function requestItems(operationInfo, operationTypes, options = {}) {
|
|
103
131
|
const inputName = options.inputName ?? "input";
|
|
104
132
|
const items = [
|
|
@@ -114,7 +142,11 @@ function requestItems(operationInfo, operationTypes, options = {}) {
|
|
|
114
142
|
if (options.queryValueName) {
|
|
115
143
|
items.push(`query: ${options.queryValueName}`);
|
|
116
144
|
} else if (operationTypes.hasQueryParams) {
|
|
117
|
-
if (
|
|
145
|
+
if (
|
|
146
|
+
!operationTypes.hasPathParams &&
|
|
147
|
+
!operationTypes.hasHeaderParams &&
|
|
148
|
+
!operationTypes.hasCookieParams
|
|
149
|
+
) {
|
|
118
150
|
items.push(`query: ${inputName}`);
|
|
119
151
|
} else {
|
|
120
152
|
items.push(
|
|
@@ -145,9 +177,13 @@ function requestItems(operationInfo, operationTypes, options = {}) {
|
|
|
145
177
|
inputName,
|
|
146
178
|
operationTypes.parametersByLocation.cookie,
|
|
147
179
|
);
|
|
148
|
-
const cookieCondition =
|
|
149
|
-
.
|
|
150
|
-
|
|
180
|
+
const cookieCondition =
|
|
181
|
+
operationTypes.parametersByLocation.cookie
|
|
182
|
+
.map(
|
|
183
|
+
(parameter) =>
|
|
184
|
+
`${parameterValueExpression(inputName, parameter)} !== undefined`,
|
|
185
|
+
)
|
|
186
|
+
.join(" || ") || "false";
|
|
151
187
|
headerSources.push(
|
|
152
188
|
`${cookieCondition} ? { Cookie: toCookieHeader(${cookiesExpression}) } : undefined`,
|
|
153
189
|
);
|
|
@@ -157,7 +193,10 @@ function requestItems(operationInfo, operationTypes, options = {}) {
|
|
|
157
193
|
|
|
158
194
|
const type = contentTypeEnum(operationTypes.contentType);
|
|
159
195
|
if (type) items.push(`type: ${type}`);
|
|
160
|
-
const format = requestFormat(
|
|
196
|
+
const format = requestFormat(
|
|
197
|
+
operationTypes.responseContentType,
|
|
198
|
+
operationTypes.responseType,
|
|
199
|
+
);
|
|
161
200
|
if (format) items.push(`format: ${JSON.stringify(format)}`);
|
|
162
201
|
return items;
|
|
163
202
|
}
|
|
@@ -193,14 +232,33 @@ function promiseType(operationTypes) {
|
|
|
193
232
|
}
|
|
194
233
|
|
|
195
234
|
function isPaginated(operationTypes) {
|
|
196
|
-
return
|
|
235
|
+
return (
|
|
236
|
+
Boolean(operationTypes.paginationMetadata) ||
|
|
197
237
|
/(?:Api)?Pagination(?:Sort)?Response\b|Paged(?:Response|Result)?\b|Paginated(?:Response|Result)?\b/.test(
|
|
198
238
|
operationTypes.responseType,
|
|
199
|
-
)
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function isFilterForm(operationTypes) {
|
|
244
|
+
return Boolean(operationTypes.filterFormMetadata);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function isPureQueryMethod(operationTypes) {
|
|
248
|
+
return (
|
|
249
|
+
operationTypes.hasQueryParams &&
|
|
250
|
+
!operationTypes.hasPathParams &&
|
|
251
|
+
!operationTypes.bodyType &&
|
|
252
|
+
!operationTypes.hasHeaderParams &&
|
|
253
|
+
!operationTypes.hasCookieParams
|
|
254
|
+
);
|
|
200
255
|
}
|
|
201
256
|
|
|
202
257
|
function methodDescription(operationInfo, operationTypes) {
|
|
203
|
-
const description =
|
|
258
|
+
const description =
|
|
259
|
+
operationInfo.operation.description ||
|
|
260
|
+
operationInfo.operation.summary ||
|
|
261
|
+
"No description";
|
|
204
262
|
const tags = (operationInfo.operation.tags ?? []).join(", ");
|
|
205
263
|
return `/**\n * ${description.replace(/\n/g, "\n * ")}\n *\n * @tags ${tags}\n * @name ${operationTypes.methodNameSource}\n * @request ${operationInfo.method}:${operationInfo.routePath}\n */`;
|
|
206
264
|
}
|
|
@@ -214,7 +272,9 @@ function createRequestCall(operationInfo, operationTypes, options = {}) {
|
|
|
214
272
|
|
|
215
273
|
function createPaginatedMethod(operationInfo, operationTypes, defaultHandlers) {
|
|
216
274
|
const queryTypeName = operationTypes.parameterTypeNames.query;
|
|
217
|
-
const requestCall = createRequestCall(operationInfo, operationTypes, {
|
|
275
|
+
const requestCall = createRequestCall(operationInfo, operationTypes, {
|
|
276
|
+
queryValueName: "builtQuery",
|
|
277
|
+
});
|
|
218
278
|
return `${methodDescription(operationInfo, operationTypes)}
|
|
219
279
|
export async function ${operationTypes.methodName}(
|
|
220
280
|
filters: FilterFormValues<${queryTypeName}>[] = [],
|
|
@@ -237,13 +297,47 @@ export async function ${operationTypes.methodName}(
|
|
|
237
297
|
}`;
|
|
238
298
|
}
|
|
239
299
|
|
|
300
|
+
function createFilterFormMethod(
|
|
301
|
+
operationInfo,
|
|
302
|
+
operationTypes,
|
|
303
|
+
defaultHandlers,
|
|
304
|
+
) {
|
|
305
|
+
const queryTypeName = operationTypes.parameterTypeNames.query;
|
|
306
|
+
const queryPropertyOptional = operationTypes.allParametersOptional ? "?" : "";
|
|
307
|
+
const filterFormDefault = operationTypes.allParametersOptional ? " = {}" : "";
|
|
308
|
+
const requestCall = createRequestCall(operationInfo, operationTypes, {
|
|
309
|
+
queryValueName: "builtQuery",
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
return `${methodDescription(operationInfo, operationTypes)}
|
|
313
|
+
export async function ${operationTypes.methodName}(
|
|
314
|
+
filterForm: {
|
|
315
|
+
query${queryPropertyOptional}: ${queryTypeName};
|
|
316
|
+
filters?: FilterFormValues<${queryTypeName}>[];
|
|
317
|
+
}${filterFormDefault},
|
|
318
|
+
options: ${optionsType(operationTypes)} = {},
|
|
319
|
+
): ${promiseType(operationTypes)} {
|
|
320
|
+
const { onSuccess, onError, params = {} } = options;
|
|
321
|
+
const builtQuery = {
|
|
322
|
+
...(filterForm.query ?? {}),
|
|
323
|
+
...buildFilterQuery<${queryTypeName}>(filterForm.filters ?? []),
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
return handleApiResponse<${operationTypes.responseType}, ${operationTypes.errorType}>(
|
|
327
|
+
() => ${requestCall},
|
|
328
|
+
${callbackOptions(operationTypes, defaultHandlers)},
|
|
329
|
+
);
|
|
330
|
+
}`;
|
|
331
|
+
}
|
|
332
|
+
|
|
240
333
|
function regularParameterArgumentName(operationTypes) {
|
|
241
334
|
if (operationTypes.hasPathParams) return "pathParams";
|
|
242
335
|
if (
|
|
243
336
|
operationTypes.hasQueryParams &&
|
|
244
337
|
!operationTypes.hasHeaderParams &&
|
|
245
338
|
!operationTypes.hasCookieParams
|
|
246
|
-
)
|
|
339
|
+
)
|
|
340
|
+
return "query";
|
|
247
341
|
return "requestParams";
|
|
248
342
|
}
|
|
249
343
|
|
|
@@ -254,7 +348,8 @@ function createRegularMethod(operationInfo, operationTypes, defaultHandlers) {
|
|
|
254
348
|
: undefined;
|
|
255
349
|
|
|
256
350
|
if (operationTypes.paramsTypeName) {
|
|
257
|
-
const canOmitParams =
|
|
351
|
+
const canOmitParams =
|
|
352
|
+
operationTypes.allParametersOptional && !operationTypes.bodyType;
|
|
258
353
|
args.push(
|
|
259
354
|
`${parameterArgumentName}: ${operationTypes.paramsTypeName}${canOmitParams ? " = {}" : ""}`,
|
|
260
355
|
);
|
|
@@ -285,15 +380,26 @@ export async function ${operationTypes.methodName}(
|
|
|
285
380
|
|
|
286
381
|
function createMethod(operationInfo, operationTypes, defaultHandlers, options) {
|
|
287
382
|
if (
|
|
288
|
-
operationTypes
|
|
289
|
-
!operationTypes.hasPathParams &&
|
|
290
|
-
!operationTypes.bodyType &&
|
|
291
|
-
!operationTypes.hasHeaderParams &&
|
|
292
|
-
!operationTypes.hasCookieParams &&
|
|
383
|
+
isPureQueryMethod(operationTypes) &&
|
|
293
384
|
options.useFilterFormValues !== false &&
|
|
294
385
|
isPaginated(operationTypes)
|
|
295
386
|
) {
|
|
296
|
-
return createPaginatedMethod(
|
|
387
|
+
return createPaginatedMethod(
|
|
388
|
+
operationInfo,
|
|
389
|
+
operationTypes,
|
|
390
|
+
defaultHandlers,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
if (
|
|
394
|
+
isPureQueryMethod(operationTypes) &&
|
|
395
|
+
options.useFilterFormValues !== false &&
|
|
396
|
+
isFilterForm(operationTypes)
|
|
397
|
+
) {
|
|
398
|
+
return createFilterFormMethod(
|
|
399
|
+
operationInfo,
|
|
400
|
+
operationTypes,
|
|
401
|
+
defaultHandlers,
|
|
402
|
+
);
|
|
297
403
|
}
|
|
298
404
|
return createRegularMethod(operationInfo, operationTypes, defaultHandlers);
|
|
299
405
|
}
|
|
@@ -311,28 +417,43 @@ export function controllerNameForOperation(operationInfo, options = {}) {
|
|
|
311
417
|
return pascalCase(parts[1] ?? parts[0] ?? "Default", "Default");
|
|
312
418
|
}
|
|
313
419
|
|
|
314
|
-
export function generateMethodFile(
|
|
420
|
+
export function generateMethodFile(
|
|
421
|
+
openApi,
|
|
422
|
+
controllerName,
|
|
423
|
+
operations,
|
|
424
|
+
options = {},
|
|
425
|
+
) {
|
|
315
426
|
const dataContractImports = [];
|
|
316
427
|
const helperTypeImports = ["ApiResult", "ApiMethodOptions"];
|
|
317
428
|
const helperValueImports = ["handleApiResponse"];
|
|
318
429
|
const methods = [];
|
|
319
430
|
let needsContentType = false;
|
|
320
431
|
let needsPaginationTypes = false;
|
|
321
|
-
let
|
|
432
|
+
let needsFilterFormTypes = false;
|
|
433
|
+
let needsHeaderParams = false;
|
|
434
|
+
let needsCookieParams = false;
|
|
322
435
|
|
|
323
436
|
for (const operationInfo of operations) {
|
|
324
437
|
const operationTypes = getOperationTypes(openApi, operationInfo, options);
|
|
325
438
|
|
|
326
|
-
for (const typeName of Object.values(operationTypes.parameterTypeNames))
|
|
327
|
-
|
|
439
|
+
for (const typeName of Object.values(operationTypes.parameterTypeNames))
|
|
440
|
+
dataContractImports.push(typeName);
|
|
441
|
+
if (operationTypes.paramsTypeName)
|
|
442
|
+
dataContractImports.push(operationTypes.paramsTypeName);
|
|
328
443
|
if (operationTypes.bodyType && !isPrimitiveType(operationTypes.bodyType)) {
|
|
329
|
-
dataContractImports.push(
|
|
444
|
+
dataContractImports.push(
|
|
445
|
+
...extractTopLevelTypeNames(operationTypes.bodyType),
|
|
446
|
+
);
|
|
330
447
|
}
|
|
331
448
|
if (!isPrimitiveType(operationTypes.responseType)) {
|
|
332
|
-
dataContractImports.push(
|
|
449
|
+
dataContractImports.push(
|
|
450
|
+
...extractTopLevelTypeNames(operationTypes.responseType),
|
|
451
|
+
);
|
|
333
452
|
}
|
|
334
453
|
if (!isPrimitiveType(operationTypes.errorType)) {
|
|
335
|
-
dataContractImports.push(
|
|
454
|
+
dataContractImports.push(
|
|
455
|
+
...extractTopLevelTypeNames(operationTypes.errorType),
|
|
456
|
+
);
|
|
336
457
|
}
|
|
337
458
|
if (operationTypes.usesHttpErrorFallback) {
|
|
338
459
|
helperTypeImports.push("ApiHttpError");
|
|
@@ -340,36 +461,78 @@ export function generateMethodFile(openApi, controllerName, operations, options
|
|
|
340
461
|
}
|
|
341
462
|
|
|
342
463
|
if (contentTypeEnum(operationTypes.contentType)) needsContentType = true;
|
|
343
|
-
if (operationTypes.hasHeaderParams
|
|
464
|
+
if (operationTypes.hasHeaderParams) needsHeaderParams = true;
|
|
465
|
+
if (operationTypes.hasCookieParams) needsCookieParams = true;
|
|
344
466
|
if (
|
|
345
|
-
operationTypes
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
options.useFilterFormValues !== false && isPaginated(operationTypes)
|
|
467
|
+
isPureQueryMethod(operationTypes) &&
|
|
468
|
+
options.useFilterFormValues !== false &&
|
|
469
|
+
isPaginated(operationTypes)
|
|
349
470
|
) {
|
|
350
471
|
needsPaginationTypes = true;
|
|
472
|
+
} else if (
|
|
473
|
+
isPureQueryMethod(operationTypes) &&
|
|
474
|
+
options.useFilterFormValues !== false &&
|
|
475
|
+
isFilterForm(operationTypes)
|
|
476
|
+
) {
|
|
477
|
+
needsFilterFormTypes = true;
|
|
351
478
|
}
|
|
352
479
|
|
|
353
|
-
methods.push(
|
|
480
|
+
methods.push(
|
|
481
|
+
createMethod(
|
|
482
|
+
operationInfo,
|
|
483
|
+
operationTypes,
|
|
484
|
+
options.defaultHandlers,
|
|
485
|
+
options,
|
|
486
|
+
),
|
|
487
|
+
);
|
|
354
488
|
}
|
|
355
489
|
|
|
356
|
-
if (
|
|
490
|
+
if (needsHeaderParams || needsCookieParams)
|
|
491
|
+
helperValueImports.push("mergeHeaders");
|
|
492
|
+
if (needsHeaderParams) helperValueImports.push("toRequestHeaders");
|
|
493
|
+
if (needsCookieParams) helperValueImports.push("toCookieHeader");
|
|
357
494
|
if (needsPaginationTypes) {
|
|
358
495
|
helperValueImports.push("buildQuery");
|
|
359
496
|
helperTypeImports.push(
|
|
360
|
-
"ExtractDataIfPaginated",
|
|
497
|
+
"ExtractDataIfPaginated",
|
|
498
|
+
"FilterFormValues",
|
|
499
|
+
"SortableKeys",
|
|
500
|
+
"SortDirection",
|
|
501
|
+
"UnwrapArray",
|
|
361
502
|
);
|
|
362
503
|
}
|
|
504
|
+
if (needsFilterFormTypes) {
|
|
505
|
+
helperValueImports.push("buildFilterQuery");
|
|
506
|
+
helperTypeImports.push("FilterFormValues");
|
|
507
|
+
}
|
|
363
508
|
|
|
364
509
|
const useTypeOnlyImports = options.useTypeOnlyImports !== false;
|
|
365
510
|
const defaultHandlers = options.defaultHandlers;
|
|
366
511
|
const imports = [
|
|
367
512
|
generatedFileHeader(),
|
|
368
|
-
createImport(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
createImport(
|
|
513
|
+
createImport(
|
|
514
|
+
["request", ...(needsContentType ? ["ContentType"] : [])],
|
|
515
|
+
"../generated/http-client",
|
|
516
|
+
),
|
|
517
|
+
createImport(
|
|
518
|
+
["RequestParams"],
|
|
519
|
+
"../generated/http-client",
|
|
520
|
+
useTypeOnlyImports,
|
|
521
|
+
),
|
|
522
|
+
createImport(
|
|
523
|
+
dataContractImports,
|
|
524
|
+
"../generated/data-contracts",
|
|
525
|
+
useTypeOnlyImports,
|
|
526
|
+
),
|
|
527
|
+
createImport(
|
|
528
|
+
helperValueImports,
|
|
529
|
+
options.runtimePackageName ?? "typedapi-client-helpers",
|
|
530
|
+
),
|
|
531
|
+
createImport(
|
|
532
|
+
helperTypeImports,
|
|
533
|
+
options.runtimePackageName ?? "typedapi-client-helpers",
|
|
534
|
+
useTypeOnlyImports,
|
|
535
|
+
),
|
|
373
536
|
defaultHandlers
|
|
374
537
|
? `import { ${defaultHandlers.success} as typedApiDefaultSuccessHandler, ${defaultHandlers.error} as typedApiDefaultErrorHandler, ${defaultHandlers.errorMessage} as typedApiDefaultErrorMessage } from ${JSON.stringify(defaultHandlers.path)};`
|
|
375
538
|
: "",
|