buncargo 1.0.29 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +317 -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 +30 -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/quick-tunnel/cloudflared-process.d.ts +10 -0
- package/dist/core/quick-tunnel/constants.d.ts +9 -0
- package/dist/core/quick-tunnel/index.d.ts +17 -0
- package/dist/core/quick-tunnel/install.d.ts +1 -0
- package/dist/core/tunnel.d.ts +34 -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/only-apps.d.ts +10 -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-3eyrdxw9.js +577 -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-5aq985p4.js +250 -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-6cmex7m5.js +72 -0
- package/dist/index-6d6x175r.js +572 -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-7v19es2e.js +666 -0
- package/dist/index-8bw1cmz4.js +531 -0
- package/dist/index-8hbbj1mp.js +120 -121
- package/dist/index-8xj2p5n5.js +118 -97
- package/dist/index-9wyhzw0h.js +574 -0
- package/dist/index-ag90ry8t.js +576 -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-byeqyjrz.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-enj4zdma.js +574 -0
- 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-k370bech.js +72 -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-qa8akv6y.js +666 -0
- 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-vg55rq0y.js +250 -0
- package/dist/index-vhs88xhe.js +99 -95
- package/dist/index-vs81yaks.js +244 -0
- 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-x54nbgs7.js +355 -0
- package/dist/index-xkvd0nsd.js +187 -0
- package/dist/index-yedqxm1z.js +80 -0
- package/dist/index-yz4jfz7z.js +338 -0
- package/dist/index-zfjzzjkf.js +240 -199
- package/dist/index.d.ts +12 -8
- package/dist/index.js +56 -34
- 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 +544 -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 +55 -48
- package/readme.md +365 -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} +114 -10
- 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/quick-tunnel/cloudflared-process.ts +83 -0
- package/src/core/quick-tunnel/constants.ts +31 -0
- package/src/core/quick-tunnel/index.ts +96 -0
- package/src/core/quick-tunnel/install.ts +160 -0
- package/src/core/tunnel.ts +165 -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} +214 -141
- package/src/environment/index.ts +1 -0
- package/src/environment/logging.ts +115 -0
- package/src/environment/only-apps.ts +34 -0
- package/src/environment/seeding.ts +57 -0
- package/{index.ts → src/index.ts} +52 -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} +186 -8
- 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,228 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sleep
|
|
3
|
+
} from "./index-c0dr6mcv.js";
|
|
4
|
+
|
|
5
|
+
// src/docker/runtime.ts
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
var POLL_INTERVAL = 250;
|
|
8
|
+
var MAX_ATTEMPTS = 120;
|
|
9
|
+
var DOCKER_NOT_RUNNING_MESSAGE = "Docker is not running. Please start Docker and try again.";
|
|
10
|
+
async function isContainerRunning(project, service) {
|
|
11
|
+
try {
|
|
12
|
+
const result = execSync(`docker ps --filter "label=com.docker.compose.project=${project}" --filter "label=com.docker.compose.service=${service}" --format "{{.State}}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
13
|
+
return result.trim() === "running";
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function isDockerRunning() {
|
|
19
|
+
try {
|
|
20
|
+
execSync('docker info --format "{{.ServerVersion}}"', {
|
|
21
|
+
encoding: "utf-8",
|
|
22
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
23
|
+
});
|
|
24
|
+
return true;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function assertDockerRunning() {
|
|
30
|
+
if (!isDockerRunning()) {
|
|
31
|
+
throw new Error(DOCKER_NOT_RUNNING_MESSAGE);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function areContainersRunning(project, minCount = 1) {
|
|
35
|
+
try {
|
|
36
|
+
const result = execSync(`docker ps --filter "label=com.docker.compose.project=${project}" --format "{{.State}}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
37
|
+
const states = result.trim().split(`
|
|
38
|
+
`).filter(Boolean);
|
|
39
|
+
if (states.length < minCount)
|
|
40
|
+
return false;
|
|
41
|
+
return states.every((state) => state === "running");
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function getComposeArg(composeFile) {
|
|
47
|
+
return composeFile ? `-f "${composeFile}"` : "";
|
|
48
|
+
}
|
|
49
|
+
function startContainers(root, projectName, envVars, options = {}) {
|
|
50
|
+
const { verbose = true, wait = true, composeFile } = options;
|
|
51
|
+
assertDockerRunning();
|
|
52
|
+
if (verbose)
|
|
53
|
+
console.log("\uD83D\uDC33 Starting Docker containers...");
|
|
54
|
+
const composeArg = getComposeArg(composeFile);
|
|
55
|
+
const waitFlag = wait ? "--wait" : "";
|
|
56
|
+
const cmd = `docker compose ${composeArg} up -d ${waitFlag}`.trim();
|
|
57
|
+
execSync(cmd, {
|
|
58
|
+
cwd: root,
|
|
59
|
+
env: { ...process.env, ...envVars, COMPOSE_PROJECT_NAME: projectName },
|
|
60
|
+
stdio: verbose ? "inherit" : "ignore"
|
|
61
|
+
});
|
|
62
|
+
if (verbose)
|
|
63
|
+
console.log("✓ Containers started");
|
|
64
|
+
}
|
|
65
|
+
function stopContainers(root, projectName, options = {}) {
|
|
66
|
+
const { verbose = true, removeVolumes = false, composeFile } = options;
|
|
67
|
+
assertDockerRunning();
|
|
68
|
+
if (verbose) {
|
|
69
|
+
console.log(removeVolumes ? "\uD83D\uDDD1️ Stopping containers and removing volumes..." : "\uD83D\uDED1 Stopping containers...");
|
|
70
|
+
}
|
|
71
|
+
const composeArg = getComposeArg(composeFile);
|
|
72
|
+
const volumeFlag = removeVolumes ? "-v" : "";
|
|
73
|
+
const cmd = `docker compose ${composeArg} down ${volumeFlag}`.trim();
|
|
74
|
+
execSync(cmd, {
|
|
75
|
+
cwd: root,
|
|
76
|
+
env: { ...process.env, COMPOSE_PROJECT_NAME: projectName },
|
|
77
|
+
stdio: verbose ? "inherit" : "ignore"
|
|
78
|
+
});
|
|
79
|
+
if (verbose)
|
|
80
|
+
console.log("✓ Containers stopped");
|
|
81
|
+
}
|
|
82
|
+
function startService(root, projectName, serviceName, envVars, options = {}) {
|
|
83
|
+
const { verbose = true, composeFile } = options;
|
|
84
|
+
assertDockerRunning();
|
|
85
|
+
if (verbose)
|
|
86
|
+
console.log(`\uD83D\uDC33 Starting ${serviceName}...`);
|
|
87
|
+
const composeArg = getComposeArg(composeFile);
|
|
88
|
+
const cmd = `docker compose ${composeArg} up -d ${serviceName}`.trim();
|
|
89
|
+
execSync(cmd, {
|
|
90
|
+
cwd: root,
|
|
91
|
+
env: { ...process.env, ...envVars, COMPOSE_PROJECT_NAME: projectName },
|
|
92
|
+
stdio: verbose ? "inherit" : "ignore"
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function createBuiltInHealthCheck(type, serviceName, context = {}) {
|
|
96
|
+
const { projectName, root } = context;
|
|
97
|
+
switch (type) {
|
|
98
|
+
case "pg_isready":
|
|
99
|
+
return async () => {
|
|
100
|
+
try {
|
|
101
|
+
const projectArg = projectName ? `-p ${projectName}` : "";
|
|
102
|
+
execSync(`docker compose ${projectArg} exec -T ${serviceName} pg_isready -U postgres`, {
|
|
103
|
+
cwd: root,
|
|
104
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
105
|
+
});
|
|
106
|
+
return true;
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
case "redis-cli":
|
|
112
|
+
return async () => {
|
|
113
|
+
try {
|
|
114
|
+
const projectArg = projectName ? `-p ${projectName}` : "";
|
|
115
|
+
execSync(`docker compose ${projectArg} exec -T ${serviceName} redis-cli ping`, {
|
|
116
|
+
cwd: root,
|
|
117
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
} catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
case "http":
|
|
125
|
+
return async (port) => {
|
|
126
|
+
try {
|
|
127
|
+
const controller = new AbortController;
|
|
128
|
+
const timeoutId = setTimeout(() => controller.abort(), 2000);
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch(`http://localhost:${port}/`, {
|
|
131
|
+
signal: controller.signal
|
|
132
|
+
});
|
|
133
|
+
clearTimeout(timeoutId);
|
|
134
|
+
return response.ok || response.status === 404;
|
|
135
|
+
} catch {
|
|
136
|
+
clearTimeout(timeoutId);
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
} catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
case "tcp":
|
|
144
|
+
return async (port) => {
|
|
145
|
+
try {
|
|
146
|
+
const controller = new AbortController;
|
|
147
|
+
const timeoutId = setTimeout(() => controller.abort(), 1000);
|
|
148
|
+
try {
|
|
149
|
+
await fetch(`http://localhost:${port}/`, {
|
|
150
|
+
signal: controller.signal
|
|
151
|
+
});
|
|
152
|
+
clearTimeout(timeoutId);
|
|
153
|
+
return true;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
clearTimeout(timeoutId);
|
|
156
|
+
if (error instanceof Error && error.message.includes("ECONNREFUSED")) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
} catch {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
default:
|
|
166
|
+
return async () => true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function waitForService(serviceName, config, port, options = {}) {
|
|
170
|
+
const {
|
|
171
|
+
maxAttempts = MAX_ATTEMPTS,
|
|
172
|
+
pollInterval = POLL_INTERVAL,
|
|
173
|
+
projectName,
|
|
174
|
+
root
|
|
175
|
+
} = options;
|
|
176
|
+
if (config.healthCheck === false || config.healthCheck === undefined) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const healthCheckFn = typeof config.healthCheck === "function" ? config.healthCheck : createBuiltInHealthCheck(config.healthCheck, config.serviceName ?? serviceName, { projectName, root });
|
|
180
|
+
for (let i = 0;i < maxAttempts; i++) {
|
|
181
|
+
const isHealthy = await healthCheckFn(port);
|
|
182
|
+
if (isHealthy)
|
|
183
|
+
return;
|
|
184
|
+
await sleep(pollInterval);
|
|
185
|
+
}
|
|
186
|
+
throw new Error(`Service ${serviceName} did not become ready in time`);
|
|
187
|
+
}
|
|
188
|
+
async function waitForAllServices(services, ports, options = {}) {
|
|
189
|
+
const { verbose = true, ...waitOptions } = options;
|
|
190
|
+
if (verbose)
|
|
191
|
+
console.log("⏳ Waiting for services to be healthy...");
|
|
192
|
+
const promises = Object.entries(services).map(([name, config]) => {
|
|
193
|
+
const port = ports[name];
|
|
194
|
+
if (port === undefined) {
|
|
195
|
+
console.warn(`⚠️ No port found for service ${name}, skipping health check`);
|
|
196
|
+
return Promise.resolve();
|
|
197
|
+
}
|
|
198
|
+
return waitForService(name, config, port, waitOptions);
|
|
199
|
+
});
|
|
200
|
+
await Promise.all(promises);
|
|
201
|
+
if (verbose)
|
|
202
|
+
console.log("✓ All services healthy");
|
|
203
|
+
}
|
|
204
|
+
async function waitForServiceByType(serviceName, healthCheckType, port, options = {}) {
|
|
205
|
+
const {
|
|
206
|
+
maxAttempts = MAX_ATTEMPTS,
|
|
207
|
+
pollInterval = POLL_INTERVAL,
|
|
208
|
+
verbose = false,
|
|
209
|
+
projectName,
|
|
210
|
+
root
|
|
211
|
+
} = options;
|
|
212
|
+
const healthCheckFn = createBuiltInHealthCheck(healthCheckType, serviceName, {
|
|
213
|
+
projectName,
|
|
214
|
+
root
|
|
215
|
+
});
|
|
216
|
+
for (let i = 0;i < maxAttempts; i++) {
|
|
217
|
+
const isHealthy = await healthCheckFn(port);
|
|
218
|
+
if (isHealthy) {
|
|
219
|
+
if (verbose)
|
|
220
|
+
console.log(`✓ ${serviceName} is ready`);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
await sleep(pollInterval);
|
|
224
|
+
}
|
|
225
|
+
throw new Error(`Service ${serviceName} did not become ready in time`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export { POLL_INTERVAL, MAX_ATTEMPTS, DOCKER_NOT_RUNNING_MESSAGE, isContainerRunning, isDockerRunning, assertDockerRunning, areContainersRunning, getComposeArg, startContainers, stopContainers, startService, createBuiltInHealthCheck, waitForService, waitForAllServices, waitForServiceByType };
|
package/dist/index-d9efy0n4.js
CHANGED
|
@@ -3,176 +3,202 @@ import { execSync } from "node:child_process";
|
|
|
3
3
|
import { readFileSync, unlinkSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import fg from "fast-glob";
|
|
6
|
+
|
|
6
7
|
var DEFAULT_PATTERNS = ["apps/*", "packages/*", "modules"];
|
|
7
8
|
var DEFAULT_CONCURRENCY = 1;
|
|
8
9
|
var CORRUPTED_CACHE_PATTERNS = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
"all goroutines are asleep - deadlock",
|
|
11
|
+
"fatal error:",
|
|
12
|
+
"panic:",
|
|
13
|
+
"github.com/microsoft/typescript-go",
|
|
13
14
|
];
|
|
14
15
|
function isCorruptedCacheError(output) {
|
|
15
|
-
|
|
16
|
+
return CORRUPTED_CACHE_PATTERNS.some((pattern) => output.includes(pattern));
|
|
16
17
|
}
|
|
17
18
|
async function clearTsBuildInfo(workspace, verbose) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
19
|
+
if (verbose) {
|
|
20
|
+
console.log(
|
|
21
|
+
`\uD83E\uDDF9 Clearing corrupted tsbuildinfo cache for ${workspace}...`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const tsbuildInfoFiles = await fg(`${workspace}/**/*.tsbuildinfo`, {
|
|
26
|
+
absolute: true,
|
|
27
|
+
});
|
|
28
|
+
for (const file of tsbuildInfoFiles) {
|
|
29
|
+
try {
|
|
30
|
+
unlinkSync(file);
|
|
31
|
+
} catch {}
|
|
32
|
+
}
|
|
33
|
+
const cacheFiles = await fg(`${workspace}/**/.cache/tsbuildinfo.json`, {
|
|
34
|
+
absolute: true,
|
|
35
|
+
});
|
|
36
|
+
for (const file of cacheFiles) {
|
|
37
|
+
try {
|
|
38
|
+
unlinkSync(file);
|
|
39
|
+
} catch {}
|
|
40
|
+
}
|
|
41
|
+
} catch {}
|
|
39
42
|
}
|
|
40
43
|
async function countTypeScriptFiles(pkgPath, root) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
const files = await fg(`${pkgPath}/**/*.{ts,tsx}`, {
|
|
45
|
+
cwd: root,
|
|
46
|
+
ignore: ["**/node_modules/**"],
|
|
47
|
+
});
|
|
48
|
+
return files.length;
|
|
46
49
|
}
|
|
47
50
|
function formatErrorOutput(output) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
return output
|
|
52
|
+
.split(`
|
|
53
|
+
`)
|
|
54
|
+
.map((line) => {
|
|
55
|
+
return line
|
|
56
|
+
.replace(/\.\.\/\.\.\/packages\/modules\//g, "")
|
|
57
|
+
.replace(/\((\d+),(\d+)\):?/g, ":$1:$2 -");
|
|
58
|
+
})
|
|
59
|
+
.join(`
|
|
60
|
+
`)
|
|
61
|
+
.trim();
|
|
53
62
|
}
|
|
54
|
-
async function runSingleTypecheck(
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
63
|
+
async function runSingleTypecheck(
|
|
64
|
+
workspace,
|
|
65
|
+
fileCount,
|
|
66
|
+
root,
|
|
67
|
+
verbose,
|
|
68
|
+
isRetry = false,
|
|
69
|
+
) {
|
|
70
|
+
const startTime = performance.now();
|
|
71
|
+
if (verbose) {
|
|
72
|
+
console.log(
|
|
73
|
+
`Running typecheck in ${workspace} (${fileCount} files)${isRetry ? " (retry)" : ""}...`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
const workspacePath = join(root, workspace);
|
|
77
|
+
let success = false;
|
|
78
|
+
let stdout = "";
|
|
79
|
+
let stderr = "";
|
|
80
|
+
try {
|
|
81
|
+
const output = execSync("bun run typecheck", {
|
|
82
|
+
cwd: workspacePath,
|
|
83
|
+
encoding: "utf-8",
|
|
84
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
85
|
+
});
|
|
86
|
+
stdout = output ?? "";
|
|
87
|
+
success = true;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
const execError = error;
|
|
90
|
+
stdout = execError.stdout ?? "";
|
|
91
|
+
stderr = execError.stderr ?? "";
|
|
92
|
+
success = false;
|
|
93
|
+
}
|
|
94
|
+
const duration = Number(((performance.now() - startTime) / 1000).toFixed(2));
|
|
95
|
+
let errorOutput;
|
|
96
|
+
if (!success) {
|
|
97
|
+
const parts = [stdout.trim(), stderr.trim()].filter(Boolean);
|
|
98
|
+
errorOutput =
|
|
99
|
+
parts.length > 0
|
|
100
|
+
? parts.join(`
|
|
101
|
+
`)
|
|
102
|
+
: undefined;
|
|
103
|
+
if (!isRetry && errorOutput && isCorruptedCacheError(errorOutput)) {
|
|
104
|
+
await clearTsBuildInfo(workspacePath, verbose);
|
|
105
|
+
return runSingleTypecheck(workspace, fileCount, root, verbose, true);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { workspace, duration, success, fileCount, errorOutput };
|
|
89
109
|
}
|
|
90
110
|
async function discoverWorkspaces(patterns, root) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
const workspaces = [];
|
|
112
|
+
for (const pattern of patterns) {
|
|
113
|
+
const matches = await fg(`${pattern}/package.json`, { cwd: root });
|
|
114
|
+
for (const match of matches) {
|
|
115
|
+
const pkgPath = match.replace("/package.json", "");
|
|
116
|
+
try {
|
|
117
|
+
const pkgJsonContent = readFileSync(join(root, match), "utf-8");
|
|
118
|
+
const pkgJson = JSON.parse(pkgJsonContent);
|
|
119
|
+
if (pkgJson.scripts?.typecheck) {
|
|
120
|
+
const fileCount = await countTypeScriptFiles(pkgPath, root);
|
|
121
|
+
workspaces.push({ path: pkgPath, fileCount });
|
|
122
|
+
}
|
|
123
|
+
} catch {}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
workspaces.sort((a, b) => a.fileCount - b.fileCount);
|
|
127
|
+
return workspaces;
|
|
108
128
|
}
|
|
109
129
|
async function runWorkspaceTypecheck(options = {}) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
const {
|
|
131
|
+
root = process.cwd(),
|
|
132
|
+
patterns = DEFAULT_PATTERNS,
|
|
133
|
+
concurrency = DEFAULT_CONCURRENCY,
|
|
134
|
+
verbose = true,
|
|
135
|
+
} = options;
|
|
136
|
+
const workspaces = await discoverWorkspaces(patterns, root);
|
|
137
|
+
if (workspaces.length === 0) {
|
|
138
|
+
if (verbose) {
|
|
139
|
+
console.log("No workspaces with typecheck script found.");
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
success: true,
|
|
143
|
+
totalDuration: 0,
|
|
144
|
+
totalFiles: 0,
|
|
145
|
+
workspaceCount: 0,
|
|
146
|
+
results: [],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const totalStartTime = performance.now();
|
|
150
|
+
if (verbose) {
|
|
151
|
+
console.log(`Running typecheck across ${workspaces.length} workspaces with concurrency limit of ${concurrency}...
|
|
132
152
|
`);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
}
|
|
154
|
+
const results = [];
|
|
155
|
+
const running = new Set();
|
|
156
|
+
for (let i = 0; i < workspaces.length; i++) {
|
|
157
|
+
const { path, fileCount } = workspaces[i];
|
|
158
|
+
const promise = runSingleTypecheck(path, fileCount, root, verbose).then(
|
|
159
|
+
(result) => {
|
|
160
|
+
results[i] = result;
|
|
161
|
+
running.delete(promise);
|
|
162
|
+
if (verbose) {
|
|
163
|
+
const icon = result.success ? "✅" : "❌";
|
|
164
|
+
const log = result.success ? console.log : console.error;
|
|
165
|
+
log(
|
|
166
|
+
`${icon} ${result.workspace} (${result.fileCount} files) ${result.success ? "completed" : "failed"} in ${result.duration.toFixed(2)}s`,
|
|
167
|
+
);
|
|
168
|
+
if (!result.success && result.errorOutput) {
|
|
169
|
+
console.error(`
|
|
147
170
|
${formatErrorOutput(result.errorOutput)}`);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
running.add(promise);
|
|
176
|
+
if (running.size >= concurrency) {
|
|
177
|
+
await Promise.race(running);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
await Promise.all(running);
|
|
181
|
+
const totalDuration = Number(
|
|
182
|
+
((performance.now() - totalStartTime) / 1000).toFixed(2),
|
|
183
|
+
);
|
|
184
|
+
const totalFiles = workspaces.reduce((sum, w) => sum + w.fileCount, 0);
|
|
185
|
+
const success = results.every((r) => r.success);
|
|
186
|
+
if (verbose) {
|
|
187
|
+
if (success) {
|
|
188
|
+
console.log(`
|
|
163
189
|
All typecheck checks passed! Total time: ${totalDuration}s (${totalFiles} files)`);
|
|
164
|
-
|
|
165
|
-
|
|
190
|
+
} else {
|
|
191
|
+
console.error(`
|
|
166
192
|
Typecheck failed. Total time: ${totalDuration}s`);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
success,
|
|
197
|
+
totalDuration,
|
|
198
|
+
totalFiles,
|
|
199
|
+
workspaceCount: workspaces.length,
|
|
200
|
+
results,
|
|
201
|
+
};
|
|
176
202
|
}
|
|
177
203
|
|
|
178
204
|
export { runWorkspaceTypecheck };
|