feat: implement toCamelCase utility function and update Clean Architecture generator to use it

This commit is contained in:
didavila
2026-03-24 15:12:52 +01:00
parent a8ecb15a09
commit 3fe2333a03
2 changed files with 29 additions and 20 deletions

View File

@@ -3,6 +3,7 @@ import path from 'path';
import mustache from 'mustache';
import { logStep, logSuccess, logInfo } from '../utils/logger';
import { mapSwaggerTypeToTs } from '../utils/type-mapper';
import { toCamelCase } from '../utils/name-formatter';
import type {
SwaggerAnalysis,
OpenApiSchema,
@@ -58,8 +59,8 @@ export function generateCleanArchitecture(
{
model: {
classname: baseName,
classFilename: baseName.toLowerCase(),
classVarName: baseName.charAt(0).toLowerCase() + baseName.slice(1),
classFilename: toCamelCase(baseName),
classVarName: toCamelCase(baseName),
description: schemaObj.description || '',
vars: varsMap
}
@@ -75,8 +76,8 @@ export function generateCleanArchitecture(
{
operations: {
classname: baseName,
classFilename: baseName.toLowerCase(),
classVarName: baseName.charAt(0).toLowerCase() + baseName.slice(1)
classFilename: toCamelCase(baseName),
classVarName: toCamelCase(baseName)
}
}
]
@@ -88,14 +89,10 @@ export function generateCleanArchitecture(
if (fs.existsSync(modelTemplatePath)) {
const template = fs.readFileSync(modelTemplatePath, 'utf8');
const output = mustache.render(template, modelViewData);
const destPath = path.join(
outputDir,
'entities/models',
`${baseName.toLowerCase()}.model.ts`
);
const destPath = path.join(outputDir, 'entities/models', `${toCamelCase(baseName)}.model.ts`);
fs.writeFileSync(destPath, output);
generatedCount.models++;
logInfo(` ${baseName.toLowerCase()}.model.ts → ${path.relative(process.cwd(), destPath)}`);
logInfo(` ${toCamelCase(baseName)}.model.ts → ${path.relative(process.cwd(), destPath)}`);
}
// Mapper
@@ -103,7 +100,7 @@ export function generateCleanArchitecture(
if (fs.existsSync(mapperTemplatePath)) {
const template = fs.readFileSync(mapperTemplatePath, 'utf8');
const output = mustache.render(template, mapperViewData);
const destPath = path.join(outputDir, 'data/mappers', `${baseName.toLowerCase()}.mapper.ts`);
const destPath = path.join(outputDir, 'data/mappers', `${toCamelCase(baseName)}.mapper.ts`);
fs.writeFileSync(destPath, output);
generatedCount.mappers++;
}
@@ -192,8 +189,8 @@ export function generateCleanArchitecture(
if (tagsMap[tag].some((op) => op.returnType === s || op.returnType === `Array<${s}>`)) {
imports.push({
classname: s,
classFilename: s.toLowerCase(),
classVarName: s.charAt(0).toLowerCase() + s.slice(1)
classFilename: toCamelCase(s),
classVarName: toCamelCase(s)
});
}
});
@@ -204,7 +201,7 @@ export function generateCleanArchitecture(
{
operations: {
classname: tag,
classFilename: tag.toLowerCase(),
classFilename: toCamelCase(tag),
constantName: tag.toUpperCase().replace(/[^A-Z0-9]/g, '_'),
operation: tagsMap[tag],
imports: imports
@@ -218,7 +215,7 @@ export function generateCleanArchitecture(
templatesDir,
'api.use-cases.contract.mustache',
apiViewData,
path.join(outputDir, 'domain/use-cases', `${tag.toLowerCase()}.use-cases.contract.ts`),
path.join(outputDir, 'domain/use-cases', `${toCamelCase(tag)}.use-cases.contract.ts`),
generatedCount,
'useCases'
);
@@ -227,7 +224,7 @@ export function generateCleanArchitecture(
templatesDir,
'api.use-cases.impl.mustache',
apiViewData,
path.join(outputDir, 'domain/use-cases', `${tag.toLowerCase()}.use-cases.impl.ts`),
path.join(outputDir, 'domain/use-cases', `${toCamelCase(tag)}.use-cases.impl.ts`),
generatedCount,
'useCases'
);
@@ -236,7 +233,7 @@ export function generateCleanArchitecture(
templatesDir,
'api.repository.contract.mustache',
apiViewData,
path.join(outputDir, 'domain/repositories', `${tag.toLowerCase()}.repository.contract.ts`),
path.join(outputDir, 'domain/repositories', `${toCamelCase(tag)}.repository.contract.ts`),
generatedCount,
'repositories'
);
@@ -245,7 +242,7 @@ export function generateCleanArchitecture(
templatesDir,
'api.repository.impl.mustache',
apiViewData,
path.join(outputDir, 'data/repositories', `${tag.toLowerCase()}.repository.impl.ts`),
path.join(outputDir, 'data/repositories', `${toCamelCase(tag)}.repository.impl.ts`),
generatedCount,
'repositories'
);
@@ -254,7 +251,7 @@ export function generateCleanArchitecture(
templatesDir,
'use-cases.provider.mustache',
apiViewData,
path.join(outputDir, 'di/use-cases', `${tag.toLowerCase()}.use-cases.provider.ts`),
path.join(outputDir, 'di/use-cases', `${toCamelCase(tag)}.use-cases.provider.ts`),
generatedCount,
'providers'
);
@@ -263,7 +260,7 @@ export function generateCleanArchitecture(
templatesDir,
'repository.provider.mustache',
apiViewData,
path.join(outputDir, 'di/repositories', `${tag.toLowerCase()}.repository.provider.ts`),
path.join(outputDir, 'di/repositories', `${toCamelCase(tag)}.repository.provider.ts`),
generatedCount,
'providers'
);

View File

@@ -0,0 +1,12 @@
/**
* Converts a PascalCase name to camelCase by lowercasing the first character.
* Used to derive class filenames and variable names from schema/tag names.
*
* @example
* toCamelCase('ProductResponse') // 'productResponse'
* toCamelCase('UserSchema') // 'userSchema'
*/
export function toCamelCase(name: string): string {
if (!name) return name;
return name.charAt(0).toLowerCase() + name.slice(1);
}