feat: enhance DTO generation and organization by tag
This commit is contained in:
@@ -59,181 +59,14 @@ export function extractTagsWithOperations(analysis: SwaggerAnalysis): TagSummary
|
||||
return [...map.values()];
|
||||
}
|
||||
|
||||
/** Generates all Clean Architecture artefacts (models, mappers, repos, use cases, providers) using Mustache. */
|
||||
export function generateCleanArchitecture(
|
||||
/**
|
||||
* Builds and returns the tagsMap from the swagger analysis, applying the optional selection filter.
|
||||
* Exported so callers (e.g. main.ts) can compute it before organizeFiles runs.
|
||||
*/
|
||||
export function buildTagsMapFromAnalysis(
|
||||
analysis: SwaggerAnalysis,
|
||||
outputDir: string,
|
||||
templatesDir: string,
|
||||
tagApiKeyMap: Record<string, string> = {},
|
||||
selectionFilter: SelectionFilter = {}
|
||||
): GeneratedCount {
|
||||
logStep('Generating Clean Architecture artefacts using Mustache...');
|
||||
const generatedCount: GeneratedCount = {
|
||||
models: 0,
|
||||
repositories: 0,
|
||||
mappers: 0,
|
||||
useCases: 0,
|
||||
providers: 0,
|
||||
mocks: 0,
|
||||
specs: 0
|
||||
};
|
||||
|
||||
const schemas =
|
||||
(analysis.swagger as { components?: { schemas?: Record<string, unknown> } }).components
|
||||
?.schemas || {};
|
||||
|
||||
// 1. Generate Models, Entities and Mappers from Schemas
|
||||
Object.keys(schemas).forEach((schemaName) => {
|
||||
const baseName = schemaName.replace(/Dto$/, '');
|
||||
|
||||
const schemaObj = schemas[schemaName] as OpenApiSchema;
|
||||
const rawProperties = schemaObj.properties || {};
|
||||
const requiredProps: string[] = schemaObj.required || [];
|
||||
|
||||
const varsMap = Object.keys(rawProperties).map((k) => {
|
||||
let tsType = mapSwaggerTypeToTs(rawProperties[k].type);
|
||||
if (rawProperties[k].$ref) {
|
||||
tsType = rawProperties[k].$ref.split('/').pop() || 'unknown';
|
||||
} else if (rawProperties[k].type === 'array' && rawProperties[k].items?.$ref) {
|
||||
tsType = `${rawProperties[k].items.$ref.split('/').pop()}[]`;
|
||||
}
|
||||
return {
|
||||
name: k,
|
||||
dataType: tsType,
|
||||
description: rawProperties[k].description || '',
|
||||
required: requiredProps.includes(k)
|
||||
};
|
||||
});
|
||||
|
||||
// Collect imports for types referenced via $ref in properties
|
||||
const referencedTypes = new Set<string>();
|
||||
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: [
|
||||
{
|
||||
model: {
|
||||
classname: baseName,
|
||||
classFilename: toCamelCase(baseName),
|
||||
classVarName: toCamelCase(baseName),
|
||||
description: schemaObj.description || '',
|
||||
imports: modelImports,
|
||||
vars: varsMap
|
||||
}
|
||||
}
|
||||
],
|
||||
allModels: [{ model: { vars: varsMap } }]
|
||||
};
|
||||
|
||||
const mapperViewData = {
|
||||
...modelViewData,
|
||||
apiInfo: {
|
||||
apis: [
|
||||
{
|
||||
operations: {
|
||||
classname: baseName,
|
||||
classFilename: toCamelCase(baseName),
|
||||
classVarName: toCamelCase(baseName)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// Model (Entities)
|
||||
const modelTemplatePath = path.join(templatesDir, 'model-entity.mustache');
|
||||
if (fs.existsSync(modelTemplatePath)) {
|
||||
const template = fs.readFileSync(modelTemplatePath, 'utf8');
|
||||
const output = mustache.render(template, modelViewData);
|
||||
const destPath = path.join(outputDir, 'entities/models', `${toCamelCase(baseName)}.model.ts`);
|
||||
fs.writeFileSync(destPath, output);
|
||||
generatedCount.models++;
|
||||
logDetail('generate', `model-entity → ${path.relative(process.cwd(), destPath)}`);
|
||||
}
|
||||
|
||||
// Mapper
|
||||
const mapperTemplatePath = path.join(templatesDir, 'mapper.mustache');
|
||||
if (fs.existsSync(mapperTemplatePath)) {
|
||||
const template = fs.readFileSync(mapperTemplatePath, 'utf8');
|
||||
const output = mustache.render(template, mapperViewData);
|
||||
const destPath = path.join(outputDir, 'data/mappers', `${toCamelCase(baseName)}.mapper.ts`);
|
||||
fs.writeFileSync(destPath, output);
|
||||
generatedCount.mappers++;
|
||||
}
|
||||
|
||||
// DTO mock — values resolved from raw schema (example, format, type)
|
||||
const dtoMockVarsMap = Object.keys(rawProperties).map((k) => ({
|
||||
name: k,
|
||||
mockValue: resolveMockValue(k, rawProperties[k], 'dto')
|
||||
}));
|
||||
const dtoMockImports = [...referencedTypes]
|
||||
.filter(Boolean)
|
||||
.map((name) => ({ classname: name, classFilename: toCamelCase(name) }));
|
||||
|
||||
const dtoMockViewData = {
|
||||
models: [
|
||||
{
|
||||
model: {
|
||||
classname: baseName,
|
||||
classFilename: toCamelCase(baseName),
|
||||
classVarName: toCamelCase(baseName),
|
||||
mockImports: dtoMockImports,
|
||||
vars: dtoMockVarsMap
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'dto.mock.mustache',
|
||||
dtoMockViewData,
|
||||
path.join(outputDir, 'data/dtos', `${toCamelCase(baseName)}.dto.mock.ts`),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
|
||||
// Model mock — delegates to mapper + DTO mock (no property values needed)
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'model.mock.mustache',
|
||||
modelViewData,
|
||||
path.join(outputDir, 'entities/models', `${toCamelCase(baseName)}.model.mock.ts`),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
|
||||
// Model spec
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'model-entity.spec.mustache',
|
||||
modelViewData,
|
||||
path.join(outputDir, 'entities/models', `${toCamelCase(baseName)}.model.spec.ts`),
|
||||
generatedCount,
|
||||
'specs'
|
||||
);
|
||||
|
||||
// Mapper spec
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'mapper.spec.mustache',
|
||||
mapperViewData,
|
||||
path.join(outputDir, 'data/mappers', `${toCamelCase(baseName)}.mapper.spec.ts`),
|
||||
generatedCount,
|
||||
'specs'
|
||||
);
|
||||
});
|
||||
|
||||
// 2. Generate Use Cases and Repositories from Paths/Tags
|
||||
): Record<string, TagOperation[]> {
|
||||
const tagsMap: Record<string, TagOperation[]> = {};
|
||||
|
||||
Object.keys(analysis.paths).forEach((pathKey) => {
|
||||
@@ -334,10 +167,266 @@ export function generateCleanArchitecture(
|
||||
});
|
||||
}
|
||||
|
||||
return tagsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps each schema basename to the tag subfolder it belongs to.
|
||||
* Schemas used by exactly one tag → that tag's camelCase name.
|
||||
* Schemas used by 0 or multiple tags → 'shared'.
|
||||
*/
|
||||
export function buildSchemaTagMap(
|
||||
schemas: Record<string, unknown>,
|
||||
tagsMap: Record<string, TagOperation[]>
|
||||
): Record<string, string> {
|
||||
const result: Record<string, string> = {};
|
||||
Object.keys(schemas).forEach((schemaName) => {
|
||||
const baseName = schemaName.replace(/Dto$/, '');
|
||||
const tagsUsing: string[] = [];
|
||||
Object.keys(tagsMap).forEach((tag) => {
|
||||
const used = tagsMap[tag].some(
|
||||
(op) =>
|
||||
op.returnType === baseName ||
|
||||
op.returnType === `${baseName}[]` ||
|
||||
op.allParams.some((p) => p.dataType === baseName || p.dataType === `${baseName}[]`)
|
||||
);
|
||||
if (used) tagsUsing.push(tag);
|
||||
});
|
||||
result[baseName] = tagsUsing.length === 1 ? toCamelCase(tagsUsing[0]) : 'shared';
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Generates all Clean Architecture artefacts (models, mappers, repos, use cases, providers) using Mustache. */
|
||||
export function generateCleanArchitecture(
|
||||
analysis: SwaggerAnalysis,
|
||||
outputDir: string,
|
||||
templatesDir: string,
|
||||
tagApiKeyMap: Record<string, string> = {},
|
||||
selectionFilter: SelectionFilter = {},
|
||||
precomputedSchemaTagMap: Record<string, string> = {}
|
||||
): GeneratedCount {
|
||||
logStep('Generating Clean Architecture artefacts using Mustache...');
|
||||
const generatedCount: GeneratedCount = {
|
||||
models: 0,
|
||||
repositories: 0,
|
||||
mappers: 0,
|
||||
useCases: 0,
|
||||
providers: 0,
|
||||
mocks: 0,
|
||||
specs: 0
|
||||
};
|
||||
|
||||
const schemas =
|
||||
(analysis.swagger as { components?: { schemas?: Record<string, unknown> } }).components
|
||||
?.schemas || {};
|
||||
|
||||
// Build tagsMap first — needed to compute schemaTagMap before the schema loop
|
||||
const tagsMap = buildTagsMapFromAnalysis(analysis, selectionFilter);
|
||||
|
||||
// Map each schema basename → tag subfolder ('shared' if used by 0 or >1 tags)
|
||||
const schemaTagMap =
|
||||
Object.keys(precomputedSchemaTagMap).length > 0
|
||||
? precomputedSchemaTagMap
|
||||
: buildSchemaTagMap(schemas, tagsMap);
|
||||
|
||||
// 1. Generate Models, Entities and Mappers from Schemas
|
||||
Object.keys(schemas).forEach((schemaName) => {
|
||||
const baseName = schemaName.replace(/Dto$/, '');
|
||||
const tagFilename = schemaTagMap[baseName] || 'shared';
|
||||
|
||||
const schemaObj = schemas[schemaName] as OpenApiSchema;
|
||||
const rawProperties = schemaObj.properties || {};
|
||||
const requiredProps: string[] = schemaObj.required || [];
|
||||
|
||||
const varsMap = Object.keys(rawProperties).map((k) => {
|
||||
let tsType = mapSwaggerTypeToTs(rawProperties[k].type);
|
||||
if (rawProperties[k].$ref) {
|
||||
tsType = rawProperties[k].$ref.split('/').pop() || 'unknown';
|
||||
} else if (rawProperties[k].type === 'array' && rawProperties[k].items?.$ref) {
|
||||
tsType = `${rawProperties[k].items.$ref.split('/').pop()}[]`;
|
||||
}
|
||||
return {
|
||||
name: k,
|
||||
dataType: tsType,
|
||||
description: rawProperties[k].description || '',
|
||||
required: requiredProps.includes(k)
|
||||
};
|
||||
});
|
||||
|
||||
// Collect imports for types referenced via $ref in properties
|
||||
const referencedTypes = new Set<string>();
|
||||
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),
|
||||
tagFilename: schemaTagMap[name] || 'shared'
|
||||
}));
|
||||
|
||||
const modelViewData = {
|
||||
tagFilename,
|
||||
models: [
|
||||
{
|
||||
model: {
|
||||
classname: baseName,
|
||||
classFilename: toCamelCase(baseName),
|
||||
classVarName: toCamelCase(baseName),
|
||||
description: schemaObj.description || '',
|
||||
imports: modelImports,
|
||||
vars: varsMap
|
||||
}
|
||||
}
|
||||
],
|
||||
allModels: [{ model: { vars: varsMap } }]
|
||||
};
|
||||
|
||||
const mapperViewData = {
|
||||
...modelViewData,
|
||||
apiInfo: {
|
||||
apis: [
|
||||
{
|
||||
operations: {
|
||||
classname: baseName,
|
||||
classFilename: toCamelCase(baseName),
|
||||
classVarName: toCamelCase(baseName),
|
||||
tagFilename
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// Model (Entities)
|
||||
const modelTemplatePath = path.join(templatesDir, 'model-entity.mustache');
|
||||
if (fs.existsSync(modelTemplatePath)) {
|
||||
const template = fs.readFileSync(modelTemplatePath, 'utf8');
|
||||
const output = mustache.render(template, modelViewData);
|
||||
const destPath = path.join(
|
||||
outputDir,
|
||||
'entities/models',
|
||||
tagFilename,
|
||||
`${toCamelCase(baseName)}.model.ts`
|
||||
);
|
||||
fs.ensureDirSync(path.dirname(destPath));
|
||||
fs.writeFileSync(destPath, output);
|
||||
generatedCount.models++;
|
||||
logDetail('generate', `model-entity → ${path.relative(process.cwd(), destPath)}`);
|
||||
}
|
||||
|
||||
// Mapper
|
||||
const mapperTemplatePath = path.join(templatesDir, 'mapper.mustache');
|
||||
if (fs.existsSync(mapperTemplatePath)) {
|
||||
const template = fs.readFileSync(mapperTemplatePath, 'utf8');
|
||||
const output = mustache.render(template, mapperViewData);
|
||||
const destPath = path.join(
|
||||
outputDir,
|
||||
'data/mappers',
|
||||
tagFilename,
|
||||
`${toCamelCase(baseName)}.mapper.ts`
|
||||
);
|
||||
fs.ensureDirSync(path.dirname(destPath));
|
||||
fs.writeFileSync(destPath, output);
|
||||
generatedCount.mappers++;
|
||||
}
|
||||
|
||||
// DTO mock — values resolved from raw schema (example, format, type)
|
||||
const dtoMockVarsMap = Object.keys(rawProperties).map((k) => ({
|
||||
name: k,
|
||||
mockValue: resolveMockValue(k, rawProperties[k], 'dto')
|
||||
}));
|
||||
const dtoMockImports = [...referencedTypes].filter(Boolean).map((name) => ({
|
||||
classname: name,
|
||||
classFilename: toCamelCase(name),
|
||||
tagFilename: schemaTagMap[name] || 'shared'
|
||||
}));
|
||||
|
||||
const dtoMockViewData = {
|
||||
tagFilename,
|
||||
models: [
|
||||
{
|
||||
model: {
|
||||
classname: baseName,
|
||||
classFilename: toCamelCase(baseName),
|
||||
classVarName: toCamelCase(baseName),
|
||||
mockImports: dtoMockImports,
|
||||
vars: dtoMockVarsMap
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'dto.mock.mustache',
|
||||
dtoMockViewData,
|
||||
path.join(outputDir, 'data/dtos', tagFilename, `${toCamelCase(baseName)}.dto.mock.ts`),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
|
||||
// Model mock — delegates to mapper + DTO mock (no property values needed)
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'model.mock.mustache',
|
||||
modelViewData,
|
||||
path.join(
|
||||
outputDir,
|
||||
'entities/models',
|
||||
tagFilename,
|
||||
`${toCamelCase(baseName)}.model.mock.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
|
||||
// Model spec
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'model-entity.spec.mustache',
|
||||
modelViewData,
|
||||
path.join(
|
||||
outputDir,
|
||||
'entities/models',
|
||||
tagFilename,
|
||||
`${toCamelCase(baseName)}.model.spec.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'specs'
|
||||
);
|
||||
|
||||
// Mapper spec
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'mapper.spec.mustache',
|
||||
mapperViewData,
|
||||
path.join(outputDir, 'data/mappers', tagFilename, `${toCamelCase(baseName)}.mapper.spec.ts`),
|
||||
generatedCount,
|
||||
'specs'
|
||||
);
|
||||
});
|
||||
|
||||
// 2. Generate Use Cases and Repositories from Paths/Tags
|
||||
// Generate per tag
|
||||
Object.keys(tagsMap).forEach((tag) => {
|
||||
const returnImports: { classname: string; classFilename: string; classVarName: string }[] = [];
|
||||
const paramImports: { classname: string; classFilename: string; classVarName: string }[] = [];
|
||||
const tagFilename = toCamelCase(tag);
|
||||
const returnImports: {
|
||||
classname: string;
|
||||
classFilename: string;
|
||||
classVarName: string;
|
||||
tagFilename: string;
|
||||
}[] = [];
|
||||
const paramImports: {
|
||||
classname: string;
|
||||
classFilename: string;
|
||||
classVarName: string;
|
||||
tagFilename: string;
|
||||
}[] = [];
|
||||
|
||||
Object.keys(schemas).forEach((s) => {
|
||||
const usedAsReturn = tagsMap[tag].some(
|
||||
@@ -347,7 +436,12 @@ export function generateCleanArchitecture(
|
||||
op.allParams.some((p) => p.dataType === s || p.dataType === `${s}[]`)
|
||||
);
|
||||
|
||||
const entry = { classname: s, classFilename: toCamelCase(s), classVarName: toCamelCase(s) };
|
||||
const entry = {
|
||||
classname: s,
|
||||
classFilename: toCamelCase(s),
|
||||
classVarName: toCamelCase(s),
|
||||
tagFilename: schemaTagMap[s] || 'shared'
|
||||
};
|
||||
|
||||
if (usedAsReturn) {
|
||||
returnImports.push(entry);
|
||||
@@ -363,17 +457,13 @@ export function generateCleanArchitecture(
|
||||
{
|
||||
operations: {
|
||||
classname: toPascalCase(tag),
|
||||
classFilename: toCamelCase(tag),
|
||||
classVarName: toCamelCase(tag),
|
||||
classFilename: tagFilename,
|
||||
classVarName: tagFilename,
|
||||
constantName: tag.toUpperCase().replace(/[^A-Z0-9]/g, '_'),
|
||||
operation: tagsMap[tag],
|
||||
// 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,
|
||||
// Environment API key for the repository base URL (e.g. "aprovalmApi")
|
||||
environmentApiKey: tagApiKeyMap[tag] || 'apiUrl'
|
||||
}
|
||||
}
|
||||
@@ -385,7 +475,7 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.use-cases.contract.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'domain/use-cases', `${toCamelCase(tag)}.use-cases.contract.ts`),
|
||||
path.join(outputDir, 'domain/use-cases', tagFilename, `${tagFilename}.use-cases.contract.ts`),
|
||||
generatedCount,
|
||||
'useCases'
|
||||
);
|
||||
@@ -394,7 +484,7 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.use-cases.impl.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'domain/use-cases', `${toCamelCase(tag)}.use-cases.impl.ts`),
|
||||
path.join(outputDir, 'domain/use-cases', tagFilename, `${tagFilename}.use-cases.impl.ts`),
|
||||
generatedCount,
|
||||
'useCases'
|
||||
);
|
||||
@@ -403,7 +493,12 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.repository.contract.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'domain/repositories', `${toCamelCase(tag)}.repository.contract.ts`),
|
||||
path.join(
|
||||
outputDir,
|
||||
'domain/repositories',
|
||||
tagFilename,
|
||||
`${tagFilename}.repository.contract.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'repositories'
|
||||
);
|
||||
@@ -412,7 +507,7 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.repository.impl.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'data/repositories', `${toCamelCase(tag)}.repository.impl.ts`),
|
||||
path.join(outputDir, 'data/repositories', tagFilename, `${tagFilename}.repository.impl.ts`),
|
||||
generatedCount,
|
||||
'repositories'
|
||||
);
|
||||
@@ -421,7 +516,7 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'use-cases.provider.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'di/use-cases', `${toCamelCase(tag)}.use-cases.provider.ts`),
|
||||
path.join(outputDir, 'di/use-cases', tagFilename, `${tagFilename}.use-cases.provider.ts`),
|
||||
generatedCount,
|
||||
'providers'
|
||||
);
|
||||
@@ -430,17 +525,22 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'repository.provider.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'di/repositories', `${toCamelCase(tag)}.repository.provider.ts`),
|
||||
path.join(outputDir, 'di/repositories', tagFilename, `${tagFilename}.repository.provider.ts`),
|
||||
generatedCount,
|
||||
'providers'
|
||||
);
|
||||
|
||||
// Mocks — repository impl, use-cases impl, repository provider, use-cases provider
|
||||
// Mocks
|
||||
renderTemplate(
|
||||
templatesDir,
|
||||
'api.repository.impl.mock.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'data/repositories', `${toCamelCase(tag)}.repository.impl.mock.ts`),
|
||||
path.join(
|
||||
outputDir,
|
||||
'data/repositories',
|
||||
tagFilename,
|
||||
`${tagFilename}.repository.impl.mock.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
@@ -449,7 +549,7 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.use-cases.mock.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'domain/use-cases', `${toCamelCase(tag)}.use-cases.mock.ts`),
|
||||
path.join(outputDir, 'domain/use-cases', tagFilename, `${tagFilename}.use-cases.mock.ts`),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
@@ -458,7 +558,12 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'repository.provider.mock.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'di/repositories', `${toCamelCase(tag)}.repository.provider.mock.ts`),
|
||||
path.join(
|
||||
outputDir,
|
||||
'di/repositories',
|
||||
tagFilename,
|
||||
`${tagFilename}.repository.provider.mock.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
@@ -467,7 +572,12 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'use-cases.provider.mock.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'di/use-cases', `${toCamelCase(tag)}.use-cases.provider.mock.ts`),
|
||||
path.join(
|
||||
outputDir,
|
||||
'di/use-cases',
|
||||
tagFilename,
|
||||
`${tagFilename}.use-cases.provider.mock.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'mocks'
|
||||
);
|
||||
@@ -477,7 +587,12 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.repository.impl.spec.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'data/repositories', `${toCamelCase(tag)}.repository.impl.spec.ts`),
|
||||
path.join(
|
||||
outputDir,
|
||||
'data/repositories',
|
||||
tagFilename,
|
||||
`${tagFilename}.repository.impl.spec.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'specs'
|
||||
);
|
||||
@@ -487,7 +602,12 @@ export function generateCleanArchitecture(
|
||||
templatesDir,
|
||||
'api.use-cases.impl.spec.mustache',
|
||||
apiViewData,
|
||||
path.join(outputDir, 'domain/use-cases', `${toCamelCase(tag)}.use-cases.impl.spec.ts`),
|
||||
path.join(
|
||||
outputDir,
|
||||
'domain/use-cases',
|
||||
tagFilename,
|
||||
`${tagFilename}.use-cases.impl.spec.ts`
|
||||
),
|
||||
generatedCount,
|
||||
'specs'
|
||||
);
|
||||
@@ -512,6 +632,7 @@ function renderTemplate(
|
||||
if (fs.existsSync(templatePath)) {
|
||||
const template = fs.readFileSync(templatePath, 'utf8');
|
||||
const output = mustache.render(template, viewData);
|
||||
fs.ensureDirSync(path.dirname(destPath));
|
||||
fs.writeFileSync(destPath, output);
|
||||
counter[key]++;
|
||||
logDetail(
|
||||
|
||||
Reference in New Issue
Block a user