@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,495 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @kb-labs/devkit - Package Structure Checker
|
|
5
|
+
*
|
|
6
|
+
* Checks for:
|
|
7
|
+
* 1. Missing README.md files
|
|
8
|
+
* 2. Missing LICENSE files
|
|
9
|
+
* 3. Required package.json fields (name, version, main, types, exports)
|
|
10
|
+
* 4. Architecture violations (e.g., domain importing from infra)
|
|
11
|
+
* 5. Inconsistent project structure
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* kb-devkit-check-structure # Check all packages
|
|
15
|
+
* kb-devkit-check-structure --package cli-core # Check specific package
|
|
16
|
+
* kb-devkit-check-structure --strict # Include warnings
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import fs from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
22
|
+
|
|
23
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
|
|
25
|
+
// ANSI colors
|
|
26
|
+
const colors = {
|
|
27
|
+
reset: '\x1b[0m',
|
|
28
|
+
red: '\x1b[31m',
|
|
29
|
+
green: '\x1b[32m',
|
|
30
|
+
yellow: '\x1b[33m',
|
|
31
|
+
blue: '\x1b[34m',
|
|
32
|
+
magenta: '\x1b[35m',
|
|
33
|
+
cyan: '\x1b[36m',
|
|
34
|
+
gray: '\x1b[90m',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function log(message, color = 'reset') {
|
|
38
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Parse CLI arguments
|
|
42
|
+
const args = process.argv.slice(2);
|
|
43
|
+
const options = {
|
|
44
|
+
package: args.find((arg) => arg.startsWith('--package='))?.split('=')[1],
|
|
45
|
+
strict: args.includes('--strict'),
|
|
46
|
+
verbose: args.includes('--verbose') || args.includes('-v'),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Required package.json fields
|
|
51
|
+
*/
|
|
52
|
+
const REQUIRED_FIELDS = {
|
|
53
|
+
critical: ['name', 'version', 'type'],
|
|
54
|
+
important: ['description', 'main', 'types'],
|
|
55
|
+
recommended: ['exports', 'files', 'scripts', 'engines'],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Required files in package directory
|
|
60
|
+
*/
|
|
61
|
+
const REQUIRED_FILES = {
|
|
62
|
+
critical: ['package.json', 'src'],
|
|
63
|
+
important: ['README.md', 'tsconfig.json'],
|
|
64
|
+
recommended: ['LICENSE', '.gitignore'],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check package structure
|
|
69
|
+
*/
|
|
70
|
+
function checkPackage(packageJsonPath) {
|
|
71
|
+
const packageDir = path.dirname(packageJsonPath);
|
|
72
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
73
|
+
const packageName = packageJson.name;
|
|
74
|
+
|
|
75
|
+
if (!packageName || !packageName.startsWith('@kb-labs/')) {
|
|
76
|
+
return null; // Skip non-KB Labs packages
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const issues = {
|
|
80
|
+
missingFiles: [],
|
|
81
|
+
missingFields: [],
|
|
82
|
+
structureIssues: [],
|
|
83
|
+
warnings: [],
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Check required files
|
|
87
|
+
for (const level of ['critical', 'important']) {
|
|
88
|
+
for (const file of REQUIRED_FILES[level]) {
|
|
89
|
+
const filePath = path.join(packageDir, file);
|
|
90
|
+
const exists = fs.existsSync(filePath);
|
|
91
|
+
|
|
92
|
+
if (!exists) {
|
|
93
|
+
issues.missingFiles.push({
|
|
94
|
+
file,
|
|
95
|
+
level,
|
|
96
|
+
severity: level === 'critical' ? 'error' : 'warning',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (options.strict) {
|
|
103
|
+
for (const file of REQUIRED_FILES.recommended) {
|
|
104
|
+
const filePath = path.join(packageDir, file);
|
|
105
|
+
if (!fs.existsSync(filePath)) {
|
|
106
|
+
issues.missingFiles.push({
|
|
107
|
+
file,
|
|
108
|
+
level: 'recommended',
|
|
109
|
+
severity: 'info',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Check required package.json fields
|
|
116
|
+
for (const level of ['critical', 'important']) {
|
|
117
|
+
for (const field of REQUIRED_FIELDS[level]) {
|
|
118
|
+
if (!packageJson[field]) {
|
|
119
|
+
issues.missingFields.push({
|
|
120
|
+
field,
|
|
121
|
+
level,
|
|
122
|
+
severity: level === 'critical' ? 'error' : 'warning',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (options.strict) {
|
|
129
|
+
for (const field of REQUIRED_FIELDS.recommended) {
|
|
130
|
+
if (!packageJson[field]) {
|
|
131
|
+
issues.missingFields.push({
|
|
132
|
+
field,
|
|
133
|
+
level: 'recommended',
|
|
134
|
+
severity: 'info',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Check README.md content quality
|
|
141
|
+
const readmePath = path.join(packageDir, 'README.md');
|
|
142
|
+
if (fs.existsSync(readmePath)) {
|
|
143
|
+
const readmeContent = fs.readFileSync(readmePath, 'utf-8');
|
|
144
|
+
const readmeLength = readmeContent.length;
|
|
145
|
+
|
|
146
|
+
if (readmeLength < 200) {
|
|
147
|
+
issues.warnings.push({
|
|
148
|
+
type: 'readme-too-short',
|
|
149
|
+
message: `README.md is very short (${readmeLength} chars)`,
|
|
150
|
+
suggestion: 'Add documentation about purpose, usage, and API',
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Check for common sections
|
|
155
|
+
const hasSections = {
|
|
156
|
+
install: /##\s+(Installation|Install|Setup)/i.test(readmeContent),
|
|
157
|
+
usage: /##\s+(Usage|Getting Started|Quick Start)/i.test(readmeContent),
|
|
158
|
+
api: /##\s+(API|Reference|Documentation)/i.test(readmeContent),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
if (!hasSections.usage && options.strict) {
|
|
162
|
+
issues.warnings.push({
|
|
163
|
+
type: 'readme-missing-usage',
|
|
164
|
+
message: 'README.md missing "Usage" section',
|
|
165
|
+
suggestion: 'Add usage examples and getting started guide',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Check for consistent source structure
|
|
171
|
+
const srcDir = path.join(packageDir, 'src');
|
|
172
|
+
if (fs.existsSync(srcDir)) {
|
|
173
|
+
const srcFiles = fs.readdirSync(srcDir);
|
|
174
|
+
const hasIndex = srcFiles.some((f) => /^index\.(ts|tsx|js|jsx)$/.test(f));
|
|
175
|
+
|
|
176
|
+
if (!hasIndex) {
|
|
177
|
+
issues.structureIssues.push({
|
|
178
|
+
type: 'missing-index',
|
|
179
|
+
message: 'No index file in src/ directory',
|
|
180
|
+
suggestion: 'Create src/index.ts as main entry point',
|
|
181
|
+
severity: 'warning',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Check for test files in src/ (should be in tests/ or __tests__)
|
|
186
|
+
const hasTestsInSrc = srcFiles.some(
|
|
187
|
+
(f) => f.includes('.test.') || f.includes('.spec.') || f === '__tests__'
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
if (hasTestsInSrc && options.strict) {
|
|
191
|
+
issues.warnings.push({
|
|
192
|
+
type: 'tests-in-src',
|
|
193
|
+
message: 'Test files found in src/ directory',
|
|
194
|
+
suggestion: 'Consider moving tests to separate tests/ directory',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Check package.json scripts
|
|
200
|
+
if (packageJson.scripts) {
|
|
201
|
+
const hasRequiredScripts = {
|
|
202
|
+
build: !!packageJson.scripts.build,
|
|
203
|
+
test: !!packageJson.scripts.test,
|
|
204
|
+
lint: !!packageJson.scripts.lint,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
if (!hasRequiredScripts.build) {
|
|
208
|
+
issues.structureIssues.push({
|
|
209
|
+
type: 'missing-build-script',
|
|
210
|
+
message: 'No "build" script in package.json',
|
|
211
|
+
suggestion: 'Add "build": "tsup" to scripts',
|
|
212
|
+
severity: 'warning',
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check TypeScript configuration
|
|
218
|
+
const tsconfigPath = path.join(packageDir, 'tsconfig.json');
|
|
219
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
220
|
+
try {
|
|
221
|
+
const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf-8'));
|
|
222
|
+
|
|
223
|
+
// Check if it extends devkit preset
|
|
224
|
+
if (tsconfig.extends && !tsconfig.extends.includes('@kb-labs/devkit')) {
|
|
225
|
+
issues.warnings.push({
|
|
226
|
+
type: 'tsconfig-not-using-devkit',
|
|
227
|
+
message: 'tsconfig.json not extending @kb-labs/devkit preset',
|
|
228
|
+
suggestion: 'Use "@kb-labs/devkit/tsconfig/node.json" for consistency',
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
} catch (err) {
|
|
232
|
+
issues.structureIssues.push({
|
|
233
|
+
type: 'invalid-tsconfig',
|
|
234
|
+
message: 'tsconfig.json has invalid JSON',
|
|
235
|
+
suggestion: 'Fix JSON syntax errors',
|
|
236
|
+
severity: 'error',
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Check exports field consistency
|
|
242
|
+
if (packageJson.exports) {
|
|
243
|
+
const mainExport = packageJson.exports['.'];
|
|
244
|
+
|
|
245
|
+
if (!mainExport) {
|
|
246
|
+
issues.structureIssues.push({
|
|
247
|
+
type: 'exports-missing-main',
|
|
248
|
+
message: 'package.json exports field missing "." entry',
|
|
249
|
+
suggestion: 'Add main export: { ".": "./dist/index.js" }',
|
|
250
|
+
severity: 'error',
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Check for .npmignore or files field
|
|
256
|
+
const hasNpmignore = fs.existsSync(path.join(packageDir, '.npmignore'));
|
|
257
|
+
const hasFilesField = !!packageJson.files;
|
|
258
|
+
|
|
259
|
+
if (!hasNpmignore && !hasFilesField && !packageJson.private) {
|
|
260
|
+
issues.warnings.push({
|
|
261
|
+
type: 'no-publish-config',
|
|
262
|
+
message: 'No .npmignore or "files" field (will publish everything)',
|
|
263
|
+
suggestion: 'Add "files": ["dist", "README.md", "LICENSE"] to package.json',
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
packageName,
|
|
269
|
+
packageDir,
|
|
270
|
+
packageJsonPath,
|
|
271
|
+
...issues,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Find all packages in monorepo
|
|
277
|
+
*/
|
|
278
|
+
function findPackages(rootDir, filterPackage) {
|
|
279
|
+
const packages = [];
|
|
280
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
281
|
+
|
|
282
|
+
for (const entry of entries) {
|
|
283
|
+
if (!entry.isDirectory() || !entry.name.startsWith('kb-labs-')) {continue;}
|
|
284
|
+
|
|
285
|
+
const repoPath = path.join(rootDir, entry.name);
|
|
286
|
+
const packagesDir = path.join(repoPath, 'packages');
|
|
287
|
+
|
|
288
|
+
if (!fs.existsSync(packagesDir)) {continue;}
|
|
289
|
+
|
|
290
|
+
const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });
|
|
291
|
+
|
|
292
|
+
for (const pkgDir of packageDirs) {
|
|
293
|
+
if (!pkgDir.isDirectory()) {continue;}
|
|
294
|
+
|
|
295
|
+
// Filter by package name if specified
|
|
296
|
+
if (filterPackage && pkgDir.name !== filterPackage) {continue;}
|
|
297
|
+
|
|
298
|
+
const packageJsonPath = path.join(packagesDir, pkgDir.name, 'package.json');
|
|
299
|
+
|
|
300
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
301
|
+
packages.push(packageJsonPath);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return packages;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Main function
|
|
311
|
+
*/
|
|
312
|
+
function main() {
|
|
313
|
+
const rootDir = process.cwd();
|
|
314
|
+
|
|
315
|
+
log('\nš KB Labs Structure Checker\n', 'blue');
|
|
316
|
+
|
|
317
|
+
if (options.package) {
|
|
318
|
+
log(`Checking package: ${options.package}\n`, 'gray');
|
|
319
|
+
} else {
|
|
320
|
+
log('Checking all packages...\n', 'gray');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (options.strict) {
|
|
324
|
+
log('ā ļø Strict mode enabled (includes recommendations)\n', 'yellow');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const packages = findPackages(rootDir, options.package);
|
|
328
|
+
|
|
329
|
+
if (packages.length === 0) {
|
|
330
|
+
log('ā ļø No KB Labs packages found', 'yellow');
|
|
331
|
+
log(' Run this command from the monorepo root\n', 'gray');
|
|
332
|
+
process.exit(0);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
log(`Found ${packages.length} package(s) to check\n`, 'gray');
|
|
336
|
+
|
|
337
|
+
const results = [];
|
|
338
|
+
|
|
339
|
+
// Check each package
|
|
340
|
+
for (const packagePath of packages) {
|
|
341
|
+
const result = checkPackage(packagePath);
|
|
342
|
+
if (result) {
|
|
343
|
+
results.push(result);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Print results
|
|
348
|
+
let hasIssues = false;
|
|
349
|
+
let hasErrors = false;
|
|
350
|
+
|
|
351
|
+
for (const result of results) {
|
|
352
|
+
const errorCount = [
|
|
353
|
+
...result.missingFiles.filter((f) => f.severity === 'error'),
|
|
354
|
+
...result.missingFields.filter((f) => f.severity === 'error'),
|
|
355
|
+
...result.structureIssues.filter((i) => i.severity === 'error'),
|
|
356
|
+
].length;
|
|
357
|
+
|
|
358
|
+
const warningCount = [
|
|
359
|
+
...result.missingFiles.filter((f) => f.severity === 'warning'),
|
|
360
|
+
...result.missingFields.filter((f) => f.severity === 'warning'),
|
|
361
|
+
...result.structureIssues.filter((i) => i.severity === 'warning'),
|
|
362
|
+
...result.warnings,
|
|
363
|
+
].length;
|
|
364
|
+
|
|
365
|
+
const issueCount = errorCount + warningCount;
|
|
366
|
+
|
|
367
|
+
if (issueCount === 0 && !options.verbose) {continue;}
|
|
368
|
+
|
|
369
|
+
hasIssues = issueCount > 0;
|
|
370
|
+
hasErrors = hasErrors || errorCount > 0;
|
|
371
|
+
|
|
372
|
+
if (errorCount > 0) {
|
|
373
|
+
log(`\nā ${result.packageName}`, 'red');
|
|
374
|
+
} else if (warningCount > 0) {
|
|
375
|
+
log(`\nā ļø ${result.packageName}`, 'yellow');
|
|
376
|
+
} else if (options.verbose) {
|
|
377
|
+
log(`\nā
${result.packageName}`, 'green');
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
log(` ${path.relative(rootDir, result.packageDir)}`, 'gray');
|
|
381
|
+
|
|
382
|
+
// Missing files
|
|
383
|
+
const criticalFiles = result.missingFiles.filter((f) => f.severity === 'error');
|
|
384
|
+
if (criticalFiles.length > 0) {
|
|
385
|
+
log(`\n š“ Missing critical files (${criticalFiles.length}):`, 'red');
|
|
386
|
+
for (const file of criticalFiles) {
|
|
387
|
+
log(` ${file.file}`, 'yellow');
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const warningFiles = result.missingFiles.filter((f) => f.severity === 'warning');
|
|
392
|
+
if (warningFiles.length > 0) {
|
|
393
|
+
log(`\n š” Missing important files (${warningFiles.length}):`, 'yellow');
|
|
394
|
+
for (const file of warningFiles) {
|
|
395
|
+
log(` ${file.file}`, 'gray');
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Missing fields
|
|
400
|
+
const criticalFields = result.missingFields.filter((f) => f.severity === 'error');
|
|
401
|
+
if (criticalFields.length > 0) {
|
|
402
|
+
log(`\n š“ Missing critical fields (${criticalFields.length}):`, 'red');
|
|
403
|
+
for (const field of criticalFields) {
|
|
404
|
+
log(` ${field.field}`, 'yellow');
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const warningFields = result.missingFields.filter((f) => f.severity === 'warning');
|
|
409
|
+
if (warningFields.length > 0) {
|
|
410
|
+
log(`\n š” Missing important fields (${warningFields.length}):`, 'yellow');
|
|
411
|
+
for (const field of warningFields) {
|
|
412
|
+
log(` ${field.field}`, 'gray');
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Structure issues
|
|
417
|
+
if (result.structureIssues.length > 0) {
|
|
418
|
+
const errors = result.structureIssues.filter((i) => i.severity === 'error');
|
|
419
|
+
const warnings = result.structureIssues.filter((i) => i.severity === 'warning');
|
|
420
|
+
|
|
421
|
+
if (errors.length > 0) {
|
|
422
|
+
log(`\n š“ Structure errors (${errors.length}):`, 'red');
|
|
423
|
+
for (const issue of errors) {
|
|
424
|
+
log(` ${issue.message}`, 'yellow');
|
|
425
|
+
log(` š” ${issue.suggestion}`, 'blue');
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (warnings.length > 0) {
|
|
430
|
+
log(`\n š” Structure warnings (${warnings.length}):`, 'yellow');
|
|
431
|
+
for (const issue of warnings) {
|
|
432
|
+
log(` ${issue.message}`, 'gray');
|
|
433
|
+
log(` š” ${issue.suggestion}`, 'blue');
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Other warnings
|
|
439
|
+
if (result.warnings.length > 0 && options.strict) {
|
|
440
|
+
log(`\n ā¹ļø Recommendations (${result.warnings.length}):`, 'cyan');
|
|
441
|
+
for (const warning of result.warnings) {
|
|
442
|
+
log(` ${warning.message}`, 'gray');
|
|
443
|
+
if (warning.suggestion) {
|
|
444
|
+
log(` š” ${warning.suggestion}`, 'blue');
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Summary
|
|
451
|
+
log('\n' + 'ā'.repeat(60) + '\n', 'gray');
|
|
452
|
+
|
|
453
|
+
if (!hasIssues) {
|
|
454
|
+
log('ā
All packages have proper structure!\n', 'green');
|
|
455
|
+
process.exit(0);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
log('š Summary:\n', 'blue');
|
|
459
|
+
|
|
460
|
+
const totalErrors = results.reduce(
|
|
461
|
+
(sum, r) =>
|
|
462
|
+
sum +
|
|
463
|
+
r.missingFiles.filter((f) => f.severity === 'error').length +
|
|
464
|
+
r.missingFields.filter((f) => f.severity === 'error').length +
|
|
465
|
+
r.structureIssues.filter((i) => i.severity === 'error').length,
|
|
466
|
+
0
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const totalWarnings = results.reduce(
|
|
470
|
+
(sum, r) =>
|
|
471
|
+
sum +
|
|
472
|
+
r.missingFiles.filter((f) => f.severity === 'warning').length +
|
|
473
|
+
r.missingFields.filter((f) => f.severity === 'warning').length +
|
|
474
|
+
r.structureIssues.filter((i) => i.severity === 'warning').length +
|
|
475
|
+
r.warnings.length,
|
|
476
|
+
0
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
if (totalErrors > 0) {
|
|
480
|
+
log(` š“ ${totalErrors} error(s)`, 'red');
|
|
481
|
+
}
|
|
482
|
+
if (totalWarnings > 0) {
|
|
483
|
+
log(` š” ${totalWarnings} warning(s)`, 'yellow');
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
log('\nš” Tips:', 'blue');
|
|
487
|
+
log(' ⢠Use --verbose to see all packages (including clean ones)', 'gray');
|
|
488
|
+
log(' ⢠Use --package=<name> to check a specific package', 'gray');
|
|
489
|
+
log(' ⢠Use --strict to include recommendations', 'gray');
|
|
490
|
+
log('');
|
|
491
|
+
|
|
492
|
+
process.exit(hasErrors ? 1 : 0);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
main();
|