@getmonoceros/workbench 1.18.0 → 1.19.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.js +190 -54
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1903,6 +1903,41 @@ function curatedServiceEnvDefaults(name) {
|
|
|
1903
1903
|
const def = SERVICE_CATALOG[name];
|
|
1904
1904
|
return def?.env ? { ...def.env } : {};
|
|
1905
1905
|
}
|
|
1906
|
+
function serviceConnectionEnv(services) {
|
|
1907
|
+
const env = {};
|
|
1908
|
+
for (const svc of services) {
|
|
1909
|
+
if (!isCuratedService(svc.name)) continue;
|
|
1910
|
+
const host = svc.name;
|
|
1911
|
+
if (svc.name === "postgres") {
|
|
1912
|
+
const user = svc.env.POSTGRES_USER ?? "postgres";
|
|
1913
|
+
const pass = svc.env.POSTGRES_PASSWORD ?? "";
|
|
1914
|
+
const db = svc.env.POSTGRES_DB ?? user;
|
|
1915
|
+
const port = svc.port ?? 5432;
|
|
1916
|
+
env.PGHOST = host;
|
|
1917
|
+
env.PGPORT = String(port);
|
|
1918
|
+
env.PGUSER = user;
|
|
1919
|
+
env.PGPASSWORD = pass;
|
|
1920
|
+
env.PGDATABASE = db;
|
|
1921
|
+
env.DATABASE_URL = `postgresql://${user}:${pass}@${host}:${port}/${db}`;
|
|
1922
|
+
} else if (svc.name === "mysql") {
|
|
1923
|
+
const pass = svc.env.MYSQL_ROOT_PASSWORD ?? "";
|
|
1924
|
+
const db = svc.env.MYSQL_DATABASE ?? "";
|
|
1925
|
+
const port = svc.port ?? 3306;
|
|
1926
|
+
env.MYSQL_HOST = host;
|
|
1927
|
+
env.MYSQL_PORT = String(port);
|
|
1928
|
+
env.MYSQL_USER = "root";
|
|
1929
|
+
env.MYSQL_PASSWORD = pass;
|
|
1930
|
+
env.MYSQL_DATABASE = db;
|
|
1931
|
+
if (env.DATABASE_URL === void 0) {
|
|
1932
|
+
env.DATABASE_URL = `mysql://root:${pass}@${host}:${port}/${db}`;
|
|
1933
|
+
}
|
|
1934
|
+
} else if (svc.name === "redis") {
|
|
1935
|
+
const port = svc.port ?? 6379;
|
|
1936
|
+
env.REDIS_URL = `redis://${host}:${port}`;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
return env;
|
|
1940
|
+
}
|
|
1906
1941
|
function deriveServiceName(image) {
|
|
1907
1942
|
const lastSegment = image.split("/").pop() ?? image;
|
|
1908
1943
|
const noTag = lastSegment.split("@")[0].split(":")[0];
|
|
@@ -2438,6 +2473,14 @@ function buildComposeYaml(opts, dockerMode = "rootful") {
|
|
|
2438
2473
|
for (const v of ideVolumes) {
|
|
2439
2474
|
lines.push(` - ${v.volume}:${v.target}`);
|
|
2440
2475
|
}
|
|
2476
|
+
const wsEnv = serviceConnectionEnv(opts.services);
|
|
2477
|
+
const wsEnvKeys = Object.keys(wsEnv);
|
|
2478
|
+
if (wsEnvKeys.length > 0) {
|
|
2479
|
+
lines.push(" environment:");
|
|
2480
|
+
for (const k of wsEnvKeys) {
|
|
2481
|
+
lines.push(` ${k}: ${composeScalar(wsEnv[k])}`);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2441
2484
|
for (const svc of opts.services) {
|
|
2442
2485
|
lines.push(` ${svc.name}:`);
|
|
2443
2486
|
lines.push(` image: ${svc.image}`);
|
|
@@ -3216,8 +3259,8 @@ function removeRepoFromDoc(doc, urlOrPath) {
|
|
|
3216
3259
|
if (!isMap2(item)) return false;
|
|
3217
3260
|
const url = item.get("url");
|
|
3218
3261
|
if (url === urlOrPath) return true;
|
|
3219
|
-
const
|
|
3220
|
-
const effectivePath = typeof
|
|
3262
|
+
const path24 = item.get("path");
|
|
3263
|
+
const effectivePath = typeof path24 === "string" ? path24 : typeof url === "string" ? deriveRepoName(url) : void 0;
|
|
3221
3264
|
return effectivePath === urlOrPath;
|
|
3222
3265
|
});
|
|
3223
3266
|
if (idx < 0) return false;
|
|
@@ -3329,7 +3372,7 @@ async function runAddRepo(input) {
|
|
|
3329
3372
|
"Missing repo URL. Usage: monoceros add-repo <containername> <url>."
|
|
3330
3373
|
);
|
|
3331
3374
|
}
|
|
3332
|
-
const
|
|
3375
|
+
const path24 = (input.path ?? deriveRepoName(url)).trim();
|
|
3333
3376
|
const hasName = typeof input.gitName === "string" && input.gitName.trim().length > 0;
|
|
3334
3377
|
const hasEmail = typeof input.gitEmail === "string" && input.gitEmail.trim().length > 0;
|
|
3335
3378
|
if (hasName !== hasEmail) {
|
|
@@ -3366,7 +3409,7 @@ async function runAddRepo(input) {
|
|
|
3366
3409
|
const providerToWrite = !canonical && explicitProvider ? explicitProvider : void 0;
|
|
3367
3410
|
const entry2 = {
|
|
3368
3411
|
url,
|
|
3369
|
-
path:
|
|
3412
|
+
path: path24,
|
|
3370
3413
|
...hasName && hasEmail ? {
|
|
3371
3414
|
gitUser: {
|
|
3372
3415
|
name: input.gitName.trim(),
|
|
@@ -4767,22 +4810,42 @@ function generateAgentsMd(input) {
|
|
|
4767
4810
|
lines.push(formatServiceLine(svc));
|
|
4768
4811
|
}
|
|
4769
4812
|
lines.push("");
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4813
|
+
const connEnv = serviceConnectionEnv(input.services);
|
|
4814
|
+
if (Object.keys(connEnv).length > 0) {
|
|
4815
|
+
lines.push(
|
|
4816
|
+
"Connection details for the curated services above are already set as",
|
|
4817
|
+
"environment variables in this container. Read them from the",
|
|
4818
|
+
"environment \u2014 do not ask the user for credentials, and do not",
|
|
4819
|
+
"hardcode them:"
|
|
4820
|
+
);
|
|
4821
|
+
lines.push("");
|
|
4822
|
+
if (connEnv.DATABASE_URL !== void 0) {
|
|
4823
|
+
lines.push(
|
|
4824
|
+
"- `DATABASE_URL` \u2014 the SQL database. Engine-specific variables are",
|
|
4825
|
+
" set too (`PGHOST`/`PGPORT`/`PGUSER`/`PGPASSWORD`/`PGDATABASE` for",
|
|
4826
|
+
" Postgres, `MYSQL_*` for MySQL)."
|
|
4827
|
+
);
|
|
4828
|
+
}
|
|
4829
|
+
if (connEnv.REDIS_URL !== void 0) {
|
|
4830
|
+
lines.push("- `REDIS_URL` \u2014 Redis.");
|
|
4831
|
+
}
|
|
4832
|
+
lines.push("");
|
|
4833
|
+
lines.push(
|
|
4834
|
+
"These are dev-only defaults for the local container, fine to use",
|
|
4835
|
+
"directly. Prefer reading the variable (e.g. `process.env.DATABASE_URL`)",
|
|
4836
|
+
"over copying its value into code."
|
|
4837
|
+
);
|
|
4838
|
+
}
|
|
4778
4839
|
const hasCustom = input.services.some((s) => !isCuratedService(s.name));
|
|
4779
4840
|
if (hasCustom) {
|
|
4780
4841
|
lines.push("");
|
|
4781
4842
|
lines.push(
|
|
4782
4843
|
"For custom-image services, Monoceros does not know the service's",
|
|
4783
|
-
"configuration (env vars, ports beyond the primary one,
|
|
4784
|
-
"volumes). Treat such a service as a black box reachable at
|
|
4785
|
-
"listed address; if you need
|
|
4844
|
+
"configuration or credentials (env vars, ports beyond the primary one,",
|
|
4845
|
+
"required volumes). Treat such a service as a black box reachable at",
|
|
4846
|
+
"the listed address; if you need to connect, ask the user in the",
|
|
4847
|
+
"current chat. Do not commit credentials into the repo \u2014 they belong",
|
|
4848
|
+
"in the user's `.env` on the host."
|
|
4786
4849
|
);
|
|
4787
4850
|
}
|
|
4788
4851
|
lines.push("");
|
|
@@ -4866,6 +4929,54 @@ function generateAgentsMd(input) {
|
|
|
4866
4929
|
" DataGrip) to one of the services."
|
|
4867
4930
|
);
|
|
4868
4931
|
lines.push("");
|
|
4932
|
+
if (input.ports.length > 0) {
|
|
4933
|
+
lines.push("## Running a long-running server");
|
|
4934
|
+
lines.push("");
|
|
4935
|
+
lines.push(
|
|
4936
|
+
"When you build something that serves on a port (a web app, an API),",
|
|
4937
|
+
"start it as a **detached** background process so it keeps running after",
|
|
4938
|
+
"this session ends. A plain `npm start` (or any foreground start) dies",
|
|
4939
|
+
"the moment the user exits you or closes the terminal \u2014 and then",
|
|
4940
|
+
`\`${input.containerName}.localhost\` returns 502 Bad Gateway.`
|
|
4941
|
+
);
|
|
4942
|
+
lines.push("");
|
|
4943
|
+
lines.push(
|
|
4944
|
+
"Launch it in a new session with `setsid`, using the project's own",
|
|
4945
|
+
"start command, and record the process-group PID + log under the",
|
|
4946
|
+
"container's logs directory:"
|
|
4947
|
+
);
|
|
4948
|
+
lines.push("");
|
|
4949
|
+
lines.push("```");
|
|
4950
|
+
lines.push(
|
|
4951
|
+
`setsid sh -c 'echo $$ >/workspaces/${input.containerName}/logs/<app>.pid; \\`
|
|
4952
|
+
);
|
|
4953
|
+
lines.push(
|
|
4954
|
+
` exec <the project's start command> >/workspaces/${input.containerName}/logs/<app>.log 2>&1' </dev/null &`
|
|
4955
|
+
);
|
|
4956
|
+
lines.push("```");
|
|
4957
|
+
lines.push("");
|
|
4958
|
+
lines.push(
|
|
4959
|
+
"Use whatever start command the project actually uses (`npm start`,",
|
|
4960
|
+
"`./mvnw spring-boot:run`, `python app.py`, `go run .`, \u2026) \u2014 do not force",
|
|
4961
|
+
"a language-specific one. `<app>` is a short name you choose."
|
|
4962
|
+
);
|
|
4963
|
+
lines.push("");
|
|
4964
|
+
lines.push("To stop it, kill the whole process group (also stops children");
|
|
4965
|
+
lines.push("like node under npm or java under maven):");
|
|
4966
|
+
lines.push("");
|
|
4967
|
+
lines.push("```");
|
|
4968
|
+
lines.push(
|
|
4969
|
+
`kill -TERM -$(cat /workspaces/${input.containerName}/logs/<app>.pid)`
|
|
4970
|
+
);
|
|
4971
|
+
lines.push("```");
|
|
4972
|
+
lines.push("");
|
|
4973
|
+
lines.push(
|
|
4974
|
+
`The user can follow the output with \`monoceros logs ${input.containerName} <app>\``,
|
|
4975
|
+
"on the host. The server must listen on `0.0.0.0` (not `127.0.0.1`) on",
|
|
4976
|
+
"the exposed port, or Traefik cannot reach it."
|
|
4977
|
+
);
|
|
4978
|
+
lines.push("");
|
|
4979
|
+
}
|
|
4869
4980
|
lines.push("## Command reference");
|
|
4870
4981
|
lines.push("");
|
|
4871
4982
|
lines.push(
|
|
@@ -5373,10 +5484,12 @@ var init_cli = __esm({
|
|
|
5373
5484
|
cachedBinaryPath = null;
|
|
5374
5485
|
spawnDevcontainer = (args, cwd, options = {}) => {
|
|
5375
5486
|
const binPath = devcontainerCliPath();
|
|
5487
|
+
const env = { ...process.env, DOCKER_CLI_HINTS: "false" };
|
|
5376
5488
|
return new Promise((resolve, reject) => {
|
|
5377
5489
|
if (options.interactive) {
|
|
5378
5490
|
const child2 = spawn4(process.execPath, [binPath, ...args], {
|
|
5379
5491
|
cwd,
|
|
5492
|
+
env,
|
|
5380
5493
|
stdio: "inherit"
|
|
5381
5494
|
});
|
|
5382
5495
|
child2.on("error", reject);
|
|
@@ -5385,6 +5498,7 @@ var init_cli = __esm({
|
|
|
5385
5498
|
}
|
|
5386
5499
|
const child = spawn4(process.execPath, [binPath, ...args], {
|
|
5387
5500
|
cwd,
|
|
5501
|
+
env,
|
|
5388
5502
|
stdio: ["ignore", "pipe", "pipe"]
|
|
5389
5503
|
});
|
|
5390
5504
|
if (options.quiet) {
|
|
@@ -6293,7 +6407,7 @@ var CLI_VERSION;
|
|
|
6293
6407
|
var init_version = __esm({
|
|
6294
6408
|
"src/version.ts"() {
|
|
6295
6409
|
"use strict";
|
|
6296
|
-
CLI_VERSION = true ? "1.
|
|
6410
|
+
CLI_VERSION = true ? "1.19.0" : "dev";
|
|
6297
6411
|
}
|
|
6298
6412
|
});
|
|
6299
6413
|
|
|
@@ -7992,7 +8106,11 @@ exit 0
|
|
|
7992
8106
|
"-lc",
|
|
7993
8107
|
`export PATH="/workspaces/${name}/${RELAY_DIRNAME}:$PATH"; exec claude`
|
|
7994
8108
|
],
|
|
7995
|
-
{
|
|
8109
|
+
{
|
|
8110
|
+
cwd: root,
|
|
8111
|
+
env: { ...process.env, DOCKER_CLI_HINTS: "false" },
|
|
8112
|
+
stdio: "inherit"
|
|
8113
|
+
}
|
|
7996
8114
|
);
|
|
7997
8115
|
const code = await new Promise((resolve) => {
|
|
7998
8116
|
child.on("error", () => resolve(1));
|
|
@@ -8064,7 +8182,18 @@ var init_login2 = __esm({
|
|
|
8064
8182
|
});
|
|
8065
8183
|
|
|
8066
8184
|
// src/commands/logs.ts
|
|
8185
|
+
import { spawn as spawn9 } from "child_process";
|
|
8186
|
+
import { existsSync as existsSync12 } from "fs";
|
|
8187
|
+
import path20 from "path";
|
|
8067
8188
|
import { defineCommand as defineCommand14 } from "citty";
|
|
8189
|
+
function tailLogFile(file, follow) {
|
|
8190
|
+
const [cmd, args] = follow ? ["tail", ["-F", file]] : ["cat", [file]];
|
|
8191
|
+
return new Promise((resolve, reject) => {
|
|
8192
|
+
const child = spawn9(cmd, args, { stdio: "inherit" });
|
|
8193
|
+
child.on("error", reject);
|
|
8194
|
+
child.on("exit", (code) => resolve(code ?? 0));
|
|
8195
|
+
});
|
|
8196
|
+
}
|
|
8068
8197
|
var logsCommand;
|
|
8069
8198
|
var init_logs = __esm({
|
|
8070
8199
|
"src/commands/logs.ts"() {
|
|
@@ -8076,7 +8205,7 @@ var init_logs = __esm({
|
|
|
8076
8205
|
meta: {
|
|
8077
8206
|
name: "logs",
|
|
8078
8207
|
group: "run",
|
|
8079
|
-
description: "Tail logs from
|
|
8208
|
+
description: "Tail logs from a compose service of the named dev-container, or from a long-running app started inside it (logs/<app>.log). Pass --no-follow for a one-shot dump."
|
|
8080
8209
|
},
|
|
8081
8210
|
args: {
|
|
8082
8211
|
name: {
|
|
@@ -8086,7 +8215,7 @@ var init_logs = __esm({
|
|
|
8086
8215
|
},
|
|
8087
8216
|
service: {
|
|
8088
8217
|
type: "string",
|
|
8089
|
-
description: "
|
|
8218
|
+
description: "A compose service (e.g. postgres) or an app whose log is at logs/<service>.log. Defaults to all compose services."
|
|
8090
8219
|
},
|
|
8091
8220
|
follow: {
|
|
8092
8221
|
type: "boolean",
|
|
@@ -8096,10 +8225,17 @@ var init_logs = __esm({
|
|
|
8096
8225
|
}
|
|
8097
8226
|
},
|
|
8098
8227
|
run({ args }) {
|
|
8228
|
+
const service = typeof args.service === "string" ? args.service : void 0;
|
|
8229
|
+
if (service) {
|
|
8230
|
+
const logFile = path20.join(containerLogsDir(args.name), `${service}.log`);
|
|
8231
|
+
if (existsSync12(logFile)) {
|
|
8232
|
+
return dispatch(() => tailLogFile(logFile, args.follow));
|
|
8233
|
+
}
|
|
8234
|
+
}
|
|
8099
8235
|
return dispatch(
|
|
8100
8236
|
() => runLogs({
|
|
8101
8237
|
root: containerDir(args.name),
|
|
8102
|
-
...
|
|
8238
|
+
...service ? { service } : {},
|
|
8103
8239
|
follow: args.follow
|
|
8104
8240
|
})
|
|
8105
8241
|
);
|
|
@@ -8299,8 +8435,8 @@ var init_remove_feature = __esm({
|
|
|
8299
8435
|
});
|
|
8300
8436
|
|
|
8301
8437
|
// src/remove/index.ts
|
|
8302
|
-
import { existsSync as
|
|
8303
|
-
import
|
|
8438
|
+
import { existsSync as existsSync13, promises as fs15 } from "fs";
|
|
8439
|
+
import path21 from "path";
|
|
8304
8440
|
import { consola as consola21 } from "consola";
|
|
8305
8441
|
async function runRemove(opts) {
|
|
8306
8442
|
const home = opts.monocerosHome ?? monocerosHome();
|
|
@@ -8317,9 +8453,9 @@ async function runRemove(opts) {
|
|
|
8317
8453
|
const ymlPath = containerConfigPath(opts.name, home);
|
|
8318
8454
|
const envPath = containerEnvPath(opts.name, home);
|
|
8319
8455
|
const containerPath = containerDir(opts.name, home);
|
|
8320
|
-
const hasYml =
|
|
8321
|
-
const hasEnv =
|
|
8322
|
-
const hasContainer =
|
|
8456
|
+
const hasYml = existsSync13(ymlPath);
|
|
8457
|
+
const hasEnv = existsSync13(envPath);
|
|
8458
|
+
const hasContainer = existsSync13(containerPath);
|
|
8323
8459
|
if (!hasYml && !hasContainer) {
|
|
8324
8460
|
throw new Error(
|
|
8325
8461
|
`Nothing to remove for '${opts.name}': neither ${ymlPath} nor ${containerPath} exists.`
|
|
@@ -8345,16 +8481,16 @@ async function runRemove(opts) {
|
|
|
8345
8481
|
let backupPath = null;
|
|
8346
8482
|
if (!opts.noBackup && (hasYml || hasContainer)) {
|
|
8347
8483
|
const ts = (opts.now ?? /* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8348
|
-
backupPath =
|
|
8484
|
+
backupPath = path21.join(home, "container-backups", `${opts.name}-${ts}`);
|
|
8349
8485
|
await fs15.mkdir(backupPath, { recursive: true });
|
|
8350
8486
|
if (hasYml) {
|
|
8351
|
-
await fs15.copyFile(ymlPath,
|
|
8487
|
+
await fs15.copyFile(ymlPath, path21.join(backupPath, `${opts.name}.yml`));
|
|
8352
8488
|
}
|
|
8353
8489
|
if (hasEnv) {
|
|
8354
|
-
await fs15.copyFile(envPath,
|
|
8490
|
+
await fs15.copyFile(envPath, path21.join(backupPath, `${opts.name}.env`));
|
|
8355
8491
|
}
|
|
8356
8492
|
if (hasContainer) {
|
|
8357
|
-
await fs15.cp(containerPath,
|
|
8493
|
+
await fs15.cp(containerPath, path21.join(backupPath, "container"), {
|
|
8358
8494
|
recursive: true
|
|
8359
8495
|
});
|
|
8360
8496
|
}
|
|
@@ -8514,8 +8650,8 @@ var init_remove2 = __esm({
|
|
|
8514
8650
|
});
|
|
8515
8651
|
|
|
8516
8652
|
// src/restore/index.ts
|
|
8517
|
-
import { existsSync as
|
|
8518
|
-
import
|
|
8653
|
+
import { existsSync as existsSync14, promises as fs16 } from "fs";
|
|
8654
|
+
import path22 from "path";
|
|
8519
8655
|
import { consola as consola23 } from "consola";
|
|
8520
8656
|
async function runRestore(opts) {
|
|
8521
8657
|
const home = opts.monocerosHome ?? monocerosHome();
|
|
@@ -8523,8 +8659,8 @@ async function runRestore(opts) {
|
|
|
8523
8659
|
info: (msg) => consola23.info(msg),
|
|
8524
8660
|
success: (msg) => consola23.success(msg)
|
|
8525
8661
|
};
|
|
8526
|
-
const backup =
|
|
8527
|
-
if (!
|
|
8662
|
+
const backup = path22.resolve(opts.backupPath);
|
|
8663
|
+
if (!existsSync14(backup)) {
|
|
8528
8664
|
throw new Error(`Backup not found: ${backup}.`);
|
|
8529
8665
|
}
|
|
8530
8666
|
const stat = await fs16.stat(backup);
|
|
@@ -8545,24 +8681,24 @@ async function runRestore(opts) {
|
|
|
8545
8681
|
}
|
|
8546
8682
|
const ymlFile = ymlFiles[0];
|
|
8547
8683
|
const name = ymlFile.replace(/\.yml$/, "");
|
|
8548
|
-
const containerInBackup =
|
|
8549
|
-
const hasContainer =
|
|
8550
|
-
const envInBackup =
|
|
8551
|
-
const hasEnv =
|
|
8684
|
+
const containerInBackup = path22.join(backup, "container");
|
|
8685
|
+
const hasContainer = existsSync14(containerInBackup);
|
|
8686
|
+
const envInBackup = path22.join(backup, `${name}.env`);
|
|
8687
|
+
const hasEnv = existsSync14(envInBackup);
|
|
8552
8688
|
const destYml = containerConfigPath(name, home);
|
|
8553
8689
|
const destContainer = containerDir(name, home);
|
|
8554
|
-
if (
|
|
8690
|
+
if (existsSync14(destYml)) {
|
|
8555
8691
|
throw new Error(
|
|
8556
8692
|
`Refusing to restore: ${destYml} already exists. Remove the current container first (\`monoceros remove ${name}\`) or rename the existing config.`
|
|
8557
8693
|
);
|
|
8558
8694
|
}
|
|
8559
|
-
if (hasContainer &&
|
|
8695
|
+
if (hasContainer && existsSync14(destContainer)) {
|
|
8560
8696
|
throw new Error(
|
|
8561
8697
|
`Refusing to restore: ${destContainer} already exists. Remove the current container first (\`monoceros remove ${name}\`).`
|
|
8562
8698
|
);
|
|
8563
8699
|
}
|
|
8564
8700
|
await fs16.mkdir(containerConfigsDir(home), { recursive: true });
|
|
8565
|
-
await fs16.copyFile(
|
|
8701
|
+
await fs16.copyFile(path22.join(backup, ymlFile), destYml);
|
|
8566
8702
|
if (hasEnv) {
|
|
8567
8703
|
await fs16.copyFile(envInBackup, containerEnvPath(name, home));
|
|
8568
8704
|
}
|
|
@@ -9143,11 +9279,11 @@ var init_stop = __esm({
|
|
|
9143
9279
|
});
|
|
9144
9280
|
|
|
9145
9281
|
// src/tunnel/resolve.ts
|
|
9146
|
-
import { existsSync as
|
|
9147
|
-
import
|
|
9282
|
+
import { existsSync as existsSync15 } from "fs";
|
|
9283
|
+
import path23 from "path";
|
|
9148
9284
|
async function resolveTunnelTarget(opts) {
|
|
9149
9285
|
const ymlPath = containerConfigPath(opts.name, opts.monocerosHome);
|
|
9150
|
-
if (!
|
|
9286
|
+
if (!existsSync15(ymlPath)) {
|
|
9151
9287
|
throw new Error(
|
|
9152
9288
|
`No yml profile for '${opts.name}' at ${ymlPath}. Run \`monoceros init ${opts.name}\` first.`
|
|
9153
9289
|
);
|
|
@@ -9155,13 +9291,13 @@ async function resolveTunnelTarget(opts) {
|
|
|
9155
9291
|
const parsed = await readConfig(ymlPath);
|
|
9156
9292
|
const config = parsed.config;
|
|
9157
9293
|
const containerRoot = containerDir(opts.name, opts.monocerosHome);
|
|
9158
|
-
if (!
|
|
9294
|
+
if (!existsSync15(containerRoot)) {
|
|
9159
9295
|
throw new Error(
|
|
9160
9296
|
`Container '${opts.name}' is not materialised at ${containerRoot}. Run \`monoceros apply ${opts.name}\` first.`
|
|
9161
9297
|
);
|
|
9162
9298
|
}
|
|
9163
|
-
const composePath =
|
|
9164
|
-
const isCompose =
|
|
9299
|
+
const composePath = path23.join(containerRoot, ".devcontainer", "compose.yaml");
|
|
9300
|
+
const isCompose = existsSync15(composePath);
|
|
9165
9301
|
const parsedTarget = parseTargetArg(opts.target, config);
|
|
9166
9302
|
const docker = opts.docker ?? defaultDockerExec;
|
|
9167
9303
|
if (isCompose) {
|
|
@@ -9396,7 +9532,7 @@ var init_port_check2 = __esm({
|
|
|
9396
9532
|
});
|
|
9397
9533
|
|
|
9398
9534
|
// src/tunnel/run.ts
|
|
9399
|
-
import { spawn as
|
|
9535
|
+
import { spawn as spawn10 } from "child_process";
|
|
9400
9536
|
import { consola as consola34 } from "consola";
|
|
9401
9537
|
function signalNumber(signal) {
|
|
9402
9538
|
switch (signal) {
|
|
@@ -9486,7 +9622,7 @@ var init_run3 = __esm({
|
|
|
9486
9622
|
init_port_check2();
|
|
9487
9623
|
SOCAT_IMAGE = "alpine/socat:1.8.0.3";
|
|
9488
9624
|
defaultDockerSpawn = (args) => {
|
|
9489
|
-
const child =
|
|
9625
|
+
const child = spawn10("docker", args, {
|
|
9490
9626
|
stdio: "inherit"
|
|
9491
9627
|
});
|
|
9492
9628
|
const exited = new Promise((resolve, reject) => {
|
|
@@ -9580,7 +9716,7 @@ var init_tunnel = __esm({
|
|
|
9580
9716
|
});
|
|
9581
9717
|
|
|
9582
9718
|
// src/upgrade/index.ts
|
|
9583
|
-
import { existsSync as
|
|
9719
|
+
import { existsSync as existsSync16, promises as fs17 } from "fs";
|
|
9584
9720
|
import { consola as consola36 } from "consola";
|
|
9585
9721
|
async function fetchRuntimeVersions() {
|
|
9586
9722
|
const tokenUrl = `https://ghcr.io/token?service=ghcr.io&scope=repository:${RUNTIME_REPO}:pull`;
|
|
@@ -9639,7 +9775,7 @@ async function runUpgrade(opts) {
|
|
|
9639
9775
|
);
|
|
9640
9776
|
}
|
|
9641
9777
|
const ymlPath = containerConfigPath(opts.name, home);
|
|
9642
|
-
if (!
|
|
9778
|
+
if (!existsSync16(ymlPath)) {
|
|
9643
9779
|
throw new Error(
|
|
9644
9780
|
`No such config: ${ymlPath}. Run \`monoceros init <template> ${opts.name}\` first.`
|
|
9645
9781
|
);
|
|
@@ -10071,25 +10207,25 @@ function detectHelpRequest(argv, main2) {
|
|
|
10071
10207
|
const separatorIdx = argv.indexOf("--");
|
|
10072
10208
|
if (helpIdx === -1) return null;
|
|
10073
10209
|
if (separatorIdx !== -1 && separatorIdx < helpIdx) return null;
|
|
10074
|
-
const
|
|
10210
|
+
const path24 = [];
|
|
10075
10211
|
const tokens = argv.slice(
|
|
10076
10212
|
0,
|
|
10077
10213
|
separatorIdx === -1 ? argv.length : separatorIdx
|
|
10078
10214
|
);
|
|
10079
10215
|
let cursor = main2;
|
|
10080
10216
|
const mainName = (main2.meta ?? {}).name ?? "monoceros";
|
|
10081
|
-
|
|
10217
|
+
path24.push(mainName);
|
|
10082
10218
|
for (const tok of tokens) {
|
|
10083
10219
|
if (tok.startsWith("-")) continue;
|
|
10084
10220
|
const subs = cursor.subCommands ?? {};
|
|
10085
10221
|
if (tok in subs) {
|
|
10086
10222
|
cursor = subs[tok];
|
|
10087
|
-
|
|
10223
|
+
path24.push(tok);
|
|
10088
10224
|
continue;
|
|
10089
10225
|
}
|
|
10090
10226
|
break;
|
|
10091
10227
|
}
|
|
10092
|
-
return { path:
|
|
10228
|
+
return { path: path24, cmd: cursor };
|
|
10093
10229
|
}
|
|
10094
10230
|
async function maybeRenderHelp(argv, main2) {
|
|
10095
10231
|
const hit = detectHelpRequest(argv, main2);
|