openapi-sync 2.0.0 → 2.0.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.
@@ -0,0 +1,709 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const lodash_1 = __importDefault(require("lodash"));
18
+ const helpers_1 = require("./components/helpers");
19
+ const lodash_2 = require("lodash");
20
+ const axios_1 = __importDefault(require("axios"));
21
+ const axios_retry_1 = __importDefault(require("axios-retry"));
22
+ const openapi_core_1 = require("@redocly/openapi-core");
23
+ const state_1 = require("./state");
24
+ const curl_generator_1 = require("curl-generator");
25
+ const rootUsingCwd = process.cwd();
26
+ let fetchTimeout = {};
27
+ // Create an Axios instance
28
+ const apiClient = axios_1.default.create({
29
+ timeout: 60000, // Timeout after 1min
30
+ });
31
+ // Configure axios-retry
32
+ (0, axios_retry_1.default)(apiClient, {
33
+ retries: 20, // Number of retry attempts
34
+ retryCondition: (error) => {
35
+ // Retry on network error
36
+ return (error.code === "ECONNABORTED" || error.message.includes("Network Error"));
37
+ },
38
+ retryDelay: (retryCount) => {
39
+ return retryCount * 1000; // Exponential back-off: 1s, 2s, 3s, etc.
40
+ },
41
+ });
42
+ const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void 0, void 0, void 0, function* () {
43
+ var _a, _b, _c, _d, _e;
44
+ const specResponse = yield apiClient.get(apiUrl);
45
+ const redoclyConfig = yield (0, openapi_core_1.createConfig)({
46
+ extends: ["minimal"],
47
+ });
48
+ const source = JSON.stringify((0, helpers_1.isJson)(specResponse.data)
49
+ ? specResponse.data
50
+ : (0, helpers_1.yamlStringToJson)(specResponse.data));
51
+ const lintResults = yield (0, openapi_core_1.bundleFromString)({
52
+ source,
53
+ config: redoclyConfig,
54
+ });
55
+ const folderPath = path_1.default.join((config === null || config === void 0 ? void 0 : config.folder) || "", apiName);
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
+ };
310
+ // auto update only on dev
311
+ if (refetchInterval && !isNaN(refetchInterval) && refetchInterval > 0) {
312
+ if (!(process.env.NODE_ENV &&
313
+ ["production", "prod", "test", "staging"].includes(process.env.NODE_ENV))) {
314
+ // auto sync at interval
315
+ if (fetchTimeout[apiName])
316
+ clearTimeout(fetchTimeout[apiName]);
317
+ // set next request timeout
318
+ fetchTimeout[apiName] = setTimeout(() => OpenapiSync(apiUrl, apiName, config, refetchInterval), refetchInterval);
319
+ }
320
+ }
321
+ // compare new spec with old spec, continuing only if spec it different
322
+ const prevSpec = (0, state_1.getState)(apiName);
323
+ if ((0, lodash_2.isEqual)(prevSpec, spec))
324
+ return;
325
+ (0, state_1.setState)(apiName, spec);
326
+ let endpointsFileContent = "";
327
+ let typesFileContent = "";
328
+ let sharedTypesFileContent = {};
329
+ if (spec.components) {
330
+ Object.keys(spec.components).forEach((key) => {
331
+ if ([
332
+ "schemas",
333
+ "responses",
334
+ "parameters",
335
+ "examples",
336
+ "requestBodies",
337
+ "headers",
338
+ "links",
339
+ "callbacks",
340
+ ].includes(key)) {
341
+ // Create components (shared) types
342
+ const components = spec.components[key];
343
+ const componentInterfaces = {};
344
+ const componentSchema = {};
345
+ const contentKeys = Object.keys(components);
346
+ // only need 1 schema so will us the first schema provided
347
+ contentKeys.forEach((contentKey) => {
348
+ var _a;
349
+ /* const schema = (() => {
350
+ switch (key) {
351
+ case "parameters":
352
+ return components[contentKey].schema;
353
+ default:
354
+ return components[contentKey];
355
+ }
356
+ })() as IOpenApSchemaSpec; */
357
+ const schema = (((_a = components[contentKey]) === null || _a === void 0 ? void 0 : _a.schema)
358
+ ? components[contentKey].schema
359
+ : components[contentKey]);
360
+ const typeCnt = `${parseSchemaToType(spec, schema, "", true, {
361
+ noSharedImport: true,
362
+ useComponentName: ["parameters"].includes(key),
363
+ })}`;
364
+ if (typeCnt) {
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)}`);
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";
415
+ });
416
+ }
417
+ });
418
+ }
419
+ const getBodySchemaType = (requestBody) => {
420
+ let typeCnt = "";
421
+ if (requestBody.content) {
422
+ const contentKeys = Object.keys(requestBody.content);
423
+ // only need 1 schema so will us the first schema provided
424
+ if (contentKeys[0] && requestBody.content[contentKeys[0]].schema) {
425
+ typeCnt += `${parseSchemaToType(spec, requestBody.content[contentKeys[0]].schema, "")}`;
426
+ }
427
+ }
428
+ return typeCnt;
429
+ };
430
+ const treatEndpointUrl = (endpointUrl) => {
431
+ var _a, _b, _c, _d, _e;
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) &&
433
+ Array.isArray(config === null || config === void 0 ? void 0 : config.endpoints.value.replaceWords)) {
434
+ let newEndpointUrl = endpointUrl;
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) => {
436
+ const regexp = new RegExp(replaceWord.replace, "g");
437
+ newEndpointUrl = newEndpointUrl.replace(regexp, replaceWord.with || "");
438
+ });
439
+ return newEndpointUrl;
440
+ }
441
+ else {
442
+ return endpointUrl;
443
+ }
444
+ };
445
+ Object.keys(spec.paths || {}).forEach((endpointPath) => {
446
+ const endpointSpec = spec.paths[endpointPath];
447
+ const endpointMethods = Object.keys(endpointSpec);
448
+ endpointMethods.forEach((_method) => {
449
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
450
+ const method = _method;
451
+ const endpoint = (0, helpers_1.getEndpointDetails)(endpointPath, method);
452
+ console.log("Endpoint details", endpoint);
453
+ 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 : "") +
454
+ endpoint.pathParts
455
+ .map((part) => {
456
+ // check if part is a variable
457
+ if (part[0] === "{" && part[part.length - 1] === "}") {
458
+ const s = part.replace(/{/, "").replace(/}/, "");
459
+ part = `\${${s}}`;
460
+ }
461
+ //api/<userId>
462
+ else if (part[0] === "<" && part[part.length - 1] === ">") {
463
+ const s = part.replace(/</, "").replace(/>/, "");
464
+ part = `\${${s}}`;
465
+ }
466
+ //api/:userId
467
+ else if (part[0] === ":") {
468
+ const s = part.replace(/:/, "");
469
+ part = `\${${s}}`;
470
+ }
471
+ return part;
472
+ })
473
+ .join("/");
474
+ let endpointUrl = `"${endpointUrlTxt}"`;
475
+ if (endpoint.variables.length > 0) {
476
+ const params = endpoint.variables.map((v) => `${v}:string`).join(",");
477
+ endpointUrl = `(${params})=> \`${endpointUrlTxt}\``;
478
+ }
479
+ //treat endpoint url
480
+ endpointUrl = treatEndpointUrl(endpointUrl);
481
+ const eSpec = endpointSpec[method];
482
+ let name = `${endpoint.name}`;
483
+ 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) {
484
+ const formattedName = config === null || config === void 0 ? void 0 : config.endpoints.name.format({
485
+ method,
486
+ path: endpointPath,
487
+ summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
488
+ });
489
+ if (formattedName)
490
+ name = formattedName;
491
+ }
492
+ let queryTypeCnt = "";
493
+ if (eSpec === null || eSpec === void 0 ? void 0 : eSpec.parameters) {
494
+ // create query parameters types
495
+ const parameters = eSpec === null || eSpec === void 0 ? void 0 : eSpec.parameters;
496
+ parameters.forEach((param, i) => {
497
+ if (param.$ref || (param.in === "query" && param.name)) {
498
+ queryTypeCnt += `${parseSchemaToType(spec, param.$ref ? param : param.schema, param.name || "", param.required)}`;
499
+ }
500
+ });
501
+ if (queryTypeCnt) {
502
+ queryTypeCnt = `{\n${queryTypeCnt}}`;
503
+ let name = `${endpoint.name}Query`;
504
+ 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) {
505
+ const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("endpoint", {
506
+ code: "",
507
+ type: "query",
508
+ method,
509
+ path: endpointPath,
510
+ summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
511
+ });
512
+ if (formattedName)
513
+ name = formattedName;
514
+ }
515
+ typesFileContent += `export type ${typePrefix}${name} = ${queryTypeCnt};\n`;
516
+ }
517
+ }
518
+ const requestBody = eSpec === null || eSpec === void 0 ? void 0 : eSpec.requestBody;
519
+ let dtoTypeCnt = "";
520
+ if (requestBody) {
521
+ //create requestBody types
522
+ dtoTypeCnt = getBodySchemaType(requestBody);
523
+ if (dtoTypeCnt) {
524
+ let name = `${endpoint.name}DTO`;
525
+ 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) {
526
+ const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("endpoint", {
527
+ code: "",
528
+ type: "dto",
529
+ method,
530
+ path: endpointPath,
531
+ summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
532
+ });
533
+ if (formattedName)
534
+ name = formattedName;
535
+ }
536
+ typesFileContent += `export type ${typePrefix}${name} = ${dtoTypeCnt};\n`;
537
+ }
538
+ }
539
+ const responseTypeObject = {};
540
+ let responseTypeCnt = "";
541
+ if (eSpec === null || eSpec === void 0 ? void 0 : eSpec.responses) {
542
+ // create request response types
543
+ const responses = eSpec === null || eSpec === void 0 ? void 0 : eSpec.responses;
544
+ const resCodes = Object.keys(responses);
545
+ resCodes.forEach((code) => {
546
+ var _a, _b;
547
+ responseTypeCnt = getBodySchemaType(responses[code]);
548
+ responseTypeObject[code] = responseTypeCnt;
549
+ if (responseTypeCnt) {
550
+ let name = `${endpoint.name}${code}Response`;
551
+ 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) {
552
+ const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("endpoint", {
553
+ code,
554
+ type: "response",
555
+ method,
556
+ path: endpointPath,
557
+ summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
558
+ });
559
+ if (formattedName)
560
+ name = formattedName;
561
+ }
562
+ typesFileContent += `export type ${typePrefix}${name} = ${responseTypeCnt};\n`;
563
+ }
564
+ });
565
+ }
566
+ // Function to format security requirements
567
+ const formatSecuritySpec = (security) => {
568
+ if (!security || !security.length)
569
+ return "";
570
+ return security
571
+ .map((securityRequirement) => {
572
+ const requirements = Object.entries(securityRequirement)
573
+ .map(([scheme, scopes]) => {
574
+ let sch = scheme;
575
+ let scopeText = "";
576
+ if (Array.isArray(scopes) && scopes.length) {
577
+ scopeText = `\n - Scopes: [\`${scopes.join("`, `")}\`]`;
578
+ sch = `**${sch}**`;
579
+ }
580
+ return `\n - ${sch}${scopeText}`;
581
+ })
582
+ .join("");
583
+ return requirements;
584
+ })
585
+ .join("\n");
586
+ };
587
+ // Get formatted security specification
588
+ const securitySpec = (eSpec === null || eSpec === void 0 ? void 0 : eSpec.security)
589
+ ? formatSecuritySpec(eSpec.security)
590
+ : "";
591
+ let doc = "";
592
+ 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)) {
593
+ let curl = "";
594
+ 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) {
595
+ // console.log("cirl data", {
596
+ // body: eSpec?.requestBody,
597
+ // bodyContent:
598
+ // eSpec?.requestBody?.content["application/json"]?.schema
599
+ // ?.properties,
600
+ // security: eSpec?.security,
601
+ // });
602
+ const headers = {};
603
+ let body = "";
604
+ let extras = "";
605
+ if ((_o = eSpec.requestBody) === null || _o === void 0 ? void 0 : _o.content) {
606
+ const contentTypes = Object.keys(eSpec.requestBody.content);
607
+ contentTypes.forEach((contentType) => {
608
+ // console.log("requestBody content", {
609
+ // contentType,
610
+ // schema: eSpec.requestBody.content[contentType].schema,
611
+ // });
612
+ const schema = eSpec.requestBody.content[contentType].schema;
613
+ if (schema) {
614
+ if (Array.isArray(headers["Content-type"])) {
615
+ headers["Content-type"].push(contentType);
616
+ }
617
+ else {
618
+ headers["Content-type"] = [contentType];
619
+ }
620
+ const schemaType = getSchemaExamples(spec, schema);
621
+ if (schemaType)
622
+ body = schemaType;
623
+ }
624
+ });
625
+ }
626
+ if (eSpec === null || eSpec === void 0 ? void 0 : eSpec.security) {
627
+ eSpec.security.forEach((securityItem) => {
628
+ Object.keys(securityItem).forEach((security) => {
629
+ var _a, _b;
630
+ const securitySchema = (_b = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes) === null || _b === void 0 ? void 0 : _b[security];
631
+ if (securitySchema) {
632
+ // headers["Authorization"] = securitySchema;
633
+ if (securitySchema.type === "mutualTLS") {
634
+ extras += `\n--cert client-certificate.crt \
635
+ --key client-private-key.key \
636
+ --cacert ca-certificate.crt`;
637
+ }
638
+ else if (securitySchema.type === "apiKey") {
639
+ headers[(securitySchema === null || securitySchema === void 0 ? void 0 : securitySchema.name) || "X-API-KEY"] = `{API_KEY_VALUE}`;
640
+ }
641
+ else {
642
+ 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"}}`;
643
+ }
644
+ }
645
+ });
646
+ });
647
+ }
648
+ const curlHeaders = {};
649
+ Object.keys(headers).forEach((header) => {
650
+ if (Array.isArray(headers[header])) {
651
+ curlHeaders[header] = headers[header].join("; ");
652
+ }
653
+ else {
654
+ curlHeaders[header] = headers[header];
655
+ }
656
+ });
657
+ // console.log("curlHeaders", { headers, curlHeaders, body });
658
+ curl = `\n\`\`\`bash
659
+ ${(0, curl_generator_1.CurlGenerator)({
660
+ url: serverUrl + endpointPath,
661
+ method: method.toUpperCase(),
662
+ headers: curlHeaders,
663
+ body,
664
+ })}${extras}
665
+ \`\`\``;
666
+ }
667
+ doc = `/**${(eSpec === null || eSpec === void 0 ? void 0 : eSpec.description) ? `\n* ${eSpec === null || eSpec === void 0 ? void 0 : eSpec.description} ` : ""}
668
+ * **Method**: \`${method.toUpperCase()}\`
669
+ * **Summary**: ${(eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary) || ""}
670
+ * **Tags**: [${((_p = eSpec === null || eSpec === void 0 ? void 0 : eSpec.tags) === null || _p === void 0 ? void 0 : _p.join(", ")) || ""}]
671
+ * **OperationId**: ${(eSpec === null || eSpec === void 0 ? void 0 : eSpec.operationId) || ""} ${queryTypeCnt
672
+ ? `\n * **Query**: ${(0, helpers_1.renderTypeRefMD)(queryTypeCnt)} `
673
+ : ""}${dtoTypeCnt ? `\n * **DTO**: ${(0, helpers_1.renderTypeRefMD)(dtoTypeCnt)} ` : ""}${responseTypeCnt
674
+ ? `\n * **Response**: ${Object.entries(responseTypeObject)
675
+ .map(([code, type]) => `\n - **${code}**: ${(0, helpers_1.renderTypeRefMD)(type, 2)} `)
676
+ .join("")}`
677
+ : ""}${securitySpec ? `\n * **Security**: ${securitySpec}\n` : ""}${curl}
678
+ */\n`;
679
+ }
680
+ // Add the endpoint url
681
+ endpointsFileContent += `${doc}export const ${endpointPrefix}${name} = ${endpointUrl};
682
+ `;
683
+ });
684
+ });
685
+ // Create the necessary directories
686
+ const endpointsFilePath = path_1.default.join(rootUsingCwd, folderPath, "endpoints.ts");
687
+ yield fs_1.default.promises.mkdir(path_1.default.dirname(endpointsFilePath), { recursive: true });
688
+ // Create the file asynchronously
689
+ yield fs_1.default.promises.writeFile(endpointsFilePath, endpointsFileContent);
690
+ if (Object.values(sharedTypesFileContent).length > 0) {
691
+ // Create the necessary directories
692
+ const sharedTypesFilePath = path_1.default.join(rootUsingCwd, folderPath, "types", "shared.ts");
693
+ yield fs_1.default.promises.mkdir(path_1.default.dirname(sharedTypesFilePath), {
694
+ recursive: true,
695
+ });
696
+ // Create the file asynchronously
697
+ yield fs_1.default.promises.writeFile(sharedTypesFilePath, Object.values(sharedTypesFileContent).join("\n"));
698
+ }
699
+ if (typesFileContent.length > 0) {
700
+ // Create the necessary directories
701
+ const typesFilePath = path_1.default.join(rootUsingCwd, folderPath, "types", "index.ts");
702
+ yield fs_1.default.promises.mkdir(path_1.default.dirname(typesFilePath), { recursive: true });
703
+ // Create the file asynchronously
704
+ yield fs_1.default.promises.writeFile(typesFilePath, `${Object.values(sharedTypesFileContent).length > 0
705
+ ? `import * as Shared from "./shared";\n\n`
706
+ : ""}${typesFileContent}`);
707
+ }
708
+ });
709
+ exports.default = OpenapiSync;