feat(mod_format): Refactor formatting modules to new BaseFormatter and implement concrete analyze/apply logic
This commit is contained in:
@@ -1,8 +1,155 @@
|
||||
import { LegacyFormatter } from './legacy.formatter.js';
|
||||
import * as formatTemplates from '../format.templates.js';
|
||||
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||
import type { IPlannedChange } from '../interfaces.format.js';
|
||||
import * as plugins from '../mod.plugins.js';
|
||||
import * as paths from '../../paths.js';
|
||||
import { logger, logVerbose } from '../../gitzone.logging.js';
|
||||
|
||||
export class TemplatesFormatter extends LegacyFormatter {
|
||||
constructor(context: any, project: any) {
|
||||
super(context, project, 'templates', formatTemplates);
|
||||
export class TemplatesFormatter extends BaseFormatter {
|
||||
get name(): string {
|
||||
return 'templates';
|
||||
}
|
||||
|
||||
async analyze(): Promise<IPlannedChange[]> {
|
||||
const changes: IPlannedChange[] = [];
|
||||
const project = this.project;
|
||||
const projectType = project.gitzoneConfig?.data?.projectType;
|
||||
|
||||
// VSCode template - for all projects
|
||||
const vscodeChanges = await this.analyzeTemplate('vscode', [
|
||||
{ templatePath: '.vscode/settings.json', destPath: '.vscode/settings.json' },
|
||||
{ templatePath: '.vscode/launch.json', destPath: '.vscode/launch.json' },
|
||||
]);
|
||||
changes.push(...vscodeChanges);
|
||||
|
||||
// CI and other templates based on projectType
|
||||
switch (projectType) {
|
||||
case 'npm':
|
||||
case 'wcc':
|
||||
const accessLevel = project.gitzoneConfig?.data?.npmciOptions?.npmAccessLevel;
|
||||
const ciTemplate = accessLevel === 'public' ? 'ci_default' : 'ci_default_private';
|
||||
const ciChanges = await this.analyzeTemplate(ciTemplate, [
|
||||
{ templatePath: '.gitea/workflows/default_nottags.yaml', destPath: '.gitea/workflows/default_nottags.yaml' },
|
||||
{ templatePath: '.gitea/workflows/default_tags.yaml', destPath: '.gitea/workflows/default_tags.yaml' },
|
||||
]);
|
||||
changes.push(...ciChanges);
|
||||
break;
|
||||
|
||||
case 'service':
|
||||
case 'website':
|
||||
const dockerCiChanges = await this.analyzeTemplate('ci_docker', [
|
||||
{ templatePath: '.gitea/workflows/docker_nottags.yaml', destPath: '.gitea/workflows/docker_nottags.yaml' },
|
||||
{ templatePath: '.gitea/workflows/docker_tags.yaml', destPath: '.gitea/workflows/docker_tags.yaml' },
|
||||
]);
|
||||
changes.push(...dockerCiChanges);
|
||||
|
||||
const dockerfileChanges = await this.analyzeTemplate('dockerfile_service', [
|
||||
{ templatePath: 'Dockerfile', destPath: 'Dockerfile' },
|
||||
{ templatePath: 'dockerignore', destPath: '.dockerignore' },
|
||||
]);
|
||||
changes.push(...dockerfileChanges);
|
||||
|
||||
const cliChanges = await this.analyzeTemplate('cli', [
|
||||
{ templatePath: 'cli.js', destPath: 'cli.js' },
|
||||
{ templatePath: 'cli.ts.js', destPath: 'cli.ts.js' },
|
||||
]);
|
||||
changes.push(...cliChanges);
|
||||
break;
|
||||
}
|
||||
|
||||
// Update templates based on projectType
|
||||
if (projectType === 'website') {
|
||||
const websiteChanges = await this.analyzeTemplate('website_update', [
|
||||
{ templatePath: 'html/index.html', destPath: 'html/index.html' },
|
||||
]);
|
||||
changes.push(...websiteChanges);
|
||||
} else if (projectType === 'service') {
|
||||
const serviceChanges = await this.analyzeTemplate('service_update', []);
|
||||
changes.push(...serviceChanges);
|
||||
} else if (projectType === 'wcc') {
|
||||
const wccChanges = await this.analyzeTemplate('wcc_update', [
|
||||
{ templatePath: 'html/index.html', destPath: 'html/index.html' },
|
||||
{ templatePath: 'html/index.ts', destPath: 'html/index.ts' },
|
||||
]);
|
||||
changes.push(...wccChanges);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
private async analyzeTemplate(
|
||||
templateName: string,
|
||||
files: Array<{ templatePath: string; destPath: string }>,
|
||||
): Promise<IPlannedChange[]> {
|
||||
const changes: IPlannedChange[] = [];
|
||||
const templateDir = plugins.path.join(paths.templatesDir, templateName);
|
||||
|
||||
// Check if template exists
|
||||
const templateExists = await plugins.smartfs.directory(templateDir).exists();
|
||||
if (!templateExists) {
|
||||
logVerbose(`Template ${templateName} not found`);
|
||||
return changes;
|
||||
}
|
||||
|
||||
for (const file of files) {
|
||||
const templateFilePath = plugins.path.join(templateDir, file.templatePath);
|
||||
const destFilePath = file.destPath;
|
||||
|
||||
// Check if template file exists
|
||||
const fileExists = await plugins.smartfs.file(templateFilePath).exists();
|
||||
if (!fileExists) {
|
||||
logVerbose(`Template file ${templateFilePath} not found`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// Read template content
|
||||
const templateContent = (await plugins.smartfs
|
||||
.file(templateFilePath)
|
||||
.encoding('utf8')
|
||||
.read()) as string;
|
||||
|
||||
// Check if destination file exists
|
||||
const destExists = await plugins.smartfs.file(destFilePath).exists();
|
||||
let currentContent = '';
|
||||
if (destExists) {
|
||||
currentContent = (await plugins.smartfs
|
||||
.file(destFilePath)
|
||||
.encoding('utf8')
|
||||
.read()) as string;
|
||||
}
|
||||
|
||||
// Only add change if content differs
|
||||
if (templateContent !== currentContent) {
|
||||
changes.push({
|
||||
type: destExists ? 'modify' : 'create',
|
||||
path: destFilePath,
|
||||
module: this.name,
|
||||
description: `Apply template ${templateName}/${file.templatePath}`,
|
||||
content: templateContent,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logVerbose(`Failed to read template ${templateFilePath}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
async applyChange(change: IPlannedChange): Promise<void> {
|
||||
if (!change.content) return;
|
||||
|
||||
// Ensure destination directory exists
|
||||
const destDir = plugins.path.dirname(change.path);
|
||||
if (destDir && destDir !== '.') {
|
||||
await plugins.smartfs.directory(destDir).recursive().create();
|
||||
}
|
||||
|
||||
if (change.type === 'create') {
|
||||
await this.createFile(change.path, change.content);
|
||||
} else {
|
||||
await this.modifyFile(change.path, change.content);
|
||||
}
|
||||
logger.log('info', `Applied template to ${change.path}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user