From 7149c7d56f00ec21a2ef1d3b398230f667d452d0 Mon Sep 17 00:00:00 2001 From: Frederic Charette Date: Tue, 28 Oct 2025 10:47:29 -0400 Subject: [PATCH 1/4] qol updates for 8.1.1 --- CHANGELOG.md | 11 +++++++++++ package.json | 24 ++++++++++++------------ packages/kalm/package.json | 2 +- packages/kalm/src/components/client.ts | 2 ++ packages/kalm/src/kalm.ts | 5 +++++ packages/ws/README.md | 2 ++ packages/ws/package.json | 2 +- packages/ws/src/ws.ts | 9 +++++++-- packages/ws/types.d.ts | 2 ++ 9 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce0a634..27bb698 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [v8.1.1] - 2025-10-28 + +commit [#](https://github.com/kalm/kalm.js/commits) + +### Minor changes (QOL) + +- added warning on misnamed config parameters +- added a client `disconnect()` method that is an alias for `destroy()` +- added a `secure` property on ws transport config for simpler wss +- throws an error on channel subscription with non-function handler + ## [v8.1.0] - 2025-10-27 commit [#](https://github.com/kalm/kalm.js/commits) diff --git a/package.json b/package.json index 4340cd1..0c73b06 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "kalm.js", "private": true, - "version": "8.1.0", + "version": "8.1.1", "description": "The socket optimizer", "main": "packages/kalm/dist/kalm.js", "scripts": { @@ -53,26 +53,26 @@ } }, "devDependencies": { - "@rollup/plugin-commonjs": "^28.0.6", - "@rollup/plugin-node-resolve": "^16.0.1", - "@rollup/plugin-sucrase": "^5.0.2", - "@rollup/plugin-typescript": "^12.1.4", - "@stylistic/eslint-plugin": "^5.2.0", + "@rollup/plugin-commonjs": "^28.0.0", + "@rollup/plugin-node-resolve": "^16.0.0", + "@rollup/plugin-sucrase": "^5.0.0", + "@rollup/plugin-typescript": "^12.3.0", + "@stylistic/eslint-plugin": "^5.5.0", "@types/jest": "^30.0.0", - "@types/node": "^24.1.0", - "eslint": "^9.32.0", + "@types/node": "^24.9.0", + "eslint": "^9.38.0", "eslint-plugin-jest": "^29.0.0", "husky": "^9.1.0", - "jest": "^30.0.0", - "rollup": "^4.46.0", + "jest": "^30.2.0", + "rollup": "^4.52.0", "rollup-plugin-polyfill-node": "^0.13.0", "snappy": "^7.3.0", "socket.io": "^4.8.0", "socket.io-client": "^4.8.0", "ts-jest": "^29.4.0", "tsx": "^4.20.3", - "typescript": "^5.8.0", - "typescript-eslint": "^8.38.0", + "typescript": "^5.9.0", + "typescript-eslint": "^8.46.0", "ws": "^8.18.3" } } diff --git a/packages/kalm/package.json b/packages/kalm/package.json index 4ef0f0c..01a6a67 100644 --- a/packages/kalm/package.json +++ b/packages/kalm/package.json @@ -1,6 +1,6 @@ { "name": "kalm", - "version": "8.1.0", + "version": "8.1.1", "description": "The socket optimizer", "main": "dist/kalm.js", "scripts": { diff --git a/packages/kalm/src/components/client.ts b/packages/kalm/src/components/client.ts index 8e5e844..d77f573 100644 --- a/packages/kalm/src/components/client.ts +++ b/packages/kalm/src/components/client.ts @@ -101,6 +101,7 @@ export function Client(params: ClientConfig, emitter: EventEmitter, socket?: any } function subscribe(channelName: string, handler: (msg: any, context: Context) => void): void { + if (!handler || typeof handler !== 'function') throw new Error(`Subscribe handler is not a function: ${handler.toString()}`); _resolveChannel(channelName).handlers.push(handler); } @@ -126,6 +127,7 @@ export function Client(params: ClientConfig, emitter: EventEmitter, socket?: any instance = Object.assign(emitter, { write, destroy, + disconnect: destroy, subscribe, unsubscribe, remote, diff --git a/packages/kalm/src/kalm.ts b/packages/kalm/src/kalm.ts index 3fbaeff..05dfecb 100644 --- a/packages/kalm/src/kalm.ts +++ b/packages/kalm/src/kalm.ts @@ -42,6 +42,11 @@ function validateOptions(options: ServerConfig): void { throw new Error('Routine is not valid, it may not have been invoked, see: https://github.com/kalm/kalm.js#documentation'); } } + + // Common misnamed parameters + if (options['hostname'] && !options.host) { + console.warn('Kalm: Option "hostname" does not exist, did you mean "host" ?'); + } } export function listen(options: ServerConfig): Server { diff --git a/packages/ws/README.md b/packages/ws/README.md index 565207f..922dc15 100644 --- a/packages/ws/README.md +++ b/packages/ws/README.md @@ -28,6 +28,8 @@ A websocket transport for the [Kalm](https://github.com/kalm/kalm.js) framework. cert?: string /** The key file content for a secure socket connection, both this and `cert` must be set */ key?: string + /** Indicates wether a server or client should use wss:// protocol. Will throw an error if set without cert or key on the server */ + secure?: boolean /** The maximum idle time for the connection before it hangs up (default: 30000) */ socketTimeout: number } diff --git a/packages/ws/package.json b/packages/ws/package.json index a313fbb..ea37a85 100644 --- a/packages/ws/package.json +++ b/packages/ws/package.json @@ -1,6 +1,6 @@ { "name": "@kalm/ws", - "version": "8.0.0", + "version": "8.1.1", "description": "WebSocket transport for Kalm", "main": "dist/ws.js", "scripts": { diff --git a/packages/ws/src/ws.ts b/packages/ws/src/ws.ts index 694fe00..87ff71a 100644 --- a/packages/ws/src/ws.ts +++ b/packages/ws/src/ws.ts @@ -6,6 +6,7 @@ type WSConfig = { cert?: string key?: string socketTimeout?: number + secure?: boolean }; type WSHandle = WebSocket & { @@ -16,12 +17,16 @@ type WSHandle = WebSocket & { _socket?: any }; -export default function ws({ cert, key, socketTimeout = 30000 }: WSConfig = {}): KalmTransport { +export default function ws({ cert, key, secure, socketTimeout = 30000 }: WSConfig = {}): KalmTransport { return function socket(params: ClientConfig, emitter: NodeJS.EventEmitter): Socket { let listener; async function bind(): Promise { if (typeof window !== 'undefined') throw new Error('Cannot create a websocket server from the browser'); + if (secure) { + if (!cert) throw new Error('Missing cert to create a secure websocket server'); + if (!key) throw new Error('Missing key to create a secure websocket server'); + } if (cert && key) { const https = await import('https'); @@ -47,7 +52,7 @@ export default function ws({ cert, key, socketTimeout = 30000 }: WSConfig = {}): } function connect(handle?: WSHandle): WSHandle { - const protocol: string = (!!cert && !!key) === true ? 'wss' : 'ws'; + const protocol: string = ((!!secure) || (!!cert && !!key)) === true ? 'wss' : 'ws'; const connection: WSHandle = handle || new (nativeAPIExists ? WebSocket : WSClient)(`${protocol}://${params.host}:${params.port}`); connection.binaryType = 'arraybuffer'; const evtType: string = nativeAPIExists ? 'addEventListener' : 'on'; diff --git a/packages/ws/types.d.ts b/packages/ws/types.d.ts index ab5aa90..70f09f7 100644 --- a/packages/ws/types.d.ts +++ b/packages/ws/types.d.ts @@ -4,6 +4,8 @@ declare module '@kalm/ws' { cert?: string /** The key file content for a secure socket connection, both this and `cert` must be set */ key?: string + /** Indicates wether a server or client should use wss:// protocol. Will throw an error if set without cert or key on the server */ + secure?: boolean /** The maximum idle time for the connection before it hangs up (default: 30000) */ socketTimeout?: number } From c471fbad23576705b92278cf375aa4fd1468eee3 Mon Sep 17 00:00:00 2001 From: Frederic Charette Date: Tue, 28 Oct 2025 12:39:52 -0400 Subject: [PATCH 2/4] updated ipc docs, added path validation, cleaned udp timeout on disconnect --- packages/ipc/README.md | 6 +++++- packages/ipc/src/ipc.ts | 13 +++++++++++++ packages/udp/src/udp.ts | 6 ++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/ipc/README.md b/packages/ipc/README.md index 24b5c0a..e1a0b07 100644 --- a/packages/ipc/README.md +++ b/packages/ipc/README.md @@ -24,8 +24,12 @@ An IPC transport for the [Kalm](https://github.com/kalm/kalm.js) framework. ``` { + /** The maximum idle time for the connection before it hangs up (default: 30000) */ socketTimeout: 30000, - path: '/tmp/app.socket' + /** The prefix to use for file handler location. Final handler is ${path + port} + Ex: '/tmp/app.socket-9001' for Mac and Linux or 'C:\Windows\Temp\app.socket-9001' on Windows + */ + path: '/tmp/app.socket-' } ``` diff --git a/packages/ipc/src/ipc.ts b/packages/ipc/src/ipc.ts index 1d49644..f9689ab 100644 --- a/packages/ipc/src/ipc.ts +++ b/packages/ipc/src/ipc.ts @@ -1,4 +1,5 @@ import net from 'node:net'; +import path from 'node:path'; interface IPCSocket extends net.Socket { server?: { @@ -17,12 +18,24 @@ type IPCConfig = { path?: string }; +function isValidPathSyntax(filePath) { + try { + path.parse(filePath); + return true; + } + catch (e) { + return e; + } +} + export default function ipc({ socketTimeout = 30000, path = '/tmp/app.socket-' }: IPCConfig = {}): KalmTransport { if (typeof window !== 'undefined') throw new Error('Cannot use IPC from the browser'); return function socket(params: ClientConfig, emitter: NodeJS.EventEmitter): Socket { let listener: net.Server; + if (isValidPathSyntax(path + params.port) !== true) throw new Error(`Invalid IPC location, path is not resolvable: ${path + params.port}`); + function bind(): void { listener = net.createServer(soc => emitter.emit('socket', soc)); listener.on('error', err => emitter.emit('error', err)); diff --git a/packages/udp/src/udp.ts b/packages/udp/src/udp.ts index 314f7ae..0d1dffe 100644 --- a/packages/udp/src/udp.ts +++ b/packages/udp/src/udp.ts @@ -4,13 +4,14 @@ type UDPSocketHandle = { socket: dgram.Socket port: number host: string + _timer?: number }; type UDPConfig = { type?: dgram.SocketType localAddr?: string reuseAddr?: boolean - socketTimeout?: number + socketTimeout?: NodeJS.Timeout }; export default function udp({ type = 'udp4', localAddr = '0.0.0.0', reuseAddr = false, socketTimeout = 30000 }: UDPConfig = {}): KalmTransport { @@ -72,6 +73,7 @@ export default function udp({ type = 'udp4', localAddr = '0.0.0.0', reuseAddr = } function disconnect(handle?: UDPSocketHandle): void { + if (handle && handle._timer) clearTimeout(handle._timer); if (handle && handle.socket) handle.socket = null; setTimeout(() => emitter.emit('disconnected'), 1); } @@ -124,7 +126,7 @@ export default function udp({ type = 'udp4', localAddr = '0.0.0.0', reuseAddr = } } - function resetTimeout(handle) { + function resetTimeout(handle: UDPSocketHandle) { clearTimeout(handle._timer); handle._timer = setTimeout(() => { disconnect(handle); From 7e0a292554a7b0889b01623a1874f989df8f05e6 Mon Sep 17 00:00:00 2001 From: Frederic Charette Date: Tue, 28 Oct 2025 12:42:05 -0400 Subject: [PATCH 3/4] removed legacy npmignore --- .npmignore | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .npmignore diff --git a/.npmignore b/.npmignore deleted file mode 100644 index b61438f..0000000 --- a/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -tests -src -examples -.gitignore -tsconfig.json -tslint.json -*.md -package-lock.json -yarn.lock -.vscode -.github -jest.config.js From 1fcd00083ae7140df569e735f1a7128d6b66c0c5 Mon Sep 17 00:00:00 2001 From: Frederic Charette Date: Tue, 28 Oct 2025 12:46:29 -0400 Subject: [PATCH 4/4] bumped ipc and udp versions --- packages/ipc/package.json | 2 +- packages/udp/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ipc/package.json b/packages/ipc/package.json index 1717c9c..d64e8b3 100644 --- a/packages/ipc/package.json +++ b/packages/ipc/package.json @@ -1,6 +1,6 @@ { "name": "@kalm/ipc", - "version": "8.0.0", + "version": "8.1.1", "description": "IPC transport for Kalm", "main": "dist/ipc.js", "scripts": { diff --git a/packages/udp/package.json b/packages/udp/package.json index f730d35..f527403 100644 --- a/packages/udp/package.json +++ b/packages/udp/package.json @@ -1,6 +1,6 @@ { "name": "@kalm/udp", - "version": "8.0.0", + "version": "8.1.1", "description": "UDP transport for Kalm", "main": "dist/udp.js", "scripts": {