api-core-lib 12.0.67 → 12.0.69
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 +199 -172
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -74,19 +74,17 @@ var import_chalk = __toESM(require("chalk"), 1);
|
|
|
74
74
|
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
75
75
|
var import_swagger_parser = __toESM(require("@apidevtools/swagger-parser"), 1);
|
|
76
76
|
var import_openapi_types = __toESM(require_dist(), 1);
|
|
77
|
-
var import_json_schema_to_typescript = require("json-schema-to-typescript");
|
|
78
77
|
var DEBUG_MODE = process.env.DEBUG === "true";
|
|
79
|
-
var debugLog = (title, data) =>
|
|
80
|
-
|
|
81
|
-
console.log(import_chalk.default.yellow(`
|
|
82
|
-
[DEBUG: ${title}]`));
|
|
83
|
-
console.log(import_util.default.inspect(data, { depth: null, colors: true }));
|
|
84
|
-
}
|
|
85
|
-
};
|
|
78
|
+
var debugLog = (title, data) => DEBUG_MODE && console.log(import_chalk.default.yellow(`
|
|
79
|
+
[DEBUG: ${title}]`), import_util.default.inspect(data, { depth, colors: true }));
|
|
86
80
|
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
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
var toCamelCase = (str) => {
|
|
82
|
+
const s = toPascalCase(str);
|
|
83
|
+
return s.charAt(0).toLowerCase() + s.slice(1);
|
|
84
|
+
};
|
|
85
|
+
var getModuleName = (opId) => `${opId.split("_")[0].replace(/Controller$/, "")}Api`;
|
|
86
|
+
var getActionName = (opId) => toCamelCase(opId.split("_")[1] || opId);
|
|
87
|
+
var findCommonPath = (paths) => {
|
|
90
88
|
if (!paths || paths.length === 0) return "/";
|
|
91
89
|
const sorted = [...paths].sort();
|
|
92
90
|
const first = sorted[0];
|
|
@@ -96,15 +94,52 @@ var findCommonBasePath = (paths) => {
|
|
|
96
94
|
const prefix = first.substring(0, i);
|
|
97
95
|
return prefix.substring(0, prefix.lastIndexOf("/") + 1) || "/";
|
|
98
96
|
};
|
|
97
|
+
var generateFriendlyMessage = (fieldName, validation) => {
|
|
98
|
+
const friendlyName = fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
|
|
99
|
+
return `${friendlyName} is required.`;
|
|
100
|
+
};
|
|
101
|
+
function parseSchema(name, schema, allEnums) {
|
|
102
|
+
const properties = [];
|
|
103
|
+
const enums = {};
|
|
104
|
+
if (schema.properties) {
|
|
105
|
+
for (const propName in schema.properties) {
|
|
106
|
+
const propSchema = schema.properties[propName];
|
|
107
|
+
if (propSchema.enum) {
|
|
108
|
+
const enumName = `${toPascalCase(name)}${toPascalCase(propName)}Enum`;
|
|
109
|
+
enums[propName] = propSchema.enum;
|
|
110
|
+
if (!allEnums.has(enumName)) allEnums.set(enumName, { name: enumName, values: propSchema.enum });
|
|
111
|
+
}
|
|
112
|
+
properties.push({
|
|
113
|
+
name: propName,
|
|
114
|
+
type: propSchema.type || "object",
|
|
115
|
+
isRequired: (schema.required || []).includes(propName),
|
|
116
|
+
isNullable: propSchema.nullable || false,
|
|
117
|
+
description: propSchema.description,
|
|
118
|
+
example: propSchema.example,
|
|
119
|
+
enum: propSchema.enum,
|
|
120
|
+
format: propSchema.format,
|
|
121
|
+
items: propSchema.type === "array" && propSchema.items ? parseSchema(`${name}${toPascalCase(propName)}Item`, propSchema.items, allEnums).properties[0] : void 0,
|
|
122
|
+
properties: propSchema.properties ? parseSchema(`${name}${toPascalCase(propName)}`, propSchema, allEnums).properties : void 0
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { name, description: schema.description, properties, enums };
|
|
127
|
+
}
|
|
99
128
|
function parseSpecToModules(spec) {
|
|
100
129
|
const modules = /* @__PURE__ */ new Map();
|
|
101
130
|
const allSchemas = /* @__PURE__ */ new Map();
|
|
131
|
+
const allEnums = /* @__PURE__ */ new Map();
|
|
102
132
|
const modulePaths = /* @__PURE__ */ new Map();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
const registerSchema = (schema, baseName) => {
|
|
134
|
+
if (!schema) return "unknown";
|
|
135
|
+
if (schema.type === "array" && schema.items) return `${registerSchema(schema.items, `${baseName}Item`)}[]`;
|
|
136
|
+
if (schema.type === "object" || schema.properties || schema.allOf || !schema.type) {
|
|
137
|
+
const typeName = toPascalCase(baseName.replace(/_v\d+(Request|Response)$/, "$1"));
|
|
138
|
+
if (!allSchemas.has(typeName)) allSchemas.set(typeName, parseSchema(typeName, schema, allEnums));
|
|
139
|
+
return typeName;
|
|
106
140
|
}
|
|
107
|
-
|
|
141
|
+
return schema.type === "integer" ? "number" : schema.type || "unknown";
|
|
142
|
+
};
|
|
108
143
|
for (const apiPath in spec.paths) {
|
|
109
144
|
const pathItem = spec.paths[apiPath];
|
|
110
145
|
if (!pathItem) continue;
|
|
@@ -112,100 +147,59 @@ function parseSpecToModules(spec) {
|
|
|
112
147
|
if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
|
|
113
148
|
const endpoint = pathItem[method];
|
|
114
149
|
if (!endpoint.operationId) continue;
|
|
115
|
-
const moduleName =
|
|
150
|
+
const moduleName = getModuleName(endpoint.operationId);
|
|
116
151
|
if (!modules.has(moduleName)) {
|
|
117
|
-
modules.set(moduleName, { moduleName, baseEndpoint: "", actions: {}, schemas: /* @__PURE__ */ new Set() });
|
|
152
|
+
modules.set(moduleName, { moduleName, baseEndpoint: "", actions: {}, schemas: /* @__PURE__ */ new Set(), enums: /* @__PURE__ */ new Set() });
|
|
118
153
|
modulePaths.set(moduleName, []);
|
|
119
154
|
}
|
|
120
155
|
const currentModule = modules.get(moduleName);
|
|
121
156
|
modulePaths.get(moduleName).push(apiPath);
|
|
122
|
-
const
|
|
157
|
+
const successKey = Object.keys(endpoint.responses).find((c) => c.startsWith("2"));
|
|
158
|
+
const successRes = successKey ? endpoint.responses[successKey] : void 0;
|
|
159
|
+
const outputType = successKey === "204" ? "void" : registerSchema(successRes?.content?.["application/json"]?.schema, `${endpoint.operationId}Response`);
|
|
160
|
+
const reqBody = endpoint.requestBody;
|
|
161
|
+
let inputType = "undefined";
|
|
162
|
+
if (reqBody?.content?.["application/json"]?.schema) inputType = registerSchema(reqBody.content["application/json"].schema, `${endpoint.operationId}Request`);
|
|
163
|
+
else if ((endpoint.parameters || []).some((p) => p.in === "query")) inputType = "QueryOptions";
|
|
123
164
|
[inputType, outputType].forEach((t) => {
|
|
124
165
|
const cleanType = t.replace("[]", "");
|
|
125
166
|
if (cleanType && !["unknown", "undefined", "void", "any", "QueryOptions", "Promise"].includes(cleanType)) {
|
|
126
167
|
currentModule.schemas.add(cleanType);
|
|
168
|
+
const schemaDef = allSchemas.get(cleanType);
|
|
169
|
+
if (schemaDef) Object.keys(schemaDef.enums).forEach((propName) => currentModule.enums.add(`${toPascalCase(cleanType)}${toPascalCase(propName)}Enum`));
|
|
127
170
|
}
|
|
128
171
|
});
|
|
129
|
-
|
|
130
|
-
currentModule.actions[actionName] = {
|
|
131
|
-
method: method.toUpperCase(),
|
|
132
|
-
path: apiPath,
|
|
133
|
-
description: endpoint.summary || "",
|
|
134
|
-
hasQuery: (endpoint.parameters || []).some((p) => p.in === "query"),
|
|
135
|
-
autoFetch: method.toUpperCase() === "GET" && !apiPath.includes("{"),
|
|
136
|
-
requiresAuth: !!endpoint.security && endpoint.security.length > 0,
|
|
137
|
-
_inputType: inputType,
|
|
138
|
-
_outputType: outputType
|
|
139
|
-
};
|
|
140
|
-
debugLog("Parsed Action", { moduleName, actionName, ...currentModule.actions[actionName] });
|
|
172
|
+
currentModule.actions[getActionName(endpoint.operationId)] = { name: getActionName(endpoint.operationId), method: method.toUpperCase(), path: apiPath, description: endpoint.summary || "", hasQuery: (endpoint.parameters || []).some((p) => p.in === "query"), autoFetch: method.toUpperCase() === "GET" && !apiPath.includes("{"), requiresAuth: !!endpoint.security && endpoint.security.length > 0, inputType, outputType };
|
|
141
173
|
}
|
|
142
174
|
}
|
|
143
175
|
modules.forEach((mod, name) => {
|
|
144
|
-
|
|
145
|
-
mod.
|
|
146
|
-
Object.values(mod.actions).forEach((action) => {
|
|
147
|
-
const relativePath = action.path.replace(basePath, "").replace(/^\//, "");
|
|
148
|
-
action.path = relativePath === "" ? "/" : relativePath;
|
|
149
|
-
});
|
|
176
|
+
mod.baseEndpoint = findCommonPath(modulePaths.get(name));
|
|
177
|
+
Object.values(mod.actions).forEach((action) => action.path = action.path.replace(mod.baseEndpoint, "").replace(/^\//, "") || "/");
|
|
150
178
|
});
|
|
151
|
-
|
|
152
|
-
}
|
|
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;
|
|
161
|
-
let inputType = "undefined";
|
|
162
|
-
if (reqSchema) {
|
|
163
|
-
inputType = _schemaToTypeName(reqSchema, `${opId}Request`, allSchemas);
|
|
164
|
-
} else if ((endpoint.parameters || []).some((p) => p.in === "query")) {
|
|
165
|
-
inputType = "QueryOptions";
|
|
166
|
-
}
|
|
167
|
-
return { inputType, outputType };
|
|
179
|
+
debugLog("Final Parsed Modules", Object.fromEntries(modules));
|
|
180
|
+
return { modules, allSchemas, allEnums };
|
|
168
181
|
}
|
|
169
|
-
function
|
|
170
|
-
|
|
171
|
-
if (schema.type === "array" && schema.items) {
|
|
172
|
-
const itemTypeName = _schemaToTypeName(schema.items, `${name}Item`, allSchemas);
|
|
173
|
-
return `${itemTypeName}[]`;
|
|
174
|
-
}
|
|
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 });
|
|
180
|
-
}
|
|
181
|
-
return typeName;
|
|
182
|
-
}
|
|
183
|
-
if (schema.type && ["string", "number", "boolean", "integer"].includes(schema.type)) {
|
|
184
|
-
return schema.type === "integer" ? "number" : schema.type;
|
|
185
|
-
}
|
|
186
|
-
return "unknown";
|
|
187
|
-
}
|
|
188
|
-
async function generateModuleFiles(module2, allSchemas, outputDir) {
|
|
189
|
-
const moduleName = module2.moduleName;
|
|
190
|
-
const moduleOutputPath = import_path.default.join(outputDir, moduleName);
|
|
182
|
+
async function generateModuleFiles(module2, allSchemas, allEnums, outputDir) {
|
|
183
|
+
const moduleOutputPath = import_path.default.join(outputDir, module2.moduleName);
|
|
191
184
|
if (!import_fs.default.existsSync(moduleOutputPath)) import_fs.default.mkdirSync(moduleOutputPath, { recursive: true });
|
|
192
185
|
console.log(import_chalk.default.cyan(`
|
|
193
|
-
Generating module: ${import_chalk.default.bold(moduleName)}`));
|
|
194
|
-
const
|
|
186
|
+
Generating module: ${import_chalk.default.bold(module2.moduleName)}`));
|
|
187
|
+
const schemasToImport = [...module2.schemas].sort();
|
|
188
|
+
const enumsToImport = [...module2.enums].sort();
|
|
195
189
|
let configContent = `/* eslint-disable */
|
|
196
190
|
// This file is auto-generated.
|
|
197
191
|
|
|
198
192
|
import type { ApiModuleConfig, ActionConfigModule, QueryOptions } from 'api-core-lib';
|
|
199
193
|
`;
|
|
200
|
-
if (
|
|
194
|
+
if (schemasToImport.length > 0) configContent += `import type { ${schemasToImport.join(", ")} } from './types';
|
|
201
195
|
`;
|
|
202
|
-
const actionsType = Object.values(module2.actions).map((a) => ` ${
|
|
196
|
+
const actionsType = Object.values(module2.actions).map((a) => ` ${a.name}: ActionConfigModule<${a.inputType}, ${a.outputType}>;`).join("\n");
|
|
203
197
|
const actionsValue = Object.values(module2.actions).map((a) => {
|
|
204
|
-
const {
|
|
205
|
-
return ` ${
|
|
198
|
+
const { inputType, outputType, name, ...c } = a;
|
|
199
|
+
return ` ${name}: ${JSON.stringify(c, null, 2).replace(/\n/g, "\n ")}`;
|
|
206
200
|
}).join(",\n");
|
|
207
201
|
configContent += `
|
|
208
|
-
export const ${moduleName}Module: ApiModuleConfig<{
|
|
202
|
+
export const ${module2.moduleName}Module: ApiModuleConfig<{
|
|
209
203
|
${actionsType}
|
|
210
204
|
}> = {
|
|
211
205
|
baseEndpoint: '${module2.baseEndpoint}',
|
|
@@ -214,154 +208,187 @@ ${actionsValue}
|
|
|
214
208
|
},
|
|
215
209
|
};
|
|
216
210
|
`;
|
|
217
|
-
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "config.ts"), configContent.trim()
|
|
211
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "config.ts"), configContent.trim());
|
|
218
212
|
console.log(import_chalk.default.gray(` \u2713 config.ts`));
|
|
219
|
-
|
|
220
|
-
|
|
213
|
+
const indexContent = [`// This file is auto-generated.
|
|
214
|
+
|
|
215
|
+
export * from './config';`];
|
|
216
|
+
if (schemasToImport.length > 0) {
|
|
217
|
+
if (enumsToImport.length > 0) {
|
|
218
|
+
let enumsContent = `// This file is auto-generated.
|
|
221
219
|
|
|
222
220
|
`;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
221
|
+
for (const enumName of enumsToImport) {
|
|
222
|
+
const enumDef = allEnums.get(enumName);
|
|
223
|
+
if (enumDef) {
|
|
224
|
+
enumsContent += `export const ${enumName} = ${JSON.stringify(enumDef.values)} as const;
|
|
225
|
+
`;
|
|
226
|
+
enumsContent += `export type ${enumName} = typeof ${enumName}[number];
|
|
227
|
+
|
|
228
|
+
`;
|
|
229
|
+
}
|
|
232
230
|
}
|
|
231
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "enums.ts"), enumsContent);
|
|
232
|
+
console.log(import_chalk.default.gray(` \u2713 enums.ts`));
|
|
233
|
+
indexContent.push(`export * from './enums';`);
|
|
233
234
|
}
|
|
234
|
-
|
|
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';
|
|
235
|
+
let typesContent = `// This file is auto-generated.
|
|
239
236
|
|
|
240
237
|
`;
|
|
241
|
-
|
|
242
|
-
const parsedSchema = allSchemas.get(typeName);
|
|
243
|
-
if (parsedSchema?.schema.type === "object") {
|
|
244
|
-
validationContent += `export const ${typeName}Schema = ${_schemaToZod(parsedSchema.schema)};
|
|
238
|
+
if (enumsToImport.length > 0) typesContent += `import type { ${enumsToImport.join(", ")} } from './enums';
|
|
245
239
|
|
|
246
240
|
`;
|
|
241
|
+
for (const typeName of schemasToImport) {
|
|
242
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
243
|
+
if (parsedSchema) {
|
|
244
|
+
if (parsedSchema.description) typesContent += `/**
|
|
245
|
+
* ${parsedSchema.description}
|
|
246
|
+
*/
|
|
247
|
+
`;
|
|
248
|
+
typesContent += `export interface ${typeName} {
|
|
249
|
+
`;
|
|
250
|
+
for (const prop of parsedSchema.properties) {
|
|
251
|
+
if (prop.description) typesContent += ` /**
|
|
252
|
+
* ${prop.description}
|
|
253
|
+
${prop.example ? ` * @example ${JSON.stringify(prop.example)}
|
|
254
|
+
` : ""} */
|
|
255
|
+
`;
|
|
256
|
+
let propType = prop.type;
|
|
257
|
+
if (prop.enum) propType = `${toPascalCase(typeName)}${toPascalCase(prop.name)}Enum`;
|
|
258
|
+
else if (prop.items) propType = prop.items.properties ? `${toPascalCase(`${typeName}${toPascalCase(prop.name)}Item`)}[]` : `${prop.items.type}[]`;
|
|
259
|
+
else if (prop.properties) propType = `Record<string, unknown>`;
|
|
260
|
+
typesContent += ` ${prop.name}${prop.isRequired ? "" : "?"}: ${propType};
|
|
261
|
+
`;
|
|
262
|
+
}
|
|
263
|
+
typesContent += `}
|
|
264
|
+
|
|
265
|
+
`;
|
|
266
|
+
}
|
|
247
267
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
import
|
|
268
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "types.ts"), typesContent);
|
|
269
|
+
console.log(import_chalk.default.gray(` \u2713 types.ts`));
|
|
270
|
+
indexContent.push(`export * from './types';`);
|
|
271
|
+
let validationContent = `// This file is auto-generated.
|
|
272
|
+
import { z } from 'zod';
|
|
273
|
+
`;
|
|
274
|
+
if (enumsToImport.length > 0) validationContent += `import { ${enumsToImport.join(", ")} } from './enums';
|
|
253
275
|
|
|
254
276
|
`;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
277
|
+
for (const typeName of schemasToImport) {
|
|
278
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
279
|
+
if (parsedSchema) {
|
|
280
|
+
let zodShape = parsedSchema.properties.map((p) => ` ${p.name}: ${_propToZod(p, typeName)}`).join(",\n");
|
|
281
|
+
validationContent += `export const ${typeName}Schema = z.object({
|
|
282
|
+
${zodShape}
|
|
283
|
+
});
|
|
259
284
|
|
|
260
285
|
`;
|
|
286
|
+
}
|
|
261
287
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
288
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "validation.ts"), validationContent);
|
|
289
|
+
console.log(import_chalk.default.gray(` \u2713 validation.ts`));
|
|
290
|
+
indexContent.push(`export * from './validation';`);
|
|
291
|
+
let mocksContent = `// This file is auto-generated.
|
|
292
|
+
import type { ${schemasToImport.join(", ")} } from './types';
|
|
293
|
+
`;
|
|
294
|
+
if (enumsToImport.length > 0) mocksContent += `import { ${enumsToImport.map((e) => e.replace(/Enum$/, "")).join(", ")} } from './enums';
|
|
266
295
|
|
|
267
|
-
export * from './config';
|
|
268
|
-
export * from './types';
|
|
269
|
-
export * from './validation';
|
|
270
|
-
export * from './mocks';
|
|
271
296
|
`;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
297
|
+
for (const typeName of schemasToImport) {
|
|
298
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
299
|
+
if (parsedSchema) {
|
|
300
|
+
let mockObject = {};
|
|
301
|
+
parsedSchema.properties.forEach((p) => {
|
|
302
|
+
mockObject[p.name] = _propToMock(p);
|
|
303
|
+
});
|
|
304
|
+
mocksContent += `export const mock${typeName}: ${typeName} = ${JSON.stringify(mockObject, null, 2)};
|
|
305
|
+
|
|
306
|
+
`;
|
|
307
|
+
}
|
|
280
308
|
}
|
|
309
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "mocks.ts"), mocksContent);
|
|
310
|
+
console.log(import_chalk.default.gray(` \u2713 mocks.ts`));
|
|
311
|
+
indexContent.push(`export * from './mocks';`);
|
|
281
312
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
})`;
|
|
313
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "index.ts"), indexContent.join("\n"));
|
|
314
|
+
console.log(import_chalk.default.gray(` \u2713 index.ts`));
|
|
285
315
|
}
|
|
286
|
-
function _propToZod(prop,
|
|
316
|
+
function _propToZod(prop, parentName) {
|
|
287
317
|
let zodString = "z.any()";
|
|
318
|
+
const errorMapParams = { errorMap: () => ({ message: prop.description || generateFriendlyMessage(prop.name, "required") }) };
|
|
288
319
|
switch (prop.type) {
|
|
289
320
|
case "string":
|
|
290
|
-
zodString =
|
|
291
|
-
if (prop.format === "email") zodString += ".email
|
|
292
|
-
if (prop.format === "uuid") zodString +=
|
|
293
|
-
if (prop.enum) zodString = `z.enum(${
|
|
321
|
+
zodString = `z.string(${JSON.stringify(errorMapParams)})`;
|
|
322
|
+
if (prop.format === "email") zodString += `.email({ message: "${generateFriendlyMessage(prop.name, "email")}" })`;
|
|
323
|
+
if (prop.format === "uuid") zodString += `.uuid()`;
|
|
324
|
+
if (prop.enum) zodString = `z.enum(${toPascalCase(parentName)}${toPascalCase(prop.name)}Enum)`;
|
|
294
325
|
break;
|
|
295
326
|
case "integer":
|
|
296
327
|
case "number":
|
|
297
|
-
zodString =
|
|
298
|
-
if (prop.minimum !== void 0) zodString += `.min(${prop.minimum})`;
|
|
299
|
-
if (prop.maximum !== void 0) zodString += `.max(${prop.maximum})`;
|
|
328
|
+
zodString = `z.number(${JSON.stringify(errorMapParams)})`;
|
|
300
329
|
break;
|
|
301
330
|
case "boolean":
|
|
302
|
-
zodString =
|
|
331
|
+
zodString = `z.boolean(${JSON.stringify(errorMapParams)})`;
|
|
303
332
|
break;
|
|
304
333
|
case "array":
|
|
305
|
-
zodString = `z.array(${prop.items ? _propToZod(prop.items,
|
|
334
|
+
zodString = `z.array(${prop.items ? _propToZod(prop.items, `${parentName}${toPascalCase(prop.name)}Item`) : "z.any()"})`;
|
|
306
335
|
break;
|
|
307
336
|
case "object":
|
|
308
|
-
|
|
337
|
+
let shape = "z.record(z.unknown())";
|
|
338
|
+
if (prop.properties) shape = `z.object({
|
|
339
|
+
${prop.properties.map((p) => ` ${p.name}: ${_propToZod(p, `${parentName}${toPascalCase(prop.name)}`)}`).join(",\n")}
|
|
340
|
+
})`;
|
|
341
|
+
zodString = shape;
|
|
309
342
|
break;
|
|
310
343
|
}
|
|
311
|
-
|
|
344
|
+
if (!prop.isRequired) zodString += ".optional()";
|
|
345
|
+
if (prop.isNullable) zodString += ".nullable()";
|
|
346
|
+
return zodString;
|
|
312
347
|
}
|
|
313
|
-
function
|
|
314
|
-
if (
|
|
315
|
-
|
|
348
|
+
function _propToMock(prop) {
|
|
349
|
+
if (prop.example) return prop.example;
|
|
350
|
+
if (prop.name.match(/image|avatar|logo|url/i)) return "https://via.placeholder.com/150";
|
|
351
|
+
if (prop.enum) return prop.enum[0];
|
|
352
|
+
switch (prop.type) {
|
|
316
353
|
case "string":
|
|
317
|
-
if (
|
|
318
|
-
if (
|
|
319
|
-
|
|
320
|
-
return "Mock String";
|
|
354
|
+
if (prop.format === "email") return "test@example.com";
|
|
355
|
+
if (prop.format === "uuid") return "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11";
|
|
356
|
+
return `Mock ${toPascalCase(prop.name)}`;
|
|
321
357
|
case "integer":
|
|
322
358
|
case "number":
|
|
323
359
|
return 1;
|
|
324
360
|
case "boolean":
|
|
325
361
|
return true;
|
|
326
362
|
case "array":
|
|
327
|
-
return
|
|
363
|
+
return prop.items ? [_propToMock(prop.items)] : [];
|
|
328
364
|
case "object":
|
|
329
365
|
const mock = {};
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
}
|
|
366
|
+
if (prop.properties) prop.properties.forEach((p) => {
|
|
367
|
+
mock[p.name] = _propToMock(p);
|
|
368
|
+
});
|
|
335
369
|
return mock;
|
|
336
370
|
default:
|
|
337
371
|
return null;
|
|
338
372
|
}
|
|
339
373
|
}
|
|
340
|
-
async function runGenerator() {
|
|
341
|
-
|
|
342
|
-
output: "src/lib/api",
|
|
343
|
-
envPath: ".env"
|
|
344
|
-
};
|
|
345
|
-
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Development Platform Generator..."));
|
|
374
|
+
async function runGenerator(options) {
|
|
375
|
+
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Development Platform Generator (Diamond Edition)..."));
|
|
346
376
|
import_dotenv.default.config({ path: options.envPath });
|
|
347
377
|
const specUrl = process.env.OPENAPI_SPEC_URL || "./swagger.json";
|
|
348
|
-
console.log(import_chalk.default.blue("\u2713 Step 1: Environment variables loaded."));
|
|
349
378
|
try {
|
|
350
379
|
console.log(import_chalk.default.blue(`
|
|
351
|
-
\u23F3 Step
|
|
380
|
+
\u23F3 Step 1: Dereferencing spec from ${specUrl}...`));
|
|
352
381
|
const spec = await import_swagger_parser.default.dereference(specUrl);
|
|
353
|
-
console.log(import_chalk.default.green("\u2713 Spec
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const { modules, allSchemas } = parseSpecToModules(spec);
|
|
382
|
+
console.log(import_chalk.default.green("\u2713 Spec fully dereferenced."));
|
|
383
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 2: Parsing spec with intelligent grouping..."));
|
|
384
|
+
const { modules, allSchemas, allEnums } = parseSpecToModules(spec);
|
|
357
385
|
console.log(import_chalk.default.green(`\u2713 Found and grouped ${modules.size} logical modules.`));
|
|
358
|
-
|
|
359
|
-
console.log(import_chalk.default.blue("\n\u23F3 Step 4: Generating all module files..."));
|
|
386
|
+
console.log(import_chalk.default.blue("\n\u23F3 Step 3: Generating all module files..."));
|
|
360
387
|
for (const module2 of modules.values()) {
|
|
361
|
-
await generateModuleFiles(module2, allSchemas, options.output);
|
|
388
|
+
await generateModuleFiles(module2, allSchemas, allEnums, options.output);
|
|
362
389
|
}
|
|
363
390
|
console.log(import_chalk.default.green("\n\u2713 All module files generated successfully."));
|
|
364
|
-
console.log(import_chalk.default.bold.green("\n\u{1F389} API generation complete!"));
|
|
391
|
+
console.log(import_chalk.default.bold.green("\n\u{1F389} API generation complete! Your development platform is ready."));
|
|
365
392
|
console.log(import_chalk.default.bold.cyan(` Output directory: ${options.output}`));
|
|
366
393
|
} catch (error) {
|
|
367
394
|
console.error(import_chalk.default.red.bold("\n\u274C An error occurred during generation:"));
|