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