@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,370 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * kb-devkit-migrate-configs
5
+ *
6
+ * Mass migration script to standardize all package configurations.
7
+ *
8
+ * What it does:
9
+ * 1. Scans all @kb-labs/* packages in workspace
10
+ * 2. Creates backups of current configs
11
+ * 3. Applies standard templates from DevKit
12
+ * 4. Generates migration report
13
+ *
14
+ * Usage:
15
+ * npx kb-devkit-migrate-configs # Dry run (preview)
16
+ * npx kb-devkit-migrate-configs --apply # Apply changes
17
+ * npx kb-devkit-migrate-configs --package=cli-core # Migrate specific package
18
+ * npx kb-devkit-migrate-configs --force # Skip confirmation prompts
19
+ */
20
+
21
+ import { promises as fs } from 'node:fs';
22
+ import { join, dirname, resolve } from 'node:path';
23
+ import { fileURLToPath } from 'node:url';
24
+ import process from 'node:process';
25
+ import { glob } from 'glob';
26
+ import { createInterface } from 'node:readline';
27
+
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = dirname(__filename);
30
+ const DEVKIT_ROOT = resolve(__dirname, '..');
31
+ const TEMPLATES_DIR = resolve(DEVKIT_ROOT, 'templates/configs');
32
+
33
+ // ANSI colors
34
+ const colors = {
35
+ reset: '\x1b[0m',
36
+ bright: '\x1b[1m',
37
+ red: '\x1b[31m',
38
+ green: '\x1b[32m',
39
+ yellow: '\x1b[33m',
40
+ blue: '\x1b[34m',
41
+ cyan: '\x1b[36m',
42
+ gray: '\x1b[90m',
43
+ };
44
+
45
+ function color(c, text) {
46
+ return process.stdout.isTTY ? `${colors[c]}${text}${colors.reset}` : text;
47
+ }
48
+
49
+ async function exists(path) {
50
+ try {
51
+ await fs.access(path);
52
+ return true;
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+
58
+ async function readJson(path) {
59
+ return JSON.parse(await fs.readFile(path, 'utf8'));
60
+ }
61
+
62
+ async function findWorkspacePackages(root) {
63
+ const wsFile = join(root, 'pnpm-workspace.yaml');
64
+ if (!(await exists(wsFile))) {
65
+ return [];
66
+ }
67
+
68
+ const pkgJsonPaths = await glob('**/package.json', {
69
+ cwd: root,
70
+ ignore: ['**/node_modules/**', '**/dist/**', '**/coverage/**'],
71
+ absolute: true,
72
+ });
73
+
74
+ const packages = [];
75
+ for (const pkgPath of pkgJsonPaths) {
76
+ try {
77
+ const pkg = await readJson(pkgPath);
78
+ if (pkg.name && pkg.name.startsWith('@kb-labs/')) {
79
+ packages.push({
80
+ name: pkg.name,
81
+ path: dirname(pkgPath),
82
+ pkg,
83
+ });
84
+ }
85
+ } catch {}
86
+ }
87
+
88
+ return packages;
89
+ }
90
+
91
+ const CONFIG_FILES = {
92
+ 'tsup.config.ts': { required: true, template: 'tsup.config.ts' },
93
+ 'eslint.config.js': { required: true, template: 'eslint.config.js' },
94
+ 'tsconfig.json': { required: true, template: 'tsconfig.json' },
95
+ 'tsconfig.build.json': { required: true, template: 'tsconfig.build.json' },
96
+ };
97
+
98
+ async function analyzePackage(pkg) {
99
+ const actions = [];
100
+
101
+ for (const [filename, meta] of Object.entries(CONFIG_FILES)) {
102
+ const filePath = join(pkg.path, filename);
103
+ const templatePath = join(TEMPLATES_DIR, meta.template);
104
+
105
+ if (!(await exists(filePath))) {
106
+ actions.push({
107
+ type: 'create',
108
+ file: filename,
109
+ from: templatePath,
110
+ to: filePath,
111
+ });
112
+ } else {
113
+ const content = await fs.readFile(filePath, 'utf8');
114
+ const templateContent = await fs.readFile(templatePath, 'utf8');
115
+
116
+ // For tsconfig files, check exact match
117
+ if (filename.includes('tsconfig')) {
118
+ const contentClean = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '').trim();
119
+ const templateClean = templateContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '').trim();
120
+
121
+ if (contentClean !== templateClean) {
122
+ actions.push({
123
+ type: 'replace',
124
+ file: filename,
125
+ from: templatePath,
126
+ to: filePath,
127
+ backup: `${filePath}.backup`,
128
+ });
129
+ }
130
+ } else {
131
+ // For tsup/eslint, preserve customizations but fix structure
132
+ actions.push({
133
+ type: 'update',
134
+ file: filename,
135
+ to: filePath,
136
+ backup: `${filePath}.backup`,
137
+ });
138
+ }
139
+ }
140
+ }
141
+
142
+ return actions;
143
+ }
144
+
145
+ async function applyMigration(pkg, actions, opts) {
146
+ const applied = [];
147
+
148
+ for (const action of actions) {
149
+ if (action.type === 'create') {
150
+ await fs.copyFile(action.from, action.to);
151
+ applied.push({ action, result: 'created' });
152
+ } else if (action.type === 'replace') {
153
+ // Backup original
154
+ const content = await fs.readFile(action.to, 'utf8');
155
+ await fs.writeFile(action.backup, content);
156
+
157
+ // Copy template
158
+ await fs.copyFile(action.from, action.to);
159
+ applied.push({ action, result: 'replaced (backup created)' });
160
+ } else if (action.type === 'update') {
161
+ // For tsup/eslint, apply smart updates
162
+ const content = await fs.readFile(action.to, 'utf8');
163
+ await fs.writeFile(action.backup, content);
164
+
165
+ // Apply fixes
166
+ let updated = content;
167
+
168
+ // Fix dts: false → dts: true
169
+ updated = updated.replace(/dts:\s*false/g, 'dts: true');
170
+
171
+ // Remove redundant external declarations (smart detection)
172
+ // This is a conservative fix - only remove obvious duplicates
173
+
174
+ await fs.writeFile(action.to, updated);
175
+ applied.push({ action, result: 'updated (backup created)' });
176
+ }
177
+ }
178
+
179
+ return applied;
180
+ }
181
+
182
+ async function promptConfirm(message) {
183
+ const rl = createInterface({
184
+ input: process.stdin,
185
+ output: process.stdout,
186
+ });
187
+
188
+ return new Promise(resolve => {
189
+ rl.question(`${message} (y/N): `, answer => {
190
+ rl.close();
191
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
192
+ });
193
+ });
194
+ }
195
+
196
+ function parseArgs(argv) {
197
+ const flags = new Set();
198
+ const kv = new Map();
199
+
200
+ for (const arg of argv.slice(2)) {
201
+ if (arg.startsWith('--')) {
202
+ const [k, v] = arg.split('=', 2);
203
+ if (v === undefined) {
204
+ flags.add(k);
205
+ } else {
206
+ kv.set(k, v);
207
+ }
208
+ }
209
+ }
210
+
211
+ return {
212
+ help: flags.has('--help') || flags.has('-h'),
213
+ apply: flags.has('--apply'),
214
+ force: flags.has('--force'),
215
+ json: flags.has('--json'),
216
+ verbose: flags.has('--verbose'),
217
+ package: kv.get('--package'),
218
+ };
219
+ }
220
+
221
+ function printHelp() {
222
+ console.log(`
223
+ ${color('bright', 'kb-devkit-migrate-configs')}
224
+
225
+ Mass migration script to standardize all package configurations.
226
+
227
+ ${color('blue', 'Usage:')}
228
+ npx kb-devkit-migrate-configs [options]
229
+
230
+ ${color('blue', 'Options:')}
231
+ --help, -h Show this help
232
+ --apply Apply changes (default: dry run)
233
+ --force Skip confirmation prompts
234
+ --package=NAME Migrate specific package only
235
+ --json Output JSON format
236
+ --verbose Verbose output
237
+
238
+ ${color('blue', 'Examples:')}
239
+ # Preview changes
240
+ npx kb-devkit-migrate-configs
241
+
242
+ # Apply to all packages
243
+ npx kb-devkit-migrate-configs --apply
244
+
245
+ # Migrate specific package
246
+ npx kb-devkit-migrate-configs --package=@kb-labs/core --apply
247
+
248
+ ${color('blue', 'What gets migrated:')}
249
+ ✓ tsup.config.ts → Standard template with minimal config
250
+ ✓ eslint.config.js → DevKit preset with minimal ignores
251
+ ✓ tsconfig.json → Standard TypeScript config
252
+ ✓ tsconfig.build.json → Build-specific config
253
+
254
+ ${color('blue', 'Safety:')}
255
+ • Creates .backup files for all modified configs
256
+ • Dry run by default (use --apply to execute)
257
+ • Interactive confirmation (use --force to skip)
258
+ `);
259
+ }
260
+
261
+ async function main() {
262
+ const opts = parseArgs(process.argv);
263
+
264
+ if (opts.help) {
265
+ printHelp();
266
+ process.exit(0);
267
+ }
268
+
269
+ console.log(color('bright', '\n🔄 KB Labs Configuration Migration\n'));
270
+
271
+ if (!opts.apply) {
272
+ console.log(color('yellow', '⚠️ DRY RUN MODE (use --apply to execute changes)\n'));
273
+ }
274
+
275
+ const cwd = process.cwd();
276
+ let packages = await findWorkspacePackages(cwd);
277
+
278
+ if (opts.package) {
279
+ packages = packages.filter(p => p.name === opts.package);
280
+ if (packages.length === 0) {
281
+ console.error(color('red', `❌ Package ${opts.package} not found`));
282
+ process.exit(1);
283
+ }
284
+ }
285
+
286
+ console.log(color('gray', `Found ${packages.length} package(s) to check\n`));
287
+
288
+ // Analyze all packages
289
+ const migrations = [];
290
+ for (const pkg of packages) {
291
+ const actions = await analyzePackage(pkg);
292
+ if (actions.length > 0) {
293
+ migrations.push({ pkg, actions });
294
+ }
295
+ }
296
+
297
+ if (migrations.length === 0) {
298
+ console.log(color('green', '✅ All packages are already up to date!\n'));
299
+ process.exit(0);
300
+ }
301
+
302
+ // Print summary
303
+ console.log(color('bright', `📊 Migration Summary:\n`));
304
+ console.log(color('gray', ` Packages to migrate: ${migrations.length}`));
305
+
306
+ let totalCreate = 0;
307
+ let totalReplace = 0;
308
+ let totalUpdate = 0;
309
+
310
+ for (const { pkg, actions } of migrations) {
311
+ console.log(color('cyan', `\n ${pkg.name}`));
312
+ for (const action of actions) {
313
+ if (action.type === 'create') {
314
+ console.log(color('green', ` ✓ Create ${action.file}`));
315
+ totalCreate++;
316
+ } else if (action.type === 'replace') {
317
+ console.log(color('yellow', ` ⚠ Replace ${action.file}`));
318
+ totalReplace++;
319
+ } else if (action.type === 'update') {
320
+ console.log(color('blue', ` → Update ${action.file}`));
321
+ totalUpdate++;
322
+ }
323
+ }
324
+ }
325
+
326
+ console.log(color('gray', `\n Total: ${totalCreate} create, ${totalReplace} replace, ${totalUpdate} update\n`));
327
+
328
+ // Confirm before applying
329
+ if (opts.apply) {
330
+ if (!opts.force && !opts.json) {
331
+ const confirmed = await promptConfirm(color('yellow', '\n⚠️ This will modify files. Continue?'));
332
+ if (!confirmed) {
333
+ console.log(color('gray', '\nMigration cancelled.\n'));
334
+ process.exit(0);
335
+ }
336
+ }
337
+
338
+ console.log(color('bright', '\n🔨 Applying migrations...\n'));
339
+
340
+ let totalApplied = 0;
341
+
342
+ for (const { pkg, actions } of migrations) {
343
+ const applied = await applyMigration(pkg, actions, opts);
344
+ totalApplied += applied.length;
345
+
346
+ if (opts.verbose) {
347
+ console.log(color('gray', ` ${pkg.name}: ${applied.length} file(s) migrated`));
348
+ }
349
+ }
350
+
351
+ console.log(color('green', `\n✅ Migration complete! ${totalApplied} file(s) migrated\n`));
352
+ console.log(color('gray', ' Backups created with .backup extension\n'));
353
+ console.log(color('cyan', '💡 Next steps:'));
354
+ console.log(color('gray', ' 1. Review changes: git diff'));
355
+ console.log(color('gray', ' 2. Test builds: pnpm run build'));
356
+ console.log(color('gray', ' 3. Run checks: npx kb-devkit-check-configs\n'));
357
+ } else {
358
+ console.log(color('cyan', '\n💡 Run with --apply to execute this migration\n'));
359
+ }
360
+
361
+ process.exit(0);
362
+ }
363
+
364
+ main().catch(err => {
365
+ console.error(color('red', '\n❌ Error:'), err.message);
366
+ if (process.env.DEBUG) {
367
+ console.error(err.stack);
368
+ }
369
+ process.exit(1);
370
+ });
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { dirname, resolve, relative, 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-paths] 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, cwd) {
45
+ const packages = new Map();
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 pkgDir = dirname(pkgPath);
61
+ const pkg = await readJson(pkgPath);
62
+ if (!pkg?.name || typeof pkg.name !== 'string') {continue;}
63
+ if (!pkg.name.startsWith('@kb-labs/')) {continue;}
64
+ if (!packages.has(pkg.name)) {
65
+ packages.set(pkg.name, pkgDir);
66
+ }
67
+ } catch (error) {
68
+ console.warn('[devkit-paths] failed to read package', match, error);
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ return packages;
75
+ }
76
+
77
+ async function resolveSourceEntries(pkgDir) {
78
+ const entries = [];
79
+ const candidates = [
80
+ 'src/index.ts',
81
+ 'src/index.tsx',
82
+ 'src/index.js',
83
+ 'dist/index.d.ts',
84
+ 'dist/index.js',
85
+ ];
86
+ for (const candidate of candidates) {
87
+ const abs = join(pkgDir, candidate);
88
+ if (await exists(abs)) {
89
+ entries.push(abs);
90
+ break;
91
+ }
92
+ }
93
+ const wildcardBase = await exists(join(pkgDir, 'src')) ? join(pkgDir, 'src') : null;
94
+ return { entries, wildcardBase };
95
+ }
96
+
97
+ async function collectProjectDependencies(rootDir) {
98
+ const dependencies = new Set();
99
+
100
+ // Find all package.json files in the project (exclude node_modules)
101
+ const packageJsonFiles = await glob('**/package.json', {
102
+ cwd: rootDir,
103
+ dot: false,
104
+ nodir: true,
105
+ ignore: ['**/node_modules/**', '**/dist/**'],
106
+ });
107
+
108
+ for (const pkgFile of packageJsonFiles) {
109
+ try {
110
+ const pkgPath = resolve(rootDir, pkgFile);
111
+ const pkg = await readJson(pkgPath);
112
+
113
+ // Collect all @kb-labs/* dependencies from dependencies, devDependencies, and peerDependencies
114
+ const allDeps = [
115
+ ...Object.keys(pkg.dependencies ?? {}),
116
+ ...Object.keys(pkg.devDependencies ?? {}),
117
+ ...Object.keys(pkg.peerDependencies ?? {}),
118
+ ];
119
+
120
+ for (const dep of allDeps) {
121
+ if (dep.startsWith('@kb-labs/')) {
122
+ dependencies.add(dep);
123
+ }
124
+ }
125
+ } catch (error) {
126
+ console.warn('[devkit-paths] failed to read package.json', pkgFile, error);
127
+ }
128
+ }
129
+
130
+ return dependencies;
131
+ }
132
+
133
+ async function generatePathsFile(rootDir) {
134
+ const workspaceRoots = await findWorkspaceConfigs(rootDir);
135
+ if (!workspaceRoots.length) {
136
+ console.error('[devkit-paths] no pnpm-workspace.yaml found up the tree');
137
+ process.exit(1);
138
+ }
139
+
140
+ const packages = await collectWorkspacePackages(workspaceRoots, rootDir);
141
+ if (!packages.size) {
142
+ console.warn('[devkit-paths] no packages discovered');
143
+ }
144
+
145
+ // Collect dependencies from project's package.json files
146
+ const projectDependencies = await collectProjectDependencies(rootDir);
147
+
148
+ const paths = {};
149
+ for (const [name, pkgDir] of packages) {
150
+ // Only include packages that are used in project's package.json files
151
+ if (!projectDependencies.has(name)) {
152
+ continue;
153
+ }
154
+
155
+ const relDir = relative(rootDir, pkgDir).replace(/\\/g, '/');
156
+ const { entries, wildcardBase } = await resolveSourceEntries(pkgDir);
157
+ const resolvedEntries = entries.map((abs) => relative(rootDir, abs).replace(/\\/g, '/'));
158
+ if (!resolvedEntries.length) {continue;}
159
+ paths[name] = resolvedEntries;
160
+ if (wildcardBase) {
161
+ const relBase = relative(rootDir, wildcardBase).replace(/\\/g, '/');
162
+ paths[`${name}/*`] = [`${relBase}/*`];
163
+ }
164
+ }
165
+
166
+ const output = {
167
+ $schema: 'https://json.schemastore.org/tsconfig',
168
+ compilerOptions: {
169
+ baseUrl: '.',
170
+ paths: Object.keys(paths)
171
+ .sort()
172
+ .reduce((acc, key) => {
173
+ acc[key] = paths[key];
174
+ return acc;
175
+ }, {}),
176
+ },
177
+ };
178
+
179
+ const outPath = join(rootDir, 'tsconfig.paths.json');
180
+ await fs.writeFile(outPath, `${JSON.stringify(output, null, 2)}\n`);
181
+ console.log(`[devkit-paths] wrote ${Object.keys(paths).length} mappings to ${relative(rootDir, outPath) || 'tsconfig.paths.json'} (${projectDependencies.size} dependencies found)`);
182
+ }
183
+
184
+ async function main() {
185
+ const rootDir = process.cwd();
186
+ await generatePathsFile(rootDir);
187
+ }
188
+
189
+ main().catch((error) => {
190
+ console.error('[devkit-paths] failed', error);
191
+ process.exit(1);
192
+ });