api-core-lib 12.0.66 → 12.0.67
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 +221 -141
- package/package.json +7 -4
package/dist/cli.cjs
CHANGED
|
@@ -69,17 +69,42 @@ var import_path2 = __toESM(require("path"), 1);
|
|
|
69
69
|
// src/generator/index.ts
|
|
70
70
|
var import_fs = __toESM(require("fs"), 1);
|
|
71
71
|
var import_path = __toESM(require("path"), 1);
|
|
72
|
+
var import_util = __toESM(require("util"), 1);
|
|
72
73
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
73
74
|
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
74
75
|
var import_swagger_parser = __toESM(require("@apidevtools/swagger-parser"), 1);
|
|
75
76
|
var import_openapi_types = __toESM(require_dist(), 1);
|
|
76
77
|
var import_json_schema_to_typescript = require("json-schema-to-typescript");
|
|
78
|
+
var DEBUG_MODE = process.env.DEBUG === "true";
|
|
79
|
+
var debugLog = (title, data) => {
|
|
80
|
+
if (DEBUG_MODE) {
|
|
81
|
+
console.log(import_chalk.default.yellow(`
|
|
82
|
+
[DEBUG: ${title}]`));
|
|
83
|
+
console.log(import_util.default.inspect(data, { depth: null, colors: true }));
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var toPascalCase = (str) => str.replace(/[^a-zA-Z0-9_]/g, " ").replace(/(?:^\w|[A-Z]|\b\w)/g, (w) => w.toUpperCase()).replace(/\s+/g, "");
|
|
87
|
+
var getModuleNameFromOpId = (opId) => `${opId.split("_")[0].replace(/Controller$/, "")}Api`;
|
|
88
|
+
var getActionNameFromOpId = (opId) => (opId.split("_")[1] || opId).replace(/^\w/, (c) => c.toLowerCase());
|
|
89
|
+
var findCommonBasePath = (paths) => {
|
|
90
|
+
if (!paths || paths.length === 0) return "/";
|
|
91
|
+
const sorted = [...paths].sort();
|
|
92
|
+
const first = sorted[0];
|
|
93
|
+
const last = sorted[sorted.length - 1];
|
|
94
|
+
let i = 0;
|
|
95
|
+
while (i < first.length && first.charAt(i) === last.charAt(i)) i++;
|
|
96
|
+
const prefix = first.substring(0, i);
|
|
97
|
+
return prefix.substring(0, prefix.lastIndexOf("/") + 1) || "/";
|
|
98
|
+
};
|
|
77
99
|
function parseSpecToModules(spec) {
|
|
78
|
-
const modules =
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
|
|
100
|
+
const modules = /* @__PURE__ */ new Map();
|
|
101
|
+
const allSchemas = /* @__PURE__ */ new Map();
|
|
102
|
+
const modulePaths = /* @__PURE__ */ new Map();
|
|
103
|
+
if (spec.components?.schemas) {
|
|
104
|
+
for (const schemaName in spec.components.schemas) {
|
|
105
|
+
allSchemas.set(schemaName, { name: schemaName, schema: spec.components.schemas[schemaName] });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
83
108
|
for (const apiPath in spec.paths) {
|
|
84
109
|
const pathItem = spec.paths[apiPath];
|
|
85
110
|
if (!pathItem) continue;
|
|
@@ -87,206 +112,261 @@ function parseSpecToModules(spec) {
|
|
|
87
112
|
if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
|
|
88
113
|
const endpoint = pathItem[method];
|
|
89
114
|
if (!endpoint.operationId) continue;
|
|
90
|
-
const moduleName =
|
|
91
|
-
if (!modules
|
|
92
|
-
modules
|
|
93
|
-
modulePaths
|
|
115
|
+
const moduleName = getModuleNameFromOpId(endpoint.operationId);
|
|
116
|
+
if (!modules.has(moduleName)) {
|
|
117
|
+
modules.set(moduleName, { moduleName, baseEndpoint: "", actions: {}, schemas: /* @__PURE__ */ new Set() });
|
|
118
|
+
modulePaths.set(moduleName, []);
|
|
94
119
|
}
|
|
95
|
-
|
|
96
|
-
|
|
120
|
+
const currentModule = modules.get(moduleName);
|
|
121
|
+
modulePaths.get(moduleName).push(apiPath);
|
|
122
|
+
const { inputType, outputType } = _extractAndRegisterTypes(endpoint, allSchemas);
|
|
97
123
|
[inputType, outputType].forEach((t) => {
|
|
98
|
-
|
|
99
|
-
|
|
124
|
+
const cleanType = t.replace("[]", "");
|
|
125
|
+
if (cleanType && !["unknown", "undefined", "void", "any", "QueryOptions", "Promise"].includes(cleanType)) {
|
|
126
|
+
currentModule.schemas.add(cleanType);
|
|
100
127
|
}
|
|
101
128
|
});
|
|
102
|
-
const actionName =
|
|
103
|
-
|
|
129
|
+
const actionName = getActionNameFromOpId(endpoint.operationId);
|
|
130
|
+
currentModule.actions[actionName] = {
|
|
104
131
|
method: method.toUpperCase(),
|
|
105
132
|
path: apiPath,
|
|
106
|
-
// سنقوم بتعديل هذا لاحقًا ليصبح نسبيًا
|
|
107
133
|
description: endpoint.summary || "",
|
|
108
134
|
hasQuery: (endpoint.parameters || []).some((p) => p.in === "query"),
|
|
109
135
|
autoFetch: method.toUpperCase() === "GET" && !apiPath.includes("{"),
|
|
110
|
-
|
|
136
|
+
requiresAuth: !!endpoint.security && endpoint.security.length > 0,
|
|
111
137
|
_inputType: inputType,
|
|
112
138
|
_outputType: outputType
|
|
113
139
|
};
|
|
140
|
+
debugLog("Parsed Action", { moduleName, actionName, ...currentModule.actions[actionName] });
|
|
114
141
|
}
|
|
115
142
|
}
|
|
116
|
-
|
|
117
|
-
const basePath =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const action = modules[moduleName].actions[actionName];
|
|
143
|
+
modules.forEach((mod, name) => {
|
|
144
|
+
const basePath = findCommonBasePath(modulePaths.get(name));
|
|
145
|
+
mod.baseEndpoint = basePath;
|
|
146
|
+
Object.values(mod.actions).forEach((action) => {
|
|
121
147
|
const relativePath = action.path.replace(basePath, "").replace(/^\//, "");
|
|
122
148
|
action.path = relativePath === "" ? "/" : relativePath;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return modules;
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
return { modules, allSchemas };
|
|
126
152
|
}
|
|
127
|
-
function
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
const outputType =
|
|
133
|
-
const
|
|
134
|
-
const
|
|
153
|
+
function _extractAndRegisterTypes(endpoint, allSchemas) {
|
|
154
|
+
const opId = endpoint.operationId || "Unnamed";
|
|
155
|
+
const successKey = Object.keys(endpoint.responses).find((c) => c.startsWith("2"));
|
|
156
|
+
const successRes = successKey ? endpoint.responses[successKey] : void 0;
|
|
157
|
+
const resSchema = successRes?.content?.["application/json"]?.schema;
|
|
158
|
+
const outputType = successKey === "204" ? "void" : _schemaToTypeName(resSchema, `${opId}Response`, allSchemas);
|
|
159
|
+
const reqBody = endpoint.requestBody;
|
|
160
|
+
const reqSchema = reqBody?.content?.["application/json"]?.schema;
|
|
135
161
|
let inputType = "undefined";
|
|
136
|
-
if (
|
|
137
|
-
inputType = _schemaToTypeName(
|
|
162
|
+
if (reqSchema) {
|
|
163
|
+
inputType = _schemaToTypeName(reqSchema, `${opId}Request`, allSchemas);
|
|
138
164
|
} else if ((endpoint.parameters || []).some((p) => p.in === "query")) {
|
|
139
165
|
inputType = "QueryOptions";
|
|
140
166
|
}
|
|
141
167
|
return { inputType, outputType };
|
|
142
168
|
}
|
|
143
|
-
function _schemaToTypeName(schema, name,
|
|
169
|
+
function _schemaToTypeName(schema, name, allSchemas) {
|
|
144
170
|
if (!schema) return "unknown";
|
|
145
171
|
if (schema.type === "array" && schema.items) {
|
|
146
|
-
const itemTypeName = _schemaToTypeName(schema.items, `${name}Item`,
|
|
172
|
+
const itemTypeName = _schemaToTypeName(schema.items, `${name}Item`, allSchemas);
|
|
147
173
|
return `${itemTypeName}[]`;
|
|
148
174
|
}
|
|
149
|
-
if (schema.type === "object" || schema.properties || schema.allOf) {
|
|
150
|
-
const typeName =
|
|
151
|
-
if (!
|
|
152
|
-
|
|
175
|
+
if (schema.type === "object" || schema.properties || schema.allOf || !schema.type) {
|
|
176
|
+
const typeName = toPascalCase(name);
|
|
177
|
+
if (!allSchemas.has(typeName)) {
|
|
178
|
+
debugLog("Registering new inline schema", { assignedName: typeName, originalSchema: schema });
|
|
179
|
+
allSchemas.set(typeName, { name: typeName, schema });
|
|
153
180
|
}
|
|
154
181
|
return typeName;
|
|
155
182
|
}
|
|
156
183
|
if (schema.type && ["string", "number", "boolean", "integer"].includes(schema.type)) {
|
|
157
184
|
return schema.type === "integer" ? "number" : schema.type;
|
|
158
185
|
}
|
|
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
|
-
}
|
|
166
186
|
return "unknown";
|
|
167
187
|
}
|
|
168
|
-
async function generateModuleFiles(
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
if (!import_fs.default.existsSync(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
console.log(import_chalk.default.yellow(` - No types for module "${moduleName}". Skipping types.ts.`));
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
console.log(import_chalk.default.gray(` - Generating types.ts with ${typeNames.size} types...`));
|
|
181
|
-
let typesContent = `// This file is auto-generated by the API generator. Do not edit.
|
|
188
|
+
async function generateModuleFiles(module2, allSchemas, outputDir) {
|
|
189
|
+
const moduleName = module2.moduleName;
|
|
190
|
+
const moduleOutputPath = import_path.default.join(outputDir, moduleName);
|
|
191
|
+
if (!import_fs.default.existsSync(moduleOutputPath)) import_fs.default.mkdirSync(moduleOutputPath, { recursive: true });
|
|
192
|
+
console.log(import_chalk.default.cyan(`
|
|
193
|
+
Generating module: ${import_chalk.default.bold(moduleName)}`));
|
|
194
|
+
const typesToImport = [...module2.schemas].sort();
|
|
195
|
+
let configContent = `/* eslint-disable */
|
|
196
|
+
// This file is auto-generated.
|
|
182
197
|
|
|
198
|
+
import type { ApiModuleConfig, ActionConfigModule, QueryOptions } from 'api-core-lib';
|
|
183
199
|
`;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
200
|
+
if (typesToImport.length > 0) configContent += `import type { ${typesToImport.join(", ")} } from './types';
|
|
201
|
+
`;
|
|
202
|
+
const actionsType = Object.values(module2.actions).map((a) => ` ${getActionNameFromOpId(a.path)}: ActionConfigModule<${a._inputType}, ${a._outputType}>;`).join("\n");
|
|
203
|
+
const actionsValue = Object.values(module2.actions).map((a) => {
|
|
204
|
+
const { _inputType, _outputType, ...config } = a;
|
|
205
|
+
return ` ${getActionNameFromOpId(a.path)}: ${JSON.stringify(config, null, 2).replace(/\n/g, "\n ")}`;
|
|
206
|
+
}).join(",\n");
|
|
207
|
+
configContent += `
|
|
208
|
+
export const ${moduleName}Module: ApiModuleConfig<{
|
|
209
|
+
${actionsType}
|
|
210
|
+
}> = {
|
|
211
|
+
baseEndpoint: '${module2.baseEndpoint}',
|
|
212
|
+
actions: {
|
|
213
|
+
${actionsValue}
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
`;
|
|
217
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "config.ts"), configContent.trim(), { encoding: "utf-8" });
|
|
218
|
+
console.log(import_chalk.default.gray(` \u2713 config.ts`));
|
|
219
|
+
if (typesToImport.length === 0) return;
|
|
220
|
+
let typesContent = `// This file is auto-generated.
|
|
221
|
+
|
|
222
|
+
`;
|
|
223
|
+
const tsOptions = { bannerComment: "", style: { bracketSpacing: true, printWidth: 120, semi: true, singleQuote: true, tabWidth: 2 }, additionalProperties: false };
|
|
224
|
+
for (const typeName of typesToImport) {
|
|
225
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
226
|
+
if (parsedSchema) {
|
|
192
227
|
try {
|
|
193
|
-
const tsType = await (0, import_json_schema_to_typescript.compile)(schema, typeName,
|
|
228
|
+
const tsType = await (0, import_json_schema_to_typescript.compile)(parsedSchema.schema, typeName, tsOptions);
|
|
194
229
|
typesContent += tsType + "\n";
|
|
195
|
-
} catch (
|
|
196
|
-
console.error(import_chalk.default.red(` - Error compiling type "${typeName}": ${
|
|
230
|
+
} catch (e) {
|
|
231
|
+
console.error(import_chalk.default.red(` - Error compiling type "${typeName}": ${e.message}`));
|
|
197
232
|
}
|
|
198
|
-
} else {
|
|
199
|
-
console.log(import_chalk.default.yellow(` - Warning: Schema for type "${typeName}" not found.`));
|
|
200
233
|
}
|
|
201
234
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const actionsCount = Object.keys(moduleData.actions).length;
|
|
207
|
-
console.log(import_chalk.default.gray(` - Generating config.ts with ${actionsCount} actions...`));
|
|
208
|
-
const typeNamesArray = [...moduleData.types].sort();
|
|
209
|
-
const typesImportStatement = typeNamesArray.length > 0 ? `import type { ${typeNamesArray.join(", ")} } from './types';` : ``;
|
|
210
|
-
const actionsTypeParts = Object.entries(moduleData.actions).map(
|
|
211
|
-
([actionName, actionData]) => ` ${actionName}: ActionConfigModule<${actionData._inputType}, ${actionData._outputType}>;`
|
|
212
|
-
);
|
|
213
|
-
const actionsTypeDefinition = `{
|
|
214
|
-
${actionsTypeParts.join("\n")}
|
|
215
|
-
}`;
|
|
216
|
-
const actionsValueParts = Object.entries(moduleData.actions).map(([actionName, actionData]) => {
|
|
217
|
-
const { _inputType, _outputType, ...config } = actionData;
|
|
218
|
-
return ` ${actionName}: ${JSON.stringify(config, null, 2).replace(/\n/g, "\n ")}`;
|
|
219
|
-
});
|
|
220
|
-
const actionsValueDefinition = `{
|
|
221
|
-
${actionsValueParts.join(",\n")}
|
|
222
|
-
}`;
|
|
223
|
-
const configContent = `/* eslint-disable */
|
|
224
|
-
// This file is auto-generated...
|
|
235
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "types.ts"), typesContent, { encoding: "utf-8" });
|
|
236
|
+
console.log(import_chalk.default.gray(` \u2713 types.ts`));
|
|
237
|
+
let validationContent = `// This file is auto-generated.
|
|
238
|
+
import { z } from 'zod';
|
|
225
239
|
|
|
226
|
-
|
|
227
|
-
|
|
240
|
+
`;
|
|
241
|
+
for (const typeName of typesToImport) {
|
|
242
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
243
|
+
if (parsedSchema?.schema.type === "object") {
|
|
244
|
+
validationContent += `export const ${typeName}Schema = ${_schemaToZod(parsedSchema.schema)};
|
|
228
245
|
|
|
229
|
-
export const ${moduleName}Module: ApiModuleConfig<${actionsTypeDefinition}> = {
|
|
230
|
-
baseEndpoint: '${moduleData.baseEndpoint}',
|
|
231
|
-
actions: ${actionsValueDefinition},
|
|
232
|
-
};
|
|
233
246
|
`;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "validation.ts"), validationContent, { encoding: "utf-8" });
|
|
250
|
+
console.log(import_chalk.default.gray(` \u2713 validation.ts`));
|
|
251
|
+
let mocksContent = `// This file is auto-generated.
|
|
252
|
+
import type { ${typesToImport.join(", ")} } from './types';
|
|
253
|
+
|
|
254
|
+
`;
|
|
255
|
+
for (const typeName of typesToImport) {
|
|
256
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
257
|
+
if (parsedSchema) {
|
|
258
|
+
mocksContent += `export const mock${typeName}: ${typeName} = ${JSON.stringify(_schemaToMock(parsedSchema.schema), null, 2)};
|
|
259
|
+
|
|
260
|
+
`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "mocks.ts"), mocksContent, { encoding: "utf-8" });
|
|
264
|
+
console.log(import_chalk.default.gray(` \u2713 mocks.ts`));
|
|
265
|
+
let indexContent = `// This file is auto-generated.
|
|
266
|
+
|
|
267
|
+
export * from './config';
|
|
268
|
+
export * from './types';
|
|
269
|
+
export * from './validation';
|
|
270
|
+
export * from './mocks';
|
|
271
|
+
`;
|
|
272
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "index.ts"), indexContent, { encoding: "utf-8" });
|
|
273
|
+
console.log(import_chalk.default.gray(` \u2713 index.ts`));
|
|
239
274
|
}
|
|
240
|
-
function
|
|
241
|
-
const
|
|
242
|
-
|
|
275
|
+
function _schemaToZod(schema) {
|
|
276
|
+
const shape = [];
|
|
277
|
+
if (schema.properties) {
|
|
278
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
279
|
+
shape.push(` ${key}: ${_propToZod(prop, (schema.required || []).includes(key))}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return `z.object({
|
|
283
|
+
${shape.join(",\n")}
|
|
284
|
+
})`;
|
|
243
285
|
}
|
|
244
|
-
function
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
286
|
+
function _propToZod(prop, isRequired) {
|
|
287
|
+
let zodString = "z.any()";
|
|
288
|
+
switch (prop.type) {
|
|
289
|
+
case "string":
|
|
290
|
+
zodString = "z.string()";
|
|
291
|
+
if (prop.format === "email") zodString += ".email()";
|
|
292
|
+
if (prop.format === "uuid") zodString += ".uuid()";
|
|
293
|
+
if (prop.enum) zodString = `z.enum(${JSON.stringify(prop.enum)})`;
|
|
294
|
+
break;
|
|
295
|
+
case "integer":
|
|
296
|
+
case "number":
|
|
297
|
+
zodString = "z.number()";
|
|
298
|
+
if (prop.minimum !== void 0) zodString += `.min(${prop.minimum})`;
|
|
299
|
+
if (prop.maximum !== void 0) zodString += `.max(${prop.maximum})`;
|
|
300
|
+
break;
|
|
301
|
+
case "boolean":
|
|
302
|
+
zodString = "z.boolean()";
|
|
303
|
+
break;
|
|
304
|
+
case "array":
|
|
305
|
+
zodString = `z.array(${prop.items ? _propToZod(prop.items, true) : "z.any()"})`;
|
|
306
|
+
break;
|
|
307
|
+
case "object":
|
|
308
|
+
zodString = _schemaToZod(prop);
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
return isRequired ? zodString : `${zodString}.optional().nullable()`;
|
|
249
312
|
}
|
|
250
|
-
function
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
313
|
+
function _schemaToMock(schema) {
|
|
314
|
+
if (schema.example) return schema.example;
|
|
315
|
+
switch (schema.type) {
|
|
316
|
+
case "string":
|
|
317
|
+
if (schema.format === "email") return "test@example.com";
|
|
318
|
+
if (schema.format === "uuid") return "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11";
|
|
319
|
+
if (schema.enum) return schema.enum[0];
|
|
320
|
+
return "Mock String";
|
|
321
|
+
case "integer":
|
|
322
|
+
case "number":
|
|
323
|
+
return 1;
|
|
324
|
+
case "boolean":
|
|
325
|
+
return true;
|
|
326
|
+
case "array":
|
|
327
|
+
return schema.items ? [_schemaToMock(schema.items)] : [];
|
|
328
|
+
case "object":
|
|
329
|
+
const mock = {};
|
|
330
|
+
if (schema.properties) {
|
|
331
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
332
|
+
mock[key] = _schemaToMock(prop);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return mock;
|
|
336
|
+
default:
|
|
337
|
+
return null;
|
|
258
338
|
}
|
|
259
|
-
let prefix = first.substring(0, i);
|
|
260
|
-
return prefix.substring(0, prefix.lastIndexOf("/") + 1) || "/";
|
|
261
339
|
}
|
|
262
|
-
async function runGenerator(
|
|
263
|
-
|
|
340
|
+
async function runGenerator() {
|
|
341
|
+
const options = {
|
|
342
|
+
output: "src/lib/api",
|
|
343
|
+
envPath: ".env"
|
|
344
|
+
};
|
|
345
|
+
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Development Platform Generator..."));
|
|
264
346
|
import_dotenv.default.config({ path: options.envPath });
|
|
265
347
|
const specUrl = process.env.OPENAPI_SPEC_URL || "./swagger.json";
|
|
266
348
|
console.log(import_chalk.default.blue("\u2713 Step 1: Environment variables loaded."));
|
|
267
349
|
try {
|
|
268
350
|
console.log(import_chalk.default.blue(`
|
|
269
351
|
\u23F3 Step 2: Fetching and fully dereferencing spec from ${specUrl}...`));
|
|
270
|
-
const
|
|
352
|
+
const spec = await import_swagger_parser.default.dereference(specUrl);
|
|
271
353
|
console.log(import_chalk.default.green("\u2713 Spec fetched and fully dereferenced successfully."));
|
|
354
|
+
debugLog("Dereferenced Spec", spec);
|
|
272
355
|
console.log(import_chalk.default.blue("\n\u23F3 Step 3: Parsing spec using intelligent grouping..."));
|
|
273
|
-
const modules = parseSpecToModules(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
console.log(import_chalk.default.blue("\n\u23F3 Step 4: Generating module files..."));
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
for (const moduleName in modules) {
|
|
280
|
-
const moduleData = modules[moduleName];
|
|
281
|
-
await generateModuleFiles(moduleName, moduleData, allSchemas, modulesOutputPath);
|
|
356
|
+
const { modules, allSchemas } = parseSpecToModules(spec);
|
|
357
|
+
console.log(import_chalk.default.green(`\u2713 Found and grouped ${modules.size} logical modules.`));
|
|
358
|
+
debugLog("Parsed Modules", Object.fromEntries(modules));
|
|
359
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 4: Generating all module files..."));
|
|
360
|
+
for (const module2 of modules.values()) {
|
|
361
|
+
await generateModuleFiles(module2, allSchemas, options.output);
|
|
282
362
|
}
|
|
283
|
-
console.log(import_chalk.default.green("\u2713 All module files generated."));
|
|
363
|
+
console.log(import_chalk.default.green("\n\u2713 All module files generated successfully."));
|
|
284
364
|
console.log(import_chalk.default.bold.green("\n\u{1F389} API generation complete!"));
|
|
285
365
|
console.log(import_chalk.default.bold.cyan(` Output directory: ${options.output}`));
|
|
286
366
|
} catch (error) {
|
|
287
367
|
console.error(import_chalk.default.red.bold("\n\u274C An error occurred during generation:"));
|
|
288
368
|
console.error(import_chalk.default.red(`Error Message: ${error.message}`));
|
|
289
|
-
if (error.stack) console.error(import_chalk.default.gray(error.stack));
|
|
369
|
+
if (error.stack && DEBUG_MODE) console.error(import_chalk.default.gray(error.stack));
|
|
290
370
|
process.exit(1);
|
|
291
371
|
}
|
|
292
372
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "api-core-lib",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.67",
|
|
4
4
|
"description": "A flexible and powerful API client library for modern web applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -42,24 +42,27 @@
|
|
|
42
42
|
"chalk": "^4.1.2",
|
|
43
43
|
"colorette": "^2.0.20",
|
|
44
44
|
"commander": "^9.4.1",
|
|
45
|
-
"dotenv": "^16.
|
|
45
|
+
"dotenv": "^16.6.1",
|
|
46
46
|
"fast-deep-equal": "^3.1.3",
|
|
47
47
|
"fs-extra": "^11.3.1",
|
|
48
48
|
"json-schema-to-typescript": "^15.0.4",
|
|
49
49
|
"openapi-typescript": "^6.2.4",
|
|
50
50
|
"openapi-typescript-codegen": "^0.29.0",
|
|
51
51
|
"path": "^0.12.7",
|
|
52
|
-
"
|
|
52
|
+
"swagger-parser": "^10.0.3",
|
|
53
|
+
"uuid": "^9.0.1",
|
|
54
|
+
"zod": "^4.1.5"
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
55
57
|
"@openapitools/openapi-generator-cli": "^2.23.1",
|
|
56
58
|
"@types/fs-extra": "^11.0.4",
|
|
57
59
|
"@types/jest": "^30.0.0",
|
|
58
|
-
"@types/node": "^24.
|
|
60
|
+
"@types/node": "^24.3.0",
|
|
59
61
|
"@types/react": "^18.3.2",
|
|
60
62
|
"@types/uuid": "^9.0.8",
|
|
61
63
|
"javascript-obfuscator": "^4.1.1",
|
|
62
64
|
"jest": "^30.0.5",
|
|
65
|
+
"openapi-types": "^12.1.3",
|
|
63
66
|
"react": "19.1.0",
|
|
64
67
|
"react-dom": "19.1.0",
|
|
65
68
|
"ts-jest": "^29.4.1",
|