@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/nx-webpieces-rules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.113",
|
|
4
4
|
"description": "Nx-specific webpieces validation rules. Includes all rules from @webpieces/webpieces-rules plus Nx graph validators and inference plugin.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@webpieces/webpieces-rules": "0.
|
|
21
|
-
"@webpieces/code-rules": "0.
|
|
20
|
+
"@webpieces/webpieces-rules": "0.2.113",
|
|
21
|
+
"@webpieces/code-rules": "0.2.113"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"@nx/devkit": ">=18.0.0"
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|
|
35
|
-
}
|
|
35
|
+
},
|
|
36
|
+
"types": "./src/index.d.ts"
|
|
36
37
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExecutorResult = void 0;
|
|
4
|
+
class ExecutorResult {
|
|
5
|
+
constructor(success) {
|
|
6
|
+
this.success = success;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.ExecutorResult = ExecutorResult;
|
|
10
|
+
//# sourceMappingURL=executor-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor-result.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/executor-result.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAc;IAGvB,YAAY,OAAgB;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CACJ;AAND,wCAMC","sourcesContent":["export class ExecutorResult {\n success: boolean;\n\n constructor(success: boolean) {\n this.success = success;\n }\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Executor
|
|
3
|
+
*
|
|
4
|
+
* Generates the architecture dependency graph and saves it to architecture/dependencies.json.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* nx run architecture:generate
|
|
8
|
+
*/
|
|
9
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
10
|
+
export interface GenerateExecutorOptions {
|
|
11
|
+
graphPath?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ExecutorResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
}
|
|
16
|
+
export default function runExecutor(options: GenerateExecutorOptions, context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Generate Executor
|
|
3
4
|
*
|
|
@@ -6,56 +7,40 @@
|
|
|
6
7
|
* Usage:
|
|
7
8
|
* nx run architecture:generate
|
|
8
9
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export interface GenerateExecutorOptions {
|
|
17
|
-
graphPath?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ExecutorResult {
|
|
21
|
-
success: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default async function runExecutor(
|
|
25
|
-
options: GenerateExecutorOptions,
|
|
26
|
-
context: ExecutorContext
|
|
27
|
-
): Promise<ExecutorResult> {
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.default = runExecutor;
|
|
12
|
+
const graph_generator_1 = require("../../lib/graph-generator");
|
|
13
|
+
const graph_sorter_1 = require("../../lib/graph-sorter");
|
|
14
|
+
const graph_loader_1 = require("../../lib/graph-loader");
|
|
15
|
+
const toError_1 = require("../../toError");
|
|
16
|
+
async function runExecutor(options, context) {
|
|
28
17
|
const graphPath = options.graphPath;
|
|
29
18
|
const workspaceRoot = context.root;
|
|
30
|
-
|
|
31
19
|
console.log('\n📊 Architecture Graph Generator\n');
|
|
32
|
-
|
|
33
20
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
34
21
|
try {
|
|
35
22
|
// Step 1: Generate current graph from project.json files
|
|
36
23
|
console.log('📊 Generating dependency graph from project.json files...');
|
|
37
|
-
const rawGraph = await generateGraph();
|
|
38
|
-
|
|
24
|
+
const rawGraph = await (0, graph_generator_1.generateGraph)();
|
|
39
25
|
// Step 2: Topological sort (to assign levels for visualization)
|
|
40
26
|
console.log('🔄 Computing topological layers...');
|
|
41
|
-
const enhancedGraph = sortGraphTopologically(rawGraph);
|
|
42
|
-
|
|
27
|
+
const enhancedGraph = (0, graph_sorter_1.sortGraphTopologically)(rawGraph);
|
|
43
28
|
// Step 3: Save the graph
|
|
44
29
|
console.log('💾 Saving graph to architecture/dependencies.json...');
|
|
45
|
-
saveGraph(enhancedGraph, workspaceRoot, graphPath);
|
|
30
|
+
(0, graph_loader_1.saveGraph)(enhancedGraph, workspaceRoot, graphPath);
|
|
46
31
|
console.log('✅ Graph saved successfully');
|
|
47
|
-
|
|
48
32
|
// Print summary
|
|
49
33
|
const projectCount = Object.keys(enhancedGraph).length;
|
|
50
34
|
const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));
|
|
51
35
|
console.log(`\n📈 Graph Summary:`);
|
|
52
36
|
console.log(` Projects: ${projectCount}`);
|
|
53
37
|
console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);
|
|
54
|
-
|
|
55
38
|
return { success: true };
|
|
56
|
-
}
|
|
57
|
-
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const error = (0, toError_1.toError)(err);
|
|
58
42
|
console.error('❌ Graph generation failed:', error.message);
|
|
59
43
|
return { success: false };
|
|
60
44
|
}
|
|
61
45
|
}
|
|
46
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/generate/executor.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAgBH,8BAqCC;AAlDD,+DAA0D;AAC1D,yDAAgE;AAChE,yDAAmD;AACnD,2CAAwC;AAUzB,KAAK,UAAU,WAAW,CACrC,OAAgC,EAChC,OAAwB;IAExB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,8DAA8D;IAC9D,IAAI,CAAC;QACD,yDAAyD;QACzD,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAA,+BAAa,GAAE,CAAC;QAEvC,gEAAgE;QAChE,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,MAAM,aAAa,GAAG,IAAA,qCAAsB,EAAC,QAAQ,CAAC,CAAC;QAEvD,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,IAAA,wBAAS,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAE1C,gBAAgB;QAChB,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,gBAAgB,YAAY,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAEpE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAA,iBAAO,EAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;AACL,CAAC","sourcesContent":["/**\n * Generate Executor\n *\n * Generates the architecture dependency graph and saves it to architecture/dependencies.json.\n *\n * Usage:\n * nx run architecture:generate\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { generateGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { saveGraph } from '../../lib/graph-loader';\nimport { toError } from '../../toError';\n\nexport interface GenerateExecutorOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nexport default async function runExecutor(\n options: GenerateExecutorOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const graphPath = options.graphPath;\n const workspaceRoot = context.root;\n\n console.log('\\n📊 Architecture Graph Generator\\n');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Step 1: Generate current graph from project.json files\n console.log('📊 Generating dependency graph from project.json files...');\n const rawGraph = await generateGraph();\n\n // Step 2: Topological sort (to assign levels for visualization)\n console.log('🔄 Computing topological layers...');\n const enhancedGraph = sortGraphTopologically(rawGraph);\n\n // Step 3: Save the graph\n console.log('💾 Saving graph to architecture/dependencies.json...');\n saveGraph(enhancedGraph, workspaceRoot, graphPath);\n console.log('✅ Graph saved successfully');\n\n // Print summary\n const projectCount = Object.keys(enhancedGraph).length;\n const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));\n console.log(`\\n📈 Graph Summary:`);\n console.log(` Projects: ${projectCount}`);\n console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);\n\n return { success: true };\n } catch (err: unknown) {\n const error = toError(err);\n console.error('❌ Graph generation failed:', error.message);\n return { success: false };\n }\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
2
|
+
export interface HelpExecutorOptions {
|
|
3
|
+
}
|
|
4
|
+
type HelpExecutorResult = {
|
|
5
|
+
success: true;
|
|
6
|
+
};
|
|
7
|
+
export default function helpExecutor(options: HelpExecutorOptions, context: ExecutorContext): Promise<HelpExecutorResult>;
|
|
8
|
+
export {};
|
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type HelpExecutorResult = { success: true };
|
|
6
|
-
|
|
7
|
-
export default async function helpExecutor(
|
|
8
|
-
options: HelpExecutorOptions,
|
|
9
|
-
context: ExecutorContext
|
|
10
|
-
): Promise<HelpExecutorResult> {
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = helpExecutor;
|
|
4
|
+
async function helpExecutor(options, context) {
|
|
11
5
|
// ANSI color codes
|
|
12
6
|
const GREEN = '\x1b[32m\x1b[1m';
|
|
13
7
|
const BOLD = '\x1b[1m';
|
|
14
8
|
const RESET = '\x1b[0m';
|
|
15
|
-
|
|
16
9
|
console.log('');
|
|
17
10
|
console.log(`${GREEN}💡 @webpieces/nx-webpieces-rules - Available Commands${RESET}`);
|
|
18
11
|
console.log('');
|
|
@@ -58,6 +51,6 @@ export default async function helpExecutor(
|
|
|
58
51
|
console.log(` ${BOLD}npm run arch:generate${RESET} # Generate the graph first`);
|
|
59
52
|
console.log(` ${BOLD}npm run arch:validate-complete${RESET} # Run complete validation`);
|
|
60
53
|
console.log('');
|
|
61
|
-
|
|
62
54
|
return { success: true };
|
|
63
55
|
}
|
|
56
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/help/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\n\nexport interface HelpExecutorOptions {}\n\ntype HelpExecutorResult = { success: true };\n\nexport default async function helpExecutor(\n options: HelpExecutorOptions,\n context: ExecutorContext\n): Promise<HelpExecutorResult> {\n // ANSI color codes\n const GREEN = '\\x1b[32m\\x1b[1m';\n const BOLD = '\\x1b[1m';\n const RESET = '\\x1b[0m';\n\n console.log('');\n console.log(`${GREEN}💡 @webpieces/nx-webpieces-rules - Available Commands${RESET}`);\n console.log('');\n console.log(`${BOLD}📝 Available npm scripts (convenient shortcuts):${RESET}`);\n console.log('');\n console.log(' Architecture graph:');\n console.log(' npm run arch:generate # Generate dependency graph');\n console.log(' npm run arch:visualize # Visualize dependency graph');\n console.log('');\n console.log(' Validation:');\n console.log(' npm run arch:validate # Quick validation (no-cycles + no-skiplevel-deps)');\n console.log(' npm run arch:validate-all # Full arch validation (+ unchanged check)');\n console.log(' npm run arch:check-circular # Check all projects for circular deps');\n console.log(' npm run arch:check-circular-affected # Check affected projects only');\n console.log(' npm run arch:validate-complete # Complete validation (arch + circular)');\n console.log('');\n console.log(`${BOLD}📝 Available Nx targets:${RESET}`);\n console.log('');\n console.log(' Workspace-level architecture validation:');\n console.log(' nx run architecture:generate # Generate dependency graph');\n console.log(' nx run architecture:visualize # Visualize dependency graph');\n console.log(' nx run architecture:validate-no-architecture-cycles # Check for circular project dependencies');\n console.log(' nx run architecture:validate-no-skiplevel-deps # Check for redundant dependencies');\n console.log(' nx run architecture:validate-architecture-unchanged # Validate against blessed graph');\n console.log('');\n console.log(' Per-project file import cycle checking:');\n console.log(' nx run <project>:validate-no-file-import-cycles # Check project for file import cycles');\n console.log(' nx affected --target=validate-no-file-import-cycles # Check all affected projects');\n console.log(' nx run-many --target=validate-no-file-import-cycles --all # Check all projects');\n console.log('');\n console.log(' Per-project CI target (lint + build + test):');\n console.log(' nx run <project>:ci # Run lint, build, test together');\n console.log(' nx run-many --target=ci --all # Run ci for all projects');\n console.log('');\n console.log(' Execution order (test waits for build via targetDefaults):');\n console.log(' ci (nx:noop)');\n console.log(' ├── lint ─────────────────┐');\n console.log(' ├── build ────────────────┼── run in parallel');\n console.log(' └── test ─────────────────┘');\n console.log(' └── depends on build (waits)');\n console.log('');\n console.log(`${GREEN}💡 Quick start:${RESET}`);\n console.log(` ${BOLD}npm run arch:generate${RESET} # Generate the graph first`);\n console.log(` ${BOLD}npm run arch:validate-complete${RESET} # Run complete validation`);\n console.log('');\n\n return { success: true };\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Architecture Unchanged Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that the current architecture graph matches the saved blessed graph.
|
|
5
|
+
* This ensures no unapproved architecture changes have been made.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:validate-architecture-unchanged
|
|
9
|
+
*/
|
|
10
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
11
|
+
export interface ValidateArchitectureUnchangedOptions {
|
|
12
|
+
graphPath?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ExecutorResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
}
|
|
17
|
+
export default function runExecutor(options: ValidateArchitectureUnchangedOptions, context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Validate Architecture Unchanged Executor
|
|
3
4
|
*
|
|
@@ -7,27 +8,18 @@
|
|
|
7
8
|
* Usage:
|
|
8
9
|
* nx run architecture:validate-architecture-unchanged
|
|
9
10
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export interface ValidateArchitectureUnchangedOptions {
|
|
21
|
-
graphPath?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ExecutorResult {
|
|
25
|
-
success: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.default = runExecutor;
|
|
13
|
+
const tslib_1 = require("tslib");
|
|
14
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
15
|
+
const path = tslib_1.__importStar(require("path"));
|
|
16
|
+
const graph_generator_1 = require("../../lib/graph-generator");
|
|
17
|
+
const graph_sorter_1 = require("../../lib/graph-sorter");
|
|
18
|
+
const graph_comparator_1 = require("../../lib/graph-comparator");
|
|
19
|
+
const graph_loader_1 = require("../../lib/graph-loader");
|
|
20
|
+
const toError_1 = require("../../toError");
|
|
28
21
|
const TMP_DIR = '.webpieces/instruct-ai';
|
|
29
22
|
const TMP_MD_FILE = 'webpieces.dependencies.md';
|
|
30
|
-
|
|
31
23
|
const DEPENDENCIES_DOC_CONTENT = `# Instructions: Architecture Dependency Violation
|
|
32
24
|
|
|
33
25
|
IN GENERAL, it is better to avoid these changes and find a different way by moving classes
|
|
@@ -165,36 +157,26 @@ Instead of importing, receive the dependency as a constructor or method paramete
|
|
|
165
157
|
- The best dependency is the one you don't need
|
|
166
158
|
- When in doubt, refactor rather than add dependencies
|
|
167
159
|
`;
|
|
168
|
-
|
|
169
160
|
/**
|
|
170
161
|
* Write the instructions documentation to tmp directory
|
|
171
162
|
*/
|
|
172
|
-
function writeTmpInstructionsFile(workspaceRoot
|
|
163
|
+
function writeTmpInstructionsFile(workspaceRoot) {
|
|
173
164
|
const tmpDir = path.join(workspaceRoot, TMP_DIR);
|
|
174
165
|
const mdPath = path.join(tmpDir, TMP_MD_FILE);
|
|
175
|
-
|
|
176
166
|
// Ensure tmp directory exists
|
|
177
167
|
fs.mkdirSync(tmpDir, { recursive: true });
|
|
178
|
-
|
|
179
168
|
// Write documentation MD file
|
|
180
169
|
fs.writeFileSync(mdPath, DEPENDENCIES_DOC_CONTENT);
|
|
181
|
-
|
|
182
170
|
return mdPath;
|
|
183
171
|
}
|
|
184
|
-
|
|
185
|
-
export default async function runExecutor(
|
|
186
|
-
options: ValidateArchitectureUnchangedOptions,
|
|
187
|
-
context: ExecutorContext
|
|
188
|
-
): Promise<ExecutorResult> {
|
|
172
|
+
async function runExecutor(options, context) {
|
|
189
173
|
const graphPath = options.graphPath;
|
|
190
174
|
const workspaceRoot = context.root;
|
|
191
|
-
|
|
192
175
|
console.log('\n🔍 Validating Architecture Unchanged\n');
|
|
193
|
-
|
|
194
176
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
195
177
|
try {
|
|
196
178
|
// Check if saved graph exists
|
|
197
|
-
if (!graphFileExists(workspaceRoot, graphPath)) {
|
|
179
|
+
if (!(0, graph_loader_1.graphFileExists)(workspaceRoot, graphPath)) {
|
|
198
180
|
console.error('❌ No saved graph found at architecture/dependencies.json');
|
|
199
181
|
console.error('');
|
|
200
182
|
console.error('To initialize:');
|
|
@@ -204,35 +186,29 @@ export default async function runExecutor(
|
|
|
204
186
|
console.error(' 4. Commit architecture/dependencies.json');
|
|
205
187
|
return { success: false };
|
|
206
188
|
}
|
|
207
|
-
|
|
208
189
|
// Step 1: Generate current graph from project.json files
|
|
209
190
|
console.log('📊 Generating current dependency graph...');
|
|
210
|
-
const rawGraph = await generateGraph();
|
|
211
|
-
|
|
191
|
+
const rawGraph = await (0, graph_generator_1.generateGraph)();
|
|
212
192
|
// Step 2: Topological sort (to get enhanced graph with levels)
|
|
213
193
|
console.log('🔄 Computing topological layers...');
|
|
214
|
-
const currentGraph = sortGraphTopologically(rawGraph);
|
|
215
|
-
|
|
194
|
+
const currentGraph = (0, graph_sorter_1.sortGraphTopologically)(rawGraph);
|
|
216
195
|
// Step 3: Load saved graph
|
|
217
196
|
console.log('📂 Loading saved graph...');
|
|
218
|
-
const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);
|
|
219
|
-
|
|
197
|
+
const savedGraph = (0, graph_loader_1.loadBlessedGraph)(workspaceRoot, graphPath);
|
|
220
198
|
if (!savedGraph) {
|
|
221
199
|
console.error('❌ Could not load saved graph');
|
|
222
200
|
return { success: false };
|
|
223
201
|
}
|
|
224
|
-
|
|
225
202
|
// Step 4: Compare graphs
|
|
226
203
|
console.log('🔍 Comparing current graph to saved graph...');
|
|
227
|
-
const comparison = compareGraphs(currentGraph, savedGraph);
|
|
228
|
-
|
|
204
|
+
const comparison = (0, graph_comparator_1.compareGraphs)(currentGraph, savedGraph);
|
|
229
205
|
if (comparison.identical) {
|
|
230
206
|
console.log('✅ Architecture unchanged - current graph matches saved graph');
|
|
231
207
|
return { success: true };
|
|
232
|
-
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
233
210
|
// Write instructions file for AI agent
|
|
234
211
|
const mdPath = writeTmpInstructionsFile(workspaceRoot);
|
|
235
|
-
|
|
236
212
|
console.error('❌ Architecture has changed since last update!');
|
|
237
213
|
console.error('\nDifferences:');
|
|
238
214
|
console.error(comparison.summary);
|
|
@@ -245,9 +221,11 @@ export default async function runExecutor(
|
|
|
245
221
|
console.error(' 3. Commit the updated architecture/dependencies.json');
|
|
246
222
|
return { success: false };
|
|
247
223
|
}
|
|
248
|
-
}
|
|
249
|
-
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
const error = (0, toError_1.toError)(err);
|
|
250
227
|
console.error('❌ Architecture validation failed:', error.message);
|
|
251
228
|
return { success: false };
|
|
252
229
|
}
|
|
253
230
|
}
|
|
231
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Architecture Unchanged Executor\n *\n * Validates that the current architecture graph matches the saved blessed graph.\n * This ensures no unapproved architecture changes have been made.\n *\n * Usage:\n * nx run architecture:validate-architecture-unchanged\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { generateGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { compareGraphs } from '../../lib/graph-comparator';\nimport { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';\nimport { toError } from '../../toError';\n\nexport interface ValidateArchitectureUnchangedOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nconst TMP_DIR = '.webpieces/instruct-ai';\nconst TMP_MD_FILE = 'webpieces.dependencies.md';\n\nconst DEPENDENCIES_DOC_CONTENT = `# Instructions: Architecture Dependency Violation\n\nIN GENERAL, it is better to avoid these changes and find a different way by moving classes\naround to existing packages you already depend on. It is not always avoidable though.\nA clean dependency graph keeps you out of huge trouble later.\n\nIf you are a human, simply run these commands:\n* nx run architecture:visualize - to see the new dependencies and validate that change is desired\n* nx run architecture:generate - updates the dep graph\n* git diff architecture/dependencies.json - to see the deps changes you made\n\n**READ THIS FILE FIRST before making any changes!**\n\n## ⚠️ CRITICAL WARNING ⚠️\n\n**This is a VERY IMPORTANT change that has LARGE REPERCUSSIONS later!**\n\nAdding new dependencies creates technical debt that compounds over time:\n- Creates coupling between packages that may be hard to undo\n- Can create circular dependency tangles\n- Makes packages harder to test in isolation\n- Increases build times and bundle sizes\n- May force unnecessary upgrades across the codebase\n\n**DO NOT add dependencies without senior developer approval!**\n\n## Understanding the Error\n\nYou've attempted to import from a package that is not in your project's allowed dependencies.\nThe architecture enforces a layered dependency structure where:\n- Level 0 packages are foundation packages with NO dependencies on other @webpieces packages\n- Higher level packages can only depend on lower level packages\n- All dependencies must be explicitly declared\n\n## Steps to Resolve\n\n### Step 1: Generate Current Dependency Graph\nRun this command to see the current architecture:\n\\`\\`\\`bash\nnpx nx run architecture:generate\n\\`\\`\\`\nThis creates/updates \\`architecture/dependencies.json\\` showing all packages and their levels.\n\n### Step 2: Analyze the Proposed Change\nAsk yourself:\n1. **Is this import truly necessary?** Can you refactor to avoid it?\n2. **Should the code move instead?** Maybe the code belongs in a different package.\n3. **Will this create a cycle?** Use \\`npx nx graph\\` to visualize dependencies.\n4. **Can you use an interface/abstraction?** Define interface in lower-level package, implement in higher-level.\n\n### Step 3: Get Senior Developer Approval\n\n## 🛑 AI AGENTS: STOP HERE AND ASK FOR HUMAN APPROVAL! 🛑\n\n**YOU MUST NOT PROCEED TO STEP 4 WITHOUT EXPLICIT HUMAN APPROVAL!**\n\n**REQUIRED**: Discuss this architectural change with a senior developer before proceeding.\n- Explain why the dependency is needed\n- Show you've considered alternatives (Step 2)\n- **WAIT for explicit approval before making ANY changes to project.json or package.json**\n\n**AI Agent Instructions:**\n1. Present your analysis from Step 2 to the human\n2. Explain which package needs which dependency and why\n3. ASK: \"Do you approve adding this dependency?\"\n4. **DO NOT modify project.json or package.json until you receive explicit \"yes\" or approval**\n\n### Step 4: If Approved, Add the Dependency\n\n## ⛔ NEVER MODIFY THESE FILES WITHOUT HUMAN APPROVAL FROM STEP 3! ⛔\n\nOnly after receiving explicit human approval in Step 3, make these changes:\n\n1. **Update project.json** - Add to \\`build.dependsOn\\`:\n \\`\\`\\`json\n {\n \"targets\": {\n \"build\": {\n \"dependsOn\": [\"^build\", \"dep1:build\", \"NEW_PACKAGE:build\"]\n }\n }\n }\n \\`\\`\\`\n\n2. **Update package.json** - Add to \\`dependencies\\`:\n \\`\\`\\`json\n {\n \"dependencies\": {\n \"@webpieces/NEW_PACKAGE\": \"*\"\n }\n }\n \\`\\`\\`\n\n### Step 5: Update Architecture Definition\nRun this command to validate and update the architecture:\n\\`\\`\\`bash\nnpx nx run architecture:generate\n\\`\\`\\`\n\nThis will:\n- Detect any cycles (which MUST be fixed before proceeding)\n- Update \\`architecture/dependencies.json\\` with the new dependency\n- Recalculate package levels\n\n### Step 6: Verify No Cycles\n\\`\\`\\`bash\nnpx nx run architecture:validate-no-architecture-cycles\n\\`\\`\\`\n\nIf cycles are detected, you MUST refactor to break the cycle. Common strategies:\n- Move shared code to a lower-level package\n- Use dependency inversion (interfaces in low-level, implementations in high-level)\n- Restructure package boundaries\n\n## Alternative Solutions (Preferred over adding dependencies)\n\n### Option A: Move the Code\nIf you need functionality from another package, consider moving that code to a shared lower-level package.\n\n### Option B: Dependency Inversion\nDefine an interface in the lower-level package, implement it in the higher-level package:\n\\`\\`\\`typescript\n// In foundation package (level 0)\nexport interface Logger { log(msg: string): void; }\n\n// In higher-level package\nexport class ConsoleLogger implements Logger { ... }\n\\`\\`\\`\n\n### Option C: Pass Dependencies as Parameters\nInstead of importing, receive the dependency as a constructor or method parameter.\n\n## Remember\n- Every dependency you add today is technical debt for tomorrow\n- The best dependency is the one you don't need\n- When in doubt, refactor rather than add dependencies\n`;\n\n/**\n * Write the instructions documentation to tmp directory\n */\nfunction writeTmpInstructionsFile(workspaceRoot: string): string {\n const tmpDir = path.join(workspaceRoot, TMP_DIR);\n const mdPath = path.join(tmpDir, TMP_MD_FILE);\n\n // Ensure tmp directory exists\n fs.mkdirSync(tmpDir, { recursive: true });\n\n // Write documentation MD file\n fs.writeFileSync(mdPath, DEPENDENCIES_DOC_CONTENT);\n\n return mdPath;\n}\n\nexport default async function runExecutor(\n options: ValidateArchitectureUnchangedOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const graphPath = options.graphPath;\n const workspaceRoot = context.root;\n\n console.log('\\n🔍 Validating Architecture Unchanged\\n');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check if saved graph exists\n if (!graphFileExists(workspaceRoot, graphPath)) {\n console.error('❌ No saved graph found at architecture/dependencies.json');\n console.error('');\n console.error('To initialize:');\n console.error(' 1. Run: nx run architecture:generate');\n console.error(' 2. Run: nx run architecture:visualize');\n console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');\n console.error(' 4. Commit architecture/dependencies.json');\n return { success: false };\n }\n\n // Step 1: Generate current graph from project.json files\n console.log('📊 Generating current dependency graph...');\n const rawGraph = await generateGraph();\n\n // Step 2: Topological sort (to get enhanced graph with levels)\n console.log('🔄 Computing topological layers...');\n const currentGraph = sortGraphTopologically(rawGraph);\n\n // Step 3: Load saved graph\n console.log('📂 Loading saved graph...');\n const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!savedGraph) {\n console.error('❌ Could not load saved graph');\n return { success: false };\n }\n\n // Step 4: Compare graphs\n console.log('🔍 Comparing current graph to saved graph...');\n const comparison = compareGraphs(currentGraph, savedGraph);\n\n if (comparison.identical) {\n console.log('✅ Architecture unchanged - current graph matches saved graph');\n return { success: true };\n } else {\n // Write instructions file for AI agent\n const mdPath = writeTmpInstructionsFile(workspaceRoot);\n\n console.error('❌ Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(comparison.summary);\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');\n console.error(' 3. Commit the updated architecture/dependencies.json');\n return { success: false };\n }\n } catch (err: unknown) {\n const error = toError(err);\n console.error('❌ Architecture validation failed:', error.message);\n return { success: false };\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runExecutor;
|
|
4
|
+
const code_rules_1 = require("@webpieces/code-rules");
|
|
5
|
+
async function runExecutor(
|
|
6
|
+
// webpieces-disable no-any-unknown -- options are passed through to code-rules validators
|
|
7
|
+
options, context) {
|
|
8
|
+
return (0, code_rules_1.validateCatchErrorPattern)(options, context.root);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-catch-error-pattern/executor.ts"],"names":[],"mappings":";;AAIA,8BAMC;AARD,sDAAkE;AAEnD,KAAK,UAAU,WAAW;AACrC,0FAA0F;AAC1F,OAAgC,EAChC,OAAwB;IAExB,OAAO,IAAA,sCAAyB,EAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validateCatchErrorPattern } from '@webpieces/code-rules';\n\nexport default async function runExecutor(\n // webpieces-disable no-any-unknown -- options are passed through to code-rules validators\n options: Record<string, unknown>,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n return validateCatchErrorPattern(options, context.root);\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runExecutor;
|
|
4
|
+
const code_rules_1 = require("@webpieces/code-rules");
|
|
5
|
+
async function runExecutor(
|
|
6
|
+
// webpieces-disable no-any-unknown -- options are passed through to code-rules validators
|
|
7
|
+
options, context) {
|
|
8
|
+
return (0, code_rules_1.validateCode)(options, context.root);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-code/executor.ts"],"names":[],"mappings":";;AAIA,8BAMC;AARD,sDAAqD;AAEtC,KAAK,UAAU,WAAW;AACrC,0FAA0F;AAC1F,OAAgC,EAChC,OAAwB;IAExB,OAAO,IAAA,yBAAY,EAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validateCode } from '@webpieces/code-rules';\n\nexport default async function runExecutor(\n // webpieces-disable no-any-unknown -- options are passed through to code-rules validators\n options: Record<string, unknown>,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n return validateCode(options, context.root);\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runExecutor;
|
|
4
|
+
const code_rules_1 = require("@webpieces/code-rules");
|
|
5
|
+
async function runExecutor(
|
|
6
|
+
// webpieces-disable no-any-unknown -- options are passed through to code-rules validators
|
|
7
|
+
options, context) {
|
|
8
|
+
return (0, code_rules_1.validateDtos)(options, context.root);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-dtos/executor.ts"],"names":[],"mappings":";;AAIA,8BAMC;AARD,sDAAqD;AAEtC,KAAK,UAAU,WAAW;AACrC,0FAA0F;AAC1F,OAAgC,EAChC,OAAwB;IAExB,OAAO,IAAA,yBAAY,EAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validateDtos } from '@webpieces/code-rules';\n\nexport default async function runExecutor(\n // webpieces-disable no-any-unknown -- options are passed through to code-rules validators\n options: Record<string, unknown>,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n return validateDtos(options, context.root);\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
2
|
+
export interface ValidateEslintSyncOptions {
|
|
3
|
+
}
|
|
4
|
+
export interface ExecutorResult {
|
|
5
|
+
success: boolean;
|
|
6
|
+
}
|
|
7
|
+
export default function validateEslintSyncExecutor(options: ValidateEslintSyncOptions, context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -1,60 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
success: boolean;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = validateEslintSyncExecutor;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
function calculateHash(content) {
|
|
8
|
+
return (0, crypto_1.createHash)('sha256').update(content).digest('hex');
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
function calculateHash(content: string): string {
|
|
13
|
-
return createHash('sha256').update(content).digest('hex');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function normalizeContent(content: string): string {
|
|
10
|
+
function normalizeContent(content) {
|
|
17
11
|
// Normalize line endings and trim whitespace
|
|
18
12
|
return content.replace(/\r\n/g, '\n').trim();
|
|
19
13
|
}
|
|
20
|
-
|
|
21
|
-
export default async function validateEslintSyncExecutor(
|
|
22
|
-
options: ValidateEslintSyncOptions,
|
|
23
|
-
context: ExecutorContext
|
|
24
|
-
): Promise<ExecutorResult> {
|
|
14
|
+
async function validateEslintSyncExecutor(options, context) {
|
|
25
15
|
const workspaceRoot = context.root;
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const workspacePath = join(workspaceRoot, 'eslint.webpieces.config.mjs');
|
|
29
|
-
|
|
16
|
+
const templatePath = (0, path_1.join)(workspaceRoot, 'packages/tooling/nx-webpieces-rules/templates/eslint.webpieces.config.mjs');
|
|
17
|
+
const workspacePath = (0, path_1.join)(workspaceRoot, 'eslint.webpieces.config.mjs');
|
|
30
18
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
31
19
|
try {
|
|
32
|
-
const templateContent = readFileSync(templatePath, 'utf-8');
|
|
33
|
-
const workspaceContent = readFileSync(workspacePath, 'utf-8');
|
|
34
|
-
|
|
20
|
+
const templateContent = (0, fs_1.readFileSync)(templatePath, 'utf-8');
|
|
21
|
+
const workspaceContent = (0, fs_1.readFileSync)(workspacePath, 'utf-8');
|
|
35
22
|
const templateRules = extractRulesSection(templateContent);
|
|
36
23
|
const workspaceRules = extractRulesSection(workspaceContent);
|
|
37
|
-
|
|
38
24
|
const templateHash = calculateHash(normalizeContent(templateRules));
|
|
39
25
|
const workspaceHash = calculateHash(normalizeContent(workspaceRules));
|
|
40
|
-
|
|
41
26
|
if (templateHash !== workspaceHash) {
|
|
42
27
|
printValidationError(templatePath, workspacePath);
|
|
43
28
|
return { success: false };
|
|
44
29
|
}
|
|
45
|
-
|
|
46
30
|
console.log('✅ ESLint configuration sync validated - rules match!');
|
|
47
31
|
return { success: true };
|
|
48
|
-
|
|
49
|
-
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
50
34
|
// Error occurred during validation - log and fail
|
|
51
35
|
// eslint-disable-next-line @webpieces/catch-error-pattern
|
|
52
36
|
console.error('❌ Error validating ESLint sync:', err);
|
|
53
37
|
return { success: false };
|
|
54
38
|
}
|
|
55
39
|
}
|
|
56
|
-
|
|
57
|
-
function printValidationError(templatePath: string, workspacePath: string): void {
|
|
40
|
+
function printValidationError(templatePath, workspacePath) {
|
|
58
41
|
console.error('');
|
|
59
42
|
console.error('❌ ESLint configuration sync validation FAILED');
|
|
60
43
|
console.error('');
|
|
@@ -74,14 +57,13 @@ function printValidationError(templatePath: string, workspacePath: string): void
|
|
|
74
57
|
console.error('Customization for webpieces workspace goes in: eslint.config.mjs');
|
|
75
58
|
console.error('');
|
|
76
59
|
}
|
|
77
|
-
|
|
78
|
-
function extractRulesSection(content: string): string {
|
|
60
|
+
function extractRulesSection(content) {
|
|
79
61
|
// Extract everything between "export default [" and the final "];"
|
|
80
62
|
// This includes the rules configuration
|
|
81
63
|
const match = content.match(/export default \[([\s\S]*)\];/);
|
|
82
64
|
if (!match) {
|
|
83
65
|
throw new Error('Could not extract rules section - export default not found');
|
|
84
66
|
}
|
|
85
|
-
|
|
86
67
|
return match[1].trim();
|
|
87
68
|
}
|
|
69
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-eslint-sync/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createHash } from 'crypto';\n\nexport interface ValidateEslintSyncOptions {}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nfunction calculateHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nfunction normalizeContent(content: string): string {\n // Normalize line endings and trim whitespace\n return content.replace(/\\r\\n/g, '\\n').trim();\n}\n\nexport default async function validateEslintSyncExecutor(\n options: ValidateEslintSyncOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const workspaceRoot = context.root;\n\n const templatePath = join(workspaceRoot, 'packages/tooling/nx-webpieces-rules/templates/eslint.webpieces.config.mjs');\n const workspacePath = join(workspaceRoot, 'eslint.webpieces.config.mjs');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const templateContent = readFileSync(templatePath, 'utf-8');\n const workspaceContent = readFileSync(workspacePath, 'utf-8');\n\n const templateRules = extractRulesSection(templateContent);\n const workspaceRules = extractRulesSection(workspaceContent);\n\n const templateHash = calculateHash(normalizeContent(templateRules));\n const workspaceHash = calculateHash(normalizeContent(workspaceRules));\n\n if (templateHash !== workspaceHash) {\n printValidationError(templatePath, workspacePath);\n return { success: false };\n }\n\n console.log('✅ ESLint configuration sync validated - rules match!');\n return { success: true };\n\n } catch (err: unknown) {\n // Error occurred during validation - log and fail\n // eslint-disable-next-line @webpieces/catch-error-pattern\n console.error('❌ Error validating ESLint sync:', err);\n return { success: false };\n }\n}\n\nfunction printValidationError(templatePath: string, workspacePath: string): void {\n console.error('');\n console.error('❌ ESLint configuration sync validation FAILED');\n console.error('');\n console.error('The @webpieces ESLint rules must be identical in both files:');\n console.error(` 1. ${templatePath}`);\n console.error(` 2. ${workspacePath}`);\n console.error('');\n console.error('These files must have identical rules sections so that:');\n console.error(' - External clients get the same rules we use internally');\n console.error(' - We \"eat our own dog food\" - same rules for everyone');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Modify the rules in ONE file (recommend: templates/eslint.webpieces.config.mjs)');\n console.error(' 2. Copy the rules section to the other file');\n console.error(' 3. Keep import statements different (template uses npm, workspace uses loadWorkspaceRules)');\n console.error('');\n console.error('Customization for webpieces workspace goes in: eslint.config.mjs');\n console.error('');\n}\n\nfunction extractRulesSection(content: string): string {\n // Extract everything between \"export default [\" and the final \"];\"\n // This includes the rules configuration\n const match = content.match(/export default \\[([\\s\\S]*)\\];/);\n if (!match) {\n throw new Error('Could not extract rules section - export default not found');\n }\n\n return match[1].trim();\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runExecutor;
|
|
4
|
+
const code_rules_1 = require("@webpieces/code-rules");
|
|
5
|
+
async function runExecutor(
|
|
6
|
+
// webpieces-disable no-any-unknown -- options are passed through to code-rules validators
|
|
7
|
+
options, context) {
|
|
8
|
+
return (0, code_rules_1.validateModifiedFiles)(options, context.root);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-modified-files/executor.ts"],"names":[],"mappings":";;AAIA,8BAMC;AARD,sDAA8D;AAE/C,KAAK,UAAU,WAAW;AACrC,0FAA0F;AAC1F,OAAgC,EAChC,OAAwB;IAExB,OAAO,IAAA,kCAAqB,EAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AACxD,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validateModifiedFiles } from '@webpieces/code-rules';\n\nexport default async function runExecutor(\n // webpieces-disable no-any-unknown -- options are passed through to code-rules validators\n options: Record<string, unknown>,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n return validateModifiedFiles(options, context.root);\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runExecutor;
|
|
4
|
+
const code_rules_1 = require("@webpieces/code-rules");
|
|
5
|
+
async function runExecutor(
|
|
6
|
+
// webpieces-disable no-any-unknown -- options are passed through to code-rules validators
|
|
7
|
+
options, context) {
|
|
8
|
+
return (0, code_rules_1.validateModifiedMethods)(options, context.root);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=executor.js.map
|