@webpieces/nx-webpieces-rules 0.0.1 → 0.2.114
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 +4 -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.js +175 -0
- 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/src/lib/package-validator.ts +0 -184
|
@@ -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.validatePrismaConverters)(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-prisma-converters/executor.ts"],"names":[],"mappings":";;AAIA,8BAMC;AARD,sDAAiE;AAElD,KAAK,UAAU,WAAW;AACrC,0FAA0F;AAC1F,OAAgC,EAChC,OAAwB;IAExB,OAAO,IAAA,qCAAwB,EAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validatePrismaConverters } 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 validatePrismaConverters(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.validateReturnTypes)(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-return-types/executor.ts"],"names":[],"mappings":";;AAIA,8BAMC;AARD,sDAA4D;AAE7C,KAAK,UAAU,WAAW;AACrC,0FAA0F;AAC1F,OAAgC,EAChC,OAAwB;IAExB,OAAO,IAAA,gCAAmB,EAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validateReturnTypes } 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 validateReturnTypes(options, context.root);\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate TypeScript Files in src/ Executor
|
|
3
|
+
*
|
|
4
|
+
* Two-layer rule:
|
|
5
|
+
* Layer 1: every .ts file inside an Nx project must live under src/
|
|
6
|
+
* (jest.config.ts at project root is the only exception)
|
|
7
|
+
* Layer 2: every .ts file anywhere in the workspace must belong to some
|
|
8
|
+
* Nx project. Orphan files (at workspace root or in a non-project
|
|
9
|
+
* directory) fail the rule unless explicitly allowlisted.
|
|
10
|
+
*
|
|
11
|
+
* Configurable via nx.json targetDefaults:
|
|
12
|
+
* "validate-ts-in-src": {
|
|
13
|
+
* "options": {
|
|
14
|
+
* "mode": "ON",
|
|
15
|
+
* "excludePaths": [...],
|
|
16
|
+
* "allowedRootFiles": [...]
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* Usage: nx run architecture:validate-ts-in-src
|
|
21
|
+
*/
|
|
22
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
23
|
+
export type ValidateTsInSrcMode = 'ON' | 'OFF';
|
|
24
|
+
export interface ValidateTsInSrcOptions {
|
|
25
|
+
mode?: ValidateTsInSrcMode;
|
|
26
|
+
excludePaths?: string[];
|
|
27
|
+
allowedRootFiles?: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface ExecutorResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
}
|
|
32
|
+
export default function runExecutor(_nxOptions: ValidateTsInSrcOptions, context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Validate TypeScript Files in src/ Executor
|
|
3
4
|
*
|
|
@@ -19,139 +20,117 @@
|
|
|
19
20
|
*
|
|
20
21
|
* Usage: nx run architecture:validate-ts-in-src
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export interface ValidateTsInSrcOptions {
|
|
32
|
-
mode?: ValidateTsInSrcMode;
|
|
33
|
-
excludePaths?: string[];
|
|
34
|
-
allowedRootFiles?: string[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface ExecutorResult {
|
|
38
|
-
success: boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const DEFAULT_EXCLUDE_PATHS: string[] = [
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.default = runExecutor;
|
|
25
|
+
const tslib_1 = require("tslib");
|
|
26
|
+
const devkit_1 = require("@nx/devkit");
|
|
27
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
28
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
29
|
+
const path = tslib_1.__importStar(require("path"));
|
|
30
|
+
const DEFAULT_EXCLUDE_PATHS = [
|
|
42
31
|
'node_modules', 'dist', '.nx', '.git',
|
|
43
32
|
'architecture', 'tmp', 'scripts',
|
|
44
33
|
];
|
|
45
|
-
|
|
46
|
-
const DEFAULT_ALLOWED_ROOT_FILES: string[] = ['jest.setup.ts'];
|
|
47
|
-
|
|
34
|
+
const DEFAULT_ALLOWED_ROOT_FILES = ['jest.setup.ts'];
|
|
48
35
|
class LayerOneViolation {
|
|
49
|
-
filePath
|
|
50
|
-
projectName: string;
|
|
51
|
-
|
|
52
|
-
constructor(filePath: string, projectName: string) {
|
|
36
|
+
constructor(filePath, projectName) {
|
|
53
37
|
this.filePath = filePath;
|
|
54
38
|
this.projectName = projectName;
|
|
55
39
|
}
|
|
56
40
|
}
|
|
57
|
-
|
|
58
41
|
class LayerTwoViolation {
|
|
59
|
-
filePath
|
|
60
|
-
|
|
61
|
-
constructor(filePath: string) {
|
|
42
|
+
constructor(filePath) {
|
|
62
43
|
this.filePath = filePath;
|
|
63
44
|
}
|
|
64
45
|
}
|
|
65
|
-
|
|
66
|
-
function isNodeModulesDir(name: string): boolean {
|
|
46
|
+
function isNodeModulesDir(name) {
|
|
67
47
|
return name === 'node_modules' || name.startsWith('node_modules_');
|
|
68
48
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
49
|
+
function shouldSkipTopLevelDir(name, excludePaths) {
|
|
50
|
+
if (isNodeModulesDir(name))
|
|
51
|
+
return true;
|
|
72
52
|
return excludePaths.includes(name);
|
|
73
53
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const roots: string[] = [];
|
|
54
|
+
async function getProjectRoots(workspaceRoot) {
|
|
55
|
+
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
56
|
+
const projectsConfig = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
|
|
57
|
+
const roots = [];
|
|
79
58
|
for (const cfg of Object.values(projectsConfig.projects)) {
|
|
80
|
-
if (cfg.root === '' || cfg.root === '.')
|
|
81
|
-
|
|
59
|
+
if (cfg.root === '' || cfg.root === '.')
|
|
60
|
+
continue;
|
|
61
|
+
if (cfg.root === 'architecture')
|
|
62
|
+
continue;
|
|
82
63
|
roots.push(path.join(workspaceRoot, cfg.root));
|
|
83
64
|
}
|
|
84
65
|
return roots;
|
|
85
66
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
67
|
+
function findTsFilesOutsideSrc(projectDir) {
|
|
68
|
+
const violations = [];
|
|
69
|
+
if (!fs.existsSync(projectDir))
|
|
70
|
+
return violations;
|
|
90
71
|
const entries = fs.readdirSync(projectDir, { withFileTypes: true });
|
|
91
|
-
|
|
92
72
|
for (const entry of entries) {
|
|
93
|
-
if (entry.name === 'src')
|
|
94
|
-
|
|
95
|
-
if (entry.name
|
|
96
|
-
|
|
73
|
+
if (entry.name === 'src')
|
|
74
|
+
continue;
|
|
75
|
+
if (isNodeModulesDir(entry.name))
|
|
76
|
+
continue;
|
|
77
|
+
if (entry.name === 'dist')
|
|
78
|
+
continue;
|
|
97
79
|
if (entry.isFile() && entry.name.endsWith('.ts')) {
|
|
98
|
-
if (entry.name === 'jest.config.ts')
|
|
80
|
+
if (entry.name === 'jest.config.ts')
|
|
81
|
+
continue;
|
|
99
82
|
violations.push(path.join(projectDir, entry.name));
|
|
100
83
|
}
|
|
101
|
-
|
|
102
84
|
if (entry.isDirectory()) {
|
|
103
85
|
const tsFiles = findTsFilesRecursively(path.join(projectDir, entry.name));
|
|
104
86
|
violations.push(...tsFiles);
|
|
105
87
|
}
|
|
106
88
|
}
|
|
107
|
-
|
|
108
89
|
return violations;
|
|
109
90
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
91
|
+
function findTsFilesRecursively(dir) {
|
|
92
|
+
const results = [];
|
|
93
|
+
if (!fs.existsSync(dir))
|
|
94
|
+
return results;
|
|
115
95
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
116
96
|
for (const entry of entries) {
|
|
117
|
-
if (isNodeModulesDir(entry.name))
|
|
118
|
-
|
|
97
|
+
if (isNodeModulesDir(entry.name))
|
|
98
|
+
continue;
|
|
99
|
+
if (entry.name === 'dist')
|
|
100
|
+
continue;
|
|
119
101
|
const fullPath = path.join(dir, entry.name);
|
|
120
102
|
if (entry.isFile() && entry.name.endsWith('.ts')) {
|
|
121
103
|
results.push(fullPath);
|
|
122
|
-
}
|
|
104
|
+
}
|
|
105
|
+
else if (entry.isDirectory()) {
|
|
123
106
|
results.push(...findTsFilesRecursively(fullPath));
|
|
124
107
|
}
|
|
125
108
|
}
|
|
126
109
|
return results;
|
|
127
110
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
projectRootSet: Set<string>,
|
|
132
|
-
workspaceRoot: string,
|
|
133
|
-
results: string[],
|
|
134
|
-
): void {
|
|
135
|
-
if (!fs.existsSync(dir)) return;
|
|
136
|
-
|
|
111
|
+
function findOrphanTsFiles(dir, projectRootSet, workspaceRoot, results) {
|
|
112
|
+
if (!fs.existsSync(dir))
|
|
113
|
+
return;
|
|
137
114
|
const relDir = path.relative(workspaceRoot, dir);
|
|
138
|
-
if (projectRootSet.has(relDir))
|
|
139
|
-
|
|
115
|
+
if (projectRootSet.has(relDir))
|
|
116
|
+
return;
|
|
140
117
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
141
118
|
for (const entry of entries) {
|
|
142
|
-
if (isNodeModulesDir(entry.name))
|
|
143
|
-
|
|
119
|
+
if (isNodeModulesDir(entry.name))
|
|
120
|
+
continue;
|
|
121
|
+
if (entry.name === 'dist')
|
|
122
|
+
continue;
|
|
144
123
|
const fullPath = path.join(dir, entry.name);
|
|
145
124
|
if (entry.isFile() && entry.name.endsWith('.ts')) {
|
|
146
125
|
results.push(fullPath);
|
|
147
|
-
}
|
|
126
|
+
}
|
|
127
|
+
else if (entry.isDirectory()) {
|
|
148
128
|
findOrphanTsFiles(fullPath, projectRootSet, workspaceRoot, results);
|
|
149
129
|
}
|
|
150
130
|
}
|
|
151
131
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const violations: LayerOneViolation[] = [];
|
|
132
|
+
function checkLayerOne(projectRoots, workspaceRoot) {
|
|
133
|
+
const violations = [];
|
|
155
134
|
for (const projectDir of projectRoots) {
|
|
156
135
|
const projectName = path.relative(workspaceRoot, projectDir);
|
|
157
136
|
const tsFiles = findTsFilesOutsideSrc(projectDir);
|
|
@@ -162,46 +141,32 @@ function checkLayerOne(projectRoots: string[], workspaceRoot: string): LayerOneV
|
|
|
162
141
|
}
|
|
163
142
|
return violations;
|
|
164
143
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
workspaceRoot
|
|
168
|
-
projectRoots: string[],
|
|
169
|
-
excludePaths: string[],
|
|
170
|
-
allowedRootFiles: string[],
|
|
171
|
-
): LayerTwoViolation[] {
|
|
172
|
-
const violations: LayerTwoViolation[] = [];
|
|
173
|
-
const projectRootSet = new Set(
|
|
174
|
-
projectRoots.map((p) => path.relative(workspaceRoot, p)),
|
|
175
|
-
);
|
|
176
|
-
|
|
144
|
+
function checkLayerTwo(workspaceRoot, projectRoots, excludePaths, allowedRootFiles) {
|
|
145
|
+
const violations = [];
|
|
146
|
+
const projectRootSet = new Set(projectRoots.map((p) => path.relative(workspaceRoot, p)));
|
|
177
147
|
const entries = fs.readdirSync(workspaceRoot, { withFileTypes: true });
|
|
178
|
-
|
|
179
148
|
for (const entry of entries) {
|
|
180
149
|
if (entry.isFile()) {
|
|
181
|
-
if (!entry.name.endsWith('.ts'))
|
|
182
|
-
|
|
150
|
+
if (!entry.name.endsWith('.ts'))
|
|
151
|
+
continue;
|
|
152
|
+
if (allowedRootFiles.includes(entry.name))
|
|
153
|
+
continue;
|
|
183
154
|
violations.push(new LayerTwoViolation(entry.name));
|
|
184
155
|
continue;
|
|
185
156
|
}
|
|
186
|
-
if (!entry.isDirectory())
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
projectRootSet,
|
|
193
|
-
workspaceRoot,
|
|
194
|
-
orphans,
|
|
195
|
-
);
|
|
157
|
+
if (!entry.isDirectory())
|
|
158
|
+
continue;
|
|
159
|
+
if (shouldSkipTopLevelDir(entry.name, excludePaths))
|
|
160
|
+
continue;
|
|
161
|
+
const orphans = [];
|
|
162
|
+
findOrphanTsFiles(path.join(workspaceRoot, entry.name), projectRootSet, workspaceRoot, orphans);
|
|
196
163
|
for (const orphan of orphans) {
|
|
197
164
|
violations.push(new LayerTwoViolation(path.relative(workspaceRoot, orphan)));
|
|
198
165
|
}
|
|
199
166
|
}
|
|
200
|
-
|
|
201
167
|
return violations;
|
|
202
168
|
}
|
|
203
|
-
|
|
204
|
-
function reportLayerOneFailure(violations: LayerOneViolation[]): void {
|
|
169
|
+
function reportLayerOneFailure(violations) {
|
|
205
170
|
console.error('❌ TypeScript files found outside src/ directory!\n');
|
|
206
171
|
console.error('All .ts source files must be inside the project\'s src/ directory.');
|
|
207
172
|
console.error('This enforces the standard project structure:\n');
|
|
@@ -210,25 +175,20 @@ function reportLayerOneFailure(violations: LayerOneViolation[]): void {
|
|
|
210
175
|
console.error(' ├── package.json');
|
|
211
176
|
console.error(' ├── project.json');
|
|
212
177
|
console.error(' └── tsconfig.json\n');
|
|
213
|
-
|
|
214
178
|
for (const v of violations) {
|
|
215
179
|
console.error(` ❌ ${v.filePath}`);
|
|
216
180
|
}
|
|
217
|
-
|
|
218
181
|
console.error('\nTo fix: Move the .ts file(s) into the src/ directory');
|
|
219
182
|
console.error('Only exception: jest.config.ts at project root\n');
|
|
220
183
|
}
|
|
221
|
-
|
|
222
|
-
function reportLayerTwoFailure(violations: LayerTwoViolation[]): void {
|
|
184
|
+
function reportLayerTwoFailure(violations) {
|
|
223
185
|
console.error('❌ TypeScript files found outside any Nx project!\n');
|
|
224
186
|
console.error('Every .ts file must belong to an Nx project so it is compiled,');
|
|
225
187
|
console.error('linted, and tested under a known project config. Orphan files are');
|
|
226
188
|
console.error('invisible to the build graph and will rot.\n');
|
|
227
|
-
|
|
228
189
|
for (const v of violations) {
|
|
229
190
|
console.error(` ❌ ${v.filePath}`);
|
|
230
191
|
}
|
|
231
|
-
|
|
232
192
|
console.error('\nTo fix, pick one:');
|
|
233
193
|
console.error(' (a) Move the file into an existing project\'s src/ directory');
|
|
234
194
|
console.error(' (b) Create a new project (add project.json) that owns the directory');
|
|
@@ -236,48 +196,33 @@ function reportLayerTwoFailure(violations: LayerTwoViolation[]): void {
|
|
|
236
196
|
console.error(' in nx.json targetDefaults, or add the filename to allowedRootFiles');
|
|
237
197
|
console.error(' if it is a legitimate workspace-root file (e.g., jest.setup.ts)\n');
|
|
238
198
|
}
|
|
239
|
-
|
|
240
|
-
export default async function runExecutor(
|
|
241
|
-
_nxOptions: ValidateTsInSrcOptions,
|
|
242
|
-
context: ExecutorContext,
|
|
243
|
-
): Promise<ExecutorResult> {
|
|
199
|
+
async function runExecutor(_nxOptions, context) {
|
|
244
200
|
// Config comes from webpieces.config.json — same source as ai-hooks
|
|
245
201
|
// and validate-code — via @webpieces/rules-config.
|
|
246
|
-
const shared = loadConfig(context.root);
|
|
202
|
+
const shared = (0, rules_config_1.loadConfig)(context.root);
|
|
247
203
|
const rule = shared.rules.get('validate-ts-in-src');
|
|
248
|
-
|
|
249
204
|
if (rule && rule.enabled === false) {
|
|
250
205
|
console.log('\n⏭️ Skipping validate-ts-in-src (enabled: false)\n');
|
|
251
206
|
return { success: true };
|
|
252
207
|
}
|
|
253
|
-
|
|
254
208
|
const workspaceRoot = context.root;
|
|
255
|
-
const excludePaths =
|
|
256
|
-
|
|
257
|
-
const allowedRootFiles =
|
|
258
|
-
(rule?.options['allowedRootFiles'] as string[] | undefined) ?? DEFAULT_ALLOWED_ROOT_FILES;
|
|
259
|
-
|
|
209
|
+
const excludePaths = rule?.options['excludePaths'] ?? DEFAULT_EXCLUDE_PATHS;
|
|
210
|
+
const allowedRootFiles = rule?.options['allowedRootFiles'] ?? DEFAULT_ALLOWED_ROOT_FILES;
|
|
260
211
|
console.log('\n📁 Validating TypeScript files are in src/ and owned by a project\n');
|
|
261
|
-
|
|
262
212
|
const projectRoots = await getProjectRoots(workspaceRoot);
|
|
263
|
-
|
|
264
213
|
const layerOneViolations = checkLayerOne(projectRoots, workspaceRoot);
|
|
265
|
-
const layerTwoViolations = checkLayerTwo(
|
|
266
|
-
workspaceRoot, projectRoots, excludePaths, allowedRootFiles,
|
|
267
|
-
);
|
|
268
|
-
|
|
214
|
+
const layerTwoViolations = checkLayerTwo(workspaceRoot, projectRoots, excludePaths, allowedRootFiles);
|
|
269
215
|
if (layerOneViolations.length === 0 && layerTwoViolations.length === 0) {
|
|
270
216
|
console.log('✅ All .ts files are inside a project\'s src/ directory\n');
|
|
271
217
|
return { success: true };
|
|
272
218
|
}
|
|
273
|
-
|
|
274
219
|
if (layerOneViolations.length > 0) {
|
|
275
220
|
reportLayerOneFailure(layerOneViolations);
|
|
276
221
|
}
|
|
277
222
|
if (layerTwoViolations.length > 0) {
|
|
278
223
|
reportLayerTwoFailure(layerTwoViolations);
|
|
279
224
|
}
|
|
280
|
-
|
|
281
225
|
console.error('To disable: set rules["validate-ts-in-src"].enabled to false in webpieces.config.json\n');
|
|
282
226
|
return { success: false };
|
|
283
227
|
}
|
|
228
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-ts-in-src/executor.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AA2NH,8BA2CC;;AAnQD,uCAAgG;AAChG,0DAAqD;AACrD,+CAAyB;AACzB,mDAA6B;AAc7B,MAAM,qBAAqB,GAAa;IACpC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IACrC,cAAc,EAAE,KAAK,EAAE,SAAS;CACnC,CAAC;AAEF,MAAM,0BAA0B,GAAa,CAAC,eAAe,CAAC,CAAC;AAE/D,MAAM,iBAAiB;IAInB,YAAY,QAAgB,EAAE,WAAmB;QAC7C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACnC,CAAC;CACJ;AAED,MAAM,iBAAiB;IAGnB,YAAY,QAAgB;QACxB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ;AAED,SAAS,gBAAgB,CAAC,IAAY;IAClC,OAAO,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY,EAAE,YAAsB;IAC/D,IAAI,gBAAgB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,aAAqB;IAChD,MAAM,YAAY,GAAG,MAAM,IAAA,gCAAuB,GAAE,CAAC;IACrD,MAAM,cAAc,GAAG,IAAA,kDAAyC,EAAC,YAAY,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG;YAAE,SAAS;QAClD,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;YAAE,SAAS;QAC1C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAkB;IAC7C,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAClD,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK;YAAE,SAAS;QACnC,IAAI,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QAC3C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAEpC,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB;gBAAE,SAAS;YAC9C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1E,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAChC,CAAC;IACL,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAW;IACvC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAExC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QAC3C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtD,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CACtB,GAAW,EACX,cAA2B,EAC3B,aAAqB,EACrB,OAAiB;IAEjB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO;IAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO;IAEvC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QAC3C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7B,iBAAiB,CAAC,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;QACxE,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,YAAsB,EAAE,aAAqB;IAChE,MAAM,UAAU,GAAwB,EAAE,CAAC;IAC3C,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;QAClD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAC1D,UAAU,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;QACtE,CAAC;IACL,CAAC;IACD,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,SAAS,aAAa,CAClB,aAAqB,EACrB,YAAsB,EACtB,YAAsB,EACtB,gBAA0B;IAE1B,MAAM,UAAU,GAAwB,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,IAAI,GAAG,CAC1B,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAC3D,CAAC;IAEF,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YAC1C,IAAI,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YACpD,UAAU,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YACnD,SAAS;QACb,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QACnC,IAAI,qBAAqB,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC;YAAE,SAAS;QAE9D,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,iBAAiB,CACb,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,EACpC,cAAc,EACd,aAAa,EACb,OAAO,CACV,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACjF,CAAC;IACL,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,SAAS,qBAAqB,CAAC,UAA+B;IAC1D,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACpF,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC/C,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC1D,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACpC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACpC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEvC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACxE,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,qBAAqB,CAAC,UAA+B;IAC1D,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAChF,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACnF,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAE9D,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACrC,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAChF,OAAO,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;IACvF,OAAO,CAAC,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACjG,OAAO,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC1F,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;AAC7F,CAAC;AAEc,KAAK,UAAU,WAAW,CACrC,UAAkC,EAClC,OAAwB;IAExB,oEAAoE;IACpE,mDAAmD;IACnD,MAAM,MAAM,GAAG,IAAA,yBAAU,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAEpD,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IACnC,MAAM,YAAY,GACb,IAAI,EAAE,OAAO,CAAC,cAAc,CAA0B,IAAI,qBAAqB,CAAC;IACrF,MAAM,gBAAgB,GACjB,IAAI,EAAE,OAAO,CAAC,kBAAkB,CAA0B,IAAI,0BAA0B,CAAC;IAE9F,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IAErF,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;IAE1D,MAAM,kBAAkB,GAAG,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IACtE,MAAM,kBAAkB,GAAG,aAAa,CACpC,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,CAC9D,CAAC;IAEF,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,yFAAyF,CAAC,CAAC;IACzG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC","sourcesContent":["/**\n * Validate TypeScript Files in src/ Executor\n *\n * Two-layer rule:\n * Layer 1: every .ts file inside an Nx project must live under src/\n * (jest.config.ts at project root is the only exception)\n * Layer 2: every .ts file anywhere in the workspace must belong to some\n * Nx project. Orphan files (at workspace root or in a non-project\n * directory) fail the rule unless explicitly allowlisted.\n *\n * Configurable via nx.json targetDefaults:\n * \"validate-ts-in-src\": {\n * \"options\": {\n * \"mode\": \"ON\",\n * \"excludePaths\": [...],\n * \"allowedRootFiles\": [...]\n * }\n * }\n *\n * Usage: nx run architecture:validate-ts-in-src\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { createProjectGraphAsync, readProjectsConfigurationFromProjectGraph } from '@nx/devkit';\nimport { loadConfig } from '@webpieces/rules-config';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport type ValidateTsInSrcMode = 'ON' | 'OFF';\n\nexport interface ValidateTsInSrcOptions {\n mode?: ValidateTsInSrcMode;\n excludePaths?: string[];\n allowedRootFiles?: string[];\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nconst DEFAULT_EXCLUDE_PATHS: string[] = [\n 'node_modules', 'dist', '.nx', '.git',\n 'architecture', 'tmp', 'scripts',\n];\n\nconst DEFAULT_ALLOWED_ROOT_FILES: string[] = ['jest.setup.ts'];\n\nclass LayerOneViolation {\n filePath: string;\n projectName: string;\n\n constructor(filePath: string, projectName: string) {\n this.filePath = filePath;\n this.projectName = projectName;\n }\n}\n\nclass LayerTwoViolation {\n filePath: string;\n\n constructor(filePath: string) {\n this.filePath = filePath;\n }\n}\n\nfunction isNodeModulesDir(name: string): boolean {\n return name === 'node_modules' || name.startsWith('node_modules_');\n}\n\nfunction shouldSkipTopLevelDir(name: string, excludePaths: string[]): boolean {\n if (isNodeModulesDir(name)) return true;\n return excludePaths.includes(name);\n}\n\nasync function getProjectRoots(workspaceRoot: string): Promise<string[]> {\n const projectGraph = await createProjectGraphAsync();\n const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);\n const roots: string[] = [];\n for (const cfg of Object.values(projectsConfig.projects)) {\n if (cfg.root === '' || cfg.root === '.') continue;\n if (cfg.root === 'architecture') continue;\n roots.push(path.join(workspaceRoot, cfg.root));\n }\n return roots;\n}\n\nfunction findTsFilesOutsideSrc(projectDir: string): string[] {\n const violations: string[] = [];\n if (!fs.existsSync(projectDir)) return violations;\n const entries = fs.readdirSync(projectDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name === 'src') continue;\n if (isNodeModulesDir(entry.name)) continue;\n if (entry.name === 'dist') continue;\n\n if (entry.isFile() && entry.name.endsWith('.ts')) {\n if (entry.name === 'jest.config.ts') continue;\n violations.push(path.join(projectDir, entry.name));\n }\n\n if (entry.isDirectory()) {\n const tsFiles = findTsFilesRecursively(path.join(projectDir, entry.name));\n violations.push(...tsFiles);\n }\n }\n\n return violations;\n}\n\nfunction findTsFilesRecursively(dir: string): string[] {\n const results: string[] = [];\n if (!fs.existsSync(dir)) return results;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (isNodeModulesDir(entry.name)) continue;\n if (entry.name === 'dist') continue;\n const fullPath = path.join(dir, entry.name);\n if (entry.isFile() && entry.name.endsWith('.ts')) {\n results.push(fullPath);\n } else if (entry.isDirectory()) {\n results.push(...findTsFilesRecursively(fullPath));\n }\n }\n return results;\n}\n\nfunction findOrphanTsFiles(\n dir: string,\n projectRootSet: Set<string>,\n workspaceRoot: string,\n results: string[],\n): void {\n if (!fs.existsSync(dir)) return;\n\n const relDir = path.relative(workspaceRoot, dir);\n if (projectRootSet.has(relDir)) return;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (isNodeModulesDir(entry.name)) continue;\n if (entry.name === 'dist') continue;\n const fullPath = path.join(dir, entry.name);\n if (entry.isFile() && entry.name.endsWith('.ts')) {\n results.push(fullPath);\n } else if (entry.isDirectory()) {\n findOrphanTsFiles(fullPath, projectRootSet, workspaceRoot, results);\n }\n }\n}\n\nfunction checkLayerOne(projectRoots: string[], workspaceRoot: string): LayerOneViolation[] {\n const violations: LayerOneViolation[] = [];\n for (const projectDir of projectRoots) {\n const projectName = path.relative(workspaceRoot, projectDir);\n const tsFiles = findTsFilesOutsideSrc(projectDir);\n for (const tsFile of tsFiles) {\n const relativePath = path.relative(workspaceRoot, tsFile);\n violations.push(new LayerOneViolation(relativePath, projectName));\n }\n }\n return violations;\n}\n\nfunction checkLayerTwo(\n workspaceRoot: string,\n projectRoots: string[],\n excludePaths: string[],\n allowedRootFiles: string[],\n): LayerTwoViolation[] {\n const violations: LayerTwoViolation[] = [];\n const projectRootSet = new Set(\n projectRoots.map((p) => path.relative(workspaceRoot, p)),\n );\n\n const entries = fs.readdirSync(workspaceRoot, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isFile()) {\n if (!entry.name.endsWith('.ts')) continue;\n if (allowedRootFiles.includes(entry.name)) continue;\n violations.push(new LayerTwoViolation(entry.name));\n continue;\n }\n if (!entry.isDirectory()) continue;\n if (shouldSkipTopLevelDir(entry.name, excludePaths)) continue;\n\n const orphans: string[] = [];\n findOrphanTsFiles(\n path.join(workspaceRoot, entry.name),\n projectRootSet,\n workspaceRoot,\n orphans,\n );\n for (const orphan of orphans) {\n violations.push(new LayerTwoViolation(path.relative(workspaceRoot, orphan)));\n }\n }\n\n return violations;\n}\n\nfunction reportLayerOneFailure(violations: LayerOneViolation[]): void {\n console.error('❌ TypeScript files found outside src/ directory!\\n');\n console.error('All .ts source files must be inside the project\\'s src/ directory.');\n console.error('This enforces the standard project structure:\\n');\n console.error(' packages/{category}/{name}/');\n console.error(' ├── src/ ← ALL .ts files here');\n console.error(' ├── package.json');\n console.error(' ├── project.json');\n console.error(' └── tsconfig.json\\n');\n\n for (const v of violations) {\n console.error(` ❌ ${v.filePath}`);\n }\n\n console.error('\\nTo fix: Move the .ts file(s) into the src/ directory');\n console.error('Only exception: jest.config.ts at project root\\n');\n}\n\nfunction reportLayerTwoFailure(violations: LayerTwoViolation[]): void {\n console.error('❌ TypeScript files found outside any Nx project!\\n');\n console.error('Every .ts file must belong to an Nx project so it is compiled,');\n console.error('linted, and tested under a known project config. Orphan files are');\n console.error('invisible to the build graph and will rot.\\n');\n\n for (const v of violations) {\n console.error(` ❌ ${v.filePath}`);\n }\n\n console.error('\\nTo fix, pick one:');\n console.error(' (a) Move the file into an existing project\\'s src/ directory');\n console.error(' (b) Create a new project (add project.json) that owns the directory');\n console.error(' (c) Add the containing top-level directory to validate-ts-in-src.excludePaths');\n console.error(' in nx.json targetDefaults, or add the filename to allowedRootFiles');\n console.error(' if it is a legitimate workspace-root file (e.g., jest.setup.ts)\\n');\n}\n\nexport default async function runExecutor(\n _nxOptions: ValidateTsInSrcOptions,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n // Config comes from webpieces.config.json — same source as ai-hooks\n // and validate-code — via @webpieces/rules-config.\n const shared = loadConfig(context.root);\n const rule = shared.rules.get('validate-ts-in-src');\n\n if (rule && rule.enabled === false) {\n console.log('\\n⏭️ Skipping validate-ts-in-src (enabled: false)\\n');\n return { success: true };\n }\n\n const workspaceRoot = context.root;\n const excludePaths =\n (rule?.options['excludePaths'] as string[] | undefined) ?? DEFAULT_EXCLUDE_PATHS;\n const allowedRootFiles =\n (rule?.options['allowedRootFiles'] as string[] | undefined) ?? DEFAULT_ALLOWED_ROOT_FILES;\n\n console.log('\\n📁 Validating TypeScript files are in src/ and owned by a project\\n');\n\n const projectRoots = await getProjectRoots(workspaceRoot);\n\n const layerOneViolations = checkLayerOne(projectRoots, workspaceRoot);\n const layerTwoViolations = checkLayerTwo(\n workspaceRoot, projectRoots, excludePaths, allowedRootFiles,\n );\n\n if (layerOneViolations.length === 0 && layerTwoViolations.length === 0) {\n console.log('✅ All .ts files are inside a project\\'s src/ directory\\n');\n return { success: true };\n }\n\n if (layerOneViolations.length > 0) {\n reportLayerOneFailure(layerOneViolations);\n }\n if (layerTwoViolations.length > 0) {\n reportLayerTwoFailure(layerTwoViolations);\n }\n\n console.error('To disable: set rules[\"validate-ts-in-src\"].enabled to false in webpieces.config.json\\n');\n return { success: false };\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Versions Locked Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that package.json versions are:
|
|
5
|
+
* 1. LOCKED (exact versions, no semver ranges like ^, ~, *)
|
|
6
|
+
* 2. CONSISTENT across all package.json files (no version conflicts)
|
|
7
|
+
*
|
|
8
|
+
* Why locked versions matter:
|
|
9
|
+
* - Micro bugs ARE introduced via patch versions (1.4.5 → 1.4.6)
|
|
10
|
+
* - git bisect fails when software changes OUTSIDE of git
|
|
11
|
+
* - Library upgrades must be explicit via PR/commit, not implicit drift
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* nx run architecture:validate-versions-locked
|
|
15
|
+
*/
|
|
16
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
17
|
+
export interface ValidateVersionsLockedOptions {
|
|
18
|
+
}
|
|
19
|
+
export interface ExecutorResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
}
|
|
22
|
+
export default function runExecutor(_options: ValidateVersionsLockedOptions, context: ExecutorContext): Promise<ExecutorResult>;
|