@ganglion/xacpx-relay 0.1.0 → 0.2.1

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
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  export interface RelayCliIo {
2
3
  print(line: string): void;
3
4
  }
@@ -12,7 +13,8 @@ export declare function resolveBundledWebRoot(): string | undefined;
12
13
  export interface StartOptions {
13
14
  dbPath: string;
14
15
  httpPort: number;
15
- wsPort: number;
16
+ /** Dedicated gateway port; undefined (default) merges the gateway onto the HTTP port. */
17
+ wsPort: number | undefined;
16
18
  host: string | undefined;
17
19
  webRoot: string | undefined;
18
20
  historyRetentionDays: number | undefined;
package/dist/cli.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import { createRequire } from "node:module";
2
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
4
 
@@ -979,26 +980,37 @@ async function startRelayServer(options) {
979
980
  reject(err);
980
981
  }
981
982
  });
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));
983
+ const dedicated = options.wsPort !== undefined;
984
+ let wss;
985
+ let gatewayWss;
986
+ if (dedicated) {
987
+ wss = new WebSocketServer({ port: options.wsPort, host });
988
+ await new Promise((resolve) => wss.on("listening", () => resolve()));
989
+ wss.on("connection", (socket) => runtime.gateway.handleConnection(socket));
990
+ } else {
991
+ gatewayWss = new WebSocketServer({ noServer: true });
992
+ }
985
993
  const webWss = new WebSocketServer({ noServer: true });
986
994
  httpServer.on("upgrade", (req, socket, head) => {
987
- const path = (req.url ?? "").split("?")[0];
988
- if (path !== "/ws") {
989
- socket.destroy();
995
+ const path = (req.url ?? "").split("?")[0] ?? "";
996
+ if (path === "/ws") {
997
+ const token = parseCookie(req.headers.cookie ?? "")["xrelay_session"];
998
+ const account = token ? runtime.accounts.getSessionAccount(token) : null;
999
+ if (!account) {
1000
+ socket.destroy();
1001
+ return;
1002
+ }
1003
+ webWss.handleUpgrade(req, socket, head, (ws) => runtime.webGateway.register(account.id, ws));
990
1004
  return;
991
1005
  }
992
- const token = parseCookie(req.headers.cookie ?? "")["xrelay_session"];
993
- const account = token ? runtime.accounts.getSessionAccount(token) : null;
994
- if (!account) {
995
- socket.destroy();
1006
+ if (gatewayWss && (path === "/" || path === "/gateway" || path.startsWith("/gateway/"))) {
1007
+ gatewayWss.handleUpgrade(req, socket, head, (ws) => runtime.gateway.handleConnection(ws));
996
1008
  return;
997
1009
  }
998
- webWss.handleUpgrade(req, socket, head, (ws) => runtime.webGateway.register(account.id, ws));
1010
+ socket.destroy();
999
1011
  });
1000
1012
  const httpPort = httpServer.address().port;
1001
- const wsPort = wss.address().port;
1013
+ const wsPort = wss ? wss.address().port : null;
1002
1014
  return {
1003
1015
  runtime,
1004
1016
  httpPort,
@@ -1006,7 +1018,10 @@ async function startRelayServer(options) {
1006
1018
  close: async () => {
1007
1019
  stopMaintenance();
1008
1020
  await new Promise((resolve) => webWss.close(() => resolve()));
1009
- await new Promise((resolve) => wss.close(() => resolve()));
1021
+ if (gatewayWss)
1022
+ await new Promise((resolve) => gatewayWss.close(() => resolve()));
1023
+ if (wss)
1024
+ await new Promise((resolve) => wss.close(() => resolve()));
1010
1025
  await new Promise((resolve) => httpServer.close(() => resolve()));
1011
1026
  runtime.close();
1012
1027
  }
@@ -1044,7 +1059,8 @@ function resolveBundledWebRoot() {
1044
1059
  }
1045
1060
  var USAGE = [
1046
1061
  "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]",
1062
+ " 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]",
1063
+ " (--ws-port omitted = gateway merged onto the HTTP port; pass it only for a dedicated gateway port)",
1048
1064
  " add token [--label <note>] [--db <path>]",
1049
1065
  " ls [--db <path>]",
1050
1066
  " rm token <value-or-id> [--db <path>]",
@@ -1069,7 +1085,7 @@ function parseStartOptions(args) {
1069
1085
  return {
1070
1086
  dbPath,
1071
1087
  httpPort: Number(flag(args, "--http-port") ?? "8787"),
1072
- wsPort: Number(flag(args, "--ws-port") ?? "8788"),
1088
+ wsPort: flag(args, "--ws-port") !== undefined ? Number(flag(args, "--ws-port")) : undefined,
1073
1089
  host: flag(args, "--host"),
1074
1090
  webRoot: flag(args, "--web-root"),
1075
1091
  historyRetentionDays: retentionDays !== undefined && !Number.isNaN(retentionDays) ? retentionDays : undefined,
@@ -1085,7 +1101,8 @@ async function runRelayCli(args, io) {
1085
1101
  startOpts.webRoot = resolveBundledWebRoot();
1086
1102
  }
1087
1103
  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)"}`);
1104
+ const gatewayDesc = running.wsPort !== null ? `instance ws :${running.wsPort}` : `instance gateway: merged on http :${running.httpPort} (path / or /gateway)`;
1105
+ io.print(`xacpx-relay listening: http :${running.httpPort}, ${gatewayDesc}, db ${startOpts.dbPath}, dashboard: ${startOpts.webRoot ?? "(none)"}`);
1089
1106
  return await new Promise((resolve2) => {
1090
1107
  const shutdown = () => {
1091
1108
  running.close().then(() => resolve2(0));
@@ -1103,7 +1120,7 @@ async function runRelayCli(args, io) {
1103
1120
  const { token } = runtime.accounts.createLoginToken(acc.id, label);
1104
1121
  io.print(`access token: ${token}`);
1105
1122
  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}`);
1123
+ io.print(`hint: use this token for web login AND: xacpx channel add relay --url <host> --token ${token}`);
1107
1124
  return 0;
1108
1125
  } finally {
1109
1126
  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.1",
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"],