api-core-lib 12.0.57 → 12.0.59
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/cli.cjs +250 -180
- package/package.json +3 -1
package/dist/cli.cjs
CHANGED
|
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
9
12
|
var __copyProps = (to, from, except, desc) => {
|
|
10
13
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
14
|
for (let key of __getOwnPropNames(from))
|
|
@@ -23,42 +26,161 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
26
|
mod
|
|
24
27
|
));
|
|
25
28
|
|
|
29
|
+
// node_modules/openapi-types/dist/index.js
|
|
30
|
+
var require_dist = __commonJS({
|
|
31
|
+
"node_modules/openapi-types/dist/index.js"(exports2) {
|
|
32
|
+
"use strict";
|
|
33
|
+
exports2.__esModule = true;
|
|
34
|
+
exports2.OpenAPIV2 = exports2.OpenAPIV3 = void 0;
|
|
35
|
+
var OpenAPIV32;
|
|
36
|
+
(function(OpenAPIV33) {
|
|
37
|
+
var HttpMethods;
|
|
38
|
+
(function(HttpMethods2) {
|
|
39
|
+
HttpMethods2["GET"] = "get";
|
|
40
|
+
HttpMethods2["PUT"] = "put";
|
|
41
|
+
HttpMethods2["POST"] = "post";
|
|
42
|
+
HttpMethods2["DELETE"] = "delete";
|
|
43
|
+
HttpMethods2["OPTIONS"] = "options";
|
|
44
|
+
HttpMethods2["HEAD"] = "head";
|
|
45
|
+
HttpMethods2["PATCH"] = "patch";
|
|
46
|
+
HttpMethods2["TRACE"] = "trace";
|
|
47
|
+
})(HttpMethods = OpenAPIV33.HttpMethods || (OpenAPIV33.HttpMethods = {}));
|
|
48
|
+
})(OpenAPIV32 = exports2.OpenAPIV3 || (exports2.OpenAPIV3 = {}));
|
|
49
|
+
var OpenAPIV2;
|
|
50
|
+
(function(OpenAPIV22) {
|
|
51
|
+
var HttpMethods;
|
|
52
|
+
(function(HttpMethods2) {
|
|
53
|
+
HttpMethods2["GET"] = "get";
|
|
54
|
+
HttpMethods2["PUT"] = "put";
|
|
55
|
+
HttpMethods2["POST"] = "post";
|
|
56
|
+
HttpMethods2["DELETE"] = "delete";
|
|
57
|
+
HttpMethods2["OPTIONS"] = "options";
|
|
58
|
+
HttpMethods2["HEAD"] = "head";
|
|
59
|
+
HttpMethods2["PATCH"] = "patch";
|
|
60
|
+
})(HttpMethods = OpenAPIV22.HttpMethods || (OpenAPIV22.HttpMethods = {}));
|
|
61
|
+
})(OpenAPIV2 = exports2.OpenAPIV2 || (exports2.OpenAPIV2 = {}));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
26
65
|
// src/cli.ts
|
|
27
66
|
var import_commander = require("commander");
|
|
28
|
-
var
|
|
67
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
29
68
|
|
|
30
69
|
// src/generator/index.ts
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
var
|
|
70
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
71
|
+
var import_path = __toESM(require("path"), 1);
|
|
72
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
34
73
|
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
74
|
+
var import_swagger_parser = __toESM(require("@apidevtools/swagger-parser"), 1);
|
|
75
|
+
var import_openapi_types = __toESM(require_dist(), 1);
|
|
76
|
+
var import_json_schema_to_typescript = require("json-schema-to-typescript");
|
|
77
|
+
function preprocessSpec(spec) {
|
|
78
|
+
if (!spec.components) spec.components = {};
|
|
79
|
+
if (!spec.components.schemas) spec.components.schemas = {};
|
|
80
|
+
const schemas = spec.components.schemas;
|
|
81
|
+
for (const apiPath in spec.paths) {
|
|
82
|
+
const pathItem = spec.paths[apiPath];
|
|
83
|
+
if (!pathItem) continue;
|
|
84
|
+
for (const method in pathItem) {
|
|
85
|
+
if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
|
|
86
|
+
const endpoint = pathItem[method];
|
|
87
|
+
const baseName = _generateBaseNameForSchema(method, apiPath, endpoint.operationId);
|
|
88
|
+
const requestBody = endpoint.requestBody;
|
|
89
|
+
if (requestBody?.content?.["application/json"]?.schema) {
|
|
90
|
+
requestBody.content["application/json"].schema = _normalizeSchema(
|
|
91
|
+
requestBody.content["application/json"].schema,
|
|
92
|
+
schemas,
|
|
93
|
+
baseName,
|
|
94
|
+
"Request"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (endpoint.responses) {
|
|
98
|
+
for (const statusCode in endpoint.responses) {
|
|
99
|
+
const response = endpoint.responses[statusCode];
|
|
100
|
+
const mediaTypeObject = response.content?.["application/json"];
|
|
101
|
+
if (mediaTypeObject?.schema) {
|
|
102
|
+
mediaTypeObject.schema = _normalizeSchema(
|
|
103
|
+
mediaTypeObject.schema,
|
|
104
|
+
// مرر المخطط الأصلي
|
|
105
|
+
schemas,
|
|
106
|
+
baseName,
|
|
107
|
+
`Response${statusCode}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return spec;
|
|
115
|
+
}
|
|
116
|
+
function _normalizeSchema(schema, schemas, baseName, suffix) {
|
|
117
|
+
if (!schema || "$ref" in schema) {
|
|
118
|
+
return schema;
|
|
119
|
+
}
|
|
120
|
+
if (schema.type === "array" && schema.items) {
|
|
121
|
+
schema.items = _normalizeSchema(schema.items, schemas, baseName, suffix.replace("[]", "Item"));
|
|
122
|
+
return schema;
|
|
123
|
+
}
|
|
124
|
+
if (schema.type === "object" && schema.properties) {
|
|
125
|
+
const typeName = `${_toPascalCase(baseName)}${_toPascalCase(suffix)}Dto`;
|
|
126
|
+
if (!schemas[typeName]) {
|
|
127
|
+
schemas[typeName] = schema;
|
|
128
|
+
for (const propName in schema.properties) {
|
|
129
|
+
schema.properties[propName] = _normalizeSchema(
|
|
130
|
+
schema.properties[propName],
|
|
131
|
+
schemas,
|
|
132
|
+
baseName,
|
|
133
|
+
`${_toPascalCase(propName)}Property`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { $ref: `#/components/schemas/${typeName}` };
|
|
138
|
+
}
|
|
139
|
+
return schema;
|
|
140
|
+
}
|
|
141
|
+
function _generateBaseNameForSchema(method, path3, operationId) {
|
|
142
|
+
if (operationId) return _toPascalCase(operationId.replace(/_v\d+$/, ""));
|
|
143
|
+
const pathPart = path3.replace(/[\/{}]/g, " ").trim();
|
|
144
|
+
return `${_toPascalCase(method)} ${_toPascalCase(pathPart)}`;
|
|
145
|
+
}
|
|
38
146
|
function parseSpecToModules(spec) {
|
|
39
147
|
const modules = {};
|
|
40
148
|
for (const apiPath in spec.paths) {
|
|
41
|
-
|
|
42
|
-
|
|
149
|
+
const pathItem = spec.paths[apiPath];
|
|
150
|
+
if (!pathItem) continue;
|
|
151
|
+
for (const method in pathItem) {
|
|
152
|
+
if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
|
|
153
|
+
const endpoint = pathItem[method];
|
|
43
154
|
if (!endpoint.tags || endpoint.tags.length === 0) continue;
|
|
44
155
|
const tagName = endpoint.tags[0];
|
|
45
|
-
const moduleName =
|
|
156
|
+
const moduleName = _sanitizeTagName(tagName) + "Api";
|
|
46
157
|
if (!modules[moduleName]) {
|
|
47
|
-
|
|
48
|
-
|
|
158
|
+
modules[moduleName] = { baseEndpoint: _findCommonBasePath(spec, tagName), actions: {}, types: /* @__PURE__ */ new Set() };
|
|
159
|
+
}
|
|
160
|
+
const currentModule = modules[moduleName];
|
|
161
|
+
const successResponseKey = Object.keys(endpoint.responses).find((code) => code.startsWith("2"));
|
|
162
|
+
const successResponse = successResponseKey ? endpoint.responses[successResponseKey] : void 0;
|
|
163
|
+
const responseSchema = successResponse?.content?.["application/json"]?.schema;
|
|
164
|
+
const outputType = successResponseKey === "204" ? "void" : _extractTypeNameFromSchema(responseSchema);
|
|
165
|
+
const requestBody = endpoint.requestBody;
|
|
166
|
+
const requestSchema = requestBody?.content?.["application/json"]?.schema;
|
|
167
|
+
let inputType = "undefined";
|
|
168
|
+
if (requestSchema) {
|
|
169
|
+
inputType = _extractTypeNameFromSchema(requestSchema);
|
|
170
|
+
} else if ((endpoint.parameters || []).some((p) => p.in === "query")) {
|
|
171
|
+
inputType = "QueryOptions";
|
|
49
172
|
}
|
|
50
|
-
const { inputType, outputType } = getInputOutputTypes(endpoint);
|
|
51
173
|
[inputType, outputType].forEach((t) => {
|
|
52
|
-
if (t && !["unknown", "undefined", "any", "QueryOptions", "Promise"].includes(t)) {
|
|
53
|
-
|
|
174
|
+
if (t && !["unknown", "undefined", "void", "any", "QueryOptions", "Promise"].includes(t)) {
|
|
175
|
+
currentModule.types.add(t.replace("[]", ""));
|
|
54
176
|
}
|
|
55
177
|
});
|
|
56
|
-
const actionName =
|
|
57
|
-
const relativePath = apiPath.replace(
|
|
58
|
-
|
|
178
|
+
const actionName = _sanitizeActionName(endpoint.operationId, method, apiPath);
|
|
179
|
+
const relativePath = apiPath.replace(currentModule.baseEndpoint, "").replace(/^\//, "");
|
|
180
|
+
currentModule.actions[actionName] = {
|
|
59
181
|
method: method.toUpperCase(),
|
|
60
|
-
path: relativePath,
|
|
61
|
-
description: endpoint.summary || "
|
|
182
|
+
path: relativePath === "" ? "/" : relativePath,
|
|
183
|
+
description: endpoint.summary || "",
|
|
62
184
|
hasQuery: (endpoint.parameters || []).some((p) => p.in === "query"),
|
|
63
185
|
autoFetch: method.toUpperCase() === "GET" && !apiPath.includes("{"),
|
|
64
186
|
invalidates: [],
|
|
@@ -69,104 +191,77 @@ function parseSpecToModules(spec) {
|
|
|
69
191
|
}
|
|
70
192
|
return modules;
|
|
71
193
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
} else if (successResponseSchema.type === "array" && successResponseSchema.items?.$ref) {
|
|
80
|
-
outputType = `${refToTypeName(successResponseSchema.items.$ref)}[]`;
|
|
194
|
+
function _extractTypeNameFromSchema(schema) {
|
|
195
|
+
if (!schema) return "unknown";
|
|
196
|
+
if ("$ref" in schema && schema.$ref) return _refToTypeName(schema.$ref);
|
|
197
|
+
if (!("$ref" in schema)) {
|
|
198
|
+
if (schema.type === "array" && schema.items) {
|
|
199
|
+
const itemType = _extractTypeNameFromSchema(schema.items);
|
|
200
|
+
return itemType !== "unknown" ? `${itemType}[]` : "unknown[]";
|
|
81
201
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (requestBodySchema) {
|
|
85
|
-
if (requestBodySchema.$ref) {
|
|
86
|
-
inputType = refToTypeName(requestBodySchema.$ref);
|
|
87
|
-
} else if (requestBodySchema.type === "object") {
|
|
88
|
-
inputType = "any";
|
|
202
|
+
if (schema.type && ["string", "number", "boolean", "integer"].includes(schema.type)) {
|
|
203
|
+
return schema.type === "integer" ? "number" : schema.type;
|
|
89
204
|
}
|
|
90
|
-
} else if ((endpoint.parameters || []).some((p) => p.in === "query")) {
|
|
91
|
-
inputType = "QueryOptions";
|
|
92
205
|
}
|
|
93
|
-
return
|
|
206
|
+
return "unknown";
|
|
94
207
|
}
|
|
95
|
-
function sanitizeTagName(tagName) {
|
|
96
|
-
return tagName.replace(/[^a-zA-Z0-9]/g, "").replace(/Central|Tenant/g, "");
|
|
97
|
-
}
|
|
98
|
-
function sanitizeActionName(operationId) {
|
|
99
|
-
if (!operationId) return `unnamedAction_${Date.now()}`;
|
|
100
|
-
const name = operationId.split("_").slice(1).join("_");
|
|
101
|
-
return name.charAt(0).toLowerCase() + name.slice(1).replace(/_v\d+$/, "");
|
|
102
|
-
}
|
|
103
|
-
function refToTypeName(ref) {
|
|
104
|
-
if (!ref) return "unknown";
|
|
105
|
-
return ref.split("/").pop() || "unknown";
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// src/generator/file-generator.ts
|
|
109
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
110
|
-
var import_path = __toESM(require("path"), 1);
|
|
111
|
-
var import_chalk = __toESM(require("chalk"), 1);
|
|
112
|
-
var import_json_schema_to_typescript = require("json-schema-to-typescript");
|
|
113
208
|
async function generateModuleFiles(moduleName, moduleData, spec, outputDir) {
|
|
114
|
-
console.log(import_chalk.default.
|
|
115
|
-
Generating module: ${moduleName}`));
|
|
209
|
+
console.log(import_chalk.default.gray(` Generating files for module: ${import_chalk.default.bold(moduleName)}...`));
|
|
116
210
|
const moduleFolderPath = import_path.default.join(outputDir, moduleName);
|
|
117
211
|
if (!import_fs.default.existsSync(moduleFolderPath)) {
|
|
118
212
|
import_fs.default.mkdirSync(moduleFolderPath, { recursive: true });
|
|
119
213
|
}
|
|
120
|
-
await
|
|
121
|
-
await
|
|
214
|
+
await _generateTypesFile(moduleFolderPath, moduleName, moduleData.types, spec);
|
|
215
|
+
await _generateConfigFile(moduleFolderPath, moduleName, moduleData);
|
|
122
216
|
}
|
|
123
|
-
async function
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
217
|
+
async function _generateTypesFile(moduleFolderPath, moduleName, typeNames, spec) {
|
|
218
|
+
if (typeNames.size === 0) {
|
|
219
|
+
console.log(import_chalk.default.yellow(` - No types found for module "${moduleName}". Skipping types.ts generation.`));
|
|
220
|
+
const typesFilePath2 = import_path.default.join(moduleFolderPath, "types.ts");
|
|
221
|
+
import_fs.default.writeFileSync(typesFilePath2, `// No types found for this module.
|
|
222
|
+
`);
|
|
223
|
+
return;
|
|
129
224
|
}
|
|
225
|
+
console.log(import_chalk.default.gray(` - Generating types.ts with ${typeNames.size} types...`));
|
|
130
226
|
let typesContent = `// This file is auto-generated by the API generator. Do not edit.
|
|
131
227
|
|
|
132
228
|
`;
|
|
133
229
|
const allSchemas = spec.components?.schemas || {};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
230
|
+
const compilationOptions = {
|
|
231
|
+
bannerComment: "",
|
|
232
|
+
style: { bracketSpacing: true, printWidth: 120, semi: true, singleQuote: true, tabWidth: 2, trailingComma: "es5", useTabs: false },
|
|
233
|
+
additionalProperties: false,
|
|
234
|
+
declareExternallyReferenced: true
|
|
235
|
+
};
|
|
236
|
+
const rootSchemaForCompilation = {
|
|
237
|
+
$id: "allSchemas",
|
|
238
|
+
definitions: allSchemas,
|
|
239
|
+
type: "object",
|
|
240
|
+
// <-- الإصلاح هنا
|
|
241
|
+
properties: {}
|
|
242
|
+
};
|
|
243
|
+
for (const typeName of Array.from(typeNames).sort()) {
|
|
244
|
+
if (allSchemas[typeName]) {
|
|
137
245
|
try {
|
|
138
|
-
const tsType = await (0, import_json_schema_to_typescript.compile)(
|
|
139
|
-
bannerComment: "",
|
|
140
|
-
additionalProperties: false,
|
|
141
|
-
style: {
|
|
142
|
-
bracketSpacing: true,
|
|
143
|
-
printWidth: 120,
|
|
144
|
-
semi: true,
|
|
145
|
-
singleQuote: true,
|
|
146
|
-
tabWidth: 2,
|
|
147
|
-
trailingComma: "es5",
|
|
148
|
-
useTabs: false
|
|
149
|
-
}
|
|
150
|
-
});
|
|
246
|
+
const tsType = await (0, import_json_schema_to_typescript.compile)(rootSchemaForCompilation, typeName, compilationOptions);
|
|
151
247
|
typesContent += tsType + "\n";
|
|
152
248
|
} catch (compileError) {
|
|
153
|
-
console.error(import_chalk.default.red(`
|
|
154
|
-
console.error(import_chalk.default.red(` ${compileError.message}`));
|
|
249
|
+
console.error(import_chalk.default.red(` - Error compiling type "${typeName}": ${compileError.message}`));
|
|
155
250
|
}
|
|
156
251
|
} else {
|
|
157
|
-
console.log(import_chalk.default.yellow(`
|
|
252
|
+
console.log(import_chalk.default.yellow(` - Warning: Schema for type "${typeName}" not found, skipping.`));
|
|
158
253
|
}
|
|
159
254
|
}
|
|
160
255
|
const typesFilePath = import_path.default.join(moduleFolderPath, "types.ts");
|
|
161
|
-
import_fs.default.writeFileSync(typesFilePath, typesContent);
|
|
256
|
+
import_fs.default.writeFileSync(typesFilePath, typesContent, { encoding: "utf-8" });
|
|
162
257
|
}
|
|
163
|
-
async function
|
|
164
|
-
const typeNamesArray = [...moduleData.types];
|
|
258
|
+
async function _generateConfigFile(moduleFolderPath, moduleName, moduleData) {
|
|
165
259
|
const actionsCount = Object.keys(moduleData.actions).length;
|
|
166
|
-
console.log(import_chalk.default.gray(`
|
|
167
|
-
const
|
|
260
|
+
console.log(import_chalk.default.gray(` - Generating config.ts with ${actionsCount} actions...`));
|
|
261
|
+
const typeNamesArray = [...moduleData.types].sort();
|
|
262
|
+
const typesImportStatement = typeNamesArray.length > 0 ? `import type { ${typeNamesArray.join(", ")} } from './types';` : `// No types to import for this module`;
|
|
168
263
|
const actionsTypeParts = Object.entries(moduleData.actions).map(
|
|
169
|
-
([actionName, actionData]) => ` ${actionName}: ActionConfigModule<${actionData._inputType}, ${actionData._outputType}>;`
|
|
264
|
+
([actionName, actionData]) => ` ${actionName}: ActionConfigModule<${actionData._inputType || "undefined"}, ${actionData._outputType || "unknown"}>;`
|
|
170
265
|
);
|
|
171
266
|
const actionsTypeDefinition = `{
|
|
172
267
|
${actionsTypeParts.join("\n")}
|
|
@@ -180,8 +275,10 @@ ${actionsTypeParts.join("\n")}
|
|
|
180
275
|
const actionsValueDefinition = `{
|
|
181
276
|
${actionsValueParts.join(",\n")}
|
|
182
277
|
}`;
|
|
183
|
-
const configContent =
|
|
184
|
-
|
|
278
|
+
const configContent = `/* eslint-disable */
|
|
279
|
+
// This file is auto-generated by the API generator. Do not edit.
|
|
280
|
+
|
|
281
|
+
import type { ApiModuleConfig, ActionConfigModule, QueryOptions } from 'api-core-lib'; // \u0627\u0641\u062A\u0631\u0636 \u0623\u0646 \u0647\u0630\u0627 \u0627\u0644\u0645\u0633\u0627\u0631 \u0635\u062D\u064A\u062D
|
|
185
282
|
${typesImportStatement}
|
|
186
283
|
|
|
187
284
|
export const ${moduleName}Module: ApiModuleConfig<${actionsTypeDefinition}> = {
|
|
@@ -190,104 +287,77 @@ export const ${moduleName}Module: ApiModuleConfig<${actionsTypeDefinition}> = {
|
|
|
190
287
|
};
|
|
191
288
|
`;
|
|
192
289
|
const configFilePath = import_path.default.join(moduleFolderPath, "config.ts");
|
|
193
|
-
import_fs.default.writeFileSync(configFilePath, configContent);
|
|
290
|
+
import_fs.default.writeFileSync(configFilePath, configContent.trim(), { encoding: "utf-8" });
|
|
194
291
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
function toPascalCase(str) {
|
|
198
|
-
return str.replace(/_v\d+$/, "").split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
292
|
+
function _toPascalCase(str) {
|
|
293
|
+
return str.replace(/[^a-zA-Z0-9]/g, " ").replace(/(?:^\w|[A-Z]|\b\w)/g, (word) => word.toUpperCase()).replace(/\s+/g, "");
|
|
199
294
|
}
|
|
200
|
-
function
|
|
201
|
-
if (!
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return schema;
|
|
295
|
+
function _refToTypeName(ref) {
|
|
296
|
+
if (!ref) return "unknown";
|
|
297
|
+
return ref.split("/").pop() || "unknown";
|
|
298
|
+
}
|
|
299
|
+
function _sanitizeTagName(tagName) {
|
|
300
|
+
return tagName.replace(/[^a-zA-Z0-9]/g, "").replace(/Central|Tenant/g, "");
|
|
301
|
+
}
|
|
302
|
+
function _sanitizeActionName(operationId, method, path3) {
|
|
303
|
+
if (operationId) {
|
|
304
|
+
const name = operationId.split("_").slice(1).join("_");
|
|
305
|
+
const sanitized = name.charAt(0).toLowerCase() + name.slice(1).replace(/_v\d+$/, "");
|
|
306
|
+
return sanitized || "action";
|
|
213
307
|
}
|
|
214
|
-
|
|
308
|
+
const pathPart = path3.replace(/[\/{}]/g, "_").replace(/^_|_$/g, "");
|
|
309
|
+
return `${method.toLowerCase()}_${pathPart}`;
|
|
215
310
|
}
|
|
216
|
-
function
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
for (const method in
|
|
221
|
-
const endpoint =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
if (endpoint.responses) {
|
|
234
|
-
for (const statusCode in endpoint.responses) {
|
|
235
|
-
const responseSchema = endpoint.responses[statusCode]?.content?.["application/json"]?.schema;
|
|
236
|
-
if (responseSchema) {
|
|
237
|
-
endpoint.responses[statusCode].content["application/json"].schema = normalizeSchema(
|
|
238
|
-
responseSchema,
|
|
239
|
-
spec.components.schemas,
|
|
240
|
-
operationId,
|
|
241
|
-
"Response"
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
311
|
+
function _findCommonBasePath(spec, tagName) {
|
|
312
|
+
const paths = Object.keys(spec.paths).filter((p) => {
|
|
313
|
+
const pathItem = spec.paths[p];
|
|
314
|
+
if (!pathItem) return false;
|
|
315
|
+
for (const method in pathItem) {
|
|
316
|
+
const endpoint = pathItem[method];
|
|
317
|
+
if (endpoint.tags?.includes(tagName)) return true;
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
});
|
|
321
|
+
if (paths.length === 0) return "/";
|
|
322
|
+
let commonPrefix = paths[0];
|
|
323
|
+
for (let i = 1; i < paths.length; i++) {
|
|
324
|
+
while (paths[i].indexOf(commonPrefix) !== 0) {
|
|
325
|
+
commonPrefix = commonPrefix.substring(0, commonPrefix.length - 1);
|
|
246
326
|
}
|
|
247
327
|
}
|
|
248
|
-
return
|
|
328
|
+
return commonPrefix.substring(0, commonPrefix.lastIndexOf("/") + 1) || "/";
|
|
249
329
|
}
|
|
250
|
-
|
|
251
|
-
// src/generator/index.ts
|
|
252
330
|
async function runGenerator(options) {
|
|
253
|
-
console.log(
|
|
254
|
-
console.log(import_chalk2.default.gray(`Output directory: ${options.output}`));
|
|
255
|
-
console.log(import_chalk2.default.gray(`.env path: ${options.envPath}`));
|
|
256
|
-
console.log("\n" + import_chalk2.default.blue("Step 1: Loading environment variables..."));
|
|
331
|
+
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Core Lib Code Generator..."));
|
|
257
332
|
import_dotenv.default.config({ path: options.envPath });
|
|
258
333
|
const specUrl = getSpecUrl();
|
|
259
|
-
console.log(
|
|
334
|
+
console.log(import_chalk.default.blue("\u2713 Step 1: Environment variables loaded."));
|
|
260
335
|
try {
|
|
261
|
-
console.log(
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
console.log(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
console.log(
|
|
271
|
-
console.log(import_chalk2.default.blue("Step 2.5: Dereferencing all $refs in the spec..."));
|
|
272
|
-
const dereferencedSpec = await import_json_schema_ref_parser.default.dereference(normalizedSpec);
|
|
273
|
-
console.log(import_chalk2.default.green("\u2713 Spec dereferenced successfully."));
|
|
274
|
-
console.log("\n" + import_chalk2.default.blue("Step 3: Parsing spec and generating API modules..."));
|
|
336
|
+
console.log(import_chalk.default.blue(`
|
|
337
|
+
\u23F3 Step 2: Fetching and validating spec from ${specUrl}...`));
|
|
338
|
+
const initialSpec = await import_swagger_parser.default.validate(specUrl, {
|
|
339
|
+
dereference: { circular: "ignore" }
|
|
340
|
+
});
|
|
341
|
+
console.log(import_chalk.default.green("\u2713 Spec fetched and validated successfully."));
|
|
342
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 3: Preprocessing spec to normalize inline schemas..."));
|
|
343
|
+
const normalizedSpec = preprocessSpec(initialSpec);
|
|
344
|
+
console.log(import_chalk.default.green("\u2713 Spec has been normalized successfully."));
|
|
345
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 4: Parsing spec and generating API modules structure..."));
|
|
275
346
|
const modules = parseSpecToModules(normalizedSpec);
|
|
276
347
|
const modulesCount = Object.keys(modules).length;
|
|
277
|
-
console.log(
|
|
348
|
+
console.log(import_chalk.default.green(`\u2713 Found ${modulesCount} modules to generate.`));
|
|
278
349
|
if (modulesCount === 0) {
|
|
279
|
-
console.log(
|
|
350
|
+
console.log(import_chalk.default.yellow("Warning: No modules were found in the spec."));
|
|
280
351
|
}
|
|
281
|
-
|
|
352
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 5: Generating module files..."));
|
|
353
|
+
const modulesOutputPath = import_path.default.join(options.output, "modules");
|
|
282
354
|
for (const moduleName in modules) {
|
|
283
355
|
const moduleData = modules[moduleName];
|
|
284
|
-
await generateModuleFiles(moduleName, moduleData,
|
|
285
|
-
}
|
|
286
|
-
if (modulesCount > 0) {
|
|
287
|
-
console.log(import_chalk2.default.green("\u2713 All custom modules generated."));
|
|
356
|
+
await generateModuleFiles(moduleName, moduleData, normalizedSpec, modulesOutputPath);
|
|
288
357
|
}
|
|
289
|
-
console.log(
|
|
290
|
-
console.log(
|
|
358
|
+
console.log(import_chalk.default.green("\u2713 All module files generated."));
|
|
359
|
+
console.log(import_chalk.default.bold.green("\n\u{1F389} API generation complete!"));
|
|
360
|
+
console.log(import_chalk.default.bold.cyan(` Output directory: ${options.output}`));
|
|
291
361
|
} catch (error) {
|
|
292
362
|
handleGenerationError(error);
|
|
293
363
|
}
|
|
@@ -295,24 +365,24 @@ async function runGenerator(options) {
|
|
|
295
365
|
function getSpecUrl() {
|
|
296
366
|
const specUrl = process.env.OPENAPI_SPEC_URL || (process.env.API_URL ? `${process.env.API_URL}/docs-json` : null) || (process.env.NEXT_PUBLIC_API_URL ? `${process.env.NEXT_PUBLIC_API_URL}/docs-json` : null);
|
|
297
367
|
if (!specUrl) {
|
|
298
|
-
console.error(
|
|
368
|
+
console.error(import_chalk.default.red.bold("\n\u274C Error: API specification URL not found."));
|
|
299
369
|
process.exit(1);
|
|
300
370
|
}
|
|
301
371
|
return specUrl;
|
|
302
372
|
}
|
|
303
373
|
function handleGenerationError(error) {
|
|
304
|
-
console.error(
|
|
305
|
-
console.error(
|
|
374
|
+
console.error(import_chalk.default.red.bold("\n\u274C An error occurred during generation:"));
|
|
375
|
+
console.error(import_chalk.default.red(`Error Message: ${error.message}`));
|
|
306
376
|
if (error.stack) {
|
|
307
|
-
console.error(
|
|
377
|
+
console.error(import_chalk.default.gray(error.stack));
|
|
308
378
|
}
|
|
309
379
|
process.exit(1);
|
|
310
380
|
}
|
|
311
381
|
|
|
312
382
|
// src/cli.ts
|
|
313
383
|
console.log("API Core Lib - Code Generator");
|
|
314
|
-
import_commander.program.option("-o, --output <path>", "Output directory for generated files", "src/lib/api-generated").option("--env-path <path>", ".env file path",
|
|
315
|
-
const absoluteOutputPath =
|
|
384
|
+
import_commander.program.option("-o, --output <path>", "Output directory for generated files", "src/lib/api-generated").option("--env-path <path>", ".env file path", import_path2.default.resolve(process.cwd(), ".env")).action((options) => {
|
|
385
|
+
const absoluteOutputPath = import_path2.default.resolve(process.cwd(), options.output);
|
|
316
386
|
runGenerator({ ...options, output: absoluteOutputPath });
|
|
317
387
|
});
|
|
318
388
|
import_commander.program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "api-core-lib",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.59",
|
|
4
4
|
"description": "A flexible and powerful API client library for modern web applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@apidevtools/json-schema-ref-parser": "^14.2.0",
|
|
39
|
+
"@apidevtools/swagger-parser": "^12.0.0",
|
|
39
40
|
"axios": "^1.6.8",
|
|
40
41
|
"axios-retry": "^4.1.0",
|
|
41
42
|
"chalk": "^4.1.2",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"fs-extra": "^11.3.1",
|
|
47
48
|
"json-schema-to-typescript": "^15.0.4",
|
|
48
49
|
"openapi-typescript": "^6.2.4",
|
|
50
|
+
"openapi-typescript-codegen": "^0.29.0",
|
|
49
51
|
"path": "^0.12.7",
|
|
50
52
|
"uuid": "^9.0.1"
|
|
51
53
|
},
|