openapi-sync 1.0.25 → 2.0.1
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/db.json +1 -1
- package/dist/Openapi-sync/components/helpers.js +40 -124
- package/dist/Openapi-sync/index.js +528 -57
- package/dist/Openapi-sync/state.js +3 -0
- package/dist/Openapi-sync/test.js +709 -0
- package/dist/index.js +15 -2
- package/package.json +3 -1
- package/types.ts +124 -0
- /package/dist/{Openapi-sync/types.js → types.js} +0 -0
|
@@ -14,12 +14,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const fs_1 = __importDefault(require("fs"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
17
18
|
const helpers_1 = require("./components/helpers");
|
|
18
|
-
const
|
|
19
|
+
const lodash_2 = require("lodash");
|
|
19
20
|
const axios_1 = __importDefault(require("axios"));
|
|
20
21
|
const axios_retry_1 = __importDefault(require("axios-retry"));
|
|
21
22
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
22
23
|
const state_1 = require("./state");
|
|
24
|
+
const curl_generator_1 = require("curl-generator");
|
|
23
25
|
const rootUsingCwd = process.cwd();
|
|
24
26
|
let fetchTimeout = {};
|
|
25
27
|
// Create an Axios instance
|
|
@@ -37,7 +39,8 @@ const apiClient = axios_1.default.create({
|
|
|
37
39
|
return retryCount * 1000; // Exponential back-off: 1s, 2s, 3s, etc.
|
|
38
40
|
},
|
|
39
41
|
});
|
|
40
|
-
const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
+
const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
var _a, _b, _c, _d, _e;
|
|
41
44
|
const specResponse = yield apiClient.get(apiUrl);
|
|
42
45
|
const redoclyConfig = yield (0, openapi_core_1.createConfig)({
|
|
43
46
|
extends: ["minimal"],
|
|
@@ -49,10 +52,261 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
49
52
|
source,
|
|
50
53
|
config: redoclyConfig,
|
|
51
54
|
});
|
|
52
|
-
|
|
53
|
-
const config = require(path_1.default.join(rootUsingCwd, "openapi.sync.json"));
|
|
54
|
-
const folderPath = path_1.default.join(config.folder || "", apiName);
|
|
55
|
+
const folderPath = path_1.default.join((config === null || config === void 0 ? void 0 : config.folder) || "", apiName);
|
|
55
56
|
const spec = lintResults.bundle.parsed;
|
|
57
|
+
const serverUrl = (_a = spec.servers[(config === null || config === void 0 ? void 0 : config.server) || 0]) === null || _a === void 0 ? void 0 : _a.url;
|
|
58
|
+
const typePrefix = typeof ((_c = (_b = config === null || config === void 0 ? void 0 : config.types) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.prefix) === "string"
|
|
59
|
+
? config === null || config === void 0 ? void 0 : config.types.name.prefix
|
|
60
|
+
: "I";
|
|
61
|
+
const endpointPrefix = typeof ((_e = (_d = config === null || config === void 0 ? void 0 : config.endpoints) === null || _d === void 0 ? void 0 : _d.name) === null || _e === void 0 ? void 0 : _e.prefix) === "string"
|
|
62
|
+
? config === null || config === void 0 ? void 0 : config.endpoints.name.prefix
|
|
63
|
+
: "";
|
|
64
|
+
const getSharedComponentName = (componentName, componentType) => {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
if ((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.format) {
|
|
67
|
+
const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("shared", {
|
|
68
|
+
name: componentName,
|
|
69
|
+
});
|
|
70
|
+
if (formattedName)
|
|
71
|
+
return `${typePrefix}${formattedName}`;
|
|
72
|
+
}
|
|
73
|
+
return `${typePrefix}${(0, helpers_1.capitalize)(componentName)}`;
|
|
74
|
+
};
|
|
75
|
+
const parseSchemaToType = (apiDoc, schema, name, isRequired, options, indentLevel = 0) => {
|
|
76
|
+
let overrideName = "";
|
|
77
|
+
let componentName = "";
|
|
78
|
+
let type = "";
|
|
79
|
+
if (schema) {
|
|
80
|
+
if (schema.$ref) {
|
|
81
|
+
if (schema.$ref[0] === "#") {
|
|
82
|
+
let pathToComponentParts = (schema.$ref || "").split("/");
|
|
83
|
+
pathToComponentParts.shift();
|
|
84
|
+
const partsClone = [...pathToComponentParts];
|
|
85
|
+
partsClone.pop();
|
|
86
|
+
const pathToComponent = pathToComponentParts;
|
|
87
|
+
const component = lodash_1.default.get(apiDoc, pathToComponent, null);
|
|
88
|
+
if (component) {
|
|
89
|
+
if (component === null || component === void 0 ? void 0 : component.name) {
|
|
90
|
+
overrideName = component.name;
|
|
91
|
+
}
|
|
92
|
+
componentName =
|
|
93
|
+
pathToComponentParts[pathToComponentParts.length - 1];
|
|
94
|
+
let name = getSharedComponentName(componentName);
|
|
95
|
+
if (name.includes(".")) {
|
|
96
|
+
const nameParts = name.split(".");
|
|
97
|
+
name = nameParts
|
|
98
|
+
.map((part, i) => {
|
|
99
|
+
if (i === 0) {
|
|
100
|
+
return part;
|
|
101
|
+
}
|
|
102
|
+
return `["${part}"]`;
|
|
103
|
+
})
|
|
104
|
+
.join("");
|
|
105
|
+
}
|
|
106
|
+
// Reference component via import instead of parsing
|
|
107
|
+
type += `${(options === null || options === void 0 ? void 0 : options.noSharedImport) ? "" : "Shared."}${name}`;
|
|
108
|
+
// type += `${parseSchemaToType(apiDoc, component, "", isRequired)}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
type += "";
|
|
113
|
+
//TODO $ref is a uri - use axios to fetch doc
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (schema.anyOf) {
|
|
117
|
+
type += `(${schema.anyOf
|
|
118
|
+
.map((v) => parseSchemaToType(apiDoc, v, "", isRequired, options))
|
|
119
|
+
.join("|")})`;
|
|
120
|
+
}
|
|
121
|
+
else if (schema.oneOf) {
|
|
122
|
+
type += `(${schema.oneOf
|
|
123
|
+
.map((v) => parseSchemaToType(apiDoc, v, "", isRequired, options))
|
|
124
|
+
.join("|")})`;
|
|
125
|
+
}
|
|
126
|
+
else if (schema.allOf) {
|
|
127
|
+
type += `(${schema.allOf
|
|
128
|
+
.map((v) => parseSchemaToType(apiDoc, v, "", isRequired, options))
|
|
129
|
+
.join("&")})`;
|
|
130
|
+
}
|
|
131
|
+
else if (schema.items) {
|
|
132
|
+
type += `${parseSchemaToType(apiDoc, schema.items, "", false, options)}[]`;
|
|
133
|
+
}
|
|
134
|
+
else if (schema.properties) {
|
|
135
|
+
//parse object key one at a time
|
|
136
|
+
const objKeys = Object.keys(schema.properties);
|
|
137
|
+
const requiredKeys = schema.required || [];
|
|
138
|
+
let typeCnt = "";
|
|
139
|
+
objKeys.forEach((key) => {
|
|
140
|
+
var _a, _b, _c, _d, _e, _f;
|
|
141
|
+
let doc = "";
|
|
142
|
+
if (!((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.doc) === null || _b === void 0 ? void 0 : _b.disable) &&
|
|
143
|
+
((_d = (_c = schema.properties) === null || _c === void 0 ? void 0 : _c[key]) === null || _d === void 0 ? void 0 : _d.description)) {
|
|
144
|
+
doc =
|
|
145
|
+
" * " +
|
|
146
|
+
((_e = schema.properties) === null || _e === void 0 ? void 0 : _e[key].description.split("\n").filter((line) => line.trim() !== "").join(` \n *${" ".repeat(1)}`));
|
|
147
|
+
}
|
|
148
|
+
typeCnt +=
|
|
149
|
+
(doc ? `/**\n${doc}\n */\n` : "") +
|
|
150
|
+
`${parseSchemaToType(apiDoc, (_f = schema.properties) === null || _f === void 0 ? void 0 : _f[key], key, requiredKeys.includes(key), options, indentLevel + 1)}`;
|
|
151
|
+
});
|
|
152
|
+
if (typeCnt.length > 0) {
|
|
153
|
+
type += `{\n${" ".repeat(indentLevel)}${typeCnt}${" ".repeat(indentLevel)}}`;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
type += "{[k: string]: any}";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (schema.enum && schema.enum.length > 0) {
|
|
160
|
+
if (schema.enum.length > 1)
|
|
161
|
+
type += "(";
|
|
162
|
+
schema.enum.forEach((v) => {
|
|
163
|
+
let val = JSON.stringify(v);
|
|
164
|
+
if (val)
|
|
165
|
+
type += `|${val}`;
|
|
166
|
+
});
|
|
167
|
+
if (schema.enum.length > 1)
|
|
168
|
+
type += ")";
|
|
169
|
+
}
|
|
170
|
+
else if (schema.type) {
|
|
171
|
+
if (["string", "integer", "number", "array", "boolean"].includes(schema.type)) {
|
|
172
|
+
if (["integer", "number"].includes(schema.type)) {
|
|
173
|
+
type += `number`;
|
|
174
|
+
}
|
|
175
|
+
else if (schema.type === "array") {
|
|
176
|
+
//Since we would have already parsed the arrays keys above "schema.items" if it exists
|
|
177
|
+
type += "any[]";
|
|
178
|
+
/* if (schema.items) {
|
|
179
|
+
type += `${parseSchemaToType(
|
|
180
|
+
apiDoc,
|
|
181
|
+
schema.items,
|
|
182
|
+
"",
|
|
183
|
+
false,
|
|
184
|
+
options
|
|
185
|
+
)}[]`;
|
|
186
|
+
} else {
|
|
187
|
+
type += "any[]";
|
|
188
|
+
} */
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
type += schema.type;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (schema.type === "object") {
|
|
195
|
+
//Since we would have already parsed the object keys above "schema.properties" if it exists
|
|
196
|
+
if (schema.additionalProperties) {
|
|
197
|
+
type += `{[k: string]: ${parseSchemaToType(apiDoc, schema.additionalProperties, "", true, options) || "any"}}`;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
type += "{[k: string]: any}";
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
//Default type to string if no schema provided
|
|
207
|
+
type = "string";
|
|
208
|
+
}
|
|
209
|
+
let _name = overrideName || name;
|
|
210
|
+
if ((options === null || options === void 0 ? void 0 : options.useComponentName) && !_name) {
|
|
211
|
+
_name = componentName;
|
|
212
|
+
}
|
|
213
|
+
let typeName = _name ? `\t"${_name}"${isRequired ? "" : "?"}: ` : "";
|
|
214
|
+
const nullable = (schema === null || schema === void 0 ? void 0 : schema.nullable) ? " | null" : "";
|
|
215
|
+
return type.length > 0
|
|
216
|
+
? `${typeName}${type}${nullable}${_name ? ";\n" : ""}`
|
|
217
|
+
: "";
|
|
218
|
+
};
|
|
219
|
+
const getSchemaExamples = (apiDoc, schema) => {
|
|
220
|
+
let overrideName = "";
|
|
221
|
+
let componentName = "";
|
|
222
|
+
let type = "";
|
|
223
|
+
if (schema) {
|
|
224
|
+
if (schema.$ref) {
|
|
225
|
+
if (schema.$ref[0] === "#") {
|
|
226
|
+
let pathToComponentParts = (schema.$ref || "").split("/");
|
|
227
|
+
pathToComponentParts.shift();
|
|
228
|
+
const pathToComponent = pathToComponentParts;
|
|
229
|
+
const component = lodash_1.default.get(apiDoc, pathToComponent, null);
|
|
230
|
+
if (component) {
|
|
231
|
+
if (component === null || component === void 0 ? void 0 : component.name) {
|
|
232
|
+
overrideName = component.name;
|
|
233
|
+
}
|
|
234
|
+
componentName =
|
|
235
|
+
pathToComponentParts[pathToComponentParts.length - 1];
|
|
236
|
+
type += getSchemaExamples(apiDoc, component);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
type += "";
|
|
241
|
+
//TODO $ref is a uri - use axios to fetch doc
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else if (schema.anyOf) {
|
|
245
|
+
type += getSchemaExamples(apiDoc, schema.anyOf[0]);
|
|
246
|
+
}
|
|
247
|
+
else if (schema.oneOf) {
|
|
248
|
+
type += getSchemaExamples(apiDoc, schema.oneOf[0]);
|
|
249
|
+
}
|
|
250
|
+
else if (schema.allOf) {
|
|
251
|
+
type += `{${schema.allOf
|
|
252
|
+
.map((v) => `...(${getSchemaExamples(apiDoc, v)})`)
|
|
253
|
+
.join(",")}}`;
|
|
254
|
+
}
|
|
255
|
+
else if (schema.items) {
|
|
256
|
+
type += `[${getSchemaExamples(apiDoc, schema.items)}]`;
|
|
257
|
+
}
|
|
258
|
+
else if (schema.properties) {
|
|
259
|
+
//parse object key one at a time
|
|
260
|
+
const objKeys = Object.keys(schema.properties);
|
|
261
|
+
const arr = objKeys.map((key) => {
|
|
262
|
+
var _a;
|
|
263
|
+
return ` "${key}": ${getSchemaExamples(apiDoc, (_a = schema.properties) === null || _a === void 0 ? void 0 : _a[key])}`;
|
|
264
|
+
});
|
|
265
|
+
let typeCnt = arr.join(",\n");
|
|
266
|
+
if (typeCnt.length > 0) {
|
|
267
|
+
type += `{\n${typeCnt}\n }`;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
type += "{}";
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else if (schema.enum && schema.enum.length > 0) {
|
|
274
|
+
if (schema.enum.length > 1)
|
|
275
|
+
type += schema.enum[0];
|
|
276
|
+
}
|
|
277
|
+
else if (schema.type) {
|
|
278
|
+
if (schema.example) {
|
|
279
|
+
type += JSON.stringify(schema.example);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
if (["string", "integer", "number", "array", "boolean"].includes(schema.type)) {
|
|
283
|
+
if (["integer", "number"].includes(schema.type)) {
|
|
284
|
+
type += `123`;
|
|
285
|
+
}
|
|
286
|
+
else if (schema.type === "array") {
|
|
287
|
+
//Since we would have already parsed the arrays keys above "schema.items" if it exists
|
|
288
|
+
type += "[]";
|
|
289
|
+
}
|
|
290
|
+
else if (schema.type === "boolean") {
|
|
291
|
+
type += `true`;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
type += `"${schema.type}"`;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else if (schema.type === "object") {
|
|
298
|
+
//Since we would have already parsed the object keys above "schema.properties" if it exists
|
|
299
|
+
type += "{}";
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
//Default type to string if no schema provided
|
|
306
|
+
type = "string";
|
|
307
|
+
}
|
|
308
|
+
return type;
|
|
309
|
+
};
|
|
56
310
|
// auto update only on dev
|
|
57
311
|
if (refetchInterval && !isNaN(refetchInterval) && refetchInterval > 0) {
|
|
58
312
|
if (!(process.env.NODE_ENV &&
|
|
@@ -61,12 +315,12 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
61
315
|
if (fetchTimeout[apiName])
|
|
62
316
|
clearTimeout(fetchTimeout[apiName]);
|
|
63
317
|
// set next request timeout
|
|
64
|
-
fetchTimeout[apiName] = setTimeout(() => OpenapiSync(apiUrl, apiName, refetchInterval), refetchInterval);
|
|
318
|
+
fetchTimeout[apiName] = setTimeout(() => OpenapiSync(apiUrl, apiName, config, refetchInterval), refetchInterval);
|
|
65
319
|
}
|
|
66
320
|
}
|
|
67
321
|
// compare new spec with old spec, continuing only if spec it different
|
|
68
322
|
const prevSpec = (0, state_1.getState)(apiName);
|
|
69
|
-
if ((0,
|
|
323
|
+
if ((0, lodash_2.isEqual)(prevSpec, spec))
|
|
70
324
|
return;
|
|
71
325
|
(0, state_1.setState)(apiName, spec);
|
|
72
326
|
let endpointsFileContent = "";
|
|
@@ -86,10 +340,12 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
86
340
|
].includes(key)) {
|
|
87
341
|
// Create components (shared) types
|
|
88
342
|
const components = spec.components[key];
|
|
343
|
+
const componentInterfaces = {};
|
|
344
|
+
const componentSchema = {};
|
|
89
345
|
const contentKeys = Object.keys(components);
|
|
90
346
|
// only need 1 schema so will us the first schema provided
|
|
91
347
|
contentKeys.forEach((contentKey) => {
|
|
92
|
-
var _a
|
|
348
|
+
var _a;
|
|
93
349
|
/* const schema = (() => {
|
|
94
350
|
switch (key) {
|
|
95
351
|
case "parameters":
|
|
@@ -101,15 +357,61 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
101
357
|
const schema = (((_a = components[contentKey]) === null || _a === void 0 ? void 0 : _a.schema)
|
|
102
358
|
? components[contentKey].schema
|
|
103
359
|
: components[contentKey]);
|
|
104
|
-
const typeCnt = `${
|
|
360
|
+
const typeCnt = `${parseSchemaToType(spec, schema, "", true, {
|
|
105
361
|
noSharedImport: true,
|
|
106
362
|
useComponentName: ["parameters"].includes(key),
|
|
107
363
|
})}`;
|
|
108
364
|
if (typeCnt) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
365
|
+
const parts = contentKey.split(".");
|
|
366
|
+
let currentLevel = componentInterfaces;
|
|
367
|
+
let currentSchemaLevel = componentSchema;
|
|
368
|
+
// Navigate or create the nested structure
|
|
369
|
+
for (let i = 0; i < parts.length; i++) {
|
|
370
|
+
const part = parts[i];
|
|
371
|
+
if (i < parts.length - 1) {
|
|
372
|
+
// If it's not the last part, create a nested object if it doesn't exist
|
|
373
|
+
if (!(part in currentLevel)) {
|
|
374
|
+
currentLevel[part] = {}; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentInterfaces
|
|
375
|
+
currentSchemaLevel[part] = {}; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentSchema
|
|
376
|
+
}
|
|
377
|
+
currentLevel = currentLevel[part]; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentInterfaces
|
|
378
|
+
currentSchemaLevel = currentSchemaLevel[part]; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentSchema
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
// This is the last part, assign the original schema value
|
|
382
|
+
currentLevel[part] = typeCnt; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentInterfaces
|
|
383
|
+
currentSchemaLevel[part] = schema; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentSchema
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
// Generate TypeScript interfaces for each component
|
|
389
|
+
Object.keys(componentInterfaces).forEach((key) => {
|
|
390
|
+
var _a, _b, _c, _d;
|
|
391
|
+
const name = getSharedComponentName(key);
|
|
392
|
+
const cnt = componentInterfaces[key];
|
|
393
|
+
let doc = "";
|
|
394
|
+
if (!((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.doc) === null || _b === void 0 ? void 0 : _b.disable) &&
|
|
395
|
+
key in components &&
|
|
396
|
+
(
|
|
397
|
+
//@ts-expect-error
|
|
398
|
+
(_c = components[key]) === null || _c === void 0 ? void 0 : _c.description)) {
|
|
399
|
+
doc =
|
|
400
|
+
" * " +
|
|
401
|
+
//@ts-expect-error
|
|
402
|
+
components[key].description
|
|
403
|
+
.split("\n")
|
|
404
|
+
.filter((line) => line.trim() !== "")
|
|
405
|
+
.join(` \n *${" ".repeat(1)}`);
|
|
112
406
|
}
|
|
407
|
+
sharedTypesFileContent[key] =
|
|
408
|
+
((_d = sharedTypesFileContent[key]) !== null && _d !== void 0 ? _d : "") +
|
|
409
|
+
(doc ? `/**\n${doc}\n */\n` : "") +
|
|
410
|
+
"export type " +
|
|
411
|
+
name +
|
|
412
|
+
" = " +
|
|
413
|
+
(typeof cnt === "string" ? cnt : (0, helpers_1.JSONStringify)(cnt)) +
|
|
414
|
+
";\n";
|
|
113
415
|
});
|
|
114
416
|
}
|
|
115
417
|
});
|
|
@@ -120,17 +422,17 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
120
422
|
const contentKeys = Object.keys(requestBody.content);
|
|
121
423
|
// only need 1 schema so will us the first schema provided
|
|
122
424
|
if (contentKeys[0] && requestBody.content[contentKeys[0]].schema) {
|
|
123
|
-
typeCnt += `${
|
|
425
|
+
typeCnt += `${parseSchemaToType(spec, requestBody.content[contentKeys[0]].schema, "")}`;
|
|
124
426
|
}
|
|
125
427
|
}
|
|
126
428
|
return typeCnt;
|
|
127
429
|
};
|
|
128
430
|
const treatEndpointUrl = (endpointUrl) => {
|
|
129
|
-
var _a, _b;
|
|
431
|
+
var _a, _b, _c, _d, _e;
|
|
130
432
|
if (((_b = (_a = config === null || config === void 0 ? void 0 : config.endpoints) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.replaceWords) &&
|
|
131
|
-
Array.isArray(config.endpoints.value.replaceWords)) {
|
|
433
|
+
Array.isArray(config === null || config === void 0 ? void 0 : config.endpoints.value.replaceWords)) {
|
|
132
434
|
let newEndpointUrl = endpointUrl;
|
|
133
|
-
config.endpoints.value.replaceWords.forEach((replaceWord, indx) => {
|
|
435
|
+
(_e = (_d = (_c = config === null || config === void 0 ? void 0 : config.endpoints) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.replaceWords) === null || _e === void 0 ? void 0 : _e.forEach((replaceWord, indx) => {
|
|
134
436
|
const regexp = new RegExp(replaceWord.replace, "g");
|
|
135
437
|
newEndpointUrl = newEndpointUrl.replace(regexp, replaceWord.with || "");
|
|
136
438
|
});
|
|
@@ -143,29 +445,31 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
143
445
|
Object.keys(spec.paths || {}).forEach((endpointPath) => {
|
|
144
446
|
const endpointSpec = spec.paths[endpointPath];
|
|
145
447
|
const endpointMethods = Object.keys(endpointSpec);
|
|
146
|
-
endpointMethods.forEach((
|
|
147
|
-
var _a, _b, _c, _d, _e, _f;
|
|
448
|
+
endpointMethods.forEach((_method) => {
|
|
449
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
450
|
+
const method = _method;
|
|
148
451
|
const endpoint = (0, helpers_1.getEndpointDetails)(endpointPath, method);
|
|
149
|
-
const endpointUrlTxt =
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
452
|
+
const endpointUrlTxt = (((_b = (_a = config === null || config === void 0 ? void 0 : config.endpoints) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.includeServer) ? serverUrl : "") +
|
|
453
|
+
endpoint.pathParts
|
|
454
|
+
.map((part) => {
|
|
455
|
+
// check if part is a variable
|
|
456
|
+
if (part[0] === "{" && part[part.length - 1] === "}") {
|
|
457
|
+
const s = part.replace(/{/, "").replace(/}/, "");
|
|
458
|
+
part = `\${${s}}`;
|
|
459
|
+
}
|
|
460
|
+
//api/<userId>
|
|
461
|
+
else if (part[0] === "<" && part[part.length - 1] === ">") {
|
|
462
|
+
const s = part.replace(/</, "").replace(/>/, "");
|
|
463
|
+
part = `\${${s}}`;
|
|
464
|
+
}
|
|
465
|
+
//api/:userId
|
|
466
|
+
else if (part[0] === ":") {
|
|
467
|
+
const s = part.replace(/:/, "");
|
|
468
|
+
part = `\${${s}}`;
|
|
469
|
+
}
|
|
470
|
+
return part;
|
|
471
|
+
})
|
|
472
|
+
.join("/");
|
|
169
473
|
let endpointUrl = `"${endpointUrlTxt}"`;
|
|
170
474
|
if (endpoint.variables.length > 0) {
|
|
171
475
|
const params = endpoint.variables.map((v) => `${v}:string`).join(",");
|
|
@@ -173,41 +477,208 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
|
|
|
173
477
|
}
|
|
174
478
|
//treat endpoint url
|
|
175
479
|
endpointUrl = treatEndpointUrl(endpointUrl);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
480
|
+
const eSpec = endpointSpec[method];
|
|
481
|
+
let name = `${endpoint.name}`;
|
|
482
|
+
if ((_d = (_c = config === null || config === void 0 ? void 0 : config.endpoints) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.format) {
|
|
483
|
+
const formattedName = config === null || config === void 0 ? void 0 : config.endpoints.name.format({
|
|
484
|
+
method,
|
|
485
|
+
path: endpointPath,
|
|
486
|
+
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
487
|
+
});
|
|
488
|
+
if (formattedName)
|
|
489
|
+
name = formattedName;
|
|
490
|
+
}
|
|
491
|
+
let queryTypeCnt = "";
|
|
492
|
+
if (eSpec === null || eSpec === void 0 ? void 0 : eSpec.parameters) {
|
|
180
493
|
// create query parameters types
|
|
181
|
-
const parameters =
|
|
182
|
-
let typeCnt = "";
|
|
494
|
+
const parameters = eSpec === null || eSpec === void 0 ? void 0 : eSpec.parameters;
|
|
183
495
|
parameters.forEach((param, i) => {
|
|
184
496
|
if (param.$ref || (param.in === "query" && param.name)) {
|
|
185
|
-
|
|
497
|
+
queryTypeCnt += `${parseSchemaToType(spec, param.$ref ? param : param.schema, param.name || "", param.required)}`;
|
|
186
498
|
}
|
|
187
499
|
});
|
|
188
|
-
if (
|
|
189
|
-
|
|
500
|
+
if (queryTypeCnt) {
|
|
501
|
+
queryTypeCnt = `{\n${queryTypeCnt}}`;
|
|
502
|
+
let name = `${endpoint.name}Query`;
|
|
503
|
+
if ((_f = (_e = config === null || config === void 0 ? void 0 : config.types) === null || _e === void 0 ? void 0 : _e.name) === null || _f === void 0 ? void 0 : _f.format) {
|
|
504
|
+
const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("endpoint", {
|
|
505
|
+
code: "",
|
|
506
|
+
type: "query",
|
|
507
|
+
method,
|
|
508
|
+
path: endpointPath,
|
|
509
|
+
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
510
|
+
});
|
|
511
|
+
if (formattedName)
|
|
512
|
+
name = formattedName;
|
|
513
|
+
}
|
|
514
|
+
typesFileContent += `export type ${typePrefix}${name} = ${queryTypeCnt};\n`;
|
|
190
515
|
}
|
|
191
516
|
}
|
|
192
|
-
|
|
517
|
+
const requestBody = eSpec === null || eSpec === void 0 ? void 0 : eSpec.requestBody;
|
|
518
|
+
let dtoTypeCnt = "";
|
|
519
|
+
if (requestBody) {
|
|
193
520
|
//create requestBody types
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
521
|
+
dtoTypeCnt = getBodySchemaType(requestBody);
|
|
522
|
+
if (dtoTypeCnt) {
|
|
523
|
+
let name = `${endpoint.name}DTO`;
|
|
524
|
+
if ((_h = (_g = config === null || config === void 0 ? void 0 : config.types) === null || _g === void 0 ? void 0 : _g.name) === null || _h === void 0 ? void 0 : _h.format) {
|
|
525
|
+
const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("endpoint", {
|
|
526
|
+
code: "",
|
|
527
|
+
type: "dto",
|
|
528
|
+
method,
|
|
529
|
+
path: endpointPath,
|
|
530
|
+
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
531
|
+
});
|
|
532
|
+
if (formattedName)
|
|
533
|
+
name = formattedName;
|
|
534
|
+
}
|
|
535
|
+
typesFileContent += `export type ${typePrefix}${name} = ${dtoTypeCnt};\n`;
|
|
198
536
|
}
|
|
199
537
|
}
|
|
200
|
-
|
|
538
|
+
const responseTypeObject = {};
|
|
539
|
+
let responseTypeCnt = "";
|
|
540
|
+
if (eSpec === null || eSpec === void 0 ? void 0 : eSpec.responses) {
|
|
201
541
|
// create request response types
|
|
202
|
-
const responses =
|
|
542
|
+
const responses = eSpec === null || eSpec === void 0 ? void 0 : eSpec.responses;
|
|
203
543
|
const resCodes = Object.keys(responses);
|
|
204
544
|
resCodes.forEach((code) => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
545
|
+
var _a, _b;
|
|
546
|
+
responseTypeCnt = getBodySchemaType(responses[code]);
|
|
547
|
+
responseTypeObject[code] = responseTypeCnt;
|
|
548
|
+
if (responseTypeCnt) {
|
|
549
|
+
let name = `${endpoint.name}${code}Response`;
|
|
550
|
+
if ((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.format) {
|
|
551
|
+
const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("endpoint", {
|
|
552
|
+
code,
|
|
553
|
+
type: "response",
|
|
554
|
+
method,
|
|
555
|
+
path: endpointPath,
|
|
556
|
+
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
557
|
+
});
|
|
558
|
+
if (formattedName)
|
|
559
|
+
name = formattedName;
|
|
560
|
+
}
|
|
561
|
+
typesFileContent += `export type ${typePrefix}${name} = ${responseTypeCnt};\n`;
|
|
208
562
|
}
|
|
209
563
|
});
|
|
210
564
|
}
|
|
565
|
+
// Function to format security requirements
|
|
566
|
+
const formatSecuritySpec = (security) => {
|
|
567
|
+
if (!security || !security.length)
|
|
568
|
+
return "";
|
|
569
|
+
return security
|
|
570
|
+
.map((securityRequirement) => {
|
|
571
|
+
const requirements = Object.entries(securityRequirement)
|
|
572
|
+
.map(([scheme, scopes]) => {
|
|
573
|
+
let sch = scheme;
|
|
574
|
+
let scopeText = "";
|
|
575
|
+
if (Array.isArray(scopes) && scopes.length) {
|
|
576
|
+
scopeText = `\n - Scopes: [\`${scopes.join("`, `")}\`]`;
|
|
577
|
+
sch = `**${sch}**`;
|
|
578
|
+
}
|
|
579
|
+
return `\n - ${sch}${scopeText}`;
|
|
580
|
+
})
|
|
581
|
+
.join("");
|
|
582
|
+
return requirements;
|
|
583
|
+
})
|
|
584
|
+
.join("\n");
|
|
585
|
+
};
|
|
586
|
+
// Get formatted security specification
|
|
587
|
+
const securitySpec = (eSpec === null || eSpec === void 0 ? void 0 : eSpec.security)
|
|
588
|
+
? formatSecuritySpec(eSpec.security)
|
|
589
|
+
: "";
|
|
590
|
+
let doc = "";
|
|
591
|
+
if (!((_k = (_j = config === null || config === void 0 ? void 0 : config.endpoints) === null || _j === void 0 ? void 0 : _j.doc) === null || _k === void 0 ? void 0 : _k.disable)) {
|
|
592
|
+
let curl = "";
|
|
593
|
+
if ((_m = (_l = config === null || config === void 0 ? void 0 : config.endpoints) === null || _l === void 0 ? void 0 : _l.doc) === null || _m === void 0 ? void 0 : _m.showCurl) {
|
|
594
|
+
// console.log("cirl data", {
|
|
595
|
+
// body: eSpec?.requestBody,
|
|
596
|
+
// bodyContent:
|
|
597
|
+
// eSpec?.requestBody?.content["application/json"]?.schema
|
|
598
|
+
// ?.properties,
|
|
599
|
+
// security: eSpec?.security,
|
|
600
|
+
// });
|
|
601
|
+
const headers = {};
|
|
602
|
+
let body = "";
|
|
603
|
+
let extras = "";
|
|
604
|
+
if ((_o = eSpec.requestBody) === null || _o === void 0 ? void 0 : _o.content) {
|
|
605
|
+
const contentTypes = Object.keys(eSpec.requestBody.content);
|
|
606
|
+
contentTypes.forEach((contentType) => {
|
|
607
|
+
// console.log("requestBody content", {
|
|
608
|
+
// contentType,
|
|
609
|
+
// schema: eSpec.requestBody.content[contentType].schema,
|
|
610
|
+
// });
|
|
611
|
+
const schema = eSpec.requestBody.content[contentType].schema;
|
|
612
|
+
if (schema) {
|
|
613
|
+
if (Array.isArray(headers["Content-type"])) {
|
|
614
|
+
headers["Content-type"].push(contentType);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
headers["Content-type"] = [contentType];
|
|
618
|
+
}
|
|
619
|
+
const schemaType = getSchemaExamples(spec, schema);
|
|
620
|
+
if (schemaType)
|
|
621
|
+
body = schemaType;
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
if (eSpec === null || eSpec === void 0 ? void 0 : eSpec.security) {
|
|
626
|
+
eSpec.security.forEach((securityItem) => {
|
|
627
|
+
Object.keys(securityItem).forEach((security) => {
|
|
628
|
+
var _a, _b;
|
|
629
|
+
const securitySchema = (_b = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes) === null || _b === void 0 ? void 0 : _b[security];
|
|
630
|
+
if (securitySchema) {
|
|
631
|
+
// headers["Authorization"] = securitySchema;
|
|
632
|
+
if (securitySchema.type === "mutualTLS") {
|
|
633
|
+
extras += `\n--cert client-certificate.crt \
|
|
634
|
+
--key client-private-key.key \
|
|
635
|
+
--cacert ca-certificate.crt`;
|
|
636
|
+
}
|
|
637
|
+
else if (securitySchema.type === "apiKey") {
|
|
638
|
+
headers[(securitySchema === null || securitySchema === void 0 ? void 0 : securitySchema.name) || "X-API-KEY"] = `{API_KEY_VALUE}`;
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
headers["Authorization"] = `${(securitySchema === null || securitySchema === void 0 ? void 0 : securitySchema.scheme) === "basic" ? "Basic" : "Bearer"} {${(securitySchema === null || securitySchema === void 0 ? void 0 : securitySchema.scheme) === "basic" ? "VALUE" : "TOKEN"}}`;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
const curlHeaders = {};
|
|
648
|
+
Object.keys(headers).forEach((header) => {
|
|
649
|
+
if (Array.isArray(headers[header])) {
|
|
650
|
+
curlHeaders[header] = headers[header].join("; ");
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
curlHeaders[header] = headers[header];
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
// console.log("curlHeaders", { headers, curlHeaders, body });
|
|
657
|
+
curl = `\n\`\`\`bash
|
|
658
|
+
${(0, curl_generator_1.CurlGenerator)({
|
|
659
|
+
url: serverUrl + endpointPath,
|
|
660
|
+
method: method.toUpperCase(),
|
|
661
|
+
headers: curlHeaders,
|
|
662
|
+
body,
|
|
663
|
+
})}${extras}
|
|
664
|
+
\`\`\``;
|
|
665
|
+
}
|
|
666
|
+
doc = `/**${(eSpec === null || eSpec === void 0 ? void 0 : eSpec.description) ? `\n* ${eSpec === null || eSpec === void 0 ? void 0 : eSpec.description} ` : ""}
|
|
667
|
+
* **Method**: \`${method.toUpperCase()}\`
|
|
668
|
+
* **Summary**: ${(eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary) || ""}
|
|
669
|
+
* **Tags**: [${((_p = eSpec === null || eSpec === void 0 ? void 0 : eSpec.tags) === null || _p === void 0 ? void 0 : _p.join(", ")) || ""}]
|
|
670
|
+
* **OperationId**: ${(eSpec === null || eSpec === void 0 ? void 0 : eSpec.operationId) || ""} ${queryTypeCnt
|
|
671
|
+
? `\n * **Query**: ${(0, helpers_1.renderTypeRefMD)(queryTypeCnt)} `
|
|
672
|
+
: ""}${dtoTypeCnt ? `\n * **DTO**: ${(0, helpers_1.renderTypeRefMD)(dtoTypeCnt)} ` : ""}${responseTypeCnt
|
|
673
|
+
? `\n * **Response**: ${Object.entries(responseTypeObject)
|
|
674
|
+
.map(([code, type]) => `\n - **${code}**: ${(0, helpers_1.renderTypeRefMD)(type, 2)} `)
|
|
675
|
+
.join("")}`
|
|
676
|
+
: ""}${securitySpec ? `\n * **Security**: ${securitySpec}\n` : ""}${curl}
|
|
677
|
+
*/\n`;
|
|
678
|
+
}
|
|
679
|
+
// Add the endpoint url
|
|
680
|
+
endpointsFileContent += `${doc}export const ${endpointPrefix}${name} = ${endpointUrl};
|
|
681
|
+
`;
|
|
211
682
|
});
|
|
212
683
|
});
|
|
213
684
|
// Create the necessary directories
|