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,577 @@
1
+ import {
2
+ areContainersRunning,
3
+ isContainerRunning,
4
+ startContainers,
5
+ startService,
6
+ stopContainers,
7
+ waitForServiceByType
8
+ } from "./index-d8tyv5se.js";
9
+ import {
10
+ getLocalIp,
11
+ isCI,
12
+ logExpoApiUrl,
13
+ logFrontendPort,
14
+ waitForDevServers,
15
+ waitForServer
16
+ } from "./index-c0dr6mcv.js";
17
+ import {
18
+ computeDevIdentity,
19
+ computePorts,
20
+ computeUrls,
21
+ findMonorepoRoot
22
+ } from "./index-fb29934k.js";
23
+ import {
24
+ getGeneratedComposePath,
25
+ writeGeneratedComposeFile
26
+ } from "./index-5t9jxqm0.js";
27
+ import {
28
+ spawnWatchdog,
29
+ startHeartbeat,
30
+ stopHeartbeat,
31
+ stopWatchdog
32
+ } from "./index-mam0bcyz.js";
33
+ import {
34
+ buildApps,
35
+ execAsync,
36
+ startDevServers,
37
+ stopProcess
38
+ } from "./index-mm412dkp.js";
39
+ import {
40
+ assertValidConfig
41
+ } from "./index-t0fj6gg1.js";
42
+
43
+ // src/prisma/prisma.ts
44
+ import { spawn } from "node:child_process";
45
+ import { join } from "node:path";
46
+ function createPrismaRunner(env, config) {
47
+ const {
48
+ cwd = "packages/prisma",
49
+ service = "postgres",
50
+ urlEnvVar = "DATABASE_URL"
51
+ } = config;
52
+ const healthCheckTypes = {
53
+ postgres: "pg_isready",
54
+ redis: "redis-cli",
55
+ clickhouse: "http"
56
+ };
57
+ function getDatabaseUrl() {
58
+ const envVars = env.buildEnvVars();
59
+ const url = envVars[urlEnvVar];
60
+ if (!url) {
61
+ throw new Error(`Environment variable ${urlEnvVar} not found. Make sure your dev config defines it in envVars.`);
62
+ }
63
+ return url;
64
+ }
65
+ async function ensureDatabase() {
66
+ const alreadyRunning = await isContainerRunning(env.projectName, service);
67
+ if (alreadyRunning) {
68
+ console.log(`✓ ${service} already running`);
69
+ return;
70
+ }
71
+ console.log(`\uD83D\uDC33 Starting ${service}...`);
72
+ const composeFile = env.ensureComposeFile();
73
+ const envVars = env.buildEnvVars();
74
+ startService(env.root, env.projectName, service, envVars, {
75
+ verbose: false,
76
+ composeFile
77
+ });
78
+ const port = env.ports[service];
79
+ if (!port) {
80
+ throw new Error(`Service ${service} not found in dev environment ports`);
81
+ }
82
+ const healthCheckType = healthCheckTypes[service] ?? "tcp";
83
+ console.log(`⏳ Waiting for ${service} to be healthy...`);
84
+ await waitForServiceByType(service, healthCheckType, port, {
85
+ verbose: true
86
+ });
87
+ }
88
+ async function run(args) {
89
+ if (args.length === 0) {
90
+ console.log(`
91
+ Usage: bun prisma <command> [args...]
92
+
93
+ Examples:
94
+ bun prisma migrate dev # Create new migration
95
+ bun prisma migrate deploy # Apply migrations
96
+ bun prisma db push # Push schema changes
97
+ bun prisma studio # Open Prisma Studio
98
+ bun prisma migrate reset # Reset database
99
+ `);
100
+ return 0;
101
+ }
102
+ const port = env.ports[service];
103
+ console.log(`
104
+ \uD83D\uDD27 Prisma CLI
105
+ Project: ${env.projectName}
106
+ Database: localhost:${port}
107
+ ${env.portOffset > 0 ? `(port offset +${env.portOffset})` : ""}
108
+ `);
109
+ await ensureDatabase();
110
+ const envVars = env.buildEnvVars();
111
+ const workingDir = join(env.root, cwd);
112
+ const fullEnv = {
113
+ ...process.env,
114
+ ...envVars,
115
+ [urlEnvVar]: getDatabaseUrl()
116
+ };
117
+ console.log(`\uD83D\uDD04 Running: prisma ${args.join(" ")}
118
+ `);
119
+ return new Promise((resolve) => {
120
+ const proc = spawn("bunx", ["prisma", ...args], {
121
+ cwd: workingDir,
122
+ env: fullEnv,
123
+ stdio: "inherit"
124
+ });
125
+ proc.on("close", (code) => {
126
+ resolve(code ?? 0);
127
+ });
128
+ proc.on("error", () => {
129
+ resolve(1);
130
+ });
131
+ });
132
+ }
133
+ return { run, getDatabaseUrl, ensureDatabase };
134
+ }
135
+ // src/environment/logging.ts
136
+ import pc from "picocolors";
137
+ function formatUrl(url) {
138
+ return pc.cyan(url.replace(/:(\d+)(\/?)/, (_, port, slash) => `:${pc.bold(port)}${slash}`));
139
+ }
140
+ function formatLabel(label, value, arrow = "➜") {
141
+ return ` ${pc.green(arrow)} ${pc.bold(label.padEnd(10))} ${value}`;
142
+ }
143
+ function formatDimLabel(label, value) {
144
+ return ` ${pc.dim("•")} ${pc.dim(label.padEnd(10))} ${pc.dim(value)}`;
145
+ }
146
+ function tunnelFor(tunnels, name, kind) {
147
+ return tunnels?.find((t) => t.name === name && t.kind === kind);
148
+ }
149
+ function logEnvironmentInfo(input) {
150
+ const {
151
+ label,
152
+ projectName,
153
+ services,
154
+ apps,
155
+ ports,
156
+ localIp,
157
+ worktree,
158
+ portOffset,
159
+ projectSuffix,
160
+ tunnels
161
+ } = input;
162
+ const serviceNames = Object.keys(services);
163
+ const appNames = Object.keys(apps);
164
+ console.log("");
165
+ console.log(` ${pc.cyan(pc.bold(`\uD83D\uDC33 ${label}`))}`);
166
+ console.log(formatLabel("Project:", pc.white(projectName)));
167
+ if (serviceNames.length > 0) {
168
+ console.log("");
169
+ console.log(` ${pc.dim("─── Services ───")}`);
170
+ for (const name of serviceNames) {
171
+ const port = ports[name];
172
+ const url = `localhost:${port}`;
173
+ console.log(formatLabel(`${name}:`, formatUrl(`http://${url}`)));
174
+ const t = tunnelFor(tunnels, name, "service");
175
+ if (t) {
176
+ console.log(` ${pc.dim("Public:")} ${formatUrl(t.publicUrl)} ${pc.dim("(tunnel)")}`);
177
+ }
178
+ }
179
+ }
180
+ if (appNames.length > 0) {
181
+ console.log("");
182
+ console.log(` ${pc.dim("─── Applications ───")}`);
183
+ for (const name of appNames) {
184
+ const port = ports[name];
185
+ const localUrl = `http://localhost:${port}`;
186
+ const networkUrl = `http://${localIp}:${port}`;
187
+ console.log(` ${pc.green("➜")} ${pc.bold(pc.cyan(name))}`);
188
+ console.log(` ${pc.dim("Local:")} ${formatUrl(localUrl)}`);
189
+ console.log(` ${pc.dim("Network:")} ${formatUrl(networkUrl)}`);
190
+ const t = tunnelFor(tunnels, name, "app");
191
+ if (t) {
192
+ console.log(` ${pc.dim("Public:")} ${formatUrl(t.publicUrl)} ${pc.dim("(tunnel)")}`);
193
+ }
194
+ }
195
+ }
196
+ console.log("");
197
+ console.log(` ${pc.dim("─── Environment ───")}`);
198
+ console.log(formatDimLabel("Worktree:", worktree ? "yes" : "no"));
199
+ console.log(formatDimLabel("Port offset:", portOffset > 0 ? `+${portOffset}` : "none"));
200
+ if (projectSuffix) {
201
+ console.log(formatDimLabel("Suffix:", projectSuffix));
202
+ }
203
+ console.log(formatDimLabel("Local IP:", localIp));
204
+ console.log("");
205
+ }
206
+
207
+ // src/environment/seeding.ts
208
+ function createCheckTableHelper(urls, exec) {
209
+ return async (tableName, service) => {
210
+ const serviceName = service ?? "postgres";
211
+ const serviceUrl = urls[serviceName];
212
+ if (!serviceUrl) {
213
+ console.warn(`⚠️ Service "${serviceName}" not found for checkTable`);
214
+ return true;
215
+ }
216
+ const checkResult = await exec(`psql "${serviceUrl}" -tAc 'SELECT COUNT(*) FROM "${tableName}" LIMIT 1'`, { throwOnError: false });
217
+ const count = checkResult.stdout.trim();
218
+ const shouldSeed = checkResult.exitCode !== 0 || count === "0" || count === "";
219
+ if (!shouldSeed) {
220
+ console.log(` \uD83D\uDCCA Table "${tableName}" has ${count} rows`);
221
+ }
222
+ return shouldSeed;
223
+ };
224
+ }
225
+ function createSeedCheckContext(baseContext, checkTable) {
226
+ return {
227
+ ...baseContext,
228
+ checkTable
229
+ };
230
+ }
231
+
232
+ // src/environment/create-dev-environment.ts
233
+ function createDevEnvironment(config, options = {}) {
234
+ assertValidConfig(config);
235
+ const root = findMonorepoRoot();
236
+ const suffix = options.suffix;
237
+ const identity = computeDevIdentity({
238
+ projectPrefix: config.projectPrefix,
239
+ suffix,
240
+ root,
241
+ worktreeIsolation: config.options?.worktreeIsolation
242
+ });
243
+ const { worktree, projectSuffix, portOffset, projectName } = identity;
244
+ const localIp = getLocalIp();
245
+ const services = config.services;
246
+ const apps = config.apps ?? {};
247
+ const composeFile = getGeneratedComposePath(root, config.docker).composeFileArg;
248
+ function ensureComposeFile() {
249
+ return writeGeneratedComposeFile(root, services, config.docker);
250
+ }
251
+ const ports = computePorts(services, apps, portOffset);
252
+ const urls = computeUrls(services, apps, ports, localIp);
253
+ const publicUrls = {};
254
+ function setPublicUrls(urlsInput) {
255
+ for (const key of Object.keys(publicUrls)) {
256
+ delete publicUrls[key];
257
+ }
258
+ for (const [key, value] of Object.entries(urlsInput)) {
259
+ publicUrls[key] = value;
260
+ }
261
+ }
262
+ function clearPublicUrls() {
263
+ for (const key of Object.keys(publicUrls)) {
264
+ delete publicUrls[key];
265
+ }
266
+ }
267
+ function buildEnvVars(production = false) {
268
+ const baseEnv = {
269
+ COMPOSE_PROJECT_NAME: projectName,
270
+ NODE_ENV: production ? "production" : "development"
271
+ };
272
+ for (const [name, port] of Object.entries(ports)) {
273
+ const envName = `${name.toUpperCase()}_PORT`;
274
+ baseEnv[envName] = String(port);
275
+ }
276
+ for (const [name, url] of Object.entries(urls)) {
277
+ const envName = `${name.toUpperCase()}_URL`;
278
+ baseEnv[envName] = url;
279
+ }
280
+ for (const [name, url] of Object.entries(publicUrls)) {
281
+ const envName = `${name.toUpperCase()}_PUBLIC_URL`;
282
+ baseEnv[envName] = url;
283
+ }
284
+ if (config.envVars) {
285
+ const userEnv = config.envVars(ports, urls, {
286
+ projectName,
287
+ localIp,
288
+ portOffset,
289
+ publicUrls
290
+ });
291
+ for (const [key, value] of Object.entries(userEnv)) {
292
+ baseEnv[key] = String(value);
293
+ }
294
+ }
295
+ return baseEnv;
296
+ }
297
+ let hookContext = null;
298
+ function getHookContext() {
299
+ if (!hookContext) {
300
+ hookContext = {
301
+ projectName,
302
+ ports,
303
+ urls,
304
+ publicUrls,
305
+ root,
306
+ isCI: isCI(),
307
+ portOffset,
308
+ localIp,
309
+ exec: async (cmd, opts) => {
310
+ const envVars = buildEnvVars();
311
+ return execAsync(cmd, root, envVars, opts);
312
+ }
313
+ };
314
+ }
315
+ return hookContext;
316
+ }
317
+ function exec(cmd, options2) {
318
+ const envVars = buildEnvVars();
319
+ return execAsync(cmd, root, envVars, options2);
320
+ }
321
+ async function start(startOptions = {}) {
322
+ const isCI2 = process.env.CI === "true";
323
+ const {
324
+ verbose = config.options?.verbose ?? true,
325
+ wait = true,
326
+ startServers: shouldStartServers = true,
327
+ productionBuild = isCI2,
328
+ skipSeed = false,
329
+ skipEnvironmentLog = false
330
+ } = startOptions;
331
+ const envVars = buildEnvVars(productionBuild);
332
+ ensureComposeFile();
333
+ if (verbose && !skipEnvironmentLog) {
334
+ logInfo(productionBuild ? "Production Environment" : "Dev Environment");
335
+ }
336
+ const serviceCount = Object.keys(services).length;
337
+ const alreadyRunning = await areContainersRunning(projectName, serviceCount);
338
+ if (alreadyRunning) {
339
+ if (verbose)
340
+ console.log("✓ Containers already running");
341
+ } else {
342
+ startContainers(root, projectName, envVars, {
343
+ verbose,
344
+ wait,
345
+ composeFile
346
+ });
347
+ }
348
+ const allMigrations = [
349
+ ...config.prisma ? [
350
+ {
351
+ name: "prisma",
352
+ command: "bunx prisma migrate deploy",
353
+ cwd: config.prisma.cwd ?? "packages/prisma"
354
+ }
355
+ ] : [],
356
+ ...config.migrations ?? []
357
+ ];
358
+ if (allMigrations.length > 0) {
359
+ if (verbose)
360
+ console.log("\uD83D\uDCE6 Running migrations...");
361
+ const migrationResults = await Promise.all(allMigrations.map(async (migration) => {
362
+ const result = await exec(migration.command, {
363
+ cwd: migration.cwd,
364
+ throwOnError: false
365
+ });
366
+ return { name: migration.name, result };
367
+ }));
368
+ for (const { name, result } of migrationResults) {
369
+ if (result.exitCode !== 0) {
370
+ console.error(`❌ Migration "${name}" failed`);
371
+ if (result.stdout) {
372
+ console.error(result.stdout);
373
+ }
374
+ if (result.stderr) {
375
+ console.error(result.stderr);
376
+ }
377
+ throw new Error(`Migration "${name}" failed`);
378
+ }
379
+ }
380
+ if (verbose)
381
+ console.log("✓ Migrations complete");
382
+ }
383
+ if (config.hooks?.afterContainersReady) {
384
+ await config.hooks.afterContainersReady(getHookContext());
385
+ }
386
+ if (config.seed && !skipSeed) {
387
+ let shouldSeed = true;
388
+ if (config.seed.check) {
389
+ const checkTable = createCheckTableHelper(urls, exec);
390
+ const seedCheckContext = createSeedCheckContext(getHookContext(), checkTable);
391
+ shouldSeed = await config.seed.check(seedCheckContext);
392
+ }
393
+ if (shouldSeed) {
394
+ if (verbose)
395
+ console.log("\uD83C\uDF31 Running seeders...");
396
+ const seedResult = await exec(config.seed.command, {
397
+ cwd: config.seed.cwd,
398
+ verbose,
399
+ throwOnError: false
400
+ });
401
+ if (seedResult.exitCode !== 0) {
402
+ console.error("❌ Seeding failed");
403
+ console.error(seedResult.stderr);
404
+ } else {
405
+ if (verbose)
406
+ console.log("✓ Seeding complete");
407
+ }
408
+ } else {
409
+ if (verbose)
410
+ console.log("✓ Database already has data, skipping seeders");
411
+ }
412
+ }
413
+ if (shouldStartServers && Object.keys(apps).length > 0) {
414
+ if (config.hooks?.beforeServers) {
415
+ await config.hooks.beforeServers(getHookContext());
416
+ }
417
+ if (productionBuild) {
418
+ buildApps(apps, root, envVars, { verbose });
419
+ }
420
+ const pids = await startDevServers(apps, root, envVars, ports, {
421
+ verbose,
422
+ productionBuild,
423
+ isCI: isCI2
424
+ });
425
+ if (verbose)
426
+ console.log("⏳ Waiting for servers to be ready...");
427
+ await waitForDevServers(apps, ports, {
428
+ timeout: isCI2 ? 120000 : 60000,
429
+ verbose,
430
+ productionBuild
431
+ });
432
+ if (config.hooks?.afterServers) {
433
+ await config.hooks.afterServers(getHookContext());
434
+ }
435
+ if (verbose)
436
+ console.log(`✅ Environment ready
437
+ `);
438
+ return pids;
439
+ }
440
+ if (verbose)
441
+ console.log(`✅ Containers ready
442
+ `);
443
+ return null;
444
+ }
445
+ async function stop(stopOptions = {}) {
446
+ const { verbose = true, removeVolumes = false } = stopOptions;
447
+ ensureComposeFile();
448
+ if (config.hooks?.beforeStop) {
449
+ await config.hooks.beforeStop(getHookContext());
450
+ }
451
+ stopContainers(root, projectName, {
452
+ verbose,
453
+ removeVolumes,
454
+ composeFile
455
+ });
456
+ }
457
+ async function restart() {
458
+ await stop();
459
+ await start({ startServers: false });
460
+ }
461
+ async function isRunning() {
462
+ const serviceCount = Object.keys(services).length;
463
+ return areContainersRunning(projectName, serviceCount);
464
+ }
465
+ async function startServersOnly(options2 = {}) {
466
+ const { productionBuild = false, verbose = true } = options2;
467
+ const envVars = buildEnvVars(productionBuild);
468
+ const isCI2 = process.env.CI === "true";
469
+ if (productionBuild) {
470
+ buildApps(apps, root, envVars, { verbose });
471
+ }
472
+ return startDevServers(apps, root, envVars, ports, {
473
+ verbose,
474
+ productionBuild,
475
+ isCI: isCI2
476
+ });
477
+ }
478
+ async function waitForServersReady(options2 = {}) {
479
+ const { timeout = 60000, productionBuild = false } = options2;
480
+ await waitForDevServers(apps, ports, { timeout, productionBuild });
481
+ }
482
+ function logInfo(label = "Docker Dev", tunnels) {
483
+ const tunnelRows = tunnels?.map(({ kind, name, localUrl, publicUrl }) => ({
484
+ kind,
485
+ name,
486
+ localUrl,
487
+ publicUrl
488
+ }));
489
+ logEnvironmentInfo({
490
+ label,
491
+ projectName,
492
+ services,
493
+ apps,
494
+ ports,
495
+ localIp,
496
+ worktree,
497
+ portOffset,
498
+ projectSuffix,
499
+ tunnels: tunnelRows
500
+ });
501
+ }
502
+ async function waitForServerUrl(url, timeout) {
503
+ await waitForServer(url, { timeout });
504
+ }
505
+ function startHeartbeat2(intervalMs) {
506
+ startHeartbeat(projectName, intervalMs);
507
+ }
508
+ function stopHeartbeat2() {
509
+ stopHeartbeat();
510
+ }
511
+ async function spawnWatchdog2(timeoutMinutes) {
512
+ await spawnWatchdog(projectName, root, {
513
+ timeoutMinutes,
514
+ verbose: true,
515
+ composeFile
516
+ });
517
+ }
518
+ function stopWatchdog2() {
519
+ stopWatchdog(projectName);
520
+ }
521
+ function getExpoApiUrl() {
522
+ const apiPort = ports.api;
523
+ const url = `http://${localIp}:${apiPort}`;
524
+ logExpoApiUrl(url);
525
+ return url;
526
+ }
527
+ function getFrontendPort() {
528
+ const port = ports.platform;
529
+ logFrontendPort(port);
530
+ return port;
531
+ }
532
+ function withSuffix(newSuffix) {
533
+ return createDevEnvironment(config, { suffix: newSuffix });
534
+ }
535
+ const env = {
536
+ projectName,
537
+ ports,
538
+ urls,
539
+ publicUrls,
540
+ services,
541
+ apps,
542
+ portOffset,
543
+ isWorktree: worktree,
544
+ localIp,
545
+ root,
546
+ composeFile,
547
+ start,
548
+ stop,
549
+ restart,
550
+ isRunning,
551
+ startServers: startServersOnly,
552
+ stopProcess,
553
+ waitForServers: waitForServersReady,
554
+ buildEnvVars,
555
+ setPublicUrls: (urlsInput) => {
556
+ setPublicUrls(urlsInput);
557
+ },
558
+ clearPublicUrls,
559
+ ensureComposeFile,
560
+ exec,
561
+ waitForServer: waitForServerUrl,
562
+ logInfo,
563
+ getExpoApiUrl,
564
+ getFrontendPort,
565
+ startHeartbeat: startHeartbeat2,
566
+ stopHeartbeat: stopHeartbeat2,
567
+ spawnWatchdog: spawnWatchdog2,
568
+ stopWatchdog: stopWatchdog2,
569
+ prisma: undefined,
570
+ withSuffix
571
+ };
572
+ if (config.prisma) {
573
+ env.prisma = createPrismaRunner(env, config.prisma);
574
+ }
575
+ return env;
576
+ }
577
+ export { createDevEnvironment };
@@ -1,58 +1,66 @@
1
- import {
2
- createDevEnvironment
3
- } from "./index-wz9x8g7z.js";
4
-
5
1
  // loader.ts
6
2
  import { existsSync } from "node:fs";
7
3
  import { dirname, join } from "node:path";
4
+ import { createDevEnvironment } from "./index-wz9x8g7z.js";
5
+
8
6
  var CONFIG_FILES = [
9
- "dev.config.ts",
10
- "dev.config.js",
11
- "dev-tools.config.ts",
12
- "dev-tools.config.js"
7
+ "dev.config.ts",
8
+ "dev.config.js",
9
+ "dev-tools.config.ts",
10
+ "dev-tools.config.js",
13
11
  ];
14
12
  function findConfigFile(startDir) {
15
- let currentDir = startDir;
16
- while (true) {
17
- for (const file of CONFIG_FILES) {
18
- const configPath = join(currentDir, file);
19
- if (existsSync(configPath)) {
20
- return configPath;
21
- }
22
- }
23
- const parentDir = dirname(currentDir);
24
- if (parentDir === currentDir) {
25
- return null;
26
- }
27
- currentDir = parentDir;
28
- }
13
+ let currentDir = startDir;
14
+ while (true) {
15
+ for (const file of CONFIG_FILES) {
16
+ const configPath = join(currentDir, file);
17
+ if (existsSync(configPath)) {
18
+ return configPath;
19
+ }
20
+ }
21
+ const parentDir = dirname(currentDir);
22
+ if (parentDir === currentDir) {
23
+ return null;
24
+ }
25
+ currentDir = parentDir;
26
+ }
29
27
  }
30
28
  var cachedEnv = null;
31
29
  async function loadDevEnv(options) {
32
- if (cachedEnv && !options?.reload) {
33
- return cachedEnv;
34
- }
35
- const cwd = options?.cwd ?? process.cwd();
36
- const configPath = findConfigFile(cwd);
37
- if (configPath) {
38
- const mod = await import(configPath);
39
- const config = mod.default;
40
- if (!config?.projectPrefix || !config?.services) {
41
- throw new Error(`Invalid config in "${configPath}". Use defineDevConfig() and export as default.`);
42
- }
43
- cachedEnv = createDevEnvironment(config);
44
- return cachedEnv;
45
- }
46
- throw new Error(`No config file found. Create dev.config.ts with: export default defineDevConfig({ ... })`);
30
+ if (cachedEnv && !options?.reload) {
31
+ return cachedEnv;
32
+ }
33
+ const cwd = options?.cwd ?? process.cwd();
34
+ const configPath = findConfigFile(cwd);
35
+ if (configPath) {
36
+ const mod = await import(configPath);
37
+ const config = mod.default;
38
+ if (!config?.projectPrefix || !config?.services) {
39
+ throw new Error(
40
+ `Invalid config in "${configPath}". Use defineDevConfig() and export as default.`,
41
+ );
42
+ }
43
+ cachedEnv = createDevEnvironment(config);
44
+ return cachedEnv;
45
+ }
46
+ throw new Error(
47
+ `No config file found. Create dev.config.ts with: export default defineDevConfig({ ... })`,
48
+ );
47
49
  }
48
50
  function getDevEnv() {
49
- if (!cachedEnv) {
50
- throw new Error("Dev environment not loaded. Call loadDevEnv() first.");
51
- }
52
- return cachedEnv;
51
+ if (!cachedEnv) {
52
+ throw new Error("Dev environment not loaded. Call loadDevEnv() first.");
53
+ }
54
+ return cachedEnv;
53
55
  }
54
56
  function clearDevEnvCache() {
55
- cachedEnv = null;
57
+ cachedEnv = null;
56
58
  }
57
59
 
58
- export { CONFIG_FILES, findConfigFile, loadDevEnv, getDevEnv, clearDevEnvCache };
60
+ export {
61
+ CONFIG_FILES,
62
+ findConfigFile,
63
+ loadDevEnv,
64
+ getDevEnv,
65
+ clearDevEnvCache,
66
+ };