mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
264 lines (252 loc) • 8.43 kB
JavaScript
import fs from 'fs-extra';
import * as path from 'path';
import { DocumentationHealer } from './DocumentationHealer.js';
import { GitHooksHealer } from './GitHooksHealer.js';
import { ProjectStructureHealer } from './ProjectStructureHealer.js';
export class ProjectHealer {
projectRoot;
documentationHealer;
gitHooksHealer;
projectStructureHealer;
constructor(projectRoot) {
this.projectRoot = projectRoot;
this.documentationHealer = new DocumentationHealer(projectRoot);
this.gitHooksHealer = new GitHooksHealer(projectRoot);
this.projectStructureHealer = new ProjectStructureHealer(projectRoot);
}
async identifyHealableIssues(analysisResult) {
const issues = [];
// Check project structure issues
const structureIssues = await this.projectStructureHealer.checkStructure();
if (structureIssues.length > 0) {
issues.push({
id: 'project-structure',
description: `Project structure issues: ${structureIssues.join(', ')}`,
severity: 'high',
category: 'project-setup',
autoFixable: true,
fix: async () => this.projectStructureHealer.heal()
});
}
// Check for missing README
if (!await fs.pathExists(path.join(this.projectRoot, 'README.md'))) {
issues.push({
id: 'missing-readme',
description: 'Missing README.md file',
severity: 'medium',
category: 'documentation',
autoFixable: true,
fix: async () => this.documentationHealer.heal(analysisResult.projectInfo || this.getDefaultProjectInfo())
});
}
// Check for missing .gitignore
if (!await fs.pathExists(path.join(this.projectRoot, '.gitignore'))) {
issues.push({
id: 'missing-gitignore',
description: 'Missing .gitignore file',
severity: 'high',
category: 'project-setup',
autoFixable: true,
fix: async () => this.createGitignore()
});
}
// Check for missing EditorConfig
if (!await fs.pathExists(path.join(this.projectRoot, '.editorconfig'))) {
issues.push({
id: 'missing-editorconfig',
description: 'Missing .editorconfig file',
severity: 'low',
category: 'code-style',
autoFixable: true,
fix: async () => this.createEditorConfig()
});
}
// Check for missing linter config
const hasLinter = await this.checkForLinter();
if (!hasLinter && await fs.pathExists(path.join(this.projectRoot, 'package.json'))) {
issues.push({
id: 'missing-linter',
description: 'Missing ESLint configuration',
severity: 'medium',
category: 'code-quality',
autoFixable: true,
fix: async () => this.createEslintConfig()
});
}
// Check for missing Prettier config
const hasFormatter = await this.checkForFormatter();
if (!hasFormatter && await fs.pathExists(path.join(this.projectRoot, 'package.json'))) {
issues.push({
id: 'missing-formatter',
description: 'Missing Prettier configuration',
severity: 'low',
category: 'code-style',
autoFixable: true,
fix: async () => this.createPrettierConfig()
});
}
// Check for git hooks
if (await fs.pathExists(path.join(this.projectRoot, '.git'))) {
const hasPreCommit = await fs.pathExists(path.join(this.projectRoot, '.git', 'hooks', 'pre-commit'));
const hasPostCommit = await fs.pathExists(path.join(this.projectRoot, '.git', 'hooks', 'post-commit'));
if (!hasPreCommit || !hasPostCommit) {
issues.push({
id: 'missing-git-hooks',
description: 'Missing MIRA git hooks for enhanced development workflow',
severity: 'medium',
category: 'development-workflow',
autoFixable: true,
fix: async () => this.gitHooksHealer.heal()
});
}
}
return issues;
}
getDefaultProjectInfo() {
return {
name: path.basename(this.projectRoot),
type: 'unknown',
languages: [],
frameworks: [],
hasTests: false,
hasCI: false
};
}
async healAll(issues) {
const result = {
success: 0,
failed: 0,
details: []
};
for (const issue of issues) {
if (issue.autoFixable && issue.fix) {
try {
await issue.fix();
result.success++;
result.details.push({ issue: issue.description, status: 'success' });
}
catch (error) {
result.failed++;
result.details.push({
issue: issue.description,
status: 'failed',
error: error instanceof Error ? error.message : 'Unknown error'
});
}
}
else {
result.failed++;
result.details.push({
issue: issue.description,
status: 'failed',
error: 'Not auto-fixable'
});
}
}
return result;
}
async createGitignore() {
const gitignore = `# Dependencies
node_modules/
# Build outputs
dist/
build/
*.tsbuildinfo
# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Environment files
.env
.env.local
.env.*.local
# IDE files
.vscode/
.idea/
*.swp
*.swo
.DS_Store
# Test coverage
coverage/
.nyc_output/
# Temporary files
tmp/
temp/
*.tmp
# MIRA
.mira/reports/
`;
await fs.writeFile(path.join(this.projectRoot, '.gitignore'), gitignore);
}
async createEditorConfig() {
const editorConfig = `# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[*.{js,jsx,ts,tsx,json}]
indent_size = 2
[*.py]
indent_size = 4
`;
await fs.writeFile(path.join(this.projectRoot, '.editorconfig'), editorConfig);
}
async createEslintConfig() {
const eslintConfig = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended'
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
rules: {
'no-console': 'warn',
'no-unused-vars': 'warn'
}
};
await fs.writeJson(path.join(this.projectRoot, '.eslintrc.json'), eslintConfig, { spaces: 2 });
}
async createPrettierConfig() {
const prettierConfig = {
semi: true,
trailingComma: 'es5',
singleQuote: true,
printWidth: 100,
tabWidth: 2
};
await fs.writeJson(path.join(this.projectRoot, '.prettierrc'), prettierConfig, { spaces: 2 });
}
async checkForLinter() {
const linterFiles = ['.eslintrc', '.eslintrc.js', '.eslintrc.json', '.eslintrc.yml'];
for (const file of linterFiles) {
if (await fs.pathExists(path.join(this.projectRoot, file))) {
return true;
}
}
return false;
}
async checkForFormatter() {
const formatterFiles = ['.prettierrc', '.prettierrc.js', '.prettierrc.json', '.prettierrc.yml'];
for (const file of formatterFiles) {
if (await fs.pathExists(path.join(this.projectRoot, file))) {
return true;
}
}
return false;
}
}
//# sourceMappingURL=ProjectHealer.js.map