api-core-lib 12.0.86 → 12.0.88
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 +215 -12
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -75,6 +75,72 @@ 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
77
|
|
|
78
|
+
// src/generator/core/_propToZod.ts
|
|
79
|
+
function _propToZod(prop) {
|
|
80
|
+
let zodChain;
|
|
81
|
+
const getMsg = (key) => `{ "message": "validation.${key}" }`;
|
|
82
|
+
switch (prop.type) {
|
|
83
|
+
case "string":
|
|
84
|
+
if (prop.enumName) {
|
|
85
|
+
zodChain = `z.enum(${prop.enumName})`;
|
|
86
|
+
} else {
|
|
87
|
+
zodChain = "z.string()";
|
|
88
|
+
if (prop.isRequired) {
|
|
89
|
+
zodChain += `.min(1, ${getMsg("string.nonempty")})`;
|
|
90
|
+
}
|
|
91
|
+
if (prop.maxLength !== void 0) zodChain += `.max(${prop.maxLength}, ${getMsg("string.max")})`;
|
|
92
|
+
if (prop.pattern) zodChain += `.regex(/${prop.pattern}/, ${getMsg("string.regex")})`;
|
|
93
|
+
if (prop.format === "email") zodChain += `.email(${getMsg("string.email")})`;
|
|
94
|
+
if (prop.format === "url") zodChain += `.url(${getMsg("string.url")})`;
|
|
95
|
+
if (prop.format === "uuid") zodChain += `.uuid(${getMsg("string.uuid")})`;
|
|
96
|
+
if (prop.format === "datetime") zodChain += `.datetime(${getMsg("string.datetime")})`;
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
case "integer":
|
|
100
|
+
zodChain = `z.number().int(${getMsg("number.integer")})`;
|
|
101
|
+
if (prop.minimum !== void 0) zodChain += `.min(${prop.minimum}, ${getMsg("number.min")})`;
|
|
102
|
+
if (prop.maximum !== void 0) zodChain += `.max(${prop.maximum}, ${getMsg("number.max")})`;
|
|
103
|
+
break;
|
|
104
|
+
case "number":
|
|
105
|
+
zodChain = `z.number()`;
|
|
106
|
+
if (prop.minimum !== void 0) zodChain += `.min(${prop.minimum}, ${getMsg("number.min")})`;
|
|
107
|
+
if (prop.maximum !== void 0) zodChain += `.max(${prop.maximum}, ${getMsg("number.max")})`;
|
|
108
|
+
break;
|
|
109
|
+
case "boolean":
|
|
110
|
+
zodChain = `z.boolean()`;
|
|
111
|
+
break;
|
|
112
|
+
case "array":
|
|
113
|
+
const itemSchema = prop.items ? _propToZod(prop.items) : "z.any()";
|
|
114
|
+
zodChain = `z.array(${itemSchema})`;
|
|
115
|
+
if (prop.minItems !== void 0) zodChain += `.min(${prop.minItems}, ${getMsg("array.min")})`;
|
|
116
|
+
if (prop.maxItems !== void 0) zodChain += `.max(${prop.maxItems}, ${getMsg("array.max")})`;
|
|
117
|
+
break;
|
|
118
|
+
case "object":
|
|
119
|
+
if (prop.properties && prop.properties.length > 0) {
|
|
120
|
+
const shape = prop.properties.map((p) => ` ${p.name}: ${_propToZod(p)}`).join(",\n");
|
|
121
|
+
zodChain = `z.object({
|
|
122
|
+
${shape}
|
|
123
|
+
})`;
|
|
124
|
+
} else {
|
|
125
|
+
zodChain = "z.record(z.unknown())";
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
zodChain = "z.any()";
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
if (prop.description) {
|
|
133
|
+
zodChain += `.describe(${JSON.stringify(prop.description)})`;
|
|
134
|
+
}
|
|
135
|
+
if (!prop.isRequired) {
|
|
136
|
+
zodChain += ".optional()";
|
|
137
|
+
}
|
|
138
|
+
if (prop.isNullable) {
|
|
139
|
+
zodChain += ".nullable()";
|
|
140
|
+
}
|
|
141
|
+
return zodChain;
|
|
142
|
+
}
|
|
143
|
+
|
|
78
144
|
// src/generator/utils/index.ts
|
|
79
145
|
var getActionName = (opId) => {
|
|
80
146
|
const cleanOpId = opId.replace(/_v\d+$/, "");
|
|
@@ -256,25 +322,139 @@ async function generateModuleFiles(module2, allSchemas, allEnums, outputDir) {
|
|
|
256
322
|
if (!import_fs.default.existsSync(moduleOutputPath)) import_fs.default.mkdirSync(moduleOutputPath, { recursive: true });
|
|
257
323
|
console.log(import_chalk.default.cyan(`
|
|
258
324
|
Generating module: ${import_chalk.default.bold(module2.moduleName)}`));
|
|
259
|
-
const
|
|
325
|
+
const BUILT_IN_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "void", "undefined", "unknown", "any", "Date", "Promise", "QueryOptions", "Record<string, any>", "Record<string, unknown>"]);
|
|
326
|
+
const schemasToImport = [...module2.schemas].filter((name) => !BUILT_IN_TYPES.has(name)).sort();
|
|
260
327
|
const enumsToImport = [...module2.enums].sort();
|
|
261
|
-
const
|
|
328
|
+
const createdFileExports = ["config"];
|
|
329
|
+
let configContent = `// This file is auto-generated. Do not edit directly.
|
|
330
|
+
|
|
331
|
+
import type { ApiModuleConfig, ActionConfigModule } from 'api-core-lib';
|
|
332
|
+
`;
|
|
333
|
+
if (schemasToImport.length > 0) configContent += `import type { ${schemasToImport.join(", ")} } from './types';
|
|
334
|
+
`;
|
|
335
|
+
const actionsType = Object.values(module2.actions).map((a) => ` ${a.name}: ActionConfigModule<${a.inputType}, ${a.outputType}>;`).join("\n");
|
|
336
|
+
const actionsValue = Object.values(module2.actions).map((a) => {
|
|
337
|
+
const { inputType, outputType, name, ...c } = a;
|
|
338
|
+
return ` ${name}: ${JSON.stringify(c, null, 2).replace(/\n/g, "\n ")}`;
|
|
339
|
+
}).join(",\n");
|
|
340
|
+
configContent += `
|
|
341
|
+
export const ${module2.moduleName}: ApiModuleConfig<{
|
|
342
|
+
${actionsType}
|
|
343
|
+
}> = {
|
|
344
|
+
baseEndpoint: '${module2.baseEndpoint}',
|
|
345
|
+
actions: {
|
|
346
|
+
${actionsValue}
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
`;
|
|
350
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "config.ts"), configContent.trim());
|
|
351
|
+
console.log(import_chalk.default.gray(` \u2713 config.ts`));
|
|
262
352
|
if (schemasToImport.length > 0) {
|
|
263
|
-
if (enumsToImport.length > 0)
|
|
264
|
-
|
|
353
|
+
if (enumsToImport.length > 0) {
|
|
354
|
+
let enumsContent = `// This file is auto-generated. Do not edit directly.
|
|
355
|
+
|
|
356
|
+
`;
|
|
357
|
+
enumsToImport.forEach((enumName) => {
|
|
358
|
+
const enumDef = allEnums.get(enumName);
|
|
359
|
+
if (enumDef) {
|
|
360
|
+
enumsContent += `export const ${enumName} = ${JSON.stringify(enumDef.values)} as const;
|
|
361
|
+
`;
|
|
362
|
+
enumsContent += `export type ${enumName} = typeof ${enumName}[number];
|
|
363
|
+
|
|
364
|
+
`;
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "enums.ts"), enumsContent.trim());
|
|
368
|
+
console.log(import_chalk.default.gray(` \u2713 enums.ts`));
|
|
369
|
+
createdFileExports.push("enums");
|
|
370
|
+
}
|
|
371
|
+
let typesContent = `// This file is auto-generated. Do not edit directly.
|
|
372
|
+
|
|
373
|
+
`;
|
|
374
|
+
if (enumsToImport.length > 0) typesContent += `import type { ${enumsToImport.join(", ")} } from './enums';
|
|
375
|
+
|
|
376
|
+
`;
|
|
377
|
+
schemasToImport.forEach((typeName) => {
|
|
378
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
379
|
+
if (parsedSchema) {
|
|
380
|
+
if (parsedSchema.description) typesContent += `/** ${parsedSchema.description} */
|
|
381
|
+
`;
|
|
382
|
+
typesContent += `export interface ${typeName} {
|
|
383
|
+
`;
|
|
384
|
+
parsedSchema.properties.forEach((prop) => {
|
|
385
|
+
if (prop.description) typesContent += ` /** ${prop.description} */
|
|
386
|
+
`;
|
|
387
|
+
let propType = prop.enumName || (prop.items ? `${prop.items.type || "any"}[]` : prop.type);
|
|
388
|
+
if (propType === "integer") propType = "number";
|
|
389
|
+
if (propType === "object") propType = "Record<string, any>";
|
|
390
|
+
typesContent += ` ${prop.name}${prop.isRequired ? "" : "?"}: ${propType};
|
|
391
|
+
`;
|
|
392
|
+
});
|
|
393
|
+
typesContent += `}
|
|
394
|
+
|
|
395
|
+
`;
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "types.ts"), typesContent.trim());
|
|
399
|
+
console.log(import_chalk.default.gray(` \u2713 types.ts`));
|
|
400
|
+
createdFileExports.push("types");
|
|
401
|
+
let validationContent = `// This file is auto-generated. Do not edit directly.
|
|
402
|
+
|
|
403
|
+
import { z } from 'zod';
|
|
404
|
+
`;
|
|
405
|
+
if (enumsToImport.length > 0) validationContent += `import { ${enumsToImport.join(", ")} } from './enums';
|
|
406
|
+
`;
|
|
407
|
+
schemasToImport.forEach((typeName) => {
|
|
408
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
409
|
+
if (parsedSchema) {
|
|
410
|
+
const zodShape = parsedSchema.properties.map((p) => ` ${p.name}: ${_propToZod(p)}`).join(",\n");
|
|
411
|
+
validationContent += `
|
|
412
|
+
/** Zod schema for {@link ${typeName}}. */
|
|
413
|
+
`;
|
|
414
|
+
validationContent += `export const ${typeName}Schema = z.object({
|
|
415
|
+
${zodShape}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
`;
|
|
419
|
+
validationContent += `export type ${typeName}Validated = z.infer<typeof ${typeName}Schema>;
|
|
420
|
+
`;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "validation.ts"), validationContent.trim());
|
|
424
|
+
console.log(import_chalk.default.gray(` \u2713 validation.ts`));
|
|
425
|
+
createdFileExports.push("validation");
|
|
426
|
+
let mocksContent = `// This file is auto-generated. Do not edit directly.
|
|
427
|
+
import type { ${schemasToImport.join(", ")} } from './types';
|
|
428
|
+
`;
|
|
429
|
+
if (enumsToImport.length > 0) mocksContent += `import { ${enumsToImport.join(", ")} } from './enums';
|
|
430
|
+
|
|
431
|
+
`;
|
|
432
|
+
schemasToImport.forEach((typeName) => {
|
|
433
|
+
const parsedSchema = allSchemas.get(typeName);
|
|
434
|
+
if (parsedSchema) {
|
|
435
|
+
const mockObject = {};
|
|
436
|
+
parsedSchema.properties.forEach((p) => {
|
|
437
|
+
mockObject[p.name] = _propToMock(p);
|
|
438
|
+
});
|
|
439
|
+
mocksContent += `export const mock${typeName}: ${typeName} = ${JSON.stringify(mockObject, null, 2)};
|
|
440
|
+
|
|
441
|
+
`;
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
import_fs.default.writeFileSync(import_path.default.join(moduleOutputPath, "mocks.ts"), mocksContent.trim());
|
|
445
|
+
console.log(import_chalk.default.gray(` \u2713 mocks.ts`));
|
|
446
|
+
createdFileExports.push("mocks");
|
|
265
447
|
}
|
|
448
|
+
const indexFilePath = import_path.default.join(moduleOutputPath, "index.ts");
|
|
266
449
|
const initialIndexContent = `// This file is auto-generated. Do not edit directly.
|
|
267
450
|
|
|
268
|
-
` +
|
|
269
|
-
const indexFilePath = import_path.default.join(moduleOutputPath, "index.ts");
|
|
451
|
+
` + createdFileExports.map((e) => `export * from './${e}';`).join("\n");
|
|
270
452
|
import_fs.default.writeFileSync(indexFilePath, initialIndexContent);
|
|
271
453
|
console.log(import_chalk.default.gray(` \u2713 index.ts (Initial)`));
|
|
272
454
|
const moduleBaseName = module2.moduleName.replace(/Api$/, "");
|
|
273
455
|
const camelCaseModuleName = toCamelCase(moduleBaseName);
|
|
274
456
|
const allPathParams = /* @__PURE__ */ new Set();
|
|
275
|
-
Object.values(module2.actions).forEach((action) =>
|
|
276
|
-
action.pathParams.forEach((param) => allPathParams.add(param));
|
|
277
|
-
});
|
|
457
|
+
Object.values(module2.actions).forEach((action) => action.pathParams.forEach((param) => allPathParams.add(param)));
|
|
278
458
|
const pathParamsType = allPathParams.size > 0 ? `{ ${[...allPathParams].map((p) => `${p}?: string | number`).join("; ")} }` : "Record<string, never>";
|
|
279
459
|
let endpointsContent = `// This file is auto-generated. Do not edit directly.
|
|
280
460
|
|
|
@@ -337,14 +517,12 @@ import { ${module2.moduleName} } from './config';
|
|
|
337
517
|
|
|
338
518
|
type ModulePathParams = ${pathParamsType};
|
|
339
519
|
|
|
340
|
-
// Options for the custom hook, extending the base options with typed path parameters.
|
|
341
520
|
type ${moduleBaseName}ApiOptions = Omit<UseApiModuleOptions, 'pathParams'> & {
|
|
342
521
|
pathParams?: ModulePathParams;
|
|
343
522
|
};
|
|
344
523
|
|
|
345
524
|
/**
|
|
346
525
|
* Custom hook for interacting with the ${moduleBaseName} API module.
|
|
347
|
-
* Simplifies API calls by pre-configuring the API client and module.
|
|
348
526
|
*/
|
|
349
527
|
export const use${moduleBaseName}Api = (options: ${moduleBaseName}ApiOptions = {}) => {
|
|
350
528
|
return useApiModule<typeof TModuleType['actions']>(apiClient, ${module2.moduleName}, options);
|
|
@@ -398,12 +576,37 @@ export const create${moduleBaseName}ServerApi = () => {
|
|
|
398
576
|
`export * from './${camelCaseModuleName}.endpoints';`,
|
|
399
577
|
`export * from './use${moduleBaseName}';`,
|
|
400
578
|
`export * from './${moduleBaseName}.provider';`,
|
|
401
|
-
// <-- Note: no .tsx in export
|
|
402
579
|
`export * from './${camelCaseModuleName}.server';`
|
|
403
580
|
].join("\n");
|
|
404
581
|
import_fs.default.appendFileSync(indexFilePath, newExports);
|
|
405
582
|
console.log(import_chalk.default.gray(` \u2713 index.ts (Updated with helpers)`));
|
|
406
583
|
}
|
|
584
|
+
function _propToMock(prop) {
|
|
585
|
+
if (prop.example) return prop.example;
|
|
586
|
+
if (prop.name.match(/image|avatar|logo|url/i)) return "https://via.placeholder.com/150";
|
|
587
|
+
if (prop.enum) return prop.enum[0];
|
|
588
|
+
switch (prop.type) {
|
|
589
|
+
case "string":
|
|
590
|
+
if (prop.format === "email") return "test@example.com";
|
|
591
|
+
if (prop.format === "uuid") return "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11";
|
|
592
|
+
return `Mock ${toPascalCase(prop.name)}`;
|
|
593
|
+
case "integer":
|
|
594
|
+
case "number":
|
|
595
|
+
return 1;
|
|
596
|
+
case "boolean":
|
|
597
|
+
return true;
|
|
598
|
+
case "array":
|
|
599
|
+
return prop.items ? [_propToMock(prop.items)] : [];
|
|
600
|
+
case "object":
|
|
601
|
+
const mock = {};
|
|
602
|
+
if (prop.properties) prop.properties.forEach((p) => {
|
|
603
|
+
mock[p.name] = _propToMock(p);
|
|
604
|
+
});
|
|
605
|
+
return mock;
|
|
606
|
+
default:
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
407
610
|
async function runGenerator(options) {
|
|
408
611
|
console.log(import_chalk.default.cyan.bold("\u{1F680} Starting API Development Platform Generator (Sapphire Edition)..."));
|
|
409
612
|
import_dotenv.default.config({ path: options.envPath });
|