@getmonoceros/workbench 1.39.1 → 1.39.3
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 +111 -11
- package/dist/bin.js.map +1 -1
- package/dist/catalog.json +410 -0
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -9138,7 +9138,7 @@ var CLI_VERSION;
|
|
|
9138
9138
|
var init_version = __esm({
|
|
9139
9139
|
"src/version.ts"() {
|
|
9140
9140
|
"use strict";
|
|
9141
|
-
CLI_VERSION = true ? "1.39.
|
|
9141
|
+
CLI_VERSION = true ? "1.39.3" : "dev";
|
|
9142
9142
|
}
|
|
9143
9143
|
});
|
|
9144
9144
|
|
|
@@ -9898,7 +9898,8 @@ var init_resolve = __esm({
|
|
|
9898
9898
|
}
|
|
9899
9899
|
},
|
|
9900
9900
|
share: {
|
|
9901
|
-
positionals: [containerName, appCandidates]
|
|
9901
|
+
positionals: [containerName, appCandidates],
|
|
9902
|
+
flags: { "--forward-ports": { type: "value" } }
|
|
9902
9903
|
},
|
|
9903
9904
|
completion: {
|
|
9904
9905
|
positionals: [shellValues]
|
|
@@ -13031,8 +13032,8 @@ function renderCaddyfile(sites, certFile, keyFile) {
|
|
|
13031
13032
|
}
|
|
13032
13033
|
function buildCaddyDockerArgs(input) {
|
|
13033
13034
|
const args = ["run", "--rm", "-i", `--network=${input.network}`];
|
|
13034
|
-
for (const
|
|
13035
|
-
args.push("-p", `${input.localAddress}:${
|
|
13035
|
+
for (const { host, container } of input.ports) {
|
|
13036
|
+
args.push("-p", `${input.localAddress}:${host}:${container}`);
|
|
13036
13037
|
}
|
|
13037
13038
|
args.push(
|
|
13038
13039
|
"-v",
|
|
@@ -13057,6 +13058,31 @@ import { spawn as spawn14, spawnSync as spawnSync2 } from "child_process";
|
|
|
13057
13058
|
import { consola as consola35 } from "consola";
|
|
13058
13059
|
import { promises as fs22 } from "fs";
|
|
13059
13060
|
import path34 from "path";
|
|
13061
|
+
function parseForwardPorts(raw) {
|
|
13062
|
+
const out = [];
|
|
13063
|
+
for (const entry2 of raw.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
13064
|
+
const m = /^(\d+):(\d+)$/.exec(entry2);
|
|
13065
|
+
if (!m) {
|
|
13066
|
+
throw new Error(
|
|
13067
|
+
`Invalid --forward-ports entry '${entry2}': expected host:container (e.g. 15173:5173).`
|
|
13068
|
+
);
|
|
13069
|
+
}
|
|
13070
|
+
const host = Number(m[1]);
|
|
13071
|
+
const container = Number(m[2]);
|
|
13072
|
+
for (const [label, port] of [
|
|
13073
|
+
["host", host],
|
|
13074
|
+
["container", container]
|
|
13075
|
+
]) {
|
|
13076
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
13077
|
+
throw new Error(
|
|
13078
|
+
`Invalid --forward-ports ${label} port '${port}': must be between 1 and 65535.`
|
|
13079
|
+
);
|
|
13080
|
+
}
|
|
13081
|
+
}
|
|
13082
|
+
out.push({ host, container });
|
|
13083
|
+
}
|
|
13084
|
+
return out;
|
|
13085
|
+
}
|
|
13060
13086
|
function realHostAddresses() {
|
|
13061
13087
|
let ip;
|
|
13062
13088
|
for (const list of Object.values(os4.networkInterfaces())) {
|
|
@@ -13113,6 +13139,37 @@ async function caTrustDisplayPath(caCertPath, home) {
|
|
|
13113
13139
|
const rel = path34.relative(home, caCertPath).split(path34.sep).join("\\");
|
|
13114
13140
|
return `${prof.homeWin}\\.monoceros\\${rel}`;
|
|
13115
13141
|
}
|
|
13142
|
+
async function findFreeHostPort(start, probe, taken) {
|
|
13143
|
+
let port = start > 65535 ? 2e4 : start;
|
|
13144
|
+
for (let i = 0; i < 200 && port <= 65535; i++, port++) {
|
|
13145
|
+
if (taken.has(port)) continue;
|
|
13146
|
+
const result = await probe(port, SHARE_ADDRESS);
|
|
13147
|
+
if (result.ok) return port;
|
|
13148
|
+
}
|
|
13149
|
+
return start;
|
|
13150
|
+
}
|
|
13151
|
+
function formatShareCollision(input) {
|
|
13152
|
+
const plural = input.busyHostPorts.length > 1;
|
|
13153
|
+
const cmd = `monoceros share ${input.name} ${input.app} --forward-ports ${input.suggestions.join(",")}`;
|
|
13154
|
+
return [
|
|
13155
|
+
`Cannot share ${input.name}/${input.app}: host port${plural ? "s" : ""} ${input.busyHostPorts.join(", ")} already in use.`,
|
|
13156
|
+
"",
|
|
13157
|
+
"Your IDE forwards the container's ports to 127.0.0.1 (VS Code, Codium",
|
|
13158
|
+
"and JetBrains auto-forward over Remote-SSH, and it cannot be reliably",
|
|
13159
|
+
"turned off). That collides with share, which binds these ports on",
|
|
13160
|
+
"0.0.0.0 to reach other devices.",
|
|
13161
|
+
"",
|
|
13162
|
+
"Resolve it one of two ways:",
|
|
13163
|
+
"",
|
|
13164
|
+
` 1. In the IDE's PORTS panel, right-click each port -> "Stop Forwarding`,
|
|
13165
|
+
' Port" (stays gone across reconnects), then re-run share unchanged.',
|
|
13166
|
+
"",
|
|
13167
|
+
" 2. Re-run share and publish the busy ports under different host ports",
|
|
13168
|
+
" (Docker order, host:container):",
|
|
13169
|
+
"",
|
|
13170
|
+
` ${cmd}`
|
|
13171
|
+
].join("\n");
|
|
13172
|
+
}
|
|
13116
13173
|
async function runShare(opts) {
|
|
13117
13174
|
const log = opts.logger ?? {
|
|
13118
13175
|
info: (m) => consola35.info(m),
|
|
@@ -13133,16 +13190,49 @@ async function runShare(opts) {
|
|
|
13133
13190
|
);
|
|
13134
13191
|
}
|
|
13135
13192
|
const ports = [...new Set(ported.map((t) => t.port))];
|
|
13193
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
13194
|
+
for (const fp of opts.forwardPorts ?? []) {
|
|
13195
|
+
if (!ports.includes(fp.container)) {
|
|
13196
|
+
throw new Error(
|
|
13197
|
+
`--forward-ports maps container port ${fp.container}, but no shared target uses it. Shared ports: ${ports.join(", ")}.`
|
|
13198
|
+
);
|
|
13199
|
+
}
|
|
13200
|
+
overrides.set(fp.container, fp.host);
|
|
13201
|
+
}
|
|
13202
|
+
const hostPortFor = (container) => overrides.get(container) ?? container;
|
|
13203
|
+
const pairs = ports.map((container) => ({
|
|
13204
|
+
host: hostPortFor(container),
|
|
13205
|
+
container
|
|
13206
|
+
}));
|
|
13207
|
+
const probe = opts.probe ?? realPortProbe2;
|
|
13208
|
+
const busy = [];
|
|
13209
|
+
for (const pair of pairs) {
|
|
13210
|
+
const result = await probe(pair.host, SHARE_ADDRESS);
|
|
13211
|
+
if (!result.ok) busy.push(pair);
|
|
13212
|
+
}
|
|
13213
|
+
if (busy.length > 0) {
|
|
13214
|
+
const taken = new Set(pairs.map((p) => p.host));
|
|
13215
|
+
const suggestions = [];
|
|
13216
|
+
for (const b of busy) {
|
|
13217
|
+
const free = await findFreeHostPort(b.container + 1e4, probe, taken);
|
|
13218
|
+
taken.add(free);
|
|
13219
|
+
suggestions.push(`${free}:${b.container}`);
|
|
13220
|
+
}
|
|
13221
|
+
throw new Error(
|
|
13222
|
+
formatShareCollision({
|
|
13223
|
+
name: opts.name,
|
|
13224
|
+
app: opts.app,
|
|
13225
|
+
busyHostPorts: busy.map((b) => b.host),
|
|
13226
|
+
suggestions
|
|
13227
|
+
})
|
|
13228
|
+
);
|
|
13229
|
+
}
|
|
13136
13230
|
const resolve = opts.resolve ?? resolveTunnelTarget;
|
|
13137
13231
|
const base = await resolve({
|
|
13138
13232
|
name: opts.name,
|
|
13139
13233
|
target: String(ports[0]),
|
|
13140
13234
|
...opts.monocerosHome !== void 0 ? { monocerosHome: opts.monocerosHome } : {}
|
|
13141
13235
|
});
|
|
13142
|
-
const preflight = opts.preflight ?? preflightLocalPort;
|
|
13143
|
-
for (const port of ports) {
|
|
13144
|
-
await preflight({ port, address: SHARE_ADDRESS });
|
|
13145
|
-
}
|
|
13146
13236
|
const { ip: localIp, mdnsName } = (opts.hostAddresses ?? realHostAddresses)();
|
|
13147
13237
|
const winLanIp = await (opts.resolveWindowsLanIp ?? resolveWindowsLanIp)();
|
|
13148
13238
|
const ip = winLanIp ?? localIp;
|
|
@@ -13183,7 +13273,7 @@ async function runShare(opts) {
|
|
|
13183
13273
|
for (const t of ported) {
|
|
13184
13274
|
banner.push("", ` ${cyan2(t.name)}`);
|
|
13185
13275
|
for (const addr of addresses) {
|
|
13186
|
-
banner.push(` https://${addr}:${t.port}`);
|
|
13276
|
+
banner.push(` https://${addr}:${hostPortFor(t.port)}`);
|
|
13187
13277
|
}
|
|
13188
13278
|
}
|
|
13189
13279
|
banner.push(
|
|
@@ -13199,7 +13289,7 @@ async function runShare(opts) {
|
|
|
13199
13289
|
dockerSpawn(
|
|
13200
13290
|
buildCaddyDockerArgs({
|
|
13201
13291
|
localAddress: SHARE_ADDRESS,
|
|
13202
|
-
ports,
|
|
13292
|
+
ports: pairs,
|
|
13203
13293
|
network: base.network,
|
|
13204
13294
|
certDir: tls.certDir,
|
|
13205
13295
|
caddyfilePath
|
|
@@ -13262,11 +13352,21 @@ var init_share = __esm({
|
|
|
13262
13352
|
type: "positional",
|
|
13263
13353
|
description: "App to share (a path under projects/ with .monoceros/launch.json). Every target with a `port` is exposed on the LAN.",
|
|
13264
13354
|
required: true
|
|
13355
|
+
},
|
|
13356
|
+
"forward-ports": {
|
|
13357
|
+
type: "string",
|
|
13358
|
+
description: "Publish busy container ports under different host ports. Docker `-p` order (host:container), comma-separated: --forward-ports 15173:5173,18000:8000. Use when an IDE already forwards the port to localhost. Unlisted ports keep parity.",
|
|
13359
|
+
required: false
|
|
13265
13360
|
}
|
|
13266
13361
|
},
|
|
13267
13362
|
async run({ args }) {
|
|
13268
13363
|
try {
|
|
13269
|
-
const
|
|
13364
|
+
const forwardPorts = args["forward-ports"] ? parseForwardPorts(String(args["forward-ports"])) : void 0;
|
|
13365
|
+
const exitCode = await runShare({
|
|
13366
|
+
name: args.name,
|
|
13367
|
+
app: args.app,
|
|
13368
|
+
...forwardPorts ? { forwardPorts } : {}
|
|
13369
|
+
});
|
|
13270
13370
|
process.exit(exitCode);
|
|
13271
13371
|
} catch (err) {
|
|
13272
13372
|
consola36.error(err instanceof Error ? err.message : String(err));
|