buncargo 1.0.29 → 3.2.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 (246) hide show
  1. package/dist/bin.d.ts +1 -12
  2. package/dist/bin.js +261 -253
  3. package/dist/cli/bin.d.ts +13 -0
  4. package/dist/cli/bin.js +317 -0
  5. package/dist/cli/commands/help.d.ts +1 -0
  6. package/dist/cli/commands/runtime.d.ts +5 -0
  7. package/dist/cli/commands/version.d.ts +1 -0
  8. package/dist/cli/index.d.ts +1 -0
  9. package/dist/cli/index.js +14 -0
  10. package/dist/cli/run-cli.d.ts +30 -0
  11. package/dist/cli.d.ts +1 -22
  12. package/dist/cli.js +5 -13
  13. package/dist/config/config.d.ts +1 -0
  14. package/dist/config/define-config.d.ts +13 -0
  15. package/dist/config/index.d.ts +3 -0
  16. package/dist/config/index.js +15 -0
  17. package/dist/config/merge-configs.d.ts +3 -0
  18. package/dist/config/validate-config.d.ts +3 -0
  19. package/dist/config.d.ts +1 -72
  20. package/dist/config.js +12 -12
  21. package/dist/core/docker.d.ts +1 -83
  22. package/dist/core/docker.js +35 -32
  23. package/dist/core/index.d.ts +1 -1
  24. package/dist/core/index.js +123 -118
  25. package/dist/core/network.js +2 -2
  26. package/dist/core/ports.js +1 -1
  27. package/dist/core/process.js +1 -1
  28. package/dist/core/quick-tunnel/cloudflared-process.d.ts +10 -0
  29. package/dist/core/quick-tunnel/constants.d.ts +9 -0
  30. package/dist/core/quick-tunnel/index.d.ts +17 -0
  31. package/dist/core/quick-tunnel/install.d.ts +1 -0
  32. package/dist/core/tunnel.d.ts +34 -0
  33. package/dist/core/utils.js +2 -2
  34. package/dist/core/watchdog-runner.js +45 -42
  35. package/dist/core/watchdog.d.ts +1 -0
  36. package/dist/core/watchdog.js +4 -2
  37. package/dist/docker/index.d.ts +1 -0
  38. package/dist/docker/index.js +38 -0
  39. package/dist/docker/runtime.d.ts +87 -0
  40. package/dist/docker/runtime.js +37 -0
  41. package/dist/docker-compose/compose.d.ts +1 -0
  42. package/dist/docker-compose/generated-file.d.ts +7 -0
  43. package/dist/docker-compose/index.d.ts +3 -0
  44. package/dist/docker-compose/index.js +15 -0
  45. package/dist/docker-compose/model.d.ts +6 -0
  46. package/dist/docker-compose/services/clickhouse.d.ts +16 -0
  47. package/dist/docker-compose/services/define-docker-service.d.ts +41 -0
  48. package/dist/docker-compose/services/index.d.ts +23 -0
  49. package/dist/docker-compose/services/index.js +17 -0
  50. package/dist/docker-compose/services/postgres.d.ts +12 -0
  51. package/dist/docker-compose/services/redis.d.ts +12 -0
  52. package/dist/docker-compose/services/shared.d.ts +7 -0
  53. package/dist/docker-compose/yaml.d.ts +2 -0
  54. package/dist/environment/create-dev-environment.d.ts +23 -0
  55. package/dist/environment/index.d.ts +1 -0
  56. package/dist/environment/index.js +15 -0
  57. package/dist/environment/logging.d.ts +17 -0
  58. package/dist/environment/only-apps.d.ts +10 -0
  59. package/dist/environment/seeding.d.ts +9 -0
  60. package/dist/environment.d.ts +1 -23
  61. package/dist/environment.js +12 -14
  62. package/dist/index-045jksh5.js +147 -0
  63. package/dist/index-08wa79cs.js +125 -117
  64. package/dist/index-0kxnae3z.js +335 -0
  65. package/dist/index-1mdrf7nz.js +51 -43
  66. package/dist/index-1yvbwj4k.js +262 -242
  67. package/dist/index-23ev345g.js +475 -0
  68. package/dist/index-2ckr49sf.js +228 -0
  69. package/dist/index-2f47khe5.js +376 -369
  70. package/dist/index-2fr3g85b.js +220 -183
  71. package/dist/index-38xnzpa6.js +450 -0
  72. package/dist/index-3eyrdxw9.js +577 -0
  73. package/dist/index-3h3dhtf2.js +51 -43
  74. package/dist/index-42x95209.js +51 -43
  75. package/dist/index-4gp0az1g.js +145 -0
  76. package/dist/index-4xrxh8yv.js +72 -0
  77. package/dist/index-5aq985p4.js +250 -0
  78. package/dist/index-5gmws6ah.js +181 -0
  79. package/dist/index-5hka0tff.js +78 -76
  80. package/dist/index-5rfqps4b.js +3 -0
  81. package/dist/index-5t9jxqm0.js +428 -0
  82. package/dist/index-6c1w1xk5.js +101 -0
  83. package/dist/index-6cmex7m5.js +72 -0
  84. package/dist/index-6d6x175r.js +572 -0
  85. package/dist/index-6fm7mvwj.js +118 -97
  86. package/dist/index-6srpc523.js +127 -128
  87. package/dist/index-731rzzfp.js +157 -142
  88. package/dist/index-75y4cg2z.js +51 -43
  89. package/dist/index-7ja4ywyj.js +126 -127
  90. package/dist/index-7v19es2e.js +666 -0
  91. package/dist/index-8bw1cmz4.js +531 -0
  92. package/dist/index-8hbbj1mp.js +120 -121
  93. package/dist/index-8xj2p5n5.js +118 -97
  94. package/dist/index-9wyhzw0h.js +574 -0
  95. package/dist/index-ag90ry8t.js +576 -0
  96. package/dist/index-bj79tw5w.js +0 -0
  97. package/dist/index-bnk6nr0g.js +73 -0
  98. package/dist/index-brbbzyks.js +72 -0
  99. package/dist/index-byeqyjrz.js +72 -0
  100. package/dist/index-c0dr6mcv.js +123 -0
  101. package/dist/index-cty0bcry.js +235 -218
  102. package/dist/index-d8tyv5se.js +228 -0
  103. package/dist/index-d9efy0n4.js +176 -150
  104. package/dist/index-enj4zdma.js +574 -0
  105. package/dist/index-etfmqjjf.js +427 -0
  106. package/dist/index-fb29934k.js +172 -0
  107. package/dist/index-g50jw1yf.js +72 -0
  108. package/dist/index-g6eb5wdw.js +118 -117
  109. package/dist/index-ggq3yryx.js +99 -95
  110. package/dist/index-h70tce00.js +177 -0
  111. package/dist/index-hkxtfqtc.js +333 -0
  112. package/dist/index-k370bech.js +72 -0
  113. package/dist/index-kf3dhser.js +146 -143
  114. package/dist/index-ma6tgdb2.js +500 -0
  115. package/dist/index-mam0bcyz.js +123 -0
  116. package/dist/index-mm412dkp.js +274 -0
  117. package/dist/index-n8v18aeb.js +0 -0
  118. package/dist/index-ndnmnsej.js +378 -371
  119. package/dist/index-p8wty0e2.js +389 -379
  120. package/dist/index-qa8akv6y.js +666 -0
  121. package/dist/index-qfphr2fd.js +78 -76
  122. package/dist/index-qqmms8rs.js +51 -43
  123. package/dist/index-qw4093g2.js +51 -43
  124. package/dist/index-qzwpzjbx.js +121 -122
  125. package/dist/index-segbnm0h.js +146 -143
  126. package/dist/index-t0fj6gg1.js +112 -0
  127. package/dist/index-thdkwnv7.js +122 -0
  128. package/dist/index-tjbx2r2t.js +270 -0
  129. package/dist/index-tjqw9vtj.js +62 -54
  130. package/dist/index-vbpb89jy.js +248 -0
  131. package/dist/index-vg55rq0y.js +250 -0
  132. package/dist/index-vhs88xhe.js +99 -95
  133. package/dist/index-vs81yaks.js +244 -0
  134. package/dist/index-w8zxnjka.js +249 -0
  135. package/dist/index-wk2na3t9.js +385 -375
  136. package/dist/index-wz9x8g7z.js +383 -373
  137. package/dist/index-x249gyde.js +388 -378
  138. package/dist/index-x54nbgs7.js +355 -0
  139. package/dist/index-xkvd0nsd.js +187 -0
  140. package/dist/index-yedqxm1z.js +80 -0
  141. package/dist/index-yz4jfz7z.js +338 -0
  142. package/dist/index-zfjzzjkf.js +240 -199
  143. package/dist/index.d.ts +12 -8
  144. package/dist/index.js +56 -34
  145. package/dist/lint.d.ts +1 -46
  146. package/dist/lint.js +3 -7
  147. package/dist/loader/cache.d.ts +4 -0
  148. package/dist/loader/find-config-file.d.ts +2 -0
  149. package/dist/loader/index.d.ts +5 -0
  150. package/dist/loader/index.js +24 -0
  151. package/dist/loader/load-dev-env.d.ts +5 -0
  152. package/dist/loader/loader.d.ts +1 -0
  153. package/dist/loader.d.ts +1 -45
  154. package/dist/loader.js +22 -20
  155. package/dist/prisma/index.d.ts +1 -0
  156. package/dist/prisma/prisma.d.ts +29 -0
  157. package/dist/prisma.d.ts +1 -29
  158. package/dist/prisma.js +6 -10
  159. package/dist/src/bin.js +309 -0
  160. package/dist/src/cli.js +5 -0
  161. package/dist/src/config.js +15 -0
  162. package/dist/src/core/docker.js +38 -0
  163. package/dist/src/core/index.js +130 -0
  164. package/dist/src/core/network.js +9 -0
  165. package/dist/src/core/ports.js +23 -0
  166. package/dist/src/core/process.js +31 -0
  167. package/dist/src/core/utils.js +11 -0
  168. package/dist/src/core/watchdog-runner.js +69 -0
  169. package/dist/src/core/watchdog.js +28 -0
  170. package/dist/src/docker/runtime.js +37 -0
  171. package/dist/src/docker-compose/index.js +16 -0
  172. package/dist/src/docker-compose/services/index.js +17 -0
  173. package/dist/src/environment.js +12 -0
  174. package/dist/src/index.js +122 -0
  175. package/dist/src/lint.js +3 -0
  176. package/dist/src/loader.js +25 -0
  177. package/dist/src/prisma.js +6 -0
  178. package/dist/src/types.js +0 -0
  179. package/dist/typecheck/index.d.ts +1 -0
  180. package/dist/typecheck/index.js +7 -0
  181. package/dist/typecheck/typecheck.d.ts +46 -0
  182. package/dist/types/all-types.d.ts +544 -0
  183. package/dist/types/cli.d.ts +1 -0
  184. package/dist/types/config.d.ts +6 -0
  185. package/dist/types/docker.d.ts +15 -0
  186. package/dist/types/environment.d.ts +8 -0
  187. package/dist/types/hooks.d.ts +9 -0
  188. package/dist/types/index.d.ts +1 -0
  189. package/dist/types/index.js +0 -0
  190. package/dist/types/prisma.d.ts +1 -0
  191. package/dist/types.d.ts +1 -399
  192. package/package.json +55 -48
  193. package/readme.md +365 -109
  194. package/src/cli/bin.ts +77 -0
  195. package/src/cli/commands/help.ts +39 -0
  196. package/src/cli/commands/runtime.ts +72 -0
  197. package/src/cli/commands/version.ts +4 -0
  198. package/src/cli/index.ts +1 -0
  199. package/{cli.ts → src/cli/run-cli.ts} +114 -10
  200. package/src/config/define-config.ts +30 -0
  201. package/src/config/index.ts +3 -0
  202. package/src/config/merge-configs.ts +33 -0
  203. package/src/config/validate-config.ts +136 -0
  204. package/{core → src/core}/index.ts +2 -2
  205. package/{core → src/core}/ports.ts +5 -2
  206. package/{core → src/core}/process.ts +6 -2
  207. package/src/core/quick-tunnel/cloudflared-process.ts +83 -0
  208. package/src/core/quick-tunnel/constants.ts +31 -0
  209. package/src/core/quick-tunnel/index.ts +96 -0
  210. package/src/core/quick-tunnel/install.ts +160 -0
  211. package/src/core/tunnel.ts +165 -0
  212. package/{core → src/core}/utils.ts +1 -0
  213. package/{core → src/core}/watchdog.ts +5 -1
  214. package/src/docker/index.ts +1 -0
  215. package/{core/docker.ts → src/docker/runtime.ts} +11 -4
  216. package/src/docker-compose/generated-file.ts +45 -0
  217. package/src/docker-compose/index.ts +7 -0
  218. package/src/docker-compose/model.ts +197 -0
  219. package/src/docker-compose/services/clickhouse.ts +79 -0
  220. package/src/docker-compose/services/define-docker-service.ts +109 -0
  221. package/src/docker-compose/services/index.ts +67 -0
  222. package/src/docker-compose/services/postgres.ts +60 -0
  223. package/src/docker-compose/services/redis.ts +48 -0
  224. package/src/docker-compose/services/shared.ts +79 -0
  225. package/src/docker-compose/yaml.ts +88 -0
  226. package/{environment.ts → src/environment/create-dev-environment.ts} +214 -141
  227. package/src/environment/index.ts +1 -0
  228. package/src/environment/logging.ts +115 -0
  229. package/src/environment/only-apps.ts +34 -0
  230. package/src/environment/seeding.ts +57 -0
  231. package/{index.ts → src/index.ts} +52 -20
  232. package/src/loader/cache.ts +23 -0
  233. package/src/loader/find-config-file.ts +29 -0
  234. package/src/loader/index.ts +17 -0
  235. package/src/loader/load-dev-env.ts +38 -0
  236. package/src/prisma/index.ts +1 -0
  237. package/{prisma.ts → src/prisma/prisma.ts} +4 -2
  238. package/src/typecheck/index.ts +1 -0
  239. package/{types.ts → src/types/all-types.ts} +186 -8
  240. package/src/types/index.ts +1 -0
  241. package/bin.ts +0 -192
  242. package/config.ts +0 -194
  243. package/loader.ts +0 -126
  244. /package/{core → src/core}/network.ts +0 -0
  245. /package/{core → src/core}/watchdog-runner.ts +0 -0
  246. /package/{lint.ts → src/typecheck/typecheck.ts} +0 -0
@@ -0,0 +1,228 @@
1
+ import {
2
+ sleep
3
+ } from "./index-c0dr6mcv.js";
4
+
5
+ // src/docker/runtime.ts
6
+ import { execSync } from "node:child_process";
7
+ var POLL_INTERVAL = 250;
8
+ var MAX_ATTEMPTS = 120;
9
+ var DOCKER_NOT_RUNNING_MESSAGE = "Docker is not running. Please start Docker and try again.";
10
+ async function isContainerRunning(project, service) {
11
+ try {
12
+ const result = execSync(`docker ps --filter "label=com.docker.compose.project=${project}" --filter "label=com.docker.compose.service=${service}" --format "{{.State}}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
13
+ return result.trim() === "running";
14
+ } catch {
15
+ return false;
16
+ }
17
+ }
18
+ function isDockerRunning() {
19
+ try {
20
+ execSync('docker info --format "{{.ServerVersion}}"', {
21
+ encoding: "utf-8",
22
+ stdio: ["pipe", "pipe", "pipe"]
23
+ });
24
+ return true;
25
+ } catch {
26
+ return false;
27
+ }
28
+ }
29
+ function assertDockerRunning() {
30
+ if (!isDockerRunning()) {
31
+ throw new Error(DOCKER_NOT_RUNNING_MESSAGE);
32
+ }
33
+ }
34
+ async function areContainersRunning(project, minCount = 1) {
35
+ try {
36
+ const result = execSync(`docker ps --filter "label=com.docker.compose.project=${project}" --format "{{.State}}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
37
+ const states = result.trim().split(`
38
+ `).filter(Boolean);
39
+ if (states.length < minCount)
40
+ return false;
41
+ return states.every((state) => state === "running");
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+ function getComposeArg(composeFile) {
47
+ return composeFile ? `-f "${composeFile}"` : "";
48
+ }
49
+ function startContainers(root, projectName, envVars, options = {}) {
50
+ const { verbose = true, wait = true, composeFile } = options;
51
+ assertDockerRunning();
52
+ if (verbose)
53
+ console.log("\uD83D\uDC33 Starting Docker containers...");
54
+ const composeArg = getComposeArg(composeFile);
55
+ const waitFlag = wait ? "--wait" : "";
56
+ const cmd = `docker compose ${composeArg} up -d ${waitFlag}`.trim();
57
+ execSync(cmd, {
58
+ cwd: root,
59
+ env: { ...process.env, ...envVars, COMPOSE_PROJECT_NAME: projectName },
60
+ stdio: verbose ? "inherit" : "ignore"
61
+ });
62
+ if (verbose)
63
+ console.log("✓ Containers started");
64
+ }
65
+ function stopContainers(root, projectName, options = {}) {
66
+ const { verbose = true, removeVolumes = false, composeFile } = options;
67
+ assertDockerRunning();
68
+ if (verbose) {
69
+ console.log(removeVolumes ? "\uD83D\uDDD1️ Stopping containers and removing volumes..." : "\uD83D\uDED1 Stopping containers...");
70
+ }
71
+ const composeArg = getComposeArg(composeFile);
72
+ const volumeFlag = removeVolumes ? "-v" : "";
73
+ const cmd = `docker compose ${composeArg} down ${volumeFlag}`.trim();
74
+ execSync(cmd, {
75
+ cwd: root,
76
+ env: { ...process.env, COMPOSE_PROJECT_NAME: projectName },
77
+ stdio: verbose ? "inherit" : "ignore"
78
+ });
79
+ if (verbose)
80
+ console.log("✓ Containers stopped");
81
+ }
82
+ function startService(root, projectName, serviceName, envVars, options = {}) {
83
+ const { verbose = true, composeFile } = options;
84
+ assertDockerRunning();
85
+ if (verbose)
86
+ console.log(`\uD83D\uDC33 Starting ${serviceName}...`);
87
+ const composeArg = getComposeArg(composeFile);
88
+ const cmd = `docker compose ${composeArg} up -d ${serviceName}`.trim();
89
+ execSync(cmd, {
90
+ cwd: root,
91
+ env: { ...process.env, ...envVars, COMPOSE_PROJECT_NAME: projectName },
92
+ stdio: verbose ? "inherit" : "ignore"
93
+ });
94
+ }
95
+ function createBuiltInHealthCheck(type, serviceName, context = {}) {
96
+ const { projectName, root } = context;
97
+ switch (type) {
98
+ case "pg_isready":
99
+ return async () => {
100
+ try {
101
+ const projectArg = projectName ? `-p ${projectName}` : "";
102
+ execSync(`docker compose ${projectArg} exec -T ${serviceName} pg_isready -U postgres`, {
103
+ cwd: root,
104
+ stdio: ["pipe", "pipe", "pipe"]
105
+ });
106
+ return true;
107
+ } catch {
108
+ return false;
109
+ }
110
+ };
111
+ case "redis-cli":
112
+ return async () => {
113
+ try {
114
+ const projectArg = projectName ? `-p ${projectName}` : "";
115
+ execSync(`docker compose ${projectArg} exec -T ${serviceName} redis-cli ping`, {
116
+ cwd: root,
117
+ stdio: ["pipe", "pipe", "pipe"]
118
+ });
119
+ return true;
120
+ } catch {
121
+ return false;
122
+ }
123
+ };
124
+ case "http":
125
+ return async (port) => {
126
+ try {
127
+ const controller = new AbortController;
128
+ const timeoutId = setTimeout(() => controller.abort(), 2000);
129
+ try {
130
+ const response = await fetch(`http://localhost:${port}/`, {
131
+ signal: controller.signal
132
+ });
133
+ clearTimeout(timeoutId);
134
+ return response.ok || response.status === 404;
135
+ } catch {
136
+ clearTimeout(timeoutId);
137
+ return false;
138
+ }
139
+ } catch {
140
+ return false;
141
+ }
142
+ };
143
+ case "tcp":
144
+ return async (port) => {
145
+ try {
146
+ const controller = new AbortController;
147
+ const timeoutId = setTimeout(() => controller.abort(), 1000);
148
+ try {
149
+ await fetch(`http://localhost:${port}/`, {
150
+ signal: controller.signal
151
+ });
152
+ clearTimeout(timeoutId);
153
+ return true;
154
+ } catch (error) {
155
+ clearTimeout(timeoutId);
156
+ if (error instanceof Error && error.message.includes("ECONNREFUSED")) {
157
+ return false;
158
+ }
159
+ return true;
160
+ }
161
+ } catch {
162
+ return false;
163
+ }
164
+ };
165
+ default:
166
+ return async () => true;
167
+ }
168
+ }
169
+ async function waitForService(serviceName, config, port, options = {}) {
170
+ const {
171
+ maxAttempts = MAX_ATTEMPTS,
172
+ pollInterval = POLL_INTERVAL,
173
+ projectName,
174
+ root
175
+ } = options;
176
+ if (config.healthCheck === false || config.healthCheck === undefined) {
177
+ return;
178
+ }
179
+ const healthCheckFn = typeof config.healthCheck === "function" ? config.healthCheck : createBuiltInHealthCheck(config.healthCheck, config.serviceName ?? serviceName, { projectName, root });
180
+ for (let i = 0;i < maxAttempts; i++) {
181
+ const isHealthy = await healthCheckFn(port);
182
+ if (isHealthy)
183
+ return;
184
+ await sleep(pollInterval);
185
+ }
186
+ throw new Error(`Service ${serviceName} did not become ready in time`);
187
+ }
188
+ async function waitForAllServices(services, ports, options = {}) {
189
+ const { verbose = true, ...waitOptions } = options;
190
+ if (verbose)
191
+ console.log("⏳ Waiting for services to be healthy...");
192
+ const promises = Object.entries(services).map(([name, config]) => {
193
+ const port = ports[name];
194
+ if (port === undefined) {
195
+ console.warn(`⚠️ No port found for service ${name}, skipping health check`);
196
+ return Promise.resolve();
197
+ }
198
+ return waitForService(name, config, port, waitOptions);
199
+ });
200
+ await Promise.all(promises);
201
+ if (verbose)
202
+ console.log("✓ All services healthy");
203
+ }
204
+ async function waitForServiceByType(serviceName, healthCheckType, port, options = {}) {
205
+ const {
206
+ maxAttempts = MAX_ATTEMPTS,
207
+ pollInterval = POLL_INTERVAL,
208
+ verbose = false,
209
+ projectName,
210
+ root
211
+ } = options;
212
+ const healthCheckFn = createBuiltInHealthCheck(healthCheckType, serviceName, {
213
+ projectName,
214
+ root
215
+ });
216
+ for (let i = 0;i < maxAttempts; i++) {
217
+ const isHealthy = await healthCheckFn(port);
218
+ if (isHealthy) {
219
+ if (verbose)
220
+ console.log(`✓ ${serviceName} is ready`);
221
+ return;
222
+ }
223
+ await sleep(pollInterval);
224
+ }
225
+ throw new Error(`Service ${serviceName} did not become ready in time`);
226
+ }
227
+
228
+ export { POLL_INTERVAL, MAX_ATTEMPTS, DOCKER_NOT_RUNNING_MESSAGE, isContainerRunning, isDockerRunning, assertDockerRunning, areContainersRunning, getComposeArg, startContainers, stopContainers, startService, createBuiltInHealthCheck, waitForService, waitForAllServices, waitForServiceByType };
@@ -3,176 +3,202 @@ import { execSync } from "node:child_process";
3
3
  import { readFileSync, unlinkSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import fg from "fast-glob";
6
+
6
7
  var DEFAULT_PATTERNS = ["apps/*", "packages/*", "modules"];
7
8
  var DEFAULT_CONCURRENCY = 1;
8
9
  var CORRUPTED_CACHE_PATTERNS = [
9
- "all goroutines are asleep - deadlock",
10
- "fatal error:",
11
- "panic:",
12
- "github.com/microsoft/typescript-go"
10
+ "all goroutines are asleep - deadlock",
11
+ "fatal error:",
12
+ "panic:",
13
+ "github.com/microsoft/typescript-go",
13
14
  ];
14
15
  function isCorruptedCacheError(output) {
15
- return CORRUPTED_CACHE_PATTERNS.some((pattern) => output.includes(pattern));
16
+ return CORRUPTED_CACHE_PATTERNS.some((pattern) => output.includes(pattern));
16
17
  }
17
18
  async function clearTsBuildInfo(workspace, verbose) {
18
- if (verbose) {
19
- console.log(`\uD83E\uDDF9 Clearing corrupted tsbuildinfo cache for ${workspace}...`);
20
- }
21
- try {
22
- const tsbuildInfoFiles = await fg(`${workspace}/**/*.tsbuildinfo`, {
23
- absolute: true
24
- });
25
- for (const file of tsbuildInfoFiles) {
26
- try {
27
- unlinkSync(file);
28
- } catch {}
29
- }
30
- const cacheFiles = await fg(`${workspace}/**/.cache/tsbuildinfo.json`, {
31
- absolute: true
32
- });
33
- for (const file of cacheFiles) {
34
- try {
35
- unlinkSync(file);
36
- } catch {}
37
- }
38
- } catch {}
19
+ if (verbose) {
20
+ console.log(
21
+ `\uD83E\uDDF9 Clearing corrupted tsbuildinfo cache for ${workspace}...`,
22
+ );
23
+ }
24
+ try {
25
+ const tsbuildInfoFiles = await fg(`${workspace}/**/*.tsbuildinfo`, {
26
+ absolute: true,
27
+ });
28
+ for (const file of tsbuildInfoFiles) {
29
+ try {
30
+ unlinkSync(file);
31
+ } catch {}
32
+ }
33
+ const cacheFiles = await fg(`${workspace}/**/.cache/tsbuildinfo.json`, {
34
+ absolute: true,
35
+ });
36
+ for (const file of cacheFiles) {
37
+ try {
38
+ unlinkSync(file);
39
+ } catch {}
40
+ }
41
+ } catch {}
39
42
  }
40
43
  async function countTypeScriptFiles(pkgPath, root) {
41
- const files = await fg(`${pkgPath}/**/*.{ts,tsx}`, {
42
- cwd: root,
43
- ignore: ["**/node_modules/**"]
44
- });
45
- return files.length;
44
+ const files = await fg(`${pkgPath}/**/*.{ts,tsx}`, {
45
+ cwd: root,
46
+ ignore: ["**/node_modules/**"],
47
+ });
48
+ return files.length;
46
49
  }
47
50
  function formatErrorOutput(output) {
48
- return output.split(`
49
- `).map((line) => {
50
- return line.replace(/\.\.\/\.\.\/packages\/modules\//g, "").replace(/\((\d+),(\d+)\):?/g, ":$1:$2 -");
51
- }).join(`
52
- `).trim();
51
+ return output
52
+ .split(`
53
+ `)
54
+ .map((line) => {
55
+ return line
56
+ .replace(/\.\.\/\.\.\/packages\/modules\//g, "")
57
+ .replace(/\((\d+),(\d+)\):?/g, ":$1:$2 -");
58
+ })
59
+ .join(`
60
+ `)
61
+ .trim();
53
62
  }
54
- async function runSingleTypecheck(workspace, fileCount, root, verbose, isRetry = false) {
55
- const startTime = performance.now();
56
- if (verbose) {
57
- console.log(`Running typecheck in ${workspace} (${fileCount} files)${isRetry ? " (retry)" : ""}...`);
58
- }
59
- const workspacePath = join(root, workspace);
60
- let success = false;
61
- let stdout = "";
62
- let stderr = "";
63
- try {
64
- const output = execSync("bun run typecheck", {
65
- cwd: workspacePath,
66
- encoding: "utf-8",
67
- stdio: ["pipe", "pipe", "pipe"]
68
- });
69
- stdout = output ?? "";
70
- success = true;
71
- } catch (error) {
72
- const execError = error;
73
- stdout = execError.stdout ?? "";
74
- stderr = execError.stderr ?? "";
75
- success = false;
76
- }
77
- const duration = Number(((performance.now() - startTime) / 1000).toFixed(2));
78
- let errorOutput;
79
- if (!success) {
80
- const parts = [stdout.trim(), stderr.trim()].filter(Boolean);
81
- errorOutput = parts.length > 0 ? parts.join(`
82
- `) : undefined;
83
- if (!isRetry && errorOutput && isCorruptedCacheError(errorOutput)) {
84
- await clearTsBuildInfo(workspacePath, verbose);
85
- return runSingleTypecheck(workspace, fileCount, root, verbose, true);
86
- }
87
- }
88
- return { workspace, duration, success, fileCount, errorOutput };
63
+ async function runSingleTypecheck(
64
+ workspace,
65
+ fileCount,
66
+ root,
67
+ verbose,
68
+ isRetry = false,
69
+ ) {
70
+ const startTime = performance.now();
71
+ if (verbose) {
72
+ console.log(
73
+ `Running typecheck in ${workspace} (${fileCount} files)${isRetry ? " (retry)" : ""}...`,
74
+ );
75
+ }
76
+ const workspacePath = join(root, workspace);
77
+ let success = false;
78
+ let stdout = "";
79
+ let stderr = "";
80
+ try {
81
+ const output = execSync("bun run typecheck", {
82
+ cwd: workspacePath,
83
+ encoding: "utf-8",
84
+ stdio: ["pipe", "pipe", "pipe"],
85
+ });
86
+ stdout = output ?? "";
87
+ success = true;
88
+ } catch (error) {
89
+ const execError = error;
90
+ stdout = execError.stdout ?? "";
91
+ stderr = execError.stderr ?? "";
92
+ success = false;
93
+ }
94
+ const duration = Number(((performance.now() - startTime) / 1000).toFixed(2));
95
+ let errorOutput;
96
+ if (!success) {
97
+ const parts = [stdout.trim(), stderr.trim()].filter(Boolean);
98
+ errorOutput =
99
+ parts.length > 0
100
+ ? parts.join(`
101
+ `)
102
+ : undefined;
103
+ if (!isRetry && errorOutput && isCorruptedCacheError(errorOutput)) {
104
+ await clearTsBuildInfo(workspacePath, verbose);
105
+ return runSingleTypecheck(workspace, fileCount, root, verbose, true);
106
+ }
107
+ }
108
+ return { workspace, duration, success, fileCount, errorOutput };
89
109
  }
90
110
  async function discoverWorkspaces(patterns, root) {
91
- const workspaces = [];
92
- for (const pattern of patterns) {
93
- const matches = await fg(`${pattern}/package.json`, { cwd: root });
94
- for (const match of matches) {
95
- const pkgPath = match.replace("/package.json", "");
96
- try {
97
- const pkgJsonContent = readFileSync(join(root, match), "utf-8");
98
- const pkgJson = JSON.parse(pkgJsonContent);
99
- if (pkgJson.scripts?.typecheck) {
100
- const fileCount = await countTypeScriptFiles(pkgPath, root);
101
- workspaces.push({ path: pkgPath, fileCount });
102
- }
103
- } catch {}
104
- }
105
- }
106
- workspaces.sort((a, b) => a.fileCount - b.fileCount);
107
- return workspaces;
111
+ const workspaces = [];
112
+ for (const pattern of patterns) {
113
+ const matches = await fg(`${pattern}/package.json`, { cwd: root });
114
+ for (const match of matches) {
115
+ const pkgPath = match.replace("/package.json", "");
116
+ try {
117
+ const pkgJsonContent = readFileSync(join(root, match), "utf-8");
118
+ const pkgJson = JSON.parse(pkgJsonContent);
119
+ if (pkgJson.scripts?.typecheck) {
120
+ const fileCount = await countTypeScriptFiles(pkgPath, root);
121
+ workspaces.push({ path: pkgPath, fileCount });
122
+ }
123
+ } catch {}
124
+ }
125
+ }
126
+ workspaces.sort((a, b) => a.fileCount - b.fileCount);
127
+ return workspaces;
108
128
  }
109
129
  async function runWorkspaceTypecheck(options = {}) {
110
- const {
111
- root = process.cwd(),
112
- patterns = DEFAULT_PATTERNS,
113
- concurrency = DEFAULT_CONCURRENCY,
114
- verbose = true
115
- } = options;
116
- const workspaces = await discoverWorkspaces(patterns, root);
117
- if (workspaces.length === 0) {
118
- if (verbose) {
119
- console.log("No workspaces with typecheck script found.");
120
- }
121
- return {
122
- success: true,
123
- totalDuration: 0,
124
- totalFiles: 0,
125
- workspaceCount: 0,
126
- results: []
127
- };
128
- }
129
- const totalStartTime = performance.now();
130
- if (verbose) {
131
- console.log(`Running typecheck across ${workspaces.length} workspaces with concurrency limit of ${concurrency}...
130
+ const {
131
+ root = process.cwd(),
132
+ patterns = DEFAULT_PATTERNS,
133
+ concurrency = DEFAULT_CONCURRENCY,
134
+ verbose = true,
135
+ } = options;
136
+ const workspaces = await discoverWorkspaces(patterns, root);
137
+ if (workspaces.length === 0) {
138
+ if (verbose) {
139
+ console.log("No workspaces with typecheck script found.");
140
+ }
141
+ return {
142
+ success: true,
143
+ totalDuration: 0,
144
+ totalFiles: 0,
145
+ workspaceCount: 0,
146
+ results: [],
147
+ };
148
+ }
149
+ const totalStartTime = performance.now();
150
+ if (verbose) {
151
+ console.log(`Running typecheck across ${workspaces.length} workspaces with concurrency limit of ${concurrency}...
132
152
  `);
133
- }
134
- const results = [];
135
- const running = new Set;
136
- for (let i = 0;i < workspaces.length; i++) {
137
- const { path, fileCount } = workspaces[i];
138
- const promise = runSingleTypecheck(path, fileCount, root, verbose).then((result) => {
139
- results[i] = result;
140
- running.delete(promise);
141
- if (verbose) {
142
- const icon = result.success ? "✅" : "❌";
143
- const log = result.success ? console.log : console.error;
144
- log(`${icon} ${result.workspace} (${result.fileCount} files) ${result.success ? "completed" : "failed"} in ${result.duration.toFixed(2)}s`);
145
- if (!result.success && result.errorOutput) {
146
- console.error(`
153
+ }
154
+ const results = [];
155
+ const running = new Set();
156
+ for (let i = 0; i < workspaces.length; i++) {
157
+ const { path, fileCount } = workspaces[i];
158
+ const promise = runSingleTypecheck(path, fileCount, root, verbose).then(
159
+ (result) => {
160
+ results[i] = result;
161
+ running.delete(promise);
162
+ if (verbose) {
163
+ const icon = result.success ? "✅" : "❌";
164
+ const log = result.success ? console.log : console.error;
165
+ log(
166
+ `${icon} ${result.workspace} (${result.fileCount} files) ${result.success ? "completed" : "failed"} in ${result.duration.toFixed(2)}s`,
167
+ );
168
+ if (!result.success && result.errorOutput) {
169
+ console.error(`
147
170
  ${formatErrorOutput(result.errorOutput)}`);
148
- }
149
- }
150
- });
151
- running.add(promise);
152
- if (running.size >= concurrency) {
153
- await Promise.race(running);
154
- }
155
- }
156
- await Promise.all(running);
157
- const totalDuration = Number(((performance.now() - totalStartTime) / 1000).toFixed(2));
158
- const totalFiles = workspaces.reduce((sum, w) => sum + w.fileCount, 0);
159
- const success = results.every((r) => r.success);
160
- if (verbose) {
161
- if (success) {
162
- console.log(`
171
+ }
172
+ }
173
+ },
174
+ );
175
+ running.add(promise);
176
+ if (running.size >= concurrency) {
177
+ await Promise.race(running);
178
+ }
179
+ }
180
+ await Promise.all(running);
181
+ const totalDuration = Number(
182
+ ((performance.now() - totalStartTime) / 1000).toFixed(2),
183
+ );
184
+ const totalFiles = workspaces.reduce((sum, w) => sum + w.fileCount, 0);
185
+ const success = results.every((r) => r.success);
186
+ if (verbose) {
187
+ if (success) {
188
+ console.log(`
163
189
  All typecheck checks passed! Total time: ${totalDuration}s (${totalFiles} files)`);
164
- } else {
165
- console.error(`
190
+ } else {
191
+ console.error(`
166
192
  Typecheck failed. Total time: ${totalDuration}s`);
167
- }
168
- }
169
- return {
170
- success,
171
- totalDuration,
172
- totalFiles,
173
- workspaceCount: workspaces.length,
174
- results
175
- };
193
+ }
194
+ }
195
+ return {
196
+ success,
197
+ totalDuration,
198
+ totalFiles,
199
+ workspaceCount: workspaces.length,
200
+ results,
201
+ };
176
202
  }
177
203
 
178
204
  export { runWorkspaceTypecheck };