buncargo 1.0.26 → 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 (222) hide show
  1. package/dist/bin.d.ts +1 -12
  2. package/dist/bin.js +261 -252
  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 -74
  22. package/dist/core/docker.js +35 -26
  23. package/dist/core/index.d.ts +1 -1
  24. package/dist/core/index.js +123 -108
  25. package/dist/core/network.js +2 -2
  26. package/dist/core/ports.d.ts +22 -0
  27. package/dist/core/ports.js +5 -1
  28. package/dist/core/process.js +1 -1
  29. package/dist/core/tunnel.d.ts +33 -0
  30. package/dist/core/utils.js +2 -2
  31. package/dist/core/watchdog-runner.js +45 -42
  32. package/dist/core/watchdog.d.ts +1 -0
  33. package/dist/core/watchdog.js +4 -2
  34. package/dist/docker/index.d.ts +1 -0
  35. package/dist/docker/index.js +38 -0
  36. package/dist/docker/runtime.d.ts +87 -0
  37. package/dist/docker/runtime.js +37 -0
  38. package/dist/docker-compose/compose.d.ts +1 -0
  39. package/dist/docker-compose/generated-file.d.ts +7 -0
  40. package/dist/docker-compose/index.d.ts +3 -0
  41. package/dist/docker-compose/index.js +15 -0
  42. package/dist/docker-compose/model.d.ts +6 -0
  43. package/dist/docker-compose/services/clickhouse.d.ts +16 -0
  44. package/dist/docker-compose/services/define-docker-service.d.ts +41 -0
  45. package/dist/docker-compose/services/index.d.ts +23 -0
  46. package/dist/docker-compose/services/index.js +17 -0
  47. package/dist/docker-compose/services/postgres.d.ts +12 -0
  48. package/dist/docker-compose/services/redis.d.ts +12 -0
  49. package/dist/docker-compose/services/shared.d.ts +7 -0
  50. package/dist/docker-compose/yaml.d.ts +2 -0
  51. package/dist/environment/create-dev-environment.d.ts +23 -0
  52. package/dist/environment/index.d.ts +1 -0
  53. package/dist/environment/index.js +15 -0
  54. package/dist/environment/logging.d.ts +17 -0
  55. package/dist/environment/seeding.d.ts +9 -0
  56. package/dist/environment.d.ts +1 -23
  57. package/dist/environment.js +12 -14
  58. package/dist/index-045jksh5.js +147 -0
  59. package/dist/index-08wa79cs.js +125 -117
  60. package/dist/index-0kxnae3z.js +335 -0
  61. package/dist/index-1mdrf7nz.js +66 -0
  62. package/dist/index-1yvbwj4k.js +262 -242
  63. package/dist/index-23ev345g.js +475 -0
  64. package/dist/index-2ckr49sf.js +228 -0
  65. package/dist/index-2f47khe5.js +376 -369
  66. package/dist/index-2fr3g85b.js +220 -183
  67. package/dist/index-38xnzpa6.js +450 -0
  68. package/dist/index-3h3dhtf2.js +51 -43
  69. package/dist/index-42x95209.js +51 -43
  70. package/dist/index-4gp0az1g.js +145 -0
  71. package/dist/index-4xrxh8yv.js +72 -0
  72. package/dist/index-5gmws6ah.js +181 -0
  73. package/dist/index-5hka0tff.js +78 -76
  74. package/dist/index-5rfqps4b.js +3 -0
  75. package/dist/index-5t9jxqm0.js +428 -0
  76. package/dist/index-6c1w1xk5.js +101 -0
  77. package/dist/index-6fm7mvwj.js +118 -97
  78. package/dist/index-6srpc523.js +127 -128
  79. package/dist/index-731rzzfp.js +187 -0
  80. package/dist/index-75y4cg2z.js +51 -43
  81. package/dist/index-7ja4ywyj.js +126 -127
  82. package/dist/index-8bw1cmz4.js +531 -0
  83. package/dist/index-8hbbj1mp.js +120 -121
  84. package/dist/index-8xj2p5n5.js +145 -0
  85. package/dist/index-bj79tw5w.js +0 -0
  86. package/dist/index-bnk6nr0g.js +73 -0
  87. package/dist/index-brbbzyks.js +72 -0
  88. package/dist/index-c0dr6mcv.js +123 -0
  89. package/dist/index-cty0bcry.js +235 -218
  90. package/dist/index-d8tyv5se.js +228 -0
  91. package/dist/index-d9efy0n4.js +176 -150
  92. package/dist/index-etfmqjjf.js +427 -0
  93. package/dist/index-fb29934k.js +172 -0
  94. package/dist/index-g50jw1yf.js +72 -0
  95. package/dist/index-g6eb5wdw.js +118 -117
  96. package/dist/index-ggq3yryx.js +99 -95
  97. package/dist/index-h70tce00.js +177 -0
  98. package/dist/index-hkxtfqtc.js +333 -0
  99. package/dist/index-kf3dhser.js +146 -143
  100. package/dist/index-ma6tgdb2.js +500 -0
  101. package/dist/index-mam0bcyz.js +123 -0
  102. package/dist/index-mm412dkp.js +274 -0
  103. package/dist/index-n8v18aeb.js +0 -0
  104. package/dist/index-ndnmnsej.js +378 -371
  105. package/dist/index-p8wty0e2.js +389 -379
  106. package/dist/index-qfphr2fd.js +100 -0
  107. package/dist/index-qqmms8rs.js +51 -43
  108. package/dist/index-qw4093g2.js +51 -43
  109. package/dist/index-qzwpzjbx.js +121 -122
  110. package/dist/index-segbnm0h.js +146 -143
  111. package/dist/index-t0fj6gg1.js +112 -0
  112. package/dist/index-thdkwnv7.js +122 -0
  113. package/dist/index-tjbx2r2t.js +270 -0
  114. package/dist/index-tjqw9vtj.js +62 -54
  115. package/dist/index-vbpb89jy.js +248 -0
  116. package/dist/index-vhs88xhe.js +99 -95
  117. package/dist/index-w8zxnjka.js +249 -0
  118. package/dist/index-wk2na3t9.js +404 -0
  119. package/dist/index-wz9x8g7z.js +383 -373
  120. package/dist/index-x249gyde.js +388 -378
  121. package/dist/index-xkvd0nsd.js +187 -0
  122. package/dist/index-yedqxm1z.js +80 -0
  123. package/dist/index-zfjzzjkf.js +266 -0
  124. package/dist/index.d.ts +12 -8
  125. package/dist/index.js +66 -35
  126. package/dist/lint.d.ts +1 -46
  127. package/dist/lint.js +3 -7
  128. package/dist/loader/cache.d.ts +4 -0
  129. package/dist/loader/find-config-file.d.ts +2 -0
  130. package/dist/loader/index.d.ts +5 -0
  131. package/dist/loader/index.js +24 -0
  132. package/dist/loader/load-dev-env.d.ts +5 -0
  133. package/dist/loader/loader.d.ts +1 -0
  134. package/dist/loader.d.ts +1 -45
  135. package/dist/loader.js +22 -20
  136. package/dist/prisma/index.d.ts +1 -0
  137. package/dist/prisma/prisma.d.ts +29 -0
  138. package/dist/prisma.d.ts +1 -29
  139. package/dist/prisma.js +6 -10
  140. package/dist/src/bin.js +309 -0
  141. package/dist/src/cli.js +5 -0
  142. package/dist/src/config.js +15 -0
  143. package/dist/src/core/docker.js +38 -0
  144. package/dist/src/core/index.js +130 -0
  145. package/dist/src/core/network.js +9 -0
  146. package/dist/src/core/ports.js +23 -0
  147. package/dist/src/core/process.js +31 -0
  148. package/dist/src/core/utils.js +11 -0
  149. package/dist/src/core/watchdog-runner.js +69 -0
  150. package/dist/src/core/watchdog.js +28 -0
  151. package/dist/src/docker/runtime.js +37 -0
  152. package/dist/src/docker-compose/index.js +16 -0
  153. package/dist/src/docker-compose/services/index.js +17 -0
  154. package/dist/src/environment.js +12 -0
  155. package/dist/src/index.js +122 -0
  156. package/dist/src/lint.js +3 -0
  157. package/dist/src/loader.js +25 -0
  158. package/dist/src/prisma.js +6 -0
  159. package/dist/src/types.js +0 -0
  160. package/dist/typecheck/index.d.ts +1 -0
  161. package/dist/typecheck/index.js +7 -0
  162. package/dist/typecheck/typecheck.d.ts +46 -0
  163. package/dist/types/all-types.d.ts +501 -0
  164. package/dist/types/cli.d.ts +1 -0
  165. package/dist/types/config.d.ts +6 -0
  166. package/dist/types/docker.d.ts +15 -0
  167. package/dist/types/environment.d.ts +8 -0
  168. package/dist/types/hooks.d.ts +9 -0
  169. package/dist/types/index.d.ts +1 -0
  170. package/dist/types/index.js +0 -0
  171. package/dist/types/prisma.d.ts +1 -0
  172. package/dist/types.d.ts +1 -393
  173. package/package.json +145 -140
  174. package/readme.md +358 -105
  175. package/src/cli/bin.ts +77 -0
  176. package/src/cli/commands/help.ts +39 -0
  177. package/src/cli/commands/runtime.ts +72 -0
  178. package/src/cli/commands/version.ts +4 -0
  179. package/src/cli/index.ts +1 -0
  180. package/{cli.ts → src/cli/run-cli.ts} +95 -6
  181. package/src/config/define-config.ts +30 -0
  182. package/src/config/index.ts +3 -0
  183. package/src/config/merge-configs.ts +33 -0
  184. package/src/config/validate-config.ts +136 -0
  185. package/{core → src/core}/index.ts +2 -2
  186. package/{core → src/core}/ports.ts +68 -1
  187. package/{core → src/core}/process.ts +6 -2
  188. package/src/core/tunnel.ts +151 -0
  189. package/{core → src/core}/utils.ts +1 -0
  190. package/{core → src/core}/watchdog.ts +5 -1
  191. package/src/docker/index.ts +1 -0
  192. package/{core/docker.ts → src/docker/runtime.ts} +40 -4
  193. package/src/docker-compose/generated-file.ts +45 -0
  194. package/src/docker-compose/index.ts +7 -0
  195. package/src/docker-compose/model.ts +197 -0
  196. package/src/docker-compose/services/clickhouse.ts +79 -0
  197. package/src/docker-compose/services/define-docker-service.ts +109 -0
  198. package/src/docker-compose/services/index.ts +67 -0
  199. package/src/docker-compose/services/postgres.ts +60 -0
  200. package/src/docker-compose/services/redis.ts +48 -0
  201. package/src/docker-compose/services/shared.ts +79 -0
  202. package/src/docker-compose/yaml.ts +88 -0
  203. package/{environment.ts → src/environment/create-dev-environment.ts} +101 -146
  204. package/src/environment/index.ts +1 -0
  205. package/src/environment/logging.ts +101 -0
  206. package/src/environment/seeding.ts +57 -0
  207. package/{index.ts → src/index.ts} +49 -15
  208. package/src/loader/cache.ts +23 -0
  209. package/src/loader/find-config-file.ts +29 -0
  210. package/src/loader/index.ts +17 -0
  211. package/src/loader/load-dev-env.ts +38 -0
  212. package/src/prisma/index.ts +1 -0
  213. package/{prisma.ts → src/prisma/prisma.ts} +4 -2
  214. package/src/typecheck/index.ts +1 -0
  215. package/{types.ts → src/types/all-types.ts} +137 -6
  216. package/src/types/index.ts +1 -0
  217. package/bin.ts +0 -191
  218. package/config.ts +0 -194
  219. package/loader.ts +0 -126
  220. /package/{core → src/core}/network.ts +0 -0
  221. /package/{core → src/core}/watchdog-runner.ts +0 -0
  222. /package/{lint.ts → src/typecheck/typecheck.ts} +0 -0
package/readme.md CHANGED
@@ -1,144 +1,280 @@
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
+ ```
112
+
113
+ ## Services
84
114
 
85
- Need ports/urls in your code (e.g., for tests)?
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
+ }
159
+ ```
160
+
161
+ ## Apps
162
+
163
+ Define dev servers to run alongside containers:
164
+
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
+ }
94
180
  ```
95
181
 
96
- ## Features
182
+ ## Environment Variables
97
183
 
98
- ### Worktree Isolation
184
+ The `envVars` function builds all env vars from computed ports and URLs:
99
185
 
100
- Each git worktree automatically gets unique ports (offset 10-99) so you can run multiple branches simultaneously without conflicts.
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
+ ```
101
195
 
102
- ### Health Checks
196
+ These are injected into:
197
+ - Docker Compose services
198
+ - Dev server processes
199
+ - Hook `exec()` calls
200
+ - Prisma commands
103
201
 
104
- Built-in health checks for common services:
202
+ ## Worktree Isolation
105
203
 
106
- - `pg_isready` - PostgreSQL
107
- - `redis-cli` - Redis
108
- - `http` - HTTP endpoint check
109
- - `tcp` - TCP port check
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
110
208
 
111
- ### URL Templates
209
+ This means you can run multiple branches simultaneously without conflicts.
112
210
 
113
- Define connection URLs as functions:
211
+ To disable isolation and share state across worktrees:
114
212
 
115
213
  ```typescript
116
- urlTemplate: ({ port, host, localIp }) =>
117
- `postgresql://user:pass@${host}:${port}/db`
214
+ options: {
215
+ worktreeIsolation: false
216
+ }
118
217
  ```
119
218
 
120
- Default templates exist for: `postgres`, `redis`, `clickhouse`, `mysql`, `mongodb`
219
+ ## Public Tunnels
121
220
 
122
- ### Lifecycle Hooks
221
+ Expose local services to the internet using Cloudflare Quick Tunnels:
123
222
 
124
223
  ```typescript
125
- hooks: {
126
- afterContainersReady: async (ctx) => { /* Run migrations */ },
127
- beforeServers: async (ctx) => { /* Seed database */ },
128
- afterServers: async (ctx) => { /* Post-startup tasks */ },
129
- beforeStop: async (ctx) => { /* Cleanup */ }
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
+ },
130
233
  }
131
234
  ```
132
235
 
133
- ### Hook Context
236
+ ```bash
237
+ bun run dev --expose # Expose all targets with expose: true
238
+ bun run dev --expose=api # Expose specific targets
239
+ ```
240
+
241
+ Public URLs are printed in the console and available via `publicUrls` in `envVars`:
242
+
243
+ ```typescript
244
+ envVars: (_ports, urls, { publicUrls }) => ({
245
+ WEBHOOK_URL: publicUrls.api ?? urls.api,
246
+ })
247
+ ```
248
+
249
+ ## Lifecycle Hooks
250
+
251
+ Run code at specific points in the startup/shutdown cycle:
252
+
253
+ ```typescript
254
+ hooks: {
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
+ },
267
+ }
268
+ ```
134
269
 
135
- Hooks receive a context object with:
270
+ Hook context provides:
136
271
 
137
272
  ```typescript
138
273
  interface HookContext {
139
274
  projectName: string
140
275
  ports: { postgres: number, api: number, ... }
141
276
  urls: { postgres: string, api: string, ... }
277
+ publicUrls: { api?: string, ... }
142
278
  root: string
143
279
  isCI: boolean
144
280
  portOffset: number
@@ -147,54 +283,171 @@ interface HookContext {
147
283
  }
148
284
  ```
149
285
 
150
- ### Watchdog Auto-Shutdown
286
+ ## Migrations and Seeding
151
287
 
152
- Containers automatically stop after 10 minutes of inactivity when running via CLI.
288
+ ### Migrations
153
289
 
154
- ## CLI Reference
290
+ Run migration commands after containers are healthy:
155
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
+ ]
156
297
  ```
157
- COMMANDS:
158
- dev Start the development environment
159
- typecheck Run TypeScript typecheck across workspaces
160
- prisma <args> Run Prisma CLI with correct DATABASE_URL
161
- env Print environment info as JSON
162
- help Show help
163
- version Show version
164
298
 
165
- DEV OPTIONS:
166
- --up-only Start containers only (no dev servers)
167
- --down Stop containers
168
- --reset Stop containers and remove volumes
169
- --migrate Run migrations only
170
- --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
+ }
171
308
  ```
172
309
 
173
- ## Environment Variables
310
+ ## Prisma Integration
174
311
 
175
- The `envVars` function receives:
312
+ Configure Prisma to use the correct database URL:
176
313
 
177
314
  ```typescript
178
- envVars: (ports, urls, context) => ({
179
- // ports: { postgres: 5432, api: 3000, ... }
180
- // urls: { postgres: "postgresql://...", ... }
181
- // context: { localIp, portOffset, isCI, root }
182
- })
315
+ prisma: {
316
+ cwd: 'packages/prisma',
317
+ service: 'postgres', // Default: 'postgres'
318
+ urlEnvVar: 'DATABASE_URL', // Default: 'DATABASE_URL'
319
+ }
183
320
  ```
184
321
 
185
- These are injected into:
186
- - Docker Compose (via `COMPOSE_PROJECT_NAME`)
187
- - Dev server processes
188
- - 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
+ ```
189
329
 
190
- ## Docker Compose
330
+ Buncargo ensures the database container is running and injects the correct `DATABASE_URL` with worktree-aware ports.
191
331
 
192
- Your `docker-compose.yml` should use environment variables for ports:
332
+ ## Programmatic API
193
333
 
194
- ```yaml
195
- services:
196
- postgres:
197
- image: postgres:16
198
- ports:
199
- - "${POSTGRES_PORT:-5432}:5432"
334
+ Access the dev environment from code (useful for tests):
335
+
336
+ ```typescript
337
+ import { loadDevEnv } from 'buncargo'
338
+
339
+ const env = await loadDevEnv()
340
+
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
+ }
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
+ }
200
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
+ }