Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions bin/lib/launcher-utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ import { createHash } from "node:crypto";
import { createReadStream, existsSync, renameSync, rmSync } from "node:fs";
import * as path from "node:path";

export const DEFAULT_PORT = "3000";

/**
* Format a local startup link without changing the server's bind address.
* @param {string | null | undefined} hostname
* @param {string | number | null | undefined} port
* @returns {string}
*/
export function startupUrl(hostname, port) {
let host = hostname || "127.0.0.1";
if (host === "0.0.0.0") host = "127.0.0.1";
else if (host === "::" || host === "[::]") host = "[::1]";
else if (host.includes(":") && !host.startsWith("[")) host = `[${host}]`;
return `http://${host}:${port || DEFAULT_PORT}`;
}

/**
* Platform/arch pairs the release workflow builds standalone payloads for
* (must mirror the build jobs in .github/workflows/release-artifacts.yml).
Expand Down
6 changes: 4 additions & 2 deletions bin/studio.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import {
assessNodeRuntime,
assessProvenance,
extractArchive,
DEFAULT_PORT,
startupUrl,
LauncherUsageError,
parseLauncherArgs,
parseSha256Sums,
Expand Down Expand Up @@ -67,7 +69,7 @@ network only prints a warning; an archive whose provenance is actively
rejected stops the launcher (override: LIBREDB_STUDIO_SKIP_PROVENANCE=1).

Options:
--port <n> Port to listen on (default: $PORT or 3000)
--port <n> Port to listen on (default: $PORT or ${DEFAULT_PORT})
--host <addr> Address to bind (default: $HOSTNAME or 127.0.0.1;
use --host 0.0.0.0 to expose on the network)
--archive <path> Start from a local standalone archive instead of
Expand Down Expand Up @@ -316,7 +318,7 @@ function startServer(payloadDir, port, host) {
if (!env.WORKFLOW_LOCAL_DATA_DIR) env.WORKFLOW_LOCAL_DATA_DIR = resolveLedgerDir(os.homedir());
// Log-line contract: npx-engine-smoke.yml parses the resolved version from
// "Starting LibreDB Studio <version> " - keep the prefix stable.
console.log(`Starting LibreDB Studio ${pkg.version} on http://${env.HOSTNAME}:${env.PORT || "3000"}`);
console.log(`Starting LibreDB Studio ${pkg.version} on ${startupUrl(env.HOSTNAME, env.PORT)}`);
const child = spawn(process.execPath, ["server.js"], { cwd: payloadDir, env, stdio: "inherit" });
child.on("error", (error) => fail(`Could not start server.js: ${error.message}`));
for (const signal of /** @type {const} */ (["SIGINT", "SIGTERM"])) {
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/launcher-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as os from "os";
import * as path from "path";
import {
artifactName,
startupUrl,
assertReleaseVersion,
assessNodeRuntime,
assessProvenance,
Expand Down Expand Up @@ -566,3 +567,22 @@ describe("assessProvenance", () => {
expect(result.message).toContain(ARTIFACT);
});
});

describe("startupUrl", () => {
test.each([
["0.0.0.0", "4000", "http://127.0.0.1:4000"],
["::", "4000", "http://[::1]:4000"],
["[::]", "4000", "http://[::1]:4000"],
["fe80::1", "4000", "http://[fe80::1]:4000"],
["[fe80::1]", "4000", "http://[fe80::1]:4000"],
["127.0.0.1", "4000", "http://127.0.0.1:4000"],
["example.internal", "4000", "http://example.internal:4000"],
["", "4000", "http://127.0.0.1:4000"],
[undefined, undefined, "http://127.0.0.1:3000"],
[null, null, "http://127.0.0.1:3000"],
["127.0.0.1", "", "http://127.0.0.1:3000"],
["127.0.0.1", 4000, "http://127.0.0.1:4000"],
])("formats host %s and port %s", (host, port, expected) => {
expect(startupUrl(host, port)).toBe(expected);
});
});
Loading