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