api-core-lib 12.0.65 → 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.
Files changed (2) hide show
  1. package/dist/cli.cjs +227 -154
  2. package/package.json +7 -4
package/dist/cli.cjs CHANGED
@@ -69,76 +69,114 @@ 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
- if (!spec.components) spec.components = {};
80
- if (!spec.components.schemas) spec.components.schemas = {};
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
+ }
81
108
  for (const apiPath in spec.paths) {
82
109
  const pathItem = spec.paths[apiPath];
83
110
  if (!pathItem) continue;
84
111
  for (const method in pathItem) {
85
112
  if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
86
113
  const endpoint = pathItem[method];
87
- if (!endpoint.tags || endpoint.tags.length === 0) continue;
88
- const tagName = endpoint.tags[0];
89
- const moduleName = _sanitizeTagName(tagName) + "Api";
90
- if (!modules[moduleName]) {
91
- modules[moduleName] = { baseEndpoint: _findCommonBasePath(spec, tagName), actions: {}, types: /* @__PURE__ */ new Set() };
114
+ if (!endpoint.operationId) continue;
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, []);
92
119
  }
93
- const currentModule = modules[moduleName];
94
- const { inputType, outputType } = _extractInputOutputTypes(endpoint, spec.components.schemas);
120
+ const currentModule = modules.get(moduleName);
121
+ modulePaths.get(moduleName).push(apiPath);
122
+ const { inputType, outputType } = _extractAndRegisterTypes(endpoint, allSchemas);
95
123
  [inputType, outputType].forEach((t) => {
96
- if (t && !["unknown", "undefined", "void", "any", "QueryOptions", "Promise"].includes(t)) {
97
- currentModule.types.add(t.replace("[]", ""));
124
+ const cleanType = t.replace("[]", "");
125
+ if (cleanType && !["unknown", "undefined", "void", "any", "QueryOptions", "Promise"].includes(cleanType)) {
126
+ currentModule.schemas.add(cleanType);
98
127
  }
99
128
  });
100
- const actionName = _sanitizeActionName(endpoint.operationId, method, apiPath);
101
- const relativePath = apiPath.replace(currentModule.baseEndpoint, "").replace(/^\//, "");
129
+ const actionName = getActionNameFromOpId(endpoint.operationId);
102
130
  currentModule.actions[actionName] = {
103
131
  method: method.toUpperCase(),
104
- path: relativePath === "" ? "/" : relativePath,
132
+ path: apiPath,
105
133
  description: endpoint.summary || "",
106
134
  hasQuery: (endpoint.parameters || []).some((p) => p.in === "query"),
107
135
  autoFetch: method.toUpperCase() === "GET" && !apiPath.includes("{"),
108
- invalidates: [],
136
+ requiresAuth: !!endpoint.security && endpoint.security.length > 0,
109
137
  _inputType: inputType,
110
138
  _outputType: outputType
111
139
  };
140
+ debugLog("Parsed Action", { moduleName, actionName, ...currentModule.actions[actionName] });
112
141
  }
113
142
  }
114
- return modules;
143
+ modules.forEach((mod, name) => {
144
+ const basePath = findCommonBasePath(modulePaths.get(name));
145
+ mod.baseEndpoint = basePath;
146
+ Object.values(mod.actions).forEach((action) => {
147
+ const relativePath = action.path.replace(basePath, "").replace(/^\//, "");
148
+ action.path = relativePath === "" ? "/" : relativePath;
149
+ });
150
+ });
151
+ return { modules, allSchemas };
115
152
  }
116
- function _extractInputOutputTypes(endpoint, schemas) {
117
- const operationId = endpoint.operationId || "UnnamedOperation";
118
- const successResponseKey = Object.keys(endpoint.responses).find((code) => code.startsWith("2"));
119
- const successResponse = successResponseKey ? endpoint.responses[successResponseKey] : void 0;
120
- const responseSchema = successResponse?.content?.["application/json"]?.schema;
121
- const outputType = successResponseKey === "204" ? "void" : _schemaToTypeName(responseSchema, `${operationId}Response`, schemas);
122
- const requestBody = endpoint.requestBody;
123
- const requestSchema = requestBody?.content?.["application/json"]?.schema;
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;
124
161
  let inputType = "undefined";
125
- if (requestSchema) {
126
- inputType = _schemaToTypeName(requestSchema, `${operationId}Request`, schemas);
162
+ if (reqSchema) {
163
+ inputType = _schemaToTypeName(reqSchema, `${opId}Request`, allSchemas);
127
164
  } else if ((endpoint.parameters || []).some((p) => p.in === "query")) {
128
165
  inputType = "QueryOptions";
129
166
  }
130
167
  return { inputType, outputType };
131
168
  }
132
- function _schemaToTypeName(schema, name, schemas) {
169
+ function _schemaToTypeName(schema, name, allSchemas) {
133
170
  if (!schema) return "unknown";
134
171
  if (schema.type === "array" && schema.items) {
135
- const itemTypeName = _schemaToTypeName(schema.items, `${name}Item`, schemas);
172
+ const itemTypeName = _schemaToTypeName(schema.items, `${name}Item`, allSchemas);
136
173
  return `${itemTypeName}[]`;
137
174
  }
138
- if (schema.type === "object" || schema.properties || schema.allOf) {
139
- const typeName = _toPascalCase(name) + "Dto";
140
- if (!schemas[typeName]) {
141
- schemas[typeName] = schema;
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 });
142
180
  }
143
181
  return typeName;
144
182
  }
@@ -147,155 +185,190 @@ function _schemaToTypeName(schema, name, schemas) {
147
185
  }
148
186
  return "unknown";
149
187
  }
150
- async function generateModuleFiles(moduleName, moduleData, allSchemas, outputDir) {
151
- console.log(import_chalk.default.gray(` Generating files for module: ${import_chalk.default.bold(moduleName)}...`));
152
- const moduleFolderPath = import_path.default.join(outputDir, moduleName);
153
- if (!import_fs.default.existsSync(moduleFolderPath)) import_fs.default.mkdirSync(moduleFolderPath, { recursive: true });
154
- await _generateTypesFile(moduleFolderPath, moduleName, moduleData.types, allSchemas);
155
- await _generateConfigFile(moduleFolderPath, moduleName, moduleData);
156
- }
157
- async function _generateTypesFile(moduleFolderPath, moduleName, typeNames, allSchemas) {
158
- if (typeNames.size === 0) {
159
- console.log(import_chalk.default.yellow(` - No types found for module "${moduleName}". Skipping types.ts generation.`));
160
- return;
161
- }
162
- console.log(import_chalk.default.gray(` - Generating types.ts with ${typeNames.size} types...`));
163
- 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.
164
197
 
198
+ import type { ApiModuleConfig, ActionConfigModule, QueryOptions } from 'api-core-lib';
165
199
  `;
166
- const compilationOptions = {
167
- bannerComment: "",
168
- style: { bracketSpacing: true, printWidth: 120, semi: true, singleQuote: true, tabWidth: 2, trailingComma: "es5", useTabs: false },
169
- additionalProperties: false
170
- };
171
- for (const typeName of Array.from(typeNames).sort()) {
172
- const schema = allSchemas[typeName];
173
- if (schema) {
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) {
174
227
  try {
175
- const tsType = await (0, import_json_schema_to_typescript.compile)(schema, typeName, compilationOptions);
228
+ const tsType = await (0, import_json_schema_to_typescript.compile)(parsedSchema.schema, typeName, tsOptions);
176
229
  typesContent += tsType + "\n";
177
- } catch (compileError) {
178
- console.error(import_chalk.default.red(` - Error compiling type "${typeName}": ${compileError.message}`));
230
+ } catch (e) {
231
+ console.error(import_chalk.default.red(` - Error compiling type "${typeName}": ${e.message}`));
179
232
  }
180
- } else {
181
- console.log(import_chalk.default.yellow(` - Warning: Schema for type "${typeName}" not found, skipping.`));
182
233
  }
183
234
  }
184
- const typesFilePath = import_path.default.join(moduleFolderPath, "types.ts");
185
- import_fs.default.writeFileSync(typesFilePath, typesContent, { encoding: "utf-8" });
186
- }
187
- async function _generateConfigFile(moduleFolderPath, moduleName, moduleData) {
188
- const actionsCount = Object.keys(moduleData.actions).length;
189
- console.log(import_chalk.default.gray(` - Generating config.ts with ${actionsCount} actions...`));
190
- const typeNamesArray = [...moduleData.types].sort();
191
- const typesImportStatement = typeNamesArray.length > 0 ? `import type { ${typeNamesArray.join(", ")} } from './types';` : ``;
192
- const actionsTypeParts = Object.entries(moduleData.actions).map(
193
- ([actionName, actionData]) => ` ${actionName}: ActionConfigModule<${actionData._inputType}, ${actionData._outputType}>;`
194
- );
195
- const actionsTypeDefinition = `{
196
- ${actionsTypeParts.join("\n")}
197
- }`;
198
- const actionsValueParts = Object.entries(moduleData.actions).map(([actionName, actionData]) => {
199
- const { _inputType, _outputType, ...config } = actionData;
200
- return ` ${actionName}: ${JSON.stringify(config, null, 2).replace(/\n/g, "\n ")}`;
201
- });
202
- const actionsValueDefinition = `{
203
- ${actionsValueParts.join(",\n")}
204
- }`;
205
- const configContent = `/* eslint-disable */
206
- // 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';
207
239
 
208
- import type { ApiModuleConfig, ActionConfigModule, QueryOptions } from 'api-core-lib';
209
- ${typesImportStatement}
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)};
210
245
 
211
- export const ${moduleName}Module: ApiModuleConfig<${actionsTypeDefinition}> = {
212
- baseEndpoint: '${moduleData.baseEndpoint}',
213
- actions: ${actionsValueDefinition},
214
- };
215
246
  `;
216
- const configFilePath = import_path.default.join(moduleFolderPath, "config.ts");
217
- import_fs.default.writeFileSync(configFilePath, configContent.trim(), { encoding: "utf-8" });
218
- }
219
- function _toPascalCase(str) {
220
- return str.replace(/[^a-zA-Z0-9]/g, " ").replace(/(?:^\w|[A-Z]|\b\w)/g, (w) => w.toUpperCase()).replace(/\s+/g, "");
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`));
221
274
  }
222
- function _sanitizeTagName(tagName) {
223
- return tagName.replace(/[^a-zA-Z0-9]/g, "").replace(/Central|Tenant/g, "");
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
+ })`;
224
285
  }
225
- function _sanitizeActionName(operationId, method, path3) {
226
- if (operationId) {
227
- const name = operationId.split("_").slice(1).join("_");
228
- const sanitized = name.charAt(0).toLowerCase() + name.slice(1).replace(/_v\d+$/, "");
229
- return sanitized || "action";
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;
230
310
  }
231
- const pathPart = path3.replace(/[\/{}]/g, "_").replace(/^_|_$/g, "");
232
- return `${method.toLowerCase()}_${pathPart}`;
311
+ return isRequired ? zodString : `${zodString}.optional().nullable()`;
233
312
  }
234
- function _findCommonBasePath(spec, tagName) {
235
- const paths = Object.keys(spec.paths).filter((p) => {
236
- const pathItem = spec.paths[p];
237
- if (!pathItem) return false;
238
- for (const method in pathItem) {
239
- const endpoint = pathItem[method];
240
- if (endpoint.tags?.includes(tagName)) return true;
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
- }
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;
250
338
  }
251
- return commonPrefix.substring(0, commonPrefix.lastIndexOf("/") + 1) || "/";
252
339
  }
253
- async function runGenerator(options) {
254
- console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Core Lib Code Generator..."));
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..."));
255
346
  import_dotenv.default.config({ path: options.envPath });
256
- const specUrl = getSpecUrl();
347
+ const specUrl = process.env.OPENAPI_SPEC_URL || "./swagger.json";
257
348
  console.log(import_chalk.default.blue("\u2713 Step 1: Environment variables loaded."));
258
349
  try {
259
350
  console.log(import_chalk.default.blue(`
260
351
  \u23F3 Step 2: Fetching and fully dereferencing spec from ${specUrl}...`));
261
- const dereferencedSpec = await import_swagger_parser.default.dereference(specUrl);
352
+ const spec = await import_swagger_parser.default.dereference(specUrl);
262
353
  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 and generating API modules structure..."));
264
- const modules = parseSpecToModules(dereferencedSpec);
265
- const modulesCount = Object.keys(modules).length;
266
- console.log(import_chalk.default.green(`\u2713 Found ${modulesCount} modules to generate.`));
267
- if (modulesCount === 0) {
268
- console.log(import_chalk.default.yellow("Warning: No modules were found in the spec."));
354
+ debugLog("Dereferenced Spec", spec);
355
+ console.log(import_chalk.default.blue("\n\u23F3 Step 3: Parsing spec using intelligent grouping..."));
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);
269
362
  }
270
- console.log(import_chalk.default.blue("\n\u23F3 Step 4: Generating module files..."));
271
- const modulesOutputPath = import_path.default.join(options.output, "modules");
272
- const allSchemas = dereferencedSpec.components?.schemas || {};
273
- for (const moduleName in modules) {
274
- const moduleData = modules[moduleName];
275
- await generateModuleFiles(moduleName, moduleData, allSchemas, modulesOutputPath);
276
- }
277
- 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."));
278
364
  console.log(import_chalk.default.bold.green("\n\u{1F389} API generation complete!"));
279
365
  console.log(import_chalk.default.bold.cyan(` Output directory: ${options.output}`));
280
366
  } catch (error) {
281
- handleGenerationError(error);
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."));
367
+ console.error(import_chalk.default.red.bold("\n\u274C An error occurred during generation:"));
368
+ console.error(import_chalk.default.red(`Error Message: ${error.message}`));
369
+ if (error.stack && DEBUG_MODE) console.error(import_chalk.default.gray(error.stack));
288
370
  process.exit(1);
289
371
  }
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
372
  }
300
373
 
301
374
  // src/cli.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-core-lib",
3
- "version": "12.0.65",
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.0.3",
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
- "uuid": "^9.0.1"
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.2.1",
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",