@ganglion/xacpx-relay 0.1.0 → 0.2.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/dist/cli.d.ts CHANGED
@@ -12,7 +12,8 @@ export declare function resolveBundledWebRoot(): string | undefined;
12
12
  export interface StartOptions {
13
13
  dbPath: string;
14
14
  httpPort: number;
15
- wsPort: number;
15
+ /** Dedicated gateway port; undefined (default) merges the gateway onto the HTTP port. */
16
+ wsPort: number | undefined;
16
17
  host: string | undefined;
17
18
  webRoot: string | undefined;
18
19
  historyRetentionDays: number | undefined;
package/dist/cli.js CHANGED
@@ -979,26 +979,37 @@ async function startRelayServer(options) {
979
979
  reject(err);
980
980
  }
981
981
  });
982
- const wss = new WebSocketServer({ port: options.wsPort, host });
983
- await new Promise((resolve) => wss.on("listening", () => resolve()));
984
- wss.on("connection", (socket) => runtime.gateway.handleConnection(socket));
982
+ const dedicated = options.wsPort !== undefined;
983
+ let wss;
984
+ let gatewayWss;
985
+ if (dedicated) {
986
+ wss = new WebSocketServer({ port: options.wsPort, host });
987
+ await new Promise((resolve) => wss.on("listening", () => resolve()));
988
+ wss.on("connection", (socket) => runtime.gateway.handleConnection(socket));
989
+ } else {
990
+ gatewayWss = new WebSocketServer({ noServer: true });
991
+ }
985
992
  const webWss = new WebSocketServer({ noServer: true });
986
993
  httpServer.on("upgrade", (req, socket, head) => {
987
- const path = (req.url ?? "").split("?")[0];
988
- if (path !== "/ws") {
989
- socket.destroy();
994
+ const path = (req.url ?? "").split("?")[0] ?? "";
995
+ if (path === "/ws") {
996
+ const token = parseCookie(req.headers.cookie ?? "")["xrelay_session"];
997
+ const account = token ? runtime.accounts.getSessionAccount(token) : null;
998
+ if (!account) {
999
+ socket.destroy();
1000
+ return;
1001
+ }
1002
+ webWss.handleUpgrade(req, socket, head, (ws) => runtime.webGateway.register(account.id, ws));
990
1003
  return;
991
1004
  }
992
- const token = parseCookie(req.headers.cookie ?? "")["xrelay_session"];
993
- const account = token ? runtime.accounts.getSessionAccount(token) : null;
994
- if (!account) {
995
- socket.destroy();
1005
+ if (gatewayWss && (path === "/" || path === "/gateway" || path.startsWith("/gateway/"))) {
1006
+ gatewayWss.handleUpgrade(req, socket, head, (ws) => runtime.gateway.handleConnection(ws));
996
1007
  return;
997
1008
  }
998
- webWss.handleUpgrade(req, socket, head, (ws) => runtime.webGateway.register(account.id, ws));
1009
+ socket.destroy();
999
1010
  });
1000
1011
  const httpPort = httpServer.address().port;
1001
- const wsPort = wss.address().port;
1012
+ const wsPort = wss ? wss.address().port : null;
1002
1013
  return {
1003
1014
  runtime,
1004
1015
  httpPort,
@@ -1006,7 +1017,10 @@ async function startRelayServer(options) {
1006
1017
  close: async () => {
1007
1018
  stopMaintenance();
1008
1019
  await new Promise((resolve) => webWss.close(() => resolve()));
1009
- await new Promise((resolve) => wss.close(() => resolve()));
1020
+ if (gatewayWss)
1021
+ await new Promise((resolve) => gatewayWss.close(() => resolve()));
1022
+ if (wss)
1023
+ await new Promise((resolve) => wss.close(() => resolve()));
1010
1024
  await new Promise((resolve) => httpServer.close(() => resolve()));
1011
1025
  runtime.close();
1012
1026
  }
@@ -1044,7 +1058,8 @@ function resolveBundledWebRoot() {
1044
1058
  }
1045
1059
  var USAGE = [
1046
1060
  "Usage: xacpx-relay <command>",
1047
- " start [--db <path>] [--web-root <dir>] [--host 0.0.0.0] [--http-port 8787] [--ws-port 8788] [--history-retention-days 30] [--request-timeout-ms 120000] [--trust-proxy]",
1061
+ " start [--db <path>] [--web-root <dir>] [--host 0.0.0.0] [--http-port 8787] [--ws-port <n>] [--history-retention-days 30] [--request-timeout-ms 120000] [--trust-proxy]",
1062
+ " (--ws-port omitted = gateway merged onto the HTTP port; pass it only for a dedicated gateway port)",
1048
1063
  " add token [--label <note>] [--db <path>]",
1049
1064
  " ls [--db <path>]",
1050
1065
  " rm token <value-or-id> [--db <path>]",
@@ -1069,7 +1084,7 @@ function parseStartOptions(args) {
1069
1084
  return {
1070
1085
  dbPath,
1071
1086
  httpPort: Number(flag(args, "--http-port") ?? "8787"),
1072
- wsPort: Number(flag(args, "--ws-port") ?? "8788"),
1087
+ wsPort: flag(args, "--ws-port") !== undefined ? Number(flag(args, "--ws-port")) : undefined,
1073
1088
  host: flag(args, "--host"),
1074
1089
  webRoot: flag(args, "--web-root"),
1075
1090
  historyRetentionDays: retentionDays !== undefined && !Number.isNaN(retentionDays) ? retentionDays : undefined,
@@ -1085,7 +1100,8 @@ async function runRelayCli(args, io) {
1085
1100
  startOpts.webRoot = resolveBundledWebRoot();
1086
1101
  }
1087
1102
  const running = await startRelayServer(startOpts);
1088
- io.print(`xacpx-relay listening: http :${running.httpPort}, instance ws :${running.wsPort}, db ${startOpts.dbPath}, dashboard: ${startOpts.webRoot ?? "(none)"}`);
1103
+ const gatewayDesc = running.wsPort !== null ? `instance ws :${running.wsPort}` : `instance gateway: merged on http :${running.httpPort} (path / or /gateway)`;
1104
+ io.print(`xacpx-relay listening: http :${running.httpPort}, ${gatewayDesc}, db ${startOpts.dbPath}, dashboard: ${startOpts.webRoot ?? "(none)"}`);
1089
1105
  return await new Promise((resolve2) => {
1090
1106
  const shutdown = () => {
1091
1107
  running.close().then(() => resolve2(0));
@@ -1103,7 +1119,7 @@ async function runRelayCli(args, io) {
1103
1119
  const { token } = runtime.accounts.createLoginToken(acc.id, label);
1104
1120
  io.print(`access token: ${token}`);
1105
1121
  io.print("(store it now — not shown again)");
1106
- io.print(`hint: use this token for web login AND: xacpx channel add relay --url ws://<host>:<ws-port> --token ${token}`);
1122
+ io.print(`hint: use this token for web login AND: xacpx channel add relay --url <host> --token ${token}`);
1107
1123
  return 0;
1108
1124
  } finally {
1109
1125
  runtime.close();
package/dist/server.d.ts CHANGED
@@ -26,7 +26,12 @@ export declare function createRelayRuntime(dbPath: string, options?: CreateRunti
26
26
  export interface StartRelayOptions {
27
27
  dbPath: string;
28
28
  httpPort: number;
29
- wsPort: number;
29
+ /**
30
+ * Dedicated instance-gateway port (legacy two-port layout). Omit (default) to
31
+ * merge the gateway onto the HTTP port: connectors then reach it via a WS
32
+ * upgrade at `/` or `/gateway`, so a single port + domain serves everything.
33
+ */
34
+ wsPort?: number;
30
35
  host?: string;
31
36
  webRoot?: string;
32
37
  historyRetentionDays?: number;
@@ -36,7 +41,8 @@ export interface StartRelayOptions {
36
41
  export interface RunningRelay {
37
42
  runtime: RelayRuntime;
38
43
  httpPort: number;
39
- wsPort: number;
44
+ /** The dedicated gateway port, or `null` when the gateway is merged onto the HTTP port. */
45
+ wsPort: number | null;
40
46
  close(): Promise<void>;
41
47
  }
42
48
  export declare function startRelayServer(options: StartRelayOptions): Promise<RunningRelay>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ganglion/xacpx-relay",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Self-hosted relay hub for xacpx: instance gateway, accounts, and web API.",
5
5
  "license": "MIT",
6
6
  "keywords": ["xacpx", "relay", "hub"],