@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,335 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * KB Labs DevKit - Package Scripts Checker
5
+ *
6
+ * Validates that all packages have required scripts and devDependencies.
7
+ * Philosophy: "More is OK, Less is Not"
8
+ */
9
+
10
+ import { writeFile } from 'node:fs/promises';
11
+ import { join, dirname, relative } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { existsSync, readdirSync } from 'node:fs';
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+
17
+ // Required scripts (all packages MUST have these)
18
+ const REQUIRED_SCRIPTS = {
19
+ clean: 'rimraf dist',
20
+ build: 'tsup --config tsup.config.ts',
21
+ dev: 'tsup --config tsup.config.ts --watch',
22
+ lint: 'eslint src --ext .ts',
23
+ 'lint:fix': 'eslint src --ext .ts --fix',
24
+ 'type-check': 'tsc --noEmit',
25
+ test: 'vitest run',
26
+ 'test:watch': 'vitest',
27
+ };
28
+
29
+ // Required devDependencies (all packages MUST have these)
30
+ const REQUIRED_DEV_DEPS = {
31
+ '@kb-labs/devkit': 'workspace:*',
32
+ '@types/node': '^24.3.3',
33
+ rimraf: '^6.0.1',
34
+ tsup: '^8.5.0',
35
+ typescript: '^5.6.3',
36
+ vitest: '^3.2.4',
37
+ };
38
+
39
+ // Required fields
40
+ const REQUIRED_FIELDS = {
41
+ type: 'module',
42
+ engines: {
43
+ node: '>=20.0.0',
44
+ pnpm: '>=9.0.0',
45
+ },
46
+ };
47
+
48
+ // Find workspace root
49
+ function findWorkspaceRoot(cwd = process.cwd()) {
50
+ let current = cwd;
51
+ while (current !== '/') {
52
+ if (existsSync(join(current, 'pnpm-workspace.yaml'))) {
53
+ return current;
54
+ }
55
+ current = dirname(current);
56
+ }
57
+ return cwd;
58
+ }
59
+
60
+ // Get all workspace packages
61
+ async function getWorkspacePackages(root) {
62
+ const packages = [];
63
+
64
+ // Find all package.json files
65
+ const findPackages = (dir) => {
66
+ if (dir.includes('node_modules') || dir.includes('dist')) {return;}
67
+
68
+ const entries = readdirSync(dir, { withFileTypes: true });
69
+ for (const entry of entries) {
70
+ if (entry.isDirectory()) {
71
+ const fullPath = join(dir, entry.name);
72
+ const pkgJsonPath = join(fullPath, 'package.json');
73
+
74
+ if (existsSync(pkgJsonPath)) {
75
+ try {
76
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
77
+ if (pkg.name && pkg.name.startsWith('@kb-labs/')) {
78
+ packages.push({
79
+ name: pkg.name,
80
+ path: fullPath,
81
+ pkgJson: pkg,
82
+ pkgJsonPath,
83
+ });
84
+ }
85
+ } catch {}
86
+ }
87
+
88
+ // Recurse into subdirectories
89
+ if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
90
+ findPackages(fullPath);
91
+ }
92
+ }
93
+ }
94
+ };
95
+
96
+ findPackages(root);
97
+ return packages;
98
+ }
99
+
100
+ // Check package scripts and deps
101
+ function checkPackageScripts(pkg) {
102
+ const issues = [];
103
+ const warnings = [];
104
+ const { pkgJson } = pkg;
105
+
106
+ const scripts = pkgJson.scripts || {};
107
+ const devDeps = pkgJson.devDependencies || {};
108
+
109
+ // Check required scripts
110
+ for (const [name, expectedCmd] of Object.entries(REQUIRED_SCRIPTS)) {
111
+ if (!(name in scripts)) {
112
+ issues.push({
113
+ type: 'missing-script',
114
+ severity: 'error',
115
+ script: name,
116
+ expected: expectedCmd,
117
+ message: `Missing required script: ${name}`,
118
+ });
119
+ }
120
+ }
121
+
122
+ // Check required devDependencies
123
+ for (const [name, expectedVersion] of Object.entries(REQUIRED_DEV_DEPS)) {
124
+ if (!(name in devDeps)) {
125
+ issues.push({
126
+ type: 'missing-dev-dep',
127
+ severity: 'error',
128
+ dependency: name,
129
+ expected: expectedVersion,
130
+ message: `Missing required devDependency: ${name}`,
131
+ });
132
+ }
133
+ }
134
+
135
+ // Check type: "module"
136
+ if (pkgJson.type !== REQUIRED_FIELDS.type) {
137
+ issues.push({
138
+ type: 'wrong-type',
139
+ severity: 'error',
140
+ expected: REQUIRED_FIELDS.type,
141
+ actual: pkgJson.type,
142
+ message: `type should be "${REQUIRED_FIELDS.type}", got "${pkgJson.type || 'undefined'}"`,
143
+ });
144
+ }
145
+
146
+ // Check engines
147
+ const engines = pkgJson.engines || {};
148
+ for (const [name, expectedVersion] of Object.entries(REQUIRED_FIELDS.engines)) {
149
+ if (!(name in engines)) {
150
+ issues.push({
151
+ type: 'missing-engine',
152
+ severity: 'error',
153
+ engine: name,
154
+ expected: expectedVersion,
155
+ message: `Missing required engine: ${name}`,
156
+ });
157
+ } else if (engines[name] !== expectedVersion) {
158
+ warnings.push({
159
+ type: 'wrong-engine-version',
160
+ severity: 'warning',
161
+ engine: name,
162
+ expected: expectedVersion,
163
+ actual: engines[name],
164
+ message: `Engine ${name}: expected ${expectedVersion}, got ${engines[name]}`,
165
+ });
166
+ }
167
+ }
168
+
169
+ return { issues, warnings };
170
+ }
171
+
172
+ // Fix package scripts and deps
173
+ async function fixPackageScripts(pkg, issues) {
174
+ const { pkgJson, pkgJsonPath } = pkg;
175
+ let modified = false;
176
+
177
+ for (const issue of issues) {
178
+ switch (issue.type) {
179
+ case 'missing-script':
180
+ if (!pkgJson.scripts) {pkgJson.scripts = {};}
181
+ pkgJson.scripts[issue.script] = issue.expected;
182
+ modified = true;
183
+ break;
184
+
185
+ case 'missing-dev-dep':
186
+ if (!pkgJson.devDependencies) {pkgJson.devDependencies = {};}
187
+ pkgJson.devDependencies[issue.dependency] = issue.expected;
188
+ modified = true;
189
+ break;
190
+
191
+ case 'missing-engine':
192
+ if (!pkgJson.engines) {pkgJson.engines = {};}
193
+ pkgJson.engines[issue.engine] = issue.expected;
194
+ modified = true;
195
+ break;
196
+
197
+ case 'wrong-type':
198
+ pkgJson.type = issue.expected;
199
+ modified = true;
200
+ break;
201
+ }
202
+ }
203
+
204
+ if (modified) {
205
+ await writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + '\n', 'utf-8');
206
+ }
207
+
208
+ return modified;
209
+ }
210
+
211
+ // Import readFileSync
212
+ import { readFileSync } from 'node:fs';
213
+
214
+ // Main CLI
215
+ async function main() {
216
+ const args = process.argv.slice(2);
217
+ const flags = {
218
+ fix: args.includes('--fix'),
219
+ verbose: args.includes('--verbose'),
220
+ json: args.includes('--json'),
221
+ ci: args.includes('--ci'),
222
+ package: args.find((a) => a.startsWith('--package='))?.split('=')[1],
223
+ };
224
+
225
+ const root = findWorkspaceRoot();
226
+ let packages = await getWorkspacePackages(root);
227
+
228
+ if (flags.package) {
229
+ packages = packages.filter((p) => p.name === flags.package);
230
+ if (packages.length === 0) {
231
+ console.error(`\nāŒ Package ${flags.package} not found\n`);
232
+ process.exit(1);
233
+ }
234
+ }
235
+
236
+ if (!flags.json && !flags.ci) {
237
+ console.log('\nšŸ” KB Labs Package Scripts Checker\n');
238
+ console.log(`Found ${packages.length} package(s) to check\n`);
239
+ }
240
+
241
+ const results = [];
242
+ let totalIssues = 0;
243
+ let totalWarnings = 0;
244
+
245
+ for (const pkg of packages) {
246
+ const { issues, warnings } = checkPackageScripts(pkg);
247
+ totalIssues += issues.length;
248
+ totalWarnings += warnings.length;
249
+
250
+ if (flags.fix && issues.length > 0) {
251
+ const fixed = await fixPackageScripts(pkg, issues);
252
+ results.push({ pkg, issues, warnings, fixed });
253
+ } else {
254
+ results.push({ pkg, issues, warnings, fixed: false });
255
+ }
256
+ }
257
+
258
+ // Output results
259
+ if (flags.json) {
260
+ console.log(
261
+ JSON.stringify(
262
+ {
263
+ packages: results.map((r) => ({
264
+ name: r.pkg.name,
265
+ path: relative(root, r.pkg.path),
266
+ issues: r.issues.length,
267
+ warnings: r.warnings.length,
268
+ fixed: r.fixed,
269
+ details: {
270
+ issues: r.issues,
271
+ warnings: r.warnings,
272
+ },
273
+ })),
274
+ summary: {
275
+ total: packages.length,
276
+ withIssues: results.filter((r) => r.issues.length > 0).length,
277
+ withWarnings: results.filter((r) => r.warnings.length > 0).length,
278
+ fixed: results.filter((r) => r.fixed).length,
279
+ },
280
+ },
281
+ null,
282
+ 2,
283
+ ),
284
+ );
285
+ } else {
286
+ // Print issues
287
+ if (totalIssues > 0) {
288
+ console.log(`šŸ”“ Issues: ${totalIssues} error(s) in ${results.filter((r) => r.issues.length > 0).length} package(s)\n`);
289
+ for (const { pkg, issues } of results.filter((r) => r.issues.length > 0)) {
290
+ console.log(` ${pkg.name}`);
291
+ for (const issue of issues) {
292
+ console.log(` ${issue.message}`);
293
+ if (flags.verbose && issue.expected) {
294
+ console.log(` └─ Expected: ${issue.expected}`);
295
+ }
296
+ }
297
+ console.log();
298
+ }
299
+ }
300
+
301
+ // Print warnings
302
+ if (totalWarnings > 0) {
303
+ console.log(`āš ļø Warnings: ${totalWarnings} non-critical issue(s)\n`);
304
+ if (flags.verbose) {
305
+ for (const { pkg, warnings } of results.filter((r) => r.warnings.length > 0)) {
306
+ console.log(` ${pkg.name}`);
307
+ for (const warning of warnings) {
308
+ console.log(` ${warning.message}`);
309
+ }
310
+ console.log();
311
+ }
312
+ }
313
+ }
314
+
315
+ // Success message
316
+ if (totalIssues === 0 && totalWarnings === 0) {
317
+ console.log('āœ… All packages have required scripts and dependencies!\n');
318
+ } else if (flags.fix) {
319
+ console.log(`āœ… Fixed ${results.filter((r) => r.fixed).length} package(s)\n`);
320
+ console.log('šŸ’” Run "pnpm install" to install new dependencies\n');
321
+ } else {
322
+ console.log('\nšŸ’” Run with --fix to automatically fix issues\n');
323
+ }
324
+ }
325
+
326
+ // Exit code
327
+ if (flags.ci && totalIssues > 0) {
328
+ process.exit(1);
329
+ }
330
+ }
331
+
332
+ main().catch((err) => {
333
+ console.error('Error:', err.message);
334
+ process.exit(1);
335
+ });