enterprise-ui-architect-cli 1.0.0 → 1.1.0
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/assets/SKILL.md +45 -0
- package/assets/commands/verify-imports.ts +209 -0
- package/assets/data/anti-patterns.csv +1 -0
- package/assets/data/pre-delivery-checklist.csv +3 -0
- package/assets/src/index.ts +101 -0
- package/dist/commands/verify-imports.d.ts +7 -0
- package/dist/commands/verify-imports.d.ts.map +1 -0
- package/dist/commands/verify-imports.js +174 -0
- package/dist/commands/verify-imports.js.map +1 -0
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/assets/SKILL.md
CHANGED
|
@@ -512,6 +512,51 @@ Avoid:
|
|
|
512
512
|
- business-specific styling inside generic UI primitives
|
|
513
513
|
- using `item` prop on MUI v7 `Grid`
|
|
514
514
|
|
|
515
|
+
## Package Import Discipline
|
|
516
|
+
|
|
517
|
+
When adding or modifying imports in any module:
|
|
518
|
+
|
|
519
|
+
### 1. Verify Package Exists
|
|
520
|
+
Before writing a new import statement, check `package.json` (and `package-lock.json` / `yarn.lock` / `pnpm-lock.yaml`) to confirm the package is installed.
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
# Quick check
|
|
524
|
+
grep '"package-name"' package.json
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### 2. If Package Is Missing
|
|
528
|
+
**Do NOT install automatically.** Present the user with:
|
|
529
|
+
- The missing package name
|
|
530
|
+
- The import path that triggered the need
|
|
531
|
+
- The recommended install command
|
|
532
|
+
- Ask for explicit confirmation
|
|
533
|
+
|
|
534
|
+
Example prompt:
|
|
535
|
+
```
|
|
536
|
+
⚠️ Missing package: @mui/x-data-grid
|
|
537
|
+
Required by: src/features/admin/components/DataTable.tsx
|
|
538
|
+
Install: npm install @mui/x-data-grid
|
|
539
|
+
Proceed? (y/n)
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 3. Install Only After Confirmation
|
|
543
|
+
If user confirms, install with the project's package manager:
|
|
544
|
+
- Detect from lockfile: `package-lock.json` → npm, `yarn.lock` → yarn, `pnpm-lock.yaml` → pnpm
|
|
545
|
+
- Respect existing version constraints in `package.json`
|
|
546
|
+
- Update lockfile alongside install
|
|
547
|
+
|
|
548
|
+
### 4. Post-Install Verification
|
|
549
|
+
After install:
|
|
550
|
+
1. Run TypeScript check: `npx tsc --noEmit`
|
|
551
|
+
2. Verify the import resolves without error
|
|
552
|
+
3. Confirm no unused imports were added (tree-shaking friendly)
|
|
553
|
+
|
|
554
|
+
### 5. Anti-Pattern
|
|
555
|
+
- Adding imports for packages not in `package.json`
|
|
556
|
+
- Auto-installing without user consent
|
|
557
|
+
- Using different package managers within the same repo
|
|
558
|
+
- Adding unused dependencies "just in case"
|
|
559
|
+
|
|
515
560
|
## Keyboard Navigation
|
|
516
561
|
MUI components require specific keyboard patterns:
|
|
517
562
|
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync, statSync } from "fs";
|
|
2
|
+
import { resolve, dirname, join, extname } from "path";
|
|
3
|
+
|
|
4
|
+
interface VerifyOptions {
|
|
5
|
+
srcDir: string;
|
|
6
|
+
packageJsonPath: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface ImportInfo {
|
|
10
|
+
path: string;
|
|
11
|
+
line: number;
|
|
12
|
+
source: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function findPackageJson(startDir: string): string | null {
|
|
16
|
+
let dir = resolve(startDir);
|
|
17
|
+
while (dir !== dirname(dir)) {
|
|
18
|
+
const pkgPath = join(dir, "package.json");
|
|
19
|
+
if (existsSync(pkgPath)) return pkgPath;
|
|
20
|
+
dir = dirname(dir);
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function findTsConfig(startDir: string): string | null {
|
|
26
|
+
let dir = resolve(startDir);
|
|
27
|
+
while (dir !== dirname(dir)) {
|
|
28
|
+
const tsPath = join(dir, "tsconfig.json");
|
|
29
|
+
if (existsSync(tsPath)) return tsPath;
|
|
30
|
+
dir = dirname(dir);
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getInstalledPackages(packageJsonPath: string): Set<string> {
|
|
36
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
37
|
+
const deps = Object.keys(pkg.dependencies || {});
|
|
38
|
+
const devDeps = Object.keys(pkg.devDependencies || {});
|
|
39
|
+
return new Set([...deps, ...devDeps]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getPathAliases(tsConfigPath: string): string[] {
|
|
43
|
+
try {
|
|
44
|
+
const tsconfig = JSON.parse(readFileSync(tsConfigPath, "utf-8"));
|
|
45
|
+
const paths = tsconfig.compilerOptions?.paths || {};
|
|
46
|
+
return Object.keys(paths);
|
|
47
|
+
} catch {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function isPathAlias(source: string, aliases: string[]): boolean {
|
|
53
|
+
for (const alias of aliases) {
|
|
54
|
+
// Convert tsconfig glob to regex: @core/* → /^@core\//
|
|
55
|
+
const prefix = alias.replace(/\/\*$/, "");
|
|
56
|
+
if (alias.endsWith("/*")) {
|
|
57
|
+
if (source === prefix || source.startsWith(prefix + "/")) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
if (source === alias) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getSourceFiles(dir: string): string[] {
|
|
70
|
+
const results: string[] = [];
|
|
71
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
72
|
+
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
const fullPath = join(dir, entry.name);
|
|
75
|
+
|
|
76
|
+
if (entry.isDirectory()) {
|
|
77
|
+
if (
|
|
78
|
+
entry.name === "node_modules" ||
|
|
79
|
+
entry.name === "dist" ||
|
|
80
|
+
entry.name === "build" ||
|
|
81
|
+
entry.name === ".next" ||
|
|
82
|
+
entry.name.startsWith(".")
|
|
83
|
+
) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
results.push(...getSourceFiles(fullPath));
|
|
87
|
+
} else if (entry.isFile()) {
|
|
88
|
+
const ext = extname(entry.name);
|
|
89
|
+
if (ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx") {
|
|
90
|
+
results.push(fullPath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function extractImports(filePath: string): ImportInfo[] {
|
|
99
|
+
const content = readFileSync(filePath, "utf-8");
|
|
100
|
+
const lines = content.split("\n");
|
|
101
|
+
const imports: ImportInfo[] = [];
|
|
102
|
+
|
|
103
|
+
const importRegex = /^(?:import\s+.*?from\s+|import\s*\(|require\s*\()["']([^"';]+)["'];?/;
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < lines.length; i++) {
|
|
106
|
+
const line = lines[i].trim();
|
|
107
|
+
const match = importRegex.exec(line);
|
|
108
|
+
if (match) {
|
|
109
|
+
imports.push({ path: filePath, line: i + 1, source: match[1] });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return imports;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolvePackageName(source: string): string | null {
|
|
117
|
+
if (source.startsWith(".") || source.startsWith("/")) return null;
|
|
118
|
+
if (source.startsWith("node:")) return null;
|
|
119
|
+
if (source.startsWith("@/")) return null;
|
|
120
|
+
|
|
121
|
+
if (source.startsWith("@")) {
|
|
122
|
+
const parts = source.split("/");
|
|
123
|
+
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const idx = source.indexOf("/");
|
|
127
|
+
return idx > 0 ? source.slice(0, idx) : source;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function detectPackageManager(lockFiles: string[]): "npm" | "yarn" | "pnpm" | "unknown" {
|
|
131
|
+
if (lockFiles.some((f) => f.endsWith("pnpm-lock.yaml"))) return "pnpm";
|
|
132
|
+
if (lockFiles.some((f) => f.endsWith("yarn.lock"))) return "yarn";
|
|
133
|
+
if (lockFiles.some((f) => f.endsWith("package-lock.json"))) return "npm";
|
|
134
|
+
return "unknown";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function verifyImportsCommand(options: Partial<VerifyOptions> = {}): void {
|
|
138
|
+
const srcDir = options.srcDir || process.cwd();
|
|
139
|
+
const packageJsonPath = options.packageJsonPath || findPackageJson(srcDir);
|
|
140
|
+
|
|
141
|
+
if (!packageJsonPath) {
|
|
142
|
+
console.error("❌ package.json not found. Run this from a project root.");
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const installed = getInstalledPackages(packageJsonPath);
|
|
147
|
+
const projectRoot = dirname(packageJsonPath);
|
|
148
|
+
|
|
149
|
+
const tsConfigPath = findTsConfig(srcDir);
|
|
150
|
+
const pathAliases = tsConfigPath ? getPathAliases(tsConfigPath) : [];
|
|
151
|
+
|
|
152
|
+
const lockFiles = ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"].map((f) =>
|
|
153
|
+
join(projectRoot, f)
|
|
154
|
+
);
|
|
155
|
+
const existingLocks = lockFiles.filter((f) => existsSync(f));
|
|
156
|
+
const pkgManager = detectPackageManager(existingLocks);
|
|
157
|
+
|
|
158
|
+
const files = getSourceFiles(srcDir);
|
|
159
|
+
|
|
160
|
+
const allImports: ImportInfo[] = [];
|
|
161
|
+
for (const file of files) {
|
|
162
|
+
allImports.push(...extractImports(file));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const missing: Map<string, ImportInfo[]> = new Map();
|
|
166
|
+
|
|
167
|
+
for (const imp of allImports) {
|
|
168
|
+
if (isPathAlias(imp.source, pathAliases)) continue;
|
|
169
|
+
|
|
170
|
+
const pkg = resolvePackageName(imp.source);
|
|
171
|
+
if (!pkg) continue;
|
|
172
|
+
if (installed.has(pkg)) continue;
|
|
173
|
+
|
|
174
|
+
const list = missing.get(pkg) || [];
|
|
175
|
+
list.push(imp);
|
|
176
|
+
missing.set(pkg, list);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (missing.size === 0) {
|
|
180
|
+
console.log(`✅ All imports resolve to installed packages (${allImports.length} imports checked).`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(`⚠️ Found ${missing.size} missing package(s):\n`);
|
|
185
|
+
|
|
186
|
+
for (const [pkg, imports] of missing) {
|
|
187
|
+
console.log(` 📦 ${pkg}`);
|
|
188
|
+
console.log(` Used in:`);
|
|
189
|
+
for (const imp of imports.slice(0, 3)) {
|
|
190
|
+
const relPath = imp.path.replace(projectRoot + "/", "");
|
|
191
|
+
console.log(` - ${relPath}:${imp.line} → import from "${imp.source}"`);
|
|
192
|
+
}
|
|
193
|
+
if (imports.length > 3) {
|
|
194
|
+
console.log(` ... and ${imports.length - 3} more`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const installCmd =
|
|
198
|
+
pkgManager === "pnpm"
|
|
199
|
+
? `pnpm add ${pkg}`
|
|
200
|
+
: pkgManager === "yarn"
|
|
201
|
+
? `yarn add ${pkg}`
|
|
202
|
+
: `npm install ${pkg}`;
|
|
203
|
+
|
|
204
|
+
console.log(` Install: ${installCmd}\n`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
console.log(`Run the install command(s) above, then re-run this check.\n`);
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
@@ -53,3 +53,4 @@ id,area,bad_pattern,why_bad,fix
|
|
|
53
53
|
52,Charts,No empty state for charts with zero data points,Empty chart looks broken or crashes chart library,Show empty state illustration or zero baseline when no data
|
|
54
54
|
53,Charts,Using real-time updates without transition animations,Jarring jumps in chart data poor perceived performance,Use Recharts animation or smooth transitions for live data updates
|
|
55
55
|
54,Charts,Fetching all chart data on every small filter change,Excessive API calls slow performance backend overload,Debounce filter changes use TanStack Query staleTime cache filter state in URL
|
|
56
|
+
56,Dependencies,Adding new imports without verifying the package is installed,Build fails in CI or for teammates TypeScript errors runtime crashes silent failures,Always check package.json before adding an import If package is missing ask user for confirmation then install with the correct package manager
|
|
@@ -34,3 +34,6 @@ id,page_type,check,severity,why_it_matters
|
|
|
34
34
|
33,auth,Password visibility toggle present,Medium,Improves UX for password entry
|
|
35
35
|
34,auth,Form focuses first input on load,Low,Small UX improvement for keyboard users
|
|
36
36
|
35,auth,Social login buttons match brand colors,Low,Visual consistency with external services
|
|
37
|
+
36,dependencies,All new imports resolve to installed packages,High,Missing packages break builds and CI
|
|
38
|
+
37,dependencies,No unused imports or dead dependencies,Medium,Bloats bundle and confuses developers
|
|
39
|
+
38,dependencies,Package manager lockfile is in sync with package.json,High,Prevents inconsistent installs across environments
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { initCommand } from "./commands/init.js";
|
|
3
|
+
import { verifyImportsCommand } from "./commands/verify-imports.js";
|
|
4
|
+
|
|
5
|
+
function showHelp(): void {
|
|
6
|
+
console.log(`
|
|
7
|
+
Enterprise UI Architect CLI
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
enterprise-ui init [options]
|
|
11
|
+
enterprise-ui verify-imports [options]
|
|
12
|
+
|
|
13
|
+
Commands:
|
|
14
|
+
init Install skill into AI coding assistants
|
|
15
|
+
verify-imports Scan source files and report missing npm packages
|
|
16
|
+
|
|
17
|
+
Options:
|
|
18
|
+
--ai <assistant> Target AI assistant: cursor, claude, windsurf, copilot, codex, all (default: all)
|
|
19
|
+
--offline Use local assets without network (default: false)
|
|
20
|
+
--src <dir> Source directory to scan (default: current directory)
|
|
21
|
+
--help Show this help
|
|
22
|
+
--version Show version
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
enterprise-ui init --ai cursor
|
|
26
|
+
enterprise-ui init --ai claude --offline
|
|
27
|
+
enterprise-ui verify-imports
|
|
28
|
+
enterprise-ui verify-imports --src ./src
|
|
29
|
+
`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseArgs(args: string[]): {
|
|
33
|
+
command?: string;
|
|
34
|
+
ai: string;
|
|
35
|
+
offline: boolean;
|
|
36
|
+
srcDir: string;
|
|
37
|
+
help: boolean;
|
|
38
|
+
version: boolean;
|
|
39
|
+
} {
|
|
40
|
+
const result = { ai: "all", offline: false, srcDir: process.cwd(), help: false, version: false };
|
|
41
|
+
let command: string | undefined;
|
|
42
|
+
|
|
43
|
+
for (let i = 0; i < args.length; i++) {
|
|
44
|
+
const arg = args[i];
|
|
45
|
+
if (arg === "init" || arg === "verify-imports") {
|
|
46
|
+
command = arg;
|
|
47
|
+
} else if (arg === "--ai" && i + 1 < args.length) {
|
|
48
|
+
result.ai = args[++i];
|
|
49
|
+
} else if (arg === "--offline") {
|
|
50
|
+
result.offline = true;
|
|
51
|
+
} else if (arg === "--src" && i + 1 < args.length) {
|
|
52
|
+
result.srcDir = args[++i];
|
|
53
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
54
|
+
result.help = true;
|
|
55
|
+
} else if (arg === "--version" || arg === "-v") {
|
|
56
|
+
result.version = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { command, ...result };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function main(): number {
|
|
64
|
+
const args = process.argv.slice(2);
|
|
65
|
+
const parsed = parseArgs(args);
|
|
66
|
+
|
|
67
|
+
if (parsed.version) {
|
|
68
|
+
console.log("1.0.0");
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (parsed.help || args.length === 0) {
|
|
73
|
+
showHelp();
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (parsed.command === "init") {
|
|
78
|
+
try {
|
|
79
|
+
initCommand({ ai: parsed.ai, offline: parsed.offline });
|
|
80
|
+
return 0;
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.error(`Error: ${(err as Error).message}`);
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (parsed.command === "verify-imports") {
|
|
88
|
+
try {
|
|
89
|
+
verifyImportsCommand({ srcDir: parsed.srcDir });
|
|
90
|
+
return 0;
|
|
91
|
+
} catch (err) {
|
|
92
|
+
console.error(`Error: ${(err as Error).message}`);
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.error(`Unknown command. Run --help for usage.`);
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
process.exit(main());
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-imports.d.ts","sourceRoot":"","sources":["../../src/commands/verify-imports.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB;AAkID,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,IAAI,CAwE/E"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
2
|
+
import { resolve, dirname, join, extname } from "path";
|
|
3
|
+
function findPackageJson(startDir) {
|
|
4
|
+
let dir = resolve(startDir);
|
|
5
|
+
while (dir !== dirname(dir)) {
|
|
6
|
+
const pkgPath = join(dir, "package.json");
|
|
7
|
+
if (existsSync(pkgPath))
|
|
8
|
+
return pkgPath;
|
|
9
|
+
dir = dirname(dir);
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
function findTsConfig(startDir) {
|
|
14
|
+
let dir = resolve(startDir);
|
|
15
|
+
while (dir !== dirname(dir)) {
|
|
16
|
+
const tsPath = join(dir, "tsconfig.json");
|
|
17
|
+
if (existsSync(tsPath))
|
|
18
|
+
return tsPath;
|
|
19
|
+
dir = dirname(dir);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function getInstalledPackages(packageJsonPath) {
|
|
24
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
25
|
+
const deps = Object.keys(pkg.dependencies || {});
|
|
26
|
+
const devDeps = Object.keys(pkg.devDependencies || {});
|
|
27
|
+
return new Set([...deps, ...devDeps]);
|
|
28
|
+
}
|
|
29
|
+
function getPathAliases(tsConfigPath) {
|
|
30
|
+
try {
|
|
31
|
+
const tsconfig = JSON.parse(readFileSync(tsConfigPath, "utf-8"));
|
|
32
|
+
const paths = tsconfig.compilerOptions?.paths || {};
|
|
33
|
+
return Object.keys(paths);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isPathAlias(source, aliases) {
|
|
40
|
+
for (const alias of aliases) {
|
|
41
|
+
// Convert tsconfig glob to regex: @core/* → /^@core\//
|
|
42
|
+
const prefix = alias.replace(/\/\*$/, "");
|
|
43
|
+
if (alias.endsWith("/*")) {
|
|
44
|
+
if (source === prefix || source.startsWith(prefix + "/")) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (source === alias) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
function getSourceFiles(dir) {
|
|
57
|
+
const results = [];
|
|
58
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
const fullPath = join(dir, entry.name);
|
|
61
|
+
if (entry.isDirectory()) {
|
|
62
|
+
if (entry.name === "node_modules" ||
|
|
63
|
+
entry.name === "dist" ||
|
|
64
|
+
entry.name === "build" ||
|
|
65
|
+
entry.name === ".next" ||
|
|
66
|
+
entry.name.startsWith(".")) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
results.push(...getSourceFiles(fullPath));
|
|
70
|
+
}
|
|
71
|
+
else if (entry.isFile()) {
|
|
72
|
+
const ext = extname(entry.name);
|
|
73
|
+
if (ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx") {
|
|
74
|
+
results.push(fullPath);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
function extractImports(filePath) {
|
|
81
|
+
const content = readFileSync(filePath, "utf-8");
|
|
82
|
+
const lines = content.split("\n");
|
|
83
|
+
const imports = [];
|
|
84
|
+
const importRegex = /^(?:import\s+.*?from\s+|import\s*\(|require\s*\()["']([^"';]+)["'];?/;
|
|
85
|
+
for (let i = 0; i < lines.length; i++) {
|
|
86
|
+
const line = lines[i].trim();
|
|
87
|
+
const match = importRegex.exec(line);
|
|
88
|
+
if (match) {
|
|
89
|
+
imports.push({ path: filePath, line: i + 1, source: match[1] });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return imports;
|
|
93
|
+
}
|
|
94
|
+
function resolvePackageName(source) {
|
|
95
|
+
if (source.startsWith(".") || source.startsWith("/"))
|
|
96
|
+
return null;
|
|
97
|
+
if (source.startsWith("node:"))
|
|
98
|
+
return null;
|
|
99
|
+
if (source.startsWith("@/"))
|
|
100
|
+
return null;
|
|
101
|
+
if (source.startsWith("@")) {
|
|
102
|
+
const parts = source.split("/");
|
|
103
|
+
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;
|
|
104
|
+
}
|
|
105
|
+
const idx = source.indexOf("/");
|
|
106
|
+
return idx > 0 ? source.slice(0, idx) : source;
|
|
107
|
+
}
|
|
108
|
+
function detectPackageManager(lockFiles) {
|
|
109
|
+
if (lockFiles.some((f) => f.endsWith("pnpm-lock.yaml")))
|
|
110
|
+
return "pnpm";
|
|
111
|
+
if (lockFiles.some((f) => f.endsWith("yarn.lock")))
|
|
112
|
+
return "yarn";
|
|
113
|
+
if (lockFiles.some((f) => f.endsWith("package-lock.json")))
|
|
114
|
+
return "npm";
|
|
115
|
+
return "unknown";
|
|
116
|
+
}
|
|
117
|
+
export function verifyImportsCommand(options = {}) {
|
|
118
|
+
const srcDir = options.srcDir || process.cwd();
|
|
119
|
+
const packageJsonPath = options.packageJsonPath || findPackageJson(srcDir);
|
|
120
|
+
if (!packageJsonPath) {
|
|
121
|
+
console.error("❌ package.json not found. Run this from a project root.");
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const installed = getInstalledPackages(packageJsonPath);
|
|
125
|
+
const projectRoot = dirname(packageJsonPath);
|
|
126
|
+
const tsConfigPath = findTsConfig(srcDir);
|
|
127
|
+
const pathAliases = tsConfigPath ? getPathAliases(tsConfigPath) : [];
|
|
128
|
+
const lockFiles = ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"].map((f) => join(projectRoot, f));
|
|
129
|
+
const existingLocks = lockFiles.filter((f) => existsSync(f));
|
|
130
|
+
const pkgManager = detectPackageManager(existingLocks);
|
|
131
|
+
const files = getSourceFiles(srcDir);
|
|
132
|
+
const allImports = [];
|
|
133
|
+
for (const file of files) {
|
|
134
|
+
allImports.push(...extractImports(file));
|
|
135
|
+
}
|
|
136
|
+
const missing = new Map();
|
|
137
|
+
for (const imp of allImports) {
|
|
138
|
+
if (isPathAlias(imp.source, pathAliases))
|
|
139
|
+
continue;
|
|
140
|
+
const pkg = resolvePackageName(imp.source);
|
|
141
|
+
if (!pkg)
|
|
142
|
+
continue;
|
|
143
|
+
if (installed.has(pkg))
|
|
144
|
+
continue;
|
|
145
|
+
const list = missing.get(pkg) || [];
|
|
146
|
+
list.push(imp);
|
|
147
|
+
missing.set(pkg, list);
|
|
148
|
+
}
|
|
149
|
+
if (missing.size === 0) {
|
|
150
|
+
console.log(`✅ All imports resolve to installed packages (${allImports.length} imports checked).`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
console.log(`⚠️ Found ${missing.size} missing package(s):\n`);
|
|
154
|
+
for (const [pkg, imports] of missing) {
|
|
155
|
+
console.log(` 📦 ${pkg}`);
|
|
156
|
+
console.log(` Used in:`);
|
|
157
|
+
for (const imp of imports.slice(0, 3)) {
|
|
158
|
+
const relPath = imp.path.replace(projectRoot + "/", "");
|
|
159
|
+
console.log(` - ${relPath}:${imp.line} → import from "${imp.source}"`);
|
|
160
|
+
}
|
|
161
|
+
if (imports.length > 3) {
|
|
162
|
+
console.log(` ... and ${imports.length - 3} more`);
|
|
163
|
+
}
|
|
164
|
+
const installCmd = pkgManager === "pnpm"
|
|
165
|
+
? `pnpm add ${pkg}`
|
|
166
|
+
: pkgManager === "yarn"
|
|
167
|
+
? `yarn add ${pkg}`
|
|
168
|
+
: `npm install ${pkg}`;
|
|
169
|
+
console.log(` Install: ${installCmd}\n`);
|
|
170
|
+
}
|
|
171
|
+
console.log(`Run the install command(s) above, then re-run this check.\n`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=verify-imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-imports.js","sourceRoot":"","sources":["../../src/commands/verify-imports.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { initCommand } from "./commands/init.js";
|
|
3
|
+
import { verifyImportsCommand } from "./commands/verify-imports.js";
|
|
3
4
|
function showHelp() {
|
|
4
5
|
console.log(`
|
|
5
6
|
Enterprise UI Architect CLI
|
|
6
7
|
|
|
7
8
|
Usage:
|
|
8
9
|
enterprise-ui init [options]
|
|
10
|
+
enterprise-ui verify-imports [options]
|
|
11
|
+
|
|
12
|
+
Commands:
|
|
13
|
+
init Install skill into AI coding assistants
|
|
14
|
+
verify-imports Scan source files and report missing npm packages
|
|
9
15
|
|
|
10
16
|
Options:
|
|
11
17
|
--ai <assistant> Target AI assistant: cursor, claude, windsurf, copilot, codex, all (default: all)
|
|
12
18
|
--offline Use local assets without network (default: false)
|
|
19
|
+
--src <dir> Source directory to scan (default: current directory)
|
|
13
20
|
--help Show this help
|
|
14
21
|
--version Show version
|
|
15
22
|
|
|
16
23
|
Examples:
|
|
17
24
|
enterprise-ui init --ai cursor
|
|
18
25
|
enterprise-ui init --ai claude --offline
|
|
19
|
-
enterprise-ui
|
|
26
|
+
enterprise-ui verify-imports
|
|
27
|
+
enterprise-ui verify-imports --src ./src
|
|
20
28
|
`);
|
|
21
29
|
}
|
|
22
30
|
function parseArgs(args) {
|
|
23
|
-
const result = { ai: "all", offline: false, help: false, version: false };
|
|
31
|
+
const result = { ai: "all", offline: false, srcDir: process.cwd(), help: false, version: false };
|
|
24
32
|
let command;
|
|
25
33
|
for (let i = 0; i < args.length; i++) {
|
|
26
34
|
const arg = args[i];
|
|
27
|
-
if (arg === "init") {
|
|
28
|
-
command =
|
|
35
|
+
if (arg === "init" || arg === "verify-imports") {
|
|
36
|
+
command = arg;
|
|
29
37
|
}
|
|
30
38
|
else if (arg === "--ai" && i + 1 < args.length) {
|
|
31
39
|
result.ai = args[++i];
|
|
@@ -33,6 +41,9 @@ function parseArgs(args) {
|
|
|
33
41
|
else if (arg === "--offline") {
|
|
34
42
|
result.offline = true;
|
|
35
43
|
}
|
|
44
|
+
else if (arg === "--src" && i + 1 < args.length) {
|
|
45
|
+
result.srcDir = args[++i];
|
|
46
|
+
}
|
|
36
47
|
else if (arg === "--help" || arg === "-h") {
|
|
37
48
|
result.help = true;
|
|
38
49
|
}
|
|
@@ -63,10 +74,18 @@ function main() {
|
|
|
63
74
|
return 1;
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
if (parsed.command === "verify-imports") {
|
|
78
|
+
try {
|
|
79
|
+
verifyImportsCommand({ srcDir: parsed.srcDir });
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.error(`Error: ${err.message}`);
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
69
86
|
}
|
|
87
|
+
console.error(`Unknown command. Run --help for usage.`);
|
|
88
|
+
return 1;
|
|
70
89
|
}
|
|
71
90
|
process.exit(main());
|
|
72
91
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|