openapi-sync 2.1.3 → 2.1.5
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/dist/Openapi-sync/index.d.ts +3 -0
- package/dist/Openapi-sync/index.js +8 -7
- package/dist/Openapi-sync/state.d.ts +4 -0
- package/dist/helpers.d.ts +12 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +39 -22
- package/dist/openapi.sync.sample.d.ts +1 -0
- package/dist/openapi.sync.sample.js +2 -7
- package/dist/regex.d.ts +2 -0
- package/dist/types.d.ts +113 -0
- package/package.json +24 -3
- package/dist/Openapi-sync/test.js +0 -709
- package/types.ts +0 -135
- /package/dist/{Openapi-sync/components/helpers.js → helpers.js} +0 -0
- /package/dist/{Openapi-sync/components/regex.js → regex.js} +0 -0
|
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const fs_1 = __importDefault(require("fs"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
17
|
const lodash_1 = __importDefault(require("lodash"));
|
|
18
|
-
const helpers_1 = require("
|
|
18
|
+
const helpers_1 = require("../helpers");
|
|
19
19
|
const lodash_2 = require("lodash");
|
|
20
20
|
const axios_1 = __importDefault(require("axios"));
|
|
21
21
|
const axios_retry_1 = __importDefault(require("axios-retry"));
|
|
@@ -65,14 +65,15 @@ const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void
|
|
|
65
65
|
: "";
|
|
66
66
|
const getSharedComponentName = (componentName, componentType) => {
|
|
67
67
|
var _a, _b;
|
|
68
|
+
const defaultName = (0, helpers_1.capitalize)(componentName);
|
|
68
69
|
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) {
|
|
69
70
|
const formattedName = config === null || config === void 0 ? void 0 : config.types.name.format("shared", {
|
|
70
71
|
name: componentName,
|
|
71
|
-
});
|
|
72
|
+
}, defaultName);
|
|
72
73
|
if (formattedName)
|
|
73
74
|
return `${typePrefix}${formattedName}`;
|
|
74
75
|
}
|
|
75
|
-
return `${typePrefix}${
|
|
76
|
+
return `${typePrefix}${defaultName}`;
|
|
76
77
|
};
|
|
77
78
|
const parseSchemaToType = (apiDoc, schema, name, isRequired, options, indentLevel = 0) => {
|
|
78
79
|
let overrideName = "";
|
|
@@ -552,7 +553,7 @@ const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void
|
|
|
552
553
|
method,
|
|
553
554
|
path: endpointPath,
|
|
554
555
|
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
555
|
-
});
|
|
556
|
+
}, name);
|
|
556
557
|
if (formattedName)
|
|
557
558
|
name = formattedName;
|
|
558
559
|
}
|
|
@@ -573,7 +574,7 @@ const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void
|
|
|
573
574
|
method,
|
|
574
575
|
path: endpointPath,
|
|
575
576
|
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
576
|
-
});
|
|
577
|
+
}, name);
|
|
577
578
|
if (formattedName)
|
|
578
579
|
name = formattedName;
|
|
579
580
|
}
|
|
@@ -599,7 +600,7 @@ const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void
|
|
|
599
600
|
method,
|
|
600
601
|
path: endpointPath,
|
|
601
602
|
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
602
|
-
});
|
|
603
|
+
}, name);
|
|
603
604
|
if (formattedName)
|
|
604
605
|
name = formattedName;
|
|
605
606
|
}
|
|
@@ -731,7 +732,7 @@ ${(0, curl_generator_1.CurlGenerator)({
|
|
|
731
732
|
path: endpointPath,
|
|
732
733
|
summary: eSpec === null || eSpec === void 0 ? void 0 : eSpec.summary,
|
|
733
734
|
operationId: eSpec === null || eSpec === void 0 ? void 0 : eSpec.operationId,
|
|
734
|
-
});
|
|
735
|
+
}, name);
|
|
735
736
|
if (formattedName)
|
|
736
737
|
name = formattedName;
|
|
737
738
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const isJson: (value: any) => boolean;
|
|
2
|
+
export declare const isYamlString: (fileContent: string) => boolean;
|
|
3
|
+
export declare const yamlStringToJson: (fileContent: string) => any;
|
|
4
|
+
export declare const capitalize: (text: string) => string;
|
|
5
|
+
export declare const getEndpointDetails: (path: string, method: string) => {
|
|
6
|
+
name: string;
|
|
7
|
+
variables: string[];
|
|
8
|
+
pathParts: string[];
|
|
9
|
+
};
|
|
10
|
+
export declare const JSONStringify: (obj: Record<string, any>, indent?: number) => string;
|
|
11
|
+
export declare const renderTypeRefMD: (typeRef: string, indent?: number) => string;
|
|
12
|
+
export declare function getNestedValue<T>(obj: object, path: string): T | undefined;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
17
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
18
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -18,40 +32,43 @@ const dotenv_1 = __importDefault(require("dotenv"));
|
|
|
18
32
|
const path_1 = __importDefault(require("path"));
|
|
19
33
|
const fs_1 = __importDefault(require("fs"));
|
|
20
34
|
const state_1 = require("./Openapi-sync/state");
|
|
35
|
+
// Re-export modules for user consumption
|
|
36
|
+
__exportStar(require("./types"), exports);
|
|
37
|
+
__exportStar(require("./helpers"), exports);
|
|
38
|
+
__exportStar(require("./regex"), exports);
|
|
21
39
|
dotenv_1.default.config();
|
|
22
40
|
const rootUsingCwd = process.cwd();
|
|
23
41
|
const Init = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
42
|
// Load config file
|
|
25
|
-
let configJS
|
|
43
|
+
let configJS;
|
|
44
|
+
// Register TypeScript loader before requiring the file
|
|
26
45
|
try {
|
|
27
|
-
|
|
46
|
+
require("esbuild-register");
|
|
28
47
|
}
|
|
29
|
-
catch (
|
|
30
|
-
|
|
48
|
+
catch (registerError) {
|
|
49
|
+
throw registerError;
|
|
31
50
|
}
|
|
51
|
+
const jsConfigPath = path_1.default.join(rootUsingCwd, "openapi.sync.");
|
|
52
|
+
const tsConfigPath = path_1.default.join(rootUsingCwd, "openapi.sync.ts");
|
|
53
|
+
const jsonConfigPath = path_1.default.join(rootUsingCwd, "openapi.sync.json");
|
|
54
|
+
const configPaths = [jsConfigPath, tsConfigPath, jsonConfigPath];
|
|
32
55
|
try {
|
|
33
|
-
|
|
56
|
+
for (const configPath of configPaths) {
|
|
57
|
+
if (fs_1.default.existsSync(configPath)) {
|
|
58
|
+
configJS = require(configPath);
|
|
59
|
+
if (Object.keys(configJS).length === 1 && configJS.default) {
|
|
60
|
+
configJS = configJS.default;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
34
64
|
}
|
|
35
65
|
catch (e) {
|
|
36
|
-
|
|
66
|
+
console.log(e);
|
|
37
67
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (fs_1.default.existsSync(tsConfigPath)) {
|
|
42
|
-
// Register TypeScript loader before requiring the file
|
|
43
|
-
try {
|
|
44
|
-
require("esbuild-register");
|
|
45
|
-
}
|
|
46
|
-
catch (registerError) {
|
|
47
|
-
throw registerError;
|
|
48
|
-
}
|
|
49
|
-
// Now try to load TypeScript config
|
|
50
|
-
configTS = require(tsConfigPath);
|
|
51
|
-
}
|
|
68
|
+
const config = configJS;
|
|
69
|
+
if (!config) {
|
|
70
|
+
throw new Error("No config found");
|
|
52
71
|
}
|
|
53
|
-
catch (e) { }
|
|
54
|
-
const config = configTS || configJS || configJson;
|
|
55
72
|
const apiNames = Object.keys(config.api);
|
|
56
73
|
const refetchInterval = options &&
|
|
57
74
|
"refetchInterval" in options &&
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// TypeScript config file for openapi-sync
|
|
3
|
-
// To use this file, install a TypeScript loader:
|
|
4
|
-
// npm install --save-dev esbuild-register (recommended - fastest & lightest)
|
|
5
|
-
// or: npm install --save-dev tsx
|
|
6
|
-
// or: npm install --save-dev @swc/register
|
|
7
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
3
|
const config = {
|
|
9
4
|
refetchInterval: 5000,
|
|
@@ -16,7 +11,7 @@ const config = {
|
|
|
16
11
|
types: {
|
|
17
12
|
name: {
|
|
18
13
|
prefix: "",
|
|
19
|
-
format: (source, data) => {
|
|
14
|
+
format: (source, data, defaultName) => {
|
|
20
15
|
if (source === "shared") {
|
|
21
16
|
return `${data.name}`;
|
|
22
17
|
}
|
|
@@ -45,7 +40,7 @@ const config = {
|
|
|
45
40
|
name: {
|
|
46
41
|
prefix: "",
|
|
47
42
|
useOperationId: true,
|
|
48
|
-
format: ({ method, path, summary, operationId }) => {
|
|
43
|
+
format: ({ method, path, summary, operationId }, defaultName) => {
|
|
49
44
|
if (path === "/")
|
|
50
45
|
return "root";
|
|
51
46
|
return path.replace(/\//g, "_").replace(/{|}/g, "");
|
package/dist/regex.d.ts
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Method } from "axios";
|
|
2
|
+
export type IOpenApiSpec = Record<"openapi", string> & Record<string, any>;
|
|
3
|
+
export type IOpenApSchemaSpec = {
|
|
4
|
+
nullable?: boolean;
|
|
5
|
+
type: "string" | "integer" | "number" | "array" | "object" | "boolean" | "null" | any[];
|
|
6
|
+
example?: any;
|
|
7
|
+
enum?: string[];
|
|
8
|
+
format?: string;
|
|
9
|
+
items?: IOpenApSchemaSpec;
|
|
10
|
+
required?: string[];
|
|
11
|
+
description?: string;
|
|
12
|
+
$ref?: string;
|
|
13
|
+
properties?: Record<string, IOpenApSchemaSpec>;
|
|
14
|
+
additionalProperties?: IOpenApSchemaSpec;
|
|
15
|
+
anyOf?: IOpenApSchemaSpec[];
|
|
16
|
+
oneOf?: IOpenApSchemaSpec[];
|
|
17
|
+
allOf?: IOpenApSchemaSpec[];
|
|
18
|
+
};
|
|
19
|
+
export type IOpenApiParameterSpec = {
|
|
20
|
+
$ref?: string;
|
|
21
|
+
name: string;
|
|
22
|
+
in: string;
|
|
23
|
+
enum?: string[];
|
|
24
|
+
description?: string;
|
|
25
|
+
required?: boolean;
|
|
26
|
+
deprecated?: boolean;
|
|
27
|
+
allowEmptyValue?: boolean;
|
|
28
|
+
style?: string;
|
|
29
|
+
explode?: boolean;
|
|
30
|
+
allowReserved?: boolean;
|
|
31
|
+
schema?: IOpenApSchemaSpec;
|
|
32
|
+
example?: any;
|
|
33
|
+
examples?: any[];
|
|
34
|
+
};
|
|
35
|
+
export type IOpenApiMediaTypeSpec = {
|
|
36
|
+
schema?: IOpenApSchemaSpec;
|
|
37
|
+
example?: any;
|
|
38
|
+
examples?: any[];
|
|
39
|
+
encoding?: any;
|
|
40
|
+
};
|
|
41
|
+
export type IOpenApiRequestBodySpec = {
|
|
42
|
+
description?: string;
|
|
43
|
+
required?: boolean;
|
|
44
|
+
content: Record<string, IOpenApiMediaTypeSpec>;
|
|
45
|
+
};
|
|
46
|
+
export type IOpenApiResponseSpec = Record<string, IOpenApiRequestBodySpec>;
|
|
47
|
+
export type IConfigReplaceWord = {
|
|
48
|
+
/** string and regular expression as a string*/
|
|
49
|
+
replace: string;
|
|
50
|
+
with: string;
|
|
51
|
+
type?: "endpoint" | "type";
|
|
52
|
+
};
|
|
53
|
+
export type IConfigDoc = {
|
|
54
|
+
disable?: boolean;
|
|
55
|
+
showCurl?: boolean;
|
|
56
|
+
};
|
|
57
|
+
export type IConfig = {
|
|
58
|
+
refetchInterval?: number;
|
|
59
|
+
folder?: string;
|
|
60
|
+
api: Record<string, string>;
|
|
61
|
+
server?: number | string;
|
|
62
|
+
types?: {
|
|
63
|
+
name?: {
|
|
64
|
+
prefix?: string;
|
|
65
|
+
format?: (source: "shared" | "endpoint", data: {
|
|
66
|
+
name?: string;
|
|
67
|
+
type?: "response" | "dto" | "query";
|
|
68
|
+
code?: string;
|
|
69
|
+
method?: Method;
|
|
70
|
+
path?: string;
|
|
71
|
+
summary?: string;
|
|
72
|
+
}, defaultName: string) => string | null | undefined;
|
|
73
|
+
};
|
|
74
|
+
doc?: IConfigDoc;
|
|
75
|
+
};
|
|
76
|
+
endpoints?: {
|
|
77
|
+
value?: {
|
|
78
|
+
replaceWords?: IConfigReplaceWord[];
|
|
79
|
+
includeServer?: boolean;
|
|
80
|
+
type?: "string" | "object";
|
|
81
|
+
};
|
|
82
|
+
name?: {
|
|
83
|
+
format?: (data: {
|
|
84
|
+
method: Method;
|
|
85
|
+
path: string;
|
|
86
|
+
summary: string;
|
|
87
|
+
operationId: string;
|
|
88
|
+
}, defaultName: string) => string | null;
|
|
89
|
+
prefix?: string;
|
|
90
|
+
useOperationId?: boolean;
|
|
91
|
+
};
|
|
92
|
+
doc?: IConfigDoc;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
export type IOpenApiSecuritySchemes = {
|
|
96
|
+
[key: string]: {
|
|
97
|
+
type: "http" | "apiKey" | "oauth2" | "openIdConnect" | "mutualTLS";
|
|
98
|
+
scheme?: "bearer" | "basic";
|
|
99
|
+
in?: "query" | "header" | "cookie";
|
|
100
|
+
flows?: {
|
|
101
|
+
authorizationCode: {
|
|
102
|
+
authorizationUrl: "https://example.com/auth";
|
|
103
|
+
tokenUrl: "https://example.com/token";
|
|
104
|
+
scopes: {
|
|
105
|
+
"read:data": "Grants read access";
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
bearerFormat?: "JWT";
|
|
110
|
+
openIdConnectUrl?: string;
|
|
111
|
+
name?: string;
|
|
112
|
+
};
|
|
113
|
+
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-sync",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "A developer-friendly tool designed to keep your API up-to-date by leveraging OpenAPI schemas. It automates the generation of endpoint URIs and type definitions, including shared types, directly from your OpenAPI specification.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./types": {
|
|
14
|
+
"types": "./dist/types.d.ts",
|
|
15
|
+
"require": "./dist/types.js",
|
|
16
|
+
"import": "./dist/types.js"
|
|
17
|
+
},
|
|
18
|
+
"./helpers": {
|
|
19
|
+
"types": "./dist/helpers.d.ts",
|
|
20
|
+
"require": "./dist/helpers.js",
|
|
21
|
+
"import": "./dist/helpers.js"
|
|
22
|
+
},
|
|
23
|
+
"./regex": {
|
|
24
|
+
"types": "./dist/regex.d.ts",
|
|
25
|
+
"require": "./dist/regex.js",
|
|
26
|
+
"import": "./dist/regex.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
7
29
|
"bin": {
|
|
8
30
|
"openapi-sync": "./bin/cli.js"
|
|
9
31
|
},
|
|
@@ -24,7 +46,6 @@
|
|
|
24
46
|
"bin",
|
|
25
47
|
"dist",
|
|
26
48
|
"db.json",
|
|
27
|
-
"types.ts",
|
|
28
49
|
"LICENSE",
|
|
29
50
|
"README.md",
|
|
30
51
|
"package.json"
|
|
@@ -41,13 +62,13 @@
|
|
|
41
62
|
"@types/js-yaml": "^4.0.9",
|
|
42
63
|
"@types/lodash": "^4.17.7",
|
|
43
64
|
"@types/node": "^22.1.0",
|
|
44
|
-
"esbuild-register": "^3.6.0",
|
|
45
65
|
"typescript": "^5.5.4"
|
|
46
66
|
},
|
|
47
67
|
"dependencies": {
|
|
48
68
|
"@redocly/openapi-core": "^1.19.0",
|
|
49
69
|
"axios": "^1.7.3",
|
|
50
70
|
"axios-retry": "^4.5.0",
|
|
71
|
+
"esbuild-register": "^3.6.0",
|
|
51
72
|
"curl-generator": "^0.4.2",
|
|
52
73
|
"dotenv": "^16.4.5",
|
|
53
74
|
"js-yaml": "^4.1.0",
|
|
@@ -1,709 +0,0 @@
|
|
|
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;
|
package/types.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { Method } from "axios";
|
|
2
|
-
|
|
3
|
-
export type IOpenApiSpec = Record<"openapi", string> & Record<string, any>;
|
|
4
|
-
|
|
5
|
-
export type IOpenApSchemaSpec = {
|
|
6
|
-
nullable?: boolean;
|
|
7
|
-
type:
|
|
8
|
-
| "string"
|
|
9
|
-
| "integer"
|
|
10
|
-
| "number"
|
|
11
|
-
| "array"
|
|
12
|
-
| "object"
|
|
13
|
-
| "boolean"
|
|
14
|
-
| "null"
|
|
15
|
-
| any[];
|
|
16
|
-
example?: any;
|
|
17
|
-
enum?: string[];
|
|
18
|
-
format?: string;
|
|
19
|
-
items?: IOpenApSchemaSpec;
|
|
20
|
-
required?: string[];
|
|
21
|
-
description?: string;
|
|
22
|
-
$ref?: string;
|
|
23
|
-
properties?: Record<string, IOpenApSchemaSpec>;
|
|
24
|
-
additionalProperties?: IOpenApSchemaSpec;
|
|
25
|
-
anyOf?: IOpenApSchemaSpec[];
|
|
26
|
-
oneOf?: IOpenApSchemaSpec[];
|
|
27
|
-
allOf?: IOpenApSchemaSpec[];
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type IOpenApiParameterSpec = {
|
|
31
|
-
$ref?: string;
|
|
32
|
-
name: string;
|
|
33
|
-
in: string;
|
|
34
|
-
enum?: string[];
|
|
35
|
-
description?: string;
|
|
36
|
-
required?: boolean;
|
|
37
|
-
deprecated?: boolean;
|
|
38
|
-
allowEmptyValue?: boolean;
|
|
39
|
-
style?: string;
|
|
40
|
-
explode?: boolean;
|
|
41
|
-
allowReserved?: boolean;
|
|
42
|
-
schema?: IOpenApSchemaSpec;
|
|
43
|
-
example?: any;
|
|
44
|
-
examples?: any[];
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export type IOpenApiMediaTypeSpec = {
|
|
48
|
-
schema?: IOpenApSchemaSpec;
|
|
49
|
-
example?: any;
|
|
50
|
-
examples?: any[];
|
|
51
|
-
encoding?: any;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export type IOpenApiRequestBodySpec = {
|
|
55
|
-
description?: string;
|
|
56
|
-
required?: boolean;
|
|
57
|
-
content: Record<string, IOpenApiMediaTypeSpec>;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export type IOpenApiResponseSpec = Record<string, IOpenApiRequestBodySpec>;
|
|
61
|
-
|
|
62
|
-
export type IConfigReplaceWord = {
|
|
63
|
-
/** string and regular expression as a string*/
|
|
64
|
-
replace: string;
|
|
65
|
-
with: string;
|
|
66
|
-
type?: "endpoint" | "type";
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export type IConfigDoc = {
|
|
70
|
-
disable?: boolean;
|
|
71
|
-
showCurl?: boolean;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export type IConfig = {
|
|
75
|
-
refetchInterval?: number;
|
|
76
|
-
folder?: string;
|
|
77
|
-
api: Record<string, string>;
|
|
78
|
-
server?: number | string;
|
|
79
|
-
types?: {
|
|
80
|
-
name?: {
|
|
81
|
-
prefix?: string;
|
|
82
|
-
format?: (
|
|
83
|
-
source: "shared" | "endpoint",
|
|
84
|
-
data: {
|
|
85
|
-
name?: string;
|
|
86
|
-
////. endpoint source //////
|
|
87
|
-
type?: "response" | "dto" | "query";
|
|
88
|
-
code?: string;
|
|
89
|
-
method?: Method;
|
|
90
|
-
path?: string;
|
|
91
|
-
summary?: string;
|
|
92
|
-
}
|
|
93
|
-
) => string | null | undefined;
|
|
94
|
-
};
|
|
95
|
-
doc?: IConfigDoc;
|
|
96
|
-
};
|
|
97
|
-
endpoints?: {
|
|
98
|
-
value?: {
|
|
99
|
-
replaceWords?: IConfigReplaceWord[];
|
|
100
|
-
includeServer?: boolean;
|
|
101
|
-
type?: "string" | "object";
|
|
102
|
-
};
|
|
103
|
-
name?: {
|
|
104
|
-
format?: (data: {
|
|
105
|
-
method: Method;
|
|
106
|
-
path: string;
|
|
107
|
-
summary: string;
|
|
108
|
-
operationId: string;
|
|
109
|
-
}) => string | null;
|
|
110
|
-
prefix?: string;
|
|
111
|
-
useOperationId?: boolean;
|
|
112
|
-
};
|
|
113
|
-
doc?: IConfigDoc;
|
|
114
|
-
};
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export type IOpenApiSecuritySchemes = {
|
|
118
|
-
[key: string]: {
|
|
119
|
-
type: "http" | "apiKey" | "oauth2" | "openIdConnect" | "mutualTLS";
|
|
120
|
-
scheme?: "bearer" | "basic";
|
|
121
|
-
in?: "query" | "header" | "cookie";
|
|
122
|
-
flows?: {
|
|
123
|
-
authorizationCode: {
|
|
124
|
-
authorizationUrl: "https://example.com/auth";
|
|
125
|
-
tokenUrl: "https://example.com/token";
|
|
126
|
-
scopes: {
|
|
127
|
-
"read:data": "Grants read access";
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
};
|
|
131
|
-
bearerFormat?: "JWT";
|
|
132
|
-
openIdConnectUrl?: string;
|
|
133
|
-
name?: string;
|
|
134
|
-
};
|
|
135
|
-
};
|
|
File without changes
|
|
File without changes
|