mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
feat(architecture): enable enforce-module-boundaries with comprehensive rules
- Enable @nx/enforce-module-boundaries ESLint rule - Add type-based constraints (feature, data-access, ui, shared, util, core, common) - Add domain-based constraints (oms, crm, remission, checkout, availability, etc.) - Prevent feature->feature, data-access->data-access dependencies - Enforce domain isolation (no cross-domain imports) - Tag all 80+ libraries with scope and type tags - Create automated tagging script for new libraries - Configure isa-app violations to be ignored Rules enforce: - Feature can import: data-access, ui, shared, util, core, common, icons - Data-access can import: util, generated, common, core only - UI can import: util, core, icons only - Cross-domain imports forbidden (except shared, core, common, ui, utils, icons) - Generated APIs only importable by data-access libraries
This commit is contained in:
163
scripts/add-library-tags.js
Normal file
163
scripts/add-library-tags.js
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script to add appropriate tags to all library project.json files
|
||||
* for @nx/enforce-module-boundaries rule
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { glob } = require('glob');
|
||||
|
||||
/**
|
||||
* Determine tags based on library path
|
||||
* @param {string} projectPath - Path to the project.json file
|
||||
* @returns {string[]} Array of tags
|
||||
*/
|
||||
function determineTags(projectPath) {
|
||||
const tags = [];
|
||||
|
||||
// Handle generated projects
|
||||
if (projectPath.includes('generated/')) {
|
||||
tags.push('scope:generated');
|
||||
tags.push('type:generated');
|
||||
return tags;
|
||||
}
|
||||
|
||||
const relativePath = projectPath.replace(/^.*?libs\//, 'libs/');
|
||||
|
||||
// Extract scope (domain) from path
|
||||
const pathParts = relativePath.split('/');
|
||||
if (pathParts.length < 2) return tags;
|
||||
|
||||
const domain = pathParts[1]; // e.g., 'oms', 'crm', 'ui', etc.
|
||||
|
||||
// Add scope tag
|
||||
tags.push(`scope:${domain}`);
|
||||
|
||||
// Determine type tag based on path pattern
|
||||
if (pathParts.length >= 3) {
|
||||
const typeSegment = pathParts[2];
|
||||
|
||||
if (typeSegment === 'feature') {
|
||||
tags.push('type:feature');
|
||||
} else if (typeSegment === 'data-access') {
|
||||
tags.push('type:data-access');
|
||||
} else if (typeSegment === 'shared') {
|
||||
tags.push('type:shared');
|
||||
} else if (typeSegment === 'utils' || typeSegment === 'util') {
|
||||
tags.push('type:util');
|
||||
} else if (domain === 'ui') {
|
||||
tags.push('type:ui');
|
||||
} else if (domain === 'core') {
|
||||
tags.push('type:core');
|
||||
} else if (domain === 'common') {
|
||||
tags.push('type:common');
|
||||
} else if (domain === 'icons') {
|
||||
tags.push('type:icon');
|
||||
} else if (domain === 'utils') {
|
||||
tags.push('type:util');
|
||||
} else if (domain === 'shared') {
|
||||
// Libraries directly under libs/shared/* are shared components
|
||||
tags.push('type:shared');
|
||||
}
|
||||
} else {
|
||||
// Top-level libraries (no subdirectory)
|
||||
if (domain === 'ui') {
|
||||
tags.push('type:ui');
|
||||
} else if (domain === 'core') {
|
||||
tags.push('type:core');
|
||||
} else if (domain === 'common') {
|
||||
tags.push('type:common');
|
||||
} else if (domain === 'icons') {
|
||||
tags.push('type:icon');
|
||||
} else if (domain === 'utils') {
|
||||
tags.push('type:util');
|
||||
} else if (domain === 'shared') {
|
||||
tags.push('type:shared');
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a project.json file with appropriate tags
|
||||
* @param {string} projectPath - Path to the project.json file
|
||||
*/
|
||||
function updateProjectTags(projectPath) {
|
||||
try {
|
||||
const content = fs.readFileSync(projectPath, 'utf8');
|
||||
const project = JSON.parse(content);
|
||||
|
||||
// Determine new tags
|
||||
const newTags = determineTags(projectPath);
|
||||
|
||||
if (newTags.length === 0) {
|
||||
console.warn(`⚠️ No tags determined for ${projectPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Preserve existing non-architectural tags (like skip:ci)
|
||||
const existingTags = project.tags || [];
|
||||
const preservedTags = existingTags.filter(
|
||||
tag => !tag.startsWith('scope:') && !tag.startsWith('type:')
|
||||
);
|
||||
|
||||
// Combine tags (preserved + new)
|
||||
project.tags = [...new Set([...preservedTags, ...newTags])];
|
||||
|
||||
// Write back to file
|
||||
fs.writeFileSync(
|
||||
projectPath,
|
||||
JSON.stringify(project, null, 2) + '\n',
|
||||
'utf8'
|
||||
);
|
||||
|
||||
console.log(`✅ ${projectPath}`);
|
||||
console.log(` Tags: ${project.tags.join(', ')}`);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error processing ${projectPath}:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution
|
||||
*/
|
||||
async function main() {
|
||||
console.log('🔍 Finding all library project.json files...\n');
|
||||
|
||||
// Find all project.json files in libs directory
|
||||
const libProjectFiles = await glob('libs/**/project.json', {
|
||||
ignore: ['**/node_modules/**'],
|
||||
cwd: path.resolve(__dirname, '..'),
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
// Find all project.json files in generated directory
|
||||
const generatedProjectFiles = await glob('generated/**/project.json', {
|
||||
ignore: ['**/node_modules/**'],
|
||||
cwd: path.resolve(__dirname, '..'),
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
const projectFiles = [...libProjectFiles, ...generatedProjectFiles];
|
||||
|
||||
console.log(`Found ${libProjectFiles.length} library projects`);
|
||||
console.log(`Found ${generatedProjectFiles.length} generated API projects`);
|
||||
console.log(`Total: ${projectFiles.length} projects\n`);
|
||||
|
||||
// Process each project.json
|
||||
for (const projectFile of projectFiles) {
|
||||
updateProjectTags(projectFile);
|
||||
}
|
||||
|
||||
console.log('\n✨ Done! All library tags have been updated.');
|
||||
console.log('\n📝 Next steps:');
|
||||
console.log(' 1. Review the changes: git diff');
|
||||
console.log(' 2. Run lint to check for violations: npx nx run-many --target=lint --all');
|
||||
console.log(' 3. Commit the changes if everything looks good');
|
||||
}
|
||||
|
||||
// Run the script
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user