@gjsify/ws 0.4.35 → 0.4.36

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.
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";function notSupportedInBrowser(e){let t=Error(`${e} is not available in the browser — ws's server surface has no browser equivalent. Use the native @gjsify/ws on GJS / Node.`);return t.code=`ENOTSUP`,t.syscall=e,t}const e=globalThis.WebSocket,t=e;var WebSocketServer=class{constructor(e,t){throw notSupportedInBrowser(`WebSocketServer`)}address(){throw notSupportedInBrowser(`WebSocketServer.address`)}close(e){throw notSupportedInBrowser(`WebSocketServer.close`)}handleUpgrade(){throw notSupportedInBrowser(`WebSocketServer.handleUpgrade`)}shouldHandle(){throw notSupportedInBrowser(`WebSocketServer.shouldHandle`)}on(e,t){throw notSupportedInBrowser(`WebSocketServer.on`)}once(e,t){throw notSupportedInBrowser(`WebSocketServer.once`)}off(e,t){throw notSupportedInBrowser(`WebSocketServer.off`)}emit(e,...t){throw notSupportedInBrowser(`WebSocketServer.emit`)}};const n=WebSocketServer;function createWebSocketStream(){throw notSupportedInBrowser(`createWebSocketStream`)}if(e){let t=e;t.WebSocket=e,t.WebSocketServer=WebSocketServer,t.Server=WebSocketServer,t.createWebSocketStream=createWebSocketStream}export{n as Server,t as WebSocket,WebSocketServer,createWebSocketStream,e as default};
@@ -1,4 +1,4 @@
1
- import"./_virtual/_rolldown/runtime.js";import"./constants.js";import{EventEmitter as e}from"@gjsify/events";import{Buffer as t}from"@gjsify/buffer";import{createHash as n}from"@gjsify/crypto";import r from"@girs/soup-3.0";import i from"@girs/glib-2.0";import a from"@girs/gio-2.0";import{ensureMainLoop as o}from"@gjsify/utils";const s=/^[+/0-9A-Za-z]{22}==$/;var ServerSideWebSocket=class extends e{static CONNECTING=0;static OPEN=1;static CLOSING=2;static CLOSED=3;CONNECTING=0;OPEN=1;CLOSING=2;CLOSED=3;readyState=1;protocol=``;extensions=``;url=``;_conn;constructor(e,n){super(),this._conn=e,this.url=n,e.connect(`message`,(e,n,i)=>{let a=i.get_data();if(n===r.WebsocketDataType.TEXT){let e=typeof a==`string`?a:a?new TextDecoder(`utf-8`).decode(a):``;this.emit(`message`,e,!1)}else{let e=a?t.from(a):t.alloc(0);this.emit(`message`,e,!0)}}),e.connect(`closed`,()=>{this.readyState=3;let n=e.get_close_code()||1005,r=e.get_close_data()||``;this.emit(`close`,n,t.from(r))}),e.connect(`error`,(e,t)=>{this.emit(`error`,Error(t.message))})}send(e,n,a){let o=typeof n==`function`?n:a;try{if(typeof e==`string`){let t=new TextEncoder().encode(e);this._conn.send_message(r.WebsocketDataType.TEXT,new i.Bytes(t))}else{let n;if(t.isBuffer(e)){let t=e;n=new i.Bytes(new Uint8Array(t.buffer,t.byteOffset,t.byteLength))}else if(e instanceof ArrayBuffer)n=new i.Bytes(new Uint8Array(e));else if(ArrayBuffer.isView(e)){let t=e;n=new i.Bytes(new Uint8Array(t.buffer,t.byteOffset,t.byteLength))}else throw TypeError(`Unsupported send() payload type`);this._conn.send_message(r.WebsocketDataType.BINARY,n)}o&&queueMicrotask(()=>o())}catch(e){let t=e instanceof Error?e:Error(String(e));queueMicrotask(o?()=>o(t):()=>this.emit(`error`,t))}}close(e,n){if(!(this.readyState===3||this.readyState===2)){this.readyState=2;try{let r=n===void 0?null:t.isBuffer(n)?n.toString(`utf8`):String(n);this._conn.close(e??1e3,r)}catch(e){this.emit(`error`,e instanceof Error?e:Error(String(e)))}}}terminate(){if(this.readyState!==3){this.readyState=2;try{this._conn.close(1006,null)}catch{}}}},WebSocketServer=class extends e{options;clients=new Set;path;_server=null;_address=null;constructor(e={},t){if(super(),this.options=e,this.path=e.path??`/`,e.noServer){if(e.port!==void 0||e.server!==void 0)throw Error(`ws.WebSocketServer: { noServer: true } is mutually exclusive with port and server.`);t&&this.once(`listening`,t);return}if(e.port===void 0&&!e.server)throw Error(`ws.WebSocketServer requires either options.port or options.server on Gjs.`);t&&this.once(`listening`,t),this._start(e)}_buildVerifyClientInfo(e){let t=e.get_request_headers(),n={};t.foreach((e,t)=>{let r=e.toLowerCase(),i=n[r];i===void 0?n[r]=t:Array.isArray(i)?i.push(t):n[r]=[i,t]});let r=e.get_uri(),i=r.get_path()??`/`,o=r.get_query(),s=o?`${i}?${o}`:i,c=e.get_remote_host()??`127.0.0.1`,l=e.get_remote_address(),u=l instanceof a.InetSocketAddress?l.get_port():0;return{origin:n.origin??``,secure:!1,req:{method:e.get_method(),url:s,headers:n,socket:{remoteAddress:c,remotePort:u}}}}_setupHandlers(e,t){if(t.verifyClient){let n=t.verifyClient;e.add_handler(this.path,(e,t)=>{if((t.get_request_headers().get_one(`Upgrade`)??``).toLowerCase()!==`websocket`)return;let r=this._buildVerifyClientInfo(t);n.length>=2?(t.pause(),n(r,(e,n=401)=>{e||t.set_status(n,null),t.unpause()})):n(r)||t.set_status(401,null)})}e.add_websocket_handler(this.path,null,null,(e,n,r,i)=>{let a=new ServerSideWebSocket(i,n.get_uri()?.to_string()??this.path);if(t.handleProtocols){let e=n.get_request_headers().get_one(`Sec-WebSocket-Protocol`)??``,r=new Set(e.split(`,`).map(e=>e.trim()).filter(Boolean)),i=this._buildVerifyClientInfo(n).req,o=t.handleProtocols(r,i);o&&(a.protocol=o)}t.clientTracking!==!1&&(this.clients.add(a),a.on(`close`,()=>this.clients.delete(a))),this.emit(`connection`,a,n)})}_start(e){try{if(e.server){let t=e.server,n=t.soupServer;if(!n)throw Error(`options.server has no active Soup.Server. Ensure httpServer.listen() was called before creating WebSocketServer.`);this._server=n,this._setupHandlers(n,e),o();let r=t.address();r&&(this._address={address:r.address,family:r.family,port:r.port}),queueMicrotask(()=>this.emit(`listening`))}else{this._server=new r.Server({}),this._setupHandlers(this._server,e);let t=e.host??`0.0.0.0`,n=e.port;t===`127.0.0.1`||t===`localhost`?this._server.listen_local(n,r.ServerListenOptions.IPV4_ONLY):t===`::1`?this._server.listen_local(n,r.ServerListenOptions.IPV6_ONLY):this._server.listen_all(n,0);let i=this._server.get_listeners(),a=n;if(i&&i.length>0){let e=i[0].get_local_address();e&&typeof e.get_port==`function`&&(a=e.get_port())}o(),this._address={address:t,family:`IPv4`,port:a},queueMicrotask(()=>this.emit(`listening`))}}catch(e){queueMicrotask(()=>this.emit(`error`,e instanceof Error?e:Error(String(e))))}}address(){return this._address}close(e){try{for(let e of this.clients)e.close();this.clients.clear(),this.options.server||this._server?.disconnect(),this._server=null,this._address=null,this.emit(`close`),e&&queueMicrotask(()=>e())}catch(t){let n=t instanceof Error?t:Error(String(t));this.emit(`error`,n),e&&queueMicrotask(()=>e(n))}}handleUpgrade(e,t,n,r){if(!this._validateUpgradeHeaders(e,t))return;let i=e.headers?.[`sec-websocket-key`]??``,doUpgrade=()=>this._completeUpgrade(e,t,i,r);if(this.options.verifyClient){let n=this.options.verifyClient,r=this._buildVerifyClientInfoFromReq(e);if(n.length>=2){n(r,(e,n=401)=>{if(!e){this._abortHandshake(t,n);return}doUpgrade()});return}if(!n(r)){this._abortHandshake(t,401);return}}doUpgrade()}shouldHandle(e){if(this.path===`/`)return!0;let t=e?.url??`/`;return t===this.path||t.startsWith(this.path+`?`)||t.startsWith(this.path+`/`)}_validateUpgradeHeaders(e,t){let n=e.headers??{};if(e.method!==`GET`)return this._abortHandshake(t,405),!1;if((n.upgrade??``).toLowerCase()!==`websocket`||!s.test(n[`sec-websocket-key`]??``))return this._abortHandshake(t,400),!1;let r=Number(n[`sec-websocket-version`]??`0`);return r!==13&&r!==8?(this._abortHandshake(t,426),!1):this.shouldHandle(e)?!0:(this._abortHandshake(t,400),!1)}_completeUpgrade(e,t,a,o){let s=[`HTTP/1.1 101 Switching Protocols`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Accept: ${n(`sha1`).update(a+`258EAFA5-E914-47DA-95CA-C5AB0DC85B11`).digest(`base64`)}`],c=null;if(this.options.handleProtocols){let t=e.headers?.[`sec-websocket-protocol`]??``,n=new Set(t.split(`,`).map(e=>e.trim()).filter(Boolean)),r=this.options.handleProtocols(n,this._buildVerifyClientInfoFromReq(e).req);r&&(c=r,s.push(`Sec-WebSocket-Protocol: ${r}`))}this.emit(`headers`,s,e);let l=s.join(`\r
1
+ import"./_virtual/_rolldown/runtime.js";import"./constants.js";import{EventEmitter as e}from"@gjsify/events";import{Buffer as t}from"@gjsify/buffer";import{createHash as n}from"@gjsify/crypto";import r from"@girs/soup-3.0";import i from"@girs/glib-2.0";import a from"@girs/gio-2.0";import{ensureMainLoop as o}from"@gjsify/utils";const s=/^[+/0-9A-Za-z]{22}==$/;var ServerSideWebSocket=class extends e{static CONNECTING=0;static OPEN=1;static CLOSING=2;static CLOSED=3;CONNECTING=0;OPEN=1;CLOSING=2;CLOSED=3;readyState=1;protocol=``;extensions=``;url=``;_conn;constructor(e,n){super(),this._conn=e,this.url=n,e.connect(`message`,(e,n,i)=>{let a=i.get_data();if(n===r.WebsocketDataType.TEXT){let e=typeof a==`string`?a:a?new TextDecoder(`utf-8`).decode(a):``;this.emit(`message`,e,!1)}else{let e=a?t.from(a):t.alloc(0);this.emit(`message`,e,!0)}}),e.connect(`closed`,()=>{this.readyState=3;let n=e.get_close_code()||1005,r=e.get_close_data()||``;this.emit(`close`,n,t.from(r))}),e.connect(`error`,(e,t)=>{this.emit(`error`,Error(t.message))})}send(e,n,a){let o=typeof n==`function`?n:a;try{if(typeof e==`string`){let t=new TextEncoder().encode(e);this._conn.send_message(r.WebsocketDataType.TEXT,new i.Bytes(t))}else{let n;if(t.isBuffer(e)){let t=e;n=new i.Bytes(new Uint8Array(t.buffer,t.byteOffset,t.byteLength))}else if(e instanceof ArrayBuffer)n=new i.Bytes(new Uint8Array(e));else if(ArrayBuffer.isView(e)){let t=e;n=new i.Bytes(new Uint8Array(t.buffer,t.byteOffset,t.byteLength))}else throw TypeError(`Unsupported send() payload type`);this._conn.send_message(r.WebsocketDataType.BINARY,n)}o&&queueMicrotask(()=>o())}catch(e){let t=e instanceof Error?e:Error(String(e));queueMicrotask(o?()=>o(t):()=>this.emit(`error`,t))}}close(e,n){if(!(this.readyState===3||this.readyState===2)){this.readyState=2;try{let r=n===void 0?null:t.isBuffer(n)?n.toString(`utf8`):String(n);this._conn.close(e??1e3,r)}catch(e){this.emit(`error`,e instanceof Error?e:Error(String(e)))}}}terminate(){if(this.readyState!==3){this.readyState=2;try{this._conn.close(1006,null)}catch{}}}},WebSocketServer=class extends e{options;clients=new Set;path;_server=null;_address=null;constructor(e={},t){if(super(),this.options=e,this.path=e.path??`/`,e.noServer){if(e.port!==void 0||e.server!==void 0)throw Error(`ws.WebSocketServer: { noServer: true } is mutually exclusive with port and server.`);t&&this.once(`listening`,t);return}if(e.port===void 0&&!e.server)throw Error(`ws.WebSocketServer requires either options.port or options.server on Gjs.`);t&&this.once(`listening`,t),this._start(e)}_buildVerifyClientInfo(e){let t=e.get_request_headers(),n={};t.foreach((e,t)=>{let r=e.toLowerCase(),i=n[r];i===void 0?n[r]=t:Array.isArray(i)?i.push(t):n[r]=[i,t]});let r=e.get_uri(),i=r.get_path()??`/`,o=r.get_query(),s=o?`${i}?${o}`:i,c=e.get_remote_host()??`127.0.0.1`,l=e.get_remote_address(),u=l instanceof a.InetSocketAddress?l.get_port():0;return{origin:n.origin??``,secure:!1,req:{method:e.get_method(),url:s,headers:n,socket:{remoteAddress:c,remotePort:u}}}}_setupHandlers(e,t){try{e.remove_websocket_extension(r.WebsocketExtensionDeflate.$gtype)}catch{}if(t.verifyClient){let n=t.verifyClient;e.add_handler(this.path,(e,t)=>{if((t.get_request_headers().get_one(`Upgrade`)??``).toLowerCase()!==`websocket`)return;let r=this._buildVerifyClientInfo(t);n.length>=2?(t.pause(),n(r,(e,n=401)=>{e||t.set_status(n,null),t.unpause()})):n(r)||t.set_status(401,null)})}e.add_websocket_handler(this.path,null,null,(e,n,r,i)=>{let a=new ServerSideWebSocket(i,n.get_uri()?.to_string()??this.path);if(t.handleProtocols){let e=n.get_request_headers().get_one(`Sec-WebSocket-Protocol`)??``,r=new Set(e.split(`,`).map(e=>e.trim()).filter(Boolean)),i=this._buildVerifyClientInfo(n).req,o=t.handleProtocols(r,i);o&&(a.protocol=o)}t.clientTracking!==!1&&(this.clients.add(a),a.on(`close`,()=>this.clients.delete(a))),this.emit(`connection`,a,n)})}_start(e){try{if(e.server){let t=e.server,n=t.soupServer;if(!n)throw Error(`options.server has no active Soup.Server. Ensure httpServer.listen() was called before creating WebSocketServer.`);this._server=n,this._setupHandlers(n,e),o();let r=t.address();r&&(this._address={address:r.address,family:r.family,port:r.port}),queueMicrotask(()=>this.emit(`listening`))}else{this._server=new r.Server({}),this._setupHandlers(this._server,e);let t=e.host??`0.0.0.0`,n=e.port;t===`127.0.0.1`||t===`localhost`?this._server.listen_local(n,r.ServerListenOptions.IPV4_ONLY):t===`::1`?this._server.listen_local(n,r.ServerListenOptions.IPV6_ONLY):this._server.listen_all(n,0);let i=this._server.get_listeners(),a=n;if(i&&i.length>0){let e=i[0].get_local_address();e&&typeof e.get_port==`function`&&(a=e.get_port())}o(),this._address={address:t,family:`IPv4`,port:a},queueMicrotask(()=>this.emit(`listening`))}}catch(e){queueMicrotask(()=>this.emit(`error`,e instanceof Error?e:Error(String(e))))}}address(){return this._address}close(e){try{for(let e of this.clients)e.close();this.clients.clear(),this.options.server||this._server?.disconnect(),this._server=null,this._address=null,this.emit(`close`),e&&queueMicrotask(()=>e())}catch(t){let n=t instanceof Error?t:Error(String(t));this.emit(`error`,n),e&&queueMicrotask(()=>e(n))}}handleUpgrade(e,t,n,r){if(!this._validateUpgradeHeaders(e,t))return;let i=e.headers?.[`sec-websocket-key`]??``,doUpgrade=()=>this._completeUpgrade(e,t,i,r);if(this.options.verifyClient){let n=this.options.verifyClient,r=this._buildVerifyClientInfoFromReq(e);if(n.length>=2){n(r,(e,n=401)=>{if(!e){this._abortHandshake(t,n);return}doUpgrade()});return}if(!n(r)){this._abortHandshake(t,401);return}}doUpgrade()}shouldHandle(e){if(this.path===`/`)return!0;let t=e?.url??`/`;return t===this.path||t.startsWith(this.path+`?`)||t.startsWith(this.path+`/`)}_validateUpgradeHeaders(e,t){let n=e.headers??{};if(e.method!==`GET`)return this._abortHandshake(t,405),!1;if((n.upgrade??``).toLowerCase()!==`websocket`||!s.test(n[`sec-websocket-key`]??``))return this._abortHandshake(t,400),!1;let r=Number(n[`sec-websocket-version`]??`0`);return r!==13&&r!==8?(this._abortHandshake(t,426),!1):this.shouldHandle(e)?!0:(this._abortHandshake(t,400),!1)}_completeUpgrade(e,t,a,o){let s=[`HTTP/1.1 101 Switching Protocols`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Accept: ${n(`sha1`).update(a+`258EAFA5-E914-47DA-95CA-C5AB0DC85B11`).digest(`base64`)}`],c=null;if(this.options.handleProtocols){let t=e.headers?.[`sec-websocket-protocol`]??``,n=new Set(t.split(`,`).map(e=>e.trim()).filter(Boolean)),r=this.options.handleProtocols(n,this._buildVerifyClientInfoFromReq(e).req);r&&(c=r,s.push(`Sec-WebSocket-Protocol: ${r}`))}this.emit(`headers`,s,e);let l=s.join(`\r
2
2
  `)+`\r
3
3
  \r
4
4
  `;t.write(l,()=>{let n=typeof t._releaseIOStream==`function`?t._releaseIOStream():null;if(!n){t.destroy?.();return}let a=e.url??`/`,s=i.Uri.parse(`ws://localhost${a}`,i.UriFlags.NONE),l=new ServerSideWebSocket(r.WebsocketConnection.new(n,s,r.WebsocketConnectionType.SERVER,null,c,[]),a);c&&(l.protocol=c),this.options.clientTracking!==!1&&(this.clients.add(l),l.on(`close`,()=>this.clients.delete(l))),o(l,e)})}_abortHandshake(e,t){let n={400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,405:`Method Not Allowed`,426:`Upgrade Required`}[t]??`Error`;e.write?.(`HTTP/1.1 ${t} ${n}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n`,()=>{e.destroy?.()})}_buildVerifyClientInfoFromReq(e){let t=e.headers??{};return{origin:t.origin??``,secure:!1,req:{method:e.method??`GET`,url:e.url??`/`,headers:t,socket:{remoteAddress:e.socket?.remoteAddress??`127.0.0.1`,remotePort:e.socket?.remotePort??0}}}}};export{WebSocketServer};
@@ -0,0 +1,16 @@
1
+ declare const _NativeWebSocket: any;
2
+ export declare const WebSocket: any;
3
+ export default _NativeWebSocket;
4
+ export declare class WebSocketServer {
5
+ constructor(_options?: unknown, _callback?: () => void);
6
+ address(): never;
7
+ close(_cb?: (err?: Error) => void): never;
8
+ handleUpgrade(): never;
9
+ shouldHandle(): never;
10
+ on(_event: string, _listener: (...args: unknown[]) => void): never;
11
+ once(_event: string, _listener: (...args: unknown[]) => void): never;
12
+ off(_event: string, _listener: (...args: unknown[]) => void): never;
13
+ emit(_event: string, ..._args: unknown[]): never;
14
+ }
15
+ export declare const Server: typeof WebSocketServer;
16
+ export declare function createWebSocketStream(): never;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/ws",
3
- "version": "0.4.35",
3
+ "version": "0.4.36",
4
4
  "description": "Drop-in replacement for the `ws` npm package on Gjs — wraps globalThis.WebSocket (Soup.WebsocketConnection) and Soup.Server for the WebSocketServer side",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -9,6 +9,10 @@
9
9
  ".": {
10
10
  "types": "./lib/types/index.d.ts",
11
11
  "default": "./lib/esm/index.js"
12
+ },
13
+ "./browser": {
14
+ "types": "./lib/types/browser.d.ts",
15
+ "default": "./lib/esm/browser.js"
12
16
  }
13
17
  },
14
18
  "files": [
@@ -34,26 +38,36 @@
34
38
  "websocket"
35
39
  ],
36
40
  "dependencies": {
37
- "@girs/gio-2.0": "2.88.0-4.0.1",
38
- "@girs/glib-2.0": "2.88.0-4.0.1",
39
- "@girs/soup-3.0": "3.6.6-4.0.1",
40
- "@gjsify/buffer": "^0.4.35",
41
- "@gjsify/crypto": "^0.4.35",
42
- "@gjsify/events": "^0.4.35",
43
- "@gjsify/utils": "^0.4.35",
44
- "@gjsify/websocket": "^0.4.35"
41
+ "@girs/gio-2.0": "2.88.0-4.0.4",
42
+ "@girs/glib-2.0": "2.88.0-4.0.4",
43
+ "@girs/soup-3.0": "3.6.6-4.0.4",
44
+ "@gjsify/buffer": "^0.4.36",
45
+ "@gjsify/crypto": "^0.4.36",
46
+ "@gjsify/events": "^0.4.36",
47
+ "@gjsify/utils": "^0.4.36",
48
+ "@gjsify/websocket": "^0.4.36"
45
49
  },
46
50
  "devDependencies": {
47
- "@gjsify/cli": "^0.4.35",
48
- "@gjsify/unit": "^0.4.35",
51
+ "@gjsify/cli": "^0.4.36",
52
+ "@gjsify/unit": "^0.4.36",
49
53
  "@types/node": "^25.9.1",
50
- "typescript": "^6.0.3"
54
+ "typescript": "^5.9.3"
51
55
  },
52
56
  "gjsify": {
53
57
  "runtimes": {
54
58
  "gjs": "polyfill",
55
59
  "node": "none",
56
- "browser": "none"
60
+ "browser": "partial"
57
61
  }
58
- }
62
+ },
63
+ "license": "MIT",
64
+ "repository": {
65
+ "type": "git",
66
+ "url": "git+https://github.com/gjsify/gjsify.git",
67
+ "directory": "packages/node/ws"
68
+ },
69
+ "bugs": {
70
+ "url": "https://github.com/gjsify/gjsify/issues"
71
+ },
72
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/node/ws#readme"
59
73
  }