From 3fe2333a0303260935333f6eb9312633f06a23d7 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 15:12:52 +0100 Subject: [PATCH 01/10] feat: implement toCamelCase utility function and update Clean Architecture generator to use it --- src/generators/clean-arch.generator.ts | 37 ++++++++++++-------------- src/utils/name-formatter.ts | 12 +++++++++ 2 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 src/utils/name-formatter.ts diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index b4b34f7..d9b0203 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -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' ); diff --git a/src/utils/name-formatter.ts b/src/utils/name-formatter.ts new file mode 100644 index 0000000..c6ff94b --- /dev/null +++ b/src/utils/name-formatter.ts @@ -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); +} From fc3d95052cd1f6bb55d992831994cac0785b26c7 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 15:15:06 +0100 Subject: [PATCH 02/10] fix: update import paths for repository and mapper templates --- templates/api.repository.impl.mustache | 6 +++--- templates/mapper.mustache | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/api.repository.impl.mustache b/templates/api.repository.impl.mustache index e02ce0d..7f025b8 100644 --- a/templates/api.repository.impl.mustache +++ b/templates/api.repository.impl.mustache @@ -9,11 +9,11 @@ import { environment } from '@environment'; import { MRepository } from '@mercadona/core/utils/repository'; -import { {{classname}}Repository } from '../../../domain/repositories/{{classFilename}}.repository.contract'; +import { {{classname}}Repository } from '@/domain/repositories/{{classFilename}}.repository.contract'; {{#imports}} -import { {{classname}}Dto } from '@/dtos/{{classFilename}}/{{classFilename}}.dto'; +import { {{classname}}Dto } from '@/dtos/{{classFilename}}.dto'; import { {{classname}} } from '@/entities/models/{{classFilename}}.model'; -import { {{classVarName}}Mapper } from '@/mappers/{{classFilename}}/{{classFilename}}.mapper'; +import { {{classVarName}}Mapper } from '@/mappers/{{classFilename}}.mapper'; {{/imports}} /** diff --git a/templates/mapper.mustache b/templates/mapper.mustache index 3ea1ce5..418ed34 100644 --- a/templates/mapper.mustache +++ b/templates/mapper.mustache @@ -4,7 +4,7 @@ import { MapFromFn } from '@mercadona/common/public'; import { Builder } from '@mercadona/common/utils'; -import { {{classname}}Dto } from '@/dtos/{{classFilename}}/{{classFilename}}.dto'; +import { {{classname}}Dto } from '@/dtos/{{classFilename}}.dto'; import { {{classname}} } from '@/entities/models/{{classFilename}}.model'; /** From f4d9340137387e4a6a907b6d4b2e07d35c576a44 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 15:37:26 +0100 Subject: [PATCH 03/10] feat: add returnTypeVarName and returnBaseTypeVarName to TagOperation interface and update generator function --- src/generators/clean-arch.generator.ts | 2 ++ src/types/openapi.types.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index d9b0203..710bb7a 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -175,6 +175,8 @@ export function generateCleanArchitecture( bodyParam: 'body', returnType: returnType !== 'void' ? returnType : false, returnBaseType: returnBaseType !== 'void' ? returnBaseType : false, + returnTypeVarName: returnType !== 'void' ? toCamelCase(returnType) : false, + returnBaseTypeVarName: returnBaseType !== 'void' ? toCamelCase(returnBaseType) : false, isListContainer: isListContainer, vendorExtensions: {} }); diff --git a/src/types/openapi.types.ts b/src/types/openapi.types.ts index 9b59ce6..2759cd1 100644 --- a/src/types/openapi.types.ts +++ b/src/types/openapi.types.ts @@ -78,6 +78,8 @@ export interface TagOperation { bodyParam: string; returnType: string | boolean; returnBaseType: string | boolean; + returnTypeVarName: string | boolean; + returnBaseTypeVarName: string | boolean; isListContainer: boolean; vendorExtensions: Record; } From 82b734bc556a39480eac24906527a21870dc077d Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 15:37:34 +0100 Subject: [PATCH 04/10] fix: correct import paths in use cases provider and update response mapping in repository implementation --- templates/api.repository.impl.mustache | 4 ++-- templates/use-cases.provider.mustache | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/api.repository.impl.mustache b/templates/api.repository.impl.mustache index 7f025b8..f02fbaa 100644 --- a/templates/api.repository.impl.mustache +++ b/templates/api.repository.impl.mustache @@ -33,7 +33,7 @@ export class {{classname}}RepositoryImpl extends MRepository implements {{classn params: { {{#queryParams}}{{paramName}}{{^-last}}, {{/-last}}{{/queryParams}} } }{{/hasQueryParams}}{{#hasBodyParam}}, {{bodyParam}}{{/hasBodyParam}}) .pipe( - map((response) => response.{{#vendorExtensions}}{{x-response-property}}{{/vendorExtensions}}{{^vendorExtensions}}items{{/vendorExtensions}}.map({{{returnBaseType}}}Mapper)) + map((response) => response.{{#vendorExtensions}}{{x-response-property}}{{/vendorExtensions}}{{^vendorExtensions}}items{{/vendorExtensions}}.map({{{returnBaseTypeVarName}}}Mapper)) ); {{/isListContainer}} {{^isListContainer}} @@ -42,7 +42,7 @@ export class {{classname}}RepositoryImpl extends MRepository implements {{classn params: { {{#queryParams}}{{paramName}}{{^-last}}, {{/-last}}{{/queryParams}} } }{{/hasQueryParams}}{{#hasBodyParam}}, {{bodyParam}}{{/hasBodyParam}}) .pipe( - map({{{returnType}}}Mapper) + map({{{returnTypeVarName}}}Mapper) ); {{/returnType}} {{^returnType}} diff --git a/templates/use-cases.provider.mustache b/templates/use-cases.provider.mustache index 19ed974..58a4f0b 100644 --- a/templates/use-cases.provider.mustache +++ b/templates/use-cases.provider.mustache @@ -3,8 +3,8 @@ {{#operations}} import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core'; -import { {{constantName}}_USE_CASES } from '@/domain/use-cases/{{classFilename}}/{{classFilename}}.use-cases.contract'; -import { {{classname}}UseCasesImpl } from '@/domain/use-cases/{{classFilename}}/{{classFilename}}.use-cases.impl'; +import { {{constantName}}_USE_CASES } from '@/domain/use-cases/{{classFilename}}.use-cases.contract'; +import { {{classname}}UseCasesImpl } from '@/domain/use-cases/{{classFilename}}.use-cases.impl'; /** * {{classname}} Use Cases Provider From 031bdb4b3a5372fdf536b1932ed2b90b8fdd5281 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 15:44:10 +0100 Subject: [PATCH 05/10] feat: add classVarName to operations in generateCleanArchitecture function --- src/generators/clean-arch.generator.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index 710bb7a..e4981f5 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -204,6 +204,7 @@ export function generateCleanArchitecture( operations: { classname: tag, classFilename: toCamelCase(tag), + classVarName: toCamelCase(tag), constantName: tag.toUpperCase().replace(/[^A-Z0-9]/g, '_'), operation: tagsMap[tag], imports: imports From a97c3b22facd9189d0c3ddc580e0d26c6aece320 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 15:52:11 +0100 Subject: [PATCH 06/10] feat: enhance TagOperation interface with detailed parameter structure and update return type handling in generator --- src/generators/clean-arch.generator.ts | 8 +++++++- src/types/openapi.types.ts | 10 +++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index e4981f5..878b37d 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -188,7 +188,13 @@ export function generateCleanArchitecture( Object.keys(tagsMap).forEach((tag) => { const imports: { classname: string; classFilename: string; classVarName: string }[] = []; Object.keys(schemas).forEach((s) => { - if (tagsMap[tag].some((op) => op.returnType === s || op.returnType === `Array<${s}>`)) { + const usedAsReturn = tagsMap[tag].some( + (op) => op.returnType === s || op.returnType === `Array<${s}>` + ); + const usedAsParam = tagsMap[tag].some((op) => + op.allParams.some((p) => p.dataType === s || p.dataType === `Array<${s}>`) + ); + if (usedAsReturn || usedAsParam) { imports.push({ classname: s, classFilename: toCamelCase(s), diff --git a/src/types/openapi.types.ts b/src/types/openapi.types.ts index 2759cd1..1ff7a85 100644 --- a/src/types/openapi.types.ts +++ b/src/types/openapi.types.ts @@ -65,13 +65,21 @@ export interface OpenApiOperation { * Operación normalizada y lista para ser consumida por los templates Mustache. * Cada instancia representa un endpoint agrupado bajo un tag del API. */ +export interface TagOperationParam { + paramName: string; + dataType: string; + description: string; + required: boolean; + '-last': boolean; +} + export interface TagOperation { nickname: string; summary: string; notes: string; httpMethod: string; path: string; - allParams: unknown[]; + allParams: TagOperationParam[]; hasQueryParams: boolean; queryParams: unknown[]; hasBodyParam: boolean; From e8c919ee7698068aba8f7cddca00a3ddc59588c4 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 16:02:17 +0100 Subject: [PATCH 07/10] feat: collect and render model imports for referenced types in Clean Architecture generation --- src/generators/clean-arch.generator.ts | 14 ++++++++++++++ templates/model.mustache | 3 +++ 2 files changed, 17 insertions(+) diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index 878b37d..92fa261 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -54,6 +54,19 @@ export function generateCleanArchitecture( }; }); + // Collect imports for types referenced via $ref in properties + const referencedTypes = new Set(); + Object.values(rawProperties).forEach((prop) => { + if (prop.$ref) { + referencedTypes.add(prop.$ref.split('/').pop() || ''); + } else if (prop.type === 'array' && prop.items?.$ref) { + referencedTypes.add(prop.items.$ref.split('/').pop() || ''); + } + }); + const modelImports = [...referencedTypes] + .filter(Boolean) + .map((name) => ({ classname: name, classFilename: toCamelCase(name) })); + const modelViewData = { models: [ { @@ -62,6 +75,7 @@ export function generateCleanArchitecture( classFilename: toCamelCase(baseName), classVarName: toCamelCase(baseName), description: schemaObj.description || '', + imports: modelImports, vars: varsMap } } diff --git a/templates/model.mustache b/templates/model.mustache index 8139b1f..4224b8b 100644 --- a/templates/model.mustache +++ b/templates/model.mustache @@ -1,5 +1,8 @@ {{#models}} {{#model}} +{{#imports}} +import { {{classname}} } from './{{classFilename}}.dto'; +{{/imports}} /** * {{classname}} DTO * {{#description}}{{description}}{{/description}} From e008144813071e77b355cb96bb99eae27425cfac Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 16:27:10 +0100 Subject: [PATCH 08/10] refactor: normalize array type notation from Array to T[] in generators and type mapper --- src/generators/clean-arch.generator.ts | 8 ++++---- src/generators/dto.generator.ts | 15 ++++++++++----- src/utils/type-mapper.ts | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index 92fa261..2bf48b2 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -44,7 +44,7 @@ export function generateCleanArchitecture( if (rawProperties[k].$ref) { tsType = rawProperties[k].$ref.split('/').pop() || 'unknown'; } else if (rawProperties[k].type === 'array' && rawProperties[k].items?.$ref) { - tsType = `Array<${rawProperties[k].items.$ref.split('/').pop()}>`; + tsType = `${rawProperties[k].items.$ref.split('/').pop()}[]`; } return { name: k, @@ -163,7 +163,7 @@ export function generateCleanArchitecture( returnBaseType = returnType; } else if (responseSchema.type === 'array' && responseSchema.items?.$ref) { returnBaseType = responseSchema.items.$ref.split('/').pop() || 'unknown'; - returnType = `Array<${returnBaseType}>`; + returnType = `${returnBaseType}[]`; isListContainer = true; } } @@ -203,10 +203,10 @@ export function generateCleanArchitecture( const imports: { classname: string; classFilename: string; classVarName: string }[] = []; Object.keys(schemas).forEach((s) => { const usedAsReturn = tagsMap[tag].some( - (op) => op.returnType === s || op.returnType === `Array<${s}>` + (op) => op.returnType === s || op.returnType === `${s}[]` ); const usedAsParam = tagsMap[tag].some((op) => - op.allParams.some((p) => p.dataType === s || p.dataType === `Array<${s}>`) + op.allParams.some((p) => p.dataType === s || p.dataType === `${s}[]`) ); if (usedAsReturn || usedAsParam) { imports.push({ diff --git a/src/generators/dto.generator.ts b/src/generators/dto.generator.ts index d52d18d..83a7747 100644 --- a/src/generators/dto.generator.ts +++ b/src/generators/dto.generator.ts @@ -61,7 +61,7 @@ export function organizeFiles(tempDir: string, outputDir: string): void { logSuccess(`${filesMoved} DTOs movidos correctamente`); } -/** Post-procesa los DTOs generados añadiendo los imports de tipos referenciados. */ +/** Post-procesa los DTOs generados añadiendo imports y normalizando Array → T[]. */ export function addDtoImports(outputDir: string): void { logStep('Añadiendo imports a los DTOs generados...'); @@ -85,11 +85,15 @@ export function addDtoImports(outputDir: string): void { files.forEach((file) => { const filePath = path.join(dtosDir, file); - let content = fs.readFileSync(filePath, 'utf8'); + const originalContent = fs.readFileSync(filePath, 'utf8'); + let content = originalContent; const selfMatch = content.match(/export interface (\w+)/); const selfName = selfMatch ? selfMatch[1] : ''; + // Normalize Array → T[] (openapi-generator-cli always outputs Array) + content = content.replace(/Array<(\w+)>/g, '$1[]'); + // Find all Dto type references in the file body (excluding the interface name itself) const references = new Set(); const typeRegex = /\b(\w+Dto)\b/g; @@ -100,8 +104,6 @@ export function addDtoImports(outputDir: string): void { } } - if (references.size === 0) return; - // Build import lines for each referenced type that exists in the dtoMap const imports: string[] = []; references.forEach((ref) => { @@ -112,9 +114,12 @@ export function addDtoImports(outputDir: string): void { if (imports.length > 0) { content = imports.join('\n') + '\n' + content; + } + + if (content !== originalContent) { fs.writeFileSync(filePath, content); filesProcessed++; - logInfo(` Imports añadidos a ${file}`); + logInfo(` Procesado ${file}`); } }); diff --git a/src/utils/type-mapper.ts b/src/utils/type-mapper.ts index f128eb2..b6529b1 100644 --- a/src/utils/type-mapper.ts +++ b/src/utils/type-mapper.ts @@ -7,7 +7,7 @@ export function mapSwaggerTypeToTs(type?: string): string { string: 'string', boolean: 'boolean', number: 'number', - array: 'Array', + array: 'unknown[]', object: 'unknown' }; return typeMap[type] || 'unknown'; From ca63b85086d580d7d70c5cbca0a659258ecac565 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 16:31:17 +0100 Subject: [PATCH 09/10] refactor: remove unused imports section from model template --- templates/model.mustache | 3 --- 1 file changed, 3 deletions(-) diff --git a/templates/model.mustache b/templates/model.mustache index 4224b8b..8139b1f 100644 --- a/templates/model.mustache +++ b/templates/model.mustache @@ -1,8 +1,5 @@ {{#models}} {{#model}} -{{#imports}} -import { {{classname}} } from './{{classFilename}}.dto'; -{{/imports}} /** * {{classname}} DTO * {{#description}}{{description}}{{/description}} From 5229a3ad45655d03f574feec5117a77fb6bda8d8 Mon Sep 17 00:00:00 2001 From: didavila Date: Tue, 24 Mar 2026 16:40:34 +0100 Subject: [PATCH 10/10] refactor: separate return and param imports in Clean Architecture generator --- src/generators/clean-arch.generator.ts | 25 +++++++++++++++++-------- templates/api.repository.impl.mustache | 7 +++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/generators/clean-arch.generator.ts b/src/generators/clean-arch.generator.ts index 2bf48b2..17c09f2 100644 --- a/src/generators/clean-arch.generator.ts +++ b/src/generators/clean-arch.generator.ts @@ -200,7 +200,9 @@ export function generateCleanArchitecture( // Generar por cada Tag Object.keys(tagsMap).forEach((tag) => { - const imports: { classname: string; classFilename: string; classVarName: string }[] = []; + const returnImports: { classname: string; classFilename: string; classVarName: string }[] = []; + const paramImports: { classname: string; classFilename: string; classVarName: string }[] = []; + Object.keys(schemas).forEach((s) => { const usedAsReturn = tagsMap[tag].some( (op) => op.returnType === s || op.returnType === `${s}[]` @@ -208,12 +210,14 @@ export function generateCleanArchitecture( const usedAsParam = tagsMap[tag].some((op) => op.allParams.some((p) => p.dataType === s || p.dataType === `${s}[]`) ); - if (usedAsReturn || usedAsParam) { - imports.push({ - classname: s, - classFilename: toCamelCase(s), - classVarName: toCamelCase(s) - }); + + const entry = { classname: s, classFilename: toCamelCase(s), classVarName: toCamelCase(s) }; + + if (usedAsReturn) { + returnImports.push(entry); + } else if (usedAsParam) { + // Param-only types: entity import needed for method signatures, but no Dto or Mapper + paramImports.push(entry); } }); @@ -227,7 +231,12 @@ export function generateCleanArchitecture( classVarName: toCamelCase(tag), constantName: tag.toUpperCase().replace(/[^A-Z0-9]/g, '_'), operation: tagsMap[tag], - imports: imports + // All entity imports (return + param) — for contracts and use-cases + imports: [...returnImports, ...paramImports], + // Return-type-only imports — for repo impl (Dto + Entity + Mapper) + returnImports, + // Param-only imports — for repo impl (Entity only, no Dto/Mapper) + paramImports } } ] diff --git a/templates/api.repository.impl.mustache b/templates/api.repository.impl.mustache index f02fbaa..80bc23b 100644 --- a/templates/api.repository.impl.mustache +++ b/templates/api.repository.impl.mustache @@ -10,11 +10,14 @@ import { environment } from '@environment'; import { MRepository } from '@mercadona/core/utils/repository'; import { {{classname}}Repository } from '@/domain/repositories/{{classFilename}}.repository.contract'; -{{#imports}} +{{#returnImports}} import { {{classname}}Dto } from '@/dtos/{{classFilename}}.dto'; import { {{classname}} } from '@/entities/models/{{classFilename}}.model'; import { {{classVarName}}Mapper } from '@/mappers/{{classFilename}}.mapper'; -{{/imports}} +{{/returnImports}} +{{#paramImports}} +import { {{classname}} } from '@/entities/models/{{classFilename}}.model'; +{{/paramImports}} /** * {{classname}} Repository Implementation