api-core-lib 12.0.65 → 12.0.66
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 +56 -63
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -76,32 +76,34 @@ var import_openapi_types = __toESM(require_dist(), 1);
|
|
|
76
76
|
var import_json_schema_to_typescript = require("json-schema-to-typescript");
|
|
77
77
|
function parseSpecToModules(spec) {
|
|
78
78
|
const modules = {};
|
|
79
|
+
const modulePaths = {};
|
|
79
80
|
if (!spec.components) spec.components = {};
|
|
80
81
|
if (!spec.components.schemas) spec.components.schemas = {};
|
|
82
|
+
const allSchemas = spec.components.schemas;
|
|
81
83
|
for (const apiPath in spec.paths) {
|
|
82
84
|
const pathItem = spec.paths[apiPath];
|
|
83
85
|
if (!pathItem) continue;
|
|
84
86
|
for (const method in pathItem) {
|
|
85
87
|
if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
|
|
86
88
|
const endpoint = pathItem[method];
|
|
87
|
-
if (!endpoint.
|
|
88
|
-
const
|
|
89
|
-
const moduleName = _sanitizeTagName(tagName) + "Api";
|
|
89
|
+
if (!endpoint.operationId) continue;
|
|
90
|
+
const moduleName = _getModuleNameFromOperationId(endpoint.operationId);
|
|
90
91
|
if (!modules[moduleName]) {
|
|
91
|
-
modules[moduleName] = { baseEndpoint:
|
|
92
|
+
modules[moduleName] = { baseEndpoint: "", actions: {}, types: /* @__PURE__ */ new Set() };
|
|
93
|
+
modulePaths[moduleName] = [];
|
|
92
94
|
}
|
|
93
|
-
|
|
94
|
-
const { inputType, outputType } = _extractInputOutputTypes(endpoint,
|
|
95
|
+
modulePaths[moduleName].push(apiPath);
|
|
96
|
+
const { inputType, outputType } = _extractInputOutputTypes(endpoint, allSchemas);
|
|
95
97
|
[inputType, outputType].forEach((t) => {
|
|
96
98
|
if (t && !["unknown", "undefined", "void", "any", "QueryOptions", "Promise"].includes(t)) {
|
|
97
|
-
|
|
99
|
+
modules[moduleName].types.add(t.replace("[]", ""));
|
|
98
100
|
}
|
|
99
101
|
});
|
|
100
|
-
const actionName = _sanitizeActionName(endpoint.operationId
|
|
101
|
-
|
|
102
|
-
currentModule.actions[actionName] = {
|
|
102
|
+
const actionName = _sanitizeActionName(endpoint.operationId);
|
|
103
|
+
modules[moduleName].actions[actionName] = {
|
|
103
104
|
method: method.toUpperCase(),
|
|
104
|
-
path:
|
|
105
|
+
path: apiPath,
|
|
106
|
+
// سنقوم بتعديل هذا لاحقًا ليصبح نسبيًا
|
|
105
107
|
description: endpoint.summary || "",
|
|
106
108
|
hasQuery: (endpoint.parameters || []).some((p) => p.in === "query"),
|
|
107
109
|
autoFetch: method.toUpperCase() === "GET" && !apiPath.includes("{"),
|
|
@@ -111,6 +113,15 @@ function parseSpecToModules(spec) {
|
|
|
111
113
|
};
|
|
112
114
|
}
|
|
113
115
|
}
|
|
116
|
+
for (const moduleName in modules) {
|
|
117
|
+
const basePath = _findCommonBasePath(modulePaths[moduleName]);
|
|
118
|
+
modules[moduleName].baseEndpoint = basePath;
|
|
119
|
+
for (const actionName in modules[moduleName].actions) {
|
|
120
|
+
const action = modules[moduleName].actions[actionName];
|
|
121
|
+
const relativePath = action.path.replace(basePath, "").replace(/^\//, "");
|
|
122
|
+
action.path = relativePath === "" ? "/" : relativePath;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
114
125
|
return modules;
|
|
115
126
|
}
|
|
116
127
|
function _extractInputOutputTypes(endpoint, schemas) {
|
|
@@ -136,7 +147,7 @@ function _schemaToTypeName(schema, name, schemas) {
|
|
|
136
147
|
return `${itemTypeName}[]`;
|
|
137
148
|
}
|
|
138
149
|
if (schema.type === "object" || schema.properties || schema.allOf) {
|
|
139
|
-
const typeName = _toPascalCase(name)
|
|
150
|
+
const typeName = _toPascalCase(name);
|
|
140
151
|
if (!schemas[typeName]) {
|
|
141
152
|
schemas[typeName] = schema;
|
|
142
153
|
}
|
|
@@ -145,6 +156,13 @@ function _schemaToTypeName(schema, name, schemas) {
|
|
|
145
156
|
if (schema.type && ["string", "number", "boolean", "integer"].includes(schema.type)) {
|
|
146
157
|
return schema.type === "integer" ? "number" : schema.type;
|
|
147
158
|
}
|
|
159
|
+
if (Object.keys(schema).length === 0) {
|
|
160
|
+
const typeName = _toPascalCase(name);
|
|
161
|
+
if (!schemas[typeName]) {
|
|
162
|
+
schemas[typeName] = { type: "object", properties: {}, description: "Represents a dynamic or empty object." };
|
|
163
|
+
}
|
|
164
|
+
return typeName;
|
|
165
|
+
}
|
|
148
166
|
return "unknown";
|
|
149
167
|
}
|
|
150
168
|
async function generateModuleFiles(moduleName, moduleData, allSchemas, outputDir) {
|
|
@@ -156,7 +174,7 @@ async function generateModuleFiles(moduleName, moduleData, allSchemas, outputDir
|
|
|
156
174
|
}
|
|
157
175
|
async function _generateTypesFile(moduleFolderPath, moduleName, typeNames, allSchemas) {
|
|
158
176
|
if (typeNames.size === 0) {
|
|
159
|
-
console.log(import_chalk.default.yellow(` - No types
|
|
177
|
+
console.log(import_chalk.default.yellow(` - No types for module "${moduleName}". Skipping types.ts.`));
|
|
160
178
|
return;
|
|
161
179
|
}
|
|
162
180
|
console.log(import_chalk.default.gray(` - Generating types.ts with ${typeNames.size} types...`));
|
|
@@ -178,7 +196,7 @@ async function _generateTypesFile(moduleFolderPath, moduleName, typeNames, allSc
|
|
|
178
196
|
console.error(import_chalk.default.red(` - Error compiling type "${typeName}": ${compileError.message}`));
|
|
179
197
|
}
|
|
180
198
|
} else {
|
|
181
|
-
console.log(import_chalk.default.yellow(` - Warning: Schema for type "${typeName}" not found
|
|
199
|
+
console.log(import_chalk.default.yellow(` - Warning: Schema for type "${typeName}" not found.`));
|
|
182
200
|
}
|
|
183
201
|
}
|
|
184
202
|
const typesFilePath = import_path.default.join(moduleFolderPath, "types.ts");
|
|
@@ -219,54 +237,42 @@ export const ${moduleName}Module: ApiModuleConfig<${actionsTypeDefinition}> = {
|
|
|
219
237
|
function _toPascalCase(str) {
|
|
220
238
|
return str.replace(/[^a-zA-Z0-9]/g, " ").replace(/(?:^\w|[A-Z]|\b\w)/g, (w) => w.toUpperCase()).replace(/\s+/g, "");
|
|
221
239
|
}
|
|
222
|
-
function
|
|
223
|
-
|
|
240
|
+
function _getModuleNameFromOperationId(operationId) {
|
|
241
|
+
const controllerName = operationId.split("_")[0].replace(/Controller$/, "");
|
|
242
|
+
return `${controllerName}Api`;
|
|
224
243
|
}
|
|
225
|
-
function _sanitizeActionName(operationId
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
const pathPart = path3.replace(/[\/{}]/g, "_").replace(/^_|_$/g, "");
|
|
232
|
-
return `${method.toLowerCase()}_${pathPart}`;
|
|
244
|
+
function _sanitizeActionName(operationId) {
|
|
245
|
+
const nameParts = operationId.split("_");
|
|
246
|
+
if (nameParts.length <= 1) return operationId;
|
|
247
|
+
const actionPart = nameParts[1];
|
|
248
|
+
return actionPart.charAt(0).toLowerCase() + actionPart.slice(1);
|
|
233
249
|
}
|
|
234
|
-
function _findCommonBasePath(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
return false;
|
|
243
|
-
});
|
|
244
|
-
if (paths.length === 0) return "/";
|
|
245
|
-
let commonPrefix = paths[0];
|
|
246
|
-
for (let i = 1; i < paths.length; i++) {
|
|
247
|
-
while (paths[i].indexOf(commonPrefix) !== 0) {
|
|
248
|
-
commonPrefix = commonPrefix.substring(0, commonPrefix.length - 1);
|
|
249
|
-
}
|
|
250
|
+
function _findCommonBasePath(paths) {
|
|
251
|
+
if (!paths || paths.length === 0) return "/";
|
|
252
|
+
const sortedPaths = [...paths].sort();
|
|
253
|
+
const first = sortedPaths[0];
|
|
254
|
+
const last = sortedPaths[sortedPaths.length - 1];
|
|
255
|
+
let i = 0;
|
|
256
|
+
while (i < first.length && first.charAt(i) === last.charAt(i)) {
|
|
257
|
+
i++;
|
|
250
258
|
}
|
|
251
|
-
|
|
259
|
+
let prefix = first.substring(0, i);
|
|
260
|
+
return prefix.substring(0, prefix.lastIndexOf("/") + 1) || "/";
|
|
252
261
|
}
|
|
253
262
|
async function runGenerator(options) {
|
|
254
263
|
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Core Lib Code Generator..."));
|
|
255
264
|
import_dotenv.default.config({ path: options.envPath });
|
|
256
|
-
const specUrl =
|
|
265
|
+
const specUrl = process.env.OPENAPI_SPEC_URL || "./swagger.json";
|
|
257
266
|
console.log(import_chalk.default.blue("\u2713 Step 1: Environment variables loaded."));
|
|
258
267
|
try {
|
|
259
268
|
console.log(import_chalk.default.blue(`
|
|
260
269
|
\u23F3 Step 2: Fetching and fully dereferencing spec from ${specUrl}...`));
|
|
261
270
|
const dereferencedSpec = await import_swagger_parser.default.dereference(specUrl);
|
|
262
271
|
console.log(import_chalk.default.green("\u2713 Spec fetched and fully dereferenced successfully."));
|
|
263
|
-
console.log(import_chalk.default.blue("\n\u23F3 Step 3: Parsing spec
|
|
272
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 3: Parsing spec using intelligent grouping..."));
|
|
264
273
|
const modules = parseSpecToModules(dereferencedSpec);
|
|
265
274
|
const modulesCount = Object.keys(modules).length;
|
|
266
|
-
console.log(import_chalk.default.green(`\u2713 Found ${modulesCount} modules
|
|
267
|
-
if (modulesCount === 0) {
|
|
268
|
-
console.log(import_chalk.default.yellow("Warning: No modules were found in the spec."));
|
|
269
|
-
}
|
|
275
|
+
console.log(import_chalk.default.green(`\u2713 Found and grouped ${modulesCount} logical modules.`));
|
|
270
276
|
console.log(import_chalk.default.blue("\n\u23F3 Step 4: Generating module files..."));
|
|
271
277
|
const modulesOutputPath = import_path.default.join(options.output, "modules");
|
|
272
278
|
const allSchemas = dereferencedSpec.components?.schemas || {};
|
|
@@ -278,24 +284,11 @@ async function runGenerator(options) {
|
|
|
278
284
|
console.log(import_chalk.default.bold.green("\n\u{1F389} API generation complete!"));
|
|
279
285
|
console.log(import_chalk.default.bold.cyan(` Output directory: ${options.output}`));
|
|
280
286
|
} catch (error) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
function getSpecUrl() {
|
|
285
|
-
const specUrl = process.env.OPENAPI_SPEC_URL || "./swagger.json";
|
|
286
|
-
if (!specUrl) {
|
|
287
|
-
console.error(import_chalk.default.red.bold("\n\u274C Error: API specification URL not found."));
|
|
287
|
+
console.error(import_chalk.default.red.bold("\n\u274C An error occurred during generation:"));
|
|
288
|
+
console.error(import_chalk.default.red(`Error Message: ${error.message}`));
|
|
289
|
+
if (error.stack) console.error(import_chalk.default.gray(error.stack));
|
|
288
290
|
process.exit(1);
|
|
289
291
|
}
|
|
290
|
-
return specUrl;
|
|
291
|
-
}
|
|
292
|
-
function handleGenerationError(error) {
|
|
293
|
-
console.error(import_chalk.default.red.bold("\n\u274C An error occurred during generation:"));
|
|
294
|
-
console.error(import_chalk.default.red(`Error Message: ${error.message}`));
|
|
295
|
-
if (error.stack) {
|
|
296
|
-
console.error(import_chalk.default.gray(error.stack));
|
|
297
|
-
}
|
|
298
|
-
process.exit(1);
|
|
299
292
|
}
|
|
300
293
|
|
|
301
294
|
// src/cli.ts
|