@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.
Files changed (120) hide show
  1. package/package.json +4 -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.js +175 -0
  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
  120. package/src/lib/package-validator.ts +0 -184
@@ -1,35 +1,12 @@
1
+ "use strict";
1
2
  /**
2
3
  * Graph Comparator
3
4
  *
4
5
  * Compares the current generated graph with the saved (blessed) graph.
5
6
  * Used in validate mode to ensure developers have updated the graph file.
6
7
  */
7
-
8
- import type { EnhancedGraph } from './graph-sorter';
9
-
10
- /**
11
- * Difference between two graphs
12
- */
13
- export interface GraphDiff {
14
- added: string[];
15
- removed: string[];
16
- modified: {
17
- project: string;
18
- addedDeps: string[];
19
- removedDeps: string[];
20
- levelChanged: { from: number; to: number } | null;
21
- }[];
22
- }
23
-
24
- /**
25
- * Comparison result
26
- */
27
- export interface ComparisonResult {
28
- identical: boolean;
29
- diff: GraphDiff;
30
- summary: string;
31
- }
32
-
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.compareGraphs = compareGraphs;
33
10
  /**
34
11
  * Compare two graphs and return the differences
35
12
  *
@@ -37,81 +14,59 @@ export interface ComparisonResult {
37
14
  * @param saved - Previously saved (blessed) graph
38
15
  * @returns Comparison result with detailed diff
39
16
  */
40
- export function compareGraphs(current: EnhancedGraph, saved: EnhancedGraph): ComparisonResult {
17
+ function compareGraphs(current, saved) {
41
18
  const currentProjects = new Set(Object.keys(current));
42
19
  const savedProjects = new Set(Object.keys(saved));
43
-
44
- const diff: GraphDiff = {
20
+ const diff = {
45
21
  added: [],
46
22
  removed: [],
47
23
  modified: [],
48
24
  };
49
-
50
25
  // Find added projects
51
26
  for (const project of currentProjects) {
52
27
  if (!savedProjects.has(project)) {
53
28
  diff.added.push(project);
54
29
  }
55
30
  }
56
-
57
31
  // Find removed projects
58
32
  for (const project of savedProjects) {
59
33
  if (!currentProjects.has(project)) {
60
34
  diff.removed.push(project);
61
35
  }
62
36
  }
63
-
64
37
  // Find modified projects
65
38
  findModifiedProjects(current, saved, currentProjects, savedProjects, diff);
66
-
67
- const identical =
68
- diff.added.length === 0 && diff.removed.length === 0 && diff.modified.length === 0;
69
-
39
+ const identical = diff.added.length === 0 && diff.removed.length === 0 && diff.modified.length === 0;
70
40
  const summary = identical ? 'Graphs are identical' : buildSummary(diff);
71
-
72
41
  return {
73
42
  identical,
74
43
  diff,
75
44
  summary,
76
45
  };
77
46
  }
78
-
79
- function findModifiedProjects(
80
- current: EnhancedGraph,
81
- saved: EnhancedGraph,
82
- currentProjects: Set<string>,
83
- savedProjects: Set<string>,
84
- diff: GraphDiff
85
- ): void {
47
+ function findModifiedProjects(current, saved, currentProjects, savedProjects, diff) {
86
48
  for (const project of currentProjects) {
87
- if (!savedProjects.has(project)) continue;
88
-
49
+ if (!savedProjects.has(project))
50
+ continue;
89
51
  const currentEntry = current[project];
90
52
  const savedEntry = saved[project];
91
-
92
53
  const currentDeps = new Set(currentEntry.dependsOn);
93
54
  const savedDeps = new Set(savedEntry.dependsOn);
94
-
95
- const addedDeps: string[] = [];
96
- const removedDeps: string[] = [];
97
-
55
+ const addedDeps = [];
56
+ const removedDeps = [];
98
57
  for (const dep of currentDeps) {
99
58
  if (!savedDeps.has(dep)) {
100
59
  addedDeps.push(dep);
101
60
  }
102
61
  }
103
-
104
62
  for (const dep of savedDeps) {
105
63
  if (!currentDeps.has(dep)) {
106
64
  removedDeps.push(dep);
107
65
  }
108
66
  }
109
-
110
- const levelChanged =
111
- currentEntry.level !== savedEntry.level
112
- ? { from: savedEntry.level, to: currentEntry.level }
113
- : null;
114
-
67
+ const levelChanged = currentEntry.level !== savedEntry.level
68
+ ? { from: savedEntry.level, to: currentEntry.level }
69
+ : null;
115
70
  if (addedDeps.length > 0 || removedDeps.length > 0 || levelChanged) {
116
71
  diff.modified.push({
117
72
  project,
@@ -122,20 +77,16 @@ function findModifiedProjects(
122
77
  }
123
78
  }
124
79
  }
125
-
126
- function buildSummary(diff: GraphDiff): string {
127
- const summaryParts: string[] = [];
128
-
80
+ function buildSummary(diff) {
81
+ const summaryParts = [];
129
82
  if (diff.added.length > 0) {
130
83
  summaryParts.push(`Added projects: ${diff.added.join(', ')}`);
131
84
  }
132
-
133
85
  if (diff.removed.length > 0) {
134
86
  summaryParts.push(`Removed projects: ${diff.removed.join(', ')}`);
135
87
  }
136
-
137
88
  for (const mod of diff.modified) {
138
- const parts: string[] = [];
89
+ const parts = [];
139
90
  if (mod.addedDeps.length > 0) {
140
91
  parts.push(`+deps: ${mod.addedDeps.join(', ')}`);
141
92
  }
@@ -149,6 +100,6 @@ function buildSummary(diff: GraphDiff): string {
149
100
  summaryParts.push(`${mod.project}: ${parts.join('; ')}`);
150
101
  }
151
102
  }
152
-
153
103
  return summaryParts.join('\n');
154
104
  }
105
+ //# sourceMappingURL=graph-comparator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-comparator.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-comparator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Comparator\n *\n * Compares the current generated graph with the saved (blessed) graph.\n * Used in validate mode to ensure developers have updated the graph file.\n */\n\nimport type { EnhancedGraph } from './graph-sorter';\n\n/**\n * Difference between two graphs\n */\nexport interface GraphDiff {\n added: string[];\n removed: string[];\n modified: {\n project: string;\n addedDeps: string[];\n removedDeps: string[];\n levelChanged: { from: number; to: number } | null;\n }[];\n}\n\n/**\n * Comparison result\n */\nexport interface ComparisonResult {\n identical: boolean;\n diff: GraphDiff;\n summary: string;\n}\n\n/**\n * Compare two graphs and return the differences\n *\n * @param current - Currently generated graph\n * @param saved - Previously saved (blessed) graph\n * @returns Comparison result with detailed diff\n */\nexport function compareGraphs(current: EnhancedGraph, saved: EnhancedGraph): ComparisonResult {\n const currentProjects = new Set(Object.keys(current));\n const savedProjects = new Set(Object.keys(saved));\n\n const diff: GraphDiff = {\n added: [],\n removed: [],\n modified: [],\n };\n\n // Find added projects\n for (const project of currentProjects) {\n if (!savedProjects.has(project)) {\n diff.added.push(project);\n }\n }\n\n // Find removed projects\n for (const project of savedProjects) {\n if (!currentProjects.has(project)) {\n diff.removed.push(project);\n }\n }\n\n // Find modified projects\n findModifiedProjects(current, saved, currentProjects, savedProjects, diff);\n\n const identical =\n diff.added.length === 0 && diff.removed.length === 0 && diff.modified.length === 0;\n\n const summary = identical ? 'Graphs are identical' : buildSummary(diff);\n\n return {\n identical,\n diff,\n summary,\n };\n}\n\nfunction findModifiedProjects(\n current: EnhancedGraph,\n saved: EnhancedGraph,\n currentProjects: Set<string>,\n savedProjects: Set<string>,\n diff: GraphDiff\n): void {\n for (const project of currentProjects) {\n if (!savedProjects.has(project)) continue;\n\n const currentEntry = current[project];\n const savedEntry = saved[project];\n\n const currentDeps = new Set(currentEntry.dependsOn);\n const savedDeps = new Set(savedEntry.dependsOn);\n\n const addedDeps: string[] = [];\n const removedDeps: string[] = [];\n\n for (const dep of currentDeps) {\n if (!savedDeps.has(dep)) {\n addedDeps.push(dep);\n }\n }\n\n for (const dep of savedDeps) {\n if (!currentDeps.has(dep)) {\n removedDeps.push(dep);\n }\n }\n\n const levelChanged =\n currentEntry.level !== savedEntry.level\n ? { from: savedEntry.level, to: currentEntry.level }\n : null;\n\n if (addedDeps.length > 0 || removedDeps.length > 0 || levelChanged) {\n diff.modified.push({\n project,\n addedDeps,\n removedDeps,\n levelChanged,\n });\n }\n }\n}\n\nfunction buildSummary(diff: GraphDiff): string {\n const summaryParts: string[] = [];\n\n if (diff.added.length > 0) {\n summaryParts.push(`Added projects: ${diff.added.join(', ')}`);\n }\n\n if (diff.removed.length > 0) {\n summaryParts.push(`Removed projects: ${diff.removed.join(', ')}`);\n }\n\n for (const mod of diff.modified) {\n const parts: string[] = [];\n if (mod.addedDeps.length > 0) {\n parts.push(`+deps: ${mod.addedDeps.join(', ')}`);\n }\n if (mod.removedDeps.length > 0) {\n parts.push(`-deps: ${mod.removedDeps.join(', ')}`);\n }\n if (mod.levelChanged) {\n parts.push(`level: ${mod.levelChanged.from} -> ${mod.levelChanged.to}`);\n }\n if (parts.length > 0) {\n summaryParts.push(`${mod.project}: ${parts.join('; ')}`);\n }\n }\n\n return summaryParts.join('\\n');\n}\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Graph Generator
3
+ *
4
+ * Generates dependency graph from project.json files in the workspace.
5
+ * Reads build.dependsOn and implicitDependencies to determine project relationships.
6
+ */
7
+ /**
8
+ * Generate raw dependency graph from project.json files
9
+ * Returns: { projectName: [dependencyNames] }
10
+ */
11
+ export declare function generateRawGraph(): Promise<Record<string, string[]>>;
12
+ /**
13
+ * Transform project names (sorting dependencies only - no scope transformation)
14
+ */
15
+ export declare function transformGraph(rawGraph: Record<string, string[]>): Record<string, string[]>;
16
+ /**
17
+ * Generate complete dependency graph with transformations
18
+ */
19
+ export declare function generateGraph(): Promise<Record<string, string[]>>;
@@ -1,27 +1,24 @@
1
+ "use strict";
1
2
  /**
2
3
  * Graph Generator
3
4
  *
4
5
  * Generates dependency graph from project.json files in the workspace.
5
6
  * Reads build.dependsOn and implicitDependencies to determine project relationships.
6
7
  */
7
-
8
- import {
9
- createProjectGraphAsync,
10
- readProjectsConfigurationFromProjectGraph,
11
- ProjectConfiguration,
12
- } from '@nx/devkit';
13
-
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.generateRawGraph = generateRawGraph;
10
+ exports.transformGraph = transformGraph;
11
+ exports.generateGraph = generateGraph;
12
+ const devkit_1 = require("@nx/devkit");
14
13
  /**
15
14
  * Projects to exclude from graph validation (tools, configs, etc.)
16
15
  */
17
- const EXCLUDED_PROJECTS = new Set<string>([]);
18
-
16
+ const EXCLUDED_PROJECTS = new Set([]);
19
17
  /**
20
18
  * Extract project dependencies from project.json's build.dependsOn and implicitDependencies
21
19
  */
22
- function extractBuildDependencies(projectConfig: ProjectConfiguration): string[] {
23
- const deps: string[] = [];
24
-
20
+ function extractBuildDependencies(projectConfig) {
21
+ const deps = [];
25
22
  // 1. Read from build.dependsOn
26
23
  const buildTarget = projectConfig.targets?.['build'];
27
24
  if (buildTarget && buildTarget.dependsOn) {
@@ -35,7 +32,6 @@ function extractBuildDependencies(projectConfig: ProjectConfiguration): string[]
35
32
  }
36
33
  }
37
34
  }
38
-
39
35
  // 2. Also read from implicitDependencies
40
36
  if (projectConfig.implicitDependencies && Array.isArray(projectConfig.implicitDependencies)) {
41
37
  for (const dep of projectConfig.implicitDependencies) {
@@ -44,54 +40,45 @@ function extractBuildDependencies(projectConfig: ProjectConfiguration): string[]
44
40
  }
45
41
  }
46
42
  }
47
-
48
43
  return deps.sort();
49
44
  }
50
-
51
45
  /**
52
46
  * Generate raw dependency graph from project.json files
53
47
  * Returns: { projectName: [dependencyNames] }
54
48
  */
55
- export async function generateRawGraph(): Promise<Record<string, string[]>> {
56
- const projectGraph = await createProjectGraphAsync();
57
- const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);
58
- const rawDeps: Record<string, string[]> = {};
59
-
49
+ async function generateRawGraph() {
50
+ const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
51
+ const projectsConfig = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
52
+ const rawDeps = {};
60
53
  for (const [projectName, projectConfig] of Object.entries(projectsConfig.projects)) {
61
54
  // Skip excluded projects (tools, plugins)
62
55
  if (EXCLUDED_PROJECTS.has(projectName)) {
63
56
  continue;
64
57
  }
65
-
66
58
  // Extract dependencies from build.dependsOn in project.json
67
59
  const deps = extractBuildDependencies(projectConfig);
68
60
  rawDeps[projectName] = deps;
69
61
  }
70
-
71
62
  return rawDeps;
72
63
  }
73
-
74
64
  /**
75
65
  * Transform project names (sorting dependencies only - no scope transformation)
76
66
  */
77
- export function transformGraph(rawGraph: Record<string, string[]>): Record<string, string[]> {
78
- const result: Record<string, string[]> = {};
79
-
67
+ function transformGraph(rawGraph) {
68
+ const result = {};
80
69
  for (const [projectName, deps] of Object.entries(rawGraph)) {
81
70
  // Use project names as-is - don't force @webpieces scope on client projects
82
71
  const transformedName = projectName;
83
72
  const transformedDeps = deps.sort();
84
-
85
73
  result[transformedName] = transformedDeps;
86
74
  }
87
-
88
75
  return result;
89
76
  }
90
-
91
77
  /**
92
78
  * Generate complete dependency graph with transformations
93
79
  */
94
- export async function generateGraph(): Promise<Record<string, string[]>> {
80
+ async function generateGraph() {
95
81
  const rawGraph = await generateRawGraph();
96
82
  return transformGraph(rawGraph);
97
83
  }
84
+ //# sourceMappingURL=graph-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-generator.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-generator.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAiDH,4CAiBC;AAKD,wCAYC;AAKD,sCAGC;AAzFD,uCAIoB;AAEpB;;GAEG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAS,EAAE,CAAC,CAAC;AAE9C;;GAEG;AACH,SAAS,wBAAwB,CAAC,aAAmC;IACjE,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,+BAA+B;IAC/B,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,WAAW,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC1B,0DAA0D;gBAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAC3C,IAAI,KAAK,EAAE,CAAC;oBACR,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxB,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,yCAAyC;IACzC,IAAI,aAAa,CAAC,oBAAoB,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC1F,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,oBAAoB,EAAE,CAAC;YACnD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,gBAAgB;IAClC,MAAM,YAAY,GAAG,MAAM,IAAA,gCAAuB,GAAE,CAAC;IACrD,MAAM,cAAc,GAAG,IAAA,kDAAyC,EAAC,YAAY,CAAC,CAAC;IAC/E,MAAM,OAAO,GAA6B,EAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjF,0CAA0C;QAC1C,IAAI,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACrC,SAAS;QACb,CAAC;QAED,4DAA4D;QAC5D,MAAM,IAAI,GAAG,wBAAwB,CAAC,aAAa,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,QAAkC;IAC7D,MAAM,MAAM,GAA6B,EAAE,CAAC;IAE5C,KAAK,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,4EAA4E;QAC5E,MAAM,eAAe,GAAG,WAAW,CAAC;QACpC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAEpC,MAAM,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC;IAC9C,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,aAAa;IAC/B,MAAM,QAAQ,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC1C,OAAO,cAAc,CAAC,QAAQ,CAAC,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Graph Generator\n *\n * Generates dependency graph from project.json files in the workspace.\n * Reads build.dependsOn and implicitDependencies to determine project relationships.\n */\n\nimport {\n createProjectGraphAsync,\n readProjectsConfigurationFromProjectGraph,\n ProjectConfiguration,\n} from '@nx/devkit';\n\n/**\n * Projects to exclude from graph validation (tools, configs, etc.)\n */\nconst EXCLUDED_PROJECTS = new Set<string>([]);\n\n/**\n * Extract project dependencies from project.json's build.dependsOn and implicitDependencies\n */\nfunction extractBuildDependencies(projectConfig: ProjectConfiguration): string[] {\n const deps: string[] = [];\n\n // 1. Read from build.dependsOn\n const buildTarget = projectConfig.targets?.['build'];\n if (buildTarget && buildTarget.dependsOn) {\n for (const dep of buildTarget.dependsOn) {\n if (typeof dep === 'string') {\n // Format: \"project-name:build\" or just \"build\" (for self)\n const match = dep.match(/^([^:]+):build$/);\n if (match) {\n deps.push(match[1]);\n }\n }\n }\n }\n\n // 2. Also read from implicitDependencies\n if (projectConfig.implicitDependencies && Array.isArray(projectConfig.implicitDependencies)) {\n for (const dep of projectConfig.implicitDependencies) {\n if (typeof dep === 'string' && !deps.includes(dep)) {\n deps.push(dep);\n }\n }\n }\n\n return deps.sort();\n}\n\n/**\n * Generate raw dependency graph from project.json files\n * Returns: { projectName: [dependencyNames] }\n */\nexport async function generateRawGraph(): Promise<Record<string, string[]>> {\n const projectGraph = await createProjectGraphAsync();\n const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);\n const rawDeps: Record<string, string[]> = {};\n\n for (const [projectName, projectConfig] of Object.entries(projectsConfig.projects)) {\n // Skip excluded projects (tools, plugins)\n if (EXCLUDED_PROJECTS.has(projectName)) {\n continue;\n }\n\n // Extract dependencies from build.dependsOn in project.json\n const deps = extractBuildDependencies(projectConfig);\n rawDeps[projectName] = deps;\n }\n\n return rawDeps;\n}\n\n/**\n * Transform project names (sorting dependencies only - no scope transformation)\n */\nexport function transformGraph(rawGraph: Record<string, string[]>): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n\n for (const [projectName, deps] of Object.entries(rawGraph)) {\n // Use project names as-is - don't force @webpieces scope on client projects\n const transformedName = projectName;\n const transformedDeps = deps.sort();\n\n result[transformedName] = transformedDeps;\n }\n\n return result;\n}\n\n/**\n * Generate complete dependency graph with transformations\n */\nexport async function generateGraph(): Promise<Record<string, string[]>> {\n const rawGraph = await generateRawGraph();\n return transformGraph(rawGraph);\n}\n"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Graph Loader
3
+ *
4
+ * Handles loading and saving the blessed dependency graph file.
5
+ * The graph is stored at architecture/dependencies.json in the workspace root.
6
+ */
7
+ import type { EnhancedGraph } from './graph-sorter';
8
+ /**
9
+ * Default path for the dependencies file (relative to workspace root)
10
+ */
11
+ export declare const DEFAULT_GRAPH_PATH = "architecture/dependencies.json";
12
+ /**
13
+ * Load the blessed graph from disk
14
+ *
15
+ * @param workspaceRoot - Absolute path to workspace root
16
+ * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
17
+ * @returns The blessed graph, or null if file doesn't exist
18
+ */
19
+ export declare function loadBlessedGraph(workspaceRoot: string, graphPath?: string): EnhancedGraph | null;
20
+ /**
21
+ * Save the graph to disk
22
+ *
23
+ * @param graph - The graph to save
24
+ * @param workspaceRoot - Absolute path to workspace root
25
+ * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
26
+ */
27
+ export declare function saveGraph(graph: EnhancedGraph, workspaceRoot: string, graphPath?: string): void;
28
+ /**
29
+ * Check if the graph file exists
30
+ */
31
+ export declare function graphFileExists(workspaceRoot: string, graphPath?: string): boolean;
@@ -1,20 +1,23 @@
1
+ "use strict";
1
2
  /**
2
3
  * Graph Loader
3
4
  *
4
5
  * Handles loading and saving the blessed dependency graph file.
5
6
  * The graph is stored at architecture/dependencies.json in the workspace root.
6
7
  */
7
-
8
- import * as fs from 'fs';
9
- import * as path from 'path';
10
- import type { EnhancedGraph } from './graph-sorter';
11
- import { toError } from '../toError';
12
-
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DEFAULT_GRAPH_PATH = void 0;
10
+ exports.loadBlessedGraph = loadBlessedGraph;
11
+ exports.saveGraph = saveGraph;
12
+ exports.graphFileExists = graphFileExists;
13
+ const tslib_1 = require("tslib");
14
+ const fs = tslib_1.__importStar(require("fs"));
15
+ const path = tslib_1.__importStar(require("path"));
16
+ const toError_1 = require("../toError");
13
17
  /**
14
18
  * Default path for the dependencies file (relative to workspace root)
15
19
  */
16
- export const DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';
17
-
20
+ exports.DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';
18
21
  /**
19
22
  * Load the blessed graph from disk
20
23
  *
@@ -22,44 +25,37 @@ export const DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';
22
25
  * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
23
26
  * @returns The blessed graph, or null if file doesn't exist
24
27
  */
25
- export function loadBlessedGraph(
26
- workspaceRoot: string,
27
- graphPath: string = DEFAULT_GRAPH_PATH
28
- ): EnhancedGraph | null {
28
+ function loadBlessedGraph(workspaceRoot, graphPath = exports.DEFAULT_GRAPH_PATH) {
29
29
  const fullPath = path.join(workspaceRoot, graphPath);
30
-
31
30
  if (!fs.existsSync(fullPath)) {
32
31
  return null;
33
32
  }
34
-
35
33
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
36
34
  try {
37
35
  const content = fs.readFileSync(fullPath, 'utf-8');
38
- return JSON.parse(content) as EnhancedGraph;
39
- } catch (err: unknown) {
40
- const error = toError(err);
36
+ return JSON.parse(content);
37
+ }
38
+ catch (err) {
39
+ const error = (0, toError_1.toError)(err);
41
40
  throw new Error(`Failed to load graph from ${fullPath}: ${error.message}`);
42
41
  }
43
42
  }
44
-
45
43
  /**
46
44
  * Format a graph as JSON with multi-line arrays for readability
47
45
  */
48
- function formatGraphJson(graph: EnhancedGraph): string {
49
- const lines: string[] = ['{'];
46
+ function formatGraphJson(graph) {
47
+ const lines = ['{'];
50
48
  const keys = Object.keys(graph).sort();
51
-
52
49
  keys.forEach((key, index) => {
53
50
  const entry = graph[key];
54
51
  const isLast = index === keys.length - 1;
55
52
  const comma = isLast ? '' : ',';
56
-
57
53
  lines.push(` "${key}": {`);
58
54
  lines.push(` "level": ${entry.level},`);
59
-
60
55
  if (entry.dependsOn.length === 0) {
61
56
  lines.push(` "dependsOn": []`);
62
- } else {
57
+ }
58
+ else {
63
59
  lines.push(` "dependsOn": [`);
64
60
  entry.dependsOn.forEach((dep, depIndex) => {
65
61
  const depComma = depIndex === entry.dependsOn.length - 1 ? '' : ',';
@@ -67,15 +63,11 @@ function formatGraphJson(graph: EnhancedGraph): string {
67
63
  });
68
64
  lines.push(` ]`);
69
65
  }
70
-
71
66
  lines.push(` }${comma}`);
72
-
73
67
  });
74
-
75
68
  lines.push('}');
76
69
  return lines.join('\n') + '\n';
77
70
  }
78
-
79
71
  /**
80
72
  * Save the graph to disk
81
73
  *
@@ -83,37 +75,27 @@ function formatGraphJson(graph: EnhancedGraph): string {
83
75
  * @param workspaceRoot - Absolute path to workspace root
84
76
  * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
85
77
  */
86
- export function saveGraph(
87
- graph: EnhancedGraph,
88
- workspaceRoot: string,
89
- graphPath: string = DEFAULT_GRAPH_PATH
90
- ): void {
78
+ function saveGraph(graph, workspaceRoot, graphPath = exports.DEFAULT_GRAPH_PATH) {
91
79
  const fullPath = path.join(workspaceRoot, graphPath);
92
80
  const dir = path.dirname(fullPath);
93
-
94
81
  // Ensure directory exists
95
82
  if (!fs.existsSync(dir)) {
96
83
  fs.mkdirSync(dir, { recursive: true });
97
84
  }
98
-
99
85
  // Sort keys for deterministic output
100
- const sortedGraph: EnhancedGraph = {};
86
+ const sortedGraph = {};
101
87
  const sortedKeys = Object.keys(graph).sort();
102
88
  for (const key of sortedKeys) {
103
89
  sortedGraph[key] = graph[key];
104
90
  }
105
-
106
91
  const content = formatGraphJson(sortedGraph);
107
92
  fs.writeFileSync(fullPath, content, 'utf-8');
108
93
  }
109
-
110
94
  /**
111
95
  * Check if the graph file exists
112
96
  */
113
- export function graphFileExists(
114
- workspaceRoot: string,
115
- graphPath: string = DEFAULT_GRAPH_PATH
116
- ): boolean {
97
+ function graphFileExists(workspaceRoot, graphPath = exports.DEFAULT_GRAPH_PATH) {
117
98
  const fullPath = path.join(workspaceRoot, graphPath);
118
99
  return fs.existsSync(fullPath);
119
100
  }
101
+ //# sourceMappingURL=graph-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-loader.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Loader\n *\n * Handles loading and saving the blessed dependency graph file.\n * The graph is stored at architecture/dependencies.json in the workspace root.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { EnhancedGraph } from './graph-sorter';\nimport { toError } from '../toError';\n\n/**\n * Default path for the dependencies file (relative to workspace root)\n */\nexport const DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';\n\n/**\n * Load the blessed graph from disk\n *\n * @param workspaceRoot - Absolute path to workspace root\n * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)\n * @returns The blessed graph, or null if file doesn't exist\n */\nexport function loadBlessedGraph(\n workspaceRoot: string,\n graphPath: string = DEFAULT_GRAPH_PATH\n): EnhancedGraph | null {\n const fullPath = path.join(workspaceRoot, graphPath);\n\n if (!fs.existsSync(fullPath)) {\n return null;\n }\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const content = fs.readFileSync(fullPath, 'utf-8');\n return JSON.parse(content) as EnhancedGraph;\n } catch (err: unknown) {\n const error = toError(err);\n throw new Error(`Failed to load graph from ${fullPath}: ${error.message}`);\n }\n}\n\n/**\n * Format a graph as JSON with multi-line arrays for readability\n */\nfunction formatGraphJson(graph: EnhancedGraph): string {\n const lines: string[] = ['{'];\n const keys = Object.keys(graph).sort();\n\n keys.forEach((key, index) => {\n const entry = graph[key];\n const isLast = index === keys.length - 1;\n const comma = isLast ? '' : ',';\n\n lines.push(` \"${key}\": {`);\n lines.push(` \"level\": ${entry.level},`);\n\n if (entry.dependsOn.length === 0) {\n lines.push(` \"dependsOn\": []`);\n } else {\n lines.push(` \"dependsOn\": [`);\n entry.dependsOn.forEach((dep, depIndex) => {\n const depComma = depIndex === entry.dependsOn.length - 1 ? '' : ',';\n lines.push(` \"${dep}\"${depComma}`);\n });\n lines.push(` ]`);\n }\n\n lines.push(` }${comma}`);\n\n });\n\n lines.push('}');\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Save the graph to disk\n *\n * @param graph - The graph to save\n * @param workspaceRoot - Absolute path to workspace root\n * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)\n */\nexport function saveGraph(\n graph: EnhancedGraph,\n workspaceRoot: string,\n graphPath: string = DEFAULT_GRAPH_PATH\n): void {\n const fullPath = path.join(workspaceRoot, graphPath);\n const dir = path.dirname(fullPath);\n\n // Ensure directory exists\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Sort keys for deterministic output\n const sortedGraph: EnhancedGraph = {};\n const sortedKeys = Object.keys(graph).sort();\n for (const key of sortedKeys) {\n sortedGraph[key] = graph[key];\n }\n\n const content = formatGraphJson(sortedGraph);\n fs.writeFileSync(fullPath, content, 'utf-8');\n}\n\n/**\n * Check if the graph file exists\n */\nexport function graphFileExists(\n workspaceRoot: string,\n graphPath: string = DEFAULT_GRAPH_PATH\n): boolean {\n const fullPath = path.join(workspaceRoot, graphPath);\n return fs.existsSync(fullPath);\n}\n"]}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Graph Sorter
3
+ *
4
+ * Performs topological sorting on the dependency graph to:
5
+ * 1. Detect circular dependencies (fails if cycle found)
6
+ * 2. Assign level numbers to each project (level 0 = no deps, level 1 = depends on level 0, etc.)
7
+ * 3. Group projects into layers for deterministic ordering
8
+ */
9
+ /**
10
+ * Graph entry with level metadata
11
+ */
12
+ export interface GraphEntry {
13
+ level: number;
14
+ dependsOn: string[];
15
+ }
16
+ /**
17
+ * Enhanced graph format with level information
18
+ */
19
+ export type EnhancedGraph = Record<string, GraphEntry>;
20
+ /**
21
+ * Compute topological layers for dependency graph using Kahn's algorithm
22
+ *
23
+ * Projects are grouped into layers where each layer only depends on previous layers.
24
+ * Throws an error if a circular dependency is detected.
25
+ *
26
+ * @param graph - Dependency graph { project: [deps] }
27
+ * @returns Array of layers, each containing sorted project names
28
+ */
29
+ export declare function computeTopologicalLayers(graph: Record<string, string[]>): string[][];
30
+ /**
31
+ * Sort graph in topological order with alphabetical sorting within layers
32
+ * Returns enhanced format with level metadata
33
+ *
34
+ * @param graph - Unsorted dependency graph { project: [deps] }
35
+ * @returns Sorted graph with level metadata { project: { level: number, dependsOn: [deps] } }
36
+ */
37
+ export declare function sortGraphTopologically(graph: Record<string, string[]>): EnhancedGraph;