@kb-labs/devkit 1.0.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/.cursorrules +32 -0
- package/.github/CODEOWNERS +2 -0
- package/.github/actions/setup-node-pnpm/action.yml +47 -0
- package/.github/workflow-templates/ci.yml +13 -0
- package/.github/workflow-templates/drift-check.yml +10 -0
- package/.github/workflow-templates/profiles-validate.yml +16 -0
- package/.github/workflow-templates/release.yml +8 -0
- package/.github/workflows/ci-reusable.yml +131 -0
- package/.github/workflows/drift-check-reusable.yml +23 -0
- package/.github/workflows/fixtures.yml +74 -0
- package/.github/workflows/profiles-validate-reusable.yml +67 -0
- package/.github/workflows/release-reusable.yml +50 -0
- package/.vscode/settings.json +23 -0
- package/AGENTS.md +130 -0
- package/LICENSE +21 -0
- package/README.md +1542 -0
- package/agents/devkit-maintainer/context.globs +15 -0
- package/agents/devkit-maintainer/permissions.yml +17 -0
- package/agents/devkit-maintainer/prompt.md +28 -0
- package/agents/devkit-maintainer/runbook.md +31 -0
- package/agents/docs-crafter/prompt.md +24 -0
- package/agents/docs-crafter/runbook.md +18 -0
- package/agents/release-manager/context.globs +7 -0
- package/agents/release-manager/prompt.md +27 -0
- package/agents/release-manager/runbook.md +17 -0
- package/agents/test-generator/context.globs +7 -0
- package/agents/test-generator/prompt.md +27 -0
- package/agents/test-generator/runbook.md +18 -0
- package/bin/devkit-architecture.mjs +1225 -0
- package/bin/devkit-build-order.mjs +500 -0
- package/bin/devkit-check-build-readiness.mjs +222 -0
- package/bin/devkit-check-commands.mjs +394 -0
- package/bin/devkit-check-configs.mjs +461 -0
- package/bin/devkit-check-deprecated.mjs +532 -0
- package/bin/devkit-check-duplicates.mjs +431 -0
- package/bin/devkit-check-exports.mjs +561 -0
- package/bin/devkit-check-imports.mjs +712 -0
- package/bin/devkit-check-paths.mjs +670 -0
- package/bin/devkit-check-scripts.mjs +335 -0
- package/bin/devkit-check-structure.mjs +495 -0
- package/bin/devkit-check-types.mjs +450 -0
- package/bin/devkit-ci.mjs +261 -0
- package/bin/devkit-core-gate.mjs +225 -0
- package/bin/devkit-fix-deps.mjs +1169 -0
- package/bin/devkit-freshness.mjs +199 -0
- package/bin/devkit-health.mjs +489 -0
- package/bin/devkit-migrate-configs.mjs +370 -0
- package/bin/devkit-paths.mjs +192 -0
- package/bin/devkit-stats.mjs +453 -0
- package/bin/devkit-sync.mjs +12 -0
- package/bin/devkit-tsup-external.mjs +148 -0
- package/bin/devkit-types-audit.mjs +615 -0
- package/bin/devkit-types-order.mjs +637 -0
- package/bin/devkit-validate-naming.mjs +203 -0
- package/bin/devkit-visualize.mjs +452 -0
- package/bin/kb-devkit-qa-history.mjs +453 -0
- package/bin/kb-devkit-qa.mjs +915 -0
- package/eslint/node.js +134 -0
- package/eslint/react.js +260 -0
- package/package.json +186 -0
- package/prettier/index.json +10 -0
- package/sync/index.mjs +693 -0
- package/templates/configs/README.md +306 -0
- package/templates/configs/eslint.config.js +27 -0
- package/templates/configs/package.json.bin +25 -0
- package/templates/configs/package.json.lib +30 -0
- package/templates/configs/tsconfig.build.json +15 -0
- package/templates/configs/tsconfig.json +9 -0
- package/templates/configs/tsup.config.bin.ts +34 -0
- package/templates/configs/tsup.config.cli.ts +41 -0
- package/templates/configs/tsup.config.dual.ts +46 -0
- package/templates/configs/tsup.config.ts +36 -0
- package/templates/package-json/README.md +290 -0
- package/templates/package-json/package.json.bin.template +40 -0
- package/templates/package-json/package.json.template +45 -0
- package/tsconfig/base.json +21 -0
- package/tsconfig/cli.json +12 -0
- package/tsconfig/dist/__tests__/cache.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/cache.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/cache.spec.js +85 -0
- package/tsconfig/dist/__tests__/cache.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/fs-atomic.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/fs-atomic.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/fs-atomic.spec.js +153 -0
- package/tsconfig/dist/__tests__/fs-atomic.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/init-workspace.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/init-workspace.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/init-workspace.spec.js +99 -0
- package/tsconfig/dist/__tests__/init-workspace.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/kb-error.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/kb-error.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/kb-error.spec.js +190 -0
- package/tsconfig/dist/__tests__/kb-error.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/preset-lockfile.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/preset-lockfile.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/preset-lockfile.spec.js +142 -0
- package/tsconfig/dist/__tests__/preset-lockfile.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/product-config-profiles.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/product-config-profiles.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/product-config-profiles.spec.js +100 -0
- package/tsconfig/dist/__tests__/product-config-profiles.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/product-config.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/product-config.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/product-config.spec.js +298 -0
- package/tsconfig/dist/__tests__/product-config.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/runtime.spec.d.ts +2 -0
- package/tsconfig/dist/__tests__/runtime.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/runtime.spec.js +127 -0
- package/tsconfig/dist/__tests__/runtime.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/upsert-lockfile.spec.d.ts +6 -0
- package/tsconfig/dist/__tests__/upsert-lockfile.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/upsert-lockfile.spec.js +251 -0
- package/tsconfig/dist/__tests__/upsert-lockfile.spec.js.map +1 -0
- package/tsconfig/dist/__tests__/validate-config.spec.d.ts +2 -0
- package/tsconfig/dist/__tests__/validate-config.spec.d.ts.map +1 -0
- package/tsconfig/dist/__tests__/validate-config.spec.js +14 -0
- package/tsconfig/dist/__tests__/validate-config.spec.js.map +1 -0
- package/tsconfig/dist/api/init-workspace.d.ts +10 -0
- package/tsconfig/dist/api/init-workspace.d.ts.map +1 -0
- package/tsconfig/dist/api/init-workspace.js +191 -0
- package/tsconfig/dist/api/init-workspace.js.map +1 -0
- package/tsconfig/dist/api/product-config.d.ts +21 -0
- package/tsconfig/dist/api/product-config.d.ts.map +1 -0
- package/tsconfig/dist/api/product-config.js +192 -0
- package/tsconfig/dist/api/product-config.js.map +1 -0
- package/tsconfig/dist/api/read-config.d.ts +22 -0
- package/tsconfig/dist/api/read-config.d.ts.map +1 -0
- package/tsconfig/dist/api/read-config.js +105 -0
- package/tsconfig/dist/api/read-config.js.map +1 -0
- package/tsconfig/dist/api/upsert-lockfile.d.ts +10 -0
- package/tsconfig/dist/api/upsert-lockfile.d.ts.map +1 -0
- package/tsconfig/dist/api/upsert-lockfile.js +63 -0
- package/tsconfig/dist/api/upsert-lockfile.js.map +1 -0
- package/tsconfig/dist/cache/fs-cache.d.ts +38 -0
- package/tsconfig/dist/cache/fs-cache.d.ts.map +1 -0
- package/tsconfig/dist/cache/fs-cache.js +142 -0
- package/tsconfig/dist/cache/fs-cache.js.map +1 -0
- package/tsconfig/dist/errors/kb-error.d.ts +32 -0
- package/tsconfig/dist/errors/kb-error.d.ts.map +1 -0
- package/tsconfig/dist/errors/kb-error.js +54 -0
- package/tsconfig/dist/errors/kb-error.js.map +1 -0
- package/tsconfig/dist/fs/__tests__/fs.spec.d.ts +2 -0
- package/tsconfig/dist/fs/__tests__/fs.spec.d.ts.map +1 -0
- package/tsconfig/dist/fs/__tests__/fs.spec.js +22 -0
- package/tsconfig/dist/fs/__tests__/fs.spec.js.map +1 -0
- package/tsconfig/dist/fs/fs.d.ts +6 -0
- package/tsconfig/dist/fs/fs.d.ts.map +1 -0
- package/tsconfig/dist/fs/fs.js +12 -0
- package/tsconfig/dist/fs/fs.js.map +1 -0
- package/tsconfig/dist/fs/index.d.ts +2 -0
- package/tsconfig/dist/fs/index.d.ts.map +1 -0
- package/tsconfig/dist/fs/index.js +2 -0
- package/tsconfig/dist/fs/index.js.map +1 -0
- package/tsconfig/dist/hash/config-hash.d.ts +17 -0
- package/tsconfig/dist/hash/config-hash.d.ts.map +1 -0
- package/tsconfig/dist/hash/config-hash.js +55 -0
- package/tsconfig/dist/hash/config-hash.js.map +1 -0
- package/tsconfig/dist/index.d.ts +5 -0
- package/tsconfig/dist/index.d.ts.map +1 -0
- package/tsconfig/dist/index.js +5 -0
- package/tsconfig/dist/index.js.map +1 -0
- package/tsconfig/dist/lockfile/lockfile.d.ts +54 -0
- package/tsconfig/dist/lockfile/lockfile.d.ts.map +1 -0
- package/tsconfig/dist/lockfile/lockfile.js +141 -0
- package/tsconfig/dist/lockfile/lockfile.js.map +1 -0
- package/tsconfig/dist/logging/__tests__/logger.spec.d.ts +2 -0
- package/tsconfig/dist/logging/__tests__/logger.spec.d.ts.map +1 -0
- package/tsconfig/dist/logging/__tests__/logger.spec.js +65 -0
- package/tsconfig/dist/logging/__tests__/logger.spec.js.map +1 -0
- package/tsconfig/dist/logging/__tests__/redaction.spec.d.ts +2 -0
- package/tsconfig/dist/logging/__tests__/redaction.spec.d.ts.map +1 -0
- package/tsconfig/dist/logging/__tests__/redaction.spec.js +34 -0
- package/tsconfig/dist/logging/__tests__/redaction.spec.js.map +1 -0
- package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.d.ts +2 -0
- package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.d.ts.map +1 -0
- package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.js +90 -0
- package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.js.map +1 -0
- package/tsconfig/dist/logging/index.d.ts +6 -0
- package/tsconfig/dist/logging/index.d.ts.map +1 -0
- package/tsconfig/dist/logging/index.js +6 -0
- package/tsconfig/dist/logging/index.js.map +1 -0
- package/tsconfig/dist/logging/logger.d.ts +9 -0
- package/tsconfig/dist/logging/logger.d.ts.map +1 -0
- package/tsconfig/dist/logging/logger.js +101 -0
- package/tsconfig/dist/logging/logger.js.map +1 -0
- package/tsconfig/dist/logging/redaction.d.ts +7 -0
- package/tsconfig/dist/logging/redaction.d.ts.map +1 -0
- package/tsconfig/dist/logging/redaction.js +23 -0
- package/tsconfig/dist/logging/redaction.js.map +1 -0
- package/tsconfig/dist/logging/sinks/json.d.ts +4 -0
- package/tsconfig/dist/logging/sinks/json.d.ts.map +1 -0
- package/tsconfig/dist/logging/sinks/json.js +23 -0
- package/tsconfig/dist/logging/sinks/json.js.map +1 -0
- package/tsconfig/dist/logging/sinks/stdout.d.ts +3 -0
- package/tsconfig/dist/logging/sinks/stdout.d.ts.map +1 -0
- package/tsconfig/dist/logging/sinks/stdout.js +24 -0
- package/tsconfig/dist/logging/sinks/stdout.js.map +1 -0
- package/tsconfig/dist/logging/types/index.d.ts +2 -0
- package/tsconfig/dist/logging/types/index.d.ts.map +1 -0
- package/tsconfig/dist/logging/types/index.js +2 -0
- package/tsconfig/dist/logging/types/index.js.map +1 -0
- package/tsconfig/dist/logging/types/types.d.ts +37 -0
- package/tsconfig/dist/logging/types/types.d.ts.map +1 -0
- package/tsconfig/dist/logging/types/types.js +2 -0
- package/tsconfig/dist/logging/types/types.js.map +1 -0
- package/tsconfig/dist/merge/layered-merge.d.ts +16 -0
- package/tsconfig/dist/merge/layered-merge.d.ts.map +1 -0
- package/tsconfig/dist/merge/layered-merge.js +97 -0
- package/tsconfig/dist/merge/layered-merge.js.map +1 -0
- package/tsconfig/dist/preset/resolve-preset.d.ts +29 -0
- package/tsconfig/dist/preset/resolve-preset.d.ts.map +1 -0
- package/tsconfig/dist/preset/resolve-preset.js +104 -0
- package/tsconfig/dist/preset/resolve-preset.js.map +1 -0
- package/tsconfig/dist/repo/__tests__/repo.spec.d.ts +2 -0
- package/tsconfig/dist/repo/__tests__/repo.spec.d.ts.map +1 -0
- package/tsconfig/dist/repo/__tests__/repo.spec.js +25 -0
- package/tsconfig/dist/repo/__tests__/repo.spec.js.map +1 -0
- package/tsconfig/dist/repo/index.d.ts +2 -0
- package/tsconfig/dist/repo/index.d.ts.map +1 -0
- package/tsconfig/dist/repo/index.js +2 -0
- package/tsconfig/dist/repo/index.js.map +1 -0
- package/tsconfig/dist/repo/repo.d.ts +6 -0
- package/tsconfig/dist/repo/repo.d.ts.map +1 -0
- package/tsconfig/dist/repo/repo.js +25 -0
- package/tsconfig/dist/repo/repo.js.map +1 -0
- package/tsconfig/dist/runtime/index.d.ts +2 -0
- package/tsconfig/dist/runtime/index.d.ts.map +1 -0
- package/tsconfig/dist/runtime/index.js +2 -0
- package/tsconfig/dist/runtime/index.js.map +1 -0
- package/tsconfig/dist/runtime/runtime.d.ts +46 -0
- package/tsconfig/dist/runtime/runtime.d.ts.map +1 -0
- package/tsconfig/dist/runtime/runtime.js +126 -0
- package/tsconfig/dist/runtime/runtime.js.map +1 -0
- package/tsconfig/dist/tsconfig.tools.tsbuildinfo +1 -0
- package/tsconfig/dist/tsconfig.tsbuildinfo +1 -0
- package/tsconfig/dist/types/index.d.ts +2 -0
- package/tsconfig/dist/types/index.d.ts.map +1 -0
- package/tsconfig/dist/types/index.js +2 -0
- package/tsconfig/dist/types/index.js.map +1 -0
- package/tsconfig/dist/types/init.d.ts +34 -0
- package/tsconfig/dist/types/init.d.ts.map +1 -0
- package/tsconfig/dist/types/init.js +6 -0
- package/tsconfig/dist/types/init.js.map +1 -0
- package/tsconfig/dist/types/preset.d.ts +27 -0
- package/tsconfig/dist/types/preset.d.ts.map +1 -0
- package/tsconfig/dist/types/preset.js +6 -0
- package/tsconfig/dist/types/preset.js.map +1 -0
- package/tsconfig/dist/types/types.d.ts +6 -0
- package/tsconfig/dist/types/types.d.ts.map +1 -0
- package/tsconfig/dist/types/types.js +2 -0
- package/tsconfig/dist/types/types.js.map +1 -0
- package/tsconfig/dist/utils/__tests__/env.spec.d.ts +2 -0
- package/tsconfig/dist/utils/__tests__/env.spec.d.ts.map +1 -0
- package/tsconfig/dist/utils/__tests__/env.spec.js +33 -0
- package/tsconfig/dist/utils/__tests__/env.spec.js.map +1 -0
- package/tsconfig/dist/utils/env.d.ts +7 -0
- package/tsconfig/dist/utils/env.d.ts.map +1 -0
- package/tsconfig/dist/utils/env.js +25 -0
- package/tsconfig/dist/utils/env.js.map +1 -0
- package/tsconfig/dist/utils/fs-atomic.d.ts +15 -0
- package/tsconfig/dist/utils/fs-atomic.d.ts.map +1 -0
- package/tsconfig/dist/utils/fs-atomic.js +45 -0
- package/tsconfig/dist/utils/fs-atomic.js.map +1 -0
- package/tsconfig/dist/utils/index.d.ts +3 -0
- package/tsconfig/dist/utils/index.d.ts.map +1 -0
- package/tsconfig/dist/utils/index.js +3 -0
- package/tsconfig/dist/utils/index.js.map +1 -0
- package/tsconfig/dist/utils/paths.d.ts +21 -0
- package/tsconfig/dist/utils/paths.d.ts.map +1 -0
- package/tsconfig/dist/utils/paths.js +32 -0
- package/tsconfig/dist/utils/paths.js.map +1 -0
- package/tsconfig/dist/utils/product-normalize.d.ts +27 -0
- package/tsconfig/dist/utils/product-normalize.d.ts.map +1 -0
- package/tsconfig/dist/utils/product-normalize.js +45 -0
- package/tsconfig/dist/utils/product-normalize.js.map +1 -0
- package/tsconfig/dist/validation/validate-config.d.ts +7 -0
- package/tsconfig/dist/validation/validate-config.d.ts.map +1 -0
- package/tsconfig/dist/validation/validate-config.js +22 -0
- package/tsconfig/dist/validation/validate-config.js.map +1 -0
- package/tsconfig/lib.json +13 -0
- package/tsconfig/node.json +12 -0
- package/tsconfig/react-app.json +8 -0
- package/tsconfig/react-lib.json +8 -0
- package/tsconfig/test.json +15 -0
- package/tsup/bin.js +172 -0
- package/tsup/dual.js +155 -0
- package/tsup/external-sync.mjs +41 -0
- package/tsup/external.mjs +109 -0
- package/tsup/node.js +65 -0
- package/tsup/react-lib.js +18 -0
- package/tsup/sdk.js +118 -0
- package/vite/react-app.js +50 -0
- package/vitest/node.js +37 -0
- package/vitest/react.js +39 -0
- package/vitest/vitest-setup.ts +9 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @kb-labs/devkit - Path Validator
|
|
5
|
+
*
|
|
6
|
+
* Validates all paths and references in the monorepo:
|
|
7
|
+
* 1. package.json dependencies pointing to non-existent packages
|
|
8
|
+
* 2. package.json exports pointing to non-existent files
|
|
9
|
+
* 3. package.json bin pointing to non-existent scripts
|
|
10
|
+
* 4. tsconfig.json extends/references pointing to non-existent configs
|
|
11
|
+
* 5. Workspace protocol references to non-existent packages
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* kb-devkit-check-paths # Check all paths
|
|
15
|
+
* kb-devkit-check-paths --package=cli-core # Check specific package
|
|
16
|
+
* kb-devkit-check-paths --fix # Auto-fix what's possible
|
|
17
|
+
* kb-devkit-check-paths --json # JSON output
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import fs from 'node:fs';
|
|
21
|
+
import path from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
|
|
24
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
|
|
26
|
+
// ANSI colors
|
|
27
|
+
const colors = {
|
|
28
|
+
reset: '\x1b[0m',
|
|
29
|
+
red: '\x1b[31m',
|
|
30
|
+
green: '\x1b[32m',
|
|
31
|
+
yellow: '\x1b[33m',
|
|
32
|
+
blue: '\x1b[34m',
|
|
33
|
+
magenta: '\x1b[35m',
|
|
34
|
+
cyan: '\x1b[36m',
|
|
35
|
+
gray: '\x1b[90m',
|
|
36
|
+
bold: '\x1b[1m',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function log(message, color = 'reset') {
|
|
40
|
+
if (!options.json) {
|
|
41
|
+
console.log(`${colors[color] || colors.reset}${message}${colors.reset}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Parse CLI arguments
|
|
46
|
+
const args = process.argv.slice(2);
|
|
47
|
+
const options = {
|
|
48
|
+
fix: args.includes('--fix'),
|
|
49
|
+
json: args.includes('--json'),
|
|
50
|
+
verbose: args.includes('--verbose') || args.includes('-v'),
|
|
51
|
+
package: args.find((arg) => arg.startsWith('--package='))?.split('=')[1],
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Find all packages in monorepo
|
|
56
|
+
*/
|
|
57
|
+
function findPackages(rootDir, filterPackage) {
|
|
58
|
+
const packages = [];
|
|
59
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
60
|
+
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
if (!entry.isDirectory() || !entry.name.startsWith('kb-labs-')) {continue;}
|
|
63
|
+
|
|
64
|
+
const repoPath = path.join(rootDir, entry.name);
|
|
65
|
+
const packagesDir = path.join(repoPath, 'packages');
|
|
66
|
+
|
|
67
|
+
if (!fs.existsSync(packagesDir)) {continue;}
|
|
68
|
+
|
|
69
|
+
const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });
|
|
70
|
+
|
|
71
|
+
for (const pkgDir of packageDirs) {
|
|
72
|
+
if (!pkgDir.isDirectory()) {continue;}
|
|
73
|
+
|
|
74
|
+
if (filterPackage && pkgDir.name !== filterPackage) {continue;}
|
|
75
|
+
|
|
76
|
+
const packageJsonPath = path.join(packagesDir, pkgDir.name, 'package.json');
|
|
77
|
+
|
|
78
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
79
|
+
packages.push({
|
|
80
|
+
path: packageJsonPath,
|
|
81
|
+
dir: path.join(packagesDir, pkgDir.name),
|
|
82
|
+
repo: entry.name,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return packages;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get all workspace package names
|
|
93
|
+
*/
|
|
94
|
+
function getWorkspacePackageNames(packages) {
|
|
95
|
+
const names = new Set();
|
|
96
|
+
|
|
97
|
+
for (const pkg of packages) {
|
|
98
|
+
try {
|
|
99
|
+
const packageJson = JSON.parse(fs.readFileSync(pkg.path, 'utf-8'));
|
|
100
|
+
if (packageJson.name) {
|
|
101
|
+
names.add(packageJson.name);
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
// Skip invalid package.json
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return names;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Check if a path exists (file or directory)
|
|
113
|
+
*/
|
|
114
|
+
function pathExists(basePath, relativePath) {
|
|
115
|
+
const fullPath = path.resolve(basePath, relativePath);
|
|
116
|
+
|
|
117
|
+
// Try exact path
|
|
118
|
+
if (fs.existsSync(fullPath)) {
|
|
119
|
+
return { exists: true, resolved: fullPath };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Try with common extensions
|
|
123
|
+
const extensions = ['.js', '.mjs', '.cjs', '.ts', '.tsx', '.json', '.d.ts'];
|
|
124
|
+
for (const ext of extensions) {
|
|
125
|
+
if (fs.existsSync(fullPath + ext)) {
|
|
126
|
+
return { exists: true, resolved: fullPath + ext };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Try index files
|
|
131
|
+
const indexFiles = ['index.js', 'index.mjs', 'index.ts', 'index.tsx'];
|
|
132
|
+
for (const indexFile of indexFiles) {
|
|
133
|
+
const indexPath = path.join(fullPath, indexFile);
|
|
134
|
+
if (fs.existsSync(indexPath)) {
|
|
135
|
+
return { exists: true, resolved: indexPath };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { exists: false, resolved: fullPath };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check package.json dependencies
|
|
144
|
+
*/
|
|
145
|
+
function checkDependencies(packageJson, packageDir, workspaceNames) {
|
|
146
|
+
const issues = [];
|
|
147
|
+
|
|
148
|
+
const allDeps = {
|
|
149
|
+
...packageJson.dependencies,
|
|
150
|
+
...packageJson.devDependencies,
|
|
151
|
+
...packageJson.peerDependencies,
|
|
152
|
+
...packageJson.optionalDependencies,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
for (const [dep, version] of Object.entries(allDeps)) {
|
|
156
|
+
// Check workspace: protocol references
|
|
157
|
+
if (version.startsWith('workspace:')) {
|
|
158
|
+
if (dep.startsWith('@kb-labs/') && !workspaceNames.has(dep)) {
|
|
159
|
+
issues.push({
|
|
160
|
+
type: 'missing_workspace_package',
|
|
161
|
+
severity: 'error',
|
|
162
|
+
path: `dependencies.${dep}`,
|
|
163
|
+
message: `Workspace package "${dep}" does not exist in monorepo`,
|
|
164
|
+
value: version,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Check link: protocol references
|
|
170
|
+
if (version.startsWith('link:')) {
|
|
171
|
+
const linkPath = version.replace('link:', '');
|
|
172
|
+
const { exists } = pathExists(packageDir, linkPath);
|
|
173
|
+
|
|
174
|
+
if (!exists) {
|
|
175
|
+
issues.push({
|
|
176
|
+
type: 'broken_link',
|
|
177
|
+
severity: 'error',
|
|
178
|
+
path: `dependencies.${dep}`,
|
|
179
|
+
message: `Link path does not exist: ${linkPath}`,
|
|
180
|
+
value: version,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Check file: protocol references
|
|
186
|
+
if (version.startsWith('file:')) {
|
|
187
|
+
const filePath = version.replace('file:', '');
|
|
188
|
+
const { exists } = pathExists(packageDir, filePath);
|
|
189
|
+
|
|
190
|
+
if (!exists) {
|
|
191
|
+
issues.push({
|
|
192
|
+
type: 'broken_file_ref',
|
|
193
|
+
severity: 'error',
|
|
194
|
+
path: `dependencies.${dep}`,
|
|
195
|
+
message: `File path does not exist: ${filePath}`,
|
|
196
|
+
value: version,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return issues;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Check package.json exports
|
|
207
|
+
*/
|
|
208
|
+
function checkExports(packageJson, packageDir) {
|
|
209
|
+
const issues = [];
|
|
210
|
+
|
|
211
|
+
if (!packageJson.exports) {return issues;}
|
|
212
|
+
|
|
213
|
+
function checkExportPath(exportKey, exportValue, parentPath = 'exports') {
|
|
214
|
+
if (typeof exportValue === 'string') {
|
|
215
|
+
// Skip conditions like "import", "require", "types", "default"
|
|
216
|
+
if (exportValue.startsWith('./') || exportValue.startsWith('../')) {
|
|
217
|
+
// Skip glob patterns (e.g., ./dist/*)
|
|
218
|
+
if (exportValue.includes('*')) {return;}
|
|
219
|
+
|
|
220
|
+
const { exists } = pathExists(packageDir, exportValue);
|
|
221
|
+
|
|
222
|
+
if (!exists) {
|
|
223
|
+
// Check if it's a dist file (expected to not exist before build)
|
|
224
|
+
const isDist = exportValue.includes('/dist/') || exportValue.startsWith('./dist/');
|
|
225
|
+
|
|
226
|
+
issues.push({
|
|
227
|
+
type: 'broken_export',
|
|
228
|
+
severity: isDist ? 'warning' : 'error',
|
|
229
|
+
path: `${parentPath}["${exportKey}"]`,
|
|
230
|
+
message: `Export path does not exist: ${exportValue}${isDist ? ' (needs build)' : ''}`,
|
|
231
|
+
value: exportValue,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} else if (typeof exportValue === 'object' && exportValue !== null) {
|
|
236
|
+
// Handle conditional exports
|
|
237
|
+
for (const [key, value] of Object.entries(exportValue)) {
|
|
238
|
+
checkExportPath(key, value, `${parentPath}["${exportKey}"]`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
for (const [key, value] of Object.entries(packageJson.exports)) {
|
|
244
|
+
checkExportPath(key, value);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return issues;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Check package.json bin
|
|
252
|
+
*/
|
|
253
|
+
function checkBin(packageJson, packageDir) {
|
|
254
|
+
const issues = [];
|
|
255
|
+
|
|
256
|
+
if (!packageJson.bin) {return issues;}
|
|
257
|
+
|
|
258
|
+
const bins = typeof packageJson.bin === 'string'
|
|
259
|
+
? { [packageJson.name]: packageJson.bin }
|
|
260
|
+
: packageJson.bin;
|
|
261
|
+
|
|
262
|
+
for (const [binName, binPath] of Object.entries(bins)) {
|
|
263
|
+
const { exists } = pathExists(packageDir, binPath);
|
|
264
|
+
|
|
265
|
+
if (!exists) {
|
|
266
|
+
issues.push({
|
|
267
|
+
type: 'broken_bin',
|
|
268
|
+
severity: 'error',
|
|
269
|
+
path: `bin["${binName}"]`,
|
|
270
|
+
message: `Bin script does not exist: ${binPath}`,
|
|
271
|
+
value: binPath,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return issues;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Check package.json main, module, types fields
|
|
281
|
+
*/
|
|
282
|
+
function checkEntryPoints(packageJson, packageDir) {
|
|
283
|
+
const issues = [];
|
|
284
|
+
|
|
285
|
+
const entryFields = ['main', 'module', 'types', 'typings', 'browser'];
|
|
286
|
+
|
|
287
|
+
for (const field of entryFields) {
|
|
288
|
+
if (packageJson[field]) {
|
|
289
|
+
const { exists } = pathExists(packageDir, packageJson[field]);
|
|
290
|
+
|
|
291
|
+
if (!exists) {
|
|
292
|
+
// Check if it's a dist file that might not exist yet
|
|
293
|
+
const isDist = packageJson[field].includes('/dist/') || packageJson[field].startsWith('dist/');
|
|
294
|
+
|
|
295
|
+
issues.push({
|
|
296
|
+
type: 'broken_entry_point',
|
|
297
|
+
severity: isDist ? 'warning' : 'error',
|
|
298
|
+
path: field,
|
|
299
|
+
message: `Entry point does not exist: ${packageJson[field]}${isDist ? ' (may need build)' : ''}`,
|
|
300
|
+
value: packageJson[field],
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return issues;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Check tsconfig.json
|
|
311
|
+
*/
|
|
312
|
+
function checkTsconfig(packageDir) {
|
|
313
|
+
const issues = [];
|
|
314
|
+
const tsconfigPath = path.join(packageDir, 'tsconfig.json');
|
|
315
|
+
|
|
316
|
+
if (!fs.existsSync(tsconfigPath)) {return issues;}
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const content = fs.readFileSync(tsconfigPath, 'utf-8');
|
|
320
|
+
// Remove comments for JSON parsing (but not // inside strings)
|
|
321
|
+
// Only remove // comments that are not inside quotes
|
|
322
|
+
const cleanContent = content
|
|
323
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove /* */ comments
|
|
324
|
+
.replace(/^(\s*)\/\/.*$/gm, '$1'); // Remove // comments at start of lines only
|
|
325
|
+
const tsconfig = JSON.parse(cleanContent);
|
|
326
|
+
|
|
327
|
+
// Check extends (can be string or array in TS 5.0+)
|
|
328
|
+
if (tsconfig.extends) {
|
|
329
|
+
const extendsList = Array.isArray(tsconfig.extends)
|
|
330
|
+
? tsconfig.extends
|
|
331
|
+
: [tsconfig.extends];
|
|
332
|
+
|
|
333
|
+
for (let i = 0; i < extendsList.length; i++) {
|
|
334
|
+
const extendsPath = extendsList[i];
|
|
335
|
+
|
|
336
|
+
// Skip non-string values or node_modules references
|
|
337
|
+
if (typeof extendsPath !== 'string') {continue;}
|
|
338
|
+
if (extendsPath.startsWith('@') || extendsPath.includes('node_modules')) {continue;}
|
|
339
|
+
|
|
340
|
+
const { exists } = pathExists(packageDir, extendsPath);
|
|
341
|
+
|
|
342
|
+
if (!exists) {
|
|
343
|
+
const pathLabel = Array.isArray(tsconfig.extends)
|
|
344
|
+
? `tsconfig.json:extends[${i}]`
|
|
345
|
+
: 'tsconfig.json:extends';
|
|
346
|
+
|
|
347
|
+
issues.push({
|
|
348
|
+
type: 'broken_tsconfig_extends',
|
|
349
|
+
severity: 'error',
|
|
350
|
+
path: pathLabel,
|
|
351
|
+
message: `tsconfig extends path does not exist: ${extendsPath}`,
|
|
352
|
+
value: extendsPath,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Check references
|
|
359
|
+
if (tsconfig.references && Array.isArray(tsconfig.references)) {
|
|
360
|
+
for (let i = 0; i < tsconfig.references.length; i++) {
|
|
361
|
+
const ref = tsconfig.references[i];
|
|
362
|
+
if (ref.path) {
|
|
363
|
+
const { exists } = pathExists(packageDir, ref.path);
|
|
364
|
+
|
|
365
|
+
if (!exists) {
|
|
366
|
+
issues.push({
|
|
367
|
+
type: 'broken_tsconfig_reference',
|
|
368
|
+
severity: 'error',
|
|
369
|
+
path: `tsconfig.json:references[${i}]`,
|
|
370
|
+
message: `tsconfig reference path does not exist: ${ref.path}`,
|
|
371
|
+
value: ref.path,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Check paths aliases
|
|
379
|
+
if (tsconfig.compilerOptions?.paths) {
|
|
380
|
+
for (const [alias, targets] of Object.entries(tsconfig.compilerOptions.paths)) {
|
|
381
|
+
for (let i = 0; i < targets.length; i++) {
|
|
382
|
+
const target = targets[i];
|
|
383
|
+
|
|
384
|
+
// Skip wildcards
|
|
385
|
+
if (target.includes('*')) {continue;}
|
|
386
|
+
|
|
387
|
+
const baseUrl = tsconfig.compilerOptions.baseUrl || '.';
|
|
388
|
+
const basePath = path.resolve(packageDir, baseUrl);
|
|
389
|
+
const { exists } = pathExists(basePath, target);
|
|
390
|
+
|
|
391
|
+
if (!exists) {
|
|
392
|
+
issues.push({
|
|
393
|
+
type: 'broken_tsconfig_path',
|
|
394
|
+
severity: 'warning',
|
|
395
|
+
path: `tsconfig.json:compilerOptions.paths["${alias}"][${i}]`,
|
|
396
|
+
message: `tsconfig path alias target does not exist: ${target}`,
|
|
397
|
+
value: target,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
} catch (error) {
|
|
404
|
+
issues.push({
|
|
405
|
+
type: 'invalid_tsconfig',
|
|
406
|
+
severity: 'error',
|
|
407
|
+
path: 'tsconfig.json',
|
|
408
|
+
message: `Invalid tsconfig.json: ${error.message}`,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return issues;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Check package.json files field
|
|
417
|
+
*/
|
|
418
|
+
function checkFilesField(packageJson, packageDir) {
|
|
419
|
+
const issues = [];
|
|
420
|
+
|
|
421
|
+
if (!packageJson.files || !Array.isArray(packageJson.files)) {return issues;}
|
|
422
|
+
|
|
423
|
+
for (const file of packageJson.files) {
|
|
424
|
+
// Skip glob patterns
|
|
425
|
+
if (file.includes('*')) {continue;}
|
|
426
|
+
|
|
427
|
+
const { exists } = pathExists(packageDir, file);
|
|
428
|
+
|
|
429
|
+
if (!exists) {
|
|
430
|
+
// Check if it's a dist folder
|
|
431
|
+
const isDist = file === 'dist' || file.startsWith('dist/');
|
|
432
|
+
|
|
433
|
+
issues.push({
|
|
434
|
+
type: 'broken_files_entry',
|
|
435
|
+
severity: isDist ? 'warning' : 'error',
|
|
436
|
+
path: `files`,
|
|
437
|
+
message: `File/folder in "files" field does not exist: ${file}${isDist ? ' (may need build)' : ''}`,
|
|
438
|
+
value: file,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return issues;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Check single package
|
|
448
|
+
*/
|
|
449
|
+
function checkPackage(pkg, workspaceNames) {
|
|
450
|
+
const { path: packagePath, dir: packageDir, repo } = pkg;
|
|
451
|
+
|
|
452
|
+
try {
|
|
453
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
454
|
+
const packageName = packageJson.name;
|
|
455
|
+
|
|
456
|
+
if (!packageName) {
|
|
457
|
+
return {
|
|
458
|
+
name: 'unknown',
|
|
459
|
+
dir: packageDir,
|
|
460
|
+
repo,
|
|
461
|
+
issues: [{
|
|
462
|
+
type: 'missing_name',
|
|
463
|
+
severity: 'error',
|
|
464
|
+
path: 'name',
|
|
465
|
+
message: 'package.json missing "name" field',
|
|
466
|
+
}],
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const issues = [
|
|
471
|
+
...checkDependencies(packageJson, packageDir, workspaceNames),
|
|
472
|
+
...checkExports(packageJson, packageDir),
|
|
473
|
+
...checkBin(packageJson, packageDir),
|
|
474
|
+
...checkEntryPoints(packageJson, packageDir),
|
|
475
|
+
...checkFilesField(packageJson, packageDir),
|
|
476
|
+
...checkTsconfig(packageDir),
|
|
477
|
+
];
|
|
478
|
+
|
|
479
|
+
return {
|
|
480
|
+
name: packageName,
|
|
481
|
+
dir: packageDir,
|
|
482
|
+
repo,
|
|
483
|
+
issues,
|
|
484
|
+
};
|
|
485
|
+
} catch (error) {
|
|
486
|
+
return {
|
|
487
|
+
name: 'unknown',
|
|
488
|
+
dir: packageDir,
|
|
489
|
+
repo,
|
|
490
|
+
issues: [{
|
|
491
|
+
type: 'invalid_package_json',
|
|
492
|
+
severity: 'error',
|
|
493
|
+
path: 'package.json',
|
|
494
|
+
message: `Invalid package.json: ${error.message}`,
|
|
495
|
+
}],
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Print results
|
|
502
|
+
*/
|
|
503
|
+
function printResults(results) {
|
|
504
|
+
log('\nš KB Labs Path Validator\n', 'bold');
|
|
505
|
+
|
|
506
|
+
const packagesWithIssues = results.filter(r => r.issues.length > 0);
|
|
507
|
+
const errorCount = results.reduce((sum, r) =>
|
|
508
|
+
sum + r.issues.filter(i => i.severity === 'error').length, 0);
|
|
509
|
+
const warningCount = results.reduce((sum, r) =>
|
|
510
|
+
sum + r.issues.filter(i => i.severity === 'warning').length, 0);
|
|
511
|
+
|
|
512
|
+
if (packagesWithIssues.length === 0) {
|
|
513
|
+
log('ā
All paths are valid!\n', 'green');
|
|
514
|
+
log(`Checked ${results.length} package(s)`, 'gray');
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Group by issue type
|
|
519
|
+
const byType = new Map();
|
|
520
|
+
for (const result of packagesWithIssues) {
|
|
521
|
+
for (const issue of result.issues) {
|
|
522
|
+
if (!byType.has(issue.type)) {
|
|
523
|
+
byType.set(issue.type, []);
|
|
524
|
+
}
|
|
525
|
+
byType.get(issue.type).push({ ...issue, package: result.name, repo: result.repo });
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Print by severity first - errors
|
|
530
|
+
const issueTypeNames = {
|
|
531
|
+
missing_workspace_package: 'š¦ Missing Workspace Packages',
|
|
532
|
+
broken_link: 'š Broken Link References',
|
|
533
|
+
broken_file_ref: 'š Broken File References',
|
|
534
|
+
broken_export: 'š¤ Broken Exports',
|
|
535
|
+
broken_bin: 'āļø Broken Bin Scripts',
|
|
536
|
+
broken_entry_point: 'šŖ Broken Entry Points',
|
|
537
|
+
broken_tsconfig_extends: 'š Broken tsconfig Extends',
|
|
538
|
+
broken_tsconfig_reference: 'š Broken tsconfig References',
|
|
539
|
+
broken_tsconfig_path: 'š Broken tsconfig Paths',
|
|
540
|
+
broken_files_entry: 'š Broken Files Field Entries',
|
|
541
|
+
invalid_tsconfig: 'ā Invalid tsconfig.json',
|
|
542
|
+
invalid_package_json: 'ā Invalid package.json',
|
|
543
|
+
missing_name: 'ā Missing Package Name',
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
// Print errors first
|
|
547
|
+
for (const [type, issues] of byType.entries()) {
|
|
548
|
+
const errors = issues.filter(i => i.severity === 'error');
|
|
549
|
+
if (errors.length === 0) {continue;}
|
|
550
|
+
|
|
551
|
+
log(`\n${issueTypeNames[type] || type} (${errors.length}):\n`, 'red');
|
|
552
|
+
|
|
553
|
+
// Group by repo
|
|
554
|
+
const byRepo = new Map();
|
|
555
|
+
for (const issue of errors) {
|
|
556
|
+
if (!byRepo.has(issue.repo)) {
|
|
557
|
+
byRepo.set(issue.repo, []);
|
|
558
|
+
}
|
|
559
|
+
byRepo.get(issue.repo).push(issue);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
for (const [repo, repoIssues] of byRepo.entries()) {
|
|
563
|
+
log(` ${repo}/`, 'yellow');
|
|
564
|
+
for (const issue of repoIssues) {
|
|
565
|
+
log(` ${issue.package}`, 'cyan');
|
|
566
|
+
log(` ${issue.message}`, 'gray');
|
|
567
|
+
if (issue.value && options.verbose) {
|
|
568
|
+
log(` Value: ${issue.value}`, 'gray');
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Print warnings
|
|
575
|
+
for (const [type, issues] of byType.entries()) {
|
|
576
|
+
const warnings = issues.filter(i => i.severity === 'warning');
|
|
577
|
+
if (warnings.length === 0) {continue;}
|
|
578
|
+
|
|
579
|
+
log(`\n${issueTypeNames[type] || type} (${warnings.length}) ā ļø:\n`, 'yellow');
|
|
580
|
+
|
|
581
|
+
for (const issue of warnings.slice(0, 10)) {
|
|
582
|
+
log(` ${issue.package}: ${issue.message}`, 'gray');
|
|
583
|
+
}
|
|
584
|
+
if (warnings.length > 10) {
|
|
585
|
+
log(` ... and ${warnings.length - 10} more`, 'gray');
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Summary
|
|
590
|
+
log('\n' + 'ā'.repeat(60), 'gray');
|
|
591
|
+
log('š Summary:', 'blue');
|
|
592
|
+
log(` Packages checked: ${results.length}`, 'cyan');
|
|
593
|
+
log(` Packages with issues: ${packagesWithIssues.length}`, packagesWithIssues.length > 0 ? 'yellow' : 'green');
|
|
594
|
+
log(` ā Errors: ${errorCount}`, errorCount > 0 ? 'red' : 'green');
|
|
595
|
+
log(` ā ļø Warnings: ${warningCount}`, warningCount > 0 ? 'yellow' : 'green');
|
|
596
|
+
log('', 'reset');
|
|
597
|
+
|
|
598
|
+
if (errorCount > 0) {
|
|
599
|
+
log('š” Tips:', 'blue');
|
|
600
|
+
log(' ⢠Missing workspace packages: Remove or fix the dependency', 'gray');
|
|
601
|
+
log(' ⢠Broken exports/bin: Update path or create missing file', 'gray');
|
|
602
|
+
log(' ⢠Broken entry points with "(may need build)": Run pnpm build', 'gray');
|
|
603
|
+
log(' ⢠Broken tsconfig: Fix extends/references paths', 'gray');
|
|
604
|
+
log('', 'reset');
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Main function
|
|
610
|
+
*/
|
|
611
|
+
function main() {
|
|
612
|
+
const rootDir = process.cwd();
|
|
613
|
+
|
|
614
|
+
if (!options.json) {
|
|
615
|
+
log('\nš KB Labs Path Validator\n', 'bold');
|
|
616
|
+
log('Validating all paths and references...\n', 'gray');
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const packages = findPackages(rootDir, options.package);
|
|
620
|
+
|
|
621
|
+
if (packages.length === 0) {
|
|
622
|
+
if (!options.json) {
|
|
623
|
+
log('ā ļø No KB Labs packages found', 'yellow');
|
|
624
|
+
}
|
|
625
|
+
process.exit(0);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (!options.json) {
|
|
629
|
+
log(`Found ${packages.length} package(s) to check\n`, 'gray');
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Get all workspace package names for reference validation
|
|
633
|
+
const workspaceNames = getWorkspacePackageNames(packages);
|
|
634
|
+
|
|
635
|
+
// Check all packages
|
|
636
|
+
const results = packages.map(pkg => checkPackage(pkg, workspaceNames));
|
|
637
|
+
|
|
638
|
+
if (options.json) {
|
|
639
|
+
const errorCount = results.reduce((sum, r) =>
|
|
640
|
+
sum + r.issues.filter(i => i.severity === 'error').length, 0);
|
|
641
|
+
const warningCount = results.reduce((sum, r) =>
|
|
642
|
+
sum + r.issues.filter(i => i.severity === 'warning').length, 0);
|
|
643
|
+
|
|
644
|
+
console.log(JSON.stringify({
|
|
645
|
+
totalPackages: results.length,
|
|
646
|
+
packagesWithIssues: results.filter(r => r.issues.length > 0).length,
|
|
647
|
+
errorCount,
|
|
648
|
+
warningCount,
|
|
649
|
+
issues: results
|
|
650
|
+
.filter(r => r.issues.length > 0)
|
|
651
|
+
.map(r => ({
|
|
652
|
+
package: r.name,
|
|
653
|
+
repo: r.repo,
|
|
654
|
+
issues: r.issues,
|
|
655
|
+
})),
|
|
656
|
+
}, null, 2));
|
|
657
|
+
|
|
658
|
+
process.exit(errorCount > 0 ? 1 : 0);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
printResults(results);
|
|
662
|
+
|
|
663
|
+
// Exit with error if there are errors
|
|
664
|
+
const errorCount = results.reduce((sum, r) =>
|
|
665
|
+
sum + r.issues.filter(i => i.severity === 'error').length, 0);
|
|
666
|
+
|
|
667
|
+
process.exit(errorCount > 0 ? 1 : 0);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
main();
|