Skip to content
Closed
8 changes: 8 additions & 0 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ npm install -g @agegr/pi-web@latest
pi-web
```

**最新バージョンに更新:**

```bash
pi-web update
```

更新後に pi-web を再起動してください。

**グローバルインストールをアンインストール:**

```bash
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ npm install -g @agegr/pi-web@latest
pi-web
```

**Update to the latest version:**

```bash
pi-web update
```

Restart pi-web after updating.

**Uninstall a global installation:**

```bash
Expand Down
8 changes: 8 additions & 0 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ npm install -g @agegr/pi-web@latest
pi-web
```

**Обновление до последней версии:**

```bash
pi-web update
```

После обновления перезапустите pi-web.

**Удаление глобальной установки:**

```bash
Expand Down
8 changes: 8 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ npm install -g @agegr/pi-web@latest
pi-web
```

**更新到最新版本:**

```bash
pi-web update
```

更新完成后请重启 pi-web。

**卸载全局安装:**

```bash
Expand Down
33 changes: 27 additions & 6 deletions bin/pi-web-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ function isEnabled(value) {
return typeof value === "string" && TRUE_VALUES.has(value.trim().toLowerCase());
}

const LAUNCH_OPTIONS = {
port: { type: "string", short: "p" },
hostname: { type: "string", short: "H" },
"no-open": { type: "boolean" },
};

function parseLaunchOptions(args = process.argv.slice(2), env = process.env) {
const { values: cliArgs } = parseArgs({
args,
options: {
port: { type: "string", short: "p" },
hostname: { type: "string", short: "H" },
"no-open": { type: "boolean" },
},
options: LAUNCH_OPTIONS,
strict: false,
});

Expand All @@ -27,4 +29,23 @@ function parseLaunchOptions(args = process.argv.slice(2), env = process.env) {
};
}

module.exports = { parseLaunchOptions };
// Only used to detect the `update` subcommand. Kept separate from
// parseLaunchOptions so the launch options object stays stable.
function getCommandPositionals(args = process.argv.slice(2)) {
try {
return parseArgs({
args,
options: LAUNCH_OPTIONS,
strict: true,
allowPositionals: true,
}).positionals;
} catch {
return [];
}
}

function shouldRunUpdate(args = process.argv.slice(2)) {
return getCommandPositionals(args)[0] === "update";
}

module.exports = { getCommandPositionals, parseLaunchOptions, shouldRunUpdate };
48 changes: 48 additions & 0 deletions bin/pi-web-options.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import assert from "node:assert/strict";
import { createRequire } from "node:module";
import test from "node:test";

const require = createRequire(import.meta.url);
const {
getCommandPositionals,
parseLaunchOptions,
shouldRunUpdate,
} = require("./pi-web-options.js");

test("reports the first positional argument", () => {
assert.deepEqual(getCommandPositionals(["update"]), ["update"]);
assert.deepEqual(getCommandPositionals(["update", "--port", "8080"]), ["update"]);
assert.deepEqual(getCommandPositionals(["--port", "8080", "update"]), ["update"]);
assert.deepEqual(getCommandPositionals(["--port", "8080"]), []);
assert.deepEqual(getCommandPositionals([]), []);
});

test("does not mistake option values for positional arguments", () => {
assert.deepEqual(getCommandPositionals(["--hostname", "update"]), []);
assert.deepEqual(getCommandPositionals(["--port", "update"]), []);
});

test("dispatches only when the first positional is update", () => {
assert.equal(shouldRunUpdate(["update"]), true);
assert.equal(shouldRunUpdate(["--port", "8080", "update"]), true);
assert.equal(shouldRunUpdate(["serve", "update"]), false);
assert.equal(shouldRunUpdate([]), false);
});

test("does not dispatch update when argument parsing fails", () => {
assert.equal(shouldRunUpdate(["--host", "update"]), false);
assert.equal(shouldRunUpdate(["--unknown", "value", "update"]), false);
assert.equal(shouldRunUpdate(["--hostname"]), false);
});

test("does not dispatch update when it is a known option value", () => {
assert.equal(shouldRunUpdate(["--hostname", "update"]), false);
assert.equal(shouldRunUpdate(["--port", "update"]), false);
});

test("keeps launch options stable", () => {
const options = parseLaunchOptions(["-p", "8080", "-H", "0.0.0.0", "--no-open"]);
assert.equal(options.port, "8080");
assert.equal(options.hostname, "0.0.0.0");
assert.equal(options.openBrowser, false);
});
Loading