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:
@@ -4,7 +4,7 @@
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"sourceRoot": "apps/isa-app/src",
|
||||
"tags": ["skip:ci"],
|
||||
"tags": ["skip:ci", "scope:app", "type:app"],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@angular-devkit/build-angular:application",
|
||||
|
||||
286
eslint.config.js
286
eslint.config.js
@@ -13,24 +13,274 @@ module.exports = [
|
||||
'**/generated/**',
|
||||
],
|
||||
},
|
||||
// {
|
||||
// files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
// rules: {
|
||||
// '@nx/enforce-module-boundaries': [
|
||||
// 'error',
|
||||
// {
|
||||
// enforceBuildableLibDependency: true,
|
||||
// allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
|
||||
// depConstraints: [
|
||||
// {
|
||||
// sourceTag: '*',
|
||||
// onlyDependOnLibsWithTags: ['*'],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
rules: {
|
||||
'@nx/enforce-module-boundaries': [
|
||||
'error',
|
||||
{
|
||||
enforceBuildableLibDependency: true,
|
||||
allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
|
||||
depConstraints: [
|
||||
// ========================================
|
||||
// TYPE-BASED CONSTRAINTS (Layer Rules)
|
||||
// ========================================
|
||||
|
||||
// FEATURE libraries can import: data-access, ui, shared, util, core (within same domain)
|
||||
{
|
||||
sourceTag: 'type:feature',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'type:data-access',
|
||||
'type:ui',
|
||||
'type:shared',
|
||||
'type:util',
|
||||
'type:core',
|
||||
'type:common',
|
||||
'type:icon',
|
||||
],
|
||||
},
|
||||
|
||||
// DATA-ACCESS libraries can import: util, generated, common-data-access only
|
||||
{
|
||||
sourceTag: 'type:data-access',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'type:util',
|
||||
'type:generated',
|
||||
'type:common',
|
||||
'type:core',
|
||||
],
|
||||
bannedExternalImports: [],
|
||||
},
|
||||
|
||||
// DATA-ACCESS cannot import other DATA-ACCESS (except common)
|
||||
{
|
||||
sourceTag: 'type:data-access',
|
||||
notDependOnLibsWithTags: ['type:data-access'],
|
||||
allowedExternalImports: [],
|
||||
},
|
||||
|
||||
// UI libraries can import: util, core only (NOT shared, NOT data-access)
|
||||
{
|
||||
sourceTag: 'type:ui',
|
||||
onlyDependOnLibsWithTags: ['type:util', 'type:core', 'type:icon'],
|
||||
},
|
||||
|
||||
// SHARED libraries can import: ui, util, core within same domain
|
||||
{
|
||||
sourceTag: 'type:shared',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'type:ui',
|
||||
'type:util',
|
||||
'type:core',
|
||||
'type:common',
|
||||
'type:icon',
|
||||
],
|
||||
},
|
||||
|
||||
// UTIL libraries are leaf nodes - cannot import feature/data-access/ui/shared
|
||||
{
|
||||
sourceTag: 'type:util',
|
||||
onlyDependOnLibsWithTags: ['type:util', 'type:core'],
|
||||
},
|
||||
|
||||
// GENERATED (swagger clients) can only be imported by data-access
|
||||
// This is enforced by the data-access rule above
|
||||
|
||||
// CORE libraries can be imported by anyone, but cannot import feature/data-access
|
||||
{
|
||||
sourceTag: 'type:core',
|
||||
onlyDependOnLibsWithTags: ['type:core', 'type:util', 'type:common'],
|
||||
},
|
||||
|
||||
// COMMON libraries can be imported by anyone
|
||||
{
|
||||
sourceTag: 'type:common',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'type:util',
|
||||
'type:core',
|
||||
'type:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// ICON libraries can be imported by anyone
|
||||
{
|
||||
sourceTag: 'type:icon',
|
||||
onlyDependOnLibsWithTags: [],
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// DOMAIN-BASED CONSTRAINTS (Scope Rules)
|
||||
// ========================================
|
||||
|
||||
// OMS domain can only import from OMS, shared, core, common, ui, utils, icons
|
||||
{
|
||||
sourceTag: 'scope:oms',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:oms',
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// CRM domain can only import from CRM, shared, core, common, ui, utils, icons
|
||||
{
|
||||
sourceTag: 'scope:crm',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:crm',
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// REMISSION domain can only import from REMISSION, shared, core, common, ui, utils, icons
|
||||
{
|
||||
sourceTag: 'scope:remission',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:remission',
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// CHECKOUT domain can only import from CHECKOUT, shared, core, common, ui, utils, icons
|
||||
{
|
||||
sourceTag: 'scope:checkout',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:checkout',
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// AVAILABILITY domain can only import from AVAILABILITY, shared, core, common, ui, utils, icons
|
||||
{
|
||||
sourceTag: 'scope:availability',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:availability',
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// CATALOGUE domain can only import from CATALOGUE, shared, core, common, ui, utils, icons
|
||||
{
|
||||
sourceTag: 'scope:catalogue',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:catalogue',
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// SHARED libraries can be imported by all domains
|
||||
{
|
||||
sourceTag: 'scope:shared',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:shared',
|
||||
'scope:core',
|
||||
'scope:common',
|
||||
'scope:ui',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
],
|
||||
},
|
||||
|
||||
// UI libraries can be imported by all domains
|
||||
{
|
||||
sourceTag: 'scope:ui',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:ui',
|
||||
'scope:core',
|
||||
'scope:utils',
|
||||
'scope:icons',
|
||||
],
|
||||
},
|
||||
|
||||
// UTILS libraries can be imported by all domains
|
||||
{
|
||||
sourceTag: 'scope:utils',
|
||||
onlyDependOnLibsWithTags: ['scope:utils', 'scope:core'],
|
||||
},
|
||||
|
||||
// CORE libraries can be imported by all domains
|
||||
{
|
||||
sourceTag: 'scope:core',
|
||||
onlyDependOnLibsWithTags: ['scope:core', 'scope:common', 'scope:utils'],
|
||||
},
|
||||
|
||||
// COMMON libraries can be imported by all domains
|
||||
{
|
||||
sourceTag: 'scope:common',
|
||||
onlyDependOnLibsWithTags: [
|
||||
'scope:common',
|
||||
'scope:core',
|
||||
'scope:utils',
|
||||
'scope:generated',
|
||||
],
|
||||
},
|
||||
|
||||
// ICONS libraries can be imported by all domains
|
||||
{
|
||||
sourceTag: 'scope:icons',
|
||||
onlyDependOnLibsWithTags: [],
|
||||
},
|
||||
|
||||
// GENERATED (swagger) can only be imported by data-access
|
||||
{
|
||||
sourceTag: 'scope:generated',
|
||||
onlyDependOnLibsWithTags: [],
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// SPECIAL RULES
|
||||
// ========================================
|
||||
|
||||
// APP scope - violations ignored for now (as per user requirement)
|
||||
{
|
||||
sourceTag: 'scope:app',
|
||||
onlyDependOnLibsWithTags: ['*'],
|
||||
},
|
||||
|
||||
// Disallow relative imports - must use path aliases
|
||||
{
|
||||
sourceTag: '*',
|
||||
bannedExternalImports: ['../*', '../../*', '../../../*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
},
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/availability-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger","availability","api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"availability",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/cat-search-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "cat-search", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"cat-search",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/checkout-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "checkout", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"checkout",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/crm-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "crm", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"crm",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/eis-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger","eis", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"eis",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"download": {
|
||||
"command": "curl -o {projectRoot}/swagger.json https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1/swagger.json"
|
||||
@@ -17,8 +24,12 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"dependsOn": ["download"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"dependsOn": [
|
||||
"download"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/inventory-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated", "swagger", "inventory", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"inventory",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/isa-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "isa", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"isa",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/oms-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "oms", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"oms",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/print-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "print", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"print",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
"sourceRoot": "generated/swagger/wws-api/src",
|
||||
"prefix": "lib",
|
||||
"projectType": "library",
|
||||
"tags": ["generated","swagger", "wws", "api"],
|
||||
"tags": [
|
||||
"generated",
|
||||
"swagger",
|
||||
"wws",
|
||||
"api",
|
||||
"scope:generated",
|
||||
"type:generated"
|
||||
],
|
||||
"targets": {
|
||||
"generate": {
|
||||
"command": "ng-swagger-gen --config {projectRoot}/ng-swagger-gen.json --output {projectRoot}/src",
|
||||
@@ -13,7 +20,9 @@
|
||||
"{projectRoot}/ng-swagger-gen.json",
|
||||
"!{projectRoot}/src/**/*.ts"
|
||||
],
|
||||
"outputs": ["{projectRoot}/src"],
|
||||
"outputs": [
|
||||
"{projectRoot}/src"
|
||||
],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "libs/icons/src",
|
||||
"projectType": "library",
|
||||
"tags": [],
|
||||
"tags": [
|
||||
"scope:icons",
|
||||
"type:icon"
|
||||
],
|
||||
"targets": {
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"outputs": [
|
||||
"{workspaceRoot}/coverage/{projectRoot}"
|
||||
],
|
||||
"options": {
|
||||
"jestConfig": "libs/icons/jest.config.ts"
|
||||
}
|
||||
|
||||
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