@getmonoceros/workbench 1.38.0 → 1.38.2

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 CHANGED
@@ -4593,75 +4593,87 @@ function generateAgentsMd(input) {
4593
4593
  " DataGrip) to one of the services."
4594
4594
  );
4595
4595
  lines.push("");
4596
- if (input.ports.length > 0) {
4597
- lines.push("## Running a long-running server");
4598
- lines.push("");
4599
- lines.push(
4600
- "When you build something that serves on a port (a web app, an API),",
4601
- "it must keep running after this session ends. A plain `npm start` (or",
4602
- "any foreground start) dies the moment the user exits you or closes the",
4603
- `terminal, and then \`${input.containerName}.localhost${portSuffix}\` returns 502 Bad Gateway.`
4604
- );
4605
- lines.push("");
4606
- lines.push(
4607
- "Declare it in the app's own launch config at",
4608
- "`projects/<app>/.monoceros/launch.json`, then start it with",
4609
- "`monoceros-ctl`. Add or update an entry whenever you set up a",
4610
- "long-running server. The file travels with the app, so the human can",
4611
- "restart it later without knowing your start command:"
4612
- );
4613
- lines.push("");
4614
- lines.push("```json");
4615
- lines.push("{");
4616
- lines.push(' "configurations": [');
4617
- lines.push(
4618
- ` { "name": "web", "command": "<the project's start command>", "port": ${input.ports[0]}, "default": true }`
4619
- );
4620
- lines.push(" ]");
4621
- lines.push("}");
4622
- lines.push("```");
4623
- lines.push("");
4596
+ const examplePort = input.ports.length > 0 ? String(input.ports[0]) : "<port>";
4597
+ lines.push("## Running a long-running server");
4598
+ lines.push("");
4599
+ lines.push(
4600
+ "When you build something that serves on a port (a web app, an API),",
4601
+ "it must keep running after this session ends. A plain `npm start` (or",
4602
+ "any foreground start) dies the moment the user exits you or closes the",
4603
+ input.ports.length > 0 ? `terminal, and then \`${input.containerName}.localhost${portSuffix}\` returns 502 Bad Gateway.` : "terminal, and the app stops responding."
4604
+ );
4605
+ lines.push("");
4606
+ if (input.ports.length === 0) {
4624
4607
  lines.push(
4625
- "Use whatever start command the project actually uses (`npm run dev`,",
4626
- "`./mvnw spring-boot:run`, `python manage.py runserver`, `go run .`, \u2026).",
4627
- "Do not force a language-specific one. `<app>` is the path under",
4628
- "`projects/`; `port` must be a port already exposed on the container."
4608
+ "This container exposes **no ports yet**, so a server has nothing to be",
4609
+ "reached on. Before serving one, ask the user to add a port on the host",
4610
+ "and re-apply - you cannot do this from inside:"
4629
4611
  );
4630
4612
  lines.push("");
4631
- lines.push("Start it, stop it, tail its log:");
4632
- lines.push("");
4633
4613
  lines.push("```");
4634
- lines.push("monoceros-ctl start <app>");
4635
- lines.push("monoceros-ctl stop <app>");
4636
- lines.push("monoceros-ctl logs <app>");
4614
+ lines.push(`monoceros add-port ${input.containerName} <port>`);
4615
+ lines.push(`monoceros apply ${input.containerName}`);
4637
4616
  lines.push("```");
4638
4617
  lines.push("");
4639
- lines.push(
4640
- "`start` launches it detached (it survives your session) and, when a",
4641
- "`port` is set, waits until it actually listens before returning. The",
4642
- "human can do the same from the host with",
4643
- `\`monoceros start ${input.containerName} <app>\` / \`monoceros stop ${input.containerName} <app>\`,`,
4644
- `and follow output with \`monoceros logs ${input.containerName} <app>\`.`
4645
- );
4646
- lines.push("");
4647
- lines.push(
4648
- "An app can declare several servers (e.g. an API and a web frontend).",
4649
- 'Mark every server that should come up together with `"default": true`;',
4650
- "`monoceros-ctl start <app>` (no `--target`) then starts the whole default",
4651
- "set in the order the entries appear in the file, waiting for each",
4652
- "server's `port` to listen before starting the next - so order an entry",
4653
- "before anything that depends on it. If one fails to come up, the rest are",
4654
- "not started. Pass `--target <name>` to start or stop a single one."
4655
- );
4656
- lines.push("");
4657
- lines.push(
4658
- "The server must listen on `0.0.0.0` (not `127.0.0.1`) on the exposed",
4659
- "port, or Traefik cannot reach it. You only have the ports already",
4660
- "declared on the container; if you need another, ask the human to add it",
4661
- `on the host (\`monoceros add-port ${input.containerName} <port>\`) and re-apply.`
4662
- );
4663
- lines.push("");
4664
4618
  }
4619
+ lines.push(
4620
+ "Declare the server in the app's own launch config at",
4621
+ "`projects/<app>/.monoceros/launch.json`, then start it with",
4622
+ "`monoceros-ctl`. Add or update an entry whenever you set up a",
4623
+ "long-running server. The file travels with the app, so the human can",
4624
+ "restart it later without knowing your start command:"
4625
+ );
4626
+ lines.push("");
4627
+ lines.push("```json");
4628
+ lines.push("{");
4629
+ lines.push(' "configurations": [');
4630
+ lines.push(
4631
+ ` { "name": "web", "command": "<the project's start command>", "port": ${examplePort}, "default": true }`
4632
+ );
4633
+ lines.push(" ]");
4634
+ lines.push("}");
4635
+ lines.push("```");
4636
+ lines.push("");
4637
+ lines.push(
4638
+ "Use whatever start command the project actually uses (`npm run dev`,",
4639
+ "`./mvnw spring-boot:run`, `python manage.py runserver`, `go run .`, \u2026).",
4640
+ "Do not force a language-specific one. `<app>` is the path under",
4641
+ "`projects/`; `port` must be a port exposed on the container."
4642
+ );
4643
+ lines.push("");
4644
+ lines.push("Start it, stop it, tail its log:");
4645
+ lines.push("");
4646
+ lines.push("```");
4647
+ lines.push("monoceros-ctl start <app>");
4648
+ lines.push("monoceros-ctl stop <app>");
4649
+ lines.push("monoceros-ctl logs <app>");
4650
+ lines.push("```");
4651
+ lines.push("");
4652
+ lines.push(
4653
+ "`start` launches it detached (it survives your session) and, when a",
4654
+ "`port` is set, waits until it actually listens before returning. The",
4655
+ "human can do the same from the host with",
4656
+ `\`monoceros start ${input.containerName} <app>\` / \`monoceros stop ${input.containerName} <app>\`,`,
4657
+ `and follow output with \`monoceros logs ${input.containerName} <app>\`.`
4658
+ );
4659
+ lines.push("");
4660
+ lines.push(
4661
+ "An app can declare several servers (e.g. an API and a web frontend).",
4662
+ 'Mark every server that should come up together with `"default": true`;',
4663
+ "`monoceros-ctl start <app>` (no `--target`) then starts the whole default",
4664
+ "set in the order the entries appear in the file, waiting for each",
4665
+ "server's `port` to listen before starting the next - so order an entry",
4666
+ "before anything that depends on it. If one fails to come up, the rest are",
4667
+ "not started. Pass `--target <name>` to start or stop a single one."
4668
+ );
4669
+ lines.push("");
4670
+ lines.push(
4671
+ "The server must listen on `0.0.0.0` (not `127.0.0.1`) on the exposed",
4672
+ "port, or Traefik cannot reach it. You only have the ports already",
4673
+ "declared on the container; if you need another, ask the human to add it",
4674
+ `on the host (\`monoceros add-port ${input.containerName} <port>\`) and re-apply.`
4675
+ );
4676
+ lines.push("");
4665
4677
  lines.push("## Command reference");
4666
4678
  lines.push("");
4667
4679
  lines.push(
@@ -6169,7 +6181,7 @@ var init_add_apt_packages = __esm({
6169
6181
  meta: {
6170
6182
  name: "add-apt-packages",
6171
6183
  group: "edit",
6172
- description: "Add Debian/Ubuntu apt packages to the container config. Pass package names after `--` (e.g. `monoceros add-apt-packages sandbox -- make openssh-client jq`). Idempotent. No curated whitelist \u2014 invalid names surface as apt errors at container build time."
6184
+ description: "Add Debian/Ubuntu apt packages to the container config. Pass package names as arguments (e.g. `monoceros add-apt-packages sandbox make openssh-client jq`). Idempotent. No curated whitelist \u2014 invalid names surface as apt errors at container build time."
6173
6185
  },
6174
6186
  args: {
6175
6187
  name: {
@@ -6177,6 +6189,11 @@ var init_add_apt_packages = __esm({
6177
6189
  description: "Container name (yml in $MONOCEROS_HOME/container-configs/).",
6178
6190
  required: true
6179
6191
  },
6192
+ packages: {
6193
+ type: "positional",
6194
+ description: "One or more Debian/Ubuntu apt package names (e.g. `make jq`). At least one is required.",
6195
+ required: false
6196
+ },
6180
6197
  yes: {
6181
6198
  type: "boolean",
6182
6199
  description: "Skip the interactive confirmation and apply the diff.",
@@ -6185,10 +6202,10 @@ var init_add_apt_packages = __esm({
6185
6202
  }
6186
6203
  },
6187
6204
  async run({ args }) {
6188
- const packages = [...getInnerArgs()];
6205
+ const packages = [...args._.slice(1).map(String), ...getInnerArgs()];
6189
6206
  if (packages.length === 0) {
6190
6207
  consola3.error(
6191
- "No package names given. Usage: `monoceros add-apt-packages <containername> [--yes] -- <pkg> [<pkg> \u2026]`."
6208
+ "No package names given. Usage: `monoceros add-apt-packages <containername> [--yes] <pkg> [<pkg> \u2026]`."
6192
6209
  );
6193
6210
  process.exit(1);
6194
6211
  }
@@ -6504,7 +6521,7 @@ var init_add_port = __esm({
6504
6521
  meta: {
6505
6522
  name: "add-port",
6506
6523
  group: "edit",
6507
- description: "Add one or more ports to the container config so they become reachable from the host via Traefik (`<container>.localhost` / `<container>-<port>.localhost`). Pass port numbers after `--` (e.g. `monoceros add-port sandbox -- 3000 5173 6006`). Idempotent. Persisted in the yml so later `monoceros apply` runs restore the routes. Pass `--default` together with a single port to make it the bare `<container>.localhost` route \u2014 the port is inserted at position 0 (or moved there if it already exists)."
6524
+ description: "Add one or more ports to the container config so they become reachable from the host via Traefik (`<container>.localhost` / `<container>-<port>.localhost`). Pass port numbers as arguments (e.g. `monoceros add-port sandbox 3000 5173 6006`). Idempotent. Persisted in the yml so later `monoceros apply` runs restore the routes. Pass `--default` together with a single port to make it the bare `<container>.localhost` route \u2014 the port is inserted at position 0 (or moved there if it already exists)."
6508
6525
  },
6509
6526
  args: {
6510
6527
  name: {
@@ -6512,6 +6529,11 @@ var init_add_port = __esm({
6512
6529
  description: "Container name (yml in $MONOCEROS_HOME/container-configs/).",
6513
6530
  required: true
6514
6531
  },
6532
+ ports: {
6533
+ type: "positional",
6534
+ description: "One or more port numbers to expose (e.g. `3000 5173`). At least one is required.",
6535
+ required: false
6536
+ },
6515
6537
  yes: {
6516
6538
  type: "boolean",
6517
6539
  description: "Skip the interactive confirmation and apply the diff.",
@@ -6525,10 +6547,10 @@ var init_add_port = __esm({
6525
6547
  }
6526
6548
  },
6527
6549
  async run({ args }) {
6528
- const tokens = [...getInnerArgs()];
6550
+ const tokens = [...args._.slice(1).map(String), ...getInnerArgs()];
6529
6551
  if (tokens.length === 0) {
6530
6552
  consola8.error(
6531
- "No ports given. Usage: `monoceros add-port <containername> [--yes] [--default] -- <port> [<port> \u2026]`."
6553
+ "No ports given. Usage: `monoceros add-port <containername> [--default] [--yes] <port> [<port> \u2026]`."
6532
6554
  );
6533
6555
  process.exit(1);
6534
6556
  }
@@ -8974,7 +8996,7 @@ var CLI_VERSION;
8974
8996
  var init_version = __esm({
8975
8997
  "src/version.ts"() {
8976
8998
  "use strict";
8977
- CLI_VERSION = true ? "1.38.0" : "dev";
8999
+ CLI_VERSION = true ? "1.38.2" : "dev";
8978
9000
  }
8979
9001
  });
8980
9002
 
@@ -12372,6 +12394,7 @@ var init_run3 = __esm({
12372
12394
 
12373
12395
  // src/tls/ca.ts
12374
12396
  import { promises as fs21 } from "fs";
12397
+ import os3 from "os";
12375
12398
  import path33 from "path";
12376
12399
  import forge from "node-forge";
12377
12400
  function homeDir(monocerosHome2) {
@@ -12380,6 +12403,10 @@ function homeDir(monocerosHome2) {
12380
12403
  function randomSerial() {
12381
12404
  return "00" + forge.util.bytesToHex(forge.random.getBytesSync(16));
12382
12405
  }
12406
+ function caCommonName() {
12407
+ const host = os3.hostname().replace(/\.local$/, "").trim();
12408
+ return host ? `Monoceros Local CA (${host})` : "Monoceros Local CA";
12409
+ }
12383
12410
  async function fileExists(p) {
12384
12411
  try {
12385
12412
  await fs21.access(p);
@@ -12409,7 +12436,7 @@ async function loadOrCreateCa(monocerosHome2) {
12409
12436
  cert.validity.notAfter = new Date(
12410
12437
  cert.validity.notBefore.getTime() + CA_DAYS * 24 * 60 * 60 * 1e3
12411
12438
  );
12412
- const attrs = [{ name: "commonName", value: "Monoceros Local CA" }];
12439
+ const attrs = [{ name: "commonName", value: caCommonName() }];
12413
12440
  cert.setSubject(attrs);
12414
12441
  cert.setIssuer(attrs);
12415
12442
  cert.setExtensions([
@@ -12571,14 +12598,14 @@ var init_caddy = __esm({
12571
12598
  });
12572
12599
 
12573
12600
  // src/share/run.ts
12574
- import os3 from "os";
12601
+ import os4 from "os";
12575
12602
  import { spawnSync as spawnSync2 } from "child_process";
12576
12603
  import { consola as consola35 } from "consola";
12577
12604
  import { promises as fs22 } from "fs";
12578
12605
  import path34 from "path";
12579
12606
  function realHostAddresses() {
12580
12607
  let ip;
12581
- for (const list of Object.values(os3.networkInterfaces())) {
12608
+ for (const list of Object.values(os4.networkInterfaces())) {
12582
12609
  for (const addr of list ?? []) {
12583
12610
  if (addr.family === "IPv4" && !addr.internal) {
12584
12611
  ip = addr.address;
@@ -12597,7 +12624,7 @@ function mdnsHostName() {
12597
12624
  const name = res.status === 0 ? res.stdout.trim() : "";
12598
12625
  if (name) return `${name}.local`;
12599
12626
  }
12600
- const hn = os3.hostname();
12627
+ const hn = os4.hostname();
12601
12628
  return hn.endsWith(".local") ? hn : `${hn}.local`;
12602
12629
  }
12603
12630
  async function runShare(opts) {