typedapi-client-helpers 0.1.16 → 0.2.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/README.md +220 -490
- package/dist/index.cjs +274 -47
- package/dist/index.d.cts +79 -95
- package/dist/index.d.ts +79 -95
- package/dist/index.js +267 -47
- package/package.json +30 -13
- package/scripts/generate-api-minimal.mjs +158 -785
- package/scripts/openapi-generator/controller-template.mjs +246 -0
- package/scripts/openapi-generator/http-client-template.mjs +34 -0
- package/scripts/openapi-generator/index.mjs +113 -0
- package/scripts/openapi-generator/method-template.mjs +440 -0
- package/scripts/openapi-generator/names.mjs +145 -0
- package/scripts/openapi-generator/openapi-utils.mjs +147 -0
- package/scripts/openapi-generator/schema.mjs +455 -0
- package/bin/typedapi-generate.js +0 -3
- package/dist/api/generated/Import.d.ts +0 -22
- package/dist/api/generated/Import.d.ts.map +0 -1
- package/dist/api/generated/Import.js +0 -48
- package/dist/api/generated/Import.js.map +0 -1
- package/dist/api/generated/ImportRoute.d.ts +0 -30
- package/dist/api/generated/ImportRoute.d.ts.map +0 -1
- package/dist/api/generated/ImportRoute.js +0 -13
- package/dist/api/generated/ImportRoute.js.map +0 -1
- package/dist/api/generated/Order.d.ts +0 -38
- package/dist/api/generated/Order.d.ts.map +0 -1
- package/dist/api/generated/Order.js +0 -75
- package/dist/api/generated/Order.js.map +0 -1
- package/dist/api/generated/OrderRoute.d.ts +0 -83
- package/dist/api/generated/OrderRoute.d.ts.map +0 -1
- package/dist/api/generated/OrderRoute.js +0 -13
- package/dist/api/generated/OrderRoute.js.map +0 -1
- package/dist/api/generated/Product.d.ts +0 -62
- package/dist/api/generated/Product.d.ts.map +0 -1
- package/dist/api/generated/Product.js +0 -114
- package/dist/api/generated/Product.js.map +0 -1
- package/dist/api/generated/ProductRoute.d.ts +0 -140
- package/dist/api/generated/ProductRoute.d.ts.map +0 -1
- package/dist/api/generated/ProductRoute.js +0 -13
- package/dist/api/generated/ProductRoute.js.map +0 -1
- package/dist/api/generated/Report.d.ts +0 -14
- package/dist/api/generated/Report.d.ts.map +0 -1
- package/dist/api/generated/Report.js +0 -32
- package/dist/api/generated/Report.js.map +0 -1
- package/dist/api/generated/ReportRoute.d.ts +0 -23
- package/dist/api/generated/ReportRoute.d.ts.map +0 -1
- package/dist/api/generated/ReportRoute.js +0 -13
- package/dist/api/generated/ReportRoute.js.map +0 -1
- package/dist/api/generated/Supplier.d.ts +0 -46
- package/dist/api/generated/Supplier.d.ts.map +0 -1
- package/dist/api/generated/Supplier.js +0 -87
- package/dist/api/generated/Supplier.js.map +0 -1
- package/dist/api/generated/SupplierRoute.d.ts +0 -101
- package/dist/api/generated/SupplierRoute.d.ts.map +0 -1
- package/dist/api/generated/SupplierRoute.js +0 -13
- package/dist/api/generated/SupplierRoute.js.map +0 -1
- package/dist/api/generated/data-contracts.d.ts +0 -277
- package/dist/api/generated/data-contracts.d.ts.map +0 -1
- package/dist/api/generated/data-contracts.js +0 -26
- package/dist/api/generated/data-contracts.js.map +0 -1
- package/dist/api/generated/http-client.d.ts +0 -61
- package/dist/api/generated/http-client.d.ts.map +0 -1
- package/dist/api/generated/http-client.js +0 -171
- package/dist/api/generated/http-client.js.map +0 -1
- package/dist/api/index.d.ts +0 -8
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -8
- package/dist/api/index.js.map +0 -1
- package/dist/api/methods/Import.api.d.ts +0 -6
- package/dist/api/methods/Import.api.d.ts.map +0 -1
- package/dist/api/methods/Import.api.js +0 -27
- package/dist/api/methods/Import.api.js.map +0 -1
- package/dist/api/methods/Order.api.d.ts +0 -29
- package/dist/api/methods/Order.api.d.ts.map +0 -1
- package/dist/api/methods/Order.api.js +0 -52
- package/dist/api/methods/Order.api.js.map +0 -1
- package/dist/api/methods/Product.api.d.ts +0 -39
- package/dist/api/methods/Product.api.d.ts.map +0 -1
- package/dist/api/methods/Product.api.js +0 -69
- package/dist/api/methods/Product.api.js.map +0 -1
- package/dist/api/methods/Report.api.d.ts +0 -6
- package/dist/api/methods/Report.api.d.ts.map +0 -1
- package/dist/api/methods/Report.api.js +0 -19
- package/dist/api/methods/Report.api.js.map +0 -1
- package/dist/api/methods/Supplier.api.d.ts +0 -35
- package/dist/api/methods/Supplier.api.d.ts.map +0 -1
- package/dist/api/methods/Supplier.api.js +0 -63
- package/dist/api/methods/Supplier.api.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/interfaces/ApiResult.d.ts +0 -17
- package/dist/interfaces/ApiResult.d.ts.map +0 -1
- package/dist/interfaces/ApiResult.js +0 -2
- package/dist/interfaces/ApiResult.js.map +0 -1
- package/dist/interfaces/Filter.d.ts +0 -31
- package/dist/interfaces/Filter.d.ts.map +0 -1
- package/dist/interfaces/Filter.js +0 -2
- package/dist/interfaces/Filter.js.map +0 -1
- package/dist/interfaces/SortType.d.ts +0 -7
- package/dist/interfaces/SortType.d.ts.map +0 -1
- package/dist/interfaces/SortType.js +0 -2
- package/dist/interfaces/SortType.js.map +0 -1
- package/dist/types/ApiCallOptions.d.ts +0 -9
- package/dist/types/ApiCallOptions.d.ts.map +0 -1
- package/dist/types/ApiCallOptions.js +0 -2
- package/dist/types/ApiCallOptions.js.map +0 -1
- package/dist/types/ApiMethodTypes.d.ts +0 -24
- package/dist/types/ApiMethodTypes.d.ts.map +0 -1
- package/dist/types/ApiMethodTypes.js +0 -2
- package/dist/types/ApiMethodTypes.js.map +0 -1
- package/dist/types/HttpResponse.d.ts +0 -16
- package/dist/types/HttpResponse.d.ts.map +0 -1
- package/dist/types/HttpResponse.js +0 -2
- package/dist/types/HttpResponse.js.map +0 -1
- package/dist/utils/SortTypeFromSortDirection.d.ts +0 -22
- package/dist/utils/SortTypeFromSortDirection.d.ts.map +0 -1
- package/dist/utils/SortTypeFromSortDirection.js +0 -45
- package/dist/utils/SortTypeFromSortDirection.js.map +0 -1
- package/dist/utils/buildQuery.d.ts +0 -11
- package/dist/utils/buildQuery.d.ts.map +0 -1
- package/dist/utils/buildQuery.js +0 -94
- package/dist/utils/buildQuery.js.map +0 -1
- package/dist/utils/extractArgsCallbacksAndParams.d.ts +0 -22
- package/dist/utils/extractArgsCallbacksAndParams.d.ts.map +0 -1
- package/dist/utils/extractArgsCallbacksAndParams.js +0 -44
- package/dist/utils/extractArgsCallbacksAndParams.js.map +0 -1
- package/dist/utils/extractArgsToastsAndParams.d.ts +0 -18
- package/dist/utils/extractArgsToastsAndParams.d.ts.map +0 -1
- package/dist/utils/extractArgsToastsAndParams.js +0 -40
- package/dist/utils/extractArgsToastsAndParams.js.map +0 -1
- package/dist/utils/handleApiResponse.d.ts +0 -9
- package/dist/utils/handleApiResponse.d.ts.map +0 -1
- package/dist/utils/handleApiResponse.js +0 -49
- package/dist/utils/handleApiResponse.js.map +0 -1
- package/dist/utils/toFormData.d.ts +0 -8
- package/dist/utils/toFormData.d.ts.map +0 -1
- package/dist/utils/toFormData.js +0 -68
- package/dist/utils/toFormData.js.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export const httpMethods = new Set([
|
|
2
|
+
"get",
|
|
3
|
+
"put",
|
|
4
|
+
"post",
|
|
5
|
+
"delete",
|
|
6
|
+
"options",
|
|
7
|
+
"head",
|
|
8
|
+
"patch",
|
|
9
|
+
"trace",
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
export function isObject(value) {
|
|
13
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function dereference(openApi, schemaOrRef) {
|
|
17
|
+
if (!schemaOrRef || !schemaOrRef.$ref) {
|
|
18
|
+
return schemaOrRef;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const path = schemaOrRef.$ref.replace(/^#\//, "").split("/");
|
|
22
|
+
let current = openApi;
|
|
23
|
+
|
|
24
|
+
for (const rawPart of path) {
|
|
25
|
+
const part = rawPart.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
26
|
+
current = current?.[part];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return current ?? schemaOrRef;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getRequestBodyContent(requestBody) {
|
|
33
|
+
const content = requestBody?.content ?? {};
|
|
34
|
+
const preferredTypes = [
|
|
35
|
+
"application/json",
|
|
36
|
+
"multipart/form-data",
|
|
37
|
+
"application/x-www-form-urlencoded",
|
|
38
|
+
"text/plain",
|
|
39
|
+
"application/octet-stream",
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
for (const contentType of preferredTypes) {
|
|
43
|
+
if (content[contentType]) {
|
|
44
|
+
return {
|
|
45
|
+
contentType,
|
|
46
|
+
mediaType: content[contentType],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const [contentType, mediaType] = Object.entries(content)[0] ?? [];
|
|
52
|
+
|
|
53
|
+
return contentType ? { contentType, mediaType } : undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getSuccessResponse(
|
|
57
|
+
operation,
|
|
58
|
+
defaultResponseAsSuccess = false,
|
|
59
|
+
) {
|
|
60
|
+
const responses = operation.responses ?? {};
|
|
61
|
+
const preferredStatusCodes = [
|
|
62
|
+
"200",
|
|
63
|
+
"201",
|
|
64
|
+
"202",
|
|
65
|
+
"203",
|
|
66
|
+
"204",
|
|
67
|
+
"205",
|
|
68
|
+
"206",
|
|
69
|
+
"207",
|
|
70
|
+
"208",
|
|
71
|
+
"226",
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
for (const statusCode of preferredStatusCodes) {
|
|
75
|
+
if (responses[statusCode]) {
|
|
76
|
+
return { statusCode, response: responses[statusCode] };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const successEntry = Object.entries(responses).find(([statusCode]) =>
|
|
81
|
+
/^2\d\d$/.test(statusCode),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (successEntry) {
|
|
85
|
+
return { statusCode: successEntry[0], response: successEntry[1] };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (defaultResponseAsSuccess && responses.default) {
|
|
89
|
+
return { statusCode: "default", response: responses.default };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function getResponseContent(response) {
|
|
96
|
+
const content = response?.content ?? {};
|
|
97
|
+
const preferredTypes = [
|
|
98
|
+
"application/json",
|
|
99
|
+
"text/json",
|
|
100
|
+
"application/problem+json",
|
|
101
|
+
"application/octet-stream",
|
|
102
|
+
"text/plain",
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
for (const contentType of preferredTypes) {
|
|
106
|
+
if (content[contentType]) {
|
|
107
|
+
return {
|
|
108
|
+
contentType,
|
|
109
|
+
mediaType: content[contentType],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const [contentType, mediaType] = Object.entries(content)[0] ?? [];
|
|
115
|
+
|
|
116
|
+
return contentType ? { contentType, mediaType } : undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function collectOperations(openApi) {
|
|
120
|
+
const operations = [];
|
|
121
|
+
|
|
122
|
+
for (const [routePath, pathItem] of Object.entries(openApi.paths ?? {})) {
|
|
123
|
+
const pathParameters = Array.isArray(pathItem.parameters)
|
|
124
|
+
? pathItem.parameters
|
|
125
|
+
: [];
|
|
126
|
+
|
|
127
|
+
for (const [method, operation] of Object.entries(pathItem)) {
|
|
128
|
+
if (!httpMethods.has(method)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const parameters = [
|
|
133
|
+
...pathParameters,
|
|
134
|
+
...(Array.isArray(operation.parameters) ? operation.parameters : []),
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
operations.push({
|
|
138
|
+
routePath,
|
|
139
|
+
method: method.toUpperCase(),
|
|
140
|
+
operation,
|
|
141
|
+
parameters,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return operations;
|
|
147
|
+
}
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dereference,
|
|
3
|
+
getRequestBodyContent,
|
|
4
|
+
getResponseContent,
|
|
5
|
+
getSuccessResponse,
|
|
6
|
+
} from "./openapi-utils.mjs";
|
|
7
|
+
import { camelCase, pascalCase, propertyKey, refName } from "./names.mjs";
|
|
8
|
+
|
|
9
|
+
function jsDocFromSchema(schema, indent = "") {
|
|
10
|
+
const lines = [];
|
|
11
|
+
|
|
12
|
+
if (schema?.description) {
|
|
13
|
+
lines.push(...String(schema.description).split(/\r?\n/));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (schema?.format) {
|
|
17
|
+
lines.push(`@format ${schema.format}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (Object.prototype.hasOwnProperty.call(schema ?? {}, "default")) {
|
|
21
|
+
lines.push(`@default ${JSON.stringify(schema.default)}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (schema?.deprecated) {
|
|
25
|
+
lines.push("@deprecated");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (lines.length === 0) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (lines.length === 1) {
|
|
33
|
+
return `${indent}/** ${lines[0]} */\n`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return `${indent}/**\n${lines.map((line) => `${indent} * ${line}`).join("\n")}\n${indent} */\n`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function unionTypes(types) {
|
|
40
|
+
const unique = [...new Set(types.filter(Boolean))];
|
|
41
|
+
return unique.length > 0 ? unique.join(" | ") : "any";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class TypeResolver {
|
|
45
|
+
constructor(openApi, options = {}) {
|
|
46
|
+
this.openApi = openApi;
|
|
47
|
+
this.options = options;
|
|
48
|
+
this.inlineTypes = new Map();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
resolve(schemaOrRef, contextName = "Anonymous", options = {}) {
|
|
52
|
+
if (!schemaOrRef) {
|
|
53
|
+
return "any";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (schemaOrRef.$ref) {
|
|
57
|
+
return refName(schemaOrRef.$ref);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const schema = dereference(this.openApi, schemaOrRef) ?? schemaOrRef;
|
|
61
|
+
const nullable =
|
|
62
|
+
schema.nullable ||
|
|
63
|
+
(Array.isArray(schema.type) && schema.type.includes("null"));
|
|
64
|
+
let type = this.resolveNonNullable(schema, contextName, options);
|
|
65
|
+
|
|
66
|
+
if (nullable && !type.includes("null")) {
|
|
67
|
+
type = `${type} | null`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return type;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
resolveNonNullable(schema, contextName, options = {}) {
|
|
74
|
+
if (schema.const !== undefined) {
|
|
75
|
+
return JSON.stringify(schema.const);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (Array.isArray(schema.enum)) {
|
|
79
|
+
if (options.inlineEnumAsUnion) {
|
|
80
|
+
return unionTypes(
|
|
81
|
+
this.enumLiteralValues(schema).map((value) => JSON.stringify(value)),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return pascalCase(contextName);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (schema.oneOf || schema.anyOf) {
|
|
89
|
+
const variants = schema.oneOf ?? schema.anyOf;
|
|
90
|
+
return unionTypes(
|
|
91
|
+
variants.map((item, index) =>
|
|
92
|
+
this.resolve(item, `${contextName}${index + 1}`, options),
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (schema.allOf) {
|
|
98
|
+
return schema.allOf
|
|
99
|
+
.map((item, index) =>
|
|
100
|
+
this.resolve(item, `${contextName}${index + 1}`, options),
|
|
101
|
+
)
|
|
102
|
+
.join(" & ");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const schemaType = Array.isArray(schema.type)
|
|
106
|
+
? schema.type.find((item) => item !== "null")
|
|
107
|
+
: schema.type;
|
|
108
|
+
|
|
109
|
+
switch (schemaType) {
|
|
110
|
+
case "integer":
|
|
111
|
+
case "number":
|
|
112
|
+
return "number";
|
|
113
|
+
case "boolean":
|
|
114
|
+
return "boolean";
|
|
115
|
+
case "string":
|
|
116
|
+
if (schema.format === "binary") {
|
|
117
|
+
return options.binaryAsBlob ? "Blob" : "File";
|
|
118
|
+
}
|
|
119
|
+
return "string";
|
|
120
|
+
case "array": {
|
|
121
|
+
const itemType = this.resolve(
|
|
122
|
+
schema.items ?? {},
|
|
123
|
+
`${contextName}Item`,
|
|
124
|
+
options,
|
|
125
|
+
);
|
|
126
|
+
return /^[A-Za-z_$][\w$]*(?:<.*>)?$/.test(itemType) ||
|
|
127
|
+
itemType.endsWith("[]")
|
|
128
|
+
? `${itemType}[]`
|
|
129
|
+
: `(${itemType})[]`;
|
|
130
|
+
}
|
|
131
|
+
case "object":
|
|
132
|
+
default:
|
|
133
|
+
if (schema.properties) {
|
|
134
|
+
return this.createInlineObjectType(schema, contextName, options);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (schema.additionalProperties) {
|
|
138
|
+
const valueType =
|
|
139
|
+
schema.additionalProperties === true
|
|
140
|
+
? "any"
|
|
141
|
+
: this.resolve(
|
|
142
|
+
schema.additionalProperties,
|
|
143
|
+
`${contextName}Value`,
|
|
144
|
+
options,
|
|
145
|
+
);
|
|
146
|
+
return `Record<string, ${valueType}>`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return schemaType === "object" ? "Record<string, any>" : "any";
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
createInlineObjectType(schema, contextName, options = {}) {
|
|
154
|
+
const name = pascalCase(contextName);
|
|
155
|
+
|
|
156
|
+
if (!this.inlineTypes.has(name)) {
|
|
157
|
+
this.inlineTypes.set(name, schema);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return name;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
createInterface(name, schema) {
|
|
164
|
+
const required = new Set(schema.required ?? []);
|
|
165
|
+
const lines = [`export interface ${name} {`];
|
|
166
|
+
|
|
167
|
+
for (const [propertyName, propertySchema] of Object.entries(
|
|
168
|
+
schema.properties ?? {},
|
|
169
|
+
)) {
|
|
170
|
+
// Required names must still be checked against the original OpenAPI name.
|
|
171
|
+
const propertyRequired = required.has(propertyName);
|
|
172
|
+
const optionalToken = propertyRequired ? "" : "?";
|
|
173
|
+
|
|
174
|
+
const propertyType = this.resolve(
|
|
175
|
+
propertySchema,
|
|
176
|
+
`${name}${pascalCase(propertyName)}`,
|
|
177
|
+
{ inlineEnumAsUnion: true },
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
const resolvedSchema = dereference(this.openApi, propertySchema);
|
|
181
|
+
const typescriptPropertyName = camelCase(propertyName);
|
|
182
|
+
|
|
183
|
+
lines.push(
|
|
184
|
+
jsDocFromSchema(resolvedSchema, " ") +
|
|
185
|
+
` ${propertyKey(typescriptPropertyName)}${optionalToken}: ${propertyType};`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (schema.additionalProperties) {
|
|
190
|
+
const valueType =
|
|
191
|
+
schema.additionalProperties === true
|
|
192
|
+
? "any"
|
|
193
|
+
: this.resolve(schema.additionalProperties, `${name}Value`, {
|
|
194
|
+
inlineEnumAsUnion: true,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
lines.push(` [key: string]: ${valueType};`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
lines.push("}");
|
|
201
|
+
return lines.join("\n");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
createEnum(name, schema) {
|
|
205
|
+
const values = schema.enum ?? [];
|
|
206
|
+
|
|
207
|
+
if (this.options.generateUnionEnums) {
|
|
208
|
+
return `export type ${name} = ${unionTypes(this.enumLiteralValues(schema).map((value) => JSON.stringify(value)))};`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const lines = [`export const ${name} = {`];
|
|
212
|
+
|
|
213
|
+
for (const [index, value] of values.entries()) {
|
|
214
|
+
const memberName = this.enumMemberName(schema, value, index);
|
|
215
|
+
const enumValue = this.enumRuntimeValue(schema, value, index);
|
|
216
|
+
lines.push(` ${memberName}: ${JSON.stringify(enumValue)},`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
lines.push("} as const;");
|
|
220
|
+
lines.push(`export type ${name} = (typeof ${name})[keyof typeof ${name}];`);
|
|
221
|
+
return lines.join("\n");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
enumMetadataNames(schema) {
|
|
225
|
+
const enumNames =
|
|
226
|
+
schema?.["x-enumNames"] ??
|
|
227
|
+
schema?.["x-enum-varnames"] ??
|
|
228
|
+
schema?.["x-enumVarnames"];
|
|
229
|
+
|
|
230
|
+
return Array.isArray(enumNames) ? enumNames : [];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
enumLiteralValues(schema) {
|
|
234
|
+
const values = schema.enum ?? [];
|
|
235
|
+
const enumNames = this.enumMetadataNames(schema);
|
|
236
|
+
|
|
237
|
+
if (this.options.enumNamesAsValues && enumNames.length > 0) {
|
|
238
|
+
return values.map((value, index) => enumNames[index] ?? value);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return values;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
enumRuntimeValue(schema, value, index) {
|
|
245
|
+
const enumNames = this.enumMetadataNames(schema);
|
|
246
|
+
|
|
247
|
+
if (this.options.enumNamesAsValues && enumNames.length > 0) {
|
|
248
|
+
return enumNames[index] ?? value;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return value;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
enumMemberName(schema, value, index) {
|
|
255
|
+
const enumNames = this.enumMetadataNames(schema);
|
|
256
|
+
const rawName = enumNames[index] ?? value;
|
|
257
|
+
return pascalCase(String(rawName), "Value").replace(/^[0-9]/, "_$&");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function shouldUseInterface(schema) {
|
|
262
|
+
return Boolean(
|
|
263
|
+
schema?.properties ||
|
|
264
|
+
schema?.additionalProperties ||
|
|
265
|
+
schema?.type === "object",
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function generateDataContracts(openApi, operations, options = {}) {
|
|
270
|
+
const resolver = new TypeResolver(openApi, options);
|
|
271
|
+
const declarations = [];
|
|
272
|
+
const schemas = openApi.components?.schemas ?? {};
|
|
273
|
+
|
|
274
|
+
const schemaEntries = Object.entries(schemas).sort(
|
|
275
|
+
([aName, aSchema], [bName, bSchema]) => {
|
|
276
|
+
const aIsEnum = Array.isArray(aSchema.enum);
|
|
277
|
+
const bIsEnum = Array.isArray(bSchema.enum);
|
|
278
|
+
if (aIsEnum !== bIsEnum) return aIsEnum ? -1 : 1;
|
|
279
|
+
return aName.localeCompare(bName);
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
for (const [name, schema] of schemaEntries) {
|
|
284
|
+
if (Array.isArray(schema.enum)) {
|
|
285
|
+
declarations.push(resolver.createEnum(name, schema));
|
|
286
|
+
} else if (shouldUseInterface(schema)) {
|
|
287
|
+
declarations.push(resolver.createInterface(name, schema));
|
|
288
|
+
} else {
|
|
289
|
+
declarations.push(
|
|
290
|
+
`export type ${name} = ${resolver.resolve(schema, name, { inlineEnumAsUnion: true })};`,
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
for (const operationInfo of operations) {
|
|
296
|
+
const operationId = operationInfo.operation.operationId;
|
|
297
|
+
if (!operationId) continue;
|
|
298
|
+
|
|
299
|
+
const parameterProperties = operationInfo.parameters.map((parameter) => ({
|
|
300
|
+
name: parameter.name,
|
|
301
|
+
schema: parameter.schema ?? {},
|
|
302
|
+
required: Boolean(parameter.required),
|
|
303
|
+
}));
|
|
304
|
+
|
|
305
|
+
if (parameterProperties.length > 0) {
|
|
306
|
+
declarations.push(
|
|
307
|
+
createParamsInterface(
|
|
308
|
+
openApi,
|
|
309
|
+
resolver,
|
|
310
|
+
`${operationId}Params`,
|
|
311
|
+
parameterProperties,
|
|
312
|
+
),
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const bodyContent = getRequestBodyContent(
|
|
317
|
+
operationInfo.operation.requestBody,
|
|
318
|
+
);
|
|
319
|
+
const bodySchema = bodyContent?.mediaType?.schema;
|
|
320
|
+
|
|
321
|
+
if (
|
|
322
|
+
bodySchema &&
|
|
323
|
+
!bodySchema.$ref &&
|
|
324
|
+
(bodyContent.contentType === "multipart/form-data" ||
|
|
325
|
+
shouldUseInterface(bodySchema))
|
|
326
|
+
) {
|
|
327
|
+
const payloadName = `${operationId}Payload`;
|
|
328
|
+
if (!schemas[payloadName]) {
|
|
329
|
+
declarations.push(resolver.createInterface(payloadName, bodySchema));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const successResponse = getSuccessResponse(
|
|
334
|
+
operationInfo.operation,
|
|
335
|
+
options.defaultResponseAsSuccess,
|
|
336
|
+
);
|
|
337
|
+
const responseContent = getResponseContent(successResponse?.response);
|
|
338
|
+
const responseSchema = responseContent?.mediaType?.schema;
|
|
339
|
+
|
|
340
|
+
if (responseSchema && !responseSchema.$ref) {
|
|
341
|
+
resolver.resolve(responseSchema, `${operationId}Response`, {
|
|
342
|
+
binaryAsBlob:
|
|
343
|
+
responseContent?.contentType === "application/octet-stream",
|
|
344
|
+
inlineEnumAsUnion: true,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (const [name, schema] of resolver.inlineTypes.entries()) {
|
|
350
|
+
if (!schemas[name]) {
|
|
351
|
+
declarations.push(resolver.createInterface(name, schema));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return `${generatedFileHeader()}\n\n${declarations.join("\n\n")}\n`;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function createParamsInterface(openApi, resolver, name, parameters) {
|
|
359
|
+
const required = new Set(
|
|
360
|
+
parameters
|
|
361
|
+
.filter((parameter) => parameter.required)
|
|
362
|
+
.map((parameter) => parameter.name),
|
|
363
|
+
);
|
|
364
|
+
const lines = [`export interface ${name} {`];
|
|
365
|
+
|
|
366
|
+
for (const parameter of parameters) {
|
|
367
|
+
const parameterSchema = dereference(openApi, parameter.schema);
|
|
368
|
+
const optionalToken = required.has(parameter.name) ? "" : "?";
|
|
369
|
+
const parameterType = resolver.resolve(
|
|
370
|
+
parameter.schema,
|
|
371
|
+
`${name}${pascalCase(parameter.name)}`,
|
|
372
|
+
{ inlineEnumAsUnion: true },
|
|
373
|
+
);
|
|
374
|
+
lines.push(
|
|
375
|
+
jsDocFromSchema(parameterSchema, " ") +
|
|
376
|
+
` ${propertyKey(parameter.name)}${optionalToken}: ${parameterType};`,
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
lines.push("}");
|
|
381
|
+
return lines.join("\n");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export function getOperationTypes(openApi, operationInfo, options = {}) {
|
|
385
|
+
const resolver = new TypeResolver(openApi, options);
|
|
386
|
+
const operationId = operationInfo.operation.operationId;
|
|
387
|
+
const parameters = operationInfo.parameters ?? [];
|
|
388
|
+
const pathParams = parameters.filter((parameter) => parameter.in === "path");
|
|
389
|
+
const queryParams = parameters.filter(
|
|
390
|
+
(parameter) => parameter.in === "query",
|
|
391
|
+
);
|
|
392
|
+
const requestBodyContent = getRequestBodyContent(
|
|
393
|
+
operationInfo.operation.requestBody,
|
|
394
|
+
);
|
|
395
|
+
const requestBodySchema = requestBodyContent?.mediaType?.schema;
|
|
396
|
+
const successResponse = getSuccessResponse(
|
|
397
|
+
operationInfo.operation,
|
|
398
|
+
options.defaultResponseAsSuccess,
|
|
399
|
+
);
|
|
400
|
+
const responseContent = getResponseContent(successResponse?.response);
|
|
401
|
+
const responseSchema = responseContent?.mediaType?.schema;
|
|
402
|
+
|
|
403
|
+
let bodyType;
|
|
404
|
+
if (requestBodySchema) {
|
|
405
|
+
if (requestBodySchema.$ref) {
|
|
406
|
+
bodyType = resolver.resolve(requestBodySchema, `${operationId}Payload`);
|
|
407
|
+
} else if (
|
|
408
|
+
requestBodyContent?.contentType === "multipart/form-data" ||
|
|
409
|
+
shouldUseInterface(requestBodySchema)
|
|
410
|
+
) {
|
|
411
|
+
bodyType = `${operationId}Payload`;
|
|
412
|
+
} else {
|
|
413
|
+
bodyType = resolver.resolve(requestBodySchema, `${operationId}Payload`, {
|
|
414
|
+
inlineEnumAsUnion: true,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
let responseType = "void";
|
|
420
|
+
if (responseSchema) {
|
|
421
|
+
responseType = resolver.resolve(responseSchema, `${operationId}Response`, {
|
|
422
|
+
binaryAsBlob: responseContent?.contentType === "application/octet-stream",
|
|
423
|
+
inlineEnumAsUnion: true,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return {
|
|
428
|
+
operationId,
|
|
429
|
+
methodName: operationId
|
|
430
|
+
? operationId.charAt(0).toLowerCase() + operationId.slice(1)
|
|
431
|
+
: undefined,
|
|
432
|
+
paramsTypeName: parameters.length > 0 ? `${operationId}Params` : undefined,
|
|
433
|
+
bodyType,
|
|
434
|
+
responseType,
|
|
435
|
+
contentType: requestBodyContent?.contentType,
|
|
436
|
+
responseContentType: responseContent?.contentType,
|
|
437
|
+
hasPathParams: pathParams.length > 0,
|
|
438
|
+
hasQueryParams: queryParams.length > 0,
|
|
439
|
+
pathParams,
|
|
440
|
+
queryParams,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export function generatedFileHeader() {
|
|
445
|
+
return `/* eslint-disable */
|
|
446
|
+
/* tslint:disable */
|
|
447
|
+
/*
|
|
448
|
+
* --------------------------------------------------------------------------------
|
|
449
|
+
* ## THIS FILE WAS GENERATED BY typedapi-client-helpers ##
|
|
450
|
+
* ## ##
|
|
451
|
+
* ## AUTHOR: Stef Buurman ##
|
|
452
|
+
* ## SOURCE: https://github.com/Stef-Buurman/TypedApi/tree/main/npm/typed-api-client ##
|
|
453
|
+
* --------------------------------------------------------------------------------
|
|
454
|
+
*/`;
|
|
455
|
+
}
|
package/bin/typedapi-generate.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ImportResult, UploadProductFilePayload, UploadSupplierFilePayload } from "./data-contracts";
|
|
2
|
-
import { HttpClient } from "./http-client";
|
|
3
|
-
import { RequestParams } from "./http-client";
|
|
4
|
-
export declare class Import<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
|
5
|
-
/**
|
|
6
|
-
* No description
|
|
7
|
-
*
|
|
8
|
-
* @tags Import
|
|
9
|
-
* @name UploadProductFile
|
|
10
|
-
* @request POST:/api/import/products
|
|
11
|
-
*/
|
|
12
|
-
uploadProductFile: (data: UploadProductFilePayload, params?: RequestParams) => Promise<import("./http-client").HttpResponse<ImportResult, any>>;
|
|
13
|
-
/**
|
|
14
|
-
* No description
|
|
15
|
-
*
|
|
16
|
-
* @tags Import
|
|
17
|
-
* @name UploadSupplierFile
|
|
18
|
-
* @request POST:/api/import/suppliers
|
|
19
|
-
*/
|
|
20
|
-
uploadSupplierFile: (data: UploadSupplierFilePayload, params?: RequestParams) => Promise<import("./http-client").HttpResponse<ImportResult, any>>;
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=Import.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Import.d.ts","sourceRoot":"","sources":["../../../src/api/generated/Import.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,yBAAyB,EAAG,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAe,UAAU,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,qBAAa,MAAM,CACjB,gBAAgB,GAAG,OAAO,CAC1B,SAAQ,UAAU,CAAC,gBAAgB,CAAC;IACpC;;;;;;OAMG;IACH,iBAAiB,GACf,MAAM,wBAAwB,EAC9B,SAAQ,aAAkB,sEASvB;IACL;;;;;;OAMG;IACH,kBAAkB,GAChB,MAAM,yBAAyB,EAC/B,SAAQ,aAAkB,sEASvB;CACN"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
/* tslint:disable */
|
|
3
|
-
// @ts-nocheck
|
|
4
|
-
/*
|
|
5
|
-
* ---------------------------------------------------------------
|
|
6
|
-
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
|
7
|
-
* ## ##
|
|
8
|
-
* ## AUTHOR: acacode ##
|
|
9
|
-
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
|
10
|
-
* ---------------------------------------------------------------
|
|
11
|
-
*/
|
|
12
|
-
import { ContentType, HttpClient } from "./http-client";
|
|
13
|
-
export class Import extends HttpClient {
|
|
14
|
-
constructor() {
|
|
15
|
-
super(...arguments);
|
|
16
|
-
/**
|
|
17
|
-
* No description
|
|
18
|
-
*
|
|
19
|
-
* @tags Import
|
|
20
|
-
* @name UploadProductFile
|
|
21
|
-
* @request POST:/api/import/products
|
|
22
|
-
*/
|
|
23
|
-
this.uploadProductFile = (data, params = {}) => this.request({
|
|
24
|
-
path: `/api/import/products`,
|
|
25
|
-
method: "POST",
|
|
26
|
-
body: data,
|
|
27
|
-
type: ContentType.FormData,
|
|
28
|
-
format: "json",
|
|
29
|
-
...params,
|
|
30
|
-
});
|
|
31
|
-
/**
|
|
32
|
-
* No description
|
|
33
|
-
*
|
|
34
|
-
* @tags Import
|
|
35
|
-
* @name UploadSupplierFile
|
|
36
|
-
* @request POST:/api/import/suppliers
|
|
37
|
-
*/
|
|
38
|
-
this.uploadSupplierFile = (data, params = {}) => this.request({
|
|
39
|
-
path: `/api/import/suppliers`,
|
|
40
|
-
method: "POST",
|
|
41
|
-
body: data,
|
|
42
|
-
type: ContentType.FormData,
|
|
43
|
-
format: "json",
|
|
44
|
-
...params,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=Import.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Import.js","sourceRoot":"","sources":["../../../src/api/generated/Import.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB,cAAc;AACd;;;;;;;GAOG;AAGH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGxD,MAAM,OAAO,MAEX,SAAQ,UAA4B;IAFtC;;QAGE;;;;;;WAMG;QACH,sBAAiB,GAAG,CAClB,IAA8B,EAC9B,SAAwB,EAAE,EAC1B,EAAE,CACF,IAAI,CAAC,OAAO,CAAoB;YAC9B,IAAI,EAAE,sBAAsB;YAC5B,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,WAAW,CAAC,QAAQ;YAC1B,MAAM,EAAE,MAAM;YACd,GAAG,MAAM;SACV,CAAC,CAAC;QACL;;;;;;WAMG;QACH,uBAAkB,GAAG,CACnB,IAA+B,EAC/B,SAAwB,EAAE,EAC1B,EAAE,CACF,IAAI,CAAC,OAAO,CAAoB;YAC9B,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,WAAW,CAAC,QAAQ;YAC1B,MAAM,EAAE,MAAM;YACd,GAAG,MAAM;SACV,CAAC,CAAC;IACP,CAAC;CAAA"}
|