@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,453 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @kb-labs/devkit - Quick Statistics
|
|
5
|
+
*
|
|
6
|
+
* Generates comprehensive statistics about your monorepo.
|
|
7
|
+
* Perfect for dashboards, metrics, and quick overview.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* kb-devkit-stats # Show all statistics
|
|
11
|
+
* kb-devkit-stats --json # Output JSON
|
|
12
|
+
* kb-devkit-stats --md # Output Markdown table
|
|
13
|
+
* kb-devkit-stats --health # Show health score
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import fs from 'node:fs';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
|
|
22
|
+
// ANSI colors
|
|
23
|
+
const colors = {
|
|
24
|
+
reset: '\x1b[0m',
|
|
25
|
+
red: '\x1b[31m',
|
|
26
|
+
green: '\x1b[32m',
|
|
27
|
+
yellow: '\x1b[33m',
|
|
28
|
+
blue: '\x1b[34m',
|
|
29
|
+
magenta: '\x1b[35m',
|
|
30
|
+
cyan: '\x1b[36m',
|
|
31
|
+
gray: '\x1b[90m',
|
|
32
|
+
bold: '\x1b[1m',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function log(message, color = 'reset') {
|
|
36
|
+
if (!options.json && !options.md) {
|
|
37
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Parse CLI arguments
|
|
42
|
+
const args = process.argv.slice(2);
|
|
43
|
+
const options = {
|
|
44
|
+
json: args.includes('--json'),
|
|
45
|
+
md: args.includes('--md'),
|
|
46
|
+
health: args.includes('--health'),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Find all packages
|
|
51
|
+
*/
|
|
52
|
+
function findPackages(rootDir) {
|
|
53
|
+
const packages = [];
|
|
54
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
55
|
+
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
if (!entry.isDirectory() || !entry.name.startsWith('kb-labs-')) {continue;}
|
|
58
|
+
|
|
59
|
+
const repoPath = path.join(rootDir, entry.name);
|
|
60
|
+
const packagesDir = path.join(repoPath, 'packages');
|
|
61
|
+
|
|
62
|
+
if (!fs.existsSync(packagesDir)) {continue;}
|
|
63
|
+
|
|
64
|
+
const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });
|
|
65
|
+
|
|
66
|
+
for (const pkgDir of packageDirs) {
|
|
67
|
+
if (!pkgDir.isDirectory()) {continue;}
|
|
68
|
+
|
|
69
|
+
const packageJsonPath = path.join(packagesDir, pkgDir.name, 'package.json');
|
|
70
|
+
|
|
71
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
72
|
+
packages.push(packageJsonPath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return packages;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Calculate package size
|
|
82
|
+
*/
|
|
83
|
+
function calculateSize(packageDir) {
|
|
84
|
+
const srcDir = path.join(packageDir, 'src');
|
|
85
|
+
if (!fs.existsSync(srcDir)) {
|
|
86
|
+
return { files: 0, lines: 0, bytes: 0 };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let files = 0;
|
|
90
|
+
let lines = 0;
|
|
91
|
+
let bytes = 0;
|
|
92
|
+
|
|
93
|
+
function walk(dir) {
|
|
94
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
95
|
+
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
const fullPath = path.join(dir, entry.name);
|
|
98
|
+
|
|
99
|
+
if (entry.isDirectory()) {
|
|
100
|
+
walk(fullPath);
|
|
101
|
+
} else if (entry.isFile() && /\.(ts|tsx|js|jsx)$/.test(entry.name)) {
|
|
102
|
+
files++;
|
|
103
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
104
|
+
lines += content.split('\n').length;
|
|
105
|
+
bytes += Buffer.byteLength(content, 'utf-8');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
walk(srcDir);
|
|
111
|
+
return { files, lines, bytes };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Collect statistics
|
|
116
|
+
*/
|
|
117
|
+
function collectStats(packages) {
|
|
118
|
+
const stats = {
|
|
119
|
+
overview: {
|
|
120
|
+
totalPackages: 0,
|
|
121
|
+
totalRepositories: 0,
|
|
122
|
+
totalFiles: 0,
|
|
123
|
+
totalLines: 0,
|
|
124
|
+
totalBytes: 0,
|
|
125
|
+
},
|
|
126
|
+
byRepository: {},
|
|
127
|
+
dependencies: {
|
|
128
|
+
total: 0,
|
|
129
|
+
workspace: 0,
|
|
130
|
+
external: 0,
|
|
131
|
+
duplicates: 0,
|
|
132
|
+
},
|
|
133
|
+
packages: [],
|
|
134
|
+
health: {
|
|
135
|
+
score: 0,
|
|
136
|
+
issues: [],
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const repos = new Set();
|
|
141
|
+
const allDeps = new Map();
|
|
142
|
+
|
|
143
|
+
for (const packagePath of packages) {
|
|
144
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
145
|
+
const packageName = packageJson.name;
|
|
146
|
+
|
|
147
|
+
if (!packageName || !packageName.startsWith('@kb-labs/')) {continue;}
|
|
148
|
+
|
|
149
|
+
stats.overview.totalPackages++;
|
|
150
|
+
|
|
151
|
+
const repoName = packageName.split('/')[1].split('-')[0];
|
|
152
|
+
repos.add(repoName);
|
|
153
|
+
|
|
154
|
+
const packageDir = path.dirname(packagePath);
|
|
155
|
+
const size = calculateSize(packageDir);
|
|
156
|
+
|
|
157
|
+
stats.overview.totalFiles += size.files;
|
|
158
|
+
stats.overview.totalLines += size.lines;
|
|
159
|
+
stats.overview.totalBytes += size.bytes;
|
|
160
|
+
|
|
161
|
+
// By repository
|
|
162
|
+
if (!stats.byRepository[repoName]) {
|
|
163
|
+
stats.byRepository[repoName] = {
|
|
164
|
+
packages: 0,
|
|
165
|
+
files: 0,
|
|
166
|
+
lines: 0,
|
|
167
|
+
bytes: 0,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
stats.byRepository[repoName].packages++;
|
|
172
|
+
stats.byRepository[repoName].files += size.files;
|
|
173
|
+
stats.byRepository[repoName].lines += size.lines;
|
|
174
|
+
stats.byRepository[repoName].bytes += size.bytes;
|
|
175
|
+
|
|
176
|
+
// Dependencies
|
|
177
|
+
const deps = {
|
|
178
|
+
...packageJson.dependencies,
|
|
179
|
+
...packageJson.devDependencies,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
let workspaceDeps = 0;
|
|
183
|
+
let externalDeps = 0;
|
|
184
|
+
|
|
185
|
+
for (const [dep, version] of Object.entries(deps)) {
|
|
186
|
+
if (version.startsWith('workspace:') || version.startsWith('link:')) {
|
|
187
|
+
workspaceDeps++;
|
|
188
|
+
stats.dependencies.workspace++;
|
|
189
|
+
} else {
|
|
190
|
+
externalDeps++;
|
|
191
|
+
stats.dependencies.external++;
|
|
192
|
+
|
|
193
|
+
// Track for duplicates
|
|
194
|
+
if (!allDeps.has(dep)) {
|
|
195
|
+
allDeps.set(dep, new Set());
|
|
196
|
+
}
|
|
197
|
+
allDeps.get(dep).add(version);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
stats.dependencies.total += Object.keys(deps).length;
|
|
202
|
+
|
|
203
|
+
// Health checks
|
|
204
|
+
const hasReadme = fs.existsSync(path.join(packageDir, 'README.md'));
|
|
205
|
+
const hasSrc = fs.existsSync(path.join(packageDir, 'src'));
|
|
206
|
+
const hasTsconfig = fs.existsSync(path.join(packageDir, 'tsconfig.json'));
|
|
207
|
+
|
|
208
|
+
stats.packages.push({
|
|
209
|
+
name: packageName,
|
|
210
|
+
repository: repoName,
|
|
211
|
+
files: size.files,
|
|
212
|
+
lines: size.lines,
|
|
213
|
+
bytes: size.bytes,
|
|
214
|
+
dependencies: {
|
|
215
|
+
total: Object.keys(deps).length,
|
|
216
|
+
workspace: workspaceDeps,
|
|
217
|
+
external: externalDeps,
|
|
218
|
+
},
|
|
219
|
+
health: {
|
|
220
|
+
hasReadme,
|
|
221
|
+
hasSrc,
|
|
222
|
+
hasTsconfig,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
stats.overview.totalRepositories = repos.size;
|
|
228
|
+
|
|
229
|
+
// Count duplicates
|
|
230
|
+
for (const [dep, versions] of allDeps.entries()) {
|
|
231
|
+
if (versions.size > 1) {
|
|
232
|
+
stats.dependencies.duplicates++;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Calculate health score
|
|
237
|
+
stats.health = calculateHealthScore(stats);
|
|
238
|
+
|
|
239
|
+
return stats;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Calculate overall health score
|
|
244
|
+
*/
|
|
245
|
+
function calculateHealthScore(stats) {
|
|
246
|
+
let score = 100;
|
|
247
|
+
const issues = [];
|
|
248
|
+
|
|
249
|
+
// Deduct for duplicates
|
|
250
|
+
if (stats.dependencies.duplicates > 0) {
|
|
251
|
+
const deduction = Math.min(20, stats.dependencies.duplicates * 2);
|
|
252
|
+
score -= deduction;
|
|
253
|
+
issues.push({
|
|
254
|
+
type: 'duplicates',
|
|
255
|
+
severity: 'high',
|
|
256
|
+
message: `${stats.dependencies.duplicates} duplicate dependencies`,
|
|
257
|
+
impact: -deduction,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Deduct for missing READMEs
|
|
262
|
+
const missingReadmes = stats.packages.filter((p) => !p.health.hasReadme).length;
|
|
263
|
+
if (missingReadmes > 0) {
|
|
264
|
+
const deduction = Math.min(15, missingReadmes);
|
|
265
|
+
score -= deduction;
|
|
266
|
+
issues.push({
|
|
267
|
+
type: 'documentation',
|
|
268
|
+
severity: 'medium',
|
|
269
|
+
message: `${missingReadmes} packages missing README`,
|
|
270
|
+
impact: -deduction,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Deduct for missing src
|
|
275
|
+
const missingSrc = stats.packages.filter((p) => !p.health.hasSrc).length;
|
|
276
|
+
if (missingSrc > 0) {
|
|
277
|
+
const deduction = Math.min(10, missingSrc * 2);
|
|
278
|
+
score -= deduction;
|
|
279
|
+
issues.push({
|
|
280
|
+
type: 'structure',
|
|
281
|
+
severity: 'high',
|
|
282
|
+
message: `${missingSrc} packages missing src directory`,
|
|
283
|
+
impact: -deduction,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Bonus for good practices
|
|
288
|
+
if (stats.overview.totalPackages > 50 && score > 80) {
|
|
289
|
+
score = Math.min(100, score + 5);
|
|
290
|
+
issues.push({
|
|
291
|
+
type: 'scale',
|
|
292
|
+
severity: 'info',
|
|
293
|
+
message: 'Well-maintained large monorepo',
|
|
294
|
+
impact: +5,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
score: Math.max(0, Math.round(score)),
|
|
300
|
+
grade: score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F',
|
|
301
|
+
issues,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Format bytes
|
|
307
|
+
*/
|
|
308
|
+
function formatBytes(bytes) {
|
|
309
|
+
if (bytes === 0) {return '0 B';}
|
|
310
|
+
const k = 1024;
|
|
311
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
312
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
313
|
+
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Print statistics
|
|
318
|
+
*/
|
|
319
|
+
function printStats(stats) {
|
|
320
|
+
log('\n📊 KB Labs Monorepo Statistics\n', 'bold');
|
|
321
|
+
|
|
322
|
+
// Overview
|
|
323
|
+
log('📦 Overview:', 'blue');
|
|
324
|
+
log(` Packages: ${stats.overview.totalPackages}`, 'cyan');
|
|
325
|
+
log(` Repositories: ${stats.overview.totalRepositories}`, 'cyan');
|
|
326
|
+
log(` Files: ${stats.overview.totalFiles.toLocaleString()}`, 'cyan');
|
|
327
|
+
log(` Lines of Code: ${stats.overview.totalLines.toLocaleString()}`, 'cyan');
|
|
328
|
+
log(` Total Size: ${formatBytes(stats.overview.totalBytes)}`, 'cyan');
|
|
329
|
+
log('', 'reset');
|
|
330
|
+
|
|
331
|
+
// Dependencies
|
|
332
|
+
log('🔗 Dependencies:', 'blue');
|
|
333
|
+
log(` Total: ${stats.dependencies.total.toLocaleString()}`, 'cyan');
|
|
334
|
+
log(` Workspace: ${stats.dependencies.workspace.toLocaleString()}`, 'green');
|
|
335
|
+
log(` External: ${stats.dependencies.external.toLocaleString()}`, 'yellow');
|
|
336
|
+
if (stats.dependencies.duplicates > 0) {
|
|
337
|
+
log(` Duplicates: ${stats.dependencies.duplicates} ⚠️`, 'red');
|
|
338
|
+
} else {
|
|
339
|
+
log(` Duplicates: 0 ✅`, 'green');
|
|
340
|
+
}
|
|
341
|
+
log('', 'reset');
|
|
342
|
+
|
|
343
|
+
// By Repository
|
|
344
|
+
log('📁 By Repository:', 'blue');
|
|
345
|
+
const repos = Object.entries(stats.byRepository).sort((a, b) => b[1].packages - a[1].packages);
|
|
346
|
+
|
|
347
|
+
for (const [repo, data] of repos.slice(0, 10)) {
|
|
348
|
+
log(` ${repo.padEnd(15)} ${data.packages.toString().padStart(3)} pkg ${data.lines.toLocaleString().padStart(8)} lines`, 'gray');
|
|
349
|
+
}
|
|
350
|
+
log('', 'reset');
|
|
351
|
+
|
|
352
|
+
// Health Score
|
|
353
|
+
if (options.health) {
|
|
354
|
+
log('💚 Health Score:', 'blue');
|
|
355
|
+
const scoreColor =
|
|
356
|
+
stats.health.grade === 'A' ? 'green' :
|
|
357
|
+
stats.health.grade === 'B' ? 'cyan' :
|
|
358
|
+
stats.health.grade === 'C' ? 'yellow' : 'red';
|
|
359
|
+
|
|
360
|
+
log(` Score: ${stats.health.score}/100 (Grade ${stats.health.grade})`, scoreColor);
|
|
361
|
+
|
|
362
|
+
if (stats.health.issues.length > 0) {
|
|
363
|
+
log('\n Issues:', 'yellow');
|
|
364
|
+
for (const issue of stats.health.issues) {
|
|
365
|
+
const icon =
|
|
366
|
+
issue.severity === 'high' ? '🔴' :
|
|
367
|
+
issue.severity === 'medium' ? '🟡' : 'ℹ️';
|
|
368
|
+
const impact = issue.impact > 0 ? `+${issue.impact}` : issue.impact;
|
|
369
|
+
log(` ${icon} ${issue.message} (${impact})`, 'gray');
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
log('', 'reset');
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Top packages
|
|
376
|
+
const largest = stats.packages.sort((a, b) => b.lines - a.lines).slice(0, 5);
|
|
377
|
+
log('📈 Largest Packages:', 'blue');
|
|
378
|
+
for (let i = 0; i < largest.length; i++) {
|
|
379
|
+
const pkg = largest[i];
|
|
380
|
+
log(` ${i + 1}. ${pkg.name}`, 'yellow');
|
|
381
|
+
log(` ${pkg.lines.toLocaleString()} lines, ${pkg.files} files`, 'gray');
|
|
382
|
+
}
|
|
383
|
+
log('', 'reset');
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Print Markdown
|
|
388
|
+
*/
|
|
389
|
+
function printMarkdown(stats) {
|
|
390
|
+
console.log('# KB Labs Monorepo Statistics\n');
|
|
391
|
+
|
|
392
|
+
console.log('## Overview\n');
|
|
393
|
+
console.log('| Metric | Value |');
|
|
394
|
+
console.log('|--------|-------|');
|
|
395
|
+
console.log(`| Packages | ${stats.overview.totalPackages} |`);
|
|
396
|
+
console.log(`| Repositories | ${stats.overview.totalRepositories} |`);
|
|
397
|
+
console.log(`| Files | ${stats.overview.totalFiles.toLocaleString()} |`);
|
|
398
|
+
console.log(`| Lines of Code | ${stats.overview.totalLines.toLocaleString()} |`);
|
|
399
|
+
console.log(`| Total Size | ${formatBytes(stats.overview.totalBytes)} |`);
|
|
400
|
+
console.log('');
|
|
401
|
+
|
|
402
|
+
console.log('## By Repository\n');
|
|
403
|
+
console.log('| Repository | Packages | Lines | Size |');
|
|
404
|
+
console.log('|------------|----------|-------|------|');
|
|
405
|
+
|
|
406
|
+
const repos = Object.entries(stats.byRepository).sort((a, b) => b[1].packages - a[1].packages);
|
|
407
|
+
for (const [repo, data] of repos) {
|
|
408
|
+
console.log(`| ${repo} | ${data.packages} | ${data.lines.toLocaleString()} | ${formatBytes(data.bytes)} |`);
|
|
409
|
+
}
|
|
410
|
+
console.log('');
|
|
411
|
+
|
|
412
|
+
if (options.health) {
|
|
413
|
+
console.log('## Health Score\n');
|
|
414
|
+
console.log(`**Score:** ${stats.health.score}/100 (Grade ${stats.health.grade})\n`);
|
|
415
|
+
|
|
416
|
+
if (stats.health.issues.length > 0) {
|
|
417
|
+
console.log('### Issues\n');
|
|
418
|
+
for (const issue of stats.health.issues) {
|
|
419
|
+
const emoji = issue.severity === 'high' ? '🔴' : issue.severity === 'medium' ? '🟡' : 'ℹ️';
|
|
420
|
+
console.log(`- ${emoji} ${issue.message}`);
|
|
421
|
+
}
|
|
422
|
+
console.log('');
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Main function
|
|
429
|
+
*/
|
|
430
|
+
function main() {
|
|
431
|
+
const rootDir = process.cwd();
|
|
432
|
+
|
|
433
|
+
const packages = findPackages(rootDir);
|
|
434
|
+
|
|
435
|
+
if (packages.length === 0) {
|
|
436
|
+
log('⚠️ No KB Labs packages found', 'yellow');
|
|
437
|
+
process.exit(0);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const stats = collectStats(packages);
|
|
441
|
+
|
|
442
|
+
if (options.json) {
|
|
443
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
444
|
+
} else if (options.md) {
|
|
445
|
+
printMarkdown(stats);
|
|
446
|
+
} else {
|
|
447
|
+
printStats(stats);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
process.exit(0);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
main();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { run } from '../sync/index.mjs';
|
|
3
|
+
|
|
4
|
+
(async () => {
|
|
5
|
+
try {
|
|
6
|
+
const code = await run({ args: process.argv.slice(2) });
|
|
7
|
+
process.exit(typeof code === 'number' ? code : 0);
|
|
8
|
+
} catch (e) {
|
|
9
|
+
console.error('[devkit-sync]', e?.message || e);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
})();
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { dirname, resolve, join } from 'node:path';
|
|
4
|
+
import { promises as fs } from 'node:fs';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { glob } from 'glob';
|
|
7
|
+
import { parse as parseYaml } from 'yaml';
|
|
8
|
+
|
|
9
|
+
async function exists(path) {
|
|
10
|
+
try {
|
|
11
|
+
await fs.access(path);
|
|
12
|
+
return true;
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function readJson(path) {
|
|
19
|
+
return JSON.parse(await fs.readFile(path, 'utf8'));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function findWorkspaceConfigs(startDir) {
|
|
23
|
+
const roots = [];
|
|
24
|
+
let current = resolve(startDir);
|
|
25
|
+
let prev = null;
|
|
26
|
+
while (current !== prev) {
|
|
27
|
+
const wsFile = join(current, 'pnpm-workspace.yaml');
|
|
28
|
+
if (await exists(wsFile)) {
|
|
29
|
+
try {
|
|
30
|
+
const yaml = await fs.readFile(wsFile, 'utf8');
|
|
31
|
+
const data = parseYaml(yaml);
|
|
32
|
+
const patterns = Array.isArray(data?.packages) ? data.packages.filter(Boolean) : [];
|
|
33
|
+
roots.push({ dir: current, patterns });
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.warn('[devkit-tsup-external] failed to read workspace config', wsFile, error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
prev = current;
|
|
39
|
+
current = dirname(current);
|
|
40
|
+
}
|
|
41
|
+
return roots;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function collectWorkspacePackages(workspaceRoots) {
|
|
45
|
+
const packages = new Set();
|
|
46
|
+
|
|
47
|
+
for (const { dir, patterns } of workspaceRoots) {
|
|
48
|
+
for (const pattern of patterns) {
|
|
49
|
+
if (!pattern || typeof pattern !== 'string') {continue;}
|
|
50
|
+
const searchPattern = pattern.endsWith('/') ? `${pattern}package.json` : join(pattern, 'package.json');
|
|
51
|
+
const matches = await glob(searchPattern, {
|
|
52
|
+
cwd: dir,
|
|
53
|
+
dot: false,
|
|
54
|
+
nodir: true,
|
|
55
|
+
ignore: ['**/node_modules/**', '**/dist/**'],
|
|
56
|
+
});
|
|
57
|
+
for (const match of matches) {
|
|
58
|
+
try {
|
|
59
|
+
const pkgPath = resolve(dir, match);
|
|
60
|
+
const pkg = await readJson(pkgPath);
|
|
61
|
+
if (!pkg?.name || typeof pkg.name !== 'string') {continue;}
|
|
62
|
+
if (!pkg.name.startsWith('@kb-labs/')) {continue;}
|
|
63
|
+
packages.add(pkg.name);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.warn('[devkit-tsup-external] failed to read package', match, error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return Array.from(packages).sort();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Resolves external dependencies for tsup bundling.
|
|
76
|
+
* Returns an array of package names that should be marked as external:
|
|
77
|
+
* - All @kb-labs/* workspace packages
|
|
78
|
+
* - All dependencies and peerDependencies from the current package.json
|
|
79
|
+
*
|
|
80
|
+
* @param {string} [cwd] - Current working directory (defaults to process.cwd())
|
|
81
|
+
* @returns {Promise<string[]>} Array of external package names
|
|
82
|
+
*/
|
|
83
|
+
export async function resolveTsupExternal(cwd = process.cwd()) {
|
|
84
|
+
const workspaceRoots = await findWorkspaceConfigs(cwd);
|
|
85
|
+
if (!workspaceRoots.length) {
|
|
86
|
+
console.warn('[devkit-tsup-external] no pnpm-workspace.yaml found up the tree');
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const workspacePackages = await collectWorkspacePackages(workspaceRoots);
|
|
91
|
+
|
|
92
|
+
// Also include dependencies from current package.json
|
|
93
|
+
const pkgPath = join(cwd, 'package.json');
|
|
94
|
+
let localDeps = [];
|
|
95
|
+
if (await exists(pkgPath)) {
|
|
96
|
+
try {
|
|
97
|
+
const pkg = await readJson(pkgPath);
|
|
98
|
+
const deps = Object.keys(pkg.dependencies ?? {});
|
|
99
|
+
const peerDeps = Object.keys(pkg.peerDependencies ?? {});
|
|
100
|
+
localDeps = Array.from(new Set([...deps, ...peerDeps]));
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.warn('[devkit-tsup-external] failed to read local package.json', error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Combine workspace packages and local dependencies, remove duplicates
|
|
107
|
+
return Array.from(new Set([...workspacePackages, ...localDeps])).sort();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// CLI mode: generate tsup.external.json file
|
|
111
|
+
async function generateExternalFile(rootDir) {
|
|
112
|
+
const externals = await resolveTsupExternal(rootDir);
|
|
113
|
+
|
|
114
|
+
const output = {
|
|
115
|
+
$schema: 'https://json.schemastore.org/tsconfig',
|
|
116
|
+
externals: externals,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const outPath = join(rootDir, 'tsup.external.json');
|
|
120
|
+
await fs.writeFile(outPath, `${JSON.stringify(output, null, 2)}\n`);
|
|
121
|
+
console.log(`[devkit-tsup-external] wrote ${externals.length} external packages to ${outPath}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function main() {
|
|
125
|
+
const args = process.argv.slice(2);
|
|
126
|
+
|
|
127
|
+
// Default behavior: generate file
|
|
128
|
+
if (args.length === 0 || args.includes('--generate') || args.includes('-g')) {
|
|
129
|
+
const rootDir = process.cwd();
|
|
130
|
+
await generateExternalFile(rootDir);
|
|
131
|
+
} else if (args.includes('--print') || args.includes('-p')) {
|
|
132
|
+
// Print externals (for testing)
|
|
133
|
+
const externals = await resolveTsupExternal();
|
|
134
|
+
console.log(JSON.stringify(externals, null, 2));
|
|
135
|
+
} else {
|
|
136
|
+
console.error('Usage: kb-devkit-tsup-external [--generate|-g] [--print|-p]');
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Only run main if this is the entry point
|
|
142
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
143
|
+
main().catch((error) => {
|
|
144
|
+
console.error('[devkit-tsup-external] failed', error);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|