@webpieces/nx-webpieces-rules 0.0.1 → 0.2.113
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/package.json +5 -4
- package/src/executor-result.d.ts +4 -0
- package/src/executor-result.js +10 -0
- package/src/executor-result.js.map +1 -0
- package/src/executors/generate/executor.d.ts +16 -0
- package/src/executors/generate/{executor.ts → executor.js} +15 -30
- package/src/executors/generate/executor.js.map +1 -0
- package/src/executors/help/executor.d.ts +8 -0
- package/src/executors/help/{executor.ts → executor.js} +5 -12
- package/src/executors/help/executor.js.map +1 -0
- package/src/executors/validate-architecture-unchanged/executor.d.ts +17 -0
- package/src/executors/validate-architecture-unchanged/{executor.ts → executor.js} +24 -46
- package/src/executors/validate-architecture-unchanged/executor.js.map +1 -0
- package/src/executors/validate-catch-error-pattern/executor.d.ts +3 -0
- package/src/executors/validate-catch-error-pattern/executor.js +10 -0
- package/src/executors/validate-catch-error-pattern/executor.js.map +1 -0
- package/src/executors/validate-code/executor.d.ts +3 -0
- package/src/executors/validate-code/executor.js +10 -0
- package/src/executors/validate-code/executor.js.map +1 -0
- package/src/executors/validate-dtos/executor.d.ts +3 -0
- package/src/executors/validate-dtos/executor.js +10 -0
- package/src/executors/validate-dtos/executor.js.map +1 -0
- package/src/executors/validate-eslint-sync/executor.d.ts +7 -0
- package/src/executors/validate-eslint-sync/{executor.ts → executor.js} +19 -37
- package/src/executors/validate-eslint-sync/executor.js.map +1 -0
- package/src/executors/validate-modified-files/executor.d.ts +3 -0
- package/src/executors/validate-modified-files/executor.js +10 -0
- package/src/executors/validate-modified-files/executor.js.map +1 -0
- package/src/executors/validate-modified-methods/executor.d.ts +3 -0
- package/src/executors/validate-modified-methods/executor.js +10 -0
- package/src/executors/validate-modified-methods/executor.js.map +1 -0
- package/src/executors/validate-new-methods/executor.d.ts +3 -0
- package/src/executors/validate-new-methods/executor.js +10 -0
- package/src/executors/validate-new-methods/executor.js.map +1 -0
- package/src/executors/validate-no-any-unknown/executor.d.ts +3 -0
- package/src/executors/validate-no-any-unknown/executor.js +10 -0
- package/src/executors/validate-no-any-unknown/executor.js.map +1 -0
- package/src/executors/validate-no-architecture-cycles/executor.d.ts +16 -0
- package/src/executors/validate-no-architecture-cycles/{executor.ts → executor.js} +16 -28
- package/src/executors/validate-no-architecture-cycles/executor.js.map +1 -0
- package/src/executors/validate-no-destructure/executor.d.ts +3 -0
- package/src/executors/validate-no-destructure/executor.js +10 -0
- package/src/executors/validate-no-destructure/executor.js.map +1 -0
- package/src/executors/validate-no-direct-api-resolver/executor.d.ts +3 -0
- package/src/executors/validate-no-direct-api-resolver/executor.js +10 -0
- package/src/executors/validate-no-direct-api-resolver/executor.js.map +1 -0
- package/src/executors/validate-no-implicit-any/executor.d.ts +3 -0
- package/src/executors/validate-no-implicit-any/executor.js +10 -0
- package/src/executors/validate-no-implicit-any/executor.js.map +1 -0
- package/src/executors/validate-no-inline-types/executor.d.ts +3 -0
- package/src/executors/validate-no-inline-types/executor.js +10 -0
- package/src/executors/validate-no-inline-types/executor.js.map +1 -0
- package/src/executors/validate-no-skiplevel-deps/executor.d.ts +19 -0
- package/src/executors/validate-no-skiplevel-deps/{executor.ts → executor.js} +23 -63
- package/src/executors/validate-no-skiplevel-deps/executor.js.map +1 -0
- package/src/executors/validate-no-unmanaged-exceptions/executor.d.ts +3 -0
- package/src/executors/validate-no-unmanaged-exceptions/executor.js +10 -0
- package/src/executors/validate-no-unmanaged-exceptions/executor.js.map +1 -0
- package/src/executors/validate-packagejson/executor.d.ts +16 -0
- package/src/executors/validate-packagejson/{executor.ts → executor.js} +15 -32
- package/src/executors/validate-packagejson/executor.js.map +1 -0
- package/src/executors/validate-prisma-converters/executor.d.ts +3 -0
- package/src/executors/validate-prisma-converters/executor.js +10 -0
- package/src/executors/validate-prisma-converters/executor.js.map +1 -0
- package/src/executors/validate-return-types/executor.d.ts +3 -0
- package/src/executors/validate-return-types/executor.js +10 -0
- package/src/executors/validate-return-types/executor.js.map +1 -0
- package/src/executors/validate-ts-in-src/executor.d.ts +32 -0
- package/src/executors/validate-ts-in-src/{executor.ts → executor.js} +80 -135
- package/src/executors/validate-ts-in-src/executor.js.map +1 -0
- package/src/executors/validate-versions-locked/executor.d.ts +22 -0
- package/src/executors/validate-versions-locked/{executor.ts → executor.js} +49 -116
- package/src/executors/validate-versions-locked/executor.js.map +1 -0
- package/src/executors/visualize/executor.d.ts +17 -0
- package/src/executors/visualize/{executor.ts → executor.js} +16 -30
- package/src/executors/visualize/executor.js.map +1 -0
- package/src/{index.ts → index.d.ts} +5 -1
- package/src/index.js +14 -0
- package/src/index.js.map +1 -0
- package/src/lib/graph-comparator.d.ts +39 -0
- package/src/lib/{graph-comparator.ts → graph-comparator.js} +18 -67
- package/src/lib/graph-comparator.js.map +1 -0
- package/src/lib/graph-generator.d.ts +19 -0
- package/src/lib/{graph-generator.ts → graph-generator.js} +17 -30
- package/src/lib/graph-generator.js.map +1 -0
- package/src/lib/graph-loader.d.ts +31 -0
- package/src/lib/{graph-loader.ts → graph-loader.js} +24 -42
- package/src/lib/graph-loader.js.map +1 -0
- package/src/lib/graph-sorter.d.ts +37 -0
- package/src/lib/{graph-sorter.ts → graph-sorter.js} +26 -53
- package/src/lib/graph-sorter.js.map +1 -0
- package/src/lib/graph-visualizer.d.ts +31 -0
- package/src/lib/{graph-visualizer.ts → graph-visualizer.js} +32 -56
- package/src/lib/graph-visualizer.js.map +1 -0
- package/src/lib/package-validator.d.ts +40 -0
- package/src/lib/{package-validator.ts → package-validator.js} +28 -88
- package/src/lib/package-validator.js.map +1 -0
- package/src/plugin.d.ts +86 -0
- package/src/{plugin.ts → plugin.js} +100 -255
- package/src/plugin.js.map +1 -0
- package/src/toError.d.ts +5 -0
- package/src/{toError.ts → toError.js} +7 -6
- package/src/toError.js.map +1 -0
- package/LICENSE +0 -373
- package/src/executor-result.ts +0 -7
- package/src/executors/validate-catch-error-pattern/executor.ts +0 -11
- package/src/executors/validate-code/executor.ts +0 -11
- package/src/executors/validate-dtos/executor.ts +0 -11
- package/src/executors/validate-modified-files/executor.ts +0 -11
- package/src/executors/validate-modified-methods/executor.ts +0 -11
- package/src/executors/validate-new-methods/executor.ts +0 -11
- package/src/executors/validate-no-any-unknown/executor.ts +0 -11
- package/src/executors/validate-no-destructure/executor.ts +0 -11
- package/src/executors/validate-no-direct-api-resolver/executor.ts +0 -11
- package/src/executors/validate-no-implicit-any/executor.ts +0 -11
- package/src/executors/validate-no-inline-types/executor.ts +0 -11
- package/src/executors/validate-no-unmanaged-exceptions/executor.ts +0 -11
- package/src/executors/validate-prisma-converters/executor.ts +0 -11
- package/src/executors/validate-return-types/executor.ts +0 -11
|
@@ -1,53 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Package Validator
|
|
3
4
|
*
|
|
4
5
|
* Validates that package.json dependencies match the project.json build.dependsOn
|
|
5
6
|
* This ensures the two sources of truth don't drift apart.
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from '@nx/devkit';
|
|
14
|
-
import { toError } from '../toError';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Validation result for a single project
|
|
18
|
-
*/
|
|
19
|
-
export interface ProjectValidationResult {
|
|
20
|
-
project: string;
|
|
21
|
-
valid: boolean;
|
|
22
|
-
missingInPackageJson: string[];
|
|
23
|
-
extraInPackageJson: string[];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Overall validation result
|
|
28
|
-
*/
|
|
29
|
-
export interface ValidationResult {
|
|
30
|
-
valid: boolean;
|
|
31
|
-
errors: string[];
|
|
32
|
-
projectResults: ProjectValidationResult[];
|
|
33
|
-
}
|
|
34
|
-
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.validatePackageJsonDependencies = validatePackageJsonDependencies;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
12
|
+
const path = tslib_1.__importStar(require("path"));
|
|
13
|
+
const devkit_1 = require("@nx/devkit");
|
|
35
14
|
/**
|
|
36
15
|
* Read package.json dependencies for a project
|
|
37
16
|
* Returns null if package.json doesn't exist (apps often don't have one)
|
|
38
17
|
*/
|
|
39
|
-
function readPackageJsonDeps(workspaceRoot
|
|
18
|
+
function readPackageJsonDeps(workspaceRoot, projectRoot) {
|
|
40
19
|
const packageJsonPath = path.join(workspaceRoot, projectRoot, 'package.json');
|
|
41
|
-
|
|
42
20
|
if (!fs.existsSync(packageJsonPath)) {
|
|
43
21
|
return null; // No package.json - skip validation for this project
|
|
44
22
|
}
|
|
45
|
-
|
|
46
23
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
47
24
|
try {
|
|
48
25
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
49
|
-
const deps
|
|
50
|
-
|
|
26
|
+
const deps = [];
|
|
51
27
|
// Collect ALL dependencies from package.json
|
|
52
28
|
for (const depType of ['dependencies', 'peerDependencies']) {
|
|
53
29
|
const depObj = packageJson[depType] || {};
|
|
@@ -57,29 +33,25 @@ function readPackageJsonDeps(workspaceRoot: string, projectRoot: string): string
|
|
|
57
33
|
}
|
|
58
34
|
}
|
|
59
35
|
}
|
|
60
|
-
|
|
61
36
|
return deps.sort();
|
|
62
|
-
}
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
63
39
|
//const error = toError(err);
|
|
64
40
|
void err;
|
|
65
41
|
console.warn(`Could not read package.json at ${packageJsonPath}`);
|
|
66
42
|
return [];
|
|
67
43
|
}
|
|
68
44
|
}
|
|
69
|
-
|
|
70
45
|
/**
|
|
71
46
|
* Build map of project names to their package names
|
|
72
47
|
* e.g., "core-util" → "@webpieces/core-util"
|
|
73
48
|
*/
|
|
74
|
-
function buildProjectToPackageMap(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
): Map<string, string> {
|
|
79
|
-
const map = new Map<string, string>();
|
|
80
|
-
|
|
49
|
+
function buildProjectToPackageMap(workspaceRoot,
|
|
50
|
+
// webpieces-disable no-any-unknown -- Nx devkit projectsConfig type is dynamic and not strongly typed
|
|
51
|
+
projectsConfig) {
|
|
52
|
+
const map = new Map();
|
|
81
53
|
// webpieces-disable no-any-unknown -- Nx devkit projects config entries are untyped
|
|
82
|
-
for (const [projectName, config] of Object.entries
|
|
54
|
+
for (const [projectName, config] of Object.entries(projectsConfig.projects)) {
|
|
83
55
|
const packageJsonPath = path.join(workspaceRoot, config.root, 'package.json');
|
|
84
56
|
if (fs.existsSync(packageJsonPath)) {
|
|
85
57
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
@@ -88,86 +60,54 @@ function buildProjectToPackageMap(
|
|
|
88
60
|
if (packageJson.name) {
|
|
89
61
|
map.set(projectName, packageJson.name);
|
|
90
62
|
}
|
|
91
|
-
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
92
65
|
//const error = toError(err);
|
|
93
66
|
void err;
|
|
94
67
|
// Ignore parse errors
|
|
95
68
|
}
|
|
96
69
|
}
|
|
97
70
|
}
|
|
98
|
-
|
|
99
71
|
return map;
|
|
100
72
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
*
|
|
105
|
-
* For each project in the graph:
|
|
106
|
-
* - Check that all graph dependencies exist in package.json
|
|
107
|
-
* - Maps project names to package names for accurate comparison
|
|
108
|
-
*
|
|
109
|
-
* @param graph - Enhanced graph with project dependencies (uses project names)
|
|
110
|
-
* @param workspaceRoot - Absolute path to workspace root
|
|
111
|
-
* @returns Validation result with errors if any
|
|
112
|
-
*/
|
|
113
|
-
interface GraphEntry {
|
|
114
|
-
level: number;
|
|
115
|
-
dependsOn: string[];
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export async function validatePackageJsonDependencies(
|
|
119
|
-
graph: Record<string, GraphEntry>,
|
|
120
|
-
workspaceRoot: string
|
|
121
|
-
): Promise<ValidationResult> {
|
|
122
|
-
const projectGraph = await createProjectGraphAsync();
|
|
123
|
-
const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);
|
|
124
|
-
|
|
73
|
+
async function validatePackageJsonDependencies(graph, workspaceRoot) {
|
|
74
|
+
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
75
|
+
const projectsConfig = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
|
|
125
76
|
// Build map: project name → package name
|
|
126
77
|
const projectToPackage = buildProjectToPackageMap(workspaceRoot, projectsConfig);
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
const projectResults: ProjectValidationResult[] = [];
|
|
130
|
-
|
|
78
|
+
const errors = [];
|
|
79
|
+
const projectResults = [];
|
|
131
80
|
for (const [projectName, entry] of Object.entries(graph)) {
|
|
132
81
|
// Find the project config using project name directly
|
|
133
82
|
const projectConfig = projectsConfig.projects[projectName];
|
|
134
83
|
if (!projectConfig) {
|
|
135
84
|
continue;
|
|
136
85
|
}
|
|
137
|
-
|
|
138
86
|
const projectRoot = projectConfig.root;
|
|
139
87
|
const packageJsonDeps = readPackageJsonDeps(workspaceRoot, projectRoot);
|
|
140
|
-
|
|
141
88
|
if (packageJsonDeps === null) {
|
|
142
89
|
continue;
|
|
143
90
|
}
|
|
144
|
-
|
|
145
91
|
// Convert graph dependencies (project names) to package names for comparison
|
|
146
|
-
const missingInPackageJson
|
|
92
|
+
const missingInPackageJson = [];
|
|
147
93
|
for (const depProjectName of entry.dependsOn) {
|
|
148
94
|
const depPackageName = projectToPackage.get(depProjectName) || depProjectName;
|
|
149
95
|
if (!packageJsonDeps.includes(depPackageName)) {
|
|
150
96
|
missingInPackageJson.push(depProjectName);
|
|
151
97
|
}
|
|
152
98
|
}
|
|
153
|
-
|
|
154
99
|
// Check for extra dependencies in package.json (not critical, just informational)
|
|
155
|
-
const extraInPackageJson
|
|
100
|
+
const extraInPackageJson = [];
|
|
156
101
|
for (const dep of packageJsonDeps) {
|
|
157
102
|
if (!entry.dependsOn.includes(dep)) {
|
|
158
103
|
extraInPackageJson.push(dep);
|
|
159
104
|
}
|
|
160
105
|
}
|
|
161
|
-
|
|
162
106
|
const valid = missingInPackageJson.length === 0;
|
|
163
|
-
|
|
164
107
|
if (!valid) {
|
|
165
|
-
errors.push(
|
|
166
|
-
`
|
|
167
|
-
` Fix: Add these to package.json dependencies`
|
|
168
|
-
);
|
|
108
|
+
errors.push(`Project ${projectName} (${projectRoot}/package.json) is missing dependencies: ${missingInPackageJson.join(', ')}\n` +
|
|
109
|
+
` Fix: Add these to package.json dependencies`);
|
|
169
110
|
}
|
|
170
|
-
|
|
171
111
|
projectResults.push({
|
|
172
112
|
project: projectName,
|
|
173
113
|
valid,
|
|
@@ -175,10 +115,10 @@ export async function validatePackageJsonDependencies(
|
|
|
175
115
|
extraInPackageJson,
|
|
176
116
|
});
|
|
177
117
|
}
|
|
178
|
-
|
|
179
118
|
return {
|
|
180
119
|
valid: errors.length === 0,
|
|
181
120
|
errors,
|
|
182
121
|
projectResults,
|
|
183
122
|
};
|
|
184
123
|
}
|
|
124
|
+
//# sourceMappingURL=package-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-validator.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/package-validator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Package Validator\n *\n * Validates that package.json dependencies match the project.json build.dependsOn\n * This ensures the two sources of truth don't drift apart.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport {\n createProjectGraphAsync,\n readProjectsConfigurationFromProjectGraph,\n} from '@nx/devkit';\nimport { toError } from '../toError';\n\n/**\n * Validation result for a single project\n */\nexport interface ProjectValidationResult {\n project: string;\n valid: boolean;\n missingInPackageJson: string[];\n extraInPackageJson: string[];\n}\n\n/**\n * Overall validation result\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n projectResults: ProjectValidationResult[];\n}\n\n/**\n * Read package.json dependencies for a project\n * Returns null if package.json doesn't exist (apps often don't have one)\n */\nfunction readPackageJsonDeps(workspaceRoot: string, projectRoot: string): string[] | null {\n const packageJsonPath = path.join(workspaceRoot, projectRoot, 'package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n return null; // No package.json - skip validation for this project\n }\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const deps: string[] = [];\n\n // Collect ALL dependencies from package.json\n for (const depType of ['dependencies', 'peerDependencies']) {\n const depObj = packageJson[depType] || {};\n for (const depName of Object.keys(depObj)) {\n if (!deps.includes(depName)) {\n deps.push(depName);\n }\n }\n }\n\n return deps.sort();\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n console.warn(`Could not read package.json at ${packageJsonPath}`);\n return [];\n }\n}\n\n/**\n * Build map of project names to their package names\n * e.g., \"core-util\" → \"@webpieces/core-util\"\n */\nfunction buildProjectToPackageMap(\n workspaceRoot: string,\n // webpieces-disable no-any-unknown -- Nx devkit projectsConfig type is dynamic and not strongly typed\n projectsConfig: any\n): Map<string, string> {\n const map = new Map<string, string>();\n\n // webpieces-disable no-any-unknown -- Nx devkit projects config entries are untyped\n for (const [projectName, config] of Object.entries<any>(projectsConfig.projects)) {\n const packageJsonPath = path.join(workspaceRoot, config.root, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n if (packageJson.name) {\n map.set(projectName, packageJson.name);\n }\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n // Ignore parse errors\n }\n }\n }\n\n return map;\n}\n\n/**\n * Validate that package.json dependencies match the dependency graph\n *\n * For each project in the graph:\n * - Check that all graph dependencies exist in package.json\n * - Maps project names to package names for accurate comparison\n *\n * @param graph - Enhanced graph with project dependencies (uses project names)\n * @param workspaceRoot - Absolute path to workspace root\n * @returns Validation result with errors if any\n */\ninterface GraphEntry {\n level: number;\n dependsOn: string[];\n}\n\nexport async function validatePackageJsonDependencies(\n graph: Record<string, GraphEntry>,\n workspaceRoot: string\n): Promise<ValidationResult> {\n const projectGraph = await createProjectGraphAsync();\n const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);\n\n // Build map: project name → package name\n const projectToPackage = buildProjectToPackageMap(workspaceRoot, projectsConfig);\n\n const errors: string[] = [];\n const projectResults: ProjectValidationResult[] = [];\n\n for (const [projectName, entry] of Object.entries(graph)) {\n // Find the project config using project name directly\n const projectConfig = projectsConfig.projects[projectName];\n if (!projectConfig) {\n continue;\n }\n\n const projectRoot = projectConfig.root;\n const packageJsonDeps = readPackageJsonDeps(workspaceRoot, projectRoot);\n\n if (packageJsonDeps === null) {\n continue;\n }\n\n // Convert graph dependencies (project names) to package names for comparison\n const missingInPackageJson: string[] = [];\n for (const depProjectName of entry.dependsOn) {\n const depPackageName = projectToPackage.get(depProjectName) || depProjectName;\n if (!packageJsonDeps.includes(depPackageName)) {\n missingInPackageJson.push(depProjectName);\n }\n }\n\n // Check for extra dependencies in package.json (not critical, just informational)\n const extraInPackageJson: string[] = [];\n for (const dep of packageJsonDeps) {\n if (!entry.dependsOn.includes(dep)) {\n extraInPackageJson.push(dep);\n }\n }\n\n const valid = missingInPackageJson.length === 0;\n\n if (!valid) {\n errors.push(\n `Project ${projectName} (${projectRoot}/package.json) is missing dependencies: ${missingInPackageJson.join(', ')}\\n` +\n ` Fix: Add these to package.json dependencies`\n );\n }\n\n projectResults.push({\n project: projectName,\n valid,\n missingInPackageJson,\n extraInPackageJson,\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n projectResults,\n };\n}\n"]}
|
package/src/plugin.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Nx Inference Plugin for @webpieces/nx-webpieces-rules
|
|
3
|
+
*
|
|
4
|
+
* This plugin automatically creates targets for:
|
|
5
|
+
* 1. Workspace-level architecture validation (generate, visualize, validate-*)
|
|
6
|
+
* 2. Per-project circular dependency checking
|
|
7
|
+
*
|
|
8
|
+
* Install with: nx add @webpieces/nx-webpieces-rules
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* Add to nx.json plugins array:
|
|
12
|
+
* {
|
|
13
|
+
* "plugins": ["@webpieces/nx-webpieces-rules"]
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* Then all targets appear automatically without manual project.json configuration.
|
|
17
|
+
*/
|
|
18
|
+
import type { CreateNodesV2 } from '@nx/devkit';
|
|
19
|
+
/**
|
|
20
|
+
* Circular dependency checking options
|
|
21
|
+
*/
|
|
22
|
+
export interface CircularDepsOptions {
|
|
23
|
+
enabled?: boolean;
|
|
24
|
+
targetName?: string;
|
|
25
|
+
excludePatterns?: string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validation options for architecture checks
|
|
29
|
+
*/
|
|
30
|
+
export interface ValidationOptions {
|
|
31
|
+
noCycles?: boolean;
|
|
32
|
+
noSkipLevelDeps?: boolean;
|
|
33
|
+
architectureUnchanged?: boolean;
|
|
34
|
+
validatePackageJson?: boolean;
|
|
35
|
+
validateNewMethods?: boolean;
|
|
36
|
+
validateModifiedMethods?: boolean;
|
|
37
|
+
validateModifiedFiles?: boolean;
|
|
38
|
+
validateVersionsLocked?: boolean;
|
|
39
|
+
validateTsInSrc?: boolean;
|
|
40
|
+
newMethodsMaxLines?: number;
|
|
41
|
+
modifiedAndNewMethodsMaxLines?: number;
|
|
42
|
+
modifiedFilesMaxLines?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Validation mode for method/file size limits:
|
|
45
|
+
* - STRICT: All limits enforced, disable comments ignored
|
|
46
|
+
* - NORMAL: Limits enforced, disable comments with dates work
|
|
47
|
+
* - OFF: Skip size validations entirely (for fast iteration)
|
|
48
|
+
*/
|
|
49
|
+
validationMode?: 'STRICT' | 'NORMAL' | 'OFF';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Feature flags for workspace targets
|
|
53
|
+
*/
|
|
54
|
+
export interface FeatureOptions {
|
|
55
|
+
generate?: boolean;
|
|
56
|
+
visualize?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Workspace-level configuration options
|
|
60
|
+
*/
|
|
61
|
+
export interface WorkspaceOptions {
|
|
62
|
+
enabled?: boolean;
|
|
63
|
+
targetPrefix?: string;
|
|
64
|
+
graphPath?: string;
|
|
65
|
+
validations?: ValidationOptions;
|
|
66
|
+
features?: FeatureOptions;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Configuration for @webpieces/nx-webpieces-rules Nx plugin
|
|
70
|
+
*/
|
|
71
|
+
export interface ArchitecturePluginOptions {
|
|
72
|
+
circularDeps?: CircularDepsOptions;
|
|
73
|
+
workspace?: WorkspaceOptions;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Nx V2 Inference Plugin
|
|
77
|
+
* Matches project.json and package.json files to create targets
|
|
78
|
+
*/
|
|
79
|
+
export declare const createNodesV2: CreateNodesV2<ArchitecturePluginOptions>;
|
|
80
|
+
/**
|
|
81
|
+
* Export plugin as default for Nx
|
|
82
|
+
*/
|
|
83
|
+
declare const _default: {
|
|
84
|
+
createNodesV2: CreateNodesV2<ArchitecturePluginOptions>;
|
|
85
|
+
};
|
|
86
|
+
export default _default;
|