api-core-lib 12.0.70 → 12.0.73
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 +62 -32
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -82,8 +82,8 @@ var toCamelCase = (str) => {
|
|
|
82
82
|
const s = toPascalCase(str);
|
|
83
83
|
return s.charAt(0).toLowerCase() + s.slice(1);
|
|
84
84
|
};
|
|
85
|
-
var
|
|
86
|
-
var getActionName = (opId) => toCamelCase(opId.
|
|
85
|
+
var sanitizeForModuleName = (tagName) => `${toPascalCase(tagName.replace(/[^a-zA-Z0-9]/g, " "))}Api`;
|
|
86
|
+
var getActionName = (opId) => toCamelCase(opId.replace(/^(central|tenant)/i, "").replace(/_v\d+$/, ""));
|
|
87
87
|
var findCommonPath = (paths) => {
|
|
88
88
|
if (!paths || paths.length === 0) return "/";
|
|
89
89
|
const sorted = [...paths].sort();
|
|
@@ -94,7 +94,6 @@ var findCommonPath = (paths) => {
|
|
|
94
94
|
const prefix = first.substring(0, i);
|
|
95
95
|
return prefix.substring(0, prefix.lastIndexOf("/") + 1) || "/";
|
|
96
96
|
};
|
|
97
|
-
var generateFriendlyMessage = (fieldName) => `${fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase())} is required.`;
|
|
98
97
|
function parseSchema(name, schema, allEnums) {
|
|
99
98
|
const properties = [];
|
|
100
99
|
const enums = {};
|
|
@@ -137,9 +136,7 @@ function parseSpecToModules(spec) {
|
|
|
137
136
|
if (schema.type === "array" && schema.items) {
|
|
138
137
|
const itemSchema = schema.items;
|
|
139
138
|
const itemBaseName = `${baseName}Item`;
|
|
140
|
-
if (itemSchema.properties || itemSchema.type === "object") {
|
|
141
|
-
return `${registerSchema(itemSchema, itemBaseName)}[]`;
|
|
142
|
-
}
|
|
139
|
+
if (itemSchema.properties || itemSchema.type === "object") return `${registerSchema(itemSchema, itemBaseName)}[]`;
|
|
143
140
|
return `${itemSchema.type || "unknown"}[]`;
|
|
144
141
|
}
|
|
145
142
|
if (schema.type === "object" || schema.properties || schema.allOf || !schema.type) {
|
|
@@ -155,8 +152,9 @@ function parseSpecToModules(spec) {
|
|
|
155
152
|
for (const method in pathItem) {
|
|
156
153
|
if (!Object.values(import_openapi_types.OpenAPIV3.HttpMethods).includes(method)) continue;
|
|
157
154
|
const endpoint = pathItem[method];
|
|
158
|
-
if (!endpoint.operationId) continue;
|
|
159
|
-
const
|
|
155
|
+
if (!endpoint.tags || endpoint.tags.length === 0 || !endpoint.operationId) continue;
|
|
156
|
+
const tagName = endpoint.tags[0];
|
|
157
|
+
const moduleName = sanitizeForModuleName(tagName);
|
|
160
158
|
if (!modules.has(moduleName)) {
|
|
161
159
|
modules.set(moduleName, { moduleName, baseEndpoint: "", actions: {}, schemas: /* @__PURE__ */ new Set(), enums: /* @__PURE__ */ new Set() });
|
|
162
160
|
modulePaths.set(moduleName, []);
|
|
@@ -178,7 +176,8 @@ function parseSpecToModules(spec) {
|
|
|
178
176
|
if (schemaDef) Object.keys(schemaDef.enums).forEach((propName) => currentModule.enums.add(`${toPascalCase(cleanType)}${toPascalCase(propName)}Enum`));
|
|
179
177
|
}
|
|
180
178
|
});
|
|
181
|
-
|
|
179
|
+
const actionName = getActionName(endpoint.operationId);
|
|
180
|
+
currentModule.actions[actionName] = { name: actionName, 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 };
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
modules.forEach((mod, name) => {
|
|
@@ -265,9 +264,7 @@ ${prop.example ? ` * @example ${JSON.stringify(prop.example)}
|
|
|
265
264
|
let propType = prop.type;
|
|
266
265
|
if (prop.enum) propType = `${toPascalCase(typeName)}${toPascalCase(prop.name)}Enum`;
|
|
267
266
|
else if (prop.items) propType = prop.items.name ? `${toPascalCase(prop.items.name)}[]` : `${prop.items.type || "unknown"}[]`;
|
|
268
|
-
else if (prop.type === "object") propType = prop.properties && prop.properties.length > 0 ? `
|
|
269
|
-
${prop.properties.map((p) => ` ${p.name}${p.isRequired ? "" : "?"}: ${p.type};
|
|
270
|
-
`).join("")} }` : `Record<string, unknown>`;
|
|
267
|
+
else if (prop.type === "object") propType = prop.properties && prop.properties.length > 0 ? `Record<string, unknown>` : `Record<string, unknown>`;
|
|
271
268
|
typesContent += ` ${prop.name}${prop.isRequired ? "" : "?"}: ${propType};
|
|
272
269
|
`;
|
|
273
270
|
}
|
|
@@ -288,7 +285,7 @@ import { z } from 'zod';
|
|
|
288
285
|
for (const typeName of schemasToImport) {
|
|
289
286
|
const parsedSchema = allSchemas.get(typeName);
|
|
290
287
|
if (parsedSchema) {
|
|
291
|
-
let zodShape = parsedSchema.properties.map((p) => ` ${p.name}: ${_propToZod(p
|
|
288
|
+
let zodShape = parsedSchema.properties.map((p) => ` ${p.name}: ${_propToZod(p)}`).join(",\n");
|
|
292
289
|
validationContent += `export const ${typeName}Schema = z.object({
|
|
293
290
|
${zodShape}
|
|
294
291
|
});
|
|
@@ -324,37 +321,70 @@ import type { ${schemasToImport.join(", ")} } from './types';
|
|
|
324
321
|
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "index.ts"), indexContent.join("\n"));
|
|
325
322
|
console.log(import_chalk.default.gray(` \u2713 index.ts`));
|
|
326
323
|
}
|
|
327
|
-
function _propToZod(prop
|
|
328
|
-
let
|
|
329
|
-
const
|
|
324
|
+
function _propToZod(prop) {
|
|
325
|
+
let chain;
|
|
326
|
+
const requiredErrorMessage = { required_error: `${prop.name} is required.` };
|
|
330
327
|
switch (prop.type) {
|
|
331
328
|
case "string":
|
|
332
|
-
|
|
333
|
-
if (prop.format === "email")
|
|
334
|
-
if (prop.format === "uuid")
|
|
335
|
-
if (prop.
|
|
329
|
+
chain = `z.string({ ...requiredErrorMessage, invalid_type_error: "Expected a string for ${prop.name}" })`;
|
|
330
|
+
if (prop.format === "email") chain += `.email({ message: "Invalid email address for ${prop.name}" })`;
|
|
331
|
+
if (prop.format === "uuid") chain += `.uuid({ message: "Invalid UUID for ${prop.name}" })`;
|
|
332
|
+
if (prop.format === "url") chain += `.url({ message: "Invalid URL for ${prop.name}" })`;
|
|
333
|
+
if (prop.format === "datetime") chain += `.datetime({ message: "Invalid datetime format for ${prop.name}" })`;
|
|
334
|
+
if (prop.minLength !== void 0) chain += `.min(${prop.minLength}, { message: "${prop.name} must be at least ${prop.minLength} characters long" })`;
|
|
335
|
+
if (prop.maxLength !== void 0) chain += `.max(${prop.maxLength}, { message: "${prop.name} must be at most ${prop.maxLength} characters long" })`;
|
|
336
|
+
if (prop.pattern) chain += `.regex(/${prop.pattern}/, { message: "Invalid format for ${prop.name}" })`;
|
|
337
|
+
if (prop.enum) {
|
|
338
|
+
if (prop.enum.length > 0) {
|
|
339
|
+
chain = `z.enum(${JSON.stringify(prop.enum)})`;
|
|
340
|
+
} else {
|
|
341
|
+
chain = `z.string().refine(() => false, { message: "Enum for ${prop.name} is empty" })`;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
336
344
|
break;
|
|
337
345
|
case "integer":
|
|
346
|
+
chain = `z.number({ ...requiredErrorMessage, invalid_type_error: "Expected a number for ${prop.name}" }).int({ message: "${prop.name} must be an integer" })`;
|
|
347
|
+
if (prop.minimum !== void 0) chain += `.min(${prop.minimum}, { message: "${prop.name} must be at least ${prop.minimum}" })`;
|
|
348
|
+
if (prop.maximum !== void 0) chain += `.max(${prop.maximum}, { message: "${prop.name} must be at most ${prop.maximum}" })`;
|
|
349
|
+
break;
|
|
338
350
|
case "number":
|
|
339
|
-
|
|
351
|
+
chain = `z.number({ ...requiredErrorMessage, invalid_type_error: "Expected a number for ${prop.name}" })`;
|
|
352
|
+
if (prop.minimum !== void 0) chain += `.min(${prop.minimum}, { message: "${prop.name} must be at least ${prop.minimum}" })`;
|
|
353
|
+
if (prop.maximum !== void 0) chain += `.max(${prop.maximum}, { message: "${prop.name} must be at most ${prop.maximum}" })`;
|
|
340
354
|
break;
|
|
341
355
|
case "boolean":
|
|
342
|
-
|
|
356
|
+
chain = `z.boolean({ ...requiredErrorMessage, invalid_type_error: "Expected a boolean for ${prop.name}" })`;
|
|
343
357
|
break;
|
|
344
358
|
case "array":
|
|
345
|
-
|
|
359
|
+
const itemSchema = prop.items ? _propToZod(prop.items) : "z.any()";
|
|
360
|
+
chain = `z.array(${itemSchema})`;
|
|
361
|
+
if (prop.minItems !== void 0) chain += `.min(${prop.minItems}, { message: "${prop.name} must contain at least ${prop.minItems} item(s)" })`;
|
|
362
|
+
if (prop.maxItems !== void 0) chain += `.max(${prop.maxItems}, { message: "${prop.name} must contain at most ${prop.maxItems} item(s)" })`;
|
|
346
363
|
break;
|
|
347
364
|
case "object":
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
365
|
+
if (prop.properties && prop.properties.length > 0) {
|
|
366
|
+
const shape = prop.properties.map((p) => ` ${p.name}: ${_propToZod(p)}`).join(",\n");
|
|
367
|
+
chain = `z.object({
|
|
368
|
+
${shape}
|
|
369
|
+
})`;
|
|
370
|
+
} else {
|
|
371
|
+
chain = "z.record(z.unknown())";
|
|
372
|
+
}
|
|
353
373
|
break;
|
|
374
|
+
default:
|
|
375
|
+
chain = "z.any()";
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
if (prop.description) {
|
|
379
|
+
chain += `.describe(${JSON.stringify(prop.description)})`;
|
|
380
|
+
}
|
|
381
|
+
if (!prop.isRequired) {
|
|
382
|
+
chain += ".optional()";
|
|
383
|
+
}
|
|
384
|
+
if (prop.isNullable) {
|
|
385
|
+
chain += ".nullable()";
|
|
354
386
|
}
|
|
355
|
-
|
|
356
|
-
if (prop.isNullable) zodString += ".nullable()";
|
|
357
|
-
return zodString;
|
|
387
|
+
return chain;
|
|
358
388
|
}
|
|
359
389
|
function _propToMock(prop) {
|
|
360
390
|
if (prop.example) return prop.example;
|
|
@@ -383,7 +413,7 @@ function _propToMock(prop) {
|
|
|
383
413
|
}
|
|
384
414
|
}
|
|
385
415
|
async function runGenerator(options) {
|
|
386
|
-
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Development Platform Generator (
|
|
416
|
+
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Development Platform Generator (Sapphire Edition)..."));
|
|
387
417
|
import_dotenv.default.config({ path: options.envPath });
|
|
388
418
|
const specUrl = process.env.OPENAPI_SPEC_URL || "./swagger.json";
|
|
389
419
|
try {
|