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.
- package/dist/bin.d.ts +1 -12
- package/dist/bin.js +261 -253
- 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 -83
- package/dist/core/docker.js +35 -32
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +123 -118
- package/dist/core/network.js +2 -2
- package/dist/core/ports.js +1 -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 +51 -43
- 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 +157 -142
- 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 +118 -97
- 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 +78 -76
- 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 +385 -375
- 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 +240 -199
- package/dist/index.d.ts +12 -8
- package/dist/index.js +56 -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 -399
- package/package.json +145 -140
- package/readme.md +349 -109
- 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 +5 -2
- 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} +11 -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} +93 -130
- 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 -20
- 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} +130 -5
- package/src/types/index.ts +1 -0
- package/bin.ts +0 -192
- 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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
calculatePortOffset,
|
|
3
|
+
computePorts,
|
|
4
|
+
computeUrls
|
|
5
|
+
} from "./index-fb29934k.js";
|
|
6
|
+
|
|
7
|
+
// src/core/network.ts
|
|
8
|
+
import { networkInterfaces } from "node:os";
|
|
9
|
+
function getLocalIp() {
|
|
10
|
+
const interfaces = networkInterfaces();
|
|
11
|
+
for (const name of Object.keys(interfaces)) {
|
|
12
|
+
const nets = interfaces[name];
|
|
13
|
+
if (!nets)
|
|
14
|
+
continue;
|
|
15
|
+
for (const net of nets) {
|
|
16
|
+
if (net.family === "IPv4" && !net.internal) {
|
|
17
|
+
return net.address;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return "127.0.0.1";
|
|
22
|
+
}
|
|
23
|
+
async function waitForServer(url, options = {}) {
|
|
24
|
+
const { timeout = 30000, interval = 2000, verbose = false } = options;
|
|
25
|
+
const start = Date.now();
|
|
26
|
+
let attempts = 0;
|
|
27
|
+
while (Date.now() - start < timeout) {
|
|
28
|
+
attempts++;
|
|
29
|
+
const controller = new AbortController;
|
|
30
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(url, {
|
|
33
|
+
signal: controller.signal
|
|
34
|
+
});
|
|
35
|
+
clearTimeout(timeoutId);
|
|
36
|
+
if (response.ok || response.status === 404) {
|
|
37
|
+
if (verbose) {
|
|
38
|
+
console.log(` ✓ ${url} ready after ${attempts} attempts`);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
clearTimeout(timeoutId);
|
|
44
|
+
if (verbose && attempts % 5 === 0) {
|
|
45
|
+
console.log(` ⏳ Waiting for ${url}... (${Math.round((Date.now() - start) / 1000)}s)`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
await sleep(interval);
|
|
49
|
+
}
|
|
50
|
+
throw new Error(`Server at ${url} did not respond within ${timeout}ms after ${attempts} attempts`);
|
|
51
|
+
}
|
|
52
|
+
async function waitForDevServers(apps, ports, options = {}) {
|
|
53
|
+
const { timeout = 60000, verbose = true } = options;
|
|
54
|
+
if (verbose)
|
|
55
|
+
console.log("⏳ Waiting for servers to be ready...");
|
|
56
|
+
const promises = [];
|
|
57
|
+
for (const [name, config] of Object.entries(apps)) {
|
|
58
|
+
const port = ports[name];
|
|
59
|
+
const healthPath = config.healthEndpoint ?? "/";
|
|
60
|
+
const url = `http://localhost:${port}${healthPath}`;
|
|
61
|
+
const appTimeout = config.healthTimeout ?? timeout;
|
|
62
|
+
promises.push(waitForServer(url, { timeout: appTimeout, verbose }));
|
|
63
|
+
}
|
|
64
|
+
await Promise.all(promises);
|
|
65
|
+
if (verbose)
|
|
66
|
+
console.log("✓ All servers ready");
|
|
67
|
+
}
|
|
68
|
+
async function isPortAvailable(port) {
|
|
69
|
+
const controller = new AbortController;
|
|
70
|
+
const timeoutId = setTimeout(() => controller.abort(), 500);
|
|
71
|
+
try {
|
|
72
|
+
const _response = await fetch(`http://localhost:${port}/`, {
|
|
73
|
+
signal: controller.signal
|
|
74
|
+
});
|
|
75
|
+
clearTimeout(timeoutId);
|
|
76
|
+
return false;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
clearTimeout(timeoutId);
|
|
79
|
+
if (error instanceof Error) {
|
|
80
|
+
if (error.message.includes("ECONNREFUSED") || error.message.includes("fetch failed")) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/core/utils.ts
|
|
89
|
+
function sleep(ms) {
|
|
90
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
91
|
+
}
|
|
92
|
+
function isCI() {
|
|
93
|
+
return process.env.CI === "true" || process.env.CI === "1" || process.env.GITHUB_ACTIONS === "true" || process.env.GITLAB_CI === "true" || process.env.CIRCLECI === "true" || process.env.JENKINS_URL !== undefined;
|
|
94
|
+
}
|
|
95
|
+
function logFrontendPort(port) {
|
|
96
|
+
console.log(`using_frontend_port:${port}`);
|
|
97
|
+
}
|
|
98
|
+
function getEnvVar(config, name, options = {}) {
|
|
99
|
+
const { log = true } = options;
|
|
100
|
+
const offset = calculatePortOffset();
|
|
101
|
+
const localIp = getLocalIp();
|
|
102
|
+
const ports = computePorts(config.services, config.apps, offset);
|
|
103
|
+
const urls = computeUrls(config.services, config.apps, ports, localIp);
|
|
104
|
+
const envVars = config.envVars?.(ports, urls, {
|
|
105
|
+
projectName: config.projectPrefix,
|
|
106
|
+
localIp,
|
|
107
|
+
portOffset: offset,
|
|
108
|
+
publicUrls: {}
|
|
109
|
+
});
|
|
110
|
+
const value = envVars?.[name];
|
|
111
|
+
if (log && name === "VITE_PORT" && typeof value === "number") {
|
|
112
|
+
logFrontendPort(value);
|
|
113
|
+
}
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
function logApiUrl(url) {
|
|
117
|
+
console.log(`using_api_url:${url}`);
|
|
118
|
+
}
|
|
119
|
+
function logExpoApiUrl(url) {
|
|
120
|
+
console.log(`using_expo_api_url:${url}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { sleep, isCI, logFrontendPort, getEnvVar, logApiUrl, logExpoApiUrl, getLocalIp, waitForServer, waitForDevServers, isPortAvailable };
|
package/dist/index-cty0bcry.js
CHANGED
|
@@ -1,248 +1,265 @@
|
|
|
1
1
|
// core/process.ts
|
|
2
|
-
import {
|
|
3
|
-
execSync,
|
|
4
|
-
spawn
|
|
5
|
-
} from "node:child_process";
|
|
2
|
+
import { execSync, spawn } from "node:child_process";
|
|
6
3
|
import { platform } from "node:os";
|
|
7
4
|
import { resolve } from "node:path";
|
|
5
|
+
|
|
8
6
|
function exec(cmd, root, envVars, options = {}) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
7
|
+
const { cwd, verbose = false, env = {}, throwOnError = true } = options;
|
|
8
|
+
const workingDir = cwd ? resolve(root, cwd) : root;
|
|
9
|
+
const fullEnv = { ...process.env, ...envVars, ...env };
|
|
10
|
+
try {
|
|
11
|
+
const stdout = execSync(cmd, {
|
|
12
|
+
cwd: workingDir,
|
|
13
|
+
env: fullEnv,
|
|
14
|
+
encoding: "utf-8",
|
|
15
|
+
stdio: verbose ? "inherit" : ["pipe", "pipe", "pipe"],
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
exitCode: 0,
|
|
19
|
+
stdout: typeof stdout === "string" ? stdout : "",
|
|
20
|
+
stderr: "",
|
|
21
|
+
};
|
|
22
|
+
} catch (error) {
|
|
23
|
+
const execError = error;
|
|
24
|
+
const result = {
|
|
25
|
+
exitCode: execError.status ?? 1,
|
|
26
|
+
stdout: execError.stdout ?? "",
|
|
27
|
+
stderr: execError.stderr ?? "",
|
|
28
|
+
};
|
|
29
|
+
if (throwOnError) {
|
|
30
|
+
throw new Error(`Command failed with exit code ${result.exitCode}: ${cmd}
|
|
33
31
|
${result.stderr}`);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
37
35
|
}
|
|
38
36
|
async function execAsync(cmd, root, envVars, options = {}) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
return new Promise((resolve2) => {
|
|
38
|
+
const result = exec(cmd, root, envVars, {
|
|
39
|
+
...options,
|
|
40
|
+
throwOnError: false,
|
|
41
|
+
});
|
|
42
|
+
resolve2(result);
|
|
43
|
+
});
|
|
46
44
|
}
|
|
47
45
|
async function spawnDevServer(command, root, appCwd, envVars, options = {}) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
46
|
+
const {
|
|
47
|
+
verbose = false,
|
|
48
|
+
detached = true,
|
|
49
|
+
isCI = false,
|
|
50
|
+
killExisting = true,
|
|
51
|
+
port,
|
|
52
|
+
} = options;
|
|
53
|
+
if (killExisting && port !== undefined) {
|
|
54
|
+
const existingPid = getProcessOnPort(port);
|
|
55
|
+
if (existingPid !== null) {
|
|
56
|
+
if (verbose) {
|
|
57
|
+
console.log(` ⚠️ Port ${port} is in use by process ${existingPid}`);
|
|
58
|
+
}
|
|
59
|
+
await killProcessOnPortAndWait(port, { verbose });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const parts = command.split(" ");
|
|
63
|
+
const cmd = parts[0];
|
|
64
|
+
const args = parts.slice(1);
|
|
65
|
+
if (!cmd) {
|
|
66
|
+
throw new Error("Command cannot be empty");
|
|
67
|
+
}
|
|
68
|
+
const workingDir = appCwd ? resolve(root, appCwd) : root;
|
|
69
|
+
const spawnOptions = {
|
|
70
|
+
cwd: workingDir,
|
|
71
|
+
env: { ...process.env, ...envVars },
|
|
72
|
+
detached,
|
|
73
|
+
stdio: isCI || verbose ? "inherit" : "ignore",
|
|
74
|
+
};
|
|
75
|
+
const proc = spawn(cmd, args, spawnOptions);
|
|
76
|
+
if (detached && proc.unref) {
|
|
77
|
+
proc.unref();
|
|
78
|
+
}
|
|
79
|
+
return proc;
|
|
82
80
|
}
|
|
83
81
|
async function startDevServers(apps, root, envVars, ports, options = {}) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
82
|
+
const {
|
|
83
|
+
verbose = true,
|
|
84
|
+
productionBuild = false,
|
|
85
|
+
isCI = false,
|
|
86
|
+
killExisting = true,
|
|
87
|
+
} = options;
|
|
88
|
+
const pids = {};
|
|
89
|
+
if (verbose) {
|
|
90
|
+
console.log(
|
|
91
|
+
productionBuild
|
|
92
|
+
? "\uD83D\uDE80 Starting production servers..."
|
|
93
|
+
: "\uD83D\uDD27 Starting dev servers...",
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
for (const [name, config] of Object.entries(apps)) {
|
|
97
|
+
const command = productionBuild
|
|
98
|
+
? (config.prodCommand ?? config.devCommand)
|
|
99
|
+
: config.devCommand;
|
|
100
|
+
const port = ports[name];
|
|
101
|
+
const proc = await spawnDevServer(command, root, config.cwd, envVars, {
|
|
102
|
+
verbose,
|
|
103
|
+
isCI,
|
|
104
|
+
killExisting,
|
|
105
|
+
port,
|
|
106
|
+
});
|
|
107
|
+
if (proc.pid) {
|
|
108
|
+
pids[name] = proc.pid;
|
|
109
|
+
if (verbose) {
|
|
110
|
+
console.log(` ${name} PID: ${proc.pid}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return pids;
|
|
111
115
|
}
|
|
112
116
|
function getProcessOnPort(port) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
try {
|
|
118
|
+
const os = platform();
|
|
119
|
+
let output;
|
|
120
|
+
if (os === "win32") {
|
|
121
|
+
output = execSync(`netstat -ano | findstr :${port}`, {
|
|
122
|
+
encoding: "utf-8",
|
|
123
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
124
|
+
});
|
|
125
|
+
const lines = output.trim().split(`
|
|
122
126
|
`);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
`
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
127
|
+
for (const line of lines) {
|
|
128
|
+
if (line.includes("LISTENING")) {
|
|
129
|
+
const parts = line.trim().split(/\s+/);
|
|
130
|
+
const pid = Number.parseInt(parts[parts.length - 1], 10);
|
|
131
|
+
if (!Number.isNaN(pid) && pid > 0) {
|
|
132
|
+
return pid;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
output = execSync(`lsof -ti :${port}`, {
|
|
138
|
+
encoding: "utf-8",
|
|
139
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
140
|
+
});
|
|
141
|
+
const pid = Number.parseInt(
|
|
142
|
+
output.trim().split(`
|
|
143
|
+
`)[0],
|
|
144
|
+
10,
|
|
145
|
+
);
|
|
146
|
+
if (!Number.isNaN(pid) && pid > 0) {
|
|
147
|
+
return pid;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
147
154
|
}
|
|
148
155
|
function isPortInUse(port) {
|
|
149
|
-
|
|
156
|
+
return getProcessOnPort(port) !== null;
|
|
150
157
|
}
|
|
151
158
|
function killProcessOnPort(port, options = {}) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
159
|
+
const { verbose = false, signal = "SIGTERM" } = options;
|
|
160
|
+
const pid = getProcessOnPort(port);
|
|
161
|
+
if (pid === null) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
if (verbose) {
|
|
166
|
+
console.log(` Killing process ${pid} on port ${port}`);
|
|
167
|
+
}
|
|
168
|
+
process.kill(pid, signal);
|
|
169
|
+
return true;
|
|
170
|
+
} catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
166
173
|
}
|
|
167
174
|
async function killProcessOnPortAndWait(port, options = {}) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
175
|
+
const { verbose = false, timeout = 5000 } = options;
|
|
176
|
+
const pid = getProcessOnPort(port);
|
|
177
|
+
if (pid === null) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
if (verbose) {
|
|
181
|
+
console.log(` Killing process ${pid} on port ${port}...`);
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
process.kill(pid, "SIGTERM");
|
|
185
|
+
} catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
const startTime = Date.now();
|
|
189
|
+
const checkInterval = 100;
|
|
190
|
+
while (Date.now() - startTime < timeout) {
|
|
191
|
+
await new Promise((resolve2) => setTimeout(resolve2, checkInterval));
|
|
192
|
+
if (!isPortInUse(port)) {
|
|
193
|
+
if (verbose) {
|
|
194
|
+
console.log(` ✓ Port ${port} released`);
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (verbose) {
|
|
200
|
+
console.log(` Process ${pid} didn't exit, sending SIGKILL...`);
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
process.kill(pid, "SIGKILL");
|
|
204
|
+
} catch {}
|
|
205
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
206
|
+
const released = !isPortInUse(port);
|
|
207
|
+
if (verbose) {
|
|
208
|
+
if (released) {
|
|
209
|
+
console.log(` ✓ Port ${port} released after SIGKILL`);
|
|
210
|
+
} else {
|
|
211
|
+
console.log(` ⚠ Port ${port} still in use`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return released;
|
|
208
215
|
}
|
|
209
216
|
function stopProcess(pid) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
217
|
+
try {
|
|
218
|
+
process.kill(pid, "SIGTERM");
|
|
219
|
+
} catch {}
|
|
213
220
|
}
|
|
214
221
|
function stopAllProcesses(pids, options = {}) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
222
|
+
const { verbose = true } = options;
|
|
223
|
+
for (const [name, pid] of Object.entries(pids)) {
|
|
224
|
+
if (pid) {
|
|
225
|
+
if (verbose) console.log(` Stopping ${name} (PID: ${pid})`);
|
|
226
|
+
stopProcess(pid);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
223
229
|
}
|
|
224
230
|
function isProcessAlive(pid) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
+
try {
|
|
232
|
+
process.kill(pid, 0);
|
|
233
|
+
return true;
|
|
234
|
+
} catch {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
231
237
|
}
|
|
232
238
|
function buildApps(apps, root, envVars, options = {}) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (verbose)
|
|
245
|
-
console.log("✓ Build complete");
|
|
239
|
+
const { verbose = true } = options;
|
|
240
|
+
for (const [name, config] of Object.entries(apps)) {
|
|
241
|
+
if (config.buildCommand) {
|
|
242
|
+
if (verbose) console.log(`\uD83D\uDD28 Building ${name}...`);
|
|
243
|
+
exec(config.buildCommand, root, envVars, {
|
|
244
|
+
cwd: config.cwd,
|
|
245
|
+
verbose,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (verbose) console.log("✓ Build complete");
|
|
246
250
|
}
|
|
247
251
|
|
|
248
|
-
export {
|
|
252
|
+
export {
|
|
253
|
+
exec,
|
|
254
|
+
execAsync,
|
|
255
|
+
spawnDevServer,
|
|
256
|
+
startDevServers,
|
|
257
|
+
getProcessOnPort,
|
|
258
|
+
isPortInUse,
|
|
259
|
+
killProcessOnPort,
|
|
260
|
+
killProcessOnPortAndWait,
|
|
261
|
+
stopProcess,
|
|
262
|
+
stopAllProcesses,
|
|
263
|
+
isProcessAlive,
|
|
264
|
+
buildApps,
|
|
265
|
+
};
|