@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.
Files changed (295) hide show
  1. package/.cursorrules +32 -0
  2. package/.github/CODEOWNERS +2 -0
  3. package/.github/actions/setup-node-pnpm/action.yml +47 -0
  4. package/.github/workflow-templates/ci.yml +13 -0
  5. package/.github/workflow-templates/drift-check.yml +10 -0
  6. package/.github/workflow-templates/profiles-validate.yml +16 -0
  7. package/.github/workflow-templates/release.yml +8 -0
  8. package/.github/workflows/ci-reusable.yml +131 -0
  9. package/.github/workflows/drift-check-reusable.yml +23 -0
  10. package/.github/workflows/fixtures.yml +74 -0
  11. package/.github/workflows/profiles-validate-reusable.yml +67 -0
  12. package/.github/workflows/release-reusable.yml +50 -0
  13. package/.vscode/settings.json +23 -0
  14. package/AGENTS.md +130 -0
  15. package/LICENSE +21 -0
  16. package/README.md +1542 -0
  17. package/agents/devkit-maintainer/context.globs +15 -0
  18. package/agents/devkit-maintainer/permissions.yml +17 -0
  19. package/agents/devkit-maintainer/prompt.md +28 -0
  20. package/agents/devkit-maintainer/runbook.md +31 -0
  21. package/agents/docs-crafter/prompt.md +24 -0
  22. package/agents/docs-crafter/runbook.md +18 -0
  23. package/agents/release-manager/context.globs +7 -0
  24. package/agents/release-manager/prompt.md +27 -0
  25. package/agents/release-manager/runbook.md +17 -0
  26. package/agents/test-generator/context.globs +7 -0
  27. package/agents/test-generator/prompt.md +27 -0
  28. package/agents/test-generator/runbook.md +18 -0
  29. package/bin/devkit-architecture.mjs +1225 -0
  30. package/bin/devkit-build-order.mjs +500 -0
  31. package/bin/devkit-check-build-readiness.mjs +222 -0
  32. package/bin/devkit-check-commands.mjs +394 -0
  33. package/bin/devkit-check-configs.mjs +461 -0
  34. package/bin/devkit-check-deprecated.mjs +532 -0
  35. package/bin/devkit-check-duplicates.mjs +431 -0
  36. package/bin/devkit-check-exports.mjs +561 -0
  37. package/bin/devkit-check-imports.mjs +712 -0
  38. package/bin/devkit-check-paths.mjs +670 -0
  39. package/bin/devkit-check-scripts.mjs +335 -0
  40. package/bin/devkit-check-structure.mjs +495 -0
  41. package/bin/devkit-check-types.mjs +450 -0
  42. package/bin/devkit-ci.mjs +261 -0
  43. package/bin/devkit-core-gate.mjs +225 -0
  44. package/bin/devkit-fix-deps.mjs +1169 -0
  45. package/bin/devkit-freshness.mjs +199 -0
  46. package/bin/devkit-health.mjs +489 -0
  47. package/bin/devkit-migrate-configs.mjs +370 -0
  48. package/bin/devkit-paths.mjs +192 -0
  49. package/bin/devkit-stats.mjs +453 -0
  50. package/bin/devkit-sync.mjs +12 -0
  51. package/bin/devkit-tsup-external.mjs +148 -0
  52. package/bin/devkit-types-audit.mjs +615 -0
  53. package/bin/devkit-types-order.mjs +637 -0
  54. package/bin/devkit-validate-naming.mjs +203 -0
  55. package/bin/devkit-visualize.mjs +452 -0
  56. package/bin/kb-devkit-qa-history.mjs +453 -0
  57. package/bin/kb-devkit-qa.mjs +915 -0
  58. package/eslint/node.js +134 -0
  59. package/eslint/react.js +260 -0
  60. package/package.json +186 -0
  61. package/prettier/index.json +10 -0
  62. package/sync/index.mjs +693 -0
  63. package/templates/configs/README.md +306 -0
  64. package/templates/configs/eslint.config.js +27 -0
  65. package/templates/configs/package.json.bin +25 -0
  66. package/templates/configs/package.json.lib +30 -0
  67. package/templates/configs/tsconfig.build.json +15 -0
  68. package/templates/configs/tsconfig.json +9 -0
  69. package/templates/configs/tsup.config.bin.ts +34 -0
  70. package/templates/configs/tsup.config.cli.ts +41 -0
  71. package/templates/configs/tsup.config.dual.ts +46 -0
  72. package/templates/configs/tsup.config.ts +36 -0
  73. package/templates/package-json/README.md +290 -0
  74. package/templates/package-json/package.json.bin.template +40 -0
  75. package/templates/package-json/package.json.template +45 -0
  76. package/tsconfig/base.json +21 -0
  77. package/tsconfig/cli.json +12 -0
  78. package/tsconfig/dist/__tests__/cache.spec.d.ts +6 -0
  79. package/tsconfig/dist/__tests__/cache.spec.d.ts.map +1 -0
  80. package/tsconfig/dist/__tests__/cache.spec.js +85 -0
  81. package/tsconfig/dist/__tests__/cache.spec.js.map +1 -0
  82. package/tsconfig/dist/__tests__/fs-atomic.spec.d.ts +6 -0
  83. package/tsconfig/dist/__tests__/fs-atomic.spec.d.ts.map +1 -0
  84. package/tsconfig/dist/__tests__/fs-atomic.spec.js +153 -0
  85. package/tsconfig/dist/__tests__/fs-atomic.spec.js.map +1 -0
  86. package/tsconfig/dist/__tests__/init-workspace.spec.d.ts +6 -0
  87. package/tsconfig/dist/__tests__/init-workspace.spec.d.ts.map +1 -0
  88. package/tsconfig/dist/__tests__/init-workspace.spec.js +99 -0
  89. package/tsconfig/dist/__tests__/init-workspace.spec.js.map +1 -0
  90. package/tsconfig/dist/__tests__/kb-error.spec.d.ts +6 -0
  91. package/tsconfig/dist/__tests__/kb-error.spec.d.ts.map +1 -0
  92. package/tsconfig/dist/__tests__/kb-error.spec.js +190 -0
  93. package/tsconfig/dist/__tests__/kb-error.spec.js.map +1 -0
  94. package/tsconfig/dist/__tests__/preset-lockfile.spec.d.ts +6 -0
  95. package/tsconfig/dist/__tests__/preset-lockfile.spec.d.ts.map +1 -0
  96. package/tsconfig/dist/__tests__/preset-lockfile.spec.js +142 -0
  97. package/tsconfig/dist/__tests__/preset-lockfile.spec.js.map +1 -0
  98. package/tsconfig/dist/__tests__/product-config-profiles.spec.d.ts +6 -0
  99. package/tsconfig/dist/__tests__/product-config-profiles.spec.d.ts.map +1 -0
  100. package/tsconfig/dist/__tests__/product-config-profiles.spec.js +100 -0
  101. package/tsconfig/dist/__tests__/product-config-profiles.spec.js.map +1 -0
  102. package/tsconfig/dist/__tests__/product-config.spec.d.ts +6 -0
  103. package/tsconfig/dist/__tests__/product-config.spec.d.ts.map +1 -0
  104. package/tsconfig/dist/__tests__/product-config.spec.js +298 -0
  105. package/tsconfig/dist/__tests__/product-config.spec.js.map +1 -0
  106. package/tsconfig/dist/__tests__/runtime.spec.d.ts +2 -0
  107. package/tsconfig/dist/__tests__/runtime.spec.d.ts.map +1 -0
  108. package/tsconfig/dist/__tests__/runtime.spec.js +127 -0
  109. package/tsconfig/dist/__tests__/runtime.spec.js.map +1 -0
  110. package/tsconfig/dist/__tests__/upsert-lockfile.spec.d.ts +6 -0
  111. package/tsconfig/dist/__tests__/upsert-lockfile.spec.d.ts.map +1 -0
  112. package/tsconfig/dist/__tests__/upsert-lockfile.spec.js +251 -0
  113. package/tsconfig/dist/__tests__/upsert-lockfile.spec.js.map +1 -0
  114. package/tsconfig/dist/__tests__/validate-config.spec.d.ts +2 -0
  115. package/tsconfig/dist/__tests__/validate-config.spec.d.ts.map +1 -0
  116. package/tsconfig/dist/__tests__/validate-config.spec.js +14 -0
  117. package/tsconfig/dist/__tests__/validate-config.spec.js.map +1 -0
  118. package/tsconfig/dist/api/init-workspace.d.ts +10 -0
  119. package/tsconfig/dist/api/init-workspace.d.ts.map +1 -0
  120. package/tsconfig/dist/api/init-workspace.js +191 -0
  121. package/tsconfig/dist/api/init-workspace.js.map +1 -0
  122. package/tsconfig/dist/api/product-config.d.ts +21 -0
  123. package/tsconfig/dist/api/product-config.d.ts.map +1 -0
  124. package/tsconfig/dist/api/product-config.js +192 -0
  125. package/tsconfig/dist/api/product-config.js.map +1 -0
  126. package/tsconfig/dist/api/read-config.d.ts +22 -0
  127. package/tsconfig/dist/api/read-config.d.ts.map +1 -0
  128. package/tsconfig/dist/api/read-config.js +105 -0
  129. package/tsconfig/dist/api/read-config.js.map +1 -0
  130. package/tsconfig/dist/api/upsert-lockfile.d.ts +10 -0
  131. package/tsconfig/dist/api/upsert-lockfile.d.ts.map +1 -0
  132. package/tsconfig/dist/api/upsert-lockfile.js +63 -0
  133. package/tsconfig/dist/api/upsert-lockfile.js.map +1 -0
  134. package/tsconfig/dist/cache/fs-cache.d.ts +38 -0
  135. package/tsconfig/dist/cache/fs-cache.d.ts.map +1 -0
  136. package/tsconfig/dist/cache/fs-cache.js +142 -0
  137. package/tsconfig/dist/cache/fs-cache.js.map +1 -0
  138. package/tsconfig/dist/errors/kb-error.d.ts +32 -0
  139. package/tsconfig/dist/errors/kb-error.d.ts.map +1 -0
  140. package/tsconfig/dist/errors/kb-error.js +54 -0
  141. package/tsconfig/dist/errors/kb-error.js.map +1 -0
  142. package/tsconfig/dist/fs/__tests__/fs.spec.d.ts +2 -0
  143. package/tsconfig/dist/fs/__tests__/fs.spec.d.ts.map +1 -0
  144. package/tsconfig/dist/fs/__tests__/fs.spec.js +22 -0
  145. package/tsconfig/dist/fs/__tests__/fs.spec.js.map +1 -0
  146. package/tsconfig/dist/fs/fs.d.ts +6 -0
  147. package/tsconfig/dist/fs/fs.d.ts.map +1 -0
  148. package/tsconfig/dist/fs/fs.js +12 -0
  149. package/tsconfig/dist/fs/fs.js.map +1 -0
  150. package/tsconfig/dist/fs/index.d.ts +2 -0
  151. package/tsconfig/dist/fs/index.d.ts.map +1 -0
  152. package/tsconfig/dist/fs/index.js +2 -0
  153. package/tsconfig/dist/fs/index.js.map +1 -0
  154. package/tsconfig/dist/hash/config-hash.d.ts +17 -0
  155. package/tsconfig/dist/hash/config-hash.d.ts.map +1 -0
  156. package/tsconfig/dist/hash/config-hash.js +55 -0
  157. package/tsconfig/dist/hash/config-hash.js.map +1 -0
  158. package/tsconfig/dist/index.d.ts +5 -0
  159. package/tsconfig/dist/index.d.ts.map +1 -0
  160. package/tsconfig/dist/index.js +5 -0
  161. package/tsconfig/dist/index.js.map +1 -0
  162. package/tsconfig/dist/lockfile/lockfile.d.ts +54 -0
  163. package/tsconfig/dist/lockfile/lockfile.d.ts.map +1 -0
  164. package/tsconfig/dist/lockfile/lockfile.js +141 -0
  165. package/tsconfig/dist/lockfile/lockfile.js.map +1 -0
  166. package/tsconfig/dist/logging/__tests__/logger.spec.d.ts +2 -0
  167. package/tsconfig/dist/logging/__tests__/logger.spec.d.ts.map +1 -0
  168. package/tsconfig/dist/logging/__tests__/logger.spec.js +65 -0
  169. package/tsconfig/dist/logging/__tests__/logger.spec.js.map +1 -0
  170. package/tsconfig/dist/logging/__tests__/redaction.spec.d.ts +2 -0
  171. package/tsconfig/dist/logging/__tests__/redaction.spec.d.ts.map +1 -0
  172. package/tsconfig/dist/logging/__tests__/redaction.spec.js +34 -0
  173. package/tsconfig/dist/logging/__tests__/redaction.spec.js.map +1 -0
  174. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.d.ts +2 -0
  175. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.d.ts.map +1 -0
  176. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.js +90 -0
  177. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.js.map +1 -0
  178. package/tsconfig/dist/logging/index.d.ts +6 -0
  179. package/tsconfig/dist/logging/index.d.ts.map +1 -0
  180. package/tsconfig/dist/logging/index.js +6 -0
  181. package/tsconfig/dist/logging/index.js.map +1 -0
  182. package/tsconfig/dist/logging/logger.d.ts +9 -0
  183. package/tsconfig/dist/logging/logger.d.ts.map +1 -0
  184. package/tsconfig/dist/logging/logger.js +101 -0
  185. package/tsconfig/dist/logging/logger.js.map +1 -0
  186. package/tsconfig/dist/logging/redaction.d.ts +7 -0
  187. package/tsconfig/dist/logging/redaction.d.ts.map +1 -0
  188. package/tsconfig/dist/logging/redaction.js +23 -0
  189. package/tsconfig/dist/logging/redaction.js.map +1 -0
  190. package/tsconfig/dist/logging/sinks/json.d.ts +4 -0
  191. package/tsconfig/dist/logging/sinks/json.d.ts.map +1 -0
  192. package/tsconfig/dist/logging/sinks/json.js +23 -0
  193. package/tsconfig/dist/logging/sinks/json.js.map +1 -0
  194. package/tsconfig/dist/logging/sinks/stdout.d.ts +3 -0
  195. package/tsconfig/dist/logging/sinks/stdout.d.ts.map +1 -0
  196. package/tsconfig/dist/logging/sinks/stdout.js +24 -0
  197. package/tsconfig/dist/logging/sinks/stdout.js.map +1 -0
  198. package/tsconfig/dist/logging/types/index.d.ts +2 -0
  199. package/tsconfig/dist/logging/types/index.d.ts.map +1 -0
  200. package/tsconfig/dist/logging/types/index.js +2 -0
  201. package/tsconfig/dist/logging/types/index.js.map +1 -0
  202. package/tsconfig/dist/logging/types/types.d.ts +37 -0
  203. package/tsconfig/dist/logging/types/types.d.ts.map +1 -0
  204. package/tsconfig/dist/logging/types/types.js +2 -0
  205. package/tsconfig/dist/logging/types/types.js.map +1 -0
  206. package/tsconfig/dist/merge/layered-merge.d.ts +16 -0
  207. package/tsconfig/dist/merge/layered-merge.d.ts.map +1 -0
  208. package/tsconfig/dist/merge/layered-merge.js +97 -0
  209. package/tsconfig/dist/merge/layered-merge.js.map +1 -0
  210. package/tsconfig/dist/preset/resolve-preset.d.ts +29 -0
  211. package/tsconfig/dist/preset/resolve-preset.d.ts.map +1 -0
  212. package/tsconfig/dist/preset/resolve-preset.js +104 -0
  213. package/tsconfig/dist/preset/resolve-preset.js.map +1 -0
  214. package/tsconfig/dist/repo/__tests__/repo.spec.d.ts +2 -0
  215. package/tsconfig/dist/repo/__tests__/repo.spec.d.ts.map +1 -0
  216. package/tsconfig/dist/repo/__tests__/repo.spec.js +25 -0
  217. package/tsconfig/dist/repo/__tests__/repo.spec.js.map +1 -0
  218. package/tsconfig/dist/repo/index.d.ts +2 -0
  219. package/tsconfig/dist/repo/index.d.ts.map +1 -0
  220. package/tsconfig/dist/repo/index.js +2 -0
  221. package/tsconfig/dist/repo/index.js.map +1 -0
  222. package/tsconfig/dist/repo/repo.d.ts +6 -0
  223. package/tsconfig/dist/repo/repo.d.ts.map +1 -0
  224. package/tsconfig/dist/repo/repo.js +25 -0
  225. package/tsconfig/dist/repo/repo.js.map +1 -0
  226. package/tsconfig/dist/runtime/index.d.ts +2 -0
  227. package/tsconfig/dist/runtime/index.d.ts.map +1 -0
  228. package/tsconfig/dist/runtime/index.js +2 -0
  229. package/tsconfig/dist/runtime/index.js.map +1 -0
  230. package/tsconfig/dist/runtime/runtime.d.ts +46 -0
  231. package/tsconfig/dist/runtime/runtime.d.ts.map +1 -0
  232. package/tsconfig/dist/runtime/runtime.js +126 -0
  233. package/tsconfig/dist/runtime/runtime.js.map +1 -0
  234. package/tsconfig/dist/tsconfig.tools.tsbuildinfo +1 -0
  235. package/tsconfig/dist/tsconfig.tsbuildinfo +1 -0
  236. package/tsconfig/dist/types/index.d.ts +2 -0
  237. package/tsconfig/dist/types/index.d.ts.map +1 -0
  238. package/tsconfig/dist/types/index.js +2 -0
  239. package/tsconfig/dist/types/index.js.map +1 -0
  240. package/tsconfig/dist/types/init.d.ts +34 -0
  241. package/tsconfig/dist/types/init.d.ts.map +1 -0
  242. package/tsconfig/dist/types/init.js +6 -0
  243. package/tsconfig/dist/types/init.js.map +1 -0
  244. package/tsconfig/dist/types/preset.d.ts +27 -0
  245. package/tsconfig/dist/types/preset.d.ts.map +1 -0
  246. package/tsconfig/dist/types/preset.js +6 -0
  247. package/tsconfig/dist/types/preset.js.map +1 -0
  248. package/tsconfig/dist/types/types.d.ts +6 -0
  249. package/tsconfig/dist/types/types.d.ts.map +1 -0
  250. package/tsconfig/dist/types/types.js +2 -0
  251. package/tsconfig/dist/types/types.js.map +1 -0
  252. package/tsconfig/dist/utils/__tests__/env.spec.d.ts +2 -0
  253. package/tsconfig/dist/utils/__tests__/env.spec.d.ts.map +1 -0
  254. package/tsconfig/dist/utils/__tests__/env.spec.js +33 -0
  255. package/tsconfig/dist/utils/__tests__/env.spec.js.map +1 -0
  256. package/tsconfig/dist/utils/env.d.ts +7 -0
  257. package/tsconfig/dist/utils/env.d.ts.map +1 -0
  258. package/tsconfig/dist/utils/env.js +25 -0
  259. package/tsconfig/dist/utils/env.js.map +1 -0
  260. package/tsconfig/dist/utils/fs-atomic.d.ts +15 -0
  261. package/tsconfig/dist/utils/fs-atomic.d.ts.map +1 -0
  262. package/tsconfig/dist/utils/fs-atomic.js +45 -0
  263. package/tsconfig/dist/utils/fs-atomic.js.map +1 -0
  264. package/tsconfig/dist/utils/index.d.ts +3 -0
  265. package/tsconfig/dist/utils/index.d.ts.map +1 -0
  266. package/tsconfig/dist/utils/index.js +3 -0
  267. package/tsconfig/dist/utils/index.js.map +1 -0
  268. package/tsconfig/dist/utils/paths.d.ts +21 -0
  269. package/tsconfig/dist/utils/paths.d.ts.map +1 -0
  270. package/tsconfig/dist/utils/paths.js +32 -0
  271. package/tsconfig/dist/utils/paths.js.map +1 -0
  272. package/tsconfig/dist/utils/product-normalize.d.ts +27 -0
  273. package/tsconfig/dist/utils/product-normalize.d.ts.map +1 -0
  274. package/tsconfig/dist/utils/product-normalize.js +45 -0
  275. package/tsconfig/dist/utils/product-normalize.js.map +1 -0
  276. package/tsconfig/dist/validation/validate-config.d.ts +7 -0
  277. package/tsconfig/dist/validation/validate-config.d.ts.map +1 -0
  278. package/tsconfig/dist/validation/validate-config.js +22 -0
  279. package/tsconfig/dist/validation/validate-config.js.map +1 -0
  280. package/tsconfig/lib.json +13 -0
  281. package/tsconfig/node.json +12 -0
  282. package/tsconfig/react-app.json +8 -0
  283. package/tsconfig/react-lib.json +8 -0
  284. package/tsconfig/test.json +15 -0
  285. package/tsup/bin.js +172 -0
  286. package/tsup/dual.js +155 -0
  287. package/tsup/external-sync.mjs +41 -0
  288. package/tsup/external.mjs +109 -0
  289. package/tsup/node.js +65 -0
  290. package/tsup/react-lib.js +18 -0
  291. package/tsup/sdk.js +118 -0
  292. package/vite/react-app.js +50 -0
  293. package/vitest/node.js +37 -0
  294. package/vitest/react.js +39 -0
  295. package/vitest/vitest-setup.ts +9 -0
@@ -0,0 +1,450 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @kb-labs/devkit - TypeScript Types Checker
5
+ *
6
+ * Ensures all packages properly generate TypeScript declaration files (.d.ts).
7
+ * Detects technical debt like `dts: false` in tsup configs.
8
+ *
9
+ * Usage:
10
+ * kb-devkit-check-types # Check all packages
11
+ * kb-devkit-check-types --package=cli # Check specific package
12
+ * kb-devkit-check-types --fix # Auto-fix dts: false
13
+ * kb-devkit-check-types --json # JSON output
14
+ * kb-devkit-check-types --graph # Show types dependency graph
15
+ */
16
+
17
+ import fs from 'node:fs';
18
+ import path from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+
21
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
+
23
+ // ANSI colors
24
+ const colors = {
25
+ reset: '\x1b[0m',
26
+ red: '\x1b[31m',
27
+ green: '\x1b[32m',
28
+ yellow: '\x1b[33m',
29
+ blue: '\x1b[34m',
30
+ magenta: '\x1b[35m',
31
+ cyan: '\x1b[36m',
32
+ gray: '\x1b[90m',
33
+ bold: '\x1b[1m',
34
+ };
35
+
36
+ function log(message, color = 'reset') {
37
+ if (!options.json) {
38
+ console.log(`${colors[color]}${message}${colors.reset}`);
39
+ }
40
+ }
41
+
42
+ // Parse CLI arguments
43
+ const args = process.argv.slice(2);
44
+ const options = {
45
+ fix: args.includes('--fix'),
46
+ json: args.includes('--json'),
47
+ graph: args.includes('--graph'),
48
+ verbose: args.includes('--verbose') || args.includes('-v'),
49
+ package: args.find((arg) => arg.startsWith('--package='))?.split('=')[1],
50
+ };
51
+
52
+ /**
53
+ * Find all packages
54
+ */
55
+ function findPackages(rootDir, filterPackage) {
56
+ const packages = [];
57
+ const entries = fs.readdirSync(rootDir, { withFileTypes: true });
58
+
59
+ for (const entry of entries) {
60
+ if (!entry.isDirectory() || !entry.name.startsWith('kb-labs-')) {continue;}
61
+
62
+ const repoPath = path.join(rootDir, entry.name);
63
+ const packagesDir = path.join(repoPath, 'packages');
64
+
65
+ if (!fs.existsSync(packagesDir)) {continue;}
66
+
67
+ const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });
68
+
69
+ for (const pkgDir of packageDirs) {
70
+ if (!pkgDir.isDirectory()) {continue;}
71
+
72
+ if (filterPackage && pkgDir.name !== filterPackage) {continue;}
73
+
74
+ const packageJsonPath = path.join(packagesDir, pkgDir.name, 'package.json');
75
+
76
+ if (fs.existsSync(packageJsonPath)) {
77
+ packages.push({
78
+ path: packageJsonPath,
79
+ dir: path.join(packagesDir, pkgDir.name),
80
+ });
81
+ }
82
+ }
83
+ }
84
+
85
+ return packages;
86
+ }
87
+
88
+ /**
89
+ * Check if package has TypeScript source files
90
+ */
91
+ function hasTypeScriptSources(packageDir) {
92
+ const srcDir = path.join(packageDir, 'src');
93
+ if (!fs.existsSync(srcDir)) {return false;}
94
+
95
+ function walkDir(dir) {
96
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
97
+
98
+ for (const entry of entries) {
99
+ const fullPath = path.join(dir, entry.name);
100
+
101
+ if (entry.isDirectory()) {
102
+ if (walkDir(fullPath)) {return true;}
103
+ } else if (entry.isFile() && /\.(ts|tsx)$/.test(entry.name)) {
104
+ return true;
105
+ }
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ return walkDir(srcDir);
112
+ }
113
+
114
+ /**
115
+ * Check tsup.config for dts setting
116
+ */
117
+ function checkTsupConfig(packageDir) {
118
+ const tsupConfigPath = path.join(packageDir, 'tsup.config.ts');
119
+
120
+ if (!fs.existsSync(tsupConfigPath)) {
121
+ return { exists: false };
122
+ }
123
+
124
+ const content = fs.readFileSync(tsupConfigPath, 'utf-8');
125
+
126
+ // Check for dts: false (bad!)
127
+ const hasDtsFalse = /dts\s*:\s*false/.test(content);
128
+
129
+ // Check for dts: true (good!)
130
+ const hasDtsTrue = /dts\s*:\s*true/.test(content);
131
+
132
+ // Check if dts is explicitly set
133
+ const hasDtsConfig = /dts\s*:/.test(content);
134
+
135
+ return {
136
+ exists: true,
137
+ path: tsupConfigPath,
138
+ content,
139
+ hasDtsFalse,
140
+ hasDtsTrue,
141
+ hasDtsConfig,
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Check if package.json has types field
147
+ */
148
+ function checkPackageJsonTypes(packagePath) {
149
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
150
+
151
+ return {
152
+ name: packageJson.name,
153
+ hasTypes: !!packageJson.types || !!packageJson.typings,
154
+ typesPath: packageJson.types || packageJson.typings,
155
+ hasExports: !!packageJson.exports,
156
+ };
157
+ }
158
+
159
+ /**
160
+ * Check if dist folder has .d.ts files
161
+ */
162
+ function checkDistFolder(packageDir) {
163
+ const distDir = path.join(packageDir, 'dist');
164
+
165
+ if (!fs.existsSync(distDir)) {
166
+ return { exists: false, hasDts: false };
167
+ }
168
+
169
+ function hasDtsFiles(dir) {
170
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
171
+
172
+ for (const entry of entries) {
173
+ const fullPath = path.join(dir, entry.name);
174
+
175
+ if (entry.isDirectory()) {
176
+ if (hasDtsFiles(fullPath)) {return true;}
177
+ } else if (entry.isFile() && entry.name.endsWith('.d.ts')) {
178
+ return true;
179
+ }
180
+ }
181
+
182
+ return false;
183
+ }
184
+
185
+ return {
186
+ exists: true,
187
+ hasDts: hasDtsFiles(distDir),
188
+ };
189
+ }
190
+
191
+ /**
192
+ * Fix dts: false in tsup config
193
+ */
194
+ function fixTsupConfig(tsupConfigPath, dryRun = false) {
195
+ const content = fs.readFileSync(tsupConfigPath, 'utf-8');
196
+
197
+ // Replace dts: false with dts: true
198
+ const fixed = content.replace(/dts\s*:\s*false/g, 'dts: true');
199
+
200
+ if (fixed !== content) {
201
+ if (!dryRun) {
202
+ fs.writeFileSync(tsupConfigPath, fixed);
203
+ }
204
+ return true;
205
+ }
206
+
207
+ return false;
208
+ }
209
+
210
+ /**
211
+ * Check single package
212
+ */
213
+ function checkPackage(packageInfo) {
214
+ const { path: packagePath, dir: packageDir } = packageInfo;
215
+ const packageJson = checkPackageJsonTypes(packagePath);
216
+ const packageName = packageJson.name;
217
+
218
+ if (!packageName || !packageName.startsWith('@kb-labs/')) {
219
+ return null;
220
+ }
221
+
222
+ const hasTS = hasTypeScriptSources(packageDir);
223
+ const tsupConfig = checkTsupConfig(packageDir);
224
+ const dist = checkDistFolder(packageDir);
225
+
226
+ const issues = [];
227
+
228
+ // TypeScript sources but no tsup config
229
+ if (hasTS && !tsupConfig.exists) {
230
+ issues.push({
231
+ type: 'no_tsup_config',
232
+ severity: 'warning',
233
+ message: 'Has TypeScript sources but no tsup.config.ts',
234
+ });
235
+ }
236
+
237
+ // tsup config with dts: false (technical debt!)
238
+ if (tsupConfig.hasDtsFalse) {
239
+ issues.push({
240
+ type: 'dts_false',
241
+ severity: 'error',
242
+ message: 'tsup.config.ts has dts: false (bad practice!)',
243
+ fixable: true,
244
+ });
245
+ }
246
+
247
+ // Has TypeScript but no dts config at all
248
+ if (hasTS && tsupConfig.exists && !tsupConfig.hasDtsConfig) {
249
+ issues.push({
250
+ type: 'no_dts_config',
251
+ severity: 'warning',
252
+ message: 'tsup.config.ts missing dts configuration',
253
+ });
254
+ }
255
+
256
+ // Has TypeScript but package.json has no types field
257
+ if (hasTS && !packageJson.hasTypes) {
258
+ issues.push({
259
+ type: 'no_types_field',
260
+ severity: 'error',
261
+ message: 'package.json missing "types" field',
262
+ });
263
+ }
264
+
265
+ // Has tsup with dts: true but no .d.ts files in dist
266
+ if (tsupConfig.hasDtsTrue && dist.exists && !dist.hasDts) {
267
+ issues.push({
268
+ type: 'no_dist_types',
269
+ severity: 'warning',
270
+ message: 'No .d.ts files found in dist/ (need to build?)',
271
+ });
272
+ }
273
+
274
+ return {
275
+ name: packageName,
276
+ dir: packageDir,
277
+ hasTypeScript: hasTS,
278
+ tsupConfig,
279
+ dist,
280
+ packageJson,
281
+ issues,
282
+ isClean: issues.length === 0,
283
+ };
284
+ }
285
+
286
+ /**
287
+ * Print results
288
+ */
289
+ function printResults(results) {
290
+ log('\nšŸ” KB Labs TypeScript Types Checker\n', 'bold');
291
+
292
+ const allPackages = results.filter(r => r !== null);
293
+ const withIssues = allPackages.filter(r => !r.isClean);
294
+ const dtsFalse = allPackages.filter(r => r.issues.some(i => i.type === 'dts_false'));
295
+ const clean = allPackages.filter(r => r.isClean && r.hasTypeScript);
296
+
297
+ log(`Found ${allPackages.length} package(s) to check\n`, 'gray');
298
+
299
+ // Show packages with dts: false (technical debt!)
300
+ if (dtsFalse.length > 0) {
301
+ log(`šŸ”“ Technical Debt: ${dtsFalse.length} package(s) with dts: false\n`, 'red');
302
+
303
+ for (const result of dtsFalse) {
304
+ log(` ${result.name}`, 'yellow');
305
+ log(` ${result.tsupConfig.path}`, 'gray');
306
+ log(` └─ Has "dts: false" - types not being generated!`, 'red');
307
+
308
+ if (options.fix) {
309
+ const fixed = fixTsupConfig(result.tsupConfig.path, false);
310
+ if (fixed) {
311
+ log(` āœ… Fixed: Changed to "dts: true"`, 'green');
312
+ }
313
+ }
314
+ }
315
+ log('', 'reset');
316
+
317
+ if (!options.fix) {
318
+ log('šŸ’” Run with --fix to automatically change dts: false → dts: true\n', 'cyan');
319
+ }
320
+ }
321
+
322
+ // Show other issues
323
+ const otherIssues = withIssues.filter(r => !r.issues.some(i => i.type === 'dts_false'));
324
+
325
+ if (otherIssues.length > 0) {
326
+ log(`āš ļø Other Issues: ${otherIssues.length} package(s)\n`, 'yellow');
327
+
328
+ for (const result of otherIssues) {
329
+ log(` ${result.name}`, 'yellow');
330
+
331
+ for (const issue of result.issues) {
332
+ const icon = issue.severity === 'error' ? 'āŒ' : 'āš ļø';
333
+ log(` ${icon} ${issue.message}`, 'gray');
334
+ }
335
+ }
336
+ log('', 'reset');
337
+ }
338
+
339
+ // Show clean packages (only in verbose mode)
340
+ if (options.verbose && clean.length > 0) {
341
+ log(`āœ… Clean packages with types: ${clean.length}\n`, 'green');
342
+
343
+ for (const result of clean.slice(0, 10)) {
344
+ log(` ${result.name}`, 'gray');
345
+ }
346
+
347
+ if (clean.length > 10) {
348
+ log(` ... and ${clean.length - 10} more`, 'gray');
349
+ }
350
+ log('', 'reset');
351
+ }
352
+
353
+ // Summary
354
+ log('─'.repeat(60) + '\n', 'gray');
355
+ log('šŸ“Š Summary:\n', 'blue');
356
+
357
+ log(` Total packages: ${allPackages.length}`, 'cyan');
358
+ log(` With TypeScript: ${allPackages.filter(r => r.hasTypeScript).length}`, 'cyan');
359
+ log(` āœ… Clean: ${clean.length}`, 'green');
360
+
361
+ if (dtsFalse.length > 0) {
362
+ log(` šŸ”“ dts: false: ${dtsFalse.length} (technical debt!)`, 'red');
363
+ }
364
+ if (otherIssues.length > 0) {
365
+ log(` āš ļø Other issues: ${otherIssues.length}`, 'yellow');
366
+ }
367
+
368
+ log('', 'reset');
369
+
370
+ // Tips
371
+ log('šŸ’” Tips:', 'blue');
372
+ log(' • Use --fix to automatically fix dts: false', 'gray');
373
+ log(' • Use --verbose to see all packages', 'gray');
374
+ log(' • Run pnpm run build after fixing configs', 'gray');
375
+ log('', 'reset');
376
+ }
377
+
378
+ /**
379
+ * Build types dependency graph
380
+ */
381
+ function buildTypesDependencyGraph(results) {
382
+ const graph = new Map();
383
+
384
+ // Build graph of packages that provide types
385
+ for (const result of results) {
386
+ if (!result || !result.hasTypeScript) {continue;}
387
+
388
+ const hasTypes = result.tsupConfig.hasDtsTrue && !result.issues.some(i => i.type === 'dts_false');
389
+
390
+ graph.set(result.name, {
391
+ hasTypes,
392
+ issues: result.issues.length,
393
+ });
394
+ }
395
+
396
+ return graph;
397
+ }
398
+
399
+ /**
400
+ * Main function
401
+ */
402
+ function main() {
403
+ const rootDir = process.cwd();
404
+
405
+ if (!options.json) {
406
+ log('\nšŸš€ KB Labs TypeScript Types Checker\n', 'bold');
407
+ }
408
+
409
+ const packages = findPackages(rootDir, options.package);
410
+
411
+ if (packages.length === 0) {
412
+ log('āš ļø No KB Labs packages found', 'yellow');
413
+ process.exit(0);
414
+ }
415
+
416
+ // Check all packages
417
+ const results = packages.map(checkPackage);
418
+
419
+ if (options.json) {
420
+ const output = {
421
+ total: results.filter(r => r !== null).length,
422
+ withTypeScript: results.filter(r => r && r.hasTypeScript).length,
423
+ clean: results.filter(r => r && r.isClean && r.hasTypeScript).length,
424
+ dtsFalse: results.filter(r => r && r.issues.some(i => i.type === 'dts_false')).length,
425
+ issues: results.filter(r => r && !r.isClean).map(r => ({
426
+ name: r.name,
427
+ issues: r.issues,
428
+ })),
429
+ };
430
+
431
+ console.log(JSON.stringify(output, null, 2));
432
+ } else if (options.graph) {
433
+ const graph = buildTypesDependencyGraph(results);
434
+ log('\nšŸ“Š Types Dependency Graph\n', 'blue');
435
+
436
+ for (const [pkg, info] of graph.entries()) {
437
+ const status = info.hasTypes ? 'āœ…' : 'āŒ';
438
+ log(`${status} ${pkg}${info.issues > 0 ? ` (${info.issues} issues)` : ''}`, info.hasTypes ? 'green' : 'red');
439
+ }
440
+ log('', 'reset');
441
+ } else {
442
+ printResults(results);
443
+ }
444
+
445
+ // Exit with error if issues found
446
+ const hasIssues = results.some(r => r && !r.isClean);
447
+ process.exit(hasIssues ? 1 : 0);
448
+ }
449
+
450
+ main();
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @kb-labs/devkit - CI Combo Tool
5
+ *
6
+ * Runs all devkit checks in one command for CI/CD pipelines.
7
+ * Perfect for GitHub Actions, GitLab CI, or any CI/CD system.
8
+ *
9
+ * Checks performed:
10
+ * 1. Naming convention validation
11
+ * 2. Import issues (broken imports, unused deps, circular deps)
12
+ * 3. Export issues (unused exports, dead code)
13
+ * 4. Duplicate dependencies
14
+ * 5. Package structure validation
15
+ * 6. Path validation (workspace deps, exports, bin)
16
+ * 7. TypeScript types (dts generation, types field)
17
+ *
18
+ * Usage:
19
+ * kb-devkit-ci # Run all checks
20
+ * kb-devkit-ci --skip naming # Skip naming check
21
+ * kb-devkit-ci --only imports # Run only imports check
22
+ * kb-devkit-ci --json # Output JSON for parsing
23
+ */
24
+
25
+ import { spawn } from 'node:child_process';
26
+ import path from 'node:path';
27
+ import { fileURLToPath } from 'node:url';
28
+
29
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
30
+
31
+ // ANSI colors
32
+ const colors = {
33
+ reset: '\x1b[0m',
34
+ red: '\x1b[31m',
35
+ green: '\x1b[32m',
36
+ yellow: '\x1b[33m',
37
+ blue: '\x1b[34m',
38
+ magenta: '\x1b[35m',
39
+ cyan: '\x1b[36m',
40
+ gray: '\x1b[90m',
41
+ bold: '\x1b[1m',
42
+ };
43
+
44
+ function log(message, color = 'reset') {
45
+ console.log(`${colors[color]}${message}${colors.reset}`);
46
+ }
47
+
48
+ // Parse CLI arguments
49
+ const args = process.argv.slice(2);
50
+ const options = {
51
+ skip: args.find((arg) => arg.startsWith('--skip='))?.split('=')[1]?.split(',') || [],
52
+ only: args.find((arg) => arg.startsWith('--only='))?.split('=')[1]?.split(',') || [],
53
+ json: args.includes('--json'),
54
+ verbose: args.includes('--verbose') || args.includes('-v'),
55
+ };
56
+
57
+ /**
58
+ * Available checks
59
+ */
60
+ const CHECKS = {
61
+ naming: {
62
+ name: 'Naming Convention',
63
+ command: 'devkit-validate-naming.mjs',
64
+ emoji: 'šŸ“¦',
65
+ },
66
+ imports: {
67
+ name: 'Import Analysis',
68
+ command: 'devkit-check-imports.mjs',
69
+ emoji: 'šŸ”',
70
+ },
71
+ exports: {
72
+ name: 'Export Analysis',
73
+ command: 'devkit-check-exports.mjs',
74
+ emoji: 'šŸ“¤',
75
+ },
76
+ duplicates: {
77
+ name: 'Duplicate Dependencies',
78
+ command: 'devkit-check-duplicates.mjs',
79
+ emoji: 'šŸ”„',
80
+ },
81
+ structure: {
82
+ name: 'Package Structure',
83
+ command: 'devkit-check-structure.mjs',
84
+ emoji: 'šŸ“',
85
+ },
86
+ paths: {
87
+ name: 'Path Validation',
88
+ command: 'devkit-check-paths.mjs',
89
+ emoji: 'šŸ”—',
90
+ },
91
+ types: {
92
+ name: 'TypeScript Types',
93
+ command: 'devkit-check-types.mjs',
94
+ emoji: 'šŸ“',
95
+ },
96
+ };
97
+
98
+ /**
99
+ * Run a single check
100
+ */
101
+ function runCheck(checkId, check) {
102
+ return new Promise((resolve) => {
103
+ const startTime = Date.now();
104
+ const scriptPath = path.join(__dirname, check.command);
105
+
106
+ if (!options.json) {
107
+ log(`\n${check.emoji} Running ${check.name}...`, 'blue');
108
+ }
109
+
110
+ const child = spawn('node', [scriptPath], {
111
+ stdio: options.json ? 'pipe' : 'inherit',
112
+ cwd: process.cwd(),
113
+ });
114
+
115
+ let stdout = '';
116
+ let stderr = '';
117
+
118
+ if (options.json) {
119
+ child.stdout.on('data', (data) => {
120
+ stdout += data.toString();
121
+ });
122
+ child.stderr.on('data', (data) => {
123
+ stderr += data.toString();
124
+ });
125
+ }
126
+
127
+ child.on('close', (code) => {
128
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
129
+
130
+ resolve({
131
+ checkId,
132
+ name: check.name,
133
+ emoji: check.emoji,
134
+ passed: code === 0,
135
+ exitCode: code,
136
+ duration: parseFloat(duration),
137
+ stdout,
138
+ stderr,
139
+ });
140
+ });
141
+
142
+ child.on('error', (err) => {
143
+ resolve({
144
+ checkId,
145
+ name: check.name,
146
+ emoji: check.emoji,
147
+ passed: false,
148
+ exitCode: 1,
149
+ duration: 0,
150
+ error: err.message,
151
+ });
152
+ });
153
+ });
154
+ }
155
+
156
+ /**
157
+ * Main function
158
+ */
159
+ async function main() {
160
+ const startTime = Date.now();
161
+
162
+ if (!options.json) {
163
+ log('\nšŸš€ KB Labs CI Checker\n', 'bold');
164
+ log('Running all devkit checks...\n', 'gray');
165
+ }
166
+
167
+ // Determine which checks to run
168
+ let checksToRun = Object.keys(CHECKS);
169
+
170
+ if (options.only.length > 0) {
171
+ checksToRun = checksToRun.filter((id) => options.only.includes(id));
172
+ }
173
+
174
+ if (options.skip.length > 0) {
175
+ checksToRun = checksToRun.filter((id) => !options.skip.includes(id));
176
+ }
177
+
178
+ if (checksToRun.length === 0) {
179
+ log('āš ļø No checks to run', 'yellow');
180
+ process.exit(0);
181
+ }
182
+
183
+ // Run all checks
184
+ const results = [];
185
+
186
+ for (const checkId of checksToRun) {
187
+ const check = CHECKS[checkId];
188
+ const result = await runCheck(checkId, check);
189
+ results.push(result);
190
+
191
+ if (!options.json) {
192
+ if (result.passed) {
193
+ log(` āœ… ${result.name} passed (${result.duration}s)`, 'green');
194
+ } else {
195
+ log(` āŒ ${result.name} failed (${result.duration}s)`, 'red');
196
+ }
197
+ }
198
+ }
199
+
200
+ const totalDuration = ((Date.now() - startTime) / 1000).toFixed(2);
201
+
202
+ // Print summary
203
+ const passed = results.filter((r) => r.passed).length;
204
+ const failed = results.filter((r) => !r.passed).length;
205
+ const total = results.length;
206
+
207
+ if (options.json) {
208
+ // JSON output for CI parsing
209
+ const output = {
210
+ summary: {
211
+ total,
212
+ passed,
213
+ failed,
214
+ duration: parseFloat(totalDuration),
215
+ success: failed === 0,
216
+ },
217
+ checks: results.map((r) => ({
218
+ id: r.checkId,
219
+ name: r.name,
220
+ passed: r.passed,
221
+ exitCode: r.exitCode,
222
+ duration: r.duration,
223
+ error: r.error,
224
+ })),
225
+ };
226
+
227
+ console.log(JSON.stringify(output, null, 2));
228
+ } else {
229
+ log('\n' + '─'.repeat(60) + '\n', 'gray');
230
+ log('šŸ“Š Summary:\n', 'blue');
231
+
232
+ log(` Total checks: ${total}`, 'cyan');
233
+ log(` āœ… Passed: ${passed}`, 'green');
234
+ if (failed > 0) {
235
+ log(` āŒ Failed: ${failed}`, 'red');
236
+ }
237
+ log(` ā±ļø Duration: ${totalDuration}s`, 'gray');
238
+
239
+ log('', 'reset');
240
+
241
+ if (failed > 0) {
242
+ log('šŸ’” Failed checks:', 'yellow');
243
+ for (const result of results.filter((r) => !r.passed)) {
244
+ log(` • ${result.name}`, 'red');
245
+ }
246
+ log('', 'reset');
247
+ }
248
+
249
+ log('šŸ’” Tips:', 'blue');
250
+ log(' • Run individual checks to see detailed output', 'gray');
251
+ log(' • Use --skip=<check> to skip specific checks', 'gray');
252
+ log(' • Use --only=<check> to run only specific checks', 'gray');
253
+ log(' • Use --json for machine-readable output', 'gray');
254
+ log('', 'reset');
255
+ }
256
+
257
+ // Exit with appropriate code
258
+ process.exit(failed > 0 ? 1 : 0);
259
+ }
260
+
261
+ main();