typedapi-client-helpers 0.2.0 → 0.3.0
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 +68 -0
- package/LICENSE +21 -0
- package/README.md +221 -220
- package/dist/cjs/httpClient.js +258 -0
- package/dist/cjs/httpClient.js.map +1 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/interfaces/ApiResult.js +3 -0
- package/dist/cjs/interfaces/ApiResult.js.map +1 -0
- package/dist/cjs/interfaces/Filter.js +3 -0
- package/dist/cjs/interfaces/Filter.js.map +1 -0
- package/dist/cjs/interfaces/SortType.js +3 -0
- package/dist/cjs/interfaces/SortType.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types/ApiCallOptions.js +3 -0
- package/dist/cjs/types/ApiCallOptions.js.map +1 -0
- package/dist/cjs/types/ApiMethodArguments.js +3 -0
- package/dist/cjs/types/ApiMethodArguments.js.map +1 -0
- package/dist/cjs/types/ApiMethodOptions.js +3 -0
- package/dist/cjs/types/ApiMethodOptions.js.map +1 -0
- package/dist/cjs/types/ApiMethodTypes.js +3 -0
- package/dist/cjs/types/ApiMethodTypes.js.map +1 -0
- package/dist/cjs/types/HttpResponse.js +3 -0
- package/dist/cjs/types/HttpResponse.js.map +1 -0
- package/dist/cjs/types/httpClientTypes.js +3 -0
- package/dist/cjs/types/httpClientTypes.js.map +1 -0
- package/dist/cjs/utils/SortTypeFromSortDirection.js +43 -0
- package/dist/cjs/utils/SortTypeFromSortDirection.js.map +1 -0
- package/dist/cjs/utils/buildQuery.js +96 -0
- package/dist/cjs/utils/buildQuery.js.map +1 -0
- package/dist/cjs/utils/extractArgsCallbacksAndParams.js +51 -0
- package/dist/cjs/utils/extractArgsCallbacksAndParams.js.map +1 -0
- package/dist/cjs/utils/extractArgsToastsAndParams.js +49 -0
- package/dist/cjs/utils/extractArgsToastsAndParams.js.map +1 -0
- package/dist/cjs/utils/handleApiResponse.js +124 -0
- package/dist/cjs/utils/handleApiResponse.js.map +1 -0
- package/dist/cjs/utils/toFormData.js +58 -0
- package/dist/cjs/utils/toFormData.js.map +1 -0
- package/dist/cjs/utils/wireMapping.js +123 -0
- package/dist/cjs/utils/wireMapping.js.map +1 -0
- package/dist/esm/httpClient.js +251 -0
- package/dist/esm/httpClient.js.map +1 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interfaces/ApiResult.js +2 -0
- package/dist/esm/interfaces/ApiResult.js.map +1 -0
- package/dist/esm/interfaces/Filter.js +2 -0
- package/dist/esm/interfaces/Filter.js.map +1 -0
- package/dist/esm/interfaces/SortType.js +2 -0
- package/dist/esm/interfaces/SortType.js.map +1 -0
- package/dist/esm/types/ApiCallOptions.js +2 -0
- package/dist/esm/types/ApiCallOptions.js.map +1 -0
- package/dist/esm/types/ApiMethodArguments.js +2 -0
- package/dist/esm/types/ApiMethodArguments.js.map +1 -0
- package/dist/esm/types/ApiMethodOptions.js +2 -0
- package/dist/esm/types/ApiMethodOptions.js.map +1 -0
- package/dist/esm/types/ApiMethodTypes.js +2 -0
- package/dist/esm/types/ApiMethodTypes.js.map +1 -0
- package/dist/esm/types/HttpResponse.js +2 -0
- package/dist/esm/types/HttpResponse.js.map +1 -0
- package/dist/esm/types/httpClientTypes.js +2 -0
- package/dist/esm/types/httpClientTypes.js.map +1 -0
- package/dist/esm/utils/SortTypeFromSortDirection.js +38 -0
- package/dist/esm/utils/SortTypeFromSortDirection.js.map +1 -0
- package/dist/esm/utils/buildQuery.js +93 -0
- package/dist/esm/utils/buildQuery.js.map +1 -0
- package/dist/esm/utils/extractArgsCallbacksAndParams.js +48 -0
- package/dist/esm/utils/extractArgsCallbacksAndParams.js.map +1 -0
- package/dist/esm/utils/extractArgsToastsAndParams.js +46 -0
- package/dist/esm/utils/extractArgsToastsAndParams.js.map +1 -0
- package/dist/esm/utils/handleApiResponse.js +121 -0
- package/dist/esm/utils/handleApiResponse.js.map +1 -0
- package/dist/esm/utils/toFormData.js +55 -0
- package/dist/esm/utils/toFormData.js.map +1 -0
- package/dist/esm/utils/wireMapping.js +119 -0
- package/dist/esm/utils/wireMapping.js.map +1 -0
- package/dist/types/httpClient.d.ts +63 -0
- package/dist/types/httpClient.d.ts.map +1 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/interfaces/ApiResult.d.ts +32 -0
- package/dist/types/interfaces/ApiResult.d.ts.map +1 -0
- package/dist/types/interfaces/Filter.d.ts +31 -0
- package/dist/types/interfaces/Filter.d.ts.map +1 -0
- package/dist/types/interfaces/SortType.d.ts +7 -0
- package/dist/types/interfaces/SortType.d.ts.map +1 -0
- package/dist/types/types/ApiCallOptions.d.ts +26 -0
- package/dist/types/types/ApiCallOptions.d.ts.map +1 -0
- package/dist/types/types/ApiMethodArguments.d.ts +6 -0
- package/dist/types/types/ApiMethodArguments.d.ts.map +1 -0
- package/dist/types/types/ApiMethodOptions.d.ts +8 -0
- package/dist/types/types/ApiMethodOptions.d.ts.map +1 -0
- package/dist/types/types/ApiMethodTypes.d.ts +47 -0
- package/dist/types/types/ApiMethodTypes.d.ts.map +1 -0
- package/dist/types/types/HttpResponse.d.ts +2 -0
- package/dist/types/types/HttpResponse.d.ts.map +1 -0
- package/dist/types/types/httpClientTypes.d.ts +2 -0
- package/dist/types/types/httpClientTypes.d.ts.map +1 -0
- package/dist/types/utils/SortTypeFromSortDirection.d.ts +13 -0
- package/dist/types/utils/SortTypeFromSortDirection.d.ts.map +1 -0
- package/dist/types/utils/buildQuery.d.ts +16 -0
- package/dist/types/utils/buildQuery.d.ts.map +1 -0
- package/dist/types/utils/extractArgsCallbacksAndParams.d.ts +22 -0
- package/dist/types/utils/extractArgsCallbacksAndParams.d.ts.map +1 -0
- package/dist/types/utils/extractArgsToastsAndParams.d.ts +20 -0
- package/dist/types/utils/extractArgsToastsAndParams.d.ts.map +1 -0
- package/dist/types/utils/handleApiResponse.d.ts +11 -0
- package/dist/types/utils/handleApiResponse.d.ts.map +1 -0
- package/dist/types/utils/toFormData.d.ts +10 -0
- package/dist/types/utils/toFormData.d.ts.map +1 -0
- package/dist/types/utils/wireMapping.d.ts +30 -0
- package/dist/types/utils/wireMapping.d.ts.map +1 -0
- package/package.json +90 -82
- package/scripts/build.mjs +74 -0
- package/scripts/generate-api-minimal.mjs +568 -476
- package/scripts/openapi-generator/controller-template.mjs +1 -1
- package/scripts/openapi-generator/index.mjs +357 -113
- package/scripts/openapi-generator/method-template.mjs +201 -244
- package/scripts/openapi-generator/names.mjs +37 -86
- package/scripts/openapi-generator/openapi-utils.mjs +411 -147
- package/scripts/openapi-generator/schema.mjs +518 -238
- package/dist/index.cjs +0 -536
- package/dist/index.d.cts +0 -285
- package/dist/index.d.ts +0 -285
- package/dist/index.js +0 -495
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getOperationTypes, generatedFileHeader } from "./schema.mjs";
|
|
2
|
-
import { pascalCase,
|
|
2
|
+
import { pascalCase, typePropertyName } from "./names.mjs";
|
|
3
3
|
|
|
4
4
|
function unique(values) {
|
|
5
5
|
return [...new Set(values.filter(Boolean))];
|
|
@@ -9,45 +9,48 @@ 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) {
|
|
13
|
-
return `${keyword} { ${cleanNames.join(", ")} } from ${JSON.stringify(from)};`;
|
|
14
|
-
}
|
|
12
|
+
if (cleanNames.length <= 3) return `${keyword} { ${cleanNames.join(", ")} } from ${JSON.stringify(from)};`;
|
|
15
13
|
return `${keyword} {\n${cleanNames.map((name) => ` ${name},`).join("\n")}\n} from ${JSON.stringify(from)};`;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
function isPrimitiveType(type) {
|
|
19
|
-
return /^(void|any|unknown|string|number|boolean|Blob|File|Record<)/.test(
|
|
20
|
-
type,
|
|
21
|
-
);
|
|
17
|
+
return /^(void|any|unknown|string|number|boolean|Blob|File|Record<)/.test(type);
|
|
22
18
|
}
|
|
23
19
|
|
|
24
20
|
function extractTopLevelTypeNames(type) {
|
|
25
|
-
const withoutLiterals = String(type ?? "").replace(
|
|
26
|
-
/"(?:\\.|[^"])*"|'(?:\\.|[^'])*'/g,
|
|
27
|
-
"",
|
|
28
|
-
);
|
|
21
|
+
const withoutLiterals = String(type ?? "").replace(/"(?:\\.|[^"])*"|'(?:\\.|[^'])*'/g, "");
|
|
29
22
|
const matches = withoutLiterals.match(/\b[A-Z][A-Za-z0-9_]*\b/g) ?? [];
|
|
30
23
|
return matches.filter(
|
|
31
|
-
(name) =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
(name) => ![
|
|
25
|
+
"Array", "Record", "Promise", "HttpResponse", "Blob", "File", "ApiResult",
|
|
26
|
+
"RequestParams", "FormData", "ApiClientError",
|
|
27
|
+
].includes(name),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function localPropertyAccess(baseExpression, wireName) {
|
|
32
|
+
return `${baseExpression}[${JSON.stringify(typePropertyName(wireName))}]`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parameterValueExpression(sourceExpression, parameter) {
|
|
36
|
+
return localPropertyAccess(sourceExpression, parameter.name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function parameterObjectExpression(sourceExpression, parameters) {
|
|
40
|
+
const properties = parameters.map(
|
|
41
|
+
(parameter) => `${JSON.stringify(parameter.name)}: ${parameterValueExpression(
|
|
42
|
+
sourceExpression,
|
|
43
|
+
parameter,
|
|
44
|
+
)}`,
|
|
43
45
|
);
|
|
46
|
+
return properties.length <= 2
|
|
47
|
+
? `{ ${properties.join(", ")} }`
|
|
48
|
+
: `{
|
|
49
|
+
${properties.map((property) => ` ${property},`).join("\n")}
|
|
50
|
+
}`;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
function pathExpression(
|
|
47
|
-
routePath,
|
|
48
|
-
pathParams,
|
|
49
|
-
paramsObjectName = "pathParams",
|
|
50
|
-
) {
|
|
53
|
+
function pathExpression(routePath, pathParams, inputName = "input") {
|
|
51
54
|
const parts = [];
|
|
52
55
|
let cursor = 0;
|
|
53
56
|
const regex = /\{([^}]+)\}/g;
|
|
@@ -57,144 +60,169 @@ function pathExpression(
|
|
|
57
60
|
const [placeholder, paramName] = match;
|
|
58
61
|
const before = routePath.slice(cursor, match.index);
|
|
59
62
|
if (before) parts.push(JSON.stringify(before));
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
const parameter = pathParams.find((item) => item.name === paramName);
|
|
64
|
+
const valueExpression = parameter
|
|
65
|
+
? parameterValueExpression(inputName, parameter)
|
|
66
|
+
: localPropertyAccess(inputName, paramName);
|
|
67
|
+
parts.push(`encodeURIComponent(String(${valueExpression}))`);
|
|
63
68
|
cursor = match.index + placeholder.length;
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
const after = routePath.slice(cursor);
|
|
67
72
|
if (after) parts.push(JSON.stringify(after));
|
|
68
|
-
|
|
69
73
|
if (parts.length === 0) return JSON.stringify(routePath);
|
|
70
74
|
|
|
71
75
|
return parts
|
|
72
|
-
.map((part) =>
|
|
73
|
-
/^"/.test(part) ? part.slice(1, -1).replace(/`/g, "\\`") : `\${${part}}`,
|
|
74
|
-
)
|
|
76
|
+
.map((part) => /^"/.test(part) ? part.slice(1, -1).replace(/`/g, "\\`") : `\${${part}}`)
|
|
75
77
|
.join("")
|
|
76
78
|
.replace(/^/, "`")
|
|
77
79
|
.replace(/$/, "`");
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
function requestFormat(responseContentType, responseType) {
|
|
81
|
-
if (responseType === "void") return undefined;
|
|
82
|
-
if (!responseContentType) return undefined;
|
|
83
|
+
if (responseType === "void" || !responseContentType) return undefined;
|
|
83
84
|
if (responseContentType.includes("json")) return "json";
|
|
84
85
|
if (responseContentType.startsWith("text/")) return "text";
|
|
85
|
-
if (
|
|
86
|
-
responseContentType === "application/octet-stream" ||
|
|
87
|
-
responseType === "Blob"
|
|
88
|
-
)
|
|
89
|
-
return "blob";
|
|
86
|
+
if (responseContentType === "application/octet-stream" || responseType === "Blob") return "blob";
|
|
90
87
|
return undefined;
|
|
91
88
|
}
|
|
92
89
|
|
|
93
90
|
function contentTypeEnum(contentType) {
|
|
94
91
|
switch (contentType) {
|
|
95
|
-
case "application/json":
|
|
96
|
-
|
|
97
|
-
case "
|
|
98
|
-
|
|
99
|
-
case "
|
|
100
|
-
|
|
101
|
-
case "application/x-www-form-urlencoded":
|
|
102
|
-
return "ContentType.UrlEncoded";
|
|
103
|
-
case "text/plain":
|
|
104
|
-
return "ContentType.Text";
|
|
105
|
-
default:
|
|
106
|
-
return contentType?.includes("json") ? "ContentType.Json" : undefined;
|
|
92
|
+
case "application/json": return "ContentType.Json";
|
|
93
|
+
case "application/vnd.api+json": return "ContentType.JsonApi";
|
|
94
|
+
case "multipart/form-data": return "ContentType.FormData";
|
|
95
|
+
case "application/x-www-form-urlencoded": return "ContentType.UrlEncoded";
|
|
96
|
+
case "text/plain": return "ContentType.Text";
|
|
97
|
+
default: return contentType?.includes("json") ? "ContentType.Json" : undefined;
|
|
107
98
|
}
|
|
108
99
|
}
|
|
109
100
|
|
|
110
|
-
function
|
|
111
|
-
if (!
|
|
112
|
-
|
|
113
|
-
if (!operationTypes.hasPathParams) {
|
|
114
|
-
return `${queryValueName} ?? {}`;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const entries = operationTypes.queryParams.map((parameter) => {
|
|
118
|
-
const identifier = sanitizeIdentifier(parameter.name);
|
|
119
|
-
return `${JSON.stringify(parameter.name)}: pathParams.${identifier}`;
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
return `{ ${entries.join(", ")} }`;
|
|
101
|
+
function toWireExpression(valueExpression, schemaKey) {
|
|
102
|
+
if (!schemaKey) return valueExpression;
|
|
103
|
+
return `toWireValue(${valueExpression}, typedApiWireSchemas[${JSON.stringify(schemaKey)}], typedApiWireSchemas)`;
|
|
123
104
|
}
|
|
124
105
|
|
|
125
106
|
function requestItems(operationInfo, operationTypes, options = {}) {
|
|
107
|
+
const inputName = options.inputName ?? "input";
|
|
126
108
|
const items = [
|
|
127
|
-
|
|
109
|
+
"...params",
|
|
110
|
+
`path: ${pathExpression(
|
|
111
|
+
operationInfo.routePath,
|
|
112
|
+
operationTypes.parametersByLocation.path,
|
|
113
|
+
inputName,
|
|
114
|
+
)}`,
|
|
128
115
|
`method: ${JSON.stringify(operationInfo.method)}`,
|
|
129
116
|
];
|
|
130
117
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
118
|
+
if (options.queryValueName) {
|
|
119
|
+
items.push(`query: ${options.queryValueName}`);
|
|
120
|
+
} else if (operationTypes.hasQueryParams) {
|
|
121
|
+
items.push(
|
|
122
|
+
`query: ${parameterObjectExpression(
|
|
123
|
+
inputName,
|
|
124
|
+
operationTypes.parametersByLocation.query,
|
|
125
|
+
)}`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
136
128
|
|
|
137
129
|
if (operationTypes.bodyType) {
|
|
138
|
-
|
|
130
|
+
const bodyExpression = options.bodyValueName ?? "data";
|
|
131
|
+
items.push(`body: ${toWireExpression(bodyExpression, operationTypes.bodyWireSchemaKey)}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (operationTypes.hasHeaderParams || operationTypes.hasCookieParams) {
|
|
135
|
+
const headerSources = ["params.headers"];
|
|
136
|
+
if (operationTypes.hasHeaderParams) {
|
|
137
|
+
const headersExpression = parameterObjectExpression(
|
|
138
|
+
inputName,
|
|
139
|
+
operationTypes.parametersByLocation.header,
|
|
140
|
+
);
|
|
141
|
+
headerSources.push(`toRequestHeaders(${headersExpression})`);
|
|
142
|
+
}
|
|
143
|
+
if (operationTypes.hasCookieParams) {
|
|
144
|
+
const cookiesExpression = parameterObjectExpression(
|
|
145
|
+
inputName,
|
|
146
|
+
operationTypes.parametersByLocation.cookie,
|
|
147
|
+
);
|
|
148
|
+
const cookieCondition = operationTypes.parametersByLocation.cookie
|
|
149
|
+
.map((parameter) => `${parameterValueExpression(inputName, parameter)} !== undefined`)
|
|
150
|
+
.join(" || ") || "false";
|
|
151
|
+
headerSources.push(
|
|
152
|
+
`${cookieCondition} ? { Cookie: toCookieHeader(${cookiesExpression}) } : undefined`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
items.push(`headers: mergeHeaders(${headerSources.join(", ")})`);
|
|
139
156
|
}
|
|
140
157
|
|
|
141
158
|
const type = contentTypeEnum(operationTypes.contentType);
|
|
142
159
|
if (type) items.push(`type: ${type}`);
|
|
143
|
-
|
|
144
|
-
const format = requestFormat(
|
|
145
|
-
operationTypes.responseContentType,
|
|
146
|
-
operationTypes.responseType,
|
|
147
|
-
);
|
|
160
|
+
const format = requestFormat(operationTypes.responseContentType, operationTypes.responseType);
|
|
148
161
|
if (format) items.push(`format: ${JSON.stringify(format)}`);
|
|
149
|
-
|
|
150
|
-
items.push("...params");
|
|
151
162
|
return items;
|
|
152
163
|
}
|
|
153
164
|
|
|
154
|
-
function callbackOptions(defaultHandlers) {
|
|
155
|
-
|
|
165
|
+
function callbackOptions(operationTypes, defaultHandlers) {
|
|
166
|
+
const items = [];
|
|
167
|
+
if (defaultHandlers) {
|
|
168
|
+
items.push("onSuccess: onSuccess ?? typedApiDefaultSuccessHandler");
|
|
169
|
+
items.push("onError: onError ?? typedApiDefaultErrorHandler");
|
|
170
|
+
} else {
|
|
171
|
+
items.push("onSuccess");
|
|
172
|
+
items.push("onError");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (operationTypes.responseWireSchemaKey) {
|
|
176
|
+
items.push(
|
|
177
|
+
`transformResponse: (value) => fromWireValue(value, typedApiWireSchemas[${JSON.stringify(
|
|
178
|
+
operationTypes.responseWireSchemaKey,
|
|
179
|
+
)}], typedApiWireSchemas) as ${operationTypes.responseType}`,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
if (operationTypes.errorWireSchemaKey) {
|
|
183
|
+
items.push(
|
|
184
|
+
`transformError: (value) => fromWireValue(value, typedApiWireSchemas[${JSON.stringify(
|
|
185
|
+
operationTypes.errorWireSchemaKey,
|
|
186
|
+
)}], typedApiWireSchemas) as ${operationTypes.errorType}`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
156
189
|
|
|
157
|
-
return
|
|
190
|
+
return items.length <= 2
|
|
191
|
+
? `{ ${items.join(", ")} }`
|
|
192
|
+
: `{\n ${items.join(",\n ")},\n }`;
|
|
158
193
|
}
|
|
159
194
|
|
|
160
195
|
function optionsType(operationTypes) {
|
|
161
|
-
return `ApiMethodOptions<${operationTypes.responseType},
|
|
196
|
+
return `ApiMethodOptions<${operationTypes.responseType}, ${operationTypes.errorType}, RequestParams>`;
|
|
162
197
|
}
|
|
163
198
|
|
|
164
199
|
function promiseType(operationTypes) {
|
|
165
|
-
return `Promise<ApiResult<${operationTypes.responseType}>>`;
|
|
200
|
+
return `Promise<ApiResult<${operationTypes.responseType}, ${operationTypes.errorType}>>`;
|
|
166
201
|
}
|
|
167
202
|
|
|
168
203
|
function isPaginated(operationTypes) {
|
|
169
|
-
return
|
|
170
|
-
|
|
171
|
-
|
|
204
|
+
return Boolean(operationTypes.paginationMetadata) ||
|
|
205
|
+
/(?:Api)?Pagination(?:Sort)?Response\b|Paged(?:Response|Result)?\b|Paginated(?:Response|Result)?\b/.test(
|
|
206
|
+
operationTypes.responseType,
|
|
207
|
+
);
|
|
172
208
|
}
|
|
173
209
|
|
|
174
210
|
function methodDescription(operationInfo, operationTypes) {
|
|
175
|
-
const description =
|
|
176
|
-
operationInfo.operation.description ||
|
|
177
|
-
operationInfo.operation.summary ||
|
|
178
|
-
"No description";
|
|
211
|
+
const description = operationInfo.operation.description || operationInfo.operation.summary || "No description";
|
|
179
212
|
const tags = (operationInfo.operation.tags ?? []).join(", ");
|
|
180
|
-
|
|
181
|
-
return `/**\n * ${description.replace(/\n/g, "\n * ")}\n *\n * @tags ${tags}\n * @name ${operationTypes.operationId}\n * @request ${operationInfo.method}:${operationInfo.routePath}\n */`;
|
|
213
|
+
return `/**\n * ${description.replace(/\n/g, "\n * ")}\n *\n * @tags ${tags}\n * @name ${operationTypes.methodNameSource}\n * @request ${operationInfo.method}:${operationInfo.routePath}\n */`;
|
|
182
214
|
}
|
|
183
215
|
|
|
184
216
|
function createRequestCall(operationInfo, operationTypes, options = {}) {
|
|
185
217
|
const items = requestItems(operationInfo, operationTypes, options)
|
|
186
218
|
.map((item) => ` ${item},`)
|
|
187
219
|
.join("\n");
|
|
188
|
-
|
|
189
|
-
return `request<${operationTypes.responseType}, any>({\n${items}\n })`;
|
|
220
|
+
return `request<${operationTypes.responseType}, ${operationTypes.errorType}>({\n${items}\n })`;
|
|
190
221
|
}
|
|
191
222
|
|
|
192
223
|
function createPaginatedMethod(operationInfo, operationTypes, defaultHandlers) {
|
|
193
|
-
const queryTypeName =
|
|
194
|
-
const requestCall = createRequestCall(operationInfo, operationTypes, {
|
|
195
|
-
queryValueName: "builtQuery",
|
|
196
|
-
});
|
|
197
|
-
|
|
224
|
+
const queryTypeName = operationTypes.parameterTypeNames.query;
|
|
225
|
+
const requestCall = createRequestCall(operationInfo, operationTypes, { queryValueName: "builtQuery" });
|
|
198
226
|
return `${methodDescription(operationInfo, operationTypes)}
|
|
199
227
|
export async function ${operationTypes.methodName}(
|
|
200
228
|
filters: FilterFormValues<${queryTypeName}>[] = [],
|
|
@@ -204,48 +232,40 @@ export async function ${operationTypes.methodName}(
|
|
|
204
232
|
sortDirection?: SortDirection,
|
|
205
233
|
options: ${optionsType(operationTypes)} = {},
|
|
206
234
|
): ${promiseType(operationTypes)} {
|
|
207
|
-
const { onSuccess, onError, params } = options;
|
|
235
|
+
const { onSuccess, onError, params = {} } = options;
|
|
208
236
|
const builtQuery = buildQuery<
|
|
209
237
|
${queryTypeName},
|
|
210
238
|
UnwrapArray<ExtractDataIfPaginated<${operationTypes.responseType}>>
|
|
211
239
|
>(filters, page, pageSize, sortBy, sortDirection);
|
|
212
240
|
|
|
213
|
-
return handleApiResponse<${operationTypes.responseType},
|
|
241
|
+
return handleApiResponse<${operationTypes.responseType}, ${operationTypes.errorType}>(
|
|
214
242
|
() => ${requestCall},
|
|
215
|
-
${callbackOptions(defaultHandlers)},
|
|
243
|
+
${callbackOptions(operationTypes, defaultHandlers)},
|
|
216
244
|
);
|
|
217
245
|
}`;
|
|
218
246
|
}
|
|
219
247
|
|
|
220
|
-
function
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
return `${methodDescription(operationInfo, operationTypes)}
|
|
231
|
-
export async function ${operationTypes.methodName}(
|
|
232
|
-
query?: ${queryTypeName},
|
|
233
|
-
options: ${optionsType(operationTypes)} = {},
|
|
234
|
-
): ${promiseType(operationTypes)} {
|
|
235
|
-
const { onSuccess, onError, params } = options;
|
|
236
|
-
|
|
237
|
-
return handleApiResponse<${operationTypes.responseType}, any>(
|
|
238
|
-
() => ${requestCall},
|
|
239
|
-
${callbackOptions(defaultHandlers)},
|
|
240
|
-
);
|
|
241
|
-
}`;
|
|
248
|
+
function regularParameterArgumentName(operationTypes) {
|
|
249
|
+
if (operationTypes.hasPathParams) return "pathParams";
|
|
250
|
+
if (
|
|
251
|
+
operationTypes.hasQueryParams &&
|
|
252
|
+
!operationTypes.hasHeaderParams &&
|
|
253
|
+
!operationTypes.hasCookieParams
|
|
254
|
+
) return "query";
|
|
255
|
+
return "requestParams";
|
|
242
256
|
}
|
|
243
257
|
|
|
244
|
-
function
|
|
258
|
+
function createRegularMethod(operationInfo, operationTypes, defaultHandlers) {
|
|
245
259
|
const args = [];
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
260
|
+
const parameterArgumentName = operationTypes.paramsTypeName
|
|
261
|
+
? regularParameterArgumentName(operationTypes)
|
|
262
|
+
: undefined;
|
|
263
|
+
|
|
264
|
+
if (operationTypes.paramsTypeName) {
|
|
265
|
+
const canOmitParams = operationTypes.allParametersOptional && !operationTypes.bodyType;
|
|
266
|
+
args.push(
|
|
267
|
+
`${parameterArgumentName}: ${operationTypes.paramsTypeName}${canOmitParams ? " = {}" : ""}`,
|
|
268
|
+
);
|
|
249
269
|
}
|
|
250
270
|
|
|
251
271
|
if (operationTypes.bodyType) {
|
|
@@ -253,27 +273,20 @@ function wrapperArguments(operationTypes) {
|
|
|
253
273
|
}
|
|
254
274
|
|
|
255
275
|
args.push(`options: ${optionsType(operationTypes)} = {}`);
|
|
256
|
-
return args.join(",\n ");
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function createRegularMethod(operationInfo, operationTypes, defaultHandlers) {
|
|
260
|
-
const isFormData = operationTypes.contentType === "multipart/form-data";
|
|
261
276
|
const requestCall = createRequestCall(operationInfo, operationTypes, {
|
|
262
|
-
|
|
277
|
+
inputName: parameterArgumentName ?? "undefined",
|
|
278
|
+
bodyValueName: operationTypes.bodyType ? "data" : undefined,
|
|
263
279
|
});
|
|
264
280
|
|
|
265
|
-
const formDataLine = isFormData
|
|
266
|
-
? "\n const formData = toFormData(data);\n"
|
|
267
|
-
: "";
|
|
268
|
-
|
|
269
281
|
return `${methodDescription(operationInfo, operationTypes)}
|
|
270
282
|
export async function ${operationTypes.methodName}(
|
|
271
|
-
${
|
|
283
|
+
${args.join(",\n ")}
|
|
272
284
|
): ${promiseType(operationTypes)} {
|
|
273
|
-
const { onSuccess, onError, params } = options
|
|
274
|
-
|
|
285
|
+
const { onSuccess, onError, params = {} } = options;
|
|
286
|
+
|
|
287
|
+
return handleApiResponse<${operationTypes.responseType}, ${operationTypes.errorType}>(
|
|
275
288
|
() => ${requestCall},
|
|
276
|
-
${callbackOptions(defaultHandlers)},
|
|
289
|
+
${callbackOptions(operationTypes, defaultHandlers)},
|
|
277
290
|
);
|
|
278
291
|
}`;
|
|
279
292
|
}
|
|
@@ -282,28 +295,14 @@ function createMethod(operationInfo, operationTypes, defaultHandlers, options) {
|
|
|
282
295
|
if (
|
|
283
296
|
operationTypes.hasQueryParams &&
|
|
284
297
|
!operationTypes.hasPathParams &&
|
|
298
|
+
!operationTypes.bodyType &&
|
|
299
|
+
!operationTypes.hasHeaderParams &&
|
|
300
|
+
!operationTypes.hasCookieParams &&
|
|
285
301
|
options.useFilterFormValues !== false &&
|
|
286
302
|
isPaginated(operationTypes)
|
|
287
303
|
) {
|
|
288
|
-
return createPaginatedMethod(
|
|
289
|
-
operationInfo,
|
|
290
|
-
operationTypes,
|
|
291
|
-
defaultHandlers,
|
|
292
|
-
);
|
|
304
|
+
return createPaginatedMethod(operationInfo, operationTypes, defaultHandlers);
|
|
293
305
|
}
|
|
294
|
-
|
|
295
|
-
if (
|
|
296
|
-
operationTypes.hasQueryParams &&
|
|
297
|
-
!operationTypes.hasPathParams &&
|
|
298
|
-
!operationTypes.bodyType
|
|
299
|
-
) {
|
|
300
|
-
return createSimpleQueryMethod(
|
|
301
|
-
operationInfo,
|
|
302
|
-
operationTypes,
|
|
303
|
-
defaultHandlers,
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
306
|
return createRegularMethod(operationInfo, operationTypes, defaultHandlers);
|
|
308
307
|
}
|
|
309
308
|
|
|
@@ -316,125 +315,83 @@ export function controllerNameForOperation(operationInfo, options = {}) {
|
|
|
316
315
|
const [tag] = operationInfo.operation.tags ?? [];
|
|
317
316
|
if (tag) return pascalCase(tag, "Default");
|
|
318
317
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
operationInfo.routePath.split("/").filter(Boolean)[1] ??
|
|
322
|
-
operationInfo.routePath.split("/").filter(Boolean)[0] ??
|
|
323
|
-
"Default";
|
|
324
|
-
|
|
325
|
-
return pascalCase(firstPathPart, "Default");
|
|
318
|
+
const parts = operationInfo.routePath.split("/").filter(Boolean);
|
|
319
|
+
return pascalCase(parts[1] ?? parts[0] ?? "Default", "Default");
|
|
326
320
|
}
|
|
327
321
|
|
|
328
|
-
export function generateMethodFile(
|
|
329
|
-
openApi,
|
|
330
|
-
controllerName,
|
|
331
|
-
operations,
|
|
332
|
-
options = {},
|
|
333
|
-
) {
|
|
322
|
+
export function generateMethodFile(openApi, controllerName, operations, options = {}) {
|
|
334
323
|
const dataContractImports = [];
|
|
324
|
+
const dataContractValueImports = [];
|
|
335
325
|
const helperTypeImports = ["ApiResult", "ApiMethodOptions"];
|
|
336
326
|
const helperValueImports = ["handleApiResponse"];
|
|
337
327
|
const methods = [];
|
|
338
|
-
const queryAliases = [];
|
|
339
328
|
let needsContentType = false;
|
|
340
|
-
let needsToFormData = false;
|
|
341
329
|
let needsPaginationTypes = false;
|
|
330
|
+
let needsHeaderHelpers = false;
|
|
331
|
+
let needsWireMappings = false;
|
|
342
332
|
|
|
343
333
|
for (const operationInfo of operations) {
|
|
344
334
|
const operationTypes = getOperationTypes(openApi, operationInfo, options);
|
|
345
|
-
if (!operationTypes.operationId || !operationTypes.methodName) continue;
|
|
346
335
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
if (
|
|
350
|
-
operationTypes.bodyType
|
|
351
|
-
!isPrimitiveType(operationTypes.bodyType)
|
|
352
|
-
) {
|
|
353
|
-
dataContractImports.push(
|
|
354
|
-
...extractTopLevelTypeNames(operationTypes.bodyType),
|
|
355
|
-
);
|
|
336
|
+
for (const typeName of Object.values(operationTypes.parameterTypeNames)) dataContractImports.push(typeName);
|
|
337
|
+
if (operationTypes.paramsTypeName) dataContractImports.push(operationTypes.paramsTypeName);
|
|
338
|
+
if (operationTypes.bodyType && !isPrimitiveType(operationTypes.bodyType)) {
|
|
339
|
+
dataContractImports.push(...extractTopLevelTypeNames(operationTypes.bodyType));
|
|
356
340
|
}
|
|
357
341
|
if (!isPrimitiveType(operationTypes.responseType)) {
|
|
358
|
-
dataContractImports.push(
|
|
359
|
-
...extractTopLevelTypeNames(operationTypes.responseType),
|
|
360
|
-
);
|
|
342
|
+
dataContractImports.push(...extractTopLevelTypeNames(operationTypes.responseType));
|
|
361
343
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const queryTypeName = `${pascalCase(operationTypes.methodName)}Query`;
|
|
365
|
-
queryAliases.push(
|
|
366
|
-
`export type ${queryTypeName} = NonNullable<${operationTypes.paramsTypeName}>;`,
|
|
367
|
-
);
|
|
344
|
+
if (!isPrimitiveType(operationTypes.errorType)) {
|
|
345
|
+
dataContractImports.push(...extractTopLevelTypeNames(operationTypes.errorType));
|
|
368
346
|
}
|
|
369
347
|
|
|
370
348
|
if (contentTypeEnum(operationTypes.contentType)) needsContentType = true;
|
|
371
|
-
if (operationTypes.
|
|
372
|
-
|
|
349
|
+
if (operationTypes.hasHeaderParams || operationTypes.hasCookieParams) needsHeaderHelpers = true;
|
|
350
|
+
if (
|
|
351
|
+
operationTypes.bodyWireSchemaKey ||
|
|
352
|
+
operationTypes.responseWireSchemaKey ||
|
|
353
|
+
operationTypes.errorWireSchemaKey
|
|
354
|
+
) {
|
|
355
|
+
needsWireMappings = true;
|
|
356
|
+
}
|
|
373
357
|
if (
|
|
374
358
|
operationTypes.hasQueryParams &&
|
|
375
|
-
!operationTypes.hasPathParams &&
|
|
376
|
-
|
|
377
|
-
isPaginated(operationTypes)
|
|
359
|
+
!operationTypes.hasPathParams && !operationTypes.bodyType &&
|
|
360
|
+
!operationTypes.hasHeaderParams && !operationTypes.hasCookieParams &&
|
|
361
|
+
options.useFilterFormValues !== false && isPaginated(operationTypes)
|
|
378
362
|
) {
|
|
379
363
|
needsPaginationTypes = true;
|
|
380
364
|
}
|
|
381
365
|
|
|
382
|
-
methods.push(
|
|
383
|
-
createMethod(
|
|
384
|
-
operationInfo,
|
|
385
|
-
operationTypes,
|
|
386
|
-
options.defaultHandlers,
|
|
387
|
-
options,
|
|
388
|
-
),
|
|
389
|
-
);
|
|
366
|
+
methods.push(createMethod(operationInfo, operationTypes, options.defaultHandlers, options));
|
|
390
367
|
}
|
|
391
368
|
|
|
392
|
-
if (
|
|
369
|
+
if (needsHeaderHelpers) helperValueImports.push("mergeHeaders", "toCookieHeader", "toRequestHeaders");
|
|
370
|
+
if (needsWireMappings) {
|
|
371
|
+
dataContractValueImports.push("typedApiWireSchemas");
|
|
372
|
+
helperValueImports.push("fromWireValue", "toWireValue");
|
|
373
|
+
}
|
|
393
374
|
if (needsPaginationTypes) {
|
|
394
375
|
helperValueImports.push("buildQuery");
|
|
395
376
|
helperTypeImports.push(
|
|
396
|
-
"ExtractDataIfPaginated",
|
|
397
|
-
"FilterFormValues",
|
|
398
|
-
"SortableKeys",
|
|
399
|
-
"SortDirection",
|
|
400
|
-
"UnwrapArray",
|
|
377
|
+
"ExtractDataIfPaginated", "FilterFormValues", "SortableKeys", "SortDirection", "UnwrapArray",
|
|
401
378
|
);
|
|
402
379
|
}
|
|
403
380
|
|
|
404
|
-
const defaultHandlers = options.defaultHandlers;
|
|
405
381
|
const useTypeOnlyImports = options.useTypeOnlyImports !== false;
|
|
382
|
+
const defaultHandlers = options.defaultHandlers;
|
|
406
383
|
const imports = [
|
|
407
384
|
generatedFileHeader(),
|
|
408
|
-
createImport(
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
),
|
|
412
|
-
createImport(
|
|
413
|
-
|
|
414
|
-
"../generated/http-client",
|
|
415
|
-
useTypeOnlyImports,
|
|
416
|
-
),
|
|
417
|
-
createImport(
|
|
418
|
-
dataContractImports,
|
|
419
|
-
"../generated/data-contracts",
|
|
420
|
-
useTypeOnlyImports,
|
|
421
|
-
),
|
|
422
|
-
createImport(
|
|
423
|
-
helperValueImports,
|
|
424
|
-
options.runtimePackageName ?? "typedapi-client-helpers",
|
|
425
|
-
),
|
|
426
|
-
createImport(
|
|
427
|
-
helperTypeImports,
|
|
428
|
-
options.runtimePackageName ?? "typedapi-client-helpers",
|
|
429
|
-
useTypeOnlyImports,
|
|
430
|
-
),
|
|
385
|
+
createImport(["request", ...(needsContentType ? ["ContentType"] : [])], "../generated/http-client"),
|
|
386
|
+
createImport(["RequestParams"], "../generated/http-client", useTypeOnlyImports),
|
|
387
|
+
createImport(dataContractValueImports, "../generated/data-contracts"),
|
|
388
|
+
createImport(dataContractImports, "../generated/data-contracts", useTypeOnlyImports),
|
|
389
|
+
createImport(helperValueImports, options.runtimePackageName ?? "typedapi-client-helpers"),
|
|
390
|
+
createImport(helperTypeImports, options.runtimePackageName ?? "typedapi-client-helpers", useTypeOnlyImports),
|
|
431
391
|
defaultHandlers
|
|
432
392
|
? `import { ${defaultHandlers.success} as typedApiDefaultSuccessHandler, ${defaultHandlers.error} as typedApiDefaultErrorHandler } from ${JSON.stringify(defaultHandlers.path)};`
|
|
433
393
|
: "",
|
|
434
394
|
].filter(Boolean);
|
|
435
395
|
|
|
436
|
-
|
|
437
|
-
const aliasBlock = aliases ? `${aliases}\n\n` : "";
|
|
438
|
-
|
|
439
|
-
return `${imports.join("\n")}\n\n${aliasBlock}${methods.join("\n\n")}\n`;
|
|
396
|
+
return `${imports.join("\n")}\n\n${methods.join("\n\n")}\n`;
|
|
440
397
|
}
|