diff --git a/.changeset/clean-melons-shine.md b/.changeset/clean-melons-shine.md
new file mode 100644
index 00000000..50d5dc3c
--- /dev/null
+++ b/.changeset/clean-melons-shine.md
@@ -0,0 +1,5 @@
+---
+"@nodesecure/server": minor
+---
+
+Add buildServer wsPort option
diff --git a/bin/index.js b/bin/index.js
index b8c341d7..d230b632 100755
--- a/bin/index.js
+++ b/bin/index.js
@@ -73,7 +73,8 @@ prog
.command("open [json]")
.describe(i18n.getTokenSync("cli.commands.open.desc"))
.option("-p, --port", i18n.getTokenSync("cli.commands.open.option_port"), process.env.PORT)
- .option("-f, --fresh-start", i18n.getTokenSync("cli.commands.open.option_fresh_start"), process.env.PORT)
+ .option("--ws-port", i18n.getTokenSync("cli.commands.open.option_ws_port"), process.env.WS_PORT)
+ .option("-f, --fresh-start", i18n.getTokenSync("cli.commands.open.option_fresh_start"), false)
.option("-d, --developer", i18n.getTokenSync("cli.commands.open.option_developer"), false)
.action(commands.http.start);
diff --git a/docs/cli/open.md b/docs/cli/open.md
index e3c6a2d8..beba42cf 100644
--- a/docs/cli/open.md
+++ b/docs/cli/open.md
@@ -17,5 +17,6 @@ $ nsecure open [json]
| Name | Shortcut | Default Value | Description |
|---|---|---|---|
| `--port` | `-p` | `process.env.PORT` | Specify the port on which the HTTP server should run. |
+| `--ws-port` | N/A | `process.env.WS_PORT` | Specify the port on which the WebSocket server should run. |
| `--fresh-start` | `-f` | `false` | Open the UI with no initial package. Also, the app will use a dedicated cache. |
| `--developer` | `-d` | `false` | Launch the server in developer mode, enabling automatic HTML component refresh. |
diff --git a/i18n/english.js b/i18n/english.js
index 68500b23..9391d679 100644
--- a/i18n/english.js
+++ b/i18n/english.js
@@ -43,6 +43,7 @@ const cli = {
open: {
desc: "Run an HTTP Server with a given nsecure JSON file",
option_port: "Define the running port",
+ option_ws_port: "Define the WebSocket server port",
option_fresh_start: "Launch the server from scratch, ignoring any existing payload file",
option_developer: "Launch the server in developer mode, enabling automatic HTML component refresh"
},
diff --git a/i18n/french.js b/i18n/french.js
index 79922565..58d79131 100644
--- a/i18n/french.js
+++ b/i18n/french.js
@@ -43,6 +43,7 @@ const cli = {
open: {
desc: "Démarre un serveur HTTP avec un fichier .json nsecure donné",
option_port: "Port à utiliser",
+ option_ws_port: "Port du serveur WebSocket",
option_fresh_start: "Lance le serveur à partir de zéro, en ignorant tout fichier de payload existant",
option_developer: "Lance le serveur en mode développeur, permettant le rafraîchissement automatique des composants HTML"
},
diff --git a/public/main.js b/public/main.js
index 1c000409..c3201b0d 100644
--- a/public/main.js
+++ b/public/main.js
@@ -160,7 +160,7 @@ document.addEventListener("DOMContentLoaded", async() => {
);
onSettingsSaved(window.settings.config);
- const socket = new WebSocketClient(`ws://${window.location.hostname}:1338`);
+ const socket = new WebSocketClient(`ws://${window.location.hostname}:${window.__WS_PORT__}`);
socket.addEventListener("PAYLOAD", onSocketPayload);
socket.addEventListener("INIT", onSocketInitOrReload);
socket.addEventListener("RELOAD", onSocketInitOrReload);
diff --git a/src/commands/http.js b/src/commands/http.js
index 1296ecac..100b9acd 100644
--- a/src/commands/http.js
+++ b/src/commands/http.js
@@ -28,6 +28,7 @@ export async function start(
) {
const port = Number(options.port);
const httpPort = Number.isNaN(port) ? 0 : port;
+ const wsPort = Number(options["ws-port"]) || void 0;
const freshStart = Boolean(options.f);
const enableDeveloperMode = Boolean(options.developer);
@@ -59,6 +60,7 @@ export async function start(
scanType: options.scanType,
projectRootDir: kProjectRootDir,
componentsDir: kComponentsDir,
+ wsPort,
i18n: {
english,
french
@@ -74,7 +76,8 @@ export async function start(
new WebSocketServerInstanciator({
cache,
- logger
+ logger,
+ port: wsPort
});
for (const eventName of ["SIGINT", "SIGTERM"]) {
diff --git a/views/index.html b/views/index.html
index 66cef677..d4608d50 100644
--- a/views/index.html
+++ b/views/index.html
@@ -9,6 +9,7 @@
+
NodeSecure
diff --git a/workspaces/server/src/ALS.ts b/workspaces/server/src/ALS.ts
index 1c028b1f..4abca48c 100644
--- a/workspaces/server/src/ALS.ts
+++ b/workspaces/server/src/ALS.ts
@@ -19,6 +19,7 @@ export interface AsyncStoreContext {
french: NestedStringRecord;
};
viewBuilder: ViewBuilder;
+ wsPort: number;
reporter?: typeof report;
}
diff --git a/workspaces/server/src/ViewBuilder.class.ts b/workspaces/server/src/ViewBuilder.class.ts
index 70599961..c06935ab 100644
--- a/workspaces/server/src/ViewBuilder.class.ts
+++ b/workspaces/server/src/ViewBuilder.class.ts
@@ -72,13 +72,14 @@ export class ViewBuilder {
return HTMLStr;
}
- async render(): Promise {
+ async render(wsPort: number): Promise {
const i18nLangName = await i18n.getLocalLang();
const HTMLStr = await this.#build();
const templateStr = zup(HTMLStr)({
lang: i18n.getTokenSync("lang"),
i18nLangName,
+ wsPort,
token: (tokenName: string) => i18n.getTokenSync(`ui.${tokenName}`)
});
diff --git a/workspaces/server/src/endpoints/root.ts b/workspaces/server/src/endpoints/root.ts
index 1476d9d8..8d75d6c6 100644
--- a/workspaces/server/src/endpoints/root.ts
+++ b/workspaces/server/src/endpoints/root.ts
@@ -13,9 +13,9 @@ export async function get(
res: ServerResponse
) {
try {
- const { viewBuilder } = context.getStore()!;
+ const { viewBuilder, wsPort } = context.getStore()!;
- const templateStr = await viewBuilder.render();
+ const templateStr = await viewBuilder.render(wsPort);
res.writeHead(200, {
"Content-Type": "text/html"
diff --git a/workspaces/server/src/index.ts b/workspaces/server/src/index.ts
index 466efa29..6b691ab3 100644
--- a/workspaces/server/src/index.ts
+++ b/workspaces/server/src/index.ts
@@ -18,12 +18,16 @@ import {
type NestedStringRecord
} from "./ALS.ts";
+// CONSTANTS
+export const DEFAULT_WS_PORT = 1338;
+
export interface BuildServerOptions {
hotReload?: boolean;
runFromPayload?: boolean;
scanType?: "cwd" | "from";
projectRootDir: string;
componentsDir: string;
+ wsPort?: number;
i18n: {
english: NestedStringRecord;
french: NestedStringRecord;
@@ -49,6 +53,7 @@ export async function buildServer(
scanType = "from",
projectRootDir,
componentsDir,
+ wsPort = DEFAULT_WS_PORT,
i18n,
reporter
} = options;
@@ -61,6 +66,7 @@ export async function buildServer(
const store: AsyncStoreContext = {
i18n,
viewBuilder,
+ wsPort,
cache,
reporter
};
diff --git a/workspaces/server/src/websocket/index.ts b/workspaces/server/src/websocket/index.ts
index 425a8e5d..dd3b068e 100644
--- a/workspaces/server/src/websocket/index.ts
+++ b/workspaces/server/src/websocket/index.ts
@@ -13,10 +13,12 @@ import type {
WebSocketContext,
WebSocketMessage
} from "./websocket.types.ts";
+import { DEFAULT_WS_PORT } from "../index.ts";
export interface WebSocketServerInstanciatorOptions {
logger: Logger;
cache: PayloadCache;
+ port?: number;
}
export class WebSocketServerInstanciator {
@@ -29,7 +31,7 @@ export class WebSocketServerInstanciator {
this.#logger = options.logger;
this.#cache = options.cache;
const websocket = new WebSocketServer({
- port: 1338
+ port: Number(options.port) || DEFAULT_WS_PORT
});
websocket.on("connection", this.onConnectionHandler.bind(this));
}
diff --git a/workspaces/server/test/httpServer.test.ts b/workspaces/server/test/httpServer.test.ts
index 9095eb69..55eaacba 100644
--- a/workspaces/server/test/httpServer.test.ts
+++ b/workspaces/server/test/httpServer.test.ts
@@ -340,6 +340,47 @@ describe("httpServer without options", () => {
});
});
+describe("httpServer wsPort option", () => {
+ const wsPort = 1335;
+ let httpServer: Server;
+
+ before(async() => {
+ await i18n.extendFromSystemPath(
+ path.join(import.meta.dirname, "..", "..", "..", "i18n")
+ );
+
+ ({ httpServer } = await buildServer(JSON_PATH, {
+ projectRootDir: kProjectRootDir,
+ componentsDir: kComponentsDir,
+ reporter: async() => Buffer.from("fake-pdf-data"),
+ i18n: {
+ english: {
+ ui: {}
+ },
+ french: {
+ ui: {}
+ }
+ },
+ wsPort
+ }));
+ httpServer.listen(kHttpPort);
+ await once(httpServer, "listening");
+ enableDestroy(httpServer);
+ }, { timeout: 5000 });
+
+ after(async() => {
+ httpServer.destroy();
+ });
+
+ test("'/' should return index.html content", async() => {
+ const result = await get(kHttpURL);
+
+ assert.equal(result.statusCode, 200);
+ assert.equal(result.headers["content-type"], "text/html");
+ assert.ok(result.data.includes(`window.__WS_PORT__ = Number("${wsPort}")`));
+ });
+});
+
/**
* HELPERS
*/