@getmonoceros/workbench 1.37.14 → 1.38.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/bundled-components/services/keycloak/component.yml +8 -1
- package/dist/bin.js +277 -31
- package/dist/bin.js.map +1 -1
- package/package.json +3 -1
|
@@ -9,7 +9,14 @@ service:
|
|
|
9
9
|
# Dev mode + realm import. The Keycloak image has no auto-start default,
|
|
10
10
|
# so a command is mandatory. `--import-realm` reads every *.json from
|
|
11
11
|
# /opt/keycloak/data/import at startup (a no-op if the dir is empty).
|
|
12
|
-
|
|
12
|
+
# `--proxy-headers=xforwarded` makes Keycloak derive the issuer host and
|
|
13
|
+
# scheme from X-Forwarded-Host / X-Forwarded-Proto, so the realm stamps a
|
|
14
|
+
# matching issuer whether it is reached over http via the Traefik proxy
|
|
15
|
+
# (`plantlove.localhost`) or over https via `monoceros share` on a phone.
|
|
16
|
+
# Without it Keycloak uses the raw connection scheme (always http behind a
|
|
17
|
+
# TLS-terminating proxy) and the OIDC token exchange fails on the https
|
|
18
|
+
# client. See ADR 0033.
|
|
19
|
+
command: start-dev --import-realm --proxy-headers=xforwarded
|
|
13
20
|
# Starts in a host-side second wave AFTER the repo clone (ADR 0025), so a
|
|
14
21
|
# mounted realm.json / theme from the project is present at boot. No
|
|
15
22
|
# dataMount: the dev H2 database is ephemeral and re-seeds from the
|
package/dist/bin.js
CHANGED
|
@@ -4107,12 +4107,12 @@ async function writeScaffold(opts, targetDir, scaffoldOpts = {}) {
|
|
|
4107
4107
|
const devcontainerDir = path11.join(targetDir, ".devcontainer");
|
|
4108
4108
|
const monocerosDir = path11.join(targetDir, ".monoceros");
|
|
4109
4109
|
const projectsDir = path11.join(targetDir, "projects");
|
|
4110
|
-
const
|
|
4110
|
+
const homeDir2 = path11.join(targetDir, "home");
|
|
4111
4111
|
const dataDir = path11.join(targetDir, "data");
|
|
4112
4112
|
await fs9.mkdir(devcontainerDir, { recursive: true });
|
|
4113
4113
|
await fs9.mkdir(monocerosDir, { recursive: true });
|
|
4114
4114
|
await fs9.mkdir(projectsDir, { recursive: true });
|
|
4115
|
-
await fs9.mkdir(
|
|
4115
|
+
await fs9.mkdir(homeDir2, { recursive: true });
|
|
4116
4116
|
if (needsCompose(opts)) {
|
|
4117
4117
|
await fs9.mkdir(dataDir, { recursive: true });
|
|
4118
4118
|
for (const svc of opts.services) {
|
|
@@ -4176,10 +4176,10 @@ async function writeScaffold(opts, targetDir, scaffoldOpts = {}) {
|
|
|
4176
4176
|
}
|
|
4177
4177
|
for (const f of resolvedFeatures) {
|
|
4178
4178
|
for (const sub of f.persistentHomePaths) {
|
|
4179
|
-
await fs9.mkdir(path11.join(
|
|
4179
|
+
await fs9.mkdir(path11.join(homeDir2, sub), { recursive: true });
|
|
4180
4180
|
}
|
|
4181
4181
|
for (const entry2 of f.persistentHomeFiles) {
|
|
4182
|
-
const filePath = path11.join(
|
|
4182
|
+
const filePath = path11.join(homeDir2, entry2.path);
|
|
4183
4183
|
await fs9.mkdir(path11.dirname(filePath), { recursive: true });
|
|
4184
4184
|
if (!existsSync8(filePath)) {
|
|
4185
4185
|
await fs9.writeFile(filePath, entry2.initialContent);
|
|
@@ -5481,8 +5481,8 @@ function removeRepoFromDoc(doc, urlOrPath) {
|
|
|
5481
5481
|
if (!isMap2(item)) return false;
|
|
5482
5482
|
const url = item.get("url");
|
|
5483
5483
|
if (url === urlOrPath) return true;
|
|
5484
|
-
const
|
|
5485
|
-
const effectivePath = typeof
|
|
5484
|
+
const path35 = item.get("path");
|
|
5485
|
+
const effectivePath = typeof path35 === "string" ? path35 : typeof url === "string" ? deriveRepoName(url) : void 0;
|
|
5486
5486
|
return effectivePath === urlOrPath;
|
|
5487
5487
|
});
|
|
5488
5488
|
if (idx < 0) return false;
|
|
@@ -5625,7 +5625,7 @@ async function runAddRepo(input) {
|
|
|
5625
5625
|
"Missing repo URL. Usage: monoceros add-repo <containername> <url>."
|
|
5626
5626
|
);
|
|
5627
5627
|
}
|
|
5628
|
-
const
|
|
5628
|
+
const path35 = (input.path ?? deriveRepoName(url)).trim();
|
|
5629
5629
|
const hasName = typeof input.gitName === "string" && input.gitName.trim().length > 0;
|
|
5630
5630
|
const hasEmail = typeof input.gitEmail === "string" && input.gitEmail.trim().length > 0;
|
|
5631
5631
|
if (hasName !== hasEmail) {
|
|
@@ -5662,7 +5662,7 @@ async function runAddRepo(input) {
|
|
|
5662
5662
|
const providerToWrite = !canonical && explicitProvider ? explicitProvider : void 0;
|
|
5663
5663
|
const entry2 = {
|
|
5664
5664
|
url,
|
|
5665
|
-
path:
|
|
5665
|
+
path: path35,
|
|
5666
5666
|
...hasName && hasEmail ? {
|
|
5667
5667
|
gitUser: {
|
|
5668
5668
|
name: input.gitName.trim(),
|
|
@@ -8974,7 +8974,7 @@ var CLI_VERSION;
|
|
|
8974
8974
|
var init_version = __esm({
|
|
8975
8975
|
"src/version.ts"() {
|
|
8976
8976
|
"use strict";
|
|
8977
|
-
CLI_VERSION = true ? "1.
|
|
8977
|
+
CLI_VERSION = true ? "1.38.0" : "dev";
|
|
8978
8978
|
}
|
|
8979
8979
|
});
|
|
8980
8980
|
|
|
@@ -12370,9 +12370,212 @@ var init_run3 = __esm({
|
|
|
12370
12370
|
}
|
|
12371
12371
|
});
|
|
12372
12372
|
|
|
12373
|
+
// src/tls/ca.ts
|
|
12374
|
+
import { promises as fs21 } from "fs";
|
|
12375
|
+
import path33 from "path";
|
|
12376
|
+
import forge from "node-forge";
|
|
12377
|
+
function homeDir(monocerosHome2) {
|
|
12378
|
+
return monocerosHome2 ?? monocerosHome();
|
|
12379
|
+
}
|
|
12380
|
+
function randomSerial() {
|
|
12381
|
+
return "00" + forge.util.bytesToHex(forge.random.getBytesSync(16));
|
|
12382
|
+
}
|
|
12383
|
+
async function fileExists(p) {
|
|
12384
|
+
try {
|
|
12385
|
+
await fs21.access(p);
|
|
12386
|
+
return true;
|
|
12387
|
+
} catch {
|
|
12388
|
+
return false;
|
|
12389
|
+
}
|
|
12390
|
+
}
|
|
12391
|
+
async function loadOrCreateCa(monocerosHome2) {
|
|
12392
|
+
const dir = path33.join(homeDir(monocerosHome2), CA_DIR);
|
|
12393
|
+
const certPath = path33.join(dir, CA_CERT_FILE);
|
|
12394
|
+
const keyPath = path33.join(dir, CA_KEY_FILE);
|
|
12395
|
+
if (await fileExists(certPath) && await fileExists(keyPath)) {
|
|
12396
|
+
const cert2 = forge.pki.certificateFromPem(
|
|
12397
|
+
await fs21.readFile(certPath, "utf8")
|
|
12398
|
+
);
|
|
12399
|
+
const key = forge.pki.privateKeyFromPem(
|
|
12400
|
+
await fs21.readFile(keyPath, "utf8")
|
|
12401
|
+
);
|
|
12402
|
+
return { cert: cert2, key, certPath, keyPath };
|
|
12403
|
+
}
|
|
12404
|
+
const keys = forge.pki.rsa.generateKeyPair(2048);
|
|
12405
|
+
const cert = forge.pki.createCertificate();
|
|
12406
|
+
cert.publicKey = keys.publicKey;
|
|
12407
|
+
cert.serialNumber = randomSerial();
|
|
12408
|
+
cert.validity.notBefore = /* @__PURE__ */ new Date();
|
|
12409
|
+
cert.validity.notAfter = new Date(
|
|
12410
|
+
cert.validity.notBefore.getTime() + CA_DAYS * 24 * 60 * 60 * 1e3
|
|
12411
|
+
);
|
|
12412
|
+
const attrs = [{ name: "commonName", value: "Monoceros Local CA" }];
|
|
12413
|
+
cert.setSubject(attrs);
|
|
12414
|
+
cert.setIssuer(attrs);
|
|
12415
|
+
cert.setExtensions([
|
|
12416
|
+
{ name: "basicConstraints", cA: true, critical: true },
|
|
12417
|
+
{ name: "keyUsage", keyCertSign: true, cRLSign: true, critical: true },
|
|
12418
|
+
{ name: "subjectKeyIdentifier" }
|
|
12419
|
+
]);
|
|
12420
|
+
cert.sign(keys.privateKey, forge.md.sha256.create());
|
|
12421
|
+
await fs21.mkdir(dir, { recursive: true });
|
|
12422
|
+
await fs21.writeFile(certPath, forge.pki.certificateToPem(cert), {
|
|
12423
|
+
mode: 420
|
|
12424
|
+
});
|
|
12425
|
+
await fs21.writeFile(keyPath, forge.pki.privateKeyToPem(keys.privateKey), {
|
|
12426
|
+
mode: 384
|
|
12427
|
+
});
|
|
12428
|
+
return { cert, key: keys.privateKey, certPath, keyPath };
|
|
12429
|
+
}
|
|
12430
|
+
function normalizeSans(sans) {
|
|
12431
|
+
return [...new Set(sans.filter((s) => s.length > 0))].sort();
|
|
12432
|
+
}
|
|
12433
|
+
async function readLeafMeta(metaPath) {
|
|
12434
|
+
try {
|
|
12435
|
+
return JSON.parse(await fs21.readFile(metaPath, "utf8"));
|
|
12436
|
+
} catch {
|
|
12437
|
+
return null;
|
|
12438
|
+
}
|
|
12439
|
+
}
|
|
12440
|
+
function leafStillGood(meta, sans) {
|
|
12441
|
+
if (!meta) return false;
|
|
12442
|
+
if (meta.sans.join(",") !== sans.join(",")) return false;
|
|
12443
|
+
const notAfter = new Date(meta.notAfter).getTime();
|
|
12444
|
+
if (Number.isNaN(notAfter)) return false;
|
|
12445
|
+
return notAfter - Date.now() > LEAF_RENEW_BEFORE_MS;
|
|
12446
|
+
}
|
|
12447
|
+
async function ensureLeafCert(opts) {
|
|
12448
|
+
const sans = normalizeSans(opts.sans);
|
|
12449
|
+
const dir = path33.join(homeDir(opts.monocerosHome), CERTS_DIR);
|
|
12450
|
+
const certPath = path33.join(dir, LEAF_CERT_FILE);
|
|
12451
|
+
const keyPath = path33.join(dir, LEAF_KEY_FILE);
|
|
12452
|
+
const metaPath = path33.join(dir, LEAF_META_FILE);
|
|
12453
|
+
const ca = await loadOrCreateCa(opts.monocerosHome);
|
|
12454
|
+
const haveFiles = await fileExists(certPath) && await fileExists(keyPath);
|
|
12455
|
+
if (haveFiles && leafStillGood(await readLeafMeta(metaPath), sans)) {
|
|
12456
|
+
return {
|
|
12457
|
+
caCertPath: ca.certPath,
|
|
12458
|
+
certDir: dir,
|
|
12459
|
+
certFile: LEAF_CERT_FILE,
|
|
12460
|
+
keyFile: LEAF_KEY_FILE
|
|
12461
|
+
};
|
|
12462
|
+
}
|
|
12463
|
+
const keys = forge.pki.rsa.generateKeyPair(2048);
|
|
12464
|
+
const cert = forge.pki.createCertificate();
|
|
12465
|
+
cert.publicKey = keys.publicKey;
|
|
12466
|
+
cert.serialNumber = randomSerial();
|
|
12467
|
+
cert.validity.notBefore = /* @__PURE__ */ new Date();
|
|
12468
|
+
cert.validity.notAfter = new Date(
|
|
12469
|
+
cert.validity.notBefore.getTime() + LEAF_DAYS * 24 * 60 * 60 * 1e3
|
|
12470
|
+
);
|
|
12471
|
+
cert.setSubject([{ name: "commonName", value: "monoceros share" }]);
|
|
12472
|
+
cert.setIssuer(ca.cert.subject.attributes);
|
|
12473
|
+
cert.setExtensions([
|
|
12474
|
+
{ name: "basicConstraints", cA: false },
|
|
12475
|
+
{
|
|
12476
|
+
name: "keyUsage",
|
|
12477
|
+
digitalSignature: true,
|
|
12478
|
+
keyEncipherment: true,
|
|
12479
|
+
critical: true
|
|
12480
|
+
},
|
|
12481
|
+
{ name: "extKeyUsage", serverAuth: true },
|
|
12482
|
+
{
|
|
12483
|
+
name: "subjectAltName",
|
|
12484
|
+
altNames: sans.map(
|
|
12485
|
+
(s) => IPV4_RE2.test(s) ? { type: 7, ip: s } : { type: 2, value: s }
|
|
12486
|
+
)
|
|
12487
|
+
}
|
|
12488
|
+
]);
|
|
12489
|
+
cert.sign(ca.key, forge.md.sha256.create());
|
|
12490
|
+
await fs21.mkdir(dir, { recursive: true });
|
|
12491
|
+
await fs21.writeFile(certPath, forge.pki.certificateToPem(cert), {
|
|
12492
|
+
mode: 420
|
|
12493
|
+
});
|
|
12494
|
+
await fs21.writeFile(keyPath, forge.pki.privateKeyToPem(keys.privateKey), {
|
|
12495
|
+
mode: 384
|
|
12496
|
+
});
|
|
12497
|
+
const meta = {
|
|
12498
|
+
sans,
|
|
12499
|
+
notAfter: cert.validity.notAfter.toISOString()
|
|
12500
|
+
};
|
|
12501
|
+
await fs21.writeFile(metaPath, JSON.stringify(meta), { mode: 420 });
|
|
12502
|
+
return {
|
|
12503
|
+
caCertPath: ca.certPath,
|
|
12504
|
+
certDir: dir,
|
|
12505
|
+
certFile: LEAF_CERT_FILE,
|
|
12506
|
+
keyFile: LEAF_KEY_FILE
|
|
12507
|
+
};
|
|
12508
|
+
}
|
|
12509
|
+
async function provisionShareTls(opts) {
|
|
12510
|
+
return ensureLeafCert(opts);
|
|
12511
|
+
}
|
|
12512
|
+
var CA_DIR, CA_CERT_FILE, CA_KEY_FILE, CERTS_DIR, LEAF_CERT_FILE, LEAF_KEY_FILE, LEAF_META_FILE, CA_DAYS, LEAF_DAYS, LEAF_RENEW_BEFORE_MS, IPV4_RE2;
|
|
12513
|
+
var init_ca = __esm({
|
|
12514
|
+
"src/tls/ca.ts"() {
|
|
12515
|
+
"use strict";
|
|
12516
|
+
init_paths();
|
|
12517
|
+
CA_DIR = "ca";
|
|
12518
|
+
CA_CERT_FILE = "rootCA.pem";
|
|
12519
|
+
CA_KEY_FILE = "rootCA-key.pem";
|
|
12520
|
+
CERTS_DIR = "certs";
|
|
12521
|
+
LEAF_CERT_FILE = "leaf.pem";
|
|
12522
|
+
LEAF_KEY_FILE = "leaf-key.pem";
|
|
12523
|
+
LEAF_META_FILE = "leaf.json";
|
|
12524
|
+
CA_DAYS = 3650;
|
|
12525
|
+
LEAF_DAYS = 397;
|
|
12526
|
+
LEAF_RENEW_BEFORE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
12527
|
+
IPV4_RE2 = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
12528
|
+
}
|
|
12529
|
+
});
|
|
12530
|
+
|
|
12531
|
+
// src/share/caddy.ts
|
|
12532
|
+
function renderCaddyfile(sites, certFile, keyFile) {
|
|
12533
|
+
const blocks = sites.map(
|
|
12534
|
+
(s) => `:${s.port} {
|
|
12535
|
+
tls /certs/${certFile} /certs/${keyFile}
|
|
12536
|
+
reverse_proxy http://${s.targetHost}:${s.port}
|
|
12537
|
+
}`
|
|
12538
|
+
);
|
|
12539
|
+
return [
|
|
12540
|
+
"{",
|
|
12541
|
+
" auto_https off",
|
|
12542
|
+
" admin off",
|
|
12543
|
+
" servers {",
|
|
12544
|
+
" protocols h1 h2",
|
|
12545
|
+
" }",
|
|
12546
|
+
"}",
|
|
12547
|
+
...blocks,
|
|
12548
|
+
""
|
|
12549
|
+
].join("\n");
|
|
12550
|
+
}
|
|
12551
|
+
function buildCaddyDockerArgs(input) {
|
|
12552
|
+
const args = ["run", "--rm", "-i", `--network=${input.network}`];
|
|
12553
|
+
for (const port of input.ports) {
|
|
12554
|
+
args.push("-p", `${input.localAddress}:${port}:${port}`);
|
|
12555
|
+
}
|
|
12556
|
+
args.push(
|
|
12557
|
+
"-v",
|
|
12558
|
+
`${input.certDir}:/certs:ro`,
|
|
12559
|
+
"-v",
|
|
12560
|
+
`${input.caddyfilePath}:/etc/caddy/Caddyfile:ro`,
|
|
12561
|
+
CADDY_IMAGE
|
|
12562
|
+
);
|
|
12563
|
+
return args;
|
|
12564
|
+
}
|
|
12565
|
+
var CADDY_IMAGE;
|
|
12566
|
+
var init_caddy = __esm({
|
|
12567
|
+
"src/share/caddy.ts"() {
|
|
12568
|
+
"use strict";
|
|
12569
|
+
CADDY_IMAGE = "caddy:2.11.4";
|
|
12570
|
+
}
|
|
12571
|
+
});
|
|
12572
|
+
|
|
12373
12573
|
// src/share/run.ts
|
|
12374
12574
|
import os3 from "os";
|
|
12575
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
12375
12576
|
import { consola as consola35 } from "consola";
|
|
12577
|
+
import { promises as fs22 } from "fs";
|
|
12578
|
+
import path34 from "path";
|
|
12376
12579
|
function realHostAddresses() {
|
|
12377
12580
|
let ip;
|
|
12378
12581
|
for (const list of Object.values(os3.networkInterfaces())) {
|
|
@@ -12384,9 +12587,18 @@ function realHostAddresses() {
|
|
|
12384
12587
|
}
|
|
12385
12588
|
if (ip) break;
|
|
12386
12589
|
}
|
|
12590
|
+
return { ...ip ? { ip } : {}, mdnsName: mdnsHostName() };
|
|
12591
|
+
}
|
|
12592
|
+
function mdnsHostName() {
|
|
12593
|
+
if (process.platform === "darwin") {
|
|
12594
|
+
const res = spawnSync2("scutil", ["--get", "LocalHostName"], {
|
|
12595
|
+
encoding: "utf8"
|
|
12596
|
+
});
|
|
12597
|
+
const name = res.status === 0 ? res.stdout.trim() : "";
|
|
12598
|
+
if (name) return `${name}.local`;
|
|
12599
|
+
}
|
|
12387
12600
|
const hn = os3.hostname();
|
|
12388
|
-
|
|
12389
|
-
return { ...ip ? { ip } : {}, mdnsName };
|
|
12601
|
+
return hn.endsWith(".local") ? hn : `${hn}.local`;
|
|
12390
12602
|
}
|
|
12391
12603
|
async function runShare(opts) {
|
|
12392
12604
|
const log = opts.logger ?? {
|
|
@@ -12418,31 +12630,62 @@ async function runShare(opts) {
|
|
|
12418
12630
|
for (const port of ports) {
|
|
12419
12631
|
await preflight({ port, address: SHARE_ADDRESS });
|
|
12420
12632
|
}
|
|
12633
|
+
const { ip, mdnsName } = (opts.hostAddresses ?? realHostAddresses)();
|
|
12634
|
+
const sans = [mdnsName, ip, "localhost", "127.0.0.1"].filter(
|
|
12635
|
+
(s) => typeof s === "string" && s.length > 0
|
|
12636
|
+
);
|
|
12637
|
+
const provisionTls = opts.provisionTls ?? provisionShareTls;
|
|
12638
|
+
const tls = await provisionTls({
|
|
12639
|
+
sans,
|
|
12640
|
+
...opts.monocerosHome !== void 0 ? { monocerosHome: opts.monocerosHome } : {}
|
|
12641
|
+
});
|
|
12642
|
+
const sites = ports.map((port) => ({
|
|
12643
|
+
port,
|
|
12644
|
+
targetHost: base.targetHost
|
|
12645
|
+
}));
|
|
12646
|
+
const home = opts.monocerosHome ?? monocerosHome();
|
|
12647
|
+
const shareDir = path34.join(home, "share");
|
|
12648
|
+
await fs22.mkdir(shareDir, { recursive: true });
|
|
12649
|
+
const caddyfilePath = path34.join(
|
|
12650
|
+
shareDir,
|
|
12651
|
+
`${opts.name}__${opts.app}.Caddyfile`
|
|
12652
|
+
);
|
|
12653
|
+
await fs22.rm(caddyfilePath, { force: true });
|
|
12654
|
+
await fs22.writeFile(
|
|
12655
|
+
caddyfilePath,
|
|
12656
|
+
renderCaddyfile(sites, tls.certFile, tls.keyFile)
|
|
12657
|
+
);
|
|
12421
12658
|
const dockerSpawn = opts.dockerSpawn ?? defaultDockerSpawn;
|
|
12422
|
-
const handles =
|
|
12423
|
-
|
|
12424
|
-
|
|
12659
|
+
const handles = [
|
|
12660
|
+
dockerSpawn(
|
|
12661
|
+
buildCaddyDockerArgs({
|
|
12425
12662
|
localAddress: SHARE_ADDRESS,
|
|
12426
|
-
|
|
12427
|
-
internalPort: port,
|
|
12663
|
+
ports,
|
|
12428
12664
|
network: base.network,
|
|
12429
|
-
|
|
12665
|
+
certDir: tls.certDir,
|
|
12666
|
+
caddyfilePath
|
|
12430
12667
|
})
|
|
12431
12668
|
)
|
|
12432
|
-
|
|
12433
|
-
const
|
|
12434
|
-
const host = ip ?? mdnsName ?? "<host-ip>";
|
|
12669
|
+
];
|
|
12670
|
+
const host = mdnsName ?? ip ?? "<host-ip>";
|
|
12435
12671
|
log.info(
|
|
12436
12672
|
`Sharing ${opts.name}/${opts.app} on the local network (Ctrl+C to stop):`
|
|
12437
12673
|
);
|
|
12438
12674
|
for (const t of ported) {
|
|
12439
|
-
log.info(` ${cyan2(t.name)}
|
|
12675
|
+
log.info(` ${cyan2(t.name)} https://${host}:${t.port}`);
|
|
12440
12676
|
}
|
|
12441
12677
|
if (mdnsName && ip) {
|
|
12442
12678
|
log.info(
|
|
12443
|
-
dim(
|
|
12679
|
+
dim(
|
|
12680
|
+
` also reachable as https://${ip}:<port> if .local does not resolve`
|
|
12681
|
+
)
|
|
12444
12682
|
);
|
|
12445
12683
|
}
|
|
12684
|
+
log.info(
|
|
12685
|
+
dim(
|
|
12686
|
+
` First device? Trust the local CA once so HTTPS is warning-free: ${tls.caCertPath}`
|
|
12687
|
+
)
|
|
12688
|
+
);
|
|
12446
12689
|
const installSignalHandler = opts.installSignalHandler ?? installSigintDefault;
|
|
12447
12690
|
let stopping = false;
|
|
12448
12691
|
const uninstall = installSignalHandler(() => {
|
|
@@ -12466,6 +12709,9 @@ var init_run4 = __esm({
|
|
|
12466
12709
|
init_resolve2();
|
|
12467
12710
|
init_port_check2();
|
|
12468
12711
|
init_run3();
|
|
12712
|
+
init_ca();
|
|
12713
|
+
init_caddy();
|
|
12714
|
+
init_paths();
|
|
12469
12715
|
init_format();
|
|
12470
12716
|
SHARE_ADDRESS = "0.0.0.0";
|
|
12471
12717
|
}
|
|
@@ -12483,7 +12729,7 @@ var init_share = __esm({
|
|
|
12483
12729
|
meta: {
|
|
12484
12730
|
name: "share",
|
|
12485
12731
|
group: "discovery",
|
|
12486
|
-
description: "Expose an app's ports to the local network (phone, tablet, other devices) so any device can open it - reached via the host's LAN IP (or `.local` name). Every target in the app's launch.json that declares a port is shared. Foreground: Ctrl+C stops sharing. See ADR 0030."
|
|
12732
|
+
description: "Expose an app's ports to the local network (phone, tablet, other devices) over HTTPS so any device can open it - reached via the host's LAN IP (or `.local` name). TLS is served with a machine-local CA; trust the printed rootCA.pem once per device for warning-free HTTPS (and a working PWA secure context). Every target in the app's launch.json that declares a port is shared. Foreground: Ctrl+C stops sharing. See ADR 0030 and 0033."
|
|
12487
12733
|
},
|
|
12488
12734
|
args: {
|
|
12489
12735
|
name: {
|
|
@@ -13267,7 +13513,7 @@ var init_prune = __esm({
|
|
|
13267
13513
|
});
|
|
13268
13514
|
|
|
13269
13515
|
// src/upgrade/index.ts
|
|
13270
|
-
import { existsSync as existsSync21, promises as
|
|
13516
|
+
import { existsSync as existsSync21, promises as fs23 } from "fs";
|
|
13271
13517
|
import { consola as consola41 } from "consola";
|
|
13272
13518
|
async function fetchRuntimeVersions() {
|
|
13273
13519
|
const tokenUrl = `https://ghcr.io/token?service=ghcr.io&scope=repository:${RUNTIME_REPO}:pull`;
|
|
@@ -13384,10 +13630,10 @@ async function runUpgrade(opts) {
|
|
|
13384
13630
|
for (const name of targets) {
|
|
13385
13631
|
const ymlPath = containerConfigPath(name, home);
|
|
13386
13632
|
if (!existsSync21(ymlPath)) continue;
|
|
13387
|
-
const raw = await
|
|
13633
|
+
const raw = await fs23.readFile(ymlPath, "utf8");
|
|
13388
13634
|
const updated = setRuntimeVersion(raw, pinVersion);
|
|
13389
13635
|
if (updated !== raw) {
|
|
13390
|
-
await
|
|
13636
|
+
await fs23.writeFile(ymlPath, updated);
|
|
13391
13637
|
bumped += 1;
|
|
13392
13638
|
logger.info(`Pinned '${name}' to runtime ${pinVersion}.`);
|
|
13393
13639
|
}
|
|
@@ -13429,7 +13675,7 @@ function formatPruneLine(prune) {
|
|
|
13429
13675
|
}
|
|
13430
13676
|
async function listContainerNames2(home) {
|
|
13431
13677
|
try {
|
|
13432
|
-
const entries = await
|
|
13678
|
+
const entries = await fs23.readdir(containerConfigsDir(home));
|
|
13433
13679
|
return entries.filter((e) => e.endsWith(".yml")).map((e) => e.slice(0, -".yml".length));
|
|
13434
13680
|
} catch {
|
|
13435
13681
|
return [];
|
|
@@ -13844,25 +14090,25 @@ function detectHelpRequest(argv, main2) {
|
|
|
13844
14090
|
const separatorIdx = argv.indexOf("--");
|
|
13845
14091
|
if (helpIdx === -1) return null;
|
|
13846
14092
|
if (separatorIdx !== -1 && separatorIdx < helpIdx) return null;
|
|
13847
|
-
const
|
|
14093
|
+
const path35 = [];
|
|
13848
14094
|
const tokens = argv.slice(
|
|
13849
14095
|
0,
|
|
13850
14096
|
separatorIdx === -1 ? argv.length : separatorIdx
|
|
13851
14097
|
);
|
|
13852
14098
|
let cursor = main2;
|
|
13853
14099
|
const mainName = (main2.meta ?? {}).name ?? "monoceros";
|
|
13854
|
-
|
|
14100
|
+
path35.push(mainName);
|
|
13855
14101
|
for (const tok of tokens) {
|
|
13856
14102
|
if (tok.startsWith("-")) continue;
|
|
13857
14103
|
const subs = cursor.subCommands ?? {};
|
|
13858
14104
|
if (tok in subs) {
|
|
13859
14105
|
cursor = subs[tok];
|
|
13860
|
-
|
|
14106
|
+
path35.push(tok);
|
|
13861
14107
|
continue;
|
|
13862
14108
|
}
|
|
13863
14109
|
break;
|
|
13864
14110
|
}
|
|
13865
|
-
return { path:
|
|
14111
|
+
return { path: path35, cmd: cursor };
|
|
13866
14112
|
}
|
|
13867
14113
|
async function maybeRenderHelp(argv, main2) {
|
|
13868
14114
|
const hit = detectHelpRequest(argv, main2);
|