@zimic/http 0.0.1-canary.2
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/LICENSE.md +16 -0
- package/README.md +230 -0
- package/dist/chunk-VHQRAQPQ.mjs +1371 -0
- package/dist/chunk-VHQRAQPQ.mjs.map +1 -0
- package/dist/chunk-VUDGONB5.js +1382 -0
- package/dist/chunk-VUDGONB5.js.map +1 -0
- package/dist/cli.js +116 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +109 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.ts +1306 -0
- package/dist/index.js +544 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +537 -0
- package/dist/index.mjs.map +1 -0
- package/dist/typegen.d.ts +86 -0
- package/dist/typegen.js +12 -0
- package/dist/typegen.js.map +1 -0
- package/dist/typegen.mjs +3 -0
- package/dist/typegen.mjs.map +1 -0
- package/index.d.ts +1 -0
- package/package.json +110 -0
- package/src/cli/cli.ts +92 -0
- package/src/cli/index.ts +4 -0
- package/src/cli/typegen/openapi.ts +24 -0
- package/src/formData/HttpFormData.ts +300 -0
- package/src/formData/types.ts +110 -0
- package/src/headers/HttpHeaders.ts +217 -0
- package/src/headers/types.ts +65 -0
- package/src/index.ts +55 -0
- package/src/pathParams/types.ts +67 -0
- package/src/searchParams/HttpSearchParams.ts +258 -0
- package/src/searchParams/types.ts +133 -0
- package/src/typegen/index.ts +12 -0
- package/src/typegen/namespace/TypegenNamespace.ts +18 -0
- package/src/typegen/openapi/generate.ts +168 -0
- package/src/typegen/openapi/transform/components.ts +481 -0
- package/src/typegen/openapi/transform/context.ts +67 -0
- package/src/typegen/openapi/transform/filters.ts +71 -0
- package/src/typegen/openapi/transform/imports.ts +15 -0
- package/src/typegen/openapi/transform/io.ts +86 -0
- package/src/typegen/openapi/transform/methods.ts +803 -0
- package/src/typegen/openapi/transform/operations.ts +120 -0
- package/src/typegen/openapi/transform/paths.ts +119 -0
- package/src/typegen/openapi/utils/types.ts +45 -0
- package/src/types/arrays.d.ts +4 -0
- package/src/types/json.ts +89 -0
- package/src/types/objects.d.ts +14 -0
- package/src/types/requests.ts +96 -0
- package/src/types/schema.ts +834 -0
- package/src/types/strings.d.ts +9 -0
- package/src/types/utils.ts +64 -0
- package/src/utils/console.ts +7 -0
- package/src/utils/data.ts +13 -0
- package/src/utils/files.ts +28 -0
- package/src/utils/imports.ts +12 -0
- package/src/utils/prettier.ts +13 -0
- package/src/utils/strings.ts +3 -0
- package/src/utils/time.ts +25 -0
- package/src/utils/urls.ts +52 -0
- package/typegen.d.ts +1 -0
|
@@ -0,0 +1,1371 @@
|
|
|
1
|
+
import filesystem from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import ts3 from 'typescript';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
|
|
9
|
+
// src/utils/data.ts
|
|
10
|
+
function isDefined(value) {
|
|
11
|
+
return value !== undefined && value !== null;
|
|
12
|
+
}
|
|
13
|
+
__name(isDefined, "isDefined");
|
|
14
|
+
function isNonEmpty(value) {
|
|
15
|
+
return isDefined(value) && value !== "";
|
|
16
|
+
}
|
|
17
|
+
__name(isNonEmpty, "isNonEmpty");
|
|
18
|
+
function isNeverType(type) {
|
|
19
|
+
return type.kind === ts3.SyntaxKind.NeverKeyword;
|
|
20
|
+
}
|
|
21
|
+
__name(isNeverType, "isNeverType");
|
|
22
|
+
function isUnknownType(type) {
|
|
23
|
+
return type.kind === ts3.SyntaxKind.UnknownKeyword;
|
|
24
|
+
}
|
|
25
|
+
__name(isUnknownType, "isUnknownType");
|
|
26
|
+
function isNullType(type) {
|
|
27
|
+
return type.kind === ts3.SyntaxKind.NullKeyword;
|
|
28
|
+
}
|
|
29
|
+
__name(isNullType, "isNullType");
|
|
30
|
+
function createBlobType() {
|
|
31
|
+
return ts3.factory.createTypeReferenceNode("Blob");
|
|
32
|
+
}
|
|
33
|
+
__name(createBlobType, "createBlobType");
|
|
34
|
+
function createNullType() {
|
|
35
|
+
return ts3.factory.createLiteralTypeNode(ts3.factory.createNull());
|
|
36
|
+
}
|
|
37
|
+
__name(createNullType, "createNullType");
|
|
38
|
+
function createImportSpecifier(importName) {
|
|
39
|
+
return ts3.factory.createImportSpecifier(false, undefined, ts3.factory.createIdentifier(importName));
|
|
40
|
+
}
|
|
41
|
+
__name(createImportSpecifier, "createImportSpecifier");
|
|
42
|
+
function createImportDeclaration(importSpecifiers, moduleName, options) {
|
|
43
|
+
return ts3.factory.createImportDeclaration(
|
|
44
|
+
undefined,
|
|
45
|
+
ts3.factory.createImportClause(options.typeOnly, undefined, ts3.factory.createNamedImports(importSpecifiers)),
|
|
46
|
+
ts3.factory.createStringLiteral(moduleName)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
__name(createImportDeclaration, "createImportDeclaration");
|
|
50
|
+
var HTTP_METHODS = Object.freeze(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
51
|
+
function logWithPrefix(message, options) {
|
|
52
|
+
const { method } = options;
|
|
53
|
+
console[method](chalk.cyan("[zimic]"), message);
|
|
54
|
+
}
|
|
55
|
+
__name(logWithPrefix, "logWithPrefix");
|
|
56
|
+
function createOperationsIdentifierText(serviceName) {
|
|
57
|
+
return `${serviceName}Operations`;
|
|
58
|
+
}
|
|
59
|
+
__name(createOperationsIdentifierText, "createOperationsIdentifierText");
|
|
60
|
+
function createOperationsIdentifier(serviceName) {
|
|
61
|
+
return ts3.factory.createIdentifier(createOperationsIdentifierText(serviceName));
|
|
62
|
+
}
|
|
63
|
+
__name(createOperationsIdentifier, "createOperationsIdentifier");
|
|
64
|
+
function isOperationsDeclaration(node) {
|
|
65
|
+
return node !== undefined && ts3.isInterfaceDeclaration(node) && node.name.text === "operations";
|
|
66
|
+
}
|
|
67
|
+
__name(isOperationsDeclaration, "isOperationsDeclaration");
|
|
68
|
+
function isOperation(node) {
|
|
69
|
+
return ts3.isPropertySignature(node) && (ts3.isIdentifier(node.name) || ts3.isStringLiteral(node.name)) && node.type !== undefined && ts3.isTypeLiteralNode(node.type);
|
|
70
|
+
}
|
|
71
|
+
__name(isOperation, "isOperation");
|
|
72
|
+
function wrapOperationType(type, context) {
|
|
73
|
+
context.typeImports.http.add("HttpSchema");
|
|
74
|
+
const httpSchemaMethodWrapper = ts3.factory.createQualifiedName(
|
|
75
|
+
ts3.factory.createIdentifier("HttpSchema"),
|
|
76
|
+
ts3.factory.createIdentifier("Method")
|
|
77
|
+
);
|
|
78
|
+
return ts3.factory.createTypeReferenceNode(httpSchemaMethodWrapper, [type]);
|
|
79
|
+
}
|
|
80
|
+
__name(wrapOperationType, "wrapOperationType");
|
|
81
|
+
function normalizeOperation(operation, context) {
|
|
82
|
+
if (!isOperation(operation)) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const newType = normalizeTypeLiteralMethodType(operation.type, context);
|
|
86
|
+
return ts3.factory.updatePropertySignature(
|
|
87
|
+
operation,
|
|
88
|
+
operation.modifiers,
|
|
89
|
+
operation.name,
|
|
90
|
+
operation.questionToken,
|
|
91
|
+
wrapOperationType(newType, context)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
__name(normalizeOperation, "normalizeOperation");
|
|
95
|
+
function normalizeOperations(operations, context) {
|
|
96
|
+
const newIdentifier = createOperationsIdentifier(context.serviceName);
|
|
97
|
+
const newMembers = operations.members.map((operation) => normalizeOperation(operation, context)).filter(isDefined);
|
|
98
|
+
return ts3.factory.updateInterfaceDeclaration(
|
|
99
|
+
operations,
|
|
100
|
+
operations.modifiers,
|
|
101
|
+
newIdentifier,
|
|
102
|
+
operations.typeParameters,
|
|
103
|
+
operations.heritageClauses,
|
|
104
|
+
newMembers
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
__name(normalizeOperations, "normalizeOperations");
|
|
108
|
+
function removeOperationIfUnreferenced(operation, context) {
|
|
109
|
+
if (!isOperation(operation)) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const operationName = operation.name.text;
|
|
113
|
+
const isReferenced = context.referencedTypes.operations.has(operationName);
|
|
114
|
+
if (isReferenced) {
|
|
115
|
+
context.referencedTypes.operations.delete(operationName);
|
|
116
|
+
return operation;
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
__name(removeOperationIfUnreferenced, "removeOperationIfUnreferenced");
|
|
121
|
+
function removeUnreferencedOperations(operations, context) {
|
|
122
|
+
const newMembers = operations.members.map((operation) => removeOperationIfUnreferenced(operation, context)).filter(isDefined);
|
|
123
|
+
context.referencedTypes.operations.clear();
|
|
124
|
+
if (newMembers.length === 0) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
return ts3.factory.updateInterfaceDeclaration(
|
|
128
|
+
operations,
|
|
129
|
+
operations.modifiers,
|
|
130
|
+
operations.name,
|
|
131
|
+
operations.typeParameters,
|
|
132
|
+
operations.heritageClauses,
|
|
133
|
+
newMembers
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
__name(removeUnreferencedOperations, "removeUnreferencedOperations");
|
|
137
|
+
|
|
138
|
+
// src/typegen/openapi/transform/methods.ts
|
|
139
|
+
function isMethod(node) {
|
|
140
|
+
return ts3.isPropertySignature(node) && ts3.isIdentifier(node.name) && node.type !== undefined && (ts3.isTypeLiteralNode(node.type) || ts3.isIndexedAccessTypeNode(node.type));
|
|
141
|
+
}
|
|
142
|
+
__name(isMethod, "isMethod");
|
|
143
|
+
function isMethodMember(node) {
|
|
144
|
+
return ts3.isPropertySignature(node) && ts3.isIdentifier(node.name) && node.type !== undefined && (ts3.isTypeLiteralNode(node.type) || ts3.isIndexedAccessTypeNode(node.type) || isNeverType(node.type));
|
|
145
|
+
}
|
|
146
|
+
__name(isMethodMember, "isMethodMember");
|
|
147
|
+
function isRequestMember(node) {
|
|
148
|
+
return ts3.isPropertySignature(node) && ts3.isIdentifier(node.name) && node.type !== undefined && !isNeverType(node.type);
|
|
149
|
+
}
|
|
150
|
+
__name(isRequestMember, "isRequestMember");
|
|
151
|
+
function isRequestHeaders(node) {
|
|
152
|
+
return isRequestMember(node) && node.name.text === "headers" && ts3.isTypeLiteralNode(node.type);
|
|
153
|
+
}
|
|
154
|
+
__name(isRequestHeaders, "isRequestHeaders");
|
|
155
|
+
function isNormalizedRequestHeaders(node) {
|
|
156
|
+
return isRequestMember(node) && node.name.text === "headers" && ts3.isTypeReferenceNode(node.type) && node.type.typeArguments !== undefined && node.type.typeArguments.length === 1 && ts3.isTypeLiteralNode(node.type.typeArguments[0]);
|
|
157
|
+
}
|
|
158
|
+
__name(isNormalizedRequestHeaders, "isNormalizedRequestHeaders");
|
|
159
|
+
function isRequestParameters(node) {
|
|
160
|
+
return isRequestMember(node) && node.name.text === "parameters" && ts3.isTypeLiteralNode(node.type);
|
|
161
|
+
}
|
|
162
|
+
__name(isRequestParameters, "isRequestParameters");
|
|
163
|
+
function isContentPropertySignature(node) {
|
|
164
|
+
return isRequestMember(node) && node.name.text === "content" && ts3.isTypeLiteralNode(node.type);
|
|
165
|
+
}
|
|
166
|
+
__name(isContentPropertySignature, "isContentPropertySignature");
|
|
167
|
+
function isContentMember(node) {
|
|
168
|
+
return ts3.isPropertySignature(node) && (ts3.isIdentifier(node.name) || ts3.isStringLiteral(node.name)) && node.type !== undefined && !isNeverType(node.type);
|
|
169
|
+
}
|
|
170
|
+
__name(isContentMember, "isContentMember");
|
|
171
|
+
function isResponse(node) {
|
|
172
|
+
return ts3.isPropertySignature(node) && (ts3.isIdentifier(node.name) || ts3.isStringLiteral(node.name) || ts3.isNumericLiteral(node.name)) && node.type !== undefined;
|
|
173
|
+
}
|
|
174
|
+
__name(isResponse, "isResponse");
|
|
175
|
+
function removeRedundantNullUnionIfNecessary(type) {
|
|
176
|
+
const containsRedundantNullUnion = ts3.isUnionTypeNode(type) && type.types.some((type2) => {
|
|
177
|
+
const isNull = ts3.isLiteralTypeNode(type2) && isNullType(type2.literal);
|
|
178
|
+
return isNull;
|
|
179
|
+
}) && type.types.some((type2) => {
|
|
180
|
+
return ts3.isParenthesizedTypeNode(type2) && ts3.isUnionTypeNode(type2.type) && type2.type.types.some((subType) => {
|
|
181
|
+
const isNull = ts3.isLiteralTypeNode(subType) && isNullType(subType.literal);
|
|
182
|
+
return isNull;
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
if (!containsRedundantNullUnion) {
|
|
186
|
+
return type;
|
|
187
|
+
}
|
|
188
|
+
const typesWithoutRedundantNullUnion = type.types.filter((type2) => {
|
|
189
|
+
const isNull = ts3.isLiteralTypeNode(type2) && isNullType(type2.literal);
|
|
190
|
+
return !isNull;
|
|
191
|
+
}).flatMap((type2) => {
|
|
192
|
+
if (ts3.isParenthesizedTypeNode(type2) && ts3.isUnionTypeNode(type2.type)) {
|
|
193
|
+
return type2.type.types;
|
|
194
|
+
}
|
|
195
|
+
return [type2];
|
|
196
|
+
});
|
|
197
|
+
return ts3.factory.createUnionTypeNode(typesWithoutRedundantNullUnion);
|
|
198
|
+
}
|
|
199
|
+
__name(removeRedundantNullUnionIfNecessary, "removeRedundantNullUnionIfNecessary");
|
|
200
|
+
function wrapFormDataContentType(type, context) {
|
|
201
|
+
context.typeImports.http.add("HttpFormData");
|
|
202
|
+
context.typeImports.http.add("HttpFormDataSerialized");
|
|
203
|
+
return ts3.factory.createTypeReferenceNode(ts3.factory.createIdentifier("HttpFormData"), [
|
|
204
|
+
ts3.factory.createTypeReferenceNode(ts3.factory.createIdentifier("HttpFormDataSerialized"), [
|
|
205
|
+
renameComponentReferences(type, context)
|
|
206
|
+
])
|
|
207
|
+
]);
|
|
208
|
+
}
|
|
209
|
+
__name(wrapFormDataContentType, "wrapFormDataContentType");
|
|
210
|
+
function wrapURLEncodedContentType(type, context) {
|
|
211
|
+
context.typeImports.http.add("HttpSearchParams");
|
|
212
|
+
context.typeImports.http.add("HttpSearchParamsSerialized");
|
|
213
|
+
return ts3.factory.createTypeReferenceNode(ts3.factory.createIdentifier("HttpSearchParams"), [
|
|
214
|
+
ts3.factory.createTypeReferenceNode(ts3.factory.createIdentifier("HttpSearchParamsSerialized"), [
|
|
215
|
+
renameComponentReferences(type, context)
|
|
216
|
+
])
|
|
217
|
+
]);
|
|
218
|
+
}
|
|
219
|
+
__name(wrapURLEncodedContentType, "wrapURLEncodedContentType");
|
|
220
|
+
function normalizeRequestBodyMember(requestBodyMember, context, options) {
|
|
221
|
+
if (!isContentMember(requestBodyMember)) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
const newIdentifier = ts3.factory.createIdentifier("body");
|
|
225
|
+
const contentType = requestBodyMember.name.text;
|
|
226
|
+
let newType = removeRedundantNullUnionIfNecessary(renameComponentReferences(requestBodyMember.type, context));
|
|
227
|
+
if (contentType === "multipart/form-data") {
|
|
228
|
+
newType = wrapFormDataContentType(newType, context);
|
|
229
|
+
} else if (contentType === "x-www-form-urlencoded") {
|
|
230
|
+
newType = wrapURLEncodedContentType(newType, context);
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
contentTypeName: contentType,
|
|
234
|
+
propertySignature: ts3.factory.updatePropertySignature(
|
|
235
|
+
requestBodyMember,
|
|
236
|
+
requestBodyMember.modifiers,
|
|
237
|
+
newIdentifier,
|
|
238
|
+
options.questionToken,
|
|
239
|
+
newType
|
|
240
|
+
)
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
__name(normalizeRequestBodyMember, "normalizeRequestBodyMember");
|
|
244
|
+
function wrapHeadersType(type, context) {
|
|
245
|
+
context.typeImports.http.add("HttpHeadersSerialized");
|
|
246
|
+
const serializedWrapper = ts3.factory.createIdentifier("HttpHeadersSerialized");
|
|
247
|
+
return ts3.factory.createTypeReferenceNode(
|
|
248
|
+
serializedWrapper,
|
|
249
|
+
ts3.factory.createNodeArray([type])
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
__name(wrapHeadersType, "wrapHeadersType");
|
|
253
|
+
function normalizeHeaders(headers, context) {
|
|
254
|
+
const newHeaderMembers = headers.members.filter((header) => {
|
|
255
|
+
if (ts3.isIndexSignatureDeclaration(header)) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
if (ts3.isPropertySignature(header)) {
|
|
259
|
+
return header.type !== undefined && !isUnknownType(header.type);
|
|
260
|
+
}
|
|
261
|
+
return true;
|
|
262
|
+
});
|
|
263
|
+
if (newHeaderMembers.length === 0) {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
const newHeaders = ts3.factory.updateTypeLiteralNode(headers, ts3.factory.createNodeArray(newHeaderMembers));
|
|
267
|
+
return wrapHeadersType(newHeaders, context);
|
|
268
|
+
}
|
|
269
|
+
__name(normalizeHeaders, "normalizeHeaders");
|
|
270
|
+
function normalizeRequestHeaders(requestHeader, context) {
|
|
271
|
+
if (!isRequestHeaders(requestHeader)) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
const newType = normalizeHeaders(requestHeader.type, context);
|
|
275
|
+
if (!newType) {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
return ts3.factory.updatePropertySignature(
|
|
279
|
+
requestHeader,
|
|
280
|
+
requestHeader.modifiers,
|
|
281
|
+
requestHeader.name,
|
|
282
|
+
requestHeader.questionToken,
|
|
283
|
+
newType
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
__name(normalizeRequestHeaders, "normalizeRequestHeaders");
|
|
287
|
+
function createHeaderForUnionByContentType(existingHeader, contentTypeName, context) {
|
|
288
|
+
const existingHeaderMembers = existingHeader ? existingHeader.type.typeArguments[0].members : [];
|
|
289
|
+
const contentTypeIdentifier = ts3.factory.createIdentifier('"content-type"');
|
|
290
|
+
const contentTypeValue = ts3.factory.createLiteralTypeNode(ts3.factory.createStringLiteral(contentTypeName));
|
|
291
|
+
const newHeaderType = wrapHeadersType(
|
|
292
|
+
ts3.factory.createTypeLiteralNode([
|
|
293
|
+
ts3.factory.createPropertySignature(undefined, contentTypeIdentifier, undefined, contentTypeValue),
|
|
294
|
+
...existingHeaderMembers
|
|
295
|
+
]),
|
|
296
|
+
context
|
|
297
|
+
);
|
|
298
|
+
return ts3.factory.createPropertySignature(
|
|
299
|
+
existingHeader?.modifiers,
|
|
300
|
+
ts3.factory.createIdentifier("headers"),
|
|
301
|
+
undefined,
|
|
302
|
+
newHeaderType
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
__name(createHeaderForUnionByContentType, "createHeaderForUnionByContentType");
|
|
306
|
+
function normalizeContentType(contentType, context, options) {
|
|
307
|
+
const { bodyQuestionToken } = options;
|
|
308
|
+
if (ts3.isIndexedAccessTypeNode(contentType)) {
|
|
309
|
+
return renameComponentReferences(contentType, context);
|
|
310
|
+
}
|
|
311
|
+
if (!ts3.isTypeLiteralNode(contentType)) {
|
|
312
|
+
return contentType;
|
|
313
|
+
}
|
|
314
|
+
const newHeader = contentType.members.map((member) => normalizeRequestHeaders(member, context)).find(isDefined);
|
|
315
|
+
const newBodyMembers = contentType.members.flatMap((body) => {
|
|
316
|
+
if (isContentPropertySignature(body)) {
|
|
317
|
+
return body.type.members.map((member) => normalizeRequestBodyMember(member, context, { questionToken: bodyQuestionToken })).filter(isDefined);
|
|
318
|
+
}
|
|
319
|
+
return [];
|
|
320
|
+
});
|
|
321
|
+
if (newBodyMembers.length <= 1) {
|
|
322
|
+
const newBodyMemberPropertySignatures = newBodyMembers.map((bodyMember) => bodyMember.propertySignature);
|
|
323
|
+
const newMembers = [newHeader, ...newBodyMemberPropertySignatures].filter(isDefined);
|
|
324
|
+
return ts3.factory.updateTypeLiteralNode(contentType, ts3.factory.createNodeArray(newMembers));
|
|
325
|
+
} else {
|
|
326
|
+
const bodyMemberUnionTypes = newBodyMembers.map((bodyMember) => {
|
|
327
|
+
const headerMember = createHeaderForUnionByContentType(newHeader, bodyMember.contentTypeName, context);
|
|
328
|
+
return ts3.factory.createTypeLiteralNode([headerMember, bodyMember.propertySignature]);
|
|
329
|
+
});
|
|
330
|
+
return ts3.factory.createUnionTypeNode(bodyMemberUnionTypes);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
__name(normalizeContentType, "normalizeContentType");
|
|
334
|
+
function normalizeRequest(request, context) {
|
|
335
|
+
const newIdentifier = ts3.factory.createIdentifier("request");
|
|
336
|
+
const newType = normalizeContentType(request.type, context, {
|
|
337
|
+
bodyQuestionToken: request.questionToken
|
|
338
|
+
});
|
|
339
|
+
if (request.questionToken && ts3.isIndexedAccessTypeNode(request.type) && ts3.isLiteralTypeNode(request.type.indexType) && (ts3.isIdentifier(request.type.indexType.literal) || ts3.isStringLiteral(request.type.indexType.literal))) {
|
|
340
|
+
const referencedComponentName = request.type.indexType.literal.text;
|
|
341
|
+
context.pendingActions.components.requests.toMarkBodyAsOptional.add(referencedComponentName);
|
|
342
|
+
}
|
|
343
|
+
return ts3.factory.updatePropertySignature(request, request.modifiers, newIdentifier, undefined, newType);
|
|
344
|
+
}
|
|
345
|
+
__name(normalizeRequest, "normalizeRequest");
|
|
346
|
+
function wrapResponseType(type, context) {
|
|
347
|
+
context.typeImports.http.add("HttpSchema");
|
|
348
|
+
const httpSchemaResponseWrapper = ts3.factory.createQualifiedName(
|
|
349
|
+
ts3.factory.createIdentifier("HttpSchema"),
|
|
350
|
+
ts3.factory.createIdentifier("Response")
|
|
351
|
+
);
|
|
352
|
+
return ts3.factory.createTypeReferenceNode(httpSchemaResponseWrapper, [type]);
|
|
353
|
+
}
|
|
354
|
+
__name(wrapResponseType, "wrapResponseType");
|
|
355
|
+
function normalizeResponseType(responseType, context, options) {
|
|
356
|
+
const { isComponent: isComponent2, questionToken } = options;
|
|
357
|
+
if (!ts3.isTypeLiteralNode(responseType)) {
|
|
358
|
+
return responseType;
|
|
359
|
+
}
|
|
360
|
+
const newType = normalizeContentType(responseType, context, { bodyQuestionToken: questionToken });
|
|
361
|
+
return isComponent2 ? wrapResponseType(newType, context) : newType;
|
|
362
|
+
}
|
|
363
|
+
__name(normalizeResponseType, "normalizeResponseType");
|
|
364
|
+
var NON_NUMERIC_RESPONSE_STATUS_TO_MAPPED_TYPE = {
|
|
365
|
+
default: "HttpStatusCode",
|
|
366
|
+
"1xx": "HttpStatusCode.Information",
|
|
367
|
+
"2xx": "HttpStatusCode.Success",
|
|
368
|
+
"3xx": "HttpStatusCode.Redirection",
|
|
369
|
+
"4xx": "HttpStatusCode.ClientError",
|
|
370
|
+
"5xx": "HttpStatusCode.ServerError"
|
|
371
|
+
};
|
|
372
|
+
function normalizeResponse(response, context, options = {}) {
|
|
373
|
+
const { isComponent: isComponent2 = false } = options;
|
|
374
|
+
if (!isResponse(response)) {
|
|
375
|
+
return undefined;
|
|
376
|
+
}
|
|
377
|
+
const newType = normalizeResponseType(response.type, context, {
|
|
378
|
+
isComponent: isComponent2,
|
|
379
|
+
questionToken: response.questionToken
|
|
380
|
+
});
|
|
381
|
+
const statusCodeOrComponentName = response.name.text;
|
|
382
|
+
const isNumericStatusCode = /^\d+$/.test(statusCodeOrComponentName);
|
|
383
|
+
const shouldReuseIdentifier = isComponent2 || isNumericStatusCode;
|
|
384
|
+
let newSignature;
|
|
385
|
+
if (shouldReuseIdentifier) {
|
|
386
|
+
newSignature = ts3.factory.updatePropertySignature(
|
|
387
|
+
response,
|
|
388
|
+
response.modifiers,
|
|
389
|
+
response.name,
|
|
390
|
+
response.questionToken,
|
|
391
|
+
newType
|
|
392
|
+
);
|
|
393
|
+
} else {
|
|
394
|
+
const statusCode = statusCodeOrComponentName.toLowerCase();
|
|
395
|
+
const mappedType = NON_NUMERIC_RESPONSE_STATUS_TO_MAPPED_TYPE[statusCode];
|
|
396
|
+
if (!mappedType) {
|
|
397
|
+
logWithPrefix(
|
|
398
|
+
`Warning: Response has a non-standard status code: ${chalk.yellow(response.name.text)}. Consider replacing it with a number (e.g. '200'), a pattern ('1xx', '2xx', '3xx', '4xx', or '5xx'), or 'default'.`,
|
|
399
|
+
{ method: "warn" }
|
|
400
|
+
);
|
|
401
|
+
return undefined;
|
|
402
|
+
}
|
|
403
|
+
context.typeImports.http.add("HttpStatusCode");
|
|
404
|
+
const newIdentifier = ts3.factory.createIdentifier(`[StatusCode in ${mappedType}]`);
|
|
405
|
+
newSignature = ts3.factory.updatePropertySignature(
|
|
406
|
+
response,
|
|
407
|
+
response.modifiers,
|
|
408
|
+
newIdentifier,
|
|
409
|
+
response.questionToken,
|
|
410
|
+
newType
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
newSignature,
|
|
415
|
+
statusCode: {
|
|
416
|
+
value: statusCodeOrComponentName,
|
|
417
|
+
isNumeric: isNumericStatusCode
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
__name(normalizeResponse, "normalizeResponse");
|
|
422
|
+
function normalizeResponses(responses, context) {
|
|
423
|
+
if (isNeverType(responses.type) || !ts3.isTypeLiteralNode(responses.type)) {
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
const newIdentifier = ts3.factory.createIdentifier("response");
|
|
427
|
+
const newQuestionToken = undefined;
|
|
428
|
+
const newMembers = responses.type.members.map((response) => normalizeResponse(response, context), context).filter(isDefined);
|
|
429
|
+
const sortedNewMembers = Array.from(newMembers).sort((response, otherResponse) => {
|
|
430
|
+
return response.statusCode.value.localeCompare(otherResponse.statusCode.value);
|
|
431
|
+
});
|
|
432
|
+
const isEveryStatusCodeNumeric = sortedNewMembers.every((response) => response.statusCode.isNumeric);
|
|
433
|
+
let newType;
|
|
434
|
+
if (isEveryStatusCodeNumeric) {
|
|
435
|
+
newType = ts3.factory.updateTypeLiteralNode(
|
|
436
|
+
responses.type,
|
|
437
|
+
ts3.factory.createNodeArray(sortedNewMembers.map((response) => response.newSignature))
|
|
438
|
+
);
|
|
439
|
+
} else {
|
|
440
|
+
context.typeImports.http.add("MergeHttpResponsesByStatusCode");
|
|
441
|
+
const typeMembersToMerge = sortedNewMembers.reduce(
|
|
442
|
+
(members, response) => {
|
|
443
|
+
if (response.statusCode.isNumeric) {
|
|
444
|
+
members.numeric.push(response.newSignature);
|
|
445
|
+
} else {
|
|
446
|
+
members.nonNumeric.push(response.newSignature);
|
|
447
|
+
}
|
|
448
|
+
return members;
|
|
449
|
+
},
|
|
450
|
+
{ numeric: [], nonNumeric: [] }
|
|
451
|
+
);
|
|
452
|
+
const numericTypeLiteral = ts3.factory.createTypeLiteralNode(typeMembersToMerge.numeric);
|
|
453
|
+
const nonNumericTypeLiterals = typeMembersToMerge.nonNumeric.map(
|
|
454
|
+
(response) => ts3.factory.createTypeLiteralNode([response])
|
|
455
|
+
);
|
|
456
|
+
const mergeWrapper = ts3.factory.createIdentifier("MergeHttpResponsesByStatusCode");
|
|
457
|
+
newType = ts3.factory.createTypeReferenceNode(mergeWrapper, [
|
|
458
|
+
ts3.factory.createTupleTypeNode([numericTypeLiteral, ...nonNumericTypeLiterals])
|
|
459
|
+
]);
|
|
460
|
+
}
|
|
461
|
+
return ts3.factory.updatePropertySignature(
|
|
462
|
+
responses,
|
|
463
|
+
responses.modifiers,
|
|
464
|
+
newIdentifier,
|
|
465
|
+
newQuestionToken,
|
|
466
|
+
renameComponentReferences(newType, context)
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
__name(normalizeResponses, "normalizeResponses");
|
|
470
|
+
function normalizeMethodMember(methodMember, context) {
|
|
471
|
+
if (isMethodMember(methodMember)) {
|
|
472
|
+
if (methodMember.name.text === "requestBody") {
|
|
473
|
+
return normalizeRequest(methodMember, context);
|
|
474
|
+
}
|
|
475
|
+
if (methodMember.name.text === "responses") {
|
|
476
|
+
return normalizeResponses(methodMember, context);
|
|
477
|
+
}
|
|
478
|
+
return methodMember;
|
|
479
|
+
}
|
|
480
|
+
return undefined;
|
|
481
|
+
}
|
|
482
|
+
__name(normalizeMethodMember, "normalizeMethodMember");
|
|
483
|
+
function normalizeRequestQueryWithParameters(requestMember, context) {
|
|
484
|
+
const newIdentifier = ts3.factory.createIdentifier("searchParams");
|
|
485
|
+
const newQuestionToken = undefined;
|
|
486
|
+
const newType = renameComponentReferences(requestMember.type, context);
|
|
487
|
+
context.typeImports.http.add("HttpSearchParamsSerialized");
|
|
488
|
+
const serializedWrapper = ts3.factory.createIdentifier("HttpSearchParamsSerialized");
|
|
489
|
+
const wrappedNewType = ts3.factory.createTypeReferenceNode(serializedWrapper, [newType]);
|
|
490
|
+
return ts3.factory.updatePropertySignature(
|
|
491
|
+
requestMember,
|
|
492
|
+
requestMember.modifiers,
|
|
493
|
+
newIdentifier,
|
|
494
|
+
newQuestionToken,
|
|
495
|
+
wrappedNewType
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
__name(normalizeRequestQueryWithParameters, "normalizeRequestQueryWithParameters");
|
|
499
|
+
function normalizeRequestHeadersWithParameters(requestMember, context) {
|
|
500
|
+
const newIdentifier = ts3.factory.createIdentifier("headers");
|
|
501
|
+
const newQuestionToken = undefined;
|
|
502
|
+
const newType = renameComponentReferences(requestMember.type, context);
|
|
503
|
+
context.typeImports.http.add("HttpHeadersSerialized");
|
|
504
|
+
const serializedWrapper = ts3.factory.createIdentifier("HttpHeadersSerialized");
|
|
505
|
+
const wrappedNewType = ts3.factory.createTypeReferenceNode(serializedWrapper, [newType]);
|
|
506
|
+
return ts3.factory.updatePropertySignature(
|
|
507
|
+
requestMember,
|
|
508
|
+
requestMember.modifiers,
|
|
509
|
+
newIdentifier,
|
|
510
|
+
newQuestionToken,
|
|
511
|
+
wrappedNewType
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
__name(normalizeRequestHeadersWithParameters, "normalizeRequestHeadersWithParameters");
|
|
515
|
+
function normalizeRequestMemberWithParameters(requestMember, context) {
|
|
516
|
+
if (!isRequestMember(requestMember) || requestMember.name.text === "path") {
|
|
517
|
+
return undefined;
|
|
518
|
+
}
|
|
519
|
+
if (requestMember.name.text === "query") {
|
|
520
|
+
return normalizeRequestQueryWithParameters(requestMember, context);
|
|
521
|
+
}
|
|
522
|
+
if (requestMember.name.text === "header") {
|
|
523
|
+
return normalizeRequestHeadersWithParameters(requestMember, context);
|
|
524
|
+
}
|
|
525
|
+
return requestMember;
|
|
526
|
+
}
|
|
527
|
+
__name(normalizeRequestMemberWithParameters, "normalizeRequestMemberWithParameters");
|
|
528
|
+
function mergeRequestHeadersMember(headers, otherHeaders) {
|
|
529
|
+
const headersTypeLiteral = headers.type.typeArguments[0];
|
|
530
|
+
const otherHeadersTypeLiteral = otherHeaders.type.typeArguments[0];
|
|
531
|
+
const newType = ts3.factory.updateTypeReferenceNode(
|
|
532
|
+
headers.type,
|
|
533
|
+
headers.type.typeName,
|
|
534
|
+
ts3.factory.createNodeArray([
|
|
535
|
+
ts3.factory.createTypeLiteralNode([...otherHeadersTypeLiteral.members, ...headersTypeLiteral.members])
|
|
536
|
+
])
|
|
537
|
+
);
|
|
538
|
+
return ts3.factory.updatePropertySignature(
|
|
539
|
+
headers,
|
|
540
|
+
headers.modifiers,
|
|
541
|
+
headers.name,
|
|
542
|
+
headers.questionToken,
|
|
543
|
+
newType
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
__name(mergeRequestHeadersMember, "mergeRequestHeadersMember");
|
|
547
|
+
function mergeRequestHeadersMembers(members) {
|
|
548
|
+
let mergedHeaders;
|
|
549
|
+
let firstHeadersIndex;
|
|
550
|
+
const mergedHeadersMembers = members.map((member, index) => {
|
|
551
|
+
if (!member || !isNormalizedRequestHeaders(member)) {
|
|
552
|
+
return member;
|
|
553
|
+
}
|
|
554
|
+
if (firstHeadersIndex === undefined || !mergedHeaders) {
|
|
555
|
+
firstHeadersIndex = index;
|
|
556
|
+
mergedHeaders = member;
|
|
557
|
+
return member;
|
|
558
|
+
}
|
|
559
|
+
mergedHeaders = mergeRequestHeadersMember(mergedHeaders, member);
|
|
560
|
+
return undefined;
|
|
561
|
+
});
|
|
562
|
+
if (firstHeadersIndex !== undefined) {
|
|
563
|
+
mergedHeadersMembers[firstHeadersIndex] = mergedHeaders;
|
|
564
|
+
}
|
|
565
|
+
return mergedHeadersMembers.filter(isDefined);
|
|
566
|
+
}
|
|
567
|
+
__name(mergeRequestHeadersMembers, "mergeRequestHeadersMembers");
|
|
568
|
+
function mergeRequestAndParameterTypes(requestType, methodMembers, context) {
|
|
569
|
+
const parameters = methodMembers.find(isRequestParameters);
|
|
570
|
+
const parametersMembers = parameters ? parameters.type.members : [];
|
|
571
|
+
const requestMembers = ts3.isTypeLiteralNode(requestType) ? requestType.members : [];
|
|
572
|
+
const newMembers = mergeRequestHeadersMembers(
|
|
573
|
+
[...parametersMembers, ...requestMembers].map((member) => {
|
|
574
|
+
return normalizeRequestMemberWithParameters(member, context);
|
|
575
|
+
})
|
|
576
|
+
);
|
|
577
|
+
if (newMembers.length === 0) {
|
|
578
|
+
return undefined;
|
|
579
|
+
}
|
|
580
|
+
return ts3.factory.createTypeLiteralNode(newMembers);
|
|
581
|
+
}
|
|
582
|
+
__name(mergeRequestAndParameterTypes, "mergeRequestAndParameterTypes");
|
|
583
|
+
function normalizeRequestTypeWithParameters(requestType, methodMembers, context) {
|
|
584
|
+
if (ts3.isUnionTypeNode(requestType)) {
|
|
585
|
+
const newTypes = requestType.types.map((type) => normalizeRequestTypeWithParameters(type, methodMembers, context)).filter(isDefined);
|
|
586
|
+
return ts3.factory.updateUnionTypeNode(requestType, ts3.factory.createNodeArray(newTypes));
|
|
587
|
+
}
|
|
588
|
+
if (ts3.isIndexedAccessTypeNode(requestType)) {
|
|
589
|
+
const newType = normalizeRequestTypeWithParameters(ts3.factory.createTypeLiteralNode([]), methodMembers, context);
|
|
590
|
+
return ts3.factory.createIntersectionTypeNode([requestType, newType].filter(isDefined));
|
|
591
|
+
}
|
|
592
|
+
return mergeRequestAndParameterTypes(requestType, methodMembers, context);
|
|
593
|
+
}
|
|
594
|
+
__name(normalizeRequestTypeWithParameters, "normalizeRequestTypeWithParameters");
|
|
595
|
+
function normalizeMethodMemberWithParameters(methodMember, methodMembers, context) {
|
|
596
|
+
if (!ts3.isIdentifier(methodMember.name) || !methodMember.type) {
|
|
597
|
+
return undefined;
|
|
598
|
+
}
|
|
599
|
+
if (methodMember.name.text === "request") {
|
|
600
|
+
const newType = normalizeRequestTypeWithParameters(methodMember.type, methodMembers, context);
|
|
601
|
+
if (!newType) {
|
|
602
|
+
return undefined;
|
|
603
|
+
}
|
|
604
|
+
return ts3.factory.updatePropertySignature(
|
|
605
|
+
methodMember,
|
|
606
|
+
methodMember.modifiers,
|
|
607
|
+
methodMember.name,
|
|
608
|
+
undefined,
|
|
609
|
+
newType
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
if (methodMember.name.text === "response") {
|
|
613
|
+
return methodMember;
|
|
614
|
+
}
|
|
615
|
+
return undefined;
|
|
616
|
+
}
|
|
617
|
+
__name(normalizeMethodMemberWithParameters, "normalizeMethodMemberWithParameters");
|
|
618
|
+
function normalizeTypeLiteralMethodType(methodType, context) {
|
|
619
|
+
const newMembers = methodType.members.map((member) => normalizeMethodMember(member, context)).filter(isDefined).map((member, _index, partialMembers) => normalizeMethodMemberWithParameters(member, partialMembers, context)).filter(isDefined);
|
|
620
|
+
return ts3.factory.updateTypeLiteralNode(methodType, ts3.factory.createNodeArray(newMembers));
|
|
621
|
+
}
|
|
622
|
+
__name(normalizeTypeLiteralMethodType, "normalizeTypeLiteralMethodType");
|
|
623
|
+
function normalizeIndexedAccessMethodType(methodType, context) {
|
|
624
|
+
const isOperationsReference = ts3.isTypeReferenceNode(methodType.objectType) && ts3.isIdentifier(methodType.objectType.typeName) && methodType.objectType.typeName.text === "operations";
|
|
625
|
+
if (!isOperationsReference) {
|
|
626
|
+
return methodType;
|
|
627
|
+
}
|
|
628
|
+
const newIdentifier = createOperationsIdentifier(context.serviceName);
|
|
629
|
+
const newObjectType = ts3.factory.createTypeReferenceNode(newIdentifier, methodType.objectType.typeArguments);
|
|
630
|
+
const hasIndexTypeName = ts3.isLiteralTypeNode(methodType.indexType) && (ts3.isIdentifier(methodType.indexType.literal) || ts3.isStringLiteral(methodType.indexType.literal));
|
|
631
|
+
if (hasIndexTypeName) {
|
|
632
|
+
const operationName = methodType.indexType.literal.text;
|
|
633
|
+
context.referencedTypes.operations.add(operationName);
|
|
634
|
+
}
|
|
635
|
+
return ts3.factory.updateIndexedAccessTypeNode(methodType, newObjectType, methodType.indexType);
|
|
636
|
+
}
|
|
637
|
+
__name(normalizeIndexedAccessMethodType, "normalizeIndexedAccessMethodType");
|
|
638
|
+
function normalizeMethod(method, context, options) {
|
|
639
|
+
if (!isMethod(method)) {
|
|
640
|
+
return undefined;
|
|
641
|
+
}
|
|
642
|
+
const methodName = method.name.text.toUpperCase();
|
|
643
|
+
if (!HTTP_METHODS.includes(methodName)) {
|
|
644
|
+
return undefined;
|
|
645
|
+
}
|
|
646
|
+
const pathMethodCompareString = `${methodName} ${options.pathName}`;
|
|
647
|
+
const matchesPositiveFilters = context.filters.paths.positive.length === 0 || context.filters.paths.positive.some((filter) => filter.test(pathMethodCompareString));
|
|
648
|
+
const matchesNegativeFilters = context.filters.paths.negative.length > 0 && context.filters.paths.negative.some((filter) => filter.test(pathMethodCompareString));
|
|
649
|
+
if (!matchesPositiveFilters || matchesNegativeFilters) {
|
|
650
|
+
return undefined;
|
|
651
|
+
}
|
|
652
|
+
const newIdentifier = ts3.factory.createIdentifier(methodName);
|
|
653
|
+
const newType = ts3.isTypeLiteralNode(method.type) ? normalizeTypeLiteralMethodType(method.type, context) : normalizeIndexedAccessMethodType(method.type, context);
|
|
654
|
+
return ts3.factory.updatePropertySignature(method, method.modifiers, newIdentifier, method.questionToken, newType);
|
|
655
|
+
}
|
|
656
|
+
__name(normalizeMethod, "normalizeMethod");
|
|
657
|
+
function createPathsIdentifier(serviceName) {
|
|
658
|
+
return ts3.factory.createIdentifier(`${serviceName}Schema`);
|
|
659
|
+
}
|
|
660
|
+
__name(createPathsIdentifier, "createPathsIdentifier");
|
|
661
|
+
function isPathsDeclaration(node) {
|
|
662
|
+
return node !== undefined && (ts3.isInterfaceDeclaration(node) || ts3.isTypeAliasDeclaration(node)) && node.name.text === "paths";
|
|
663
|
+
}
|
|
664
|
+
__name(isPathsDeclaration, "isPathsDeclaration");
|
|
665
|
+
function isPath(node) {
|
|
666
|
+
return ts3.isPropertySignature(node) && (ts3.isIdentifier(node.name) || ts3.isStringLiteral(node.name)) && node.type !== undefined && (ts3.isTypeLiteralNode(node.type) || ts3.isIndexedAccessTypeNode(node.type));
|
|
667
|
+
}
|
|
668
|
+
__name(isPath, "isPath");
|
|
669
|
+
function normalizePathNameWithParameters(pathName) {
|
|
670
|
+
return pathName.replace(/{([^}]+)}/g, ":$1");
|
|
671
|
+
}
|
|
672
|
+
__name(normalizePathNameWithParameters, "normalizePathNameWithParameters");
|
|
673
|
+
function wrapComponentPathType(type, context) {
|
|
674
|
+
context.typeImports.http.add("HttpSchema");
|
|
675
|
+
const httpSchemaMethodsWrapper = ts3.factory.createQualifiedName(
|
|
676
|
+
ts3.factory.createIdentifier("HttpSchema"),
|
|
677
|
+
ts3.factory.createIdentifier("Methods")
|
|
678
|
+
);
|
|
679
|
+
return ts3.factory.createTypeReferenceNode(httpSchemaMethodsWrapper, [type]);
|
|
680
|
+
}
|
|
681
|
+
__name(wrapComponentPathType, "wrapComponentPathType");
|
|
682
|
+
function normalizePath(path4, context, options = {}) {
|
|
683
|
+
const { isComponent: isComponent2 = false } = options;
|
|
684
|
+
if (!isPath(path4)) {
|
|
685
|
+
return undefined;
|
|
686
|
+
}
|
|
687
|
+
const newPathName = isComponent2 ? path4.name.text : normalizePathNameWithParameters(path4.name.text);
|
|
688
|
+
const newIdentifier = isComponent2 ? path4.name : ts3.factory.createStringLiteral(newPathName);
|
|
689
|
+
let newType;
|
|
690
|
+
if (ts3.isTypeLiteralNode(path4.type)) {
|
|
691
|
+
const newMethods = path4.type.members.map((method) => normalizeMethod(method, context, { pathName: newPathName })).filter(isDefined);
|
|
692
|
+
if (newMethods.length === 0) {
|
|
693
|
+
return undefined;
|
|
694
|
+
}
|
|
695
|
+
newType = ts3.factory.updateTypeLiteralNode(path4.type, ts3.factory.createNodeArray(newMethods));
|
|
696
|
+
} else {
|
|
697
|
+
newType = renameComponentReferences(path4.type, context);
|
|
698
|
+
}
|
|
699
|
+
return ts3.factory.updatePropertySignature(
|
|
700
|
+
path4,
|
|
701
|
+
path4.modifiers,
|
|
702
|
+
newIdentifier,
|
|
703
|
+
path4.questionToken,
|
|
704
|
+
isComponent2 ? wrapComponentPathType(newType, context) : newType
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
__name(normalizePath, "normalizePath");
|
|
708
|
+
function wrapPathsType(type, context) {
|
|
709
|
+
context.typeImports.http.add("HttpSchema");
|
|
710
|
+
const httpSchemaPathsWrapper = ts3.factory.createIdentifier("HttpSchema");
|
|
711
|
+
return ts3.factory.createTypeReferenceNode(httpSchemaPathsWrapper, [type]);
|
|
712
|
+
}
|
|
713
|
+
__name(wrapPathsType, "wrapPathsType");
|
|
714
|
+
function normalizePaths(pathsOrTypeAlias, context) {
|
|
715
|
+
const newIdentifier = createPathsIdentifier(context.serviceName);
|
|
716
|
+
const paths = ts3.isTypeAliasDeclaration(pathsOrTypeAlias) ? ts3.factory.createInterfaceDeclaration(pathsOrTypeAlias.modifiers, pathsOrTypeAlias.name, undefined, undefined, []) : pathsOrTypeAlias;
|
|
717
|
+
const newMembers = paths.members.map((path4) => normalizePath(path4, context)).filter(isDefined);
|
|
718
|
+
const newType = ts3.factory.createTypeLiteralNode(newMembers);
|
|
719
|
+
return ts3.factory.createTypeAliasDeclaration(
|
|
720
|
+
paths.modifiers,
|
|
721
|
+
newIdentifier,
|
|
722
|
+
paths.typeParameters,
|
|
723
|
+
wrapPathsType(newType, context)
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
__name(normalizePaths, "normalizePaths");
|
|
727
|
+
|
|
728
|
+
// src/typegen/openapi/transform/components.ts
|
|
729
|
+
function createComponentsIdentifierText(serviceName) {
|
|
730
|
+
return `${serviceName}Components`;
|
|
731
|
+
}
|
|
732
|
+
__name(createComponentsIdentifierText, "createComponentsIdentifierText");
|
|
733
|
+
function createComponentsIdentifier(serviceName) {
|
|
734
|
+
return ts3.factory.createIdentifier(createComponentsIdentifierText(serviceName));
|
|
735
|
+
}
|
|
736
|
+
__name(createComponentsIdentifier, "createComponentsIdentifier");
|
|
737
|
+
function isComponentsDeclaration(node, context) {
|
|
738
|
+
const componentIdentifiers = ["components", createComponentsIdentifierText(context.serviceName)];
|
|
739
|
+
return node !== undefined && ts3.isInterfaceDeclaration(node) && componentIdentifiers.includes(node.name.text);
|
|
740
|
+
}
|
|
741
|
+
__name(isComponentsDeclaration, "isComponentsDeclaration");
|
|
742
|
+
function isComponentGroup(node) {
|
|
743
|
+
return ts3.isPropertySignature(node) && node.type !== undefined && ts3.isTypeLiteralNode(node.type) && ts3.isIdentifier(node.name);
|
|
744
|
+
}
|
|
745
|
+
__name(isComponentGroup, "isComponentGroup");
|
|
746
|
+
function isComponent(node) {
|
|
747
|
+
return ts3.isPropertySignature(node) && node.type !== undefined && !isNeverType(node.type) && (ts3.isIdentifier(node.name) || ts3.isStringLiteral(node.name));
|
|
748
|
+
}
|
|
749
|
+
__name(isComponent, "isComponent");
|
|
750
|
+
function isRequestComponent(node) {
|
|
751
|
+
return ts3.isTypeLiteralNode(node.type);
|
|
752
|
+
}
|
|
753
|
+
__name(isRequestComponent, "isRequestComponent");
|
|
754
|
+
function unchangedIndexedAccessTypeNode(node) {
|
|
755
|
+
return node;
|
|
756
|
+
}
|
|
757
|
+
__name(unchangedIndexedAccessTypeNode, "unchangedIndexedAccessTypeNode");
|
|
758
|
+
function visitComponentReferences(node, context, options) {
|
|
759
|
+
const { onComponentReference, renameComponentReference = unchangedIndexedAccessTypeNode } = options;
|
|
760
|
+
if (isUnknownType(node)) {
|
|
761
|
+
return ts3.factory.createKeywordTypeNode(ts3.SyntaxKind.AnyKeyword);
|
|
762
|
+
}
|
|
763
|
+
if (ts3.isTypeReferenceNode(node)) {
|
|
764
|
+
const newTypeArguments = node.typeArguments?.map((type) => visitComponentReferences(type, context, options));
|
|
765
|
+
return ts3.factory.updateTypeReferenceNode(node, node.typeName, ts3.factory.createNodeArray(newTypeArguments));
|
|
766
|
+
}
|
|
767
|
+
if (ts3.isArrayTypeNode(node)) {
|
|
768
|
+
const newElementType = visitComponentReferences(node.elementType, context, options);
|
|
769
|
+
return ts3.factory.updateArrayTypeNode(node, newElementType);
|
|
770
|
+
}
|
|
771
|
+
if (ts3.isTupleTypeNode(node)) {
|
|
772
|
+
const newElements = node.elements.map((element) => visitComponentReferences(element, context, options));
|
|
773
|
+
return ts3.factory.updateTupleTypeNode(node, ts3.factory.createNodeArray(newElements));
|
|
774
|
+
}
|
|
775
|
+
if (ts3.isUnionTypeNode(node)) {
|
|
776
|
+
const newTypes = node.types.map((type) => visitComponentReferences(type, context, options));
|
|
777
|
+
return ts3.factory.updateUnionTypeNode(node, ts3.factory.createNodeArray(newTypes));
|
|
778
|
+
}
|
|
779
|
+
if (ts3.isIntersectionTypeNode(node)) {
|
|
780
|
+
const newTypes = node.types.map((type) => visitComponentReferences(type, context, options));
|
|
781
|
+
return ts3.factory.updateIntersectionTypeNode(node, ts3.factory.createNodeArray(newTypes));
|
|
782
|
+
}
|
|
783
|
+
if (ts3.isParenthesizedTypeNode(node)) {
|
|
784
|
+
const newType = visitComponentReferences(node.type, context, options);
|
|
785
|
+
return ts3.factory.updateParenthesizedType(node, newType);
|
|
786
|
+
}
|
|
787
|
+
if (ts3.isTypeLiteralNode(node)) {
|
|
788
|
+
const newMembers = node.members.map((member) => {
|
|
789
|
+
if (ts3.isPropertySignature(member) && member.type) {
|
|
790
|
+
const newType = visitComponentReferences(member.type, context, options);
|
|
791
|
+
return ts3.factory.updatePropertySignature(member, member.modifiers, member.name, member.questionToken, newType);
|
|
792
|
+
}
|
|
793
|
+
if (ts3.isIndexSignatureDeclaration(member)) {
|
|
794
|
+
const newType = visitComponentReferences(member.type, context, options);
|
|
795
|
+
return ts3.factory.updateIndexSignature(member, member.modifiers, member.parameters, newType);
|
|
796
|
+
}
|
|
797
|
+
return member;
|
|
798
|
+
});
|
|
799
|
+
return ts3.factory.updateTypeLiteralNode(node, ts3.factory.createNodeArray(newMembers));
|
|
800
|
+
}
|
|
801
|
+
if (ts3.isIndexedAccessTypeNode(node)) {
|
|
802
|
+
const isRootIndexedAccess = context.isComponentIndexedAccess ?? true;
|
|
803
|
+
if (ts3.isIndexedAccessTypeNode(node.objectType)) {
|
|
804
|
+
const childContext = { ...context, isComponentIndexedAccess: false };
|
|
805
|
+
const newObjectType = visitComponentReferences(node.objectType, childContext, options);
|
|
806
|
+
const newNode = ts3.factory.updateIndexedAccessTypeNode(node, newObjectType, node.indexType);
|
|
807
|
+
if (childContext.partialComponentPath && childContext.partialComponentPath.length > 0) {
|
|
808
|
+
const hasIndexTypeName = ts3.isLiteralTypeNode(node.indexType) && (ts3.isIdentifier(node.indexType.literal) || ts3.isStringLiteral(node.indexType.literal));
|
|
809
|
+
if (hasIndexTypeName) {
|
|
810
|
+
const componentName = node.indexType.literal.text;
|
|
811
|
+
childContext.partialComponentPath.push(componentName);
|
|
812
|
+
}
|
|
813
|
+
if (isRootIndexedAccess) {
|
|
814
|
+
const componentGroupName = childContext.partialComponentPath[0];
|
|
815
|
+
const componentName = childContext.partialComponentPath.slice(1).join(".");
|
|
816
|
+
const componentPath = `${componentGroupName}.${componentName}`;
|
|
817
|
+
onComponentReference(newNode, componentPath);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return newNode;
|
|
821
|
+
}
|
|
822
|
+
const componentIdentifiers = ["components", createComponentsIdentifierText(context.serviceName)];
|
|
823
|
+
const isComponentIndexedAccess = ts3.isTypeReferenceNode(node.objectType) && ts3.isIdentifier(node.objectType.typeName) && componentIdentifiers.includes(node.objectType.typeName.text) && ts3.isLiteralTypeNode(node.indexType) && (ts3.isIdentifier(node.indexType.literal) || ts3.isStringLiteral(node.indexType.literal));
|
|
824
|
+
if (isComponentIndexedAccess) {
|
|
825
|
+
const isRawComponent = node.objectType.typeName.text === "components";
|
|
826
|
+
const componentGroupName = node.indexType.literal.text;
|
|
827
|
+
const newNode = isRawComponent ? renameComponentReference(node, {
|
|
828
|
+
objectType: node.objectType,
|
|
829
|
+
indexType: node.indexType,
|
|
830
|
+
componentGroupName
|
|
831
|
+
}) : node;
|
|
832
|
+
const newNodeHasComponentGroupName = ts3.isLiteralTypeNode(newNode.indexType) && (ts3.isIdentifier(newNode.indexType.literal) || ts3.isStringLiteral(newNode.indexType.literal));
|
|
833
|
+
if (newNodeHasComponentGroupName) {
|
|
834
|
+
const newComponentGroupName = newNode.indexType.literal.text;
|
|
835
|
+
context.partialComponentPath = [newComponentGroupName];
|
|
836
|
+
}
|
|
837
|
+
return newNode;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return node;
|
|
841
|
+
}
|
|
842
|
+
__name(visitComponentReferences, "visitComponentReferences");
|
|
843
|
+
function normalizeComponentGroupName(rawComponentGroupName) {
|
|
844
|
+
if (rawComponentGroupName === "requestBodies") {
|
|
845
|
+
return "requests";
|
|
846
|
+
}
|
|
847
|
+
return rawComponentGroupName;
|
|
848
|
+
}
|
|
849
|
+
__name(normalizeComponentGroupName, "normalizeComponentGroupName");
|
|
850
|
+
function renameComponentReferences(node, context) {
|
|
851
|
+
return visitComponentReferences(node, context, {
|
|
852
|
+
onComponentReference(_node, componentPath) {
|
|
853
|
+
context.referencedTypes.components.add(componentPath);
|
|
854
|
+
},
|
|
855
|
+
renameComponentReference(node2, { indexType, objectType, componentGroupName }) {
|
|
856
|
+
const newIdentifier = createComponentsIdentifier(context.serviceName);
|
|
857
|
+
const newObjectType = ts3.factory.updateTypeReferenceNode(objectType, newIdentifier, objectType.typeArguments);
|
|
858
|
+
const newComponentGroupName = normalizeComponentGroupName(componentGroupName);
|
|
859
|
+
const newIndexType = ts3.factory.updateLiteralTypeNode(
|
|
860
|
+
indexType,
|
|
861
|
+
ts3.factory.createStringLiteral(newComponentGroupName)
|
|
862
|
+
);
|
|
863
|
+
return ts3.factory.updateIndexedAccessTypeNode(node2, newObjectType, newIndexType);
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
__name(renameComponentReferences, "renameComponentReferences");
|
|
868
|
+
function processPendingRequestComponentActions(component, context) {
|
|
869
|
+
const pendingRequestActions = context.pendingActions.components.requests;
|
|
870
|
+
const componentName = component.name.text;
|
|
871
|
+
const shouldBeMarkedAsOptional = pendingRequestActions.toMarkBodyAsOptional.has(componentName);
|
|
872
|
+
const bodyQuestionToken = shouldBeMarkedAsOptional ? ts3.factory.createToken(ts3.SyntaxKind.QuestionToken) : component.questionToken;
|
|
873
|
+
pendingRequestActions.toMarkBodyAsOptional.delete(componentName);
|
|
874
|
+
return { bodyQuestionToken };
|
|
875
|
+
}
|
|
876
|
+
__name(processPendingRequestComponentActions, "processPendingRequestComponentActions");
|
|
877
|
+
function wrapRequestComponentType(type, context) {
|
|
878
|
+
context.typeImports.http.add("HttpSchema");
|
|
879
|
+
const httpSchemaRequestWrapper = ts3.factory.createQualifiedName(
|
|
880
|
+
ts3.factory.createIdentifier("HttpSchema"),
|
|
881
|
+
ts3.factory.createIdentifier("Request")
|
|
882
|
+
);
|
|
883
|
+
return ts3.factory.createTypeReferenceNode(httpSchemaRequestWrapper, [type]);
|
|
884
|
+
}
|
|
885
|
+
__name(wrapRequestComponentType, "wrapRequestComponentType");
|
|
886
|
+
function normalizeRequestComponent(component, context) {
|
|
887
|
+
if (!isRequestComponent(component)) {
|
|
888
|
+
return undefined;
|
|
889
|
+
}
|
|
890
|
+
const { bodyQuestionToken } = processPendingRequestComponentActions(component, context);
|
|
891
|
+
const newType = normalizeContentType(component.type, context, { bodyQuestionToken });
|
|
892
|
+
return ts3.factory.updatePropertySignature(
|
|
893
|
+
component,
|
|
894
|
+
component.modifiers,
|
|
895
|
+
component.name,
|
|
896
|
+
component.questionToken,
|
|
897
|
+
wrapRequestComponentType(newType, context)
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
__name(normalizeRequestComponent, "normalizeRequestComponent");
|
|
901
|
+
function normalizeComponent(component, componentGroupName, context) {
|
|
902
|
+
if (!isComponent(component)) {
|
|
903
|
+
return undefined;
|
|
904
|
+
}
|
|
905
|
+
if (componentGroupName === "requests") {
|
|
906
|
+
return normalizeRequestComponent(component, context);
|
|
907
|
+
}
|
|
908
|
+
if (componentGroupName === "responses") {
|
|
909
|
+
const responseComponent = normalizeResponse(component, context, { isComponent: true });
|
|
910
|
+
return responseComponent?.newSignature;
|
|
911
|
+
}
|
|
912
|
+
if (componentGroupName === "pathItems") {
|
|
913
|
+
return normalizePath(component, context, { isComponent: true });
|
|
914
|
+
}
|
|
915
|
+
return ts3.factory.updatePropertySignature(
|
|
916
|
+
component,
|
|
917
|
+
component.modifiers,
|
|
918
|
+
component.name,
|
|
919
|
+
component.questionToken,
|
|
920
|
+
renameComponentReferences(component.type, context)
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
__name(normalizeComponent, "normalizeComponent");
|
|
924
|
+
function normalizeComponentGroup(componentGroup, context) {
|
|
925
|
+
if (!isComponentGroup(componentGroup)) {
|
|
926
|
+
return undefined;
|
|
927
|
+
}
|
|
928
|
+
const componentGroupName = normalizeComponentGroupName(componentGroup.name.text);
|
|
929
|
+
const newIdentifier = ts3.factory.createIdentifier(componentGroupName);
|
|
930
|
+
const newComponents = componentGroup.type.members.map((component) => normalizeComponent(component, componentGroupName, context)).filter(isDefined);
|
|
931
|
+
const newType = ts3.factory.updateTypeLiteralNode(componentGroup.type, ts3.factory.createNodeArray(newComponents));
|
|
932
|
+
return ts3.factory.updatePropertySignature(
|
|
933
|
+
componentGroup,
|
|
934
|
+
componentGroup.modifiers,
|
|
935
|
+
newIdentifier,
|
|
936
|
+
componentGroup.questionToken,
|
|
937
|
+
newType
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
__name(normalizeComponentGroup, "normalizeComponentGroup");
|
|
941
|
+
function normalizeComponents(components, context) {
|
|
942
|
+
const newIdentifier = createComponentsIdentifier(context.serviceName);
|
|
943
|
+
const newMembers = components.members.map((componentGroup) => normalizeComponentGroup(componentGroup, context)).filter(isDefined);
|
|
944
|
+
return ts3.factory.updateInterfaceDeclaration(
|
|
945
|
+
components,
|
|
946
|
+
components.modifiers,
|
|
947
|
+
newIdentifier,
|
|
948
|
+
components.typeParameters,
|
|
949
|
+
components.heritageClauses,
|
|
950
|
+
newMembers
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
__name(normalizeComponents, "normalizeComponents");
|
|
954
|
+
function populateReferencedComponents(components, context) {
|
|
955
|
+
const pathsToVisit = new Set(context.referencedTypes.components);
|
|
956
|
+
while (pathsToVisit.size > 0) {
|
|
957
|
+
const previousPathsToVisit = new Set(pathsToVisit);
|
|
958
|
+
pathsToVisit.clear();
|
|
959
|
+
for (const componentGroup of components.members) {
|
|
960
|
+
if (!isComponentGroup(componentGroup)) {
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
const componentGroupName = normalizeComponentGroupName(componentGroup.name.text);
|
|
964
|
+
for (const component of componentGroup.type.members) {
|
|
965
|
+
if (!isComponent(component)) {
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
const componentName = component.name.text;
|
|
969
|
+
const componentPath = `${componentGroupName}.${componentName}`;
|
|
970
|
+
const isComponentToVisit = previousPathsToVisit.has(componentPath);
|
|
971
|
+
if (!isComponentToVisit) {
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
context.referencedTypes.components.add(componentPath);
|
|
975
|
+
visitComponentReferences(component.type, context, {
|
|
976
|
+
onComponentReference(_node, componentPath2) {
|
|
977
|
+
const isKnownReferencedComponent = context.referencedTypes.components.has(componentPath2);
|
|
978
|
+
if (!isKnownReferencedComponent) {
|
|
979
|
+
pathsToVisit.add(componentPath2);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
__name(populateReferencedComponents, "populateReferencedComponents");
|
|
988
|
+
function removeComponentIfUnreferenced(component, componentGroupName, context) {
|
|
989
|
+
if (!isComponent(component)) {
|
|
990
|
+
return undefined;
|
|
991
|
+
}
|
|
992
|
+
const componentName = component.name.text;
|
|
993
|
+
const componentPath = `${componentGroupName}.${componentName}`;
|
|
994
|
+
if (context.referencedTypes.components.has(componentPath)) {
|
|
995
|
+
context.referencedTypes.components.delete(componentPath);
|
|
996
|
+
return component;
|
|
997
|
+
}
|
|
998
|
+
return undefined;
|
|
999
|
+
}
|
|
1000
|
+
__name(removeComponentIfUnreferenced, "removeComponentIfUnreferenced");
|
|
1001
|
+
function removeUnreferencedComponentsInGroup(componentGroup, context) {
|
|
1002
|
+
if (!isComponentGroup(componentGroup)) {
|
|
1003
|
+
return undefined;
|
|
1004
|
+
}
|
|
1005
|
+
const componentGroupName = normalizeComponentGroupName(componentGroup.name.text);
|
|
1006
|
+
const newComponents = componentGroup.type.members.map((component) => removeComponentIfUnreferenced(component, componentGroupName, context)).filter(isDefined);
|
|
1007
|
+
if (newComponents.length === 0) {
|
|
1008
|
+
return undefined;
|
|
1009
|
+
}
|
|
1010
|
+
return ts3.factory.updatePropertySignature(
|
|
1011
|
+
componentGroup,
|
|
1012
|
+
componentGroup.modifiers,
|
|
1013
|
+
componentGroup.name,
|
|
1014
|
+
componentGroup.questionToken,
|
|
1015
|
+
ts3.factory.updateTypeLiteralNode(componentGroup.type, ts3.factory.createNodeArray(newComponents))
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
__name(removeUnreferencedComponentsInGroup, "removeUnreferencedComponentsInGroup");
|
|
1019
|
+
function removeUnreferencedComponents(components, context) {
|
|
1020
|
+
const newComponentGroups = components.members.map((componentGroup) => removeUnreferencedComponentsInGroup(componentGroup, context)).filter(isDefined);
|
|
1021
|
+
context.referencedTypes.components.clear();
|
|
1022
|
+
if (newComponentGroups.length === 0) {
|
|
1023
|
+
return undefined;
|
|
1024
|
+
}
|
|
1025
|
+
return ts3.factory.updateInterfaceDeclaration(
|
|
1026
|
+
components,
|
|
1027
|
+
components.modifiers,
|
|
1028
|
+
components.name,
|
|
1029
|
+
components.typeParameters,
|
|
1030
|
+
components.heritageClauses,
|
|
1031
|
+
newComponentGroups
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
__name(removeUnreferencedComponents, "removeUnreferencedComponents");
|
|
1035
|
+
|
|
1036
|
+
// src/utils/strings.ts
|
|
1037
|
+
function convertToPascalCase(value) {
|
|
1038
|
+
return value.replace(/(?:^|[^A-Za-z\d])([A-Za-z\d])/g, (_match, letter) => letter.toUpperCase());
|
|
1039
|
+
}
|
|
1040
|
+
__name(convertToPascalCase, "convertToPascalCase");
|
|
1041
|
+
|
|
1042
|
+
// src/utils/urls.ts
|
|
1043
|
+
var InvalidURLError = class extends TypeError {
|
|
1044
|
+
static {
|
|
1045
|
+
__name(this, "InvalidURLError");
|
|
1046
|
+
}
|
|
1047
|
+
constructor(url) {
|
|
1048
|
+
super(`Invalid URL: '${url}'`);
|
|
1049
|
+
this.name = "InvalidURL";
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
function createURLOrThrow(rawURL) {
|
|
1053
|
+
try {
|
|
1054
|
+
const url = new URL(rawURL);
|
|
1055
|
+
Object.defineProperty(url, "raw", {
|
|
1056
|
+
value: rawURL.toString(),
|
|
1057
|
+
writable: false,
|
|
1058
|
+
enumerable: true,
|
|
1059
|
+
configurable: false
|
|
1060
|
+
});
|
|
1061
|
+
return url;
|
|
1062
|
+
} catch {
|
|
1063
|
+
throw new InvalidURLError(rawURL);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
__name(createURLOrThrow, "createURLOrThrow");
|
|
1067
|
+
function createURL(rawURL) {
|
|
1068
|
+
const url = createURLOrThrow(rawURL);
|
|
1069
|
+
return url;
|
|
1070
|
+
}
|
|
1071
|
+
__name(createURL, "createURL");
|
|
1072
|
+
function createFileURL(filePath) {
|
|
1073
|
+
return createURL(`file://${filePath}`);
|
|
1074
|
+
}
|
|
1075
|
+
__name(createFileURL, "createFileURL");
|
|
1076
|
+
function prepareURLForRegex(url) {
|
|
1077
|
+
const encodedURL = encodeURI(url);
|
|
1078
|
+
return encodedURL.replace(/([.()*?+$\\])/g, "\\$1");
|
|
1079
|
+
}
|
|
1080
|
+
__name(prepareURLForRegex, "prepareURLForRegex");
|
|
1081
|
+
function createRegexFromWildcardPath(path4, options) {
|
|
1082
|
+
const pathWithReplacedWildcards = prepareURLForRegex(path4).replace(/^\/+|\/+$/g, "").replace(/\\\*/g, "*").replace(/\*\*\/\*/g, "**").replace(/(^|[^*])\*([^*]|$)/g, "$1[^/]*$2").replace(/\*\*/g, ".*");
|
|
1083
|
+
return new RegExp(`^${options.prefix}/*${pathWithReplacedWildcards}/*$`);
|
|
1084
|
+
}
|
|
1085
|
+
__name(createRegexFromWildcardPath, "createRegexFromWildcardPath");
|
|
1086
|
+
|
|
1087
|
+
// src/typegen/openapi/transform/filters.ts
|
|
1088
|
+
var HTTP_METHOD_OPTIONS = HTTP_METHODS.join("|");
|
|
1089
|
+
var MODIFIER_GROUP = "(?<modifier>!?)";
|
|
1090
|
+
var METHOD_FILTER_GROUP = `(?<method>(?:\\*|(?:${HTTP_METHOD_OPTIONS})(?:,\\s*(?:${HTTP_METHOD_OPTIONS}))*))`;
|
|
1091
|
+
var PATH_FILTER_GROUP = "(?<path>.+)";
|
|
1092
|
+
var FILTER_REGEX = new RegExp(`^${MODIFIER_GROUP}\\s*${METHOD_FILTER_GROUP}\\s+${PATH_FILTER_GROUP}$`, "i");
|
|
1093
|
+
function parseRawFilter(rawFilter) {
|
|
1094
|
+
const filterMatch = rawFilter.match(FILTER_REGEX);
|
|
1095
|
+
const { modifier: filterModifier, method: filteredMethodsOrWildcard, path: filteredPath } = filterMatch?.groups ?? {};
|
|
1096
|
+
const isValidFilter = !filteredMethodsOrWildcard || !filteredPath;
|
|
1097
|
+
if (isValidFilter) {
|
|
1098
|
+
logWithPrefix(`Warning: Filter could not be parsed and was ignored: ${chalk.yellow(rawFilter)}`, {
|
|
1099
|
+
method: "warn"
|
|
1100
|
+
});
|
|
1101
|
+
return undefined;
|
|
1102
|
+
}
|
|
1103
|
+
const methodFilterGroup = `(?:${filteredMethodsOrWildcard.toUpperCase().replace(/,/g, "|").replace(/\*/g, ".*")}) `;
|
|
1104
|
+
const isNegativeMatch = filterModifier === "!";
|
|
1105
|
+
return {
|
|
1106
|
+
expression: createRegexFromWildcardPath(filteredPath, { prefix: methodFilterGroup }),
|
|
1107
|
+
isNegativeMatch
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
__name(parseRawFilter, "parseRawFilter");
|
|
1111
|
+
function groupParsedFiltersByMatch(parsedFilters) {
|
|
1112
|
+
return parsedFilters.reduce(
|
|
1113
|
+
(groupedFilters, filter) => {
|
|
1114
|
+
if (filter) {
|
|
1115
|
+
if (filter.isNegativeMatch) {
|
|
1116
|
+
groupedFilters.negative.push(filter.expression);
|
|
1117
|
+
} else {
|
|
1118
|
+
groupedFilters.positive.push(filter.expression);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
return groupedFilters;
|
|
1122
|
+
},
|
|
1123
|
+
{ positive: [], negative: [] }
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
__name(groupParsedFiltersByMatch, "groupParsedFiltersByMatch");
|
|
1127
|
+
async function readPathFiltersFromFile(filePath) {
|
|
1128
|
+
const fileContent = await filesystem.readFile(path.resolve(filePath), "utf-8");
|
|
1129
|
+
const fileContentWithoutComments = fileContent.replace(/#.*$/gm, "");
|
|
1130
|
+
const filters = fileContentWithoutComments.split("\n");
|
|
1131
|
+
return filters;
|
|
1132
|
+
}
|
|
1133
|
+
__name(readPathFiltersFromFile, "readPathFiltersFromFile");
|
|
1134
|
+
function ignoreEmptyFilters(filters) {
|
|
1135
|
+
return filters.map((line) => line.trim()).filter(isNonEmpty);
|
|
1136
|
+
}
|
|
1137
|
+
__name(ignoreEmptyFilters, "ignoreEmptyFilters");
|
|
1138
|
+
|
|
1139
|
+
// src/typegen/openapi/transform/context.ts
|
|
1140
|
+
function createTypeTransformationContext(serviceName, rawFilters) {
|
|
1141
|
+
const parsedFilters = rawFilters.map(parseRawFilter);
|
|
1142
|
+
return {
|
|
1143
|
+
serviceName: convertToPascalCase(serviceName),
|
|
1144
|
+
filters: {
|
|
1145
|
+
paths: groupParsedFiltersByMatch(parsedFilters)
|
|
1146
|
+
},
|
|
1147
|
+
typeImports: {
|
|
1148
|
+
http: /* @__PURE__ */ new Set()
|
|
1149
|
+
},
|
|
1150
|
+
referencedTypes: {
|
|
1151
|
+
operations: /* @__PURE__ */ new Set(),
|
|
1152
|
+
components: /* @__PURE__ */ new Set()
|
|
1153
|
+
},
|
|
1154
|
+
pendingActions: {
|
|
1155
|
+
components: {
|
|
1156
|
+
requests: { toMarkBodyAsOptional: /* @__PURE__ */ new Set() }
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
__name(createTypeTransformationContext, "createTypeTransformationContext");
|
|
1162
|
+
|
|
1163
|
+
// src/typegen/openapi/transform/imports.ts
|
|
1164
|
+
var TYPEGEN_HTTP_IMPORT_MODULE = "@zimic/http";
|
|
1165
|
+
function createImportDeclarations(context) {
|
|
1166
|
+
const httpTypeImports = Array.from(context.typeImports.http).sort().map(createImportSpecifier);
|
|
1167
|
+
const httpImportDeclaration = createImportDeclaration(httpTypeImports, TYPEGEN_HTTP_IMPORT_MODULE, {
|
|
1168
|
+
typeOnly: true
|
|
1169
|
+
});
|
|
1170
|
+
return [httpImportDeclaration];
|
|
1171
|
+
}
|
|
1172
|
+
__name(createImportDeclarations, "createImportDeclarations");
|
|
1173
|
+
|
|
1174
|
+
// src/utils/imports.ts
|
|
1175
|
+
function createCachedDynamicImport(importModuleDynamically) {
|
|
1176
|
+
let cachedImportResult;
|
|
1177
|
+
return /* @__PURE__ */ __name(async function importModuleDynamicallyWithCache() {
|
|
1178
|
+
if (cachedImportResult === undefined) {
|
|
1179
|
+
cachedImportResult = await importModuleDynamically();
|
|
1180
|
+
}
|
|
1181
|
+
return cachedImportResult;
|
|
1182
|
+
}, "importModuleDynamicallyWithCache");
|
|
1183
|
+
}
|
|
1184
|
+
__name(createCachedDynamicImport, "createCachedDynamicImport");
|
|
1185
|
+
|
|
1186
|
+
// src/typegen/openapi/transform/io.ts
|
|
1187
|
+
var importOpenapiTypeScript = createCachedDynamicImport(() => import('openapi-typescript'));
|
|
1188
|
+
function transformSchemaObject(schemaObject) {
|
|
1189
|
+
if (schemaObject.format === "binary") {
|
|
1190
|
+
const blobType = createBlobType();
|
|
1191
|
+
if (schemaObject.nullable) {
|
|
1192
|
+
const nullType = createNullType();
|
|
1193
|
+
return ts3.factory.createUnionTypeNode([blobType, nullType]);
|
|
1194
|
+
}
|
|
1195
|
+
return blobType;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
__name(transformSchemaObject, "transformSchemaObject");
|
|
1199
|
+
function convertFilePathOrURLToURL(filePathOrURL) {
|
|
1200
|
+
try {
|
|
1201
|
+
return createURL(filePathOrURL);
|
|
1202
|
+
} catch {
|
|
1203
|
+
return createFileURL(path.resolve(filePathOrURL));
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
__name(convertFilePathOrURLToURL, "convertFilePathOrURLToURL");
|
|
1207
|
+
async function importTypesFromOpenAPI(filePathOrURL) {
|
|
1208
|
+
const schemaURL = convertFilePathOrURLToURL(filePathOrURL);
|
|
1209
|
+
const { default: generateTypesFromOpenAPI2 } = await importOpenapiTypeScript();
|
|
1210
|
+
const rawNodes = await generateTypesFromOpenAPI2(schemaURL, {
|
|
1211
|
+
alphabetize: false,
|
|
1212
|
+
additionalProperties: false,
|
|
1213
|
+
excludeDeprecated: false,
|
|
1214
|
+
propertiesRequiredByDefault: false,
|
|
1215
|
+
defaultNonNullable: true,
|
|
1216
|
+
pathParamsAsTypes: false,
|
|
1217
|
+
emptyObjectsUnknown: true,
|
|
1218
|
+
exportType: false,
|
|
1219
|
+
arrayLength: false,
|
|
1220
|
+
immutable: false,
|
|
1221
|
+
enumValues: false,
|
|
1222
|
+
enum: false,
|
|
1223
|
+
silent: true,
|
|
1224
|
+
transform: transformSchemaObject
|
|
1225
|
+
});
|
|
1226
|
+
return rawNodes;
|
|
1227
|
+
}
|
|
1228
|
+
__name(importTypesFromOpenAPI, "importTypesFromOpenAPI");
|
|
1229
|
+
async function convertTypesToString(nodes, options) {
|
|
1230
|
+
const { astToString: convertTypeASTToString } = await importOpenapiTypeScript();
|
|
1231
|
+
const typeOutput = convertTypeASTToString(nodes, {
|
|
1232
|
+
formatOptions: { removeComments: !options.includeComments }
|
|
1233
|
+
});
|
|
1234
|
+
return typeOutput;
|
|
1235
|
+
}
|
|
1236
|
+
__name(convertTypesToString, "convertTypesToString");
|
|
1237
|
+
function prepareTypeOutputToSave(output) {
|
|
1238
|
+
const formattedOutput = output.replace(/^export (\w+)/gm, "\nexport $1").replace(/^( {4})+/gm, (match) => match.replace(/ {4}/g, " "));
|
|
1239
|
+
const formattedOutputWithPrefix = [
|
|
1240
|
+
"// Auto-generated by zimic.",
|
|
1241
|
+
"// NOTE: Do not manually edit this file. Changes will be overridden.\n",
|
|
1242
|
+
formattedOutput
|
|
1243
|
+
].join("\n");
|
|
1244
|
+
return formattedOutputWithPrefix;
|
|
1245
|
+
}
|
|
1246
|
+
__name(prepareTypeOutputToSave, "prepareTypeOutputToSave");
|
|
1247
|
+
async function writeTypeOutputToStandardOutput(formattedOutput) {
|
|
1248
|
+
await new Promise((resolve) => {
|
|
1249
|
+
process.stdout.write(formattedOutput, "utf-8", resolve);
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
__name(writeTypeOutputToStandardOutput, "writeTypeOutputToStandardOutput");
|
|
1253
|
+
|
|
1254
|
+
// src/typegen/openapi/generate.ts
|
|
1255
|
+
var RESOURCES_TO_REMOVE_IF_NOT_NORMALIZED = ["paths", "webhooks", "operations", "components", "$defs"];
|
|
1256
|
+
function removeUnknownResources(node) {
|
|
1257
|
+
const isUnknownResource = !node || (ts3.isTypeAliasDeclaration(node) || ts3.isInterfaceDeclaration(node)) && RESOURCES_TO_REMOVE_IF_NOT_NORMALIZED.includes(node.name.text);
|
|
1258
|
+
if (isUnknownResource) {
|
|
1259
|
+
return undefined;
|
|
1260
|
+
}
|
|
1261
|
+
return node;
|
|
1262
|
+
}
|
|
1263
|
+
__name(removeUnknownResources, "removeUnknownResources");
|
|
1264
|
+
function normalizeRawNodes(rawNodes, context, options) {
|
|
1265
|
+
let normalizedNodes = rawNodes.map((node) => isPathsDeclaration(node) ? normalizePaths(node, context) : node);
|
|
1266
|
+
if (options.prune) {
|
|
1267
|
+
normalizedNodes = normalizedNodes.map((node) => isOperationsDeclaration(node) ? removeUnreferencedOperations(node, context) : node).filter(isDefined);
|
|
1268
|
+
}
|
|
1269
|
+
normalizedNodes = normalizedNodes.map((node) => isOperationsDeclaration(node) ? normalizeOperations(node, context) : node).filter(isDefined);
|
|
1270
|
+
if (options.prune) {
|
|
1271
|
+
for (const node of normalizedNodes) {
|
|
1272
|
+
if (isComponentsDeclaration(node, context)) {
|
|
1273
|
+
populateReferencedComponents(node, context);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
normalizedNodes = normalizedNodes.map((node) => isComponentsDeclaration(node, context) ? removeUnreferencedComponents(node, context) : node).filter(isDefined);
|
|
1277
|
+
}
|
|
1278
|
+
normalizedNodes = normalizedNodes.map((node) => isComponentsDeclaration(node, context) ? normalizeComponents(node, context) : node).map(removeUnknownResources).filter(isDefined);
|
|
1279
|
+
return normalizedNodes;
|
|
1280
|
+
}
|
|
1281
|
+
__name(normalizeRawNodes, "normalizeRawNodes");
|
|
1282
|
+
async function generateTypesFromOpenAPI({
|
|
1283
|
+
input: inputFilePathOrURL,
|
|
1284
|
+
output: outputFilePath,
|
|
1285
|
+
serviceName,
|
|
1286
|
+
includeComments,
|
|
1287
|
+
prune,
|
|
1288
|
+
filters: filtersFromArguments = [],
|
|
1289
|
+
filterFile
|
|
1290
|
+
}) {
|
|
1291
|
+
const filtersFromFile = filterFile ? await readPathFiltersFromFile(filterFile) : [];
|
|
1292
|
+
const filters = ignoreEmptyFilters([...filtersFromFile, ...filtersFromArguments]);
|
|
1293
|
+
const rawNodes = await importTypesFromOpenAPI(inputFilePathOrURL);
|
|
1294
|
+
const context = createTypeTransformationContext(serviceName, filters);
|
|
1295
|
+
const nodes = normalizeRawNodes(rawNodes, context, { prune });
|
|
1296
|
+
const importDeclarations = createImportDeclarations(context);
|
|
1297
|
+
for (const declaration of importDeclarations) {
|
|
1298
|
+
nodes.unshift(declaration);
|
|
1299
|
+
}
|
|
1300
|
+
const typeOutput = await convertTypesToString(nodes, { includeComments });
|
|
1301
|
+
const formattedOutput = prepareTypeOutputToSave(typeOutput);
|
|
1302
|
+
const shouldWriteToStdout = outputFilePath === undefined;
|
|
1303
|
+
if (shouldWriteToStdout) {
|
|
1304
|
+
await writeTypeOutputToStandardOutput(formattedOutput);
|
|
1305
|
+
} else {
|
|
1306
|
+
await filesystem.writeFile(path.resolve(outputFilePath), formattedOutput);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
__name(generateTypesFromOpenAPI, "generateTypesFromOpenAPI");
|
|
1310
|
+
var generate_default = generateTypesFromOpenAPI;
|
|
1311
|
+
|
|
1312
|
+
// src/typegen/namespace/TypegenNamespace.ts
|
|
1313
|
+
var TypegenNamespace = class {
|
|
1314
|
+
static {
|
|
1315
|
+
__name(this, "TypegenNamespace");
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Generates TypeScript types from an OpenAPI schema.
|
|
1319
|
+
*
|
|
1320
|
+
* @param options The options to use when generating the types.
|
|
1321
|
+
* @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐typegen#typegengeneratefromopenapioptions `typegen.generateFromOpenAPI(options)` API reference}
|
|
1322
|
+
*/
|
|
1323
|
+
generateFromOpenAPI = generate_default;
|
|
1324
|
+
};
|
|
1325
|
+
var TypegenNamespace_default = TypegenNamespace;
|
|
1326
|
+
|
|
1327
|
+
// src/typegen/index.ts
|
|
1328
|
+
var typegen = Object.freeze(new TypegenNamespace_default());
|
|
1329
|
+
/* istanbul ignore if -- @preserve
|
|
1330
|
+
* Operation members are always expected to be an operation. */
|
|
1331
|
+
/* istanbul ignore else -- @preserve */
|
|
1332
|
+
/* istanbul ignore next -- @preserve
|
|
1333
|
+
* Member types are always expected to be a union type or a parenthesized union type. */
|
|
1334
|
+
/* istanbul ignore if -- @preserve
|
|
1335
|
+
* Request body members are always expected to be a request body. */
|
|
1336
|
+
/* istanbul ignore next -- @preserve
|
|
1337
|
+
* Headers are always expected to be property signatures or index signatures. */
|
|
1338
|
+
/* istanbul ignore if -- @preserve
|
|
1339
|
+
* Response members are always expected to be a response. */
|
|
1340
|
+
/* istanbul ignore next -- @preserve
|
|
1341
|
+
* Method members are always expected as property signatures in methods. */
|
|
1342
|
+
/* istanbul ignore next -- @preserve
|
|
1343
|
+
* Parameters member is always expected to be found. */
|
|
1344
|
+
/* istanbul ignore if -- @preserve
|
|
1345
|
+
* Method members are always expected to have a name and type at this point. */
|
|
1346
|
+
/* istanbul ignore if -- @preserve
|
|
1347
|
+
* In indexed access method types, the reference is always expected to be an operation. */
|
|
1348
|
+
/* istanbul ignore else -- @preserve
|
|
1349
|
+
* In indexed access method types referencing operations, an index type name is always expected. */
|
|
1350
|
+
/* istanbul ignore if -- @preserve
|
|
1351
|
+
* Path members are always expected to be a path. */
|
|
1352
|
+
/* istanbul ignore next -- @preserve
|
|
1353
|
+
* All members are expected to be either a property signature or an index signature. */
|
|
1354
|
+
/* istanbul ignore else -- @preserve
|
|
1355
|
+
* Component indexed accesses are always expected to have child indexed accesses. */
|
|
1356
|
+
/* istanbul ignore else -- @preserve
|
|
1357
|
+
* All indexed accesses are expected to point to components. */
|
|
1358
|
+
/* istanbul ignore else -- @preserve
|
|
1359
|
+
* All component indexed accesses are expected to have an index type name. */
|
|
1360
|
+
/* istanbul ignore if -- @preserve
|
|
1361
|
+
* Component group members in `requests` are always expected the be request components. */
|
|
1362
|
+
/* istanbul ignore if -- @preserve
|
|
1363
|
+
* Component group members are always expected the be components. */
|
|
1364
|
+
/* istanbul ignore if -- @preserve
|
|
1365
|
+
* Component members are always expected the be component groups. */
|
|
1366
|
+
/* istanbul ignore next -- @preserve
|
|
1367
|
+
* The root import module is defined at build time. The fallback is not expected to be used. */
|
|
1368
|
+
|
|
1369
|
+
export { __name, logWithPrefix, typegen };
|
|
1370
|
+
//# sourceMappingURL=chunk-VHQRAQPQ.mjs.map
|
|
1371
|
+
//# sourceMappingURL=chunk-VHQRAQPQ.mjs.map
|