@webpieces/dev-config 0.2.21 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,6 +6,7 @@ Development configuration, scripts, and patterns for WebPieces projects.
6
6
 
7
7
  This package provides shareable development tools for projects using the WebPieces framework:
8
8
 
9
+ - **Nx Plugin** for automatic architecture validation and circular dependency checking
9
10
  - **Executable scripts** for common development tasks
10
11
  - **ESLint configuration** with WebPieces patterns and best practices
11
12
  - **Jest preset** for testing TypeScript projects
@@ -14,6 +15,14 @@ This package provides shareable development tools for projects using the WebPiec
14
15
 
15
16
  ## Installation
16
17
 
18
+ For Nx workspaces (recommended):
19
+
20
+ ```bash
21
+ nx add @webpieces/dev-config
22
+ ```
23
+
24
+ For non-Nx projects:
25
+
17
26
  ```bash
18
27
  npm install --save-dev @webpieces/dev-config
19
28
  ```
@@ -73,7 +82,41 @@ To develop against a local copy of webpieces-ts:
73
82
  wp-use-published
74
83
  ```
75
84
 
76
- ### 2. ESLint Configuration
85
+ ### 2. Nx Plugin (Architecture Validation)
86
+
87
+ Automatically adds architecture validation and circular dependency checking to Nx workspaces.
88
+
89
+ #### Quick Start
90
+
91
+ ```bash
92
+ # Install and register the plugin
93
+ nx add @webpieces/dev-config
94
+
95
+ # Generate dependency graph
96
+ nx run .:arch:generate
97
+
98
+ # Validate architecture
99
+ nx run .:arch:validate-no-cycles
100
+
101
+ # Check project for circular dependencies
102
+ nx run my-project:check-circular-deps
103
+ ```
104
+
105
+ #### Available Targets
106
+
107
+ **Workspace-level:**
108
+ - `arch:generate` - Generate dependency graph
109
+ - `arch:visualize` - Visualize dependency graph
110
+ - `arch:validate-no-cycles` - Validate no circular dependencies
111
+ - `arch:validate-no-skiplevel-deps` - Validate no redundant dependencies
112
+ - `arch:validate-architecture-unchanged` - Validate against blessed graph
113
+
114
+ **Per-project:**
115
+ - `check-circular-deps` - Check for circular dependencies (auto-added to all projects)
116
+
117
+ For detailed documentation, see [Plugin README](./plugin/README.md).
118
+
119
+ ### 3. ESLint Configuration
77
120
 
78
121
  Import the base configuration in your `eslint.config.mjs`:
79
122
 
@@ -0,0 +1,240 @@
1
+ import { formatFiles, readNxJson, Tree, updateNxJson, updateJson, addDependenciesToPackageJson } from '@nx/devkit';
2
+ import type { InitGeneratorSchema } from './schema';
3
+
4
+ /**
5
+ * Init generator for @webpieces/dev-config
6
+ *
7
+ * Automatically runs when users execute: nx add @webpieces/dev-config
8
+ *
9
+ * Responsibilities:
10
+ * - Registers the plugin in nx.json
11
+ * - Creates architecture/ directory if needed
12
+ * - Adds madge as a devDependency (required for circular dep checking)
13
+ * - Adds convenient npm scripts to package.json
14
+ * - Always creates eslint.webpieces.config.mjs with @webpieces rules
15
+ * - Creates eslint.config.mjs (if not exists) that imports eslint.webpieces.config.mjs
16
+ * - If eslint.config.mjs exists, shows user how to import eslint.webpieces.config.mjs
17
+ * - Provides helpful output about available targets
18
+ */
19
+ export default async function initGenerator(tree: Tree, options: InitGeneratorSchema) {
20
+ registerPlugin(tree);
21
+ const installTask = addMadgeDependency(tree);
22
+ createArchitectureDirectory(tree);
23
+ addNpmScripts(tree);
24
+ createEslintConfig(tree);
25
+
26
+ if (!options.skipFormat) {
27
+ await formatFiles(tree);
28
+ }
29
+
30
+ return createSuccessCallback(installTask);
31
+ }
32
+
33
+ function registerPlugin(tree: Tree): void {
34
+ const nxJson = readNxJson(tree);
35
+ if (!nxJson) {
36
+ throw new Error('Could not read nx.json. Are you in an Nx workspace?');
37
+ }
38
+
39
+ if (!nxJson.plugins) {
40
+ nxJson.plugins = [];
41
+ }
42
+
43
+ const pluginName = '@webpieces/dev-config';
44
+ const alreadyRegistered = nxJson.plugins.some(
45
+ (p) => typeof p === 'string' ? p === pluginName : p.plugin === pluginName
46
+ );
47
+
48
+ if (!alreadyRegistered) {
49
+ nxJson.plugins.push(pluginName);
50
+ updateNxJson(tree, nxJson);
51
+ console.log(`✅ Registered ${pluginName} plugin in nx.json`);
52
+ } else {
53
+ console.log(`ℹ️ ${pluginName} plugin is already registered`);
54
+ }
55
+ }
56
+
57
+ function addMadgeDependency(tree: Tree) {
58
+ return addDependenciesToPackageJson(tree, {}, { 'madge': '^8.0.0' });
59
+ }
60
+
61
+ function createArchitectureDirectory(tree: Tree): void {
62
+ if (!tree.exists('architecture')) {
63
+ tree.write('architecture/.gitkeep', '');
64
+ console.log('✅ Created architecture/ directory');
65
+ }
66
+ }
67
+
68
+ function addNpmScripts(tree: Tree): void {
69
+ updateJson(tree, 'package.json', (pkgJson) => {
70
+ pkgJson.scripts = pkgJson.scripts ?? {};
71
+
72
+ // Add architecture validation scripts
73
+ pkgJson.scripts['arch:generate'] = 'nx run .:arch:generate';
74
+ pkgJson.scripts['arch:visualize'] = 'nx run .:arch:visualize';
75
+ pkgJson.scripts['arch:validate'] = 'nx run .:arch:validate-no-cycles && nx run .:arch:validate-no-skiplevel-deps';
76
+ pkgJson.scripts['arch:validate-all'] = 'nx run .:arch:validate-no-cycles && nx run .:arch:validate-no-skiplevel-deps && nx run .:arch:validate-architecture-unchanged';
77
+
78
+ // Add circular dependency checking scripts
79
+ pkgJson.scripts['arch:check-circular'] = 'nx run-many --target=check-circular-deps --all';
80
+ pkgJson.scripts['arch:check-circular-affected'] = 'nx affected --target=check-circular-deps';
81
+
82
+ // Complete validation including circular deps
83
+ pkgJson.scripts['arch:validate-complete'] = 'npm run arch:validate-all && npm run arch:check-circular';
84
+
85
+ return pkgJson;
86
+ });
87
+
88
+ console.log('✅ Added npm scripts for architecture validation and circular dependency checking');
89
+ }
90
+
91
+ function createEslintConfig(tree: Tree): void {
92
+ const webpiecesConfigPath = 'eslint.webpieces.config.mjs';
93
+ const mainConfigPath = 'eslint.config.mjs';
94
+
95
+ // Always create eslint.webpieces.config.mjs with our rules
96
+ createWebpiecesEslintConfig(tree, webpiecesConfigPath);
97
+
98
+ // Check if main eslint.config.mjs exists
99
+ if (tree.exists(mainConfigPath)) {
100
+ // Existing config - show them how to import
101
+ console.log('');
102
+ console.log('📋 Existing eslint.config.mjs detected');
103
+ console.log('');
104
+ console.log('To use @webpieces/dev-config ESLint rules, add this import to your eslint.config.mjs:');
105
+ console.log('');
106
+ console.log(' import webpiecesConfig from \'./eslint.webpieces.config.mjs\';');
107
+ console.log('');
108
+ console.log('Then spread it into your config array:');
109
+ console.log('');
110
+ console.log(' export default [');
111
+ console.log(' ...webpiecesConfig, // Add this line');
112
+ console.log(' // ... your existing config');
113
+ console.log(' ];');
114
+ console.log('');
115
+ } else {
116
+ // No existing config - create one that imports webpieces config
117
+ const mainConfig = `// ESLint configuration
118
+ // Imports @webpieces/dev-config rules
119
+
120
+ import webpiecesConfig from './eslint.webpieces.config.mjs';
121
+
122
+ // Export the webpieces configuration
123
+ // You can add your own rules after spreading webpiecesConfig
124
+ export default [
125
+ ...webpiecesConfig,
126
+ // Add your custom ESLint configuration here
127
+ ];
128
+ `;
129
+
130
+ tree.write(mainConfigPath, mainConfig);
131
+ console.log('✅ Created eslint.config.mjs with @webpieces/dev-config rules');
132
+ }
133
+ }
134
+
135
+ function createWebpiecesEslintConfig(tree: Tree, configPath: string): void {
136
+ const webpiecesConfig = `// @webpieces/dev-config ESLint rules
137
+ // This file contains the ESLint configuration provided by @webpieces/dev-config
138
+ // You can modify or remove rules as needed for your project
139
+
140
+ import webpiecesPlugin from '@webpieces/dev-config/eslint-plugin';
141
+ import tseslint from '@typescript-eslint/eslint-plugin';
142
+ import tsparser from '@typescript-eslint/parser';
143
+
144
+ export default [
145
+ {
146
+ ignores: ['**/dist', '**/node_modules', '**/coverage', '**/.nx'],
147
+ },
148
+ {
149
+ files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
150
+ plugins: {
151
+ '@webpieces': webpiecesPlugin,
152
+ '@typescript-eslint': tseslint,
153
+ },
154
+ languageOptions: {
155
+ parser: tsparser,
156
+ ecmaVersion: 2021,
157
+ sourceType: 'module',
158
+ },
159
+ rules: {
160
+ // WebPieces custom rules
161
+ '@webpieces/catch-error-pattern': 'error',
162
+ '@webpieces/no-unmanaged-exceptions': 'error',
163
+ '@webpieces/max-method-lines': ['error', { max: 70 }],
164
+ '@webpieces/max-file-lines': ['error', { max: 700 }],
165
+ '@webpieces/enforce-architecture': 'error',
166
+
167
+ // TypeScript rules
168
+ '@typescript-eslint/no-explicit-any': 'off',
169
+ '@typescript-eslint/explicit-function-return-type': 'off',
170
+ '@typescript-eslint/no-unused-vars': 'off',
171
+ '@typescript-eslint/no-empty-interface': 'off',
172
+ '@typescript-eslint/no-empty-function': 'off',
173
+
174
+ // General code quality
175
+ 'no-console': 'off',
176
+ 'no-debugger': 'off',
177
+ 'no-var': 'error',
178
+ 'prefer-const': 'off',
179
+ },
180
+ },
181
+ {
182
+ // Test files - relaxed rules
183
+ files: ['**/*.spec.ts', '**/*.test.ts'],
184
+ rules: {
185
+ '@typescript-eslint/no-explicit-any': 'off',
186
+ '@typescript-eslint/no-non-null-assertion': 'off',
187
+ '@webpieces/max-method-lines': 'off',
188
+ },
189
+ },
190
+ ];
191
+ `;
192
+
193
+ tree.write(configPath, webpiecesConfig);
194
+ console.log('✅ Created eslint.webpieces.config.mjs with @webpieces/dev-config rules');
195
+ }
196
+
197
+ function createSuccessCallback(installTask: ReturnType<typeof addDependenciesToPackageJson>) {
198
+ return async () => {
199
+ await installTask();
200
+ console.log('✅ Added madge to devDependencies');
201
+ console.log('');
202
+ console.log('✅ @webpieces/dev-config plugin initialized!');
203
+ console.log('');
204
+ printAvailableTargets();
205
+ };
206
+ }
207
+
208
+ function printAvailableTargets(): void {
209
+ console.log('📝 Available npm scripts (convenient shortcuts):');
210
+ console.log('');
211
+ console.log(' Architecture graph:');
212
+ console.log(' npm run arch:generate # Generate dependency graph');
213
+ console.log(' npm run arch:visualize # Visualize dependency graph');
214
+ console.log('');
215
+ console.log(' Validation:');
216
+ console.log(' npm run arch:validate # Quick validation (no-cycles + no-skiplevel-deps)');
217
+ console.log(' npm run arch:validate-all # Full arch validation (+ unchanged check)');
218
+ console.log(' npm run arch:check-circular # Check all projects for circular deps');
219
+ console.log(' npm run arch:check-circular-affected # Check affected projects only');
220
+ console.log(' npm run arch:validate-complete # Complete validation (arch + circular)');
221
+ console.log('');
222
+ console.log('📝 Available Nx targets:');
223
+ console.log('');
224
+ console.log(' Workspace-level architecture validation:');
225
+ console.log(' nx run .:arch:generate # Generate dependency graph');
226
+ console.log(' nx run .:arch:visualize # Visualize dependency graph');
227
+ console.log(' nx run .:arch:validate-no-cycles # Check for circular dependencies');
228
+ console.log(' nx run .:arch:validate-no-skiplevel-deps # Check for redundant dependencies');
229
+ console.log(' nx run .:arch:validate-architecture-unchanged # Validate against blessed graph');
230
+ console.log('');
231
+ console.log(' Per-project circular dependency checking:');
232
+ console.log(' nx run <project>:check-circular-deps # Check project for circular deps');
233
+ console.log(' nx affected --target=check-circular-deps # Check all affected projects');
234
+ console.log(' nx run-many --target=check-circular-deps --all # Check all projects');
235
+ console.log('');
236
+ console.log('💡 Quick start:');
237
+ console.log(' npm run arch:generate # Generate the graph first');
238
+ console.log(' npm run arch:validate-complete # Run complete validation');
239
+ console.log('');
240
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "$id": "InitGenerator",
4
+ "title": "Initialize @webpieces/dev-config",
5
+ "description": "Initialize @webpieces/dev-config plugin in an Nx workspace",
6
+ "type": "object",
7
+ "properties": {
8
+ "skipFormat": {
9
+ "type": "boolean",
10
+ "description": "Skip formatting files with Prettier",
11
+ "default": false
12
+ }
13
+ },
14
+ "required": []
15
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "generators": {
4
+ "init": {
5
+ "factory": "./generators/init/generator",
6
+ "schema": "./generators/init/schema.json",
7
+ "description": "Initialize @webpieces/dev-config in an Nx workspace"
8
+ }
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/dev-config",
3
- "version": "0.2.21",
3
+ "version": "0.2.24",
4
4
  "description": "Development configuration, scripts, and patterns for WebPieces projects",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  "wp-setup-patterns": "./bin/setup-claude-patterns.sh"
13
13
  },
14
14
  "executors": "./executors.json",
15
+ "generators": "./generators.json",
15
16
  "exports": {
16
17
  ".": "./index.js",
17
18
  "./package.json": "./package.json",
@@ -19,9 +20,11 @@
19
20
  "./eslint-plugin": "./eslint-plugin/index.js",
20
21
  "./jest": "./config/jest/preset.js",
21
22
  "./tsconfig": "./config/typescript/tsconfig.base.json",
23
+ "./plugin": "./plugin.js",
22
24
  "./plugins/circular-deps": "./plugins/circular-deps/index.js",
23
25
  "./architecture": "./architecture/index.js",
24
- "./executors.json": "./executors.json"
26
+ "./executors.json": "./executors.json",
27
+ "./generators.json": "./generators.json"
25
28
  },
26
29
  "files": [
27
30
  "bin/**/*",
@@ -29,6 +32,10 @@
29
32
  "eslint-plugin/**/*",
30
33
  "patterns/**/*",
31
34
  "plugins/**/*",
35
+ "plugin/**/*",
36
+ "plugin.js",
37
+ "generators/**/*",
38
+ "generators.json",
32
39
  "architecture/**/*",
33
40
  "executors.json",
34
41
  "README.md"
@@ -0,0 +1,243 @@
1
+ # @webpieces/dev-config Plugin
2
+
3
+ Nx inference plugin that automatically provides architecture validation and circular dependency checking for your workspace.
4
+
5
+ ## Features
6
+
7
+ ### Workspace-Level Architecture Validation
8
+
9
+ Automatically adds targets for managing and validating your project architecture:
10
+
11
+ - **`arch:generate`** - Generate dependency graph from project.json files
12
+ - **`arch:visualize`** - Create visual representations of the dependency graph
13
+ - **`arch:validate-no-cycles`** - Validate the architecture has no circular dependencies
14
+ - **`arch:validate-no-skiplevel-deps`** - Validate no redundant transitive dependencies
15
+ - **`arch:validate-architecture-unchanged`** - Validate against blessed dependency graph
16
+
17
+ ### Per-Project Circular Dependency Checking
18
+
19
+ Automatically adds a `check-circular-deps` target to every project with a `src/` directory using [madge](https://github.com/pahen/madge).
20
+
21
+ ## Installation
22
+
23
+ Add the plugin to your Nx workspace:
24
+
25
+ ```bash
26
+ nx add @webpieces/dev-config
27
+ ```
28
+
29
+ This automatically:
30
+ - Registers the plugin in `nx.json`
31
+ - Adds `madge` as a devDependency (required for circular dependency checking)
32
+ - Creates the `architecture/` directory
33
+ - Adds convenient npm scripts to `package.json`
34
+ - Creates `eslint.webpieces.config.mjs` with @webpieces ESLint rules
35
+ - Creates `eslint.config.mjs` (if you don't have one) that imports the webpieces rules
36
+ - If you already have `eslint.config.mjs`, shows you how to import the webpieces rules (one line)
37
+ - Makes all targets immediately available
38
+
39
+ **For new projects: Zero configuration needed!** All architecture validation, circular dependency checking, and ESLint rules are active.
40
+
41
+ **For existing projects with ESLint:** Just add one import line shown during installation to enable the @webpieces ESLint rules.
42
+
43
+ ## Usage
44
+
45
+ ### Convenient npm Scripts
46
+
47
+ The init generator adds these npm scripts for easy access:
48
+
49
+ ```bash
50
+ # Generate and visualize
51
+ npm run arch:generate # Generate dependency graph
52
+ npm run arch:visualize # Visualize in browser
53
+
54
+ # Validation
55
+ npm run arch:validate # Quick: no-cycles + no-skiplevel-deps
56
+ npm run arch:validate-all # Full: adds architecture-unchanged check
57
+ npm run arch:check-circular # Check all projects for circular deps (madge)
58
+ npm run arch:check-circular-affected # Check only affected projects
59
+ npm run arch:validate-complete # Complete: all validations + circular deps
60
+
61
+ # Recommended workflow
62
+ npm run arch:generate # 1. Generate graph first
63
+ npm run arch:validate-complete # 2. Run all validations
64
+ ```
65
+
66
+ ### Direct Nx Targets
67
+
68
+ You can also run targets directly with Nx:
69
+
70
+ ```bash
71
+ # Generate the dependency graph
72
+ nx run .:arch:generate
73
+
74
+ # Visualize the graph in your browser
75
+ nx run .:arch:visualize
76
+
77
+ # Validate no circular dependencies
78
+ nx run .:arch:validate-no-cycles
79
+
80
+ # Validate against blessed graph (for CI)
81
+ nx run .:arch:validate-architecture-unchanged
82
+
83
+ # Check for redundant dependencies
84
+ nx run .:arch:validate-no-skiplevel-deps
85
+ ```
86
+
87
+ ### Per-Project Circular Dependency Checking
88
+
89
+ ```bash
90
+ # Check a specific project
91
+ nx run my-project:check-circular-deps
92
+
93
+ # Check all affected projects
94
+ nx affected --target=check-circular-deps
95
+
96
+ # Check all projects
97
+ nx run-many --target=check-circular-deps --all
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ Configure the plugin in `nx.json`:
103
+
104
+ ```json
105
+ {
106
+ "plugins": [
107
+ {
108
+ "plugin": "@webpieces/dev-config",
109
+ "options": {
110
+ "circularDeps": {
111
+ "enabled": true,
112
+ "targetName": "check-circular-deps",
113
+ "excludePatterns": ["**/test-fixtures/**"]
114
+ },
115
+ "workspace": {
116
+ "enabled": true,
117
+ "targetPrefix": "arch:",
118
+ "validations": {
119
+ "noCycles": true,
120
+ "noSkipLevelDeps": true,
121
+ "architectureUnchanged": true
122
+ },
123
+ "features": {
124
+ "generate": true,
125
+ "visualize": true
126
+ }
127
+ }
128
+ }
129
+ }
130
+ ]
131
+ }
132
+ ```
133
+
134
+ ### Configuration Options
135
+
136
+ #### `circularDeps`
137
+
138
+ - **`enabled`** (boolean, default: `true`) - Enable/disable circular dependency checking
139
+ - **`targetName`** (string, default: `'check-circular-deps'`) - Name of the target to create
140
+ - **`excludePatterns`** (string[], default: `[]`) - Patterns to exclude from checking
141
+
142
+ #### `workspace`
143
+
144
+ - **`enabled`** (boolean, default: `true`) - Enable/disable workspace-level validation
145
+ - **`targetPrefix`** (string, default: `'arch:'`) - Prefix for workspace target names
146
+ - **`graphPath`** (string, default: `'architecture/dependencies.json'`) - Path to dependency graph file
147
+
148
+ ##### `workspace.validations`
149
+
150
+ - **`noCycles`** (boolean, default: `true`) - Enable no-cycles validation
151
+ - **`noSkipLevelDeps`** (boolean, default: `true`) - Enable skip-level deps validation
152
+ - **`architectureUnchanged`** (boolean, default: `true`) - Enable unchanged graph validation
153
+
154
+ ##### `workspace.features`
155
+
156
+ - **`generate`** (boolean, default: `true`) - Enable graph generation target
157
+ - **`visualize`** (boolean, default: `true`) - Enable visualization target
158
+
159
+ ## Examples
160
+
161
+ ### Disable Architecture Validation, Keep Circular Deps
162
+
163
+ ```json
164
+ {
165
+ "plugin": "@webpieces/dev-config",
166
+ "options": {
167
+ "workspace": { "enabled": false }
168
+ }
169
+ }
170
+ ```
171
+
172
+ ### Disable Circular Deps, Keep Architecture Validation
173
+
174
+ ```json
175
+ {
176
+ "plugin": "@webpieces/dev-config",
177
+ "options": {
178
+ "circularDeps": { "enabled": false }
179
+ }
180
+ }
181
+ ```
182
+
183
+ ### Disable Specific Validations
184
+
185
+ ```json
186
+ {
187
+ "plugin": "@webpieces/dev-config",
188
+ "options": {
189
+ "workspace": {
190
+ "validations": {
191
+ "architectureUnchanged": false,
192
+ "noSkipLevelDeps": false
193
+ }
194
+ }
195
+ }
196
+ }
197
+ ```
198
+
199
+ ### Exclude Test Fixtures from Circular Deps
200
+
201
+ ```json
202
+ {
203
+ "plugin": "@webpieces/dev-config",
204
+ "options": {
205
+ "circularDeps": {
206
+ "excludePatterns": ["**/test-fixtures/**", "**/__tests__/**"]
207
+ }
208
+ }
209
+ }
210
+ ```
211
+
212
+ ### Custom Target Names
213
+
214
+ ```json
215
+ {
216
+ "plugin": "@webpieces/dev-config",
217
+ "options": {
218
+ "circularDeps": { "targetName": "circular-check" },
219
+ "workspace": { "targetPrefix": "architecture:" }
220
+ }
221
+ }
222
+ ```
223
+
224
+ ## How It Works
225
+
226
+ The plugin uses Nx's [Project Crystal (Inferred Tasks)](https://nx.dev/concepts/inferred-tasks) feature via the `createNodesV2` API to automatically detect and configure targets:
227
+
228
+ 1. **Workspace Detection**: Looks for a `project.json` at the workspace root to add architecture targets
229
+ 2. **Project Detection**: Scans all projects for `src/` directories to add circular-deps targets
230
+ 3. **Pattern Matching**: Respects exclude patterns for fine-grained control
231
+
232
+ ## Requirements
233
+
234
+ - Nx >= 18.0.0
235
+ - Node.js >= 18.0.0
236
+ - [Graphviz](https://graphviz.org/) (for visualization)
237
+ - [madge](https://github.com/pahen/madge) (bundled, used for circular dep checking)
238
+
239
+ ## Related Documentation
240
+
241
+ - [Nx Inferred Tasks](https://nx.dev/concepts/inferred-tasks)
242
+ - [Architecture Validation Guide](../../architecture/README.md)
243
+ - [ESLint Plugin](../eslint-plugin/README.md)
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Re-export plugin from parent directory for clean imports
3
+ */
4
+ export * from '../plugin';
@@ -1,8 +0,0 @@
1
- /**
2
- * Circular Dependencies Plugin
3
- *
4
- * Nx inference plugin that automatically adds check-circular-deps target
5
- * to all projects with a src/ directory.
6
- */
7
- export * from './plugin';
8
- export { default } from './plugin';
@@ -1,14 +0,0 @@
1
- "use strict";
2
- /**
3
- * Circular Dependencies Plugin
4
- *
5
- * Nx inference plugin that automatically adds check-circular-deps target
6
- * to all projects with a src/ directory.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.default = void 0;
10
- const tslib_1 = require("tslib");
11
- tslib_1.__exportStar(require("./plugin"), exports);
12
- var plugin_1 = require("./plugin");
13
- Object.defineProperty(exports, "default", { enumerable: true, get: function () { return tslib_1.__importDefault(plugin_1).default; } });
14
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/plugins/circular-deps/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;AAEH,mDAAyB;AACzB,mCAAmC;AAA1B,0HAAA,OAAO,OAAA","sourcesContent":["/**\n * Circular Dependencies Plugin\n *\n * Nx inference plugin that automatically adds check-circular-deps target\n * to all projects with a src/ directory.\n */\n\nexport * from './plugin';\nexport { default } from './plugin';\n"]}
@@ -1,9 +0,0 @@
1
- /**
2
- * Circular Dependencies Plugin
3
- *
4
- * Nx inference plugin that automatically adds check-circular-deps target
5
- * to all projects with a src/ directory.
6
- */
7
-
8
- export * from './plugin';
9
- export { default } from './plugin';
@@ -1,32 +0,0 @@
1
- /**
2
- * Nx Inference Plugin for Circular Dependency Checking
3
- *
4
- * This plugin automatically creates a "check-circular-deps" target for ANY project
5
- * that has a src/ directory, similar to how @nx/eslint/plugin creates lint targets.
6
- *
7
- * Benefits:
8
- * - Zero configuration per project
9
- * - Works for ALL projects (services + libraries)
10
- * - New projects automatically get the target
11
- * - `nx affected --target=check-circular-deps` works on everything
12
- *
13
- * Usage:
14
- * Add to nx.json plugins array:
15
- * {
16
- * "plugins": ["@webpieces/dev-config/plugins/circular-deps"]
17
- * }
18
- *
19
- * Then run:
20
- * - nx run <project>:check-circular-deps
21
- * - nx affected --target=check-circular-deps
22
- */
23
- import type { CreateNodesV2 } from '@nx/devkit';
24
- /**
25
- * Nx V2 Inference Plugin
26
- * Matches project.json files and creates check-circular-deps target
27
- */
28
- export declare const createNodesV2: CreateNodesV2;
29
- declare const _default: {
30
- createNodesV2: CreateNodesV2;
31
- };
32
- export default _default;
@@ -1,73 +0,0 @@
1
- "use strict";
2
- /**
3
- * Nx Inference Plugin for Circular Dependency Checking
4
- *
5
- * This plugin automatically creates a "check-circular-deps" target for ANY project
6
- * that has a src/ directory, similar to how @nx/eslint/plugin creates lint targets.
7
- *
8
- * Benefits:
9
- * - Zero configuration per project
10
- * - Works for ALL projects (services + libraries)
11
- * - New projects automatically get the target
12
- * - `nx affected --target=check-circular-deps` works on everything
13
- *
14
- * Usage:
15
- * Add to nx.json plugins array:
16
- * {
17
- * "plugins": ["@webpieces/dev-config/plugins/circular-deps"]
18
- * }
19
- *
20
- * Then run:
21
- * - nx run <project>:check-circular-deps
22
- * - nx affected --target=check-circular-deps
23
- */
24
- Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.createNodesV2 = void 0;
26
- const path_1 = require("path");
27
- const fs_1 = require("fs");
28
- /**
29
- * Nx V2 Inference Plugin
30
- * Matches project.json files and creates check-circular-deps target
31
- */
32
- exports.createNodesV2 = [
33
- // Pattern to match: look for project.json files
34
- '**/project.json',
35
- // Inference function
36
- async (projectFiles, _options, context) => {
37
- const results = [];
38
- for (const projectFile of projectFiles) {
39
- const projectRoot = (0, path_1.dirname)(projectFile);
40
- const srcDir = (0, path_1.join)(context.workspaceRoot, projectRoot, 'src');
41
- // Only create target if project has a src/ directory
42
- if ((0, fs_1.existsSync)(srcDir)) {
43
- const checkCircularDepsTarget = {
44
- executor: 'nx:run-commands',
45
- cache: true,
46
- inputs: ['default'],
47
- outputs: [],
48
- options: {
49
- command: 'npx madge --circular --extensions ts,tsx src',
50
- cwd: projectRoot,
51
- },
52
- metadata: {
53
- technologies: ['madge'],
54
- description: 'Check for circular dependencies using madge',
55
- },
56
- };
57
- const result = {
58
- projects: {
59
- [projectRoot]: {
60
- targets: {
61
- 'check-circular-deps': checkCircularDepsTarget,
62
- },
63
- },
64
- },
65
- };
66
- results.push([projectFile, result]);
67
- }
68
- }
69
- return results;
70
- },
71
- ];
72
- exports.default = { createNodesV2: exports.createNodesV2 };
73
- //# sourceMappingURL=plugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/plugins/circular-deps/plugin.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AAEH,+BAAqC;AACrC,2BAAgC;AAGhC;;;GAGG;AACU,QAAA,aAAa,GAAkB;IACxC,gDAAgD;IAChD,iBAAiB;IAEjB,qBAAqB;IACrB,KAAK,EACD,YAA+B,EAC/B,QAAiB,EACjB,OAA6B,EACD,EAAE;QAC9B,MAAM,OAAO,GAAgD,EAAE,CAAC;QAEhE,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACrC,MAAM,WAAW,GAAG,IAAA,cAAO,EAAC,WAAW,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,IAAA,WAAI,EAAC,OAAO,CAAC,aAAa,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YAE/D,qDAAqD;YACrD,IAAI,IAAA,eAAU,EAAC,MAAM,CAAC,EAAE,CAAC;gBACrB,MAAM,uBAAuB,GAAG;oBAC5B,QAAQ,EAAE,iBAAiB;oBAC3B,KAAK,EAAE,IAAI;oBACX,MAAM,EAAE,CAAC,SAAS,CAAC;oBACnB,OAAO,EAAE,EAAc;oBACvB,OAAO,EAAE;wBACL,OAAO,EAAE,8CAA8C;wBACvD,GAAG,EAAE,WAAW;qBACnB;oBACD,QAAQ,EAAE;wBACN,YAAY,EAAE,CAAC,OAAO,CAAC;wBACvB,WAAW,EAAE,6CAA6C;qBAC7D;iBACJ,CAAC;gBAEF,MAAM,MAAM,GAAsB;oBAC9B,QAAQ,EAAE;wBACN,CAAC,WAAW,CAAC,EAAE;4BACX,OAAO,EAAE;gCACL,qBAAqB,EAAE,uBAAuB;6BACjD;yBACJ;qBACJ;iBACJ,CAAC;gBAEF,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,CAAU,CAAC,CAAC;YACjD,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ,CAAC;AAEF,kBAAe,EAAE,aAAa,EAAb,qBAAa,EAAE,CAAC","sourcesContent":["/**\n * Nx Inference Plugin for Circular Dependency Checking\n *\n * This plugin automatically creates a \"check-circular-deps\" target for ANY project\n * that has a src/ directory, similar to how @nx/eslint/plugin creates lint targets.\n *\n * Benefits:\n * - Zero configuration per project\n * - Works for ALL projects (services + libraries)\n * - New projects automatically get the target\n * - `nx affected --target=check-circular-deps` works on everything\n *\n * Usage:\n * Add to nx.json plugins array:\n * {\n * \"plugins\": [\"@webpieces/dev-config/plugins/circular-deps\"]\n * }\n *\n * Then run:\n * - nx run <project>:check-circular-deps\n * - nx affected --target=check-circular-deps\n */\n\nimport { dirname, join } from 'path';\nimport { existsSync } from 'fs';\nimport type { CreateNodesV2, CreateNodesContextV2, CreateNodesResultV2, CreateNodesResult } from '@nx/devkit';\n\n/**\n * Nx V2 Inference Plugin\n * Matches project.json files and creates check-circular-deps target\n */\nexport const createNodesV2: CreateNodesV2 = [\n // Pattern to match: look for project.json files\n '**/project.json',\n\n // Inference function\n async (\n projectFiles: readonly string[],\n _options: unknown,\n context: CreateNodesContextV2\n ): Promise<CreateNodesResultV2> => {\n const results: Array<readonly [string, CreateNodesResult]> = [];\n\n for (const projectFile of projectFiles) {\n const projectRoot = dirname(projectFile);\n const srcDir = join(context.workspaceRoot, projectRoot, 'src');\n\n // Only create target if project has a src/ directory\n if (existsSync(srcDir)) {\n const checkCircularDepsTarget = {\n executor: 'nx:run-commands',\n cache: true,\n inputs: ['default'],\n outputs: [] as string[],\n options: {\n command: 'npx madge --circular --extensions ts,tsx src',\n cwd: projectRoot,\n },\n metadata: {\n technologies: ['madge'],\n description: 'Check for circular dependencies using madge',\n },\n };\n\n const result: CreateNodesResult = {\n projects: {\n [projectRoot]: {\n targets: {\n 'check-circular-deps': checkCircularDepsTarget,\n },\n },\n },\n };\n\n results.push([projectFile, result] as const);\n }\n }\n\n return results;\n },\n];\n\nexport default { createNodesV2 };\n"]}
@@ -1,83 +0,0 @@
1
- /**
2
- * Nx Inference Plugin for Circular Dependency Checking
3
- *
4
- * This plugin automatically creates a "check-circular-deps" target for ANY project
5
- * that has a src/ directory, similar to how @nx/eslint/plugin creates lint targets.
6
- *
7
- * Benefits:
8
- * - Zero configuration per project
9
- * - Works for ALL projects (services + libraries)
10
- * - New projects automatically get the target
11
- * - `nx affected --target=check-circular-deps` works on everything
12
- *
13
- * Usage:
14
- * Add to nx.json plugins array:
15
- * {
16
- * "plugins": ["@webpieces/dev-config/plugins/circular-deps"]
17
- * }
18
- *
19
- * Then run:
20
- * - nx run <project>:check-circular-deps
21
- * - nx affected --target=check-circular-deps
22
- */
23
-
24
- import { dirname, join } from 'path';
25
- import { existsSync } from 'fs';
26
- import type { CreateNodesV2, CreateNodesContextV2, CreateNodesResultV2, CreateNodesResult } from '@nx/devkit';
27
-
28
- /**
29
- * Nx V2 Inference Plugin
30
- * Matches project.json files and creates check-circular-deps target
31
- */
32
- export const createNodesV2: CreateNodesV2 = [
33
- // Pattern to match: look for project.json files
34
- '**/project.json',
35
-
36
- // Inference function
37
- async (
38
- projectFiles: readonly string[],
39
- _options: unknown,
40
- context: CreateNodesContextV2
41
- ): Promise<CreateNodesResultV2> => {
42
- const results: Array<readonly [string, CreateNodesResult]> = [];
43
-
44
- for (const projectFile of projectFiles) {
45
- const projectRoot = dirname(projectFile);
46
- const srcDir = join(context.workspaceRoot, projectRoot, 'src');
47
-
48
- // Only create target if project has a src/ directory
49
- if (existsSync(srcDir)) {
50
- const checkCircularDepsTarget = {
51
- executor: 'nx:run-commands',
52
- cache: true,
53
- inputs: ['default'],
54
- outputs: [] as string[],
55
- options: {
56
- command: 'npx madge --circular --extensions ts,tsx src',
57
- cwd: projectRoot,
58
- },
59
- metadata: {
60
- technologies: ['madge'],
61
- description: 'Check for circular dependencies using madge',
62
- },
63
- };
64
-
65
- const result: CreateNodesResult = {
66
- projects: {
67
- [projectRoot]: {
68
- targets: {
69
- 'check-circular-deps': checkCircularDepsTarget,
70
- },
71
- },
72
- },
73
- };
74
-
75
- results.push([projectFile, result] as const);
76
- }
77
- }
78
-
79
- return results;
80
- },
81
- ];
82
-
83
- export default { createNodesV2 };