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.
- package/dist/bin.d.ts +1 -12
- package/dist/bin.js +261 -252
- package/dist/cli/bin.d.ts +13 -0
- package/dist/cli/bin.js +315 -0
- package/dist/cli/commands/help.d.ts +1 -0
- package/dist/cli/commands/runtime.d.ts +5 -0
- package/dist/cli/commands/version.d.ts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/run-cli.d.ts +22 -0
- package/dist/cli.d.ts +1 -22
- package/dist/cli.js +5 -13
- package/dist/config/config.d.ts +1 -0
- package/dist/config/define-config.d.ts +13 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +15 -0
- package/dist/config/merge-configs.d.ts +3 -0
- package/dist/config/validate-config.d.ts +3 -0
- package/dist/config.d.ts +1 -72
- package/dist/config.js +12 -12
- package/dist/core/docker.d.ts +1 -74
- package/dist/core/docker.js +35 -26
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +123 -108
- package/dist/core/network.js +2 -2
- package/dist/core/ports.d.ts +22 -0
- package/dist/core/ports.js +5 -1
- package/dist/core/process.js +1 -1
- package/dist/core/tunnel.d.ts +33 -0
- package/dist/core/utils.js +2 -2
- package/dist/core/watchdog-runner.js +45 -42
- package/dist/core/watchdog.d.ts +1 -0
- package/dist/core/watchdog.js +4 -2
- package/dist/docker/index.d.ts +1 -0
- package/dist/docker/index.js +38 -0
- package/dist/docker/runtime.d.ts +87 -0
- package/dist/docker/runtime.js +37 -0
- package/dist/docker-compose/compose.d.ts +1 -0
- package/dist/docker-compose/generated-file.d.ts +7 -0
- package/dist/docker-compose/index.d.ts +3 -0
- package/dist/docker-compose/index.js +15 -0
- package/dist/docker-compose/model.d.ts +6 -0
- package/dist/docker-compose/services/clickhouse.d.ts +16 -0
- package/dist/docker-compose/services/define-docker-service.d.ts +41 -0
- package/dist/docker-compose/services/index.d.ts +23 -0
- package/dist/docker-compose/services/index.js +17 -0
- package/dist/docker-compose/services/postgres.d.ts +12 -0
- package/dist/docker-compose/services/redis.d.ts +12 -0
- package/dist/docker-compose/services/shared.d.ts +7 -0
- package/dist/docker-compose/yaml.d.ts +2 -0
- package/dist/environment/create-dev-environment.d.ts +23 -0
- package/dist/environment/index.d.ts +1 -0
- package/dist/environment/index.js +15 -0
- package/dist/environment/logging.d.ts +17 -0
- package/dist/environment/seeding.d.ts +9 -0
- package/dist/environment.d.ts +1 -23
- package/dist/environment.js +12 -14
- package/dist/index-045jksh5.js +147 -0
- package/dist/index-08wa79cs.js +125 -117
- package/dist/index-0kxnae3z.js +335 -0
- package/dist/index-1mdrf7nz.js +66 -0
- package/dist/index-1yvbwj4k.js +262 -242
- package/dist/index-23ev345g.js +475 -0
- package/dist/index-2ckr49sf.js +228 -0
- package/dist/index-2f47khe5.js +376 -369
- package/dist/index-2fr3g85b.js +220 -183
- package/dist/index-38xnzpa6.js +450 -0
- package/dist/index-3h3dhtf2.js +51 -43
- package/dist/index-42x95209.js +51 -43
- package/dist/index-4gp0az1g.js +145 -0
- package/dist/index-4xrxh8yv.js +72 -0
- package/dist/index-5gmws6ah.js +181 -0
- package/dist/index-5hka0tff.js +78 -76
- package/dist/index-5rfqps4b.js +3 -0
- package/dist/index-5t9jxqm0.js +428 -0
- package/dist/index-6c1w1xk5.js +101 -0
- package/dist/index-6fm7mvwj.js +118 -97
- package/dist/index-6srpc523.js +127 -128
- package/dist/index-731rzzfp.js +187 -0
- package/dist/index-75y4cg2z.js +51 -43
- package/dist/index-7ja4ywyj.js +126 -127
- package/dist/index-8bw1cmz4.js +531 -0
- package/dist/index-8hbbj1mp.js +120 -121
- package/dist/index-8xj2p5n5.js +145 -0
- package/dist/index-bj79tw5w.js +0 -0
- package/dist/index-bnk6nr0g.js +73 -0
- package/dist/index-brbbzyks.js +72 -0
- package/dist/index-c0dr6mcv.js +123 -0
- package/dist/index-cty0bcry.js +235 -218
- package/dist/index-d8tyv5se.js +228 -0
- package/dist/index-d9efy0n4.js +176 -150
- package/dist/index-etfmqjjf.js +427 -0
- package/dist/index-fb29934k.js +172 -0
- package/dist/index-g50jw1yf.js +72 -0
- package/dist/index-g6eb5wdw.js +118 -117
- package/dist/index-ggq3yryx.js +99 -95
- package/dist/index-h70tce00.js +177 -0
- package/dist/index-hkxtfqtc.js +333 -0
- package/dist/index-kf3dhser.js +146 -143
- package/dist/index-ma6tgdb2.js +500 -0
- package/dist/index-mam0bcyz.js +123 -0
- package/dist/index-mm412dkp.js +274 -0
- package/dist/index-n8v18aeb.js +0 -0
- package/dist/index-ndnmnsej.js +378 -371
- package/dist/index-p8wty0e2.js +389 -379
- package/dist/index-qfphr2fd.js +100 -0
- package/dist/index-qqmms8rs.js +51 -43
- package/dist/index-qw4093g2.js +51 -43
- package/dist/index-qzwpzjbx.js +121 -122
- package/dist/index-segbnm0h.js +146 -143
- package/dist/index-t0fj6gg1.js +112 -0
- package/dist/index-thdkwnv7.js +122 -0
- package/dist/index-tjbx2r2t.js +270 -0
- package/dist/index-tjqw9vtj.js +62 -54
- package/dist/index-vbpb89jy.js +248 -0
- package/dist/index-vhs88xhe.js +99 -95
- package/dist/index-w8zxnjka.js +249 -0
- package/dist/index-wk2na3t9.js +404 -0
- package/dist/index-wz9x8g7z.js +383 -373
- package/dist/index-x249gyde.js +388 -378
- package/dist/index-xkvd0nsd.js +187 -0
- package/dist/index-yedqxm1z.js +80 -0
- package/dist/index-zfjzzjkf.js +266 -0
- package/dist/index.d.ts +12 -8
- package/dist/index.js +66 -35
- package/dist/lint.d.ts +1 -46
- package/dist/lint.js +3 -7
- package/dist/loader/cache.d.ts +4 -0
- package/dist/loader/find-config-file.d.ts +2 -0
- package/dist/loader/index.d.ts +5 -0
- package/dist/loader/index.js +24 -0
- package/dist/loader/load-dev-env.d.ts +5 -0
- package/dist/loader/loader.d.ts +1 -0
- package/dist/loader.d.ts +1 -45
- package/dist/loader.js +22 -20
- package/dist/prisma/index.d.ts +1 -0
- package/dist/prisma/prisma.d.ts +29 -0
- package/dist/prisma.d.ts +1 -29
- package/dist/prisma.js +6 -10
- package/dist/src/bin.js +309 -0
- package/dist/src/cli.js +5 -0
- package/dist/src/config.js +15 -0
- package/dist/src/core/docker.js +38 -0
- package/dist/src/core/index.js +130 -0
- package/dist/src/core/network.js +9 -0
- package/dist/src/core/ports.js +23 -0
- package/dist/src/core/process.js +31 -0
- package/dist/src/core/utils.js +11 -0
- package/dist/src/core/watchdog-runner.js +69 -0
- package/dist/src/core/watchdog.js +28 -0
- package/dist/src/docker/runtime.js +37 -0
- package/dist/src/docker-compose/index.js +16 -0
- package/dist/src/docker-compose/services/index.js +17 -0
- package/dist/src/environment.js +12 -0
- package/dist/src/index.js +122 -0
- package/dist/src/lint.js +3 -0
- package/dist/src/loader.js +25 -0
- package/dist/src/prisma.js +6 -0
- package/dist/src/types.js +0 -0
- package/dist/typecheck/index.d.ts +1 -0
- package/dist/typecheck/index.js +7 -0
- package/dist/typecheck/typecheck.d.ts +46 -0
- package/dist/types/all-types.d.ts +501 -0
- package/dist/types/cli.d.ts +1 -0
- package/dist/types/config.d.ts +6 -0
- package/dist/types/docker.d.ts +15 -0
- package/dist/types/environment.d.ts +8 -0
- package/dist/types/hooks.d.ts +9 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +0 -0
- package/dist/types/prisma.d.ts +1 -0
- package/dist/types.d.ts +1 -393
- package/package.json +145 -140
- package/readme.md +358 -105
- package/src/cli/bin.ts +77 -0
- package/src/cli/commands/help.ts +39 -0
- package/src/cli/commands/runtime.ts +72 -0
- package/src/cli/commands/version.ts +4 -0
- package/src/cli/index.ts +1 -0
- package/{cli.ts → src/cli/run-cli.ts} +95 -6
- package/src/config/define-config.ts +30 -0
- package/src/config/index.ts +3 -0
- package/src/config/merge-configs.ts +33 -0
- package/src/config/validate-config.ts +136 -0
- package/{core → src/core}/index.ts +2 -2
- package/{core → src/core}/ports.ts +68 -1
- package/{core → src/core}/process.ts +6 -2
- package/src/core/tunnel.ts +151 -0
- package/{core → src/core}/utils.ts +1 -0
- package/{core → src/core}/watchdog.ts +5 -1
- package/src/docker/index.ts +1 -0
- package/{core/docker.ts → src/docker/runtime.ts} +40 -4
- package/src/docker-compose/generated-file.ts +45 -0
- package/src/docker-compose/index.ts +7 -0
- package/src/docker-compose/model.ts +197 -0
- package/src/docker-compose/services/clickhouse.ts +79 -0
- package/src/docker-compose/services/define-docker-service.ts +109 -0
- package/src/docker-compose/services/index.ts +67 -0
- package/src/docker-compose/services/postgres.ts +60 -0
- package/src/docker-compose/services/redis.ts +48 -0
- package/src/docker-compose/services/shared.ts +79 -0
- package/src/docker-compose/yaml.ts +88 -0
- package/{environment.ts → src/environment/create-dev-environment.ts} +101 -146
- package/src/environment/index.ts +1 -0
- package/src/environment/logging.ts +101 -0
- package/src/environment/seeding.ts +57 -0
- package/{index.ts → src/index.ts} +49 -15
- package/src/loader/cache.ts +23 -0
- package/src/loader/find-config-file.ts +29 -0
- package/src/loader/index.ts +17 -0
- package/src/loader/load-dev-env.ts +38 -0
- package/src/prisma/index.ts +1 -0
- package/{prisma.ts → src/prisma/prisma.ts} +4 -2
- package/src/typecheck/index.ts +1 -0
- package/{types.ts → src/types/all-types.ts} +137 -6
- package/src/types/index.ts +1 -0
- package/bin.ts +0 -191
- package/config.ts +0 -194
- package/loader.ts +0 -126
- /package/{core → src/core}/network.ts +0 -0
- /package/{core → src/core}/watchdog-runner.ts +0 -0
- /package/{lint.ts → src/typecheck/typecheck.ts} +0 -0
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { assertValidConfig } from "../config";
|
|
2
|
+
import { getLocalIp, waitForDevServers, waitForServer } from "../core/network";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
startContainers,
|
|
6
|
-
stopContainers,
|
|
7
|
-
waitForAllServices,
|
|
8
|
-
} from "./core/docker";
|
|
9
|
-
import { getLocalIp, waitForDevServers, waitForServer } from "./core/network";
|
|
10
|
-
import {
|
|
11
|
-
calculatePortOffset,
|
|
4
|
+
computeDevIdentity,
|
|
12
5
|
computePorts,
|
|
13
6
|
computeUrls,
|
|
14
7
|
findMonorepoRoot,
|
|
15
|
-
|
|
16
|
-
isWorktree,
|
|
17
|
-
} from "./core/ports";
|
|
8
|
+
} from "../core/ports";
|
|
18
9
|
import {
|
|
19
10
|
buildApps,
|
|
20
11
|
execAsync,
|
|
21
12
|
startDevServers,
|
|
22
13
|
stopProcess as stopProcessFn,
|
|
23
|
-
} from "
|
|
24
|
-
import { isCI as isCIEnv, logExpoApiUrl, logFrontendPort } from "
|
|
14
|
+
} from "../core/process";
|
|
15
|
+
import { isCI as isCIEnv, logExpoApiUrl, logFrontendPort } from "../core/utils";
|
|
25
16
|
import {
|
|
26
17
|
spawnWatchdog as spawnWatchdogFn,
|
|
27
18
|
startHeartbeat as startHeartbeatFn,
|
|
28
19
|
stopHeartbeat as stopHeartbeatFn,
|
|
29
20
|
stopWatchdog as stopWatchdogFn,
|
|
30
|
-
} from "
|
|
31
|
-
import {
|
|
21
|
+
} from "../core/watchdog";
|
|
22
|
+
import {
|
|
23
|
+
areContainersRunning,
|
|
24
|
+
startContainers,
|
|
25
|
+
stopContainers,
|
|
26
|
+
} from "../docker/runtime";
|
|
27
|
+
import {
|
|
28
|
+
getGeneratedComposePath,
|
|
29
|
+
writeGeneratedComposeFile,
|
|
30
|
+
} from "../docker-compose";
|
|
31
|
+
import { createPrismaRunner } from "../prisma";
|
|
32
32
|
import type {
|
|
33
33
|
AppConfig,
|
|
34
34
|
ComputedPorts,
|
|
35
|
+
ComputedPublicUrls,
|
|
35
36
|
ComputedUrls,
|
|
36
37
|
DevConfig,
|
|
37
38
|
DevEnvironment,
|
|
@@ -42,34 +43,9 @@ import type {
|
|
|
42
43
|
ServiceConfig,
|
|
43
44
|
StartOptions,
|
|
44
45
|
StopOptions,
|
|
45
|
-
} from "
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Console Output Formatting (Vite-inspired)
|
|
49
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Format a URL with colored port number (Vite-style).
|
|
53
|
-
*/
|
|
54
|
-
function formatUrl(url: string): string {
|
|
55
|
-
return pc.cyan(
|
|
56
|
-
url.replace(/:(\d+)(\/?)/, (_, port, slash) => `:${pc.bold(port)}${slash}`),
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Format a label with arrow prefix (Vite-style).
|
|
62
|
-
*/
|
|
63
|
-
function formatLabel(label: string, value: string, arrow = "➜"): string {
|
|
64
|
-
return ` ${pc.green(arrow)} ${pc.bold(label.padEnd(10))} ${value}`;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Format a dim label (for secondary info).
|
|
69
|
-
*/
|
|
70
|
-
function formatDimLabel(label: string, value: string): string {
|
|
71
|
-
return ` ${pc.dim("•")} ${pc.dim(label.padEnd(10))} ${pc.dim(value)}`;
|
|
72
|
-
}
|
|
46
|
+
} from "../types";
|
|
47
|
+
import { logEnvironmentInfo } from "./logging";
|
|
48
|
+
import { createCheckTableHelper, createSeedCheckContext } from "./seeding";
|
|
73
49
|
|
|
74
50
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
75
51
|
// Environment Factory
|
|
@@ -107,13 +83,25 @@ export function createDevEnvironment<
|
|
|
107
83
|
// Compute environment values
|
|
108
84
|
const root = findMonorepoRoot();
|
|
109
85
|
const suffix = options.suffix;
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
86
|
+
const identity = computeDevIdentity({
|
|
87
|
+
projectPrefix: config.projectPrefix,
|
|
88
|
+
suffix,
|
|
89
|
+
root,
|
|
90
|
+
worktreeIsolation: config.options?.worktreeIsolation,
|
|
91
|
+
});
|
|
92
|
+
const { worktree, projectSuffix, portOffset, projectName } = identity;
|
|
113
93
|
const localIp = getLocalIp();
|
|
114
94
|
|
|
115
95
|
const services = config.services;
|
|
116
96
|
const apps = (config.apps ?? {}) as TApps;
|
|
97
|
+
const composeFile = getGeneratedComposePath(
|
|
98
|
+
root,
|
|
99
|
+
config.docker,
|
|
100
|
+
).composeFileArg;
|
|
101
|
+
|
|
102
|
+
function ensureComposeFile(): string {
|
|
103
|
+
return writeGeneratedComposeFile(root, services, config.docker);
|
|
104
|
+
}
|
|
117
105
|
|
|
118
106
|
// Compute ports and URLs
|
|
119
107
|
const ports = computePorts(services, apps, portOffset) as ComputedPorts<
|
|
@@ -124,6 +112,22 @@ export function createDevEnvironment<
|
|
|
124
112
|
TServices,
|
|
125
113
|
TApps
|
|
126
114
|
>;
|
|
115
|
+
const publicUrls: Record<string, string> = {};
|
|
116
|
+
|
|
117
|
+
function setPublicUrls(urlsInput: Record<string, string>): void {
|
|
118
|
+
for (const key of Object.keys(publicUrls)) {
|
|
119
|
+
delete publicUrls[key];
|
|
120
|
+
}
|
|
121
|
+
for (const [key, value] of Object.entries(urlsInput)) {
|
|
122
|
+
publicUrls[key] = value;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function clearPublicUrls(): void {
|
|
127
|
+
for (const key of Object.keys(publicUrls)) {
|
|
128
|
+
delete publicUrls[key];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
127
131
|
|
|
128
132
|
// Build environment variables
|
|
129
133
|
function buildEnvVars(production = false): Record<string, string> {
|
|
@@ -144,12 +148,19 @@ export function createDevEnvironment<
|
|
|
144
148
|
baseEnv[envName] = url;
|
|
145
149
|
}
|
|
146
150
|
|
|
151
|
+
// Add public URL environment variables when tunnels are active
|
|
152
|
+
for (const [name, url] of Object.entries(publicUrls)) {
|
|
153
|
+
const envName = `${name.toUpperCase()}_PUBLIC_URL`;
|
|
154
|
+
baseEnv[envName] = url;
|
|
155
|
+
}
|
|
156
|
+
|
|
147
157
|
// Call user's envVars function if provided
|
|
148
158
|
if (config.envVars) {
|
|
149
159
|
const userEnv = config.envVars(ports, urls, {
|
|
150
160
|
projectName,
|
|
151
161
|
localIp,
|
|
152
162
|
portOffset,
|
|
163
|
+
publicUrls: publicUrls as ComputedPublicUrls<TServices, TApps>,
|
|
153
164
|
});
|
|
154
165
|
for (const [key, value] of Object.entries(userEnv)) {
|
|
155
166
|
baseEnv[key] = String(value);
|
|
@@ -168,6 +179,7 @@ export function createDevEnvironment<
|
|
|
168
179
|
projectName,
|
|
169
180
|
ports,
|
|
170
181
|
urls,
|
|
182
|
+
publicUrls: publicUrls as ComputedPublicUrls<TServices, TApps>,
|
|
171
183
|
root,
|
|
172
184
|
isCI: isCIEnv(),
|
|
173
185
|
portOffset,
|
|
@@ -204,6 +216,7 @@ export function createDevEnvironment<
|
|
|
204
216
|
} = startOptions;
|
|
205
217
|
|
|
206
218
|
const envVars = buildEnvVars(productionBuild);
|
|
219
|
+
ensureComposeFile();
|
|
207
220
|
|
|
208
221
|
// Log environment info
|
|
209
222
|
if (verbose) {
|
|
@@ -223,16 +236,7 @@ export function createDevEnvironment<
|
|
|
223
236
|
startContainers(root, projectName, envVars, {
|
|
224
237
|
verbose,
|
|
225
238
|
wait,
|
|
226
|
-
composeFile
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Wait for services to be healthy
|
|
231
|
-
if (wait) {
|
|
232
|
-
await waitForAllServices(services, ports, {
|
|
233
|
-
verbose,
|
|
234
|
-
projectName,
|
|
235
|
-
root,
|
|
239
|
+
composeFile,
|
|
236
240
|
});
|
|
237
241
|
}
|
|
238
242
|
|
|
@@ -266,19 +270,19 @@ export function createDevEnvironment<
|
|
|
266
270
|
}),
|
|
267
271
|
);
|
|
268
272
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
// Check for failures
|
|
274
|
+
for (const { name, result } of migrationResults) {
|
|
275
|
+
if (result.exitCode !== 0) {
|
|
276
|
+
console.error(`❌ Migration "${name}" failed`);
|
|
277
|
+
if (result.stdout) {
|
|
278
|
+
console.error(result.stdout);
|
|
279
|
+
}
|
|
280
|
+
if (result.stderr) {
|
|
281
|
+
console.error(result.stderr);
|
|
282
|
+
}
|
|
283
|
+
throw new Error(`Migration "${name}" failed`);
|
|
278
284
|
}
|
|
279
|
-
throw new Error(`Migration "${name}" failed`);
|
|
280
285
|
}
|
|
281
|
-
}
|
|
282
286
|
|
|
283
287
|
if (verbose) console.log("✓ Migrations complete");
|
|
284
288
|
}
|
|
@@ -294,35 +298,14 @@ export function createDevEnvironment<
|
|
|
294
298
|
|
|
295
299
|
// Check if seeding is needed using check function
|
|
296
300
|
if (config.seed.check) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
service?: keyof TServices,
|
|
301
|
-
): Promise<boolean> => {
|
|
302
|
-
const serviceName = (service ?? "postgres") as string;
|
|
303
|
-
const serviceUrl = (urls as Record<string, string>)[serviceName];
|
|
304
|
-
if (!serviceUrl) {
|
|
305
|
-
console.warn(`⚠️ Service "${serviceName}" not found for checkTable`);
|
|
306
|
-
return true; // Default to seeding if service not found
|
|
307
|
-
}
|
|
308
|
-
const checkResult = await exec(
|
|
309
|
-
`psql "${serviceUrl}" -tAc 'SELECT COUNT(*) FROM "${tableName}" LIMIT 1'`,
|
|
310
|
-
{ throwOnError: false },
|
|
301
|
+
const checkTable = createCheckTableHelper<TServices, TApps>(
|
|
302
|
+
urls as Record<string, string>,
|
|
303
|
+
exec,
|
|
311
304
|
);
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
if (!shouldSeed) {
|
|
315
|
-
console.log(` 📊 Table "${tableName}" has ${count} rows`);
|
|
316
|
-
}
|
|
317
|
-
return shouldSeed;
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
// Build seed check context with helpers
|
|
321
|
-
const seedCheckContext = {
|
|
322
|
-
...getHookContext(),
|
|
305
|
+
const seedCheckContext = createSeedCheckContext(
|
|
306
|
+
getHookContext(),
|
|
323
307
|
checkTable,
|
|
324
|
-
|
|
325
|
-
|
|
308
|
+
);
|
|
326
309
|
shouldSeed = await config.seed.check(seedCheckContext);
|
|
327
310
|
}
|
|
328
311
|
|
|
@@ -388,6 +371,7 @@ export function createDevEnvironment<
|
|
|
388
371
|
|
|
389
372
|
async function stop(stopOptions: StopOptions = {}): Promise<void> {
|
|
390
373
|
const { verbose = true, removeVolumes = false } = stopOptions;
|
|
374
|
+
ensureComposeFile();
|
|
391
375
|
|
|
392
376
|
// Run beforeStop hook
|
|
393
377
|
if (config.hooks?.beforeStop) {
|
|
@@ -397,7 +381,7 @@ export function createDevEnvironment<
|
|
|
397
381
|
stopContainers(root, projectName, {
|
|
398
382
|
verbose,
|
|
399
383
|
removeVolumes,
|
|
400
|
-
composeFile
|
|
384
|
+
composeFile,
|
|
401
385
|
});
|
|
402
386
|
}
|
|
403
387
|
|
|
@@ -446,54 +430,17 @@ export function createDevEnvironment<
|
|
|
446
430
|
// ─────────────────────────────────────────────────────────────────────────
|
|
447
431
|
|
|
448
432
|
function logInfo(label = "Docker Dev"): void {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
for (const name of serviceNames) {
|
|
461
|
-
const port = (ports as Record<string, number>)[name];
|
|
462
|
-
const url = `localhost:${port}`;
|
|
463
|
-
console.log(formatLabel(`${name}:`, formatUrl(`http://${url}`)));
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Apps section (Dev servers)
|
|
468
|
-
if (appNames.length > 0) {
|
|
469
|
-
console.log("");
|
|
470
|
-
console.log(` ${pc.dim("─── Applications ───")}`);
|
|
471
|
-
for (const name of appNames) {
|
|
472
|
-
const port = (ports as Record<string, number>)[name];
|
|
473
|
-
const localUrl = `http://localhost:${port}`;
|
|
474
|
-
const networkUrl = `http://${localIp}:${port}`;
|
|
475
|
-
|
|
476
|
-
console.log(` ${pc.green("➜")} ${pc.bold(pc.cyan(name))}`);
|
|
477
|
-
console.log(` ${pc.dim("Local:")} ${formatUrl(localUrl)}`);
|
|
478
|
-
console.log(` ${pc.dim("Network:")} ${formatUrl(networkUrl)}`);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// Environment info
|
|
483
|
-
console.log("");
|
|
484
|
-
console.log(` ${pc.dim("─── Environment ───")}`);
|
|
485
|
-
console.log(formatDimLabel("Worktree:", worktree ? "yes" : "no"));
|
|
486
|
-
console.log(
|
|
487
|
-
formatDimLabel(
|
|
488
|
-
"Port offset:",
|
|
489
|
-
portOffset > 0 ? `+${portOffset}` : "none",
|
|
490
|
-
),
|
|
491
|
-
);
|
|
492
|
-
if (suffix) {
|
|
493
|
-
console.log(formatDimLabel("Suffix:", suffix));
|
|
494
|
-
}
|
|
495
|
-
console.log(formatDimLabel("Local IP:", localIp));
|
|
496
|
-
console.log("");
|
|
433
|
+
logEnvironmentInfo({
|
|
434
|
+
label,
|
|
435
|
+
projectName,
|
|
436
|
+
services,
|
|
437
|
+
apps,
|
|
438
|
+
ports: ports as Record<string, number>,
|
|
439
|
+
localIp,
|
|
440
|
+
worktree,
|
|
441
|
+
portOffset,
|
|
442
|
+
projectSuffix,
|
|
443
|
+
});
|
|
497
444
|
}
|
|
498
445
|
|
|
499
446
|
async function waitForServerUrl(
|
|
@@ -519,7 +466,7 @@ export function createDevEnvironment<
|
|
|
519
466
|
await spawnWatchdogFn(projectName, root, {
|
|
520
467
|
timeoutMinutes,
|
|
521
468
|
verbose: true,
|
|
522
|
-
composeFile
|
|
469
|
+
composeFile,
|
|
523
470
|
});
|
|
524
471
|
}
|
|
525
472
|
|
|
@@ -562,11 +509,14 @@ export function createDevEnvironment<
|
|
|
562
509
|
projectName,
|
|
563
510
|
ports,
|
|
564
511
|
urls,
|
|
512
|
+
publicUrls: publicUrls as ComputedPublicUrls<TServices, TApps>,
|
|
513
|
+
services,
|
|
565
514
|
apps,
|
|
566
515
|
portOffset,
|
|
567
516
|
isWorktree: worktree,
|
|
568
517
|
localIp,
|
|
569
518
|
root,
|
|
519
|
+
composeFile,
|
|
570
520
|
|
|
571
521
|
// Container management
|
|
572
522
|
start,
|
|
@@ -581,6 +531,11 @@ export function createDevEnvironment<
|
|
|
581
531
|
|
|
582
532
|
// Utilities
|
|
583
533
|
buildEnvVars,
|
|
534
|
+
setPublicUrls: (urlsInput) => {
|
|
535
|
+
setPublicUrls(urlsInput as Record<string, string>);
|
|
536
|
+
},
|
|
537
|
+
clearPublicUrls,
|
|
538
|
+
ensureComposeFile,
|
|
584
539
|
exec,
|
|
585
540
|
waitForServer: waitForServerUrl,
|
|
586
541
|
logInfo,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createDevEnvironment } from "./create-dev-environment";
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
|
|
3
|
+
function formatUrl(url: string): string {
|
|
4
|
+
return pc.cyan(
|
|
5
|
+
url.replace(/:(\d+)(\/?)/, (_, port, slash) => `:${pc.bold(port)}${slash}`),
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function formatLabel(label: string, value: string, arrow = "➜"): string {
|
|
10
|
+
return ` ${pc.green(arrow)} ${pc.bold(label.padEnd(10))} ${value}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function formatDimLabel(label: string, value: string): string {
|
|
14
|
+
return ` ${pc.dim("•")} ${pc.dim(label.padEnd(10))} ${pc.dim(value)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function logEnvironmentInfo(input: {
|
|
18
|
+
label: string;
|
|
19
|
+
projectName: string;
|
|
20
|
+
services: Record<string, unknown>;
|
|
21
|
+
apps: Record<string, unknown>;
|
|
22
|
+
ports: Record<string, number>;
|
|
23
|
+
localIp: string;
|
|
24
|
+
worktree: boolean;
|
|
25
|
+
portOffset: number;
|
|
26
|
+
projectSuffix?: string;
|
|
27
|
+
}): void {
|
|
28
|
+
const {
|
|
29
|
+
label,
|
|
30
|
+
projectName,
|
|
31
|
+
services,
|
|
32
|
+
apps,
|
|
33
|
+
ports,
|
|
34
|
+
localIp,
|
|
35
|
+
worktree,
|
|
36
|
+
portOffset,
|
|
37
|
+
projectSuffix,
|
|
38
|
+
} = input;
|
|
39
|
+
const serviceNames = Object.keys(services);
|
|
40
|
+
const appNames = Object.keys(apps);
|
|
41
|
+
|
|
42
|
+
console.log("");
|
|
43
|
+
console.log(` ${pc.cyan(pc.bold(`🐳 ${label}`))}`);
|
|
44
|
+
console.log(formatLabel("Project:", pc.white(projectName)));
|
|
45
|
+
|
|
46
|
+
if (serviceNames.length > 0) {
|
|
47
|
+
console.log("");
|
|
48
|
+
console.log(` ${pc.dim("─── Services ───")}`);
|
|
49
|
+
for (const name of serviceNames) {
|
|
50
|
+
const port = ports[name];
|
|
51
|
+
const url = `localhost:${port}`;
|
|
52
|
+
console.log(formatLabel(`${name}:`, formatUrl(`http://${url}`)));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (appNames.length > 0) {
|
|
57
|
+
console.log("");
|
|
58
|
+
console.log(` ${pc.dim("─── Applications ───")}`);
|
|
59
|
+
for (const name of appNames) {
|
|
60
|
+
const port = ports[name];
|
|
61
|
+
const localUrl = `http://localhost:${port}`;
|
|
62
|
+
const networkUrl = `http://${localIp}:${port}`;
|
|
63
|
+
|
|
64
|
+
console.log(` ${pc.green("➜")} ${pc.bold(pc.cyan(name))}`);
|
|
65
|
+
console.log(` ${pc.dim("Local:")} ${formatUrl(localUrl)}`);
|
|
66
|
+
console.log(` ${pc.dim("Network:")} ${formatUrl(networkUrl)}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log("");
|
|
71
|
+
console.log(` ${pc.dim("─── Environment ───")}`);
|
|
72
|
+
console.log(formatDimLabel("Worktree:", worktree ? "yes" : "no"));
|
|
73
|
+
console.log(
|
|
74
|
+
formatDimLabel("Port offset:", portOffset > 0 ? `+${portOffset}` : "none"),
|
|
75
|
+
);
|
|
76
|
+
if (projectSuffix) {
|
|
77
|
+
console.log(formatDimLabel("Suffix:", projectSuffix));
|
|
78
|
+
}
|
|
79
|
+
console.log(formatDimLabel("Local IP:", localIp));
|
|
80
|
+
console.log("");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function logPublicUrls(
|
|
84
|
+
tunnels: Array<{
|
|
85
|
+
kind: "service" | "app";
|
|
86
|
+
name: string;
|
|
87
|
+
publicUrl: string;
|
|
88
|
+
localUrl: string;
|
|
89
|
+
}>,
|
|
90
|
+
): void {
|
|
91
|
+
if (tunnels.length === 0) return;
|
|
92
|
+
|
|
93
|
+
console.log("");
|
|
94
|
+
console.log(` ${pc.dim("─── Public URLs (Quick Tunnel) ───")}`);
|
|
95
|
+
for (const tunnel of tunnels) {
|
|
96
|
+
const label = `${tunnel.name} (${tunnel.kind})`;
|
|
97
|
+
console.log(formatLabel(`${label}:`, formatUrl(tunnel.publicUrl), "🌐"));
|
|
98
|
+
console.log(formatDimLabel("Local target:", tunnel.localUrl));
|
|
99
|
+
}
|
|
100
|
+
console.log("");
|
|
101
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AppConfig,
|
|
3
|
+
HookContext,
|
|
4
|
+
SeedCheckContext,
|
|
5
|
+
ServiceConfig,
|
|
6
|
+
} from "../types";
|
|
7
|
+
|
|
8
|
+
export function createCheckTableHelper<
|
|
9
|
+
TServices extends Record<string, ServiceConfig>,
|
|
10
|
+
TApps extends Record<string, AppConfig>,
|
|
11
|
+
>(
|
|
12
|
+
urls: Record<string, string>,
|
|
13
|
+
exec: (
|
|
14
|
+
cmd: string,
|
|
15
|
+
options?: { throwOnError?: boolean },
|
|
16
|
+
) => Promise<{
|
|
17
|
+
exitCode: number;
|
|
18
|
+
stdout: string;
|
|
19
|
+
stderr: string;
|
|
20
|
+
}>,
|
|
21
|
+
): SeedCheckContext<TServices, TApps>["checkTable"] {
|
|
22
|
+
return async (
|
|
23
|
+
tableName: string,
|
|
24
|
+
service?: keyof TServices,
|
|
25
|
+
): Promise<boolean> => {
|
|
26
|
+
const serviceName = (service ?? "postgres") as string;
|
|
27
|
+
const serviceUrl = urls[serviceName];
|
|
28
|
+
if (!serviceUrl) {
|
|
29
|
+
console.warn(`⚠️ Service "${serviceName}" not found for checkTable`);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
const checkResult = await exec(
|
|
33
|
+
`psql "${serviceUrl}" -tAc 'SELECT COUNT(*) FROM "${tableName}" LIMIT 1'`,
|
|
34
|
+
{ throwOnError: false },
|
|
35
|
+
);
|
|
36
|
+
const count = checkResult.stdout.trim();
|
|
37
|
+
const shouldSeed =
|
|
38
|
+
checkResult.exitCode !== 0 || count === "0" || count === "";
|
|
39
|
+
if (!shouldSeed) {
|
|
40
|
+
console.log(` 📊 Table "${tableName}" has ${count} rows`);
|
|
41
|
+
}
|
|
42
|
+
return shouldSeed;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function createSeedCheckContext<
|
|
47
|
+
TServices extends Record<string, ServiceConfig>,
|
|
48
|
+
TApps extends Record<string, AppConfig>,
|
|
49
|
+
>(
|
|
50
|
+
baseContext: HookContext<TServices, TApps>,
|
|
51
|
+
checkTable: SeedCheckContext<TServices, TApps>["checkTable"],
|
|
52
|
+
): SeedCheckContext<TServices, TApps> {
|
|
53
|
+
return {
|
|
54
|
+
...baseContext,
|
|
55
|
+
checkTable,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -3,25 +3,33 @@
|
|
|
3
3
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
4
4
|
|
|
5
5
|
// CLI runner
|
|
6
|
-
export { getFlagValue, hasFlag, runCli } from "./cli";
|
|
6
|
+
export { getFlagValue, hasFlag, runCli } from "./cli/run-cli";
|
|
7
7
|
// Config factory
|
|
8
8
|
export {
|
|
9
9
|
assertValidConfig,
|
|
10
10
|
defineDevConfig,
|
|
11
11
|
mergeConfigs,
|
|
12
12
|
validateConfig,
|
|
13
|
-
} from "./config";
|
|
13
|
+
} from "./config/index";
|
|
14
|
+
export type {
|
|
15
|
+
ClickhouseServiceOptions,
|
|
16
|
+
CustomServiceOptions,
|
|
17
|
+
PostgresServiceOptions,
|
|
18
|
+
RedisServiceOptions,
|
|
19
|
+
} from "./docker-compose/services";
|
|
20
|
+
// Service helpers
|
|
21
|
+
export { service } from "./docker-compose/services";
|
|
14
22
|
// Environment factory
|
|
15
|
-
export { createDevEnvironment } from "./environment";
|
|
23
|
+
export { createDevEnvironment } from "./environment/index";
|
|
24
|
+
// Config loader (for programmatic access)
|
|
25
|
+
export { clearDevEnvCache, getDevEnv, loadDevEnv } from "./loader/index";
|
|
16
26
|
// Lint / Typecheck
|
|
17
27
|
export {
|
|
18
28
|
runWorkspaceTypecheck,
|
|
19
29
|
type TypecheckResult,
|
|
20
30
|
type WorkspaceTypecheckOptions,
|
|
21
31
|
type WorkspaceTypecheckResult,
|
|
22
|
-
} from "./
|
|
23
|
-
// Config loader (for programmatic access)
|
|
24
|
-
export { clearDevEnvCache, getDevEnv, loadDevEnv } from "./loader";
|
|
32
|
+
} from "./typecheck/index";
|
|
25
33
|
|
|
26
34
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
27
35
|
// Types
|
|
@@ -34,6 +42,7 @@ export type {
|
|
|
34
42
|
CliOptions,
|
|
35
43
|
// Computed types
|
|
36
44
|
ComputedPorts,
|
|
45
|
+
ComputedPublicUrls,
|
|
37
46
|
ComputedUrls,
|
|
38
47
|
// Main config
|
|
39
48
|
DevConfig,
|
|
@@ -42,6 +51,14 @@ export type {
|
|
|
42
51
|
DevHooks,
|
|
43
52
|
DevOptions,
|
|
44
53
|
DevServerPids,
|
|
54
|
+
DockerComposeGenerationOptions,
|
|
55
|
+
DockerComposeHealthcheckRaw,
|
|
56
|
+
DockerComposeNode,
|
|
57
|
+
DockerComposeServiceRaw,
|
|
58
|
+
DockerComposeVolumeRaw,
|
|
59
|
+
DockerPresetName,
|
|
60
|
+
DockerPresetServiceDefinition,
|
|
61
|
+
DockerServiceDefinition,
|
|
45
62
|
EnvVarsBuilder,
|
|
46
63
|
ExecOptions,
|
|
47
64
|
HealthCheckFn,
|
|
@@ -61,28 +78,22 @@ export type {
|
|
|
61
78
|
StopOptions,
|
|
62
79
|
UrlBuilderContext,
|
|
63
80
|
UrlBuilderFn,
|
|
64
|
-
} from "./types";
|
|
81
|
+
} from "./types/index";
|
|
65
82
|
|
|
66
83
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
67
84
|
// Core Utilities (for advanced use cases)
|
|
68
85
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
69
86
|
|
|
70
|
-
export {
|
|
71
|
-
areContainersRunning,
|
|
72
|
-
isContainerRunning,
|
|
73
|
-
MAX_ATTEMPTS,
|
|
74
|
-
POLL_INTERVAL,
|
|
75
|
-
} from "./core/docker";
|
|
76
|
-
|
|
77
87
|
export { getLocalIp, isPortAvailable, waitForServer } from "./core/network";
|
|
78
88
|
export {
|
|
79
89
|
calculatePortOffset,
|
|
90
|
+
computeDevIdentity,
|
|
80
91
|
findMonorepoRoot,
|
|
81
92
|
getProjectName,
|
|
82
93
|
getWorktreeName,
|
|
94
|
+
getWorktreeProjectSuffix,
|
|
83
95
|
isWorktree,
|
|
84
96
|
} from "./core/ports";
|
|
85
|
-
|
|
86
97
|
export {
|
|
87
98
|
getProcessOnPort,
|
|
88
99
|
isPortInUse,
|
|
@@ -91,6 +102,13 @@ export {
|
|
|
91
102
|
killProcessOnPort,
|
|
92
103
|
killProcessOnPortAndWait,
|
|
93
104
|
} from "./core/process";
|
|
105
|
+
export {
|
|
106
|
+
type PublicExposeTarget,
|
|
107
|
+
type PublicTunnel,
|
|
108
|
+
resolveExposeTargets,
|
|
109
|
+
startPublicTunnels,
|
|
110
|
+
stopPublicTunnels,
|
|
111
|
+
} from "./core/tunnel";
|
|
94
112
|
export {
|
|
95
113
|
getEnvVar,
|
|
96
114
|
isCI,
|
|
@@ -108,3 +126,19 @@ export {
|
|
|
108
126
|
stopHeartbeat,
|
|
109
127
|
stopWatchdog,
|
|
110
128
|
} from "./core/watchdog";
|
|
129
|
+
export {
|
|
130
|
+
areContainersRunning,
|
|
131
|
+
assertDockerRunning,
|
|
132
|
+
DOCKER_NOT_RUNNING_MESSAGE,
|
|
133
|
+
isContainerRunning,
|
|
134
|
+
isDockerRunning,
|
|
135
|
+
MAX_ATTEMPTS,
|
|
136
|
+
POLL_INTERVAL,
|
|
137
|
+
} from "./docker/index";
|
|
138
|
+
export {
|
|
139
|
+
buildComposeModel,
|
|
140
|
+
composeToYaml,
|
|
141
|
+
DEFAULT_GENERATED_COMPOSE_FILE,
|
|
142
|
+
getGeneratedComposePath,
|
|
143
|
+
writeGeneratedComposeFile,
|
|
144
|
+
} from "./docker-compose/index";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AppConfig, DevEnvironment, ServiceConfig } from "../types";
|
|
2
|
+
|
|
3
|
+
let cachedEnv: DevEnvironment<
|
|
4
|
+
Record<string, ServiceConfig>,
|
|
5
|
+
Record<string, AppConfig>
|
|
6
|
+
> | null = null;
|
|
7
|
+
|
|
8
|
+
export function setCachedDevEnv(
|
|
9
|
+
env: DevEnvironment<Record<string, ServiceConfig>, Record<string, AppConfig>>,
|
|
10
|
+
): void {
|
|
11
|
+
cachedEnv = env;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getCachedDevEnv(): DevEnvironment<
|
|
15
|
+
Record<string, ServiceConfig>,
|
|
16
|
+
Record<string, AppConfig>
|
|
17
|
+
> | null {
|
|
18
|
+
return cachedEnv;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function clearDevEnvCache(): void {
|
|
22
|
+
cachedEnv = null;
|
|
23
|
+
}
|