buncargo 1.0.29 → 3.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 (221) 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 +315 -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 +22 -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/tunnel.d.ts +33 -0
  29. package/dist/core/utils.js +2 -2
  30. package/dist/core/watchdog-runner.js +45 -42
  31. package/dist/core/watchdog.d.ts +1 -0
  32. package/dist/core/watchdog.js +4 -2
  33. package/dist/docker/index.d.ts +1 -0
  34. package/dist/docker/index.js +38 -0
  35. package/dist/docker/runtime.d.ts +87 -0
  36. package/dist/docker/runtime.js +37 -0
  37. package/dist/docker-compose/compose.d.ts +1 -0
  38. package/dist/docker-compose/generated-file.d.ts +7 -0
  39. package/dist/docker-compose/index.d.ts +3 -0
  40. package/dist/docker-compose/index.js +15 -0
  41. package/dist/docker-compose/model.d.ts +6 -0
  42. package/dist/docker-compose/services/clickhouse.d.ts +16 -0
  43. package/dist/docker-compose/services/define-docker-service.d.ts +41 -0
  44. package/dist/docker-compose/services/index.d.ts +23 -0
  45. package/dist/docker-compose/services/index.js +17 -0
  46. package/dist/docker-compose/services/postgres.d.ts +12 -0
  47. package/dist/docker-compose/services/redis.d.ts +12 -0
  48. package/dist/docker-compose/services/shared.d.ts +7 -0
  49. package/dist/docker-compose/yaml.d.ts +2 -0
  50. package/dist/environment/create-dev-environment.d.ts +23 -0
  51. package/dist/environment/index.d.ts +1 -0
  52. package/dist/environment/index.js +15 -0
  53. package/dist/environment/logging.d.ts +17 -0
  54. package/dist/environment/seeding.d.ts +9 -0
  55. package/dist/environment.d.ts +1 -23
  56. package/dist/environment.js +12 -14
  57. package/dist/index-045jksh5.js +147 -0
  58. package/dist/index-08wa79cs.js +125 -117
  59. package/dist/index-0kxnae3z.js +335 -0
  60. package/dist/index-1mdrf7nz.js +51 -43
  61. package/dist/index-1yvbwj4k.js +262 -242
  62. package/dist/index-23ev345g.js +475 -0
  63. package/dist/index-2ckr49sf.js +228 -0
  64. package/dist/index-2f47khe5.js +376 -369
  65. package/dist/index-2fr3g85b.js +220 -183
  66. package/dist/index-38xnzpa6.js +450 -0
  67. package/dist/index-3h3dhtf2.js +51 -43
  68. package/dist/index-42x95209.js +51 -43
  69. package/dist/index-4gp0az1g.js +145 -0
  70. package/dist/index-4xrxh8yv.js +72 -0
  71. package/dist/index-5gmws6ah.js +181 -0
  72. package/dist/index-5hka0tff.js +78 -76
  73. package/dist/index-5rfqps4b.js +3 -0
  74. package/dist/index-5t9jxqm0.js +428 -0
  75. package/dist/index-6c1w1xk5.js +101 -0
  76. package/dist/index-6fm7mvwj.js +118 -97
  77. package/dist/index-6srpc523.js +127 -128
  78. package/dist/index-731rzzfp.js +157 -142
  79. package/dist/index-75y4cg2z.js +51 -43
  80. package/dist/index-7ja4ywyj.js +126 -127
  81. package/dist/index-8bw1cmz4.js +531 -0
  82. package/dist/index-8hbbj1mp.js +120 -121
  83. package/dist/index-8xj2p5n5.js +118 -97
  84. package/dist/index-bj79tw5w.js +0 -0
  85. package/dist/index-bnk6nr0g.js +73 -0
  86. package/dist/index-brbbzyks.js +72 -0
  87. package/dist/index-c0dr6mcv.js +123 -0
  88. package/dist/index-cty0bcry.js +235 -218
  89. package/dist/index-d8tyv5se.js +228 -0
  90. package/dist/index-d9efy0n4.js +176 -150
  91. package/dist/index-etfmqjjf.js +427 -0
  92. package/dist/index-fb29934k.js +172 -0
  93. package/dist/index-g50jw1yf.js +72 -0
  94. package/dist/index-g6eb5wdw.js +118 -117
  95. package/dist/index-ggq3yryx.js +99 -95
  96. package/dist/index-h70tce00.js +177 -0
  97. package/dist/index-hkxtfqtc.js +333 -0
  98. package/dist/index-kf3dhser.js +146 -143
  99. package/dist/index-ma6tgdb2.js +500 -0
  100. package/dist/index-mam0bcyz.js +123 -0
  101. package/dist/index-mm412dkp.js +274 -0
  102. package/dist/index-n8v18aeb.js +0 -0
  103. package/dist/index-ndnmnsej.js +378 -371
  104. package/dist/index-p8wty0e2.js +389 -379
  105. package/dist/index-qfphr2fd.js +78 -76
  106. package/dist/index-qqmms8rs.js +51 -43
  107. package/dist/index-qw4093g2.js +51 -43
  108. package/dist/index-qzwpzjbx.js +121 -122
  109. package/dist/index-segbnm0h.js +146 -143
  110. package/dist/index-t0fj6gg1.js +112 -0
  111. package/dist/index-thdkwnv7.js +122 -0
  112. package/dist/index-tjbx2r2t.js +270 -0
  113. package/dist/index-tjqw9vtj.js +62 -54
  114. package/dist/index-vbpb89jy.js +248 -0
  115. package/dist/index-vhs88xhe.js +99 -95
  116. package/dist/index-w8zxnjka.js +249 -0
  117. package/dist/index-wk2na3t9.js +385 -375
  118. package/dist/index-wz9x8g7z.js +383 -373
  119. package/dist/index-x249gyde.js +388 -378
  120. package/dist/index-xkvd0nsd.js +187 -0
  121. package/dist/index-yedqxm1z.js +80 -0
  122. package/dist/index-zfjzzjkf.js +240 -199
  123. package/dist/index.d.ts +12 -8
  124. package/dist/index.js +56 -35
  125. package/dist/lint.d.ts +1 -46
  126. package/dist/lint.js +3 -7
  127. package/dist/loader/cache.d.ts +4 -0
  128. package/dist/loader/find-config-file.d.ts +2 -0
  129. package/dist/loader/index.d.ts +5 -0
  130. package/dist/loader/index.js +24 -0
  131. package/dist/loader/load-dev-env.d.ts +5 -0
  132. package/dist/loader/loader.d.ts +1 -0
  133. package/dist/loader.d.ts +1 -45
  134. package/dist/loader.js +22 -20
  135. package/dist/prisma/index.d.ts +1 -0
  136. package/dist/prisma/prisma.d.ts +29 -0
  137. package/dist/prisma.d.ts +1 -29
  138. package/dist/prisma.js +6 -10
  139. package/dist/src/bin.js +309 -0
  140. package/dist/src/cli.js +5 -0
  141. package/dist/src/config.js +15 -0
  142. package/dist/src/core/docker.js +38 -0
  143. package/dist/src/core/index.js +130 -0
  144. package/dist/src/core/network.js +9 -0
  145. package/dist/src/core/ports.js +23 -0
  146. package/dist/src/core/process.js +31 -0
  147. package/dist/src/core/utils.js +11 -0
  148. package/dist/src/core/watchdog-runner.js +69 -0
  149. package/dist/src/core/watchdog.js +28 -0
  150. package/dist/src/docker/runtime.js +37 -0
  151. package/dist/src/docker-compose/index.js +16 -0
  152. package/dist/src/docker-compose/services/index.js +17 -0
  153. package/dist/src/environment.js +12 -0
  154. package/dist/src/index.js +122 -0
  155. package/dist/src/lint.js +3 -0
  156. package/dist/src/loader.js +25 -0
  157. package/dist/src/prisma.js +6 -0
  158. package/dist/src/types.js +0 -0
  159. package/dist/typecheck/index.d.ts +1 -0
  160. package/dist/typecheck/index.js +7 -0
  161. package/dist/typecheck/typecheck.d.ts +46 -0
  162. package/dist/types/all-types.d.ts +501 -0
  163. package/dist/types/cli.d.ts +1 -0
  164. package/dist/types/config.d.ts +6 -0
  165. package/dist/types/docker.d.ts +15 -0
  166. package/dist/types/environment.d.ts +8 -0
  167. package/dist/types/hooks.d.ts +9 -0
  168. package/dist/types/index.d.ts +1 -0
  169. package/dist/types/index.js +0 -0
  170. package/dist/types/prisma.d.ts +1 -0
  171. package/dist/types.d.ts +1 -399
  172. package/package.json +145 -140
  173. package/readme.md +349 -109
  174. package/src/cli/bin.ts +77 -0
  175. package/src/cli/commands/help.ts +39 -0
  176. package/src/cli/commands/runtime.ts +72 -0
  177. package/src/cli/commands/version.ts +4 -0
  178. package/src/cli/index.ts +1 -0
  179. package/{cli.ts → src/cli/run-cli.ts} +95 -6
  180. package/src/config/define-config.ts +30 -0
  181. package/src/config/index.ts +3 -0
  182. package/src/config/merge-configs.ts +33 -0
  183. package/src/config/validate-config.ts +136 -0
  184. package/{core → src/core}/index.ts +2 -2
  185. package/{core → src/core}/ports.ts +5 -2
  186. package/{core → src/core}/process.ts +6 -2
  187. package/src/core/tunnel.ts +151 -0
  188. package/{core → src/core}/utils.ts +1 -0
  189. package/{core → src/core}/watchdog.ts +5 -1
  190. package/src/docker/index.ts +1 -0
  191. package/{core/docker.ts → src/docker/runtime.ts} +11 -4
  192. package/src/docker-compose/generated-file.ts +45 -0
  193. package/src/docker-compose/index.ts +7 -0
  194. package/src/docker-compose/model.ts +197 -0
  195. package/src/docker-compose/services/clickhouse.ts +79 -0
  196. package/src/docker-compose/services/define-docker-service.ts +109 -0
  197. package/src/docker-compose/services/index.ts +67 -0
  198. package/src/docker-compose/services/postgres.ts +60 -0
  199. package/src/docker-compose/services/redis.ts +48 -0
  200. package/src/docker-compose/services/shared.ts +79 -0
  201. package/src/docker-compose/yaml.ts +88 -0
  202. package/{environment.ts → src/environment/create-dev-environment.ts} +93 -130
  203. package/src/environment/index.ts +1 -0
  204. package/src/environment/logging.ts +101 -0
  205. package/src/environment/seeding.ts +57 -0
  206. package/{index.ts → src/index.ts} +49 -20
  207. package/src/loader/cache.ts +23 -0
  208. package/src/loader/find-config-file.ts +29 -0
  209. package/src/loader/index.ts +17 -0
  210. package/src/loader/load-dev-env.ts +38 -0
  211. package/src/prisma/index.ts +1 -0
  212. package/{prisma.ts → src/prisma/prisma.ts} +4 -2
  213. package/src/typecheck/index.ts +1 -0
  214. package/{types.ts → src/types/all-types.ts} +130 -5
  215. package/src/types/index.ts +1 -0
  216. package/bin.ts +0 -192
  217. package/config.ts +0 -194
  218. package/loader.ts +0 -126
  219. /package/{core → src/core}/network.ts +0 -0
  220. /package/{core → src/core}/watchdog-runner.ts +0 -0
  221. /package/{lint.ts → src/typecheck/typecheck.ts} +0 -0
package/readme.md CHANGED
@@ -1,110 +1,214 @@
1
1
  # Buncargo
2
2
 
3
- Type-safe development environment CLI for Docker Compose-based projects. Handles container lifecycle, port isolation for git worktrees, and dev server orchestration. It's easy!
3
+ A Bun-first development environment toolkit that eliminates the friction of local dev setup. Define your entire dev stack in a single typed config file—Docker services, app servers, environment variables, migrations, and more.
4
+
5
+ ## Why Buncargo?
6
+
7
+ **The problem**: Local development environments are fragile. Teams maintain separate `docker-compose.yml` files, scatter port assignments across `.env` files, manually manage container lifecycles, and struggle with port conflicts when working on multiple branches.
8
+
9
+ **The solution**: Buncargo provides a single source of truth for your dev environment. One `dev.config.ts` file defines everything. Type-safe. Auto-generated Docker Compose. Worktree-aware port isolation. Zero configuration drift.
10
+
11
+ ## Key Features
12
+
13
+ - **Single config file** — Define services, apps, ports, URLs, migrations, and hooks in one typed `dev.config.ts`
14
+ - **Auto-generated Docker Compose** — No manual compose files; buncargo generates them from your config
15
+ - **Worktree isolation** — Each git worktree gets unique ports and isolated containers automatically
16
+ - **Built-in service presets** — One-liner setup for Postgres, Redis, ClickHouse with health checks and URL templates
17
+ - **Custom service support** — Full Docker Compose escape hatch for any service
18
+ - **Dev server orchestration** — Start and monitor multiple app servers with health checks
19
+ - **Public tunnels** — Expose services via Cloudflare Quick Tunnels for webhook testing and mobile dev
20
+ - **Prisma integration** — Run Prisma commands with auto-injected `DATABASE_URL`
21
+ - **Lifecycle hooks** — Run migrations, seeders, or custom scripts at the right time
22
+ - **Programmatic API** — Access ports/URLs in tests or scripts
23
+ - **Watchdog auto-shutdown** — Containers stop automatically after inactivity
4
24
 
5
25
  ## Quick Start
6
26
 
7
- ### 1. Create `dev.config.ts` in your project root
27
+ ### 1. Install
28
+
29
+ ```bash
30
+ bun add -d buncargo
31
+ ```
32
+
33
+ ### 2. Create `dev.config.ts`
8
34
 
9
35
  ```typescript
10
- import { defineDevConfig } from 'buncargo'
36
+ import { defineDevConfig, service } from 'buncargo'
11
37
 
12
38
  export default defineDevConfig({
13
39
  projectPrefix: 'myapp',
14
40
 
15
41
  services: {
16
- postgres: {
17
- port: 5432,
18
- healthCheck: 'pg_isready',
19
- urlTemplate: ({ port }) => `postgresql://postgres:postgres@localhost:${port}/mydb`
20
- },
21
- redis: {
22
- port: 6379,
23
- healthCheck: 'redis-cli'
24
- }
42
+ postgres: service.postgres({ database: 'mydb' }),
43
+ redis: service.redis(),
25
44
  },
26
45
 
27
46
  apps: {
28
47
  api: {
29
48
  port: 3000,
30
49
  devCommand: 'bun run dev',
31
- cwd: 'apps/backend'
50
+ cwd: 'apps/backend',
32
51
  },
33
52
  web: {
34
53
  port: 5173,
35
54
  devCommand: 'bun run dev',
36
- cwd: 'apps/frontend'
37
- }
55
+ cwd: 'apps/frontend',
56
+ },
38
57
  },
39
58
 
40
59
  envVars: (ports, urls) => ({
41
60
  DATABASE_URL: urls.postgres,
42
61
  REDIS_URL: urls.redis,
43
- API_PORT: ports.api
62
+ API_PORT: ports.api,
44
63
  }),
45
-
46
- hooks: {
47
- afterContainersReady: async (ctx) => {
48
- await ctx.exec('bunx prisma migrate deploy', { cwd: 'packages/prisma' })
49
- }
50
- },
51
-
52
- prisma: {
53
- cwd: 'packages/prisma'
54
- }
55
64
  })
56
65
  ```
57
66
 
58
- ### 2. Run it
59
-
60
- ```bash
61
- bunx buncargo dev # Start containers + dev servers
62
- bunx buncargo dev --up-only # Start containers only
63
- bunx buncargo dev --down # Stop containers
64
- bunx buncargo dev --reset # Stop and remove volumes
65
- bunx buncargo typecheck # Run TypeScript typecheck across workspaces
66
- bunx buncargo prisma studio # Run prisma with correct DATABASE_URL
67
- bunx buncargo env # Print ports/urls as JSON
68
- ```
69
-
70
- Or add scripts to `package.json`:
67
+ ### 3. Add scripts to `package.json`
71
68
 
72
69
  ```json
73
70
  {
74
71
  "scripts": {
75
72
  "dev": "bunx buncargo dev",
76
- "dev:docker:down": "bunx buncargo dev --down",
77
- "typecheck": "bunx buncargo typecheck",
73
+ "dev:up": "bunx buncargo dev --up-only",
74
+ "dev:down": "bunx buncargo dev --down",
75
+ "dev:reset": "bunx buncargo dev --reset",
76
+ "dev:expose": "bunx buncargo dev --expose",
78
77
  "prisma": "bunx buncargo prisma"
79
78
  }
80
79
  }
81
80
  ```
82
81
 
83
- ## Programmatic Access
82
+ ### 4. Run
83
+
84
+ ```bash
85
+ bun run dev
86
+ ```
87
+
88
+ Buncargo will:
89
+ 1. Generate a Docker Compose file from your config
90
+ 2. Start all containers and wait for health checks
91
+ 3. Run any configured migrations
92
+ 4. Start your dev servers
93
+ 5. Print all ports and URLs
94
+
95
+ ## CLI Commands
96
+
97
+ ```bash
98
+ bunx buncargo dev # Start containers + dev servers
99
+ bunx buncargo dev --up-only # Start containers only (no dev servers)
100
+ bunx buncargo dev --down # Stop containers
101
+ bunx buncargo dev --reset # Stop containers and remove volumes
102
+ bunx buncargo dev --expose # Start with public tunnels for expose:true targets
103
+ bunx buncargo dev --expose=api # Expose specific targets
104
+ bunx buncargo dev --migrate # Run migrations only
105
+ bunx buncargo dev --seed # Run migrations and seeders
106
+ bunx buncargo prisma <args> # Run Prisma CLI with correct DATABASE_URL
107
+ bunx buncargo typecheck # Run TypeScript typecheck across workspaces
108
+ bunx buncargo env # Print ports/URLs as JSON
109
+ bunx buncargo help # Show help
110
+ bunx buncargo version # Show version
111
+ ```
84
112
 
85
- Need ports/urls in your code (e.g., for tests)?
113
+ ## Services
114
+
115
+ ### Built-in Presets
116
+
117
+ Use `service.*` helpers for common databases with sensible defaults:
86
118
 
87
119
  ```typescript
88
- import { loadDevEnv } from 'buncargo'
120
+ services: {
121
+ postgres: service.postgres({ database: 'mydb' }),
122
+ redis: service.redis(),
123
+ clickhouse: service.clickhouse({ database: 'analytics' }),
124
+ }
125
+ ```
89
126
 
90
- const env = await loadDevEnv()
91
- console.log(env.ports.postgres) // 5432 (or offset port)
92
- console.log(env.urls.api) // http://localhost:3000
93
- console.log(env.urls.postgres) // postgresql://...
127
+ Each preset includes:
128
+ - Default Docker image
129
+ - Health check configuration
130
+ - URL template (e.g., `postgresql://postgres:postgres@localhost:5432/mydb`)
131
+ - Volume for data persistence
132
+
133
+ ### Custom Services
134
+
135
+ Use `service.custom()` for any Docker service:
136
+
137
+ ```typescript
138
+ services: {
139
+ rabbitmq: service.custom({
140
+ port: 5672,
141
+ healthCheck: false,
142
+ docker: {
143
+ image: 'rabbitmq:3-management-alpine',
144
+ ports: ['${RABBITMQ_PORT:-5672}:5672', '15672:15672'],
145
+ environment: {
146
+ RABBITMQ_DEFAULT_USER: 'guest',
147
+ RABBITMQ_DEFAULT_PASS: 'guest',
148
+ },
149
+ },
150
+ }),
151
+ nats: service.custom({
152
+ port: 4222,
153
+ docker: {
154
+ image: 'nats:2-alpine',
155
+ ports: ['${NATS_PORT:-4222}:4222'],
156
+ },
157
+ }),
158
+ }
94
159
  ```
95
160
 
96
- ## Features
161
+ ## Apps
97
162
 
98
- ### Worktree Isolation
163
+ Define dev servers to run alongside containers:
99
164
 
100
- Each git worktree automatically gets:
165
+ ```typescript
166
+ apps: {
167
+ api: {
168
+ port: 3000,
169
+ devCommand: 'bun run dev',
170
+ cwd: 'apps/backend',
171
+ healthEndpoint: '/health',
172
+ },
173
+ web: {
174
+ port: 5173,
175
+ devCommand: 'bun run dev',
176
+ cwd: 'apps/frontend',
177
+ healthEndpoint: '/',
178
+ },
179
+ }
180
+ ```
101
181
 
102
- - Unique ports (offset 10-99)
103
- - Unique Docker Compose project names
182
+ ## Environment Variables
104
183
 
105
- This means each worktree has isolated containers, networks, and volumes by default.
184
+ The `envVars` function builds all env vars from computed ports and URLs:
106
185
 
107
- If you intentionally want shared Docker state across worktrees, set:
186
+ ```typescript
187
+ envVars: (ports, urls, { localIp, publicUrls }) => ({
188
+ DATABASE_URL: urls.postgres,
189
+ REDIS_URL: urls.redis,
190
+ API_PORT: ports.api,
191
+ EXPO_API_URL: `http://${localIp}:${ports.api}`,
192
+ WEBHOOK_URL: publicUrls.api ?? urls.api,
193
+ })
194
+ ```
195
+
196
+ These are injected into:
197
+ - Docker Compose services
198
+ - Dev server processes
199
+ - Hook `exec()` calls
200
+ - Prisma commands
201
+
202
+ ## Worktree Isolation
203
+
204
+ When working in git worktrees, buncargo automatically assigns unique port offsets (10-99) so each worktree has isolated:
205
+ - Ports (e.g., postgres on 5442 instead of 5432)
206
+ - Docker Compose project names
207
+ - Containers, networks, and volumes
208
+
209
+ This means you can run multiple branches simultaneously without conflicts.
210
+
211
+ To disable isolation and share state across worktrees:
108
212
 
109
213
  ```typescript
110
214
  options: {
@@ -112,46 +216,65 @@ options: {
112
216
  }
113
217
  ```
114
218
 
115
- ### Health Checks
219
+ ## Public Tunnels
116
220
 
117
- Built-in health checks for common services:
221
+ Expose local services to the internet using Cloudflare Quick Tunnels:
118
222
 
119
- - `pg_isready` - PostgreSQL
120
- - `redis-cli` - Redis
121
- - `http` - HTTP endpoint check
122
- - `tcp` - TCP port check
223
+ ```typescript
224
+ services: {
225
+ postgres: service.postgres({ database: 'mydb' }),
226
+ },
227
+ apps: {
228
+ api: {
229
+ port: 3000,
230
+ devCommand: 'bun run dev',
231
+ expose: true, // Mark as exposable
232
+ },
233
+ }
234
+ ```
123
235
 
124
- ### URL Templates
236
+ ```bash
237
+ bun run dev --expose # Expose all targets with expose: true
238
+ bun run dev --expose=api # Expose specific targets
239
+ ```
125
240
 
126
- Define connection URLs as functions:
241
+ Public URLs are printed in the console and available via `publicUrls` in `envVars`:
127
242
 
128
243
  ```typescript
129
- urlTemplate: ({ port, host, localIp }) =>
130
- `postgresql://user:pass@${host}:${port}/db`
244
+ envVars: (_ports, urls, { publicUrls }) => ({
245
+ WEBHOOK_URL: publicUrls.api ?? urls.api,
246
+ })
131
247
  ```
132
248
 
133
- Default templates exist for: `postgres`, `redis`, `clickhouse`, `mysql`, `mongodb`
249
+ ## Lifecycle Hooks
134
250
 
135
- ### Lifecycle Hooks
251
+ Run code at specific points in the startup/shutdown cycle:
136
252
 
137
253
  ```typescript
138
254
  hooks: {
139
- afterContainersReady: async (ctx) => { /* Run migrations */ },
140
- beforeServers: async (ctx) => { /* Seed database */ },
141
- afterServers: async (ctx) => { /* Post-startup tasks */ },
142
- beforeStop: async (ctx) => { /* Cleanup */ }
255
+ afterContainersReady: async (ctx) => {
256
+ await ctx.exec('bunx prisma migrate deploy', { cwd: 'packages/prisma' })
257
+ },
258
+ beforeServers: async (ctx) => {
259
+ await ctx.exec('bun run seed')
260
+ },
261
+ afterServers: async (ctx) => {
262
+ console.log(`API running at ${ctx.urls.api}`)
263
+ },
264
+ beforeStop: async (ctx) => {
265
+ await ctx.exec('bun run cleanup', { throwOnError: false })
266
+ },
143
267
  }
144
268
  ```
145
269
 
146
- ### Hook Context
147
-
148
- Hooks receive a context object with:
270
+ Hook context provides:
149
271
 
150
272
  ```typescript
151
273
  interface HookContext {
152
274
  projectName: string
153
275
  ports: { postgres: number, api: number, ... }
154
276
  urls: { postgres: string, api: string, ... }
277
+ publicUrls: { api?: string, ... }
155
278
  root: string
156
279
  isCI: boolean
157
280
  portOffset: number
@@ -160,54 +283,171 @@ interface HookContext {
160
283
  }
161
284
  ```
162
285
 
163
- ### Watchdog Auto-Shutdown
286
+ ## Migrations and Seeding
164
287
 
165
- Containers automatically stop after 10 minutes of inactivity when running via CLI.
288
+ ### Migrations
166
289
 
167
- ## CLI Reference
290
+ Run migration commands after containers are healthy:
168
291
 
292
+ ```typescript
293
+ migrations: [
294
+ { name: 'prisma', command: 'bunx prisma migrate deploy', cwd: 'packages/prisma' },
295
+ { name: 'clickhouse', command: 'bun run migrate:clickhouse' },
296
+ ]
169
297
  ```
170
- COMMANDS:
171
- dev Start the development environment
172
- typecheck Run TypeScript typecheck across workspaces
173
- prisma <args> Run Prisma CLI with correct DATABASE_URL
174
- env Print environment info as JSON
175
- help Show help
176
- version Show version
177
298
 
178
- DEV OPTIONS:
179
- --up-only Start containers only (no dev servers)
180
- --down Stop containers
181
- --reset Stop containers and remove volumes
182
- --migrate Run migrations only
183
- --seed Run seeders
299
+ ### Seeding
300
+
301
+ Seed the database with a check to avoid re-seeding:
302
+
303
+ ```typescript
304
+ seed: {
305
+ command: 'bun run seed',
306
+ check: ({ checkTable }) => checkTable('User', 'postgres'),
307
+ }
184
308
  ```
185
309
 
186
- ## Environment Variables
310
+ ## Prisma Integration
187
311
 
188
- The `envVars` function receives:
312
+ Configure Prisma to use the correct database URL:
189
313
 
190
314
  ```typescript
191
- envVars: (ports, urls, context) => ({
192
- // ports: { postgres: 5432, api: 3000, ... }
193
- // urls: { postgres: "postgresql://...", ... }
194
- // context: { localIp, portOffset, isCI, root }
195
- })
315
+ prisma: {
316
+ cwd: 'packages/prisma',
317
+ service: 'postgres', // Default: 'postgres'
318
+ urlEnvVar: 'DATABASE_URL', // Default: 'DATABASE_URL'
319
+ }
196
320
  ```
197
321
 
198
- These are injected into:
199
- - Docker Compose (via `COMPOSE_PROJECT_NAME`)
200
- - Dev server processes
201
- - Hook `exec()` calls
322
+ Then run Prisma commands through buncargo:
323
+
324
+ ```bash
325
+ bun run prisma migrate dev
326
+ bun run prisma studio
327
+ bun run prisma db push
328
+ ```
329
+
330
+ Buncargo ensures the database container is running and injects the correct `DATABASE_URL` with worktree-aware ports.
331
+
332
+ ## Programmatic API
333
+
334
+ Access the dev environment from code (useful for tests):
202
335
 
203
- ## Docker Compose
336
+ ```typescript
337
+ import { loadDevEnv } from 'buncargo'
204
338
 
205
- Your `docker-compose.yml` should use environment variables for ports:
339
+ const env = await loadDevEnv()
206
340
 
207
- ```yaml
208
- services:
209
- postgres:
210
- image: postgres:16
211
- ports:
212
- - "${POSTGRES_PORT:-5432}:5432"
341
+ console.log(env.ports.postgres) // 5432 (or offset port)
342
+ console.log(env.urls.api) // http://localhost:3000
343
+ console.log(env.urls.postgres) // postgresql://postgres:postgres@localhost:5432/mydb
344
+
345
+ // Start/stop programmatically
346
+ await env.start()
347
+ await env.stop({ removeVolumes: true })
348
+
349
+ // Build env vars for subprocess
350
+ const envVars = env.buildEnvVars()
351
+ ```
352
+
353
+ ## Docker Compose Generation
354
+
355
+ Buncargo generates Docker Compose from your config. No external `docker-compose.yml` is read.
356
+
357
+ ```typescript
358
+ docker: {
359
+ generatedFile: '.buncargo/docker-compose.generated.yml',
360
+ writeStrategy: 'always', // or 'if-missing'
361
+ volumes: {
362
+ shared_cache: {},
363
+ },
364
+ }
213
365
  ```
366
+
367
+ ## Health Checks
368
+
369
+ Built-in health check types:
370
+
371
+ | Type | Description |
372
+ |------|-------------|
373
+ | `pg_isready` | PostgreSQL readiness check |
374
+ | `redis-cli` | Redis PING check |
375
+ | `http` | HTTP endpoint check |
376
+ | `tcp` | TCP port check |
377
+
378
+ Or provide a custom health check function:
379
+
380
+ ```typescript
381
+ healthCheck: async (port) => {
382
+ const res = await fetch(`http://localhost:${port}/health`)
383
+ return res.ok
384
+ }
385
+ ```
386
+
387
+ ## Watchdog Auto-Shutdown
388
+
389
+ When running via CLI, containers automatically stop after 10 minutes of inactivity. The watchdog monitors heartbeats and shuts down orphaned environments.
390
+
391
+ ## Full Example
392
+
393
+ ```typescript
394
+ import { defineDevConfig, service } from 'buncargo'
395
+
396
+ export default defineDevConfig({
397
+ projectPrefix: 'platform',
398
+
399
+ services: {
400
+ postgres: service.postgres({ database: 'platform' }),
401
+ redis: service.redis(),
402
+ clickhouse: service.clickhouse({ database: 'platform' }),
403
+ },
404
+
405
+ apps: {
406
+ api: {
407
+ port: 3000,
408
+ expose: true,
409
+ devCommand: 'bun run dev',
410
+ cwd: 'apps/backend',
411
+ healthEndpoint: '/health',
412
+ },
413
+ web: {
414
+ port: 5173,
415
+ devCommand: 'bun run dev',
416
+ cwd: 'apps/frontend',
417
+ },
418
+ },
419
+
420
+ envVars: (ports, urls, { localIp, publicUrls }) => ({
421
+ DATABASE_URL: urls.postgres,
422
+ REDIS_URL: urls.redis,
423
+ CLICKHOUSE_URL: urls.clickhouse,
424
+ API_URL: urls.api,
425
+ VITE_API_URL: urls.api,
426
+ EXPO_API_URL: `http://${localIp}:${ports.api}`,
427
+ WEBHOOK_URL: publicUrls.api ?? urls.api,
428
+ }),
429
+
430
+ migrations: [
431
+ { name: 'prisma', command: 'bunx prisma migrate deploy', cwd: 'packages/prisma' },
432
+ ],
433
+
434
+ seed: {
435
+ command: 'bun run seed',
436
+ check: ({ checkTable }) => checkTable('User', 'postgres'),
437
+ },
438
+
439
+ prisma: {
440
+ cwd: 'packages/prisma',
441
+ },
442
+
443
+ hooks: {
444
+ afterContainersReady: async (ctx) => {
445
+ console.log(`Containers ready on port offset ${ctx.portOffset}`)
446
+ },
447
+ },
448
+ })
449
+ ```
450
+
451
+ ## License
452
+
453
+ MIT
package/src/cli/bin.ts ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * CLI Entry Point for buncargo
5
+ *
6
+ * Usage:
7
+ * bunx buncargo dev # Start containers + dev servers
8
+ * bunx buncargo dev --down # Stop containers
9
+ * bunx buncargo dev --reset # Stop + remove volumes
10
+ * bunx buncargo typecheck # Run TypeScript typecheck
11
+ * bunx buncargo prisma ... # Run prisma commands
12
+ * bunx buncargo help # Show help
13
+ */
14
+
15
+ import { showHelp } from "./commands/help";
16
+ import {
17
+ handleDev,
18
+ handleEnv,
19
+ handlePrisma,
20
+ handleTypecheck,
21
+ } from "./commands/runtime";
22
+ import { showVersion } from "./commands/version";
23
+
24
+ // ═══════════════════════════════════════════════════════════════════════════
25
+ // Main
26
+ // ═══════════════════════════════════════════════════════════════════════════
27
+
28
+ async function main(): Promise<void> {
29
+ const args = process.argv.slice(2);
30
+ const command = args[0];
31
+ const commandArgs = args.slice(1);
32
+
33
+ if (
34
+ !command ||
35
+ command === "help" ||
36
+ command === "--help" ||
37
+ command === "-h"
38
+ ) {
39
+ showHelp();
40
+ process.exit(0);
41
+ }
42
+
43
+ if (command === "version" || command === "--version" || command === "-v") {
44
+ showVersion();
45
+ process.exit(0);
46
+ }
47
+
48
+ switch (command) {
49
+ case "dev":
50
+ await handleDev(commandArgs);
51
+ break;
52
+
53
+ case "typecheck":
54
+ await handleTypecheck();
55
+ break;
56
+
57
+ case "prisma":
58
+ await handlePrisma(commandArgs);
59
+ break;
60
+
61
+ case "env":
62
+ await handleEnv();
63
+ break;
64
+
65
+ default:
66
+ console.error(`❌ Unknown command: ${command}`);
67
+ console.error("");
68
+ console.error(' Run "bunx buncargo help" for available commands.');
69
+ process.exit(1);
70
+ }
71
+ }
72
+
73
+ main().catch((error) => {
74
+ const message = error instanceof Error ? error.message : String(error);
75
+ console.error(`❌ ${message}`);
76
+ process.exit(1);
77
+ });
@@ -0,0 +1,39 @@
1
+ export function showHelp(): void {
2
+ console.log(`
3
+ buncargo - Development environment CLI
4
+
5
+ USAGE:
6
+ bunx buncargo <command> [options]
7
+
8
+ COMMANDS:
9
+ dev Start the development environment
10
+ typecheck Run TypeScript typecheck across workspaces
11
+ prisma <args> Run Prisma CLI with correct DATABASE_URL
12
+ env Print environment info as JSON
13
+ help Show this help message
14
+ version Show version
15
+
16
+ EXAMPLES:
17
+ bunx buncargo dev # Start everything
18
+ bunx buncargo dev --expose # Public quick tunnel for expose:true targets
19
+ bunx buncargo dev --expose=api # Public quick tunnel for selected target
20
+ bunx buncargo dev --help # Show dev command options
21
+ bunx buncargo dev --down # Stop containers
22
+ bunx buncargo typecheck # Run typecheck
23
+ bunx buncargo prisma studio # Open Prisma Studio
24
+ bunx buncargo env # Get ports/urls as JSON
25
+
26
+ CONFIG:
27
+ Create a dev.config.ts with a default export:
28
+
29
+ import { defineDevConfig } from 'buncargo'
30
+
31
+ export default defineDevConfig({
32
+ projectPrefix: 'myapp',
33
+ services: { ... },
34
+ apps: { ... }
35
+ })
36
+
37
+ Run "bunx buncargo dev --help" for dev command options.
38
+ `);
39
+ }