herdr-remote-relay 0.3.26 → 0.3.28

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.
Files changed (105) hide show
  1. package/dist/relay-server.d.ts +3 -0
  2. package/dist/relay-server.js +3 -1
  3. package/dist/server/http-api.d.ts +1 -0
  4. package/dist/server/http-api.js +12 -7
  5. package/dist/server/types.d.ts +2 -0
  6. package/package.json +1 -1
  7. package/web/dist/assets/index-BxVyQeOw.js +61 -0
  8. package/web/dist/assets/index-CI0UHcI0.css +32 -0
  9. package/web/dist/fonts/maple-mono/OFL.txt +93 -0
  10. package/web/dist/fonts/maple-mono/maple-mono-cjk-0-400.woff2 +0 -0
  11. package/web/dist/fonts/maple-mono/maple-mono-cjk-0-700.woff2 +0 -0
  12. package/web/dist/fonts/maple-mono/maple-mono-cjk-1-400.woff2 +0 -0
  13. package/web/dist/fonts/maple-mono/maple-mono-cjk-1-700.woff2 +0 -0
  14. package/web/dist/fonts/maple-mono/maple-mono-cjk-10-400.woff2 +0 -0
  15. package/web/dist/fonts/maple-mono/maple-mono-cjk-10-700.woff2 +0 -0
  16. package/web/dist/fonts/maple-mono/maple-mono-cjk-11-400.woff2 +0 -0
  17. package/web/dist/fonts/maple-mono/maple-mono-cjk-11-700.woff2 +0 -0
  18. package/web/dist/fonts/maple-mono/maple-mono-cjk-12-400.woff2 +0 -0
  19. package/web/dist/fonts/maple-mono/maple-mono-cjk-12-700.woff2 +0 -0
  20. package/web/dist/fonts/maple-mono/maple-mono-cjk-13-400.woff2 +0 -0
  21. package/web/dist/fonts/maple-mono/maple-mono-cjk-13-700.woff2 +0 -0
  22. package/web/dist/fonts/maple-mono/maple-mono-cjk-14-400.woff2 +0 -0
  23. package/web/dist/fonts/maple-mono/maple-mono-cjk-14-700.woff2 +0 -0
  24. package/web/dist/fonts/maple-mono/maple-mono-cjk-15-400.woff2 +0 -0
  25. package/web/dist/fonts/maple-mono/maple-mono-cjk-15-700.woff2 +0 -0
  26. package/web/dist/fonts/maple-mono/maple-mono-cjk-16-400.woff2 +0 -0
  27. package/web/dist/fonts/maple-mono/maple-mono-cjk-16-700.woff2 +0 -0
  28. package/web/dist/fonts/maple-mono/maple-mono-cjk-17-400.woff2 +0 -0
  29. package/web/dist/fonts/maple-mono/maple-mono-cjk-17-700.woff2 +0 -0
  30. package/web/dist/fonts/maple-mono/maple-mono-cjk-18-400.woff2 +0 -0
  31. package/web/dist/fonts/maple-mono/maple-mono-cjk-18-700.woff2 +0 -0
  32. package/web/dist/fonts/maple-mono/maple-mono-cjk-19-400.woff2 +0 -0
  33. package/web/dist/fonts/maple-mono/maple-mono-cjk-19-700.woff2 +0 -0
  34. package/web/dist/fonts/maple-mono/maple-mono-cjk-2-400.woff2 +0 -0
  35. package/web/dist/fonts/maple-mono/maple-mono-cjk-2-700.woff2 +0 -0
  36. package/web/dist/fonts/maple-mono/maple-mono-cjk-3-400.woff2 +0 -0
  37. package/web/dist/fonts/maple-mono/maple-mono-cjk-3-700.woff2 +0 -0
  38. package/web/dist/fonts/maple-mono/maple-mono-cjk-4-400.woff2 +0 -0
  39. package/web/dist/fonts/maple-mono/maple-mono-cjk-4-700.woff2 +0 -0
  40. package/web/dist/fonts/maple-mono/maple-mono-cjk-5-400.woff2 +0 -0
  41. package/web/dist/fonts/maple-mono/maple-mono-cjk-5-700.woff2 +0 -0
  42. package/web/dist/fonts/maple-mono/maple-mono-cjk-6-400.woff2 +0 -0
  43. package/web/dist/fonts/maple-mono/maple-mono-cjk-6-700.woff2 +0 -0
  44. package/web/dist/fonts/maple-mono/maple-mono-cjk-7-400.woff2 +0 -0
  45. package/web/dist/fonts/maple-mono/maple-mono-cjk-7-700.woff2 +0 -0
  46. package/web/dist/fonts/maple-mono/maple-mono-cjk-8-400.woff2 +0 -0
  47. package/web/dist/fonts/maple-mono/maple-mono-cjk-8-700.woff2 +0 -0
  48. package/web/dist/fonts/maple-mono/maple-mono-cjk-9-400.woff2 +0 -0
  49. package/web/dist/fonts/maple-mono/maple-mono-cjk-9-700.woff2 +0 -0
  50. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-0-400.woff2 +0 -0
  51. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-0-700.woff2 +0 -0
  52. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-1-400.woff2 +0 -0
  53. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-1-700.woff2 +0 -0
  54. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-10-400.woff2 +0 -0
  55. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-10-700.woff2 +0 -0
  56. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-11-400.woff2 +0 -0
  57. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-11-700.woff2 +0 -0
  58. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-12-400.woff2 +0 -0
  59. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-12-700.woff2 +0 -0
  60. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-13-400.woff2 +0 -0
  61. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-13-700.woff2 +0 -0
  62. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-14-400.woff2 +0 -0
  63. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-14-700.woff2 +0 -0
  64. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-2-400.woff2 +0 -0
  65. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-2-700.woff2 +0 -0
  66. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-3-400.woff2 +0 -0
  67. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-3-700.woff2 +0 -0
  68. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-4-400.woff2 +0 -0
  69. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-4-700.woff2 +0 -0
  70. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-5-400.woff2 +0 -0
  71. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-5-700.woff2 +0 -0
  72. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-6-400.woff2 +0 -0
  73. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-6-700.woff2 +0 -0
  74. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-7-400.woff2 +0 -0
  75. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-7-700.woff2 +0 -0
  76. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-8-400.woff2 +0 -0
  77. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-8-700.woff2 +0 -0
  78. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-9-400.woff2 +0 -0
  79. package/web/dist/fonts/maple-mono/maple-mono-cjk-rare-9-700.woff2 +0 -0
  80. package/web/dist/fonts/maple-mono/maple-mono-icons-0-400.woff2 +0 -0
  81. package/web/dist/fonts/maple-mono/maple-mono-icons-1-400.woff2 +0 -0
  82. package/web/dist/fonts/maple-mono/maple-mono-icons-10-400.woff2 +0 -0
  83. package/web/dist/fonts/maple-mono/maple-mono-icons-11-400.woff2 +0 -0
  84. package/web/dist/fonts/maple-mono/maple-mono-icons-12-400.woff2 +0 -0
  85. package/web/dist/fonts/maple-mono/maple-mono-icons-13-400.woff2 +0 -0
  86. package/web/dist/fonts/maple-mono/maple-mono-icons-14-400.woff2 +0 -0
  87. package/web/dist/fonts/maple-mono/maple-mono-icons-15-400.woff2 +0 -0
  88. package/web/dist/fonts/maple-mono/maple-mono-icons-16-400.woff2 +0 -0
  89. package/web/dist/fonts/maple-mono/maple-mono-icons-17-400.woff2 +0 -0
  90. package/web/dist/fonts/maple-mono/maple-mono-icons-2-400.woff2 +0 -0
  91. package/web/dist/fonts/maple-mono/maple-mono-icons-3-400.woff2 +0 -0
  92. package/web/dist/fonts/maple-mono/maple-mono-icons-4-400.woff2 +0 -0
  93. package/web/dist/fonts/maple-mono/maple-mono-icons-5-400.woff2 +0 -0
  94. package/web/dist/fonts/maple-mono/maple-mono-icons-6-400.woff2 +0 -0
  95. package/web/dist/fonts/maple-mono/maple-mono-icons-7-400.woff2 +0 -0
  96. package/web/dist/fonts/maple-mono/maple-mono-icons-8-400.woff2 +0 -0
  97. package/web/dist/fonts/maple-mono/maple-mono-icons-9-400.woff2 +0 -0
  98. package/web/dist/fonts/maple-mono/maple-mono-latin-400.woff2 +0 -0
  99. package/web/dist/fonts/maple-mono/maple-mono-latin-700.woff2 +0 -0
  100. package/web/dist/fonts/maple-mono/maple-mono-symbols-400.woff2 +0 -0
  101. package/web/dist/fonts/maple-mono/maple-mono-symbols-700.woff2 +0 -0
  102. package/web/dist/fonts/maple-mono/maple-mono.css +992 -0
  103. package/web/dist/index.html +5 -2
  104. package/web/dist/assets/index-BeveQ9Di.js +0 -61
  105. package/web/dist/assets/index-XYYRsgSb.css +0 -32
@@ -21,6 +21,8 @@ export interface RelayServerOptions {
21
21
  devLatencyMs?: number | string;
22
22
  metrics?: RelayMetrics;
23
23
  auth?: AuthStore;
24
+ /** The built web client to serve; defaults to the package's `web/dist`. */
25
+ publicDir?: string;
24
26
  }
25
27
  export type RelayAddress = {
26
28
  host: string;
@@ -47,6 +49,7 @@ declare class RelayServer implements RelayContext {
47
49
  trustProxy: boolean;
48
50
  devLatencyMs: number;
49
51
  devDelayMs: number;
52
+ publicDir: string;
50
53
  sendQueues: WeakMap<RelaySocket, SendQueue>;
51
54
  activeDelayTimers: Set<NodeJS.Timeout>;
52
55
  auth: AuthStore;
@@ -10,7 +10,7 @@ import { PROTOCOL_VERSION, WS_CLIENT_PATH, WS_HOST_PATH } from './protocol/index
10
10
  import { DEFAULTS, defaultStateDir, loadRelayConfig } from './relay-config.js';
11
11
  import { handleClientConnection } from './server/client-channel.js';
12
12
  import { handleHostConnection } from './server/host-channel.js';
13
- import { handleHttp } from './server/http-api.js';
13
+ import { handleHttp, PUBLIC_DIR } from './server/http-api.js';
14
14
  import { heartbeat, sweep } from './server/maintenance.js';
15
15
  import { isAllowedOrigin } from './server/requests.js';
16
16
  import { detachClient, detachHost } from './server/sessions.js';
@@ -35,6 +35,7 @@ class RelayServer {
35
35
  trustProxy;
36
36
  devLatencyMs;
37
37
  devDelayMs;
38
+ publicDir;
38
39
  sendQueues = new WeakMap();
39
40
  activeDelayTimers = new Set();
40
41
  auth;
@@ -57,6 +58,7 @@ class RelayServer {
57
58
  this.password = options.password ?? auth.password ?? null;
58
59
  this.adminToken = options.adminToken ?? auth.adminToken ?? null;
59
60
  this.trustProxy = Boolean(options.trustProxy ?? relay.trustProxy);
61
+ this.publicDir = path.resolve(options.publicDir ?? PUBLIC_DIR);
60
62
  // Development-only artificial latency switch for local responsiveness profiling.
61
63
  // When unset or 0, this incurs zero overhead and avoids entering the delayed path.
62
64
  // RELAY_DEV_LATENCY_MS specifies round-trip delay, so each one-way leg
@@ -1,3 +1,4 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import type { RelayContext } from './types.js';
3
+ export declare const PUBLIC_DIR: string;
3
4
  export declare function handleHttp(relay: RelayContext, req: IncomingMessage, res: ServerResponse): void;
@@ -10,7 +10,8 @@ import { detachDeviceSessions } from './sessions.js';
10
10
  import { isOpen } from './sockets.js';
11
11
  import { statusSnapshot } from './status.js';
12
12
  import { VERSION } from './version.js';
13
- const PUBLIC_DIR = path.join(PACKAGE_ROOT, 'web', 'dist');
13
+ export const PUBLIC_DIR = path.join(PACKAGE_ROOT, 'web', 'dist');
14
+ const FONT_CACHE_SECONDS = 7 * 24 * 60 * 60;
14
15
  const MIME_TYPES = {
15
16
  '.html': 'text/html; charset=utf-8',
16
17
  '.js': 'text/javascript; charset=utf-8',
@@ -179,21 +180,21 @@ export function handleHttp(relay, req, res) {
179
180
  sendError(res, 404, 'not_found', 'API route not found');
180
181
  return;
181
182
  }
182
- serveStatic(pathname, res);
183
+ serveStatic(relay.publicDir, pathname, res);
183
184
  }
184
- function serveStatic(requestPath, res) {
185
+ function serveStatic(publicDir, requestPath, res) {
185
186
  const relative = requestPath === '/' || requestPath === '/admin'
186
187
  ? 'index.html'
187
188
  : requestPath.replace(/^\/+/, '');
188
- const candidate = path.resolve(PUBLIC_DIR, relative);
189
- if (!candidate.startsWith(`${PUBLIC_DIR}${path.sep}`) &&
190
- candidate !== path.join(PUBLIC_DIR, 'index.html')) {
189
+ const candidate = path.resolve(publicDir, relative);
190
+ if (!candidate.startsWith(`${publicDir}${path.sep}`) &&
191
+ candidate !== path.join(publicDir, 'index.html')) {
191
192
  sendError(res, 403, 'forbidden', 'path is not allowed');
192
193
  return;
193
194
  }
194
195
  fs.readFile(candidate, (error, data) => {
195
196
  if (error && !path.extname(relative)) {
196
- fs.readFile(path.join(PUBLIC_DIR, 'index.html'), (fallbackError, fallbackData) => {
197
+ fs.readFile(path.join(publicDir, 'index.html'), (fallbackError, fallbackData) => {
197
198
  if (fallbackError) {
198
199
  sendError(res, 503, 'web_not_built', 'frontend has not been built');
199
200
  return;
@@ -209,6 +210,10 @@ function serveStatic(requestPath, res) {
209
210
  }
210
211
  const extension = path.extname(candidate).toLowerCase();
211
212
  setResponseHeaders(res, MIME_TYPES[extension] || 'application/octet-stream');
213
+ // The bundled fonts run to megabytes and only change with a release; a
214
+ // week is short enough that a font upgrade still arrives.
215
+ if (relative.startsWith('fonts/'))
216
+ res.setHeader('Cache-Control', `public, max-age=${FONT_CACHE_SECONDS}`);
212
217
  res.end(data);
213
218
  });
214
219
  }
@@ -118,6 +118,8 @@ export interface RelayContext {
118
118
  trustProxy: boolean;
119
119
  devLatencyMs: number;
120
120
  devDelayMs: number;
121
+ /** Where the built web client is served from. */
122
+ publicDir: string;
121
123
  sendQueues: WeakMap<RelaySocket, SendQueue>;
122
124
  activeDelayTimers: Set<NodeJS.Timeout>;
123
125
  finishHandshake(ws: RelaySocket): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "herdr-remote-relay",
3
- "version": "0.3.26",
3
+ "version": "0.3.28",
4
4
  "description": "Standalone relay server and web terminal for Herdr Remote",
5
5
  "license": "MIT",
6
6
  "type": "module",