elit 3.5.0 → 3.5.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.
Files changed (58) hide show
  1. package/README.md +80 -2
  2. package/dist/build.d.mts +1 -1
  3. package/dist/cli.js +178 -54
  4. package/dist/config.d.mts +1 -1
  5. package/dist/coverage.d.mts +1 -1
  6. package/dist/http.d.ts.map +1 -1
  7. package/dist/http.js +5 -4
  8. package/dist/http.js.map +1 -1
  9. package/dist/http.mjs +5 -4
  10. package/dist/http.mjs.map +1 -1
  11. package/dist/https.js +5 -4
  12. package/dist/https.js.map +1 -1
  13. package/dist/https.mjs +5 -4
  14. package/dist/https.mjs.map +1 -1
  15. package/dist/index.d.mts +1 -1
  16. package/dist/index.js +20 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +20 -1
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/native.js +20 -1
  21. package/dist/native.js.map +1 -1
  22. package/dist/native.mjs +20 -1
  23. package/dist/native.mjs.map +1 -1
  24. package/dist/{server-DpnTyF7I.d.mts → server--YFoC6ln.d.mts} +27 -0
  25. package/dist/{server-BU71N4fk.d.ts → server-DacsdjFJ.d.ts} +27 -0
  26. package/dist/server.d.mts +1 -1
  27. package/dist/server.d.ts.map +1 -1
  28. package/dist/server.js +141 -52
  29. package/dist/server.js.map +1 -1
  30. package/dist/server.mjs +141 -52
  31. package/dist/server.mjs.map +1 -1
  32. package/dist/state.d.ts.map +1 -1
  33. package/dist/state.js +20 -1
  34. package/dist/state.js.map +1 -1
  35. package/dist/state.mjs +20 -1
  36. package/dist/state.mjs.map +1 -1
  37. package/dist/types.d.mts +28 -1
  38. package/dist/types.d.ts +27 -0
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/types.js.map +1 -1
  41. package/dist/ws.d.mts +1 -1
  42. package/dist/ws.d.ts +1 -1
  43. package/dist/ws.d.ts.map +1 -1
  44. package/dist/ws.js +9 -4
  45. package/dist/ws.js.map +1 -1
  46. package/dist/ws.mjs +9 -4
  47. package/dist/ws.mjs.map +1 -1
  48. package/dist/wss.js +14 -8
  49. package/dist/wss.js.map +1 -1
  50. package/dist/wss.mjs +14 -8
  51. package/dist/wss.mjs.map +1 -1
  52. package/package.json +1 -1
  53. package/src/cli.ts +18 -0
  54. package/src/http.ts +5 -4
  55. package/src/server.ts +182 -56
  56. package/src/state.ts +25 -1
  57. package/src/types.ts +30 -0
  58. package/src/ws.ts +12 -5
package/README.md CHANGED
@@ -9,7 +9,7 @@ The package is split by runtime. Browser-facing APIs live in `elit` and the clie
9
9
  If you are generating or editing code for Elit, follow these rules first:
10
10
 
11
11
  - Use `elit` or the client subpaths for browser UI code.
12
- - Use `elit/server` for HTTP routes, middleware, dev server, preview server, and server-side shared state.
12
+ - Use `elit/server` for HTTP routes, WebSocket endpoints, middleware, dev server, preview server, and server-side shared state.
13
13
  - Use `elit/desktop` only inside `elit desktop ...` runtime. Those APIs are injected by the native desktop runtime and are not normal browser globals.
14
14
  - Use `elit/build` for programmatic bundling.
15
15
  - Use `elit/database` for the VM-backed file database helpers.
@@ -62,7 +62,7 @@ Use this table as the import map for generated code.
62
62
  | `elit/state` | Reactive state and render helpers | `createState`, `computed`, `reactive`, `text`, `bindValue`, `bindChecked`, `createSharedState` |
63
63
  | `elit/style` | CSS generation and injection | `CreateStyle`, `styles`, `renderStyle`, `injectStyle`, `addClass`, `addTag` |
64
64
  | `elit/router` | Client-side routing | `createRouter`, `createRouterView`, `routerLink` |
65
- | `elit/server` | HTTP router, dev server, middleware, shared server state | `ServerRouter`, `createDevServer`, `cors`, `logger`, `rateLimit`, `compress`, `security`, `StateManager` |
65
+ | `elit/server` | HTTP router, dev server, middleware, WebSocket endpoints, shared server state | `ServerRouter`, `createDevServer`, `cors`, `logger`, `rateLimit`, `compress`, `security`, `StateManager` |
66
66
  | `elit/build` | Programmatic build API | `build` |
67
67
  | `elit/desktop` | Native desktop window APIs | `createWindow`, `createWindowServer`, `onMessage`, `windowQuit`, `windowSetTitle`, `windowEval` |
68
68
  | `elit/database` | VM-backed file database | `Database`, `create`, `read`, `save`, `update`, `rename`, `remove` |
@@ -412,6 +412,17 @@ export default {
412
412
  basePath: '',
413
413
  ssr: () => documentShell,
414
414
  api,
415
+ ws: [
416
+ {
417
+ path: '/ws',
418
+ handler: ({ ws, query }) => {
419
+ ws.send(JSON.stringify({ type: 'connected', room: query.room || 'general' }));
420
+ ws.on('message', (message) => {
421
+ ws.send(message.toString());
422
+ });
423
+ },
424
+ },
425
+ ],
415
426
  },
416
427
  ],
417
428
  },
@@ -431,6 +442,14 @@ export default {
431
442
  root: './dist',
432
443
  index: './index.html',
433
444
  port: 4173,
445
+ ws: [
446
+ {
447
+ path: '/ws',
448
+ handler: ({ ws }) => {
449
+ ws.on('message', (message) => ws.send(message.toString()));
450
+ },
451
+ },
452
+ ],
434
453
  },
435
454
  test: {
436
455
  include: ['testing/unit/**/*.test.ts'],
@@ -477,6 +496,12 @@ export default {
477
496
  };
478
497
  ```
479
498
 
499
+ Notes:
500
+
501
+ - `dev.ws` and `preview.ws` register global WebSocket endpoints.
502
+ - `clients[].ws` registers client-specific endpoints and prefixes each path with that client's `basePath`.
503
+ - The internal Elit HMR and shared-state socket uses `/__elit_ws`, so do not reuse that path for custom endpoints.
504
+
480
505
  Important details:
481
506
 
482
507
  - `build` may be a single object or an array. If it is an array, all builds run sequentially.
@@ -620,6 +645,49 @@ const server = createDevServer({
620
645
  console.log(server.url);
621
646
  ```
622
647
 
648
+ ### Custom WebSocket Endpoints
649
+
650
+ Server:
651
+
652
+ ```ts
653
+ import { createDevServer } from 'elit/server';
654
+
655
+ const server = createDevServer({
656
+ root: '.',
657
+ open: false,
658
+ ws: [
659
+ {
660
+ path: '/ws',
661
+ handler: ({ ws, query }) => {
662
+ ws.send(JSON.stringify({ type: 'connected', room: query.room || 'general' }));
663
+
664
+ ws.on('message', (message) => {
665
+ ws.send(message.toString());
666
+ });
667
+ },
668
+ },
669
+ ],
670
+ });
671
+ ```
672
+
673
+ Client:
674
+
675
+ ```ts
676
+ const socket = new WebSocket(`ws://${location.host}/ws?room=general`);
677
+
678
+ socket.addEventListener('message', (event) => {
679
+ console.log(event.data);
680
+ });
681
+
682
+ socket.send('hello');
683
+ ```
684
+
685
+ Notes:
686
+
687
+ - Use `dev.ws` or `preview.ws` for global endpoints.
688
+ - Use `clients[].ws` when each client should expose its own endpoint under its `basePath`.
689
+ - Do not use `/__elit_ws`; Elit reserves that path for internal HMR and shared-state traffic.
690
+
623
691
  ### Shared State Between Server and Client
624
692
 
625
693
  Client:
@@ -801,6 +869,16 @@ npx elit test --coverage --coverage-reporter text,html
801
869
 
802
870
  The package also exports `elit/test`, `elit/test-runtime`, and `elit/test-reporter` for advanced use, but most users should stay on the CLI.
803
871
 
872
+ ## Changelog
873
+
874
+ Latest release notes live in [CHANGELOG.md](CHANGELOG.md).
875
+
876
+ Highlights in `v3.5.1`:
877
+
878
+ - Added first-class custom WebSocket endpoints for `dev`, `preview`, and `clients[]` config.
879
+ - Moved internal HMR and shared-state traffic to `/__elit_ws` so custom endpoints do not collide with Elit internals.
880
+ - Tightened cross-runtime WebSocket path matching so root endpoints no longer swallow every upgrade request.
881
+
804
882
  ## Good Defaults For Generated Code
805
883
 
806
884
  When writing new Elit code, these defaults are usually correct:
package/dist/build.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { B as BuildOptions, a as BuildResult } from './server-DpnTyF7I.mjs';
1
+ import { B as BuildOptions, a as BuildResult } from './server--YFoC6ln.mjs';
2
2
  import './http.mjs';
3
3
  import 'node:events';
4
4
  import './ws.mjs';
package/dist/cli.js CHANGED
@@ -1183,11 +1183,12 @@ var init_http = __esm({
1183
1183
  },
1184
1184
  fetch: (req) => {
1185
1185
  const urlObj = new URL(req.url);
1186
- const pathname = urlObj.pathname + urlObj.search;
1186
+ const pathname = urlObj.pathname;
1187
+ const requestUrl = urlObj.pathname + urlObj.search;
1187
1188
  const upgradeHeader = req.headers.get("upgrade");
1188
1189
  if (upgradeHeader && upgradeHeader.toLowerCase() === "websocket") {
1189
1190
  const matchingWebSocketServer = Array.from(this._bunWebSocketServers).find((wsServer) => {
1190
- return !wsServer.path || wsServer.path === "/" || wsServer.path === pathname;
1191
+ return !wsServer.path || wsServer.path === pathname;
1191
1192
  });
1192
1193
  if (!matchingWebSocketServer) {
1193
1194
  return new Response("WebSocket path not found", { status: 404 });
@@ -1201,7 +1202,7 @@ var init_http = __esm({
1201
1202
  wsServer: matchingWebSocketServer,
1202
1203
  request: {
1203
1204
  method: req.method,
1204
- url: pathname,
1205
+ url: requestUrl,
1205
1206
  headers: requestHeaders,
1206
1207
  socket: { remoteAddress: void 0 }
1207
1208
  }
@@ -1219,7 +1220,7 @@ var init_http = __esm({
1219
1220
  let responseReady = false;
1220
1221
  const incomingMessage = {
1221
1222
  method: req.method,
1222
- url: pathname,
1223
+ url: requestUrl,
1223
1224
  headers: req.headers,
1224
1225
  httpVersion: "1.1",
1225
1226
  rawHeaders: [],
@@ -59399,7 +59400,7 @@ var require_package3 = __commonJS({
59399
59400
  "package.json"(exports2, module2) {
59400
59401
  module2.exports = {
59401
59402
  name: "elit",
59402
- version: "3.5.0",
59403
+ version: "3.5.1",
59403
59404
  description: "Optimized lightweight library for creating DOM elements with reactive state",
59404
59405
  main: "dist/index.js",
59405
59406
  module: "dist/index.mjs",
@@ -59886,6 +59887,10 @@ function createNativeWebSocket(url, protocols) {
59886
59887
  }
59887
59888
  return new globalThis.WebSocket(url, protocols);
59888
59889
  }
59890
+ function getRequestPath(url) {
59891
+ const [pathname = "/"] = (url || "/").split("?");
59892
+ return pathname || "/";
59893
+ }
59889
59894
  var WebSocket2 = class extends import_events2.EventEmitter {
59890
59895
  constructor(address, protocols, _options) {
59891
59896
  super();
@@ -59982,7 +59987,7 @@ var WebSocketServer = class extends import_events2.EventEmitter {
59982
59987
  this.clients = /* @__PURE__ */ new Set();
59983
59988
  this._ownsHttpServer = false;
59984
59989
  this.options = options || {};
59985
- this.path = options?.path || "/";
59990
+ this.path = options?.path;
59986
59991
  if (runtime === "node") {
59987
59992
  if (options?.server) {
59988
59993
  this._httpServer = options.server;
@@ -60009,8 +60014,9 @@ var WebSocketServer = class extends import_events2.EventEmitter {
60009
60014
  }
60010
60015
  _setupUpgradeHandler() {
60011
60016
  this._httpServer.on("upgrade", (request3, socket, head) => {
60012
- console.log("[WebSocket] Upgrade request:", request3.url, "Expected:", this.path);
60013
- if (this.path && this.path !== "/" && request3.url !== this.path) {
60017
+ const requestPath = getRequestPath(request3.url);
60018
+ console.log("[WebSocket] Upgrade request:", requestPath, "Expected:", this.path || "(any)");
60019
+ if (this.path && requestPath !== this.path) {
60014
60020
  console.log("[WebSocket] Path mismatch, ignoring");
60015
60021
  return;
60016
60022
  }
@@ -60254,7 +60260,7 @@ var WebSocketServer = class extends import_events2.EventEmitter {
60254
60260
  * Check if server should handle request
60255
60261
  */
60256
60262
  shouldHandle(request3) {
60257
- if (this.path && request3.url !== this.path) {
60263
+ if (this.path && getRequestPath(request3.url) !== this.path) {
60258
60264
  return false;
60259
60265
  }
60260
60266
  return true;
@@ -61368,7 +61374,8 @@ var createElitImportMap = async (rootDir, basePath = "", mode = "dev") => {
61368
61374
  const allImports = { ...externalImports, ...elitImports };
61369
61375
  return `<script type="importmap">${JSON.stringify({ imports: allImports }, null, 2)}</script>`;
61370
61376
  };
61371
- var createHMRScript = (port, wsPath) => `<script>(function(){let ws;let retries=0;let maxRetries=5;function connect(){ws=new WebSocket('ws://'+window.location.hostname+':${port}${wsPath}');ws.onopen=()=>{console.log('[Elit HMR] Connected');retries=0};ws.onmessage=(e)=>{const d=JSON.parse(e.data);if(d.type==='update'){console.log('[Elit HMR] File updated:',d.path);window.location.reload()}else if(d.type==='reload'){console.log('[Elit HMR] Reloading...');window.location.reload()}else if(d.type==='error')console.error('[Elit HMR] Error:',d.error)};ws.onclose=()=>{if(retries<maxRetries){retries++;setTimeout(connect,1000*retries)}else if(retries===maxRetries){console.log('[Elit HMR] Connection closed. Start dev server to reconnect.')}};ws.onerror=()=>{ws.close()}}connect()})();</script>`;
61377
+ var ELIT_INTERNAL_WS_PATH = "/__elit_ws";
61378
+ var createHMRScript = (port) => `<script>(function(){let ws;let retries=0;let maxRetries=5;const protocol=window.location.protocol==='https:'?'wss://':'ws://';function connect(){ws=new WebSocket(protocol+window.location.hostname+':${port}${ELIT_INTERNAL_WS_PATH}');ws.onopen=()=>{console.log('[Elit HMR] Connected');retries=0};ws.onmessage=(e)=>{const d=JSON.parse(e.data);if(d.type==='update'){console.log('[Elit HMR] File updated:',d.path);window.location.reload()}else if(d.type==='reload'){console.log('[Elit HMR] Reloading...');window.location.reload()}else if(d.type==='error')console.error('[Elit HMR] Error:',d.error)};ws.onclose=()=>{if(retries<maxRetries){retries++;setTimeout(connect,1000*retries)}else if(retries===maxRetries){console.log('[Elit HMR] Connection closed. Start dev server to reconnect.')}};ws.onerror=()=>{ws.close()}}connect()})();</script>`;
61372
61379
  var rewriteRelativePaths = (html, basePath) => {
61373
61380
  if (!basePath) return html;
61374
61381
  html = html.replace(/(<script[^>]+src=["'])(?!https?:\/\/|\/)(\.\/)?([^"']+)(["'])/g, `$1${basePath}/$3$4`);
@@ -61376,6 +61383,52 @@ var rewriteRelativePaths = (html, basePath) => {
61376
61383
  return html;
61377
61384
  };
61378
61385
  var normalizeBasePath = (basePath) => basePath && basePath !== "/" ? basePath : "";
61386
+ var normalizeWebSocketPath = (path) => {
61387
+ let normalizedPath = path.trim();
61388
+ if (!normalizedPath) {
61389
+ return "/";
61390
+ }
61391
+ if (!normalizedPath.startsWith("/")) {
61392
+ normalizedPath = `/${normalizedPath}`;
61393
+ }
61394
+ if (normalizedPath.length > 1 && normalizedPath.endsWith("/")) {
61395
+ normalizedPath = normalizedPath.slice(0, -1);
61396
+ }
61397
+ return normalizedPath;
61398
+ };
61399
+ var getRequestPath2 = (url) => {
61400
+ const [pathname = "/"] = url.split("?");
61401
+ return pathname || "/";
61402
+ };
61403
+ var parseRequestQuery = (url) => {
61404
+ const query = {};
61405
+ const queryString = url.split("?")[1];
61406
+ if (!queryString) {
61407
+ return query;
61408
+ }
61409
+ for (const entry of queryString.split("&")) {
61410
+ if (!entry) {
61411
+ continue;
61412
+ }
61413
+ const [rawKey, rawValue = ""] = entry.split("=");
61414
+ if (!rawKey) {
61415
+ continue;
61416
+ }
61417
+ query[decodeURIComponent(rawKey)] = decodeURIComponent(rawValue);
61418
+ }
61419
+ return query;
61420
+ };
61421
+ var normalizeWebSocketEndpoints = (endpoints, basePath = "") => {
61422
+ const normalizedBasePath = normalizeBasePath(basePath);
61423
+ return (endpoints || []).map((endpoint) => {
61424
+ const normalizedPath = normalizeWebSocketPath(endpoint.path);
61425
+ const fullPath = !normalizedBasePath ? normalizedPath : normalizedPath === normalizedBasePath || normalizedPath.startsWith(`${normalizedBasePath}/`) ? normalizedPath : normalizedPath === "/" ? normalizedBasePath : `${normalizedBasePath}${normalizedPath}`;
61426
+ return {
61427
+ path: fullPath,
61428
+ handler: endpoint.handler
61429
+ };
61430
+ });
61431
+ };
61379
61432
  var requestAcceptsGzip = (acceptEncoding) => {
61380
61433
  if (Array.isArray(acceptEncoding)) {
61381
61434
  return acceptEncoding.some((value) => /\bgzip\b/i.test(value));
@@ -61804,7 +61857,8 @@ function createDevServer(options) {
61804
61857
  if (config.mode === "dev") {
61805
61858
  clearImportMapCache();
61806
61859
  }
61807
- const clientsToNormalize = config.clients?.length ? config.clients : config.root ? [{ root: config.root, basePath: config.basePath || "", index: config.index, ssr: config.ssr, api: config.api, proxy: config.proxy, mode: config.mode }] : null;
61860
+ const usesClientArray = Boolean(config.clients?.length);
61861
+ const clientsToNormalize = usesClientArray ? config.clients : config.root ? [{ root: config.root, basePath: config.basePath || "", index: config.index, ssr: config.ssr, api: config.api, proxy: config.proxy, ws: config.ws, mode: config.mode }] : null;
61808
61862
  if (!clientsToNormalize) throw new Error('DevServerOptions must include either "clients" array or "root" directory');
61809
61863
  const normalizedClients = clientsToNormalize.map((client) => {
61810
61864
  let basePath = client.basePath || "";
@@ -61826,10 +61880,23 @@ function createDevServer(options) {
61826
61880
  index: indexPath,
61827
61881
  ssr: client.ssr,
61828
61882
  api: client.api,
61883
+ ws: normalizeWebSocketEndpoints(client.ws, basePath),
61829
61884
  proxyHandler: client.proxy ? createProxyHandler(client.proxy) : void 0,
61830
61885
  mode: client.mode || "dev"
61831
61886
  };
61832
61887
  });
61888
+ const globalWebSocketEndpoints = usesClientArray ? normalizeWebSocketEndpoints(config.ws) : [];
61889
+ const normalizedWebSocketEndpoints = [...normalizedClients.flatMap((client) => client.ws), ...globalWebSocketEndpoints];
61890
+ const seenWebSocketPaths = /* @__PURE__ */ new Set();
61891
+ for (const endpoint of normalizedWebSocketEndpoints) {
61892
+ if (endpoint.path === ELIT_INTERNAL_WS_PATH) {
61893
+ throw new Error(`WebSocket path "${ELIT_INTERNAL_WS_PATH}" is reserved for Elit internals`);
61894
+ }
61895
+ if (seenWebSocketPaths.has(endpoint.path)) {
61896
+ throw new Error(`Duplicate WebSocket endpoint path: ${endpoint.path}`);
61897
+ }
61898
+ seenWebSocketPaths.add(endpoint.path);
61899
+ }
61833
61900
  const globalProxyHandler = config.proxy ? createProxyHandler(config.proxy) : null;
61834
61901
  const server = createServer(async (req, res) => {
61835
61902
  const originalUrl = req.url || "/";
@@ -62146,8 +62213,7 @@ ${error}`);
62146
62213
  }
62147
62214
  }
62148
62215
  if (ext === ".html") {
62149
- const wsPath = normalizeBasePath(client.basePath);
62150
- const hmrScript = config.mode !== "preview" ? createHMRScript(config.port, wsPath) : "";
62216
+ const hmrScript = config.mode !== "preview" ? createHMRScript(config.port) : "";
62151
62217
  let html = content.toString();
62152
62218
  let ssrStyles = "";
62153
62219
  if (client.ssr) {
@@ -62246,7 +62312,7 @@ ${elitImportMap}`;
62246
62312
  }
62247
62313
  const basePath = normalizeBasePath(client.basePath);
62248
62314
  html = rewriteRelativePaths(html, basePath);
62249
- const hmrScript = config.mode !== "preview" ? createHMRScript(config.port, basePath) : "";
62315
+ const hmrScript = config.mode !== "preview" ? createHMRScript(config.port) : "";
62250
62316
  const elitImportMap = await createElitImportMap(client.root, basePath, client.mode);
62251
62317
  const modeScript = config.mode === "preview" ? "<script>window.__ELIT_MODE__='preview';</script>\n" : "";
62252
62318
  html = html.includes("</head>") ? html.replace("</head>", `${modeScript}${elitImportMap}</head>`) : html;
@@ -62266,49 +62332,73 @@ ${elitImportMap}`;
62266
62332
  send500(res, "500 SSR Error");
62267
62333
  }
62268
62334
  }
62269
- let wss = null;
62270
- if (config.mode !== "preview") {
62271
- wss = new WebSocketServer({ server });
62335
+ const wss = new WebSocketServer({ server, path: ELIT_INTERNAL_WS_PATH });
62336
+ const webSocketServers = [wss];
62337
+ if (config.logging) {
62338
+ console.log(`[WebSocket] Internal server initialized at ${ELIT_INTERNAL_WS_PATH}`);
62339
+ }
62340
+ wss.on("connection", (ws, req) => {
62341
+ wsClients.add(ws);
62342
+ const message = { type: "connected", timestamp: Date.now() };
62343
+ ws.send(JSON.stringify(message));
62272
62344
  if (config.logging) {
62273
- console.log("[HMR] WebSocket server initialized");
62345
+ console.log("[WebSocket] Internal client connected from", req.socket.remoteAddress);
62274
62346
  }
62275
- wss.on("connection", (ws, req) => {
62276
- wsClients.add(ws);
62277
- const message = { type: "connected", timestamp: Date.now() };
62278
- ws.send(JSON.stringify(message));
62279
- if (config.logging) {
62280
- console.log("[HMR] Client connected from", req.socket.remoteAddress);
62281
- }
62282
- ws.on("message", (data) => {
62283
- try {
62284
- const msg = JSON.parse(data.toString());
62285
- if (msg.type === "state:subscribe") {
62286
- stateManager.subscribe(msg.key, ws);
62287
- if (config.logging) {
62288
- console.log(`[State] Client subscribed to "${msg.key}"`);
62289
- }
62290
- } else if (msg.type === "state:unsubscribe") {
62291
- stateManager.unsubscribe(msg.key, ws);
62292
- if (config.logging) {
62293
- console.log(`[State] Client unsubscribed from "${msg.key}"`);
62294
- }
62295
- } else if (msg.type === "state:change") {
62296
- stateManager.handleStateChange(msg.key, msg.value);
62297
- if (config.logging) {
62298
- console.log(`[State] Client updated "${msg.key}"`);
62299
- }
62347
+ ws.on("message", (data) => {
62348
+ try {
62349
+ const msg = JSON.parse(data.toString());
62350
+ if (msg.type === "state:subscribe") {
62351
+ stateManager.subscribe(msg.key, ws);
62352
+ if (config.logging) {
62353
+ console.log(`[State] Client subscribed to "${msg.key}"`);
62300
62354
  }
62301
- } catch (error) {
62355
+ } else if (msg.type === "state:unsubscribe") {
62356
+ stateManager.unsubscribe(msg.key, ws);
62357
+ if (config.logging) {
62358
+ console.log(`[State] Client unsubscribed from "${msg.key}"`);
62359
+ }
62360
+ } else if (msg.type === "state:change") {
62361
+ stateManager.handleStateChange(msg.key, msg.value);
62302
62362
  if (config.logging) {
62303
- console.error("[WebSocket] Message parse error:", error);
62363
+ console.log(`[State] Client updated "${msg.key}"`);
62304
62364
  }
62305
62365
  }
62306
- });
62307
- ws.on("close", () => {
62308
- wsClients.delete(ws);
62309
- stateManager.unsubscribeAll(ws);
62366
+ } catch (error) {
62310
62367
  if (config.logging) {
62311
- console.log("[HMR] Client disconnected");
62368
+ console.error("[WebSocket] Message parse error:", error);
62369
+ }
62370
+ }
62371
+ });
62372
+ ws.on("close", () => {
62373
+ wsClients.delete(ws);
62374
+ stateManager.unsubscribeAll(ws);
62375
+ if (config.logging) {
62376
+ console.log("[WebSocket] Internal client disconnected");
62377
+ }
62378
+ });
62379
+ });
62380
+ for (const endpoint of normalizedWebSocketEndpoints) {
62381
+ const endpointServer = new WebSocketServer({ server, path: endpoint.path });
62382
+ webSocketServers.push(endpointServer);
62383
+ if (config.logging) {
62384
+ console.log(`[WebSocket] Endpoint ready at ${endpoint.path}`);
62385
+ }
62386
+ endpointServer.on("connection", (ws, req) => {
62387
+ const requestUrl = req.url || endpoint.path;
62388
+ const ctx = {
62389
+ ws,
62390
+ req,
62391
+ path: getRequestPath2(requestUrl),
62392
+ query: parseRequestQuery(requestUrl),
62393
+ headers: req.headers
62394
+ };
62395
+ void Promise.resolve(endpoint.handler(ctx)).catch((error) => {
62396
+ if (config.logging) {
62397
+ console.error(`[WebSocket] Endpoint error at ${endpoint.path}:`, error);
62398
+ }
62399
+ try {
62400
+ ws.close(CLOSE_CODES.INTERNAL_ERROR, "Internal Server Error");
62401
+ } catch {
62312
62402
  }
62313
62403
  });
62314
62404
  });
@@ -62392,9 +62482,8 @@ ${elitImportMap}`;
62392
62482
  isClosing = true;
62393
62483
  if (config.logging) console.log("\n[Server] Shutting down...");
62394
62484
  if (watcher) await watcher.close();
62395
- if (wss) {
62396
- wss.close();
62397
- wsClients.forEach((client) => client.close());
62485
+ if (webSocketServers.length > 0) {
62486
+ webSocketServers.forEach((wsServer) => wsServer.close());
62398
62487
  wsClients.clear();
62399
62488
  }
62400
62489
  return new Promise((resolve8) => {
@@ -62718,7 +62807,26 @@ var import_esbuild2 = require("esbuild");
62718
62807
 
62719
62808
  // src/state.ts
62720
62809
  var ELIT_NATIVE_BINDING = /* @__PURE__ */ Symbol.for("elit.native.binding");
62810
+ var ELIT_INTERNAL_WS_PATH2 = "/__elit_ws";
62721
62811
  var createState = (initial, options) => dom.createState(initial, options);
62812
+ function resolveSharedStateWebSocketUrl(wsUrl) {
62813
+ const protocol = typeof location !== "undefined" && location.protocol === "https:" ? "wss:" : "ws:";
62814
+ const origin = typeof location !== "undefined" ? `${protocol}//${location.host}` : `${protocol}//localhost`;
62815
+ if (!wsUrl) {
62816
+ return `${origin}${ELIT_INTERNAL_WS_PATH2}`;
62817
+ }
62818
+ if (/^wss?:\/\//i.test(wsUrl)) {
62819
+ const parsedUrl = new URL(wsUrl);
62820
+ if (!parsedUrl.pathname || parsedUrl.pathname === "/") {
62821
+ parsedUrl.pathname = ELIT_INTERNAL_WS_PATH2;
62822
+ }
62823
+ return parsedUrl.toString();
62824
+ }
62825
+ if (wsUrl.startsWith("/")) {
62826
+ return `${origin}${wsUrl}`;
62827
+ }
62828
+ return wsUrl;
62829
+ }
62722
62830
  var SharedState2 = class {
62723
62831
  constructor(key, defaultValue, wsUrl) {
62724
62832
  this.key = key;
@@ -62770,7 +62878,7 @@ var SharedState2 = class {
62770
62878
  */
62771
62879
  connect() {
62772
62880
  if (typeof window === "undefined") return;
62773
- const url = this.wsUrl || `ws://${location.host}`;
62881
+ const url = resolveSharedStateWebSocketUrl(this.wsUrl);
62774
62882
  this.ws = new WebSocket(url);
62775
62883
  this.ws.addEventListener("open", () => {
62776
62884
  this.subscribe();
@@ -78676,6 +78784,9 @@ async function runPreview(args) {
78676
78784
  if (mergedOptions.api) {
78677
78785
  options.api = mergedOptions.api;
78678
78786
  }
78787
+ if (mergedOptions.ws && mergedOptions.ws.length > 0) {
78788
+ options.ws = mergedOptions.ws;
78789
+ }
78679
78790
  if (mergedOptions.https) {
78680
78791
  options.https = mergedOptions.https;
78681
78792
  }
@@ -79021,6 +79132,7 @@ Preview Options:
79021
79132
  Note: Preview mode has full feature parity with dev mode:
79022
79133
  - Single root and multi-client configurations (use clients[] in config)
79023
79134
  - REST API endpoints (use api option in config)
79135
+ - WebSocket endpoints (use ws option in config)
79024
79136
  - Proxy forwarding and Web Workers
79025
79137
  - HTTPS support, custom middleware, and SSR
79026
79138
 
@@ -79091,6 +79203,18 @@ API Configuration:
79091
79203
  1. Client-specific API routes are matched first (defined in clients[].api)
79092
79204
  2. Global API routes are matched second (defined in dev.api or preview.api)
79093
79205
 
79206
+ WebSocket Configuration:
79207
+ Configure WebSocket endpoints per client or globally.
79208
+ Supports both global configuration and client-specific configuration.
79209
+
79210
+ Options:
79211
+ - path: Upgrade path to match (required, e.g., '/ws', '/chat')
79212
+ - handler: Connection handler invoked with { ws, req, path, query, headers }
79213
+
79214
+ Priority:
79215
+ 1. Client-specific endpoints are prefixed with the client's basePath (defined in clients[].ws)
79216
+ 2. Global endpoints listen exactly as configured (defined in dev.ws or preview.ws)
79217
+
79094
79218
  Examples:
79095
79219
  elit dev
79096
79220
  elit dev --port 8080
package/dist/config.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as DevServerOptions, B as BuildOptions, P as PreviewOptions, T as TestOptions } from './server-DpnTyF7I.mjs';
1
+ import { D as DevServerOptions, B as BuildOptions, P as PreviewOptions, T as TestOptions } from './server--YFoC6ln.mjs';
2
2
  import './http.mjs';
3
3
  import 'node:events';
4
4
  import './ws.mjs';
@@ -1,4 +1,4 @@
1
- import { b as TestCoverageReporter } from './server-DpnTyF7I.mjs';
1
+ import { b as TestCoverageReporter } from './server--YFoC6ln.mjs';
2
2
  import './http.mjs';
3
3
  import 'node:events';
4
4
  import './ws.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/http.js CHANGED
@@ -424,11 +424,12 @@ var Server = class extends import_node_events.EventEmitter {
424
424
  },
425
425
  fetch: (req) => {
426
426
  const urlObj = new URL(req.url);
427
- const pathname = urlObj.pathname + urlObj.search;
427
+ const pathname = urlObj.pathname;
428
+ const requestUrl = urlObj.pathname + urlObj.search;
428
429
  const upgradeHeader = req.headers.get("upgrade");
429
430
  if (upgradeHeader && upgradeHeader.toLowerCase() === "websocket") {
430
431
  const matchingWebSocketServer = Array.from(this._bunWebSocketServers).find((wsServer) => {
431
- return !wsServer.path || wsServer.path === "/" || wsServer.path === pathname;
432
+ return !wsServer.path || wsServer.path === pathname;
432
433
  });
433
434
  if (!matchingWebSocketServer) {
434
435
  return new Response("WebSocket path not found", { status: 404 });
@@ -442,7 +443,7 @@ var Server = class extends import_node_events.EventEmitter {
442
443
  wsServer: matchingWebSocketServer,
443
444
  request: {
444
445
  method: req.method,
445
- url: pathname,
446
+ url: requestUrl,
446
447
  headers: requestHeaders,
447
448
  socket: { remoteAddress: void 0 }
448
449
  }
@@ -460,7 +461,7 @@ var Server = class extends import_node_events.EventEmitter {
460
461
  let responseReady = false;
461
462
  const incomingMessage = {
462
463
  method: req.method,
463
- url: pathname,
464
+ url: requestUrl,
464
465
  headers: req.headers,
465
466
  httpVersion: "1.1",
466
467
  rawHeaders: [],