@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,637 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @kb-labs/devkit - TypeScript Types Order Calculator
|
|
5
|
+
*
|
|
6
|
+
* Calculates the correct order for TypeScript types generation.
|
|
7
|
+
* Unlike build-order which tracks runtime dependencies, this tracks
|
|
8
|
+
* TYPE dependencies - which types are imported from which packages.
|
|
9
|
+
*
|
|
10
|
+
* This is critical in monorepos because:
|
|
11
|
+
* - ProjectA imports type G from PackageB
|
|
12
|
+
* - PackageB imports type L from PackageM
|
|
13
|
+
* - If PackageM doesn't generate types (dts: false), ProjectA breaks!
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* kb-devkit-types-order # Show types order
|
|
17
|
+
* kb-devkit-types-order --layers # Show parallel layers
|
|
18
|
+
* kb-devkit-types-order --package=cli # For specific package
|
|
19
|
+
* kb-devkit-types-order --broken # Show only broken chains
|
|
20
|
+
* kb-devkit-types-order --json # JSON output
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import fs from 'node:fs';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
|
|
27
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
|
|
29
|
+
// ANSI colors
|
|
30
|
+
const colors = {
|
|
31
|
+
reset: '\x1b[0m',
|
|
32
|
+
red: '\x1b[31m',
|
|
33
|
+
green: '\x1b[32m',
|
|
34
|
+
yellow: '\x1b[33m',
|
|
35
|
+
blue: '\x1b[34m',
|
|
36
|
+
magenta: '\x1b[35m',
|
|
37
|
+
cyan: '\x1b[36m',
|
|
38
|
+
gray: '\x1b[90m',
|
|
39
|
+
bold: '\x1b[1m',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function log(message, color = 'reset') {
|
|
43
|
+
if (!options.json) {
|
|
44
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Parse CLI arguments
|
|
49
|
+
const args = process.argv.slice(2);
|
|
50
|
+
const options = {
|
|
51
|
+
layers: args.includes('--layers'),
|
|
52
|
+
json: args.includes('--json'),
|
|
53
|
+
broken: args.includes('--broken'),
|
|
54
|
+
verbose: args.includes('--verbose') || args.includes('-v'),
|
|
55
|
+
package: args.find((arg) => arg.startsWith('--package='))?.split('=')[1],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Find all packages
|
|
60
|
+
*/
|
|
61
|
+
function findPackages(rootDir) {
|
|
62
|
+
const packages = [];
|
|
63
|
+
const entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
64
|
+
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
if (!entry.isDirectory() || !entry.name.startsWith('kb-labs-')) {continue;}
|
|
67
|
+
|
|
68
|
+
const repoPath = path.join(rootDir, entry.name);
|
|
69
|
+
const packagesDir = path.join(repoPath, 'packages');
|
|
70
|
+
|
|
71
|
+
if (!fs.existsSync(packagesDir)) {continue;}
|
|
72
|
+
|
|
73
|
+
const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });
|
|
74
|
+
|
|
75
|
+
for (const pkgDir of packageDirs) {
|
|
76
|
+
if (!pkgDir.isDirectory()) {continue;}
|
|
77
|
+
|
|
78
|
+
const packageJsonPath = path.join(packagesDir, pkgDir.name, 'package.json');
|
|
79
|
+
|
|
80
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
81
|
+
packages.push({
|
|
82
|
+
path: packageJsonPath,
|
|
83
|
+
dir: path.join(packagesDir, pkgDir.name),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return packages;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check if package generates types
|
|
94
|
+
*/
|
|
95
|
+
function checkTypesGeneration(packageDir) {
|
|
96
|
+
// Check tsup.config.ts for dts setting
|
|
97
|
+
const tsupConfigPath = path.join(packageDir, 'tsup.config.ts');
|
|
98
|
+
|
|
99
|
+
if (fs.existsSync(tsupConfigPath)) {
|
|
100
|
+
const content = fs.readFileSync(tsupConfigPath, 'utf-8');
|
|
101
|
+
|
|
102
|
+
// Check for dts: false (bad!)
|
|
103
|
+
if (/dts\s*:\s*false/.test(content)) {
|
|
104
|
+
return { generates: false, reason: 'dts: false in tsup.config.ts' };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Check for dts: true (good!)
|
|
108
|
+
if (/dts\s*:\s*true/.test(content)) {
|
|
109
|
+
return { generates: true, reason: 'dts: true in tsup.config.ts' };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// No explicit dts setting - tsup defaults to true
|
|
113
|
+
return { generates: true, reason: 'tsup default (dts: true)' };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// No tsup config - check if it's a TypeScript package
|
|
117
|
+
const srcDir = path.join(packageDir, 'src');
|
|
118
|
+
if (fs.existsSync(srcDir)) {
|
|
119
|
+
const hasTS = walkDir(srcDir, (file) => /\.(ts|tsx)$/.test(file));
|
|
120
|
+
if (hasTS) {
|
|
121
|
+
return { generates: false, reason: 'No tsup.config.ts found' };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { generates: false, reason: 'No TypeScript sources' };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Walk directory to check for files
|
|
130
|
+
*/
|
|
131
|
+
function walkDir(dir, predicate) {
|
|
132
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
133
|
+
|
|
134
|
+
for (const entry of entries) {
|
|
135
|
+
const fullPath = path.join(dir, entry.name);
|
|
136
|
+
|
|
137
|
+
if (entry.isDirectory()) {
|
|
138
|
+
if (walkDir(fullPath, predicate)) {return true;}
|
|
139
|
+
} else if (entry.isFile() && predicate(entry.name)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Extract type imports from TypeScript files
|
|
149
|
+
* Looks for:
|
|
150
|
+
* - import type { X } from '@kb-labs/...'
|
|
151
|
+
* - import { type X } from '@kb-labs/...'
|
|
152
|
+
* - import { X } from '@kb-labs/...' (might be type or value)
|
|
153
|
+
*/
|
|
154
|
+
function extractTypeImports(packageDir) {
|
|
155
|
+
const srcDir = path.join(packageDir, 'src');
|
|
156
|
+
if (!fs.existsSync(srcDir)) {return new Set();}
|
|
157
|
+
|
|
158
|
+
const typeImports = new Set();
|
|
159
|
+
|
|
160
|
+
function scanFile(filePath) {
|
|
161
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
162
|
+
|
|
163
|
+
// Match import statements
|
|
164
|
+
const importRegex = /import\s+(?:type\s+)?{([^}]+)}\s+from\s+['"](@kb-labs\/[^'"]+)['"]/g;
|
|
165
|
+
const importTypeRegex = /import\s+type\s+(?:{[^}]+}|\*\s+as\s+\w+)\s+from\s+['"](@kb-labs\/[^'"]+)['"]/g;
|
|
166
|
+
|
|
167
|
+
let match;
|
|
168
|
+
|
|
169
|
+
// Extract from 'import type { ... } from @kb-labs/...'
|
|
170
|
+
while ((match = importTypeRegex.exec(content)) !== null) {
|
|
171
|
+
typeImports.add(match[1]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Extract from 'import { ... } from @kb-labs/...'
|
|
175
|
+
// These might be types or values, but we track them as potential type dependencies
|
|
176
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
177
|
+
typeImports.add(match[2]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function walkFiles(dir) {
|
|
182
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
183
|
+
|
|
184
|
+
for (const entry of entries) {
|
|
185
|
+
const fullPath = path.join(dir, entry.name);
|
|
186
|
+
|
|
187
|
+
if (entry.isDirectory()) {
|
|
188
|
+
walkFiles(fullPath);
|
|
189
|
+
} else if (entry.isFile() && /\.(ts|tsx)$/.test(entry.name)) {
|
|
190
|
+
scanFile(fullPath);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
walkFiles(srcDir);
|
|
196
|
+
return typeImports;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Build types dependency graph
|
|
201
|
+
*/
|
|
202
|
+
function buildTypesDependencyGraph(packages) {
|
|
203
|
+
const graph = new Map(); // packageName -> { typeDeps: Set, generates: boolean, reason: string }
|
|
204
|
+
|
|
205
|
+
// First pass: collect all packages and their types generation status
|
|
206
|
+
for (const { path: packagePath, dir: packageDir } of packages) {
|
|
207
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
208
|
+
const packageName = packageJson.name;
|
|
209
|
+
|
|
210
|
+
if (!packageName || !packageName.startsWith('@kb-labs/')) {continue;}
|
|
211
|
+
|
|
212
|
+
const typesStatus = checkTypesGeneration(packageDir);
|
|
213
|
+
|
|
214
|
+
graph.set(packageName, {
|
|
215
|
+
typeDeps: new Set(),
|
|
216
|
+
generates: typesStatus.generates,
|
|
217
|
+
reason: typesStatus.reason,
|
|
218
|
+
dir: packageDir,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Second pass: extract type imports
|
|
223
|
+
for (const { path: packagePath, dir: packageDir } of packages) {
|
|
224
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
225
|
+
const packageName = packageJson.name;
|
|
226
|
+
|
|
227
|
+
if (!packageName || !packageName.startsWith('@kb-labs/')) {continue;}
|
|
228
|
+
|
|
229
|
+
const typeImports = extractTypeImports(packageDir);
|
|
230
|
+
|
|
231
|
+
for (const dep of typeImports) {
|
|
232
|
+
// Only track workspace type dependencies
|
|
233
|
+
if (dep.startsWith('@kb-labs/') && graph.has(dep)) {
|
|
234
|
+
graph.get(packageName).typeDeps.add(dep);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return graph;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Topological sort for types
|
|
244
|
+
*/
|
|
245
|
+
function topologicalSort(graph) {
|
|
246
|
+
const inDegree = new Map();
|
|
247
|
+
const reverseDeps = new Map();
|
|
248
|
+
|
|
249
|
+
for (const [pkg, { typeDeps }] of graph.entries()) {
|
|
250
|
+
if (!inDegree.has(pkg)) {
|
|
251
|
+
inDegree.set(pkg, 0);
|
|
252
|
+
}
|
|
253
|
+
if (!reverseDeps.has(pkg)) {
|
|
254
|
+
reverseDeps.set(pkg, new Set());
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
for (const dep of typeDeps) {
|
|
258
|
+
inDegree.set(pkg, (inDegree.get(pkg) || 0) + 1);
|
|
259
|
+
|
|
260
|
+
if (!reverseDeps.has(dep)) {
|
|
261
|
+
reverseDeps.set(dep, new Set());
|
|
262
|
+
}
|
|
263
|
+
reverseDeps.get(dep).add(pkg);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const queue = [];
|
|
268
|
+
for (const [pkg, degree] of inDegree.entries()) {
|
|
269
|
+
if (degree === 0) {
|
|
270
|
+
queue.push(pkg);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const layers = [];
|
|
275
|
+
const sorted = [];
|
|
276
|
+
|
|
277
|
+
while (queue.length > 0) {
|
|
278
|
+
const layer = [...queue];
|
|
279
|
+
layers.push(layer);
|
|
280
|
+
sorted.push(...layer);
|
|
281
|
+
|
|
282
|
+
queue.length = 0;
|
|
283
|
+
|
|
284
|
+
for (const pkg of layer) {
|
|
285
|
+
for (const dependent of reverseDeps.get(pkg) || []) {
|
|
286
|
+
inDegree.set(dependent, inDegree.get(dependent) - 1);
|
|
287
|
+
|
|
288
|
+
if (inDegree.get(dependent) === 0) {
|
|
289
|
+
queue.push(dependent);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (sorted.length !== graph.size) {
|
|
296
|
+
const missing = Array.from(graph.keys()).filter((pkg) => !sorted.includes(pkg));
|
|
297
|
+
return { layers, sorted, circular: missing };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return { layers, sorted, circular: [] };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Find broken type chains
|
|
305
|
+
* A chain is broken if:
|
|
306
|
+
* 1. Package A imports types from Package B
|
|
307
|
+
* 2. Package B doesn't generate types (dts: false)
|
|
308
|
+
*/
|
|
309
|
+
function findBrokenChains(graph) {
|
|
310
|
+
const broken = [];
|
|
311
|
+
|
|
312
|
+
for (const [pkg, { typeDeps }] of graph.entries()) {
|
|
313
|
+
for (const dep of typeDeps) {
|
|
314
|
+
const depNode = graph.get(dep);
|
|
315
|
+
|
|
316
|
+
if (!depNode.generates) {
|
|
317
|
+
broken.push({
|
|
318
|
+
consumer: pkg,
|
|
319
|
+
provider: dep,
|
|
320
|
+
reason: depNode.reason,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return broken;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Find circular type dependencies
|
|
331
|
+
*/
|
|
332
|
+
function findCircularTypeDependencies(graph, circularPackages) {
|
|
333
|
+
const cycles = [];
|
|
334
|
+
const visited = new Set();
|
|
335
|
+
const recursionStack = new Set();
|
|
336
|
+
const path = [];
|
|
337
|
+
|
|
338
|
+
function dfs(pkg) {
|
|
339
|
+
if (recursionStack.has(pkg)) {
|
|
340
|
+
const cycleStart = path.indexOf(pkg);
|
|
341
|
+
const cycle = [...path.slice(cycleStart), pkg];
|
|
342
|
+
|
|
343
|
+
const cycleKey = cycle.slice(0, -1).sort().join('ā');
|
|
344
|
+
if (!cycles.some((c) => c.key === cycleKey)) {
|
|
345
|
+
cycles.push({ cycle, key: cycleKey });
|
|
346
|
+
}
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (visited.has(pkg)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
visited.add(pkg);
|
|
355
|
+
recursionStack.add(pkg);
|
|
356
|
+
path.push(pkg);
|
|
357
|
+
|
|
358
|
+
const node = graph.get(pkg);
|
|
359
|
+
if (node) {
|
|
360
|
+
for (const dep of node.typeDeps) {
|
|
361
|
+
if (circularPackages.includes(dep)) {
|
|
362
|
+
dfs(dep);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
path.pop();
|
|
368
|
+
recursionStack.delete(pkg);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
for (const pkg of circularPackages) {
|
|
372
|
+
if (!visited.has(pkg)) {
|
|
373
|
+
dfs(pkg);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return cycles;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Get types order for specific package
|
|
382
|
+
*/
|
|
383
|
+
function getTypesOrderForPackage(graph, packageName) {
|
|
384
|
+
const visited = new Set();
|
|
385
|
+
const order = [];
|
|
386
|
+
|
|
387
|
+
function visit(pkg) {
|
|
388
|
+
if (visited.has(pkg)) {return;}
|
|
389
|
+
visited.add(pkg);
|
|
390
|
+
|
|
391
|
+
const node = graph.get(pkg);
|
|
392
|
+
if (!node) {return;}
|
|
393
|
+
|
|
394
|
+
for (const dep of node.typeDeps) {
|
|
395
|
+
visit(dep);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
order.push(pkg);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
visit(packageName);
|
|
402
|
+
return order;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Print types order
|
|
407
|
+
*/
|
|
408
|
+
function printTypesOrder(result, graph) {
|
|
409
|
+
log('\nš KB Labs TypeScript Types Order\n', 'bold');
|
|
410
|
+
|
|
411
|
+
// Check for broken chains first
|
|
412
|
+
const brokenChains = findBrokenChains(graph);
|
|
413
|
+
|
|
414
|
+
if (brokenChains.length > 0) {
|
|
415
|
+
log(`ā Broken Type Chains: ${brokenChains.length}\n`, 'red');
|
|
416
|
+
|
|
417
|
+
for (const { consumer, provider, reason } of brokenChains) {
|
|
418
|
+
log(` ${consumer}`, 'yellow');
|
|
419
|
+
log(` āā imports types from: ${provider}`, 'gray');
|
|
420
|
+
log(` āā ā ${provider} doesn't generate types: ${reason}`, 'red');
|
|
421
|
+
log('', 'reset');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
log('š” Fix with: npx kb-devkit-check-types --fix\n', 'cyan');
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (result.circular.length > 0) {
|
|
428
|
+
log('š Circular Type Dependencies\n', 'yellow');
|
|
429
|
+
|
|
430
|
+
const cycles = findCircularTypeDependencies(graph, result.circular);
|
|
431
|
+
|
|
432
|
+
if (cycles.length > 0) {
|
|
433
|
+
log(`Found ${cycles.length} circular type dependency cycle(s):\n`, 'yellow');
|
|
434
|
+
|
|
435
|
+
for (let i = 0; i < cycles.length; i++) {
|
|
436
|
+
const { cycle } = cycles[i];
|
|
437
|
+
log(`${i + 1}. ${cycle.join(' ā ')}`, 'red');
|
|
438
|
+
log('', 'reset');
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
log('š” To fix: Break the cycle by extracting shared types into a separate package\n', 'cyan');
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (brokenChains.length === 0 && result.circular.length === 0) {
|
|
446
|
+
log(`ā
All type chains are healthy!\n`, 'green');
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
log(`Found ${result.sorted.length} packages with TypeScript\n`, 'gray');
|
|
450
|
+
|
|
451
|
+
if (options.layers) {
|
|
452
|
+
log('š¦ Types Generation Layers (parallel):\n', 'blue');
|
|
453
|
+
|
|
454
|
+
for (let i = 0; i < result.layers.length; i++) {
|
|
455
|
+
const layer = result.layers[i];
|
|
456
|
+
log(`Layer ${i + 1} (${layer.length} packages):`, 'cyan');
|
|
457
|
+
|
|
458
|
+
for (const pkg of layer) {
|
|
459
|
+
const node = graph.get(pkg);
|
|
460
|
+
const status = node.generates ? 'ā
' : 'ā';
|
|
461
|
+
log(` ${status} ${pkg}`, node.generates ? 'gray' : 'red');
|
|
462
|
+
|
|
463
|
+
if (options.verbose && node.typeDeps.size > 0) {
|
|
464
|
+
log(` type deps: ${Array.from(node.typeDeps).join(', ')}`, 'gray');
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
log('', 'reset');
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
log(`Total layers: ${result.layers.length}`, 'blue');
|
|
471
|
+
log(`Max parallelism: ${Math.max(...result.layers.map((l) => l.length))} packages\n`, 'blue');
|
|
472
|
+
} else {
|
|
473
|
+
log('š¦ Types Generation Order (sequential):\n', 'blue');
|
|
474
|
+
|
|
475
|
+
for (let i = 0; i < result.sorted.length; i++) {
|
|
476
|
+
const pkg = result.sorted[i];
|
|
477
|
+
const node = graph.get(pkg);
|
|
478
|
+
const status = node.generates ? 'ā
' : 'ā';
|
|
479
|
+
|
|
480
|
+
log(`${(i + 1).toString().padStart(3)}. ${status} ${pkg}`, node.generates ? 'cyan' : 'red');
|
|
481
|
+
|
|
482
|
+
if (options.verbose && node.typeDeps.size > 0) {
|
|
483
|
+
log(` type deps: ${Array.from(node.typeDeps).join(', ')}`, 'gray');
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
log('', 'reset');
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Summary
|
|
490
|
+
log('ā'.repeat(60) + '\n', 'gray');
|
|
491
|
+
log('š Summary:\n', 'blue');
|
|
492
|
+
|
|
493
|
+
const generating = Array.from(graph.values()).filter((n) => n.generates).length;
|
|
494
|
+
const notGenerating = graph.size - generating;
|
|
495
|
+
|
|
496
|
+
log(` Total packages: ${graph.size}`, 'cyan');
|
|
497
|
+
log(` ā
Generating types: ${generating}`, 'green');
|
|
498
|
+
if (notGenerating > 0) {
|
|
499
|
+
log(` ā Not generating: ${notGenerating}`, 'red');
|
|
500
|
+
}
|
|
501
|
+
if (brokenChains.length > 0) {
|
|
502
|
+
log(` š“ Broken chains: ${brokenChains.length}`, 'red');
|
|
503
|
+
}
|
|
504
|
+
if (result.circular.length > 0) {
|
|
505
|
+
log(` š Circular deps: ${result.circular.length}`, 'yellow');
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
log('', 'reset');
|
|
509
|
+
|
|
510
|
+
// Tips
|
|
511
|
+
log('š” Tips:', 'blue');
|
|
512
|
+
log(' ⢠Use --broken to show only broken type chains', 'gray');
|
|
513
|
+
log(' ⢠Use --layers to see parallel generation opportunities', 'gray');
|
|
514
|
+
log(' ⢠Use npx kb-devkit-check-types --fix to fix dts: false', 'gray');
|
|
515
|
+
log('', 'reset');
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Main function
|
|
520
|
+
*/
|
|
521
|
+
function main() {
|
|
522
|
+
const rootDir = process.cwd();
|
|
523
|
+
|
|
524
|
+
if (!options.json) {
|
|
525
|
+
log('\nš KB Labs TypeScript Types Order Calculator\n', 'bold');
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const packages = findPackages(rootDir);
|
|
529
|
+
|
|
530
|
+
if (packages.length === 0) {
|
|
531
|
+
log('ā ļø No KB Labs packages found', 'yellow');
|
|
532
|
+
process.exit(0);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const graph = buildTypesDependencyGraph(packages);
|
|
536
|
+
|
|
537
|
+
if (options.broken) {
|
|
538
|
+
// Only show broken chains
|
|
539
|
+
const brokenChains = findBrokenChains(graph);
|
|
540
|
+
|
|
541
|
+
if (options.json) {
|
|
542
|
+
console.log(JSON.stringify({ brokenChains }, null, 2));
|
|
543
|
+
} else {
|
|
544
|
+
log('\nā Broken Type Chains\n', 'red');
|
|
545
|
+
|
|
546
|
+
if (brokenChains.length === 0) {
|
|
547
|
+
log('ā
No broken type chains found!\n', 'green');
|
|
548
|
+
} else {
|
|
549
|
+
for (const { consumer, provider, reason } of brokenChains) {
|
|
550
|
+
log(` ${consumer}`, 'yellow');
|
|
551
|
+
log(` āā imports types from: ${provider}`, 'gray');
|
|
552
|
+
log(` āā ā ${provider} doesn't generate types: ${reason}`, 'red');
|
|
553
|
+
log('', 'reset');
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
log(`\nTotal broken chains: ${brokenChains.length}`, 'red');
|
|
557
|
+
log('š” Fix with: npx kb-devkit-check-types --fix\n', 'cyan');
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
process.exit(brokenChains.length > 0 ? 1 : 0);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (options.package) {
|
|
565
|
+
// Types order for specific package
|
|
566
|
+
const fullPackageName = options.package.startsWith('@kb-labs/')
|
|
567
|
+
? options.package
|
|
568
|
+
: `@kb-labs/${options.package}`;
|
|
569
|
+
|
|
570
|
+
if (!graph.has(fullPackageName)) {
|
|
571
|
+
log(`ā ļø Package not found: ${fullPackageName}`, 'yellow');
|
|
572
|
+
log('\nAvailable packages:', 'gray');
|
|
573
|
+
for (const pkg of Array.from(graph.keys()).sort()) {
|
|
574
|
+
log(` ${pkg}`, 'gray');
|
|
575
|
+
}
|
|
576
|
+
process.exit(1);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const order = getTypesOrderForPackage(graph, fullPackageName);
|
|
580
|
+
|
|
581
|
+
if (options.json) {
|
|
582
|
+
console.log(JSON.stringify({ package: fullPackageName, order }, null, 2));
|
|
583
|
+
} else {
|
|
584
|
+
log(`\nš Types generation order for ${fullPackageName}:\n`, 'blue');
|
|
585
|
+
|
|
586
|
+
for (let i = 0; i < order.length; i++) {
|
|
587
|
+
const pkg = order[i];
|
|
588
|
+
const node = graph.get(pkg);
|
|
589
|
+
const isCurrent = pkg === fullPackageName;
|
|
590
|
+
const status = node.generates ? 'ā
' : 'ā';
|
|
591
|
+
|
|
592
|
+
log(
|
|
593
|
+
`${(i + 1).toString().padStart(3)}. ${status} ${pkg}${isCurrent ? ' ā¬
target' : ''}`,
|
|
594
|
+
isCurrent ? 'yellow' : node.generates ? 'gray' : 'red'
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
log('', 'reset');
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Full types order
|
|
602
|
+
const result = topologicalSort(graph);
|
|
603
|
+
const brokenChains = findBrokenChains(graph);
|
|
604
|
+
|
|
605
|
+
if (!options.package && !options.broken) {
|
|
606
|
+
if (options.json) {
|
|
607
|
+
const output = {
|
|
608
|
+
total: graph.size,
|
|
609
|
+
layers: result.layers,
|
|
610
|
+
sorted: result.sorted,
|
|
611
|
+
circular: result.circular,
|
|
612
|
+
brokenChains,
|
|
613
|
+
stats: {
|
|
614
|
+
generating: Array.from(graph.values()).filter((n) => n.generates).length,
|
|
615
|
+
notGenerating: Array.from(graph.values()).filter((n) => !n.generates).length,
|
|
616
|
+
brokenChains: brokenChains.length,
|
|
617
|
+
},
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
if (result.circular.length > 0) {
|
|
621
|
+
const cycles = findCircularTypeDependencies(graph, result.circular);
|
|
622
|
+
output.cycles = cycles.map((c) => c.cycle);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
console.log(JSON.stringify(output, null, 2));
|
|
626
|
+
} else {
|
|
627
|
+
printTypesOrder(result, graph);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Exit with error if there are broken chains or circular deps
|
|
632
|
+
const hasIssues = brokenChains.length > 0 || result.circular.length > 0;
|
|
633
|
+
|
|
634
|
+
process.exit(hasIssues ? 1 : 0);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
main();
|