Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/master-status.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [20.x, 22.x, 24.x]
node-version: [22.x, 24.x]

steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [20.x, 22.x, 24.x]
node-version: [22.x, 24.x]

steps:
- uses: actions/checkout@v1
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,31 @@ packages/ipc/bin
packages/tcp/bin
packages/udp/bin
packages/ws/bin
packages/webtransport/bin

# distribution code
packages/kalm/dist
packages/ipc/dist
packages/tcp/dist
packages/udp/dist
packages/ws/dist
packages/webtransport/dist

# publish-only files
packages/kalm/LICENSE
packages/ipc/LICENSE
packages/tcp/LICENSE
packages/udp/LICENSE
packages/ws/LICENSE
packages/webtransport/LICENSE

packages/kalm/CHANGELOG.md
packages/ipc/CHANGELOG.md
packages/tcp/CHANGELOG.md
packages/udp/CHANGELOG.md
packages/ws/CHANGELOG.md
packages/webtransport/CHANGELOG.md

packages/kalm/types.d.ts
localhost.crt
localhost.key
fingerprint.hex
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
# Changelog

## [v8.2.1] - 2026-01-29
## [v9.0.0] - 2026-04-06

commit [#](https://github.com/kalm/kalm.js/commits)

### Breaking changes

- Updated bundling output to ES modules.
- Bumped engine requirements to Node 22.
- Changed the default host from 0.0.0.0 to 127.0.0.1 for [security reasons](https://superuser.com/a/949429).

### New features

- Added WebTransport support through the `@kalm/webtransport` module. This is experimental and uses a 3rd party module for the server side (node:quic is still unstable at the time of publishing).
-


## [v8.2.1] - 2026-01-29

commit [094aa1c](https://github.com/kalm/kalm.js/commit/094aa1c0c64cf074d24e311e0096fc83af05ce90)

### Minor changes

- Added a optional generic type for `subscribe` methods' expected body.
Expand Down
6 changes: 0 additions & 6 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import eslint from '@eslint/js';
import { globalIgnores } from 'eslint/config';
import tseslint from 'typescript-eslint';
import jestConfig from 'eslint-plugin-jest';
import spacing from '@stylistic/eslint-plugin';

export default tseslint.config(
eslint.configs.recommended,
tseslint.configs.recommended,
jestConfig.configs['flat/recommended'],
spacing.configs.recommended,
{
rules: {
'@stylistic/semi': [2, 'always'],
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-require-imports': 1,
'jest/no-done-callback': 0,
'jest/no-conditional-expect': 0,
},
},
globalIgnores(['**/bin', '**/dist', '**/*.js']),
Expand Down
4 changes: 2 additions & 2 deletions examples/binary_compression/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { compressSync, uncompress } from 'snappy';

/**
* Creates a kalm client that uses the Websocket transport.
* It will attempt to connect to a server located at the address '0.0.0.0' on port 3938.
* It will attempt to connect to a server located at the address '127.0.0.1' on port 3938.
*
* The realtime routine will emit messages as soon as possible. While this is ideal in a few scenarios, for instance when the client does not send a lot of events,
* it does not leverage the benefits of buffering and may cause slowdowns if many messages are sent rapidly.
Expand All @@ -15,7 +15,7 @@ const client = connect({
transport: ws({}),
json: false,
port: 3938,
host: '0.0.0.0',
host: '127.0.0.1',
routine: routines.realtime(),
});

Expand Down
4 changes: 2 additions & 2 deletions examples/binary_compression/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { compressSync, uncompress } from 'snappy';

/**
* Creates a kalm server that uses the Websocket transport.
* It is bound to local IP 0.0.0.0 and listens on port 3938.
* It is bound to local IP 127.0.0.1 and listens on port 3938.
*
* The tick routine will emit messages to clients at a frequency no higher than 5hz, or no shorter than 20ms
*
Expand All @@ -17,7 +17,7 @@ const provider = listen({
port: 3938,
json: false,
routine: routines.tick({ hz: 5 }),
host: '0.0.0.0',
host: '127.0.0.1',
});

/**
Expand Down
2 changes: 1 addition & 1 deletion examples/browser_peer_to_peer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
*/
function advertise() {
gossip = kalm.connect({
host: '0.0.0.0',
host: '127.0.0.1',
port: 9001,
transport: ws(),
routine: kalm.routines.realtime()
Expand Down
4 changes: 2 additions & 2 deletions examples/browser_peer_to_peer/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const ws = require('../../packages/ws');

/**
* Creates a kalm server that uses the Websocket transport.
* It is bound to local IP 0.0.0.0 and listens on port 9001.
* It is bound to local IP 127.0.0.1 and listens on port 9001.
*
* The realtime routine will emit messages to clients as soon as possible
*
Expand All @@ -14,7 +14,7 @@ const Server = kalm.listen({
port: 9001,
transport: ws(),
routine: kalm.routines.realtime(),
host: '0.0.0.0',
host: '127.0.0.1',
});

Server.on('connection', (client) => {
Expand Down
12 changes: 6 additions & 6 deletions examples/distributed_pub_sub/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ Launch any number of servers first, using process arguments to specify the hosts
<hostname> <port> <seed_hostname> <seed_port>

```
node ./server.js 0.0.0.0 3000 0.0.0.0 3000
node ./server.js 0.0.0.0 3001 0.0.0.0 3000
node ./server.js 0.0.0.0 3002 0.0.0.0 3000
node ./server.js 127.0.0.1 3000 127.0.0.1 3000
node ./server.js 127.0.0.1 3001 127.0.0.1 3000
node ./server.js 127.0.0.1 3002 127.0.0.1 3000
```

With this example, three servers are launched, listening on 3 different ports, but all connected to the seed host (port 3000).
Expand All @@ -32,9 +32,9 @@ In parallel, servers also listen on `port + 10000` for clients to join.
We will now launch clients connecting to any given server.

```
node ./client.js 0.0.0.0 13000
node ./client.js 0.0.0.0 13001
node ./client.js 0.0.0.0 13002
node ./client.js 127.0.0.1 13000
node ./client.js 127.0.0.1 13001
node ./client.js 127.0.0.1 13002
```

The clients should connect to the server and send an "hello world!" message using the external channel.
Expand Down
2 changes: 1 addition & 1 deletion examples/distributed_pub_sub/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const external = kalm.listen({
transport: ws(),
port: 10000 + Number(config.port),
routine: kalm.routines.tick({ hz: 120, seed: ts }),
host: '0.0.0.0',
host: '127.0.0.1',
});

const isSeed = (config.host === seedConfig.host && config.port === seedConfig.port);
Expand Down
4 changes: 2 additions & 2 deletions examples/manual_routine/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import ws from '@kalm/ws';

/**
* Creates a kalm client that uses the Websocket transport.
* It will attempt to connect to a server located at the address '0.0.0.0' on port 3938.
* It will attempt to connect to a server located at the address '127.0.0.1' on port 3938.
*
* The manual routine needs to be constructed first in order to get access to the `flush` method.
*/
Expand All @@ -12,7 +12,7 @@ const { flush, queue } = routines.manual();
const client = connect({
transport: ws({}),
port: 3938,
host: '0.0.0.0',
host: '127.0.0.1',
routine: queue,
});

Expand Down
4 changes: 2 additions & 2 deletions examples/manual_routine/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import ws from '@kalm/ws';

/**
* Creates a kalm server that uses the Websocket transport.
* It is bound to local IP 0.0.0.0 and listens on port 3938.
* It is bound to local IP 127.0.0.1 and listens on port 3938.
*
* The manual routine needs to be constructed first in order to get access to the `flush` method.
* This can be an option if you have a seperate system to manage server ticks.
Expand All @@ -14,7 +14,7 @@ const provider = listen({
transport: ws(),
port: 3938,
routine: queue,
host: '0.0.0.0',
host: '127.0.0.1',
});

/**
Expand Down
4 changes: 2 additions & 2 deletions examples/typescript_websocket/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import ws from '@kalm/ws';

/**
* Creates a kalm client that uses the Websocket transport.
* It will attempt to connect to a server located at the address '0.0.0.0' on port 3938.
* It will attempt to connect to a server located at the address '127.0.0.1' on port 3938.
*
* The realtime routine will emit messages as soon as possible. While this is ideal in a few scenarios, for instance when the client does not send a lot of events,
* it does not leverage the benefits of buffering and may cause slowdowns if many messages are sent rapidly.
*/
const client = connect({
transport: ws({}),
port: 3938,
host: '0.0.0.0',
host: '127.0.0.1',
routine: routines.realtime(),
});

Expand Down
4 changes: 2 additions & 2 deletions examples/typescript_websocket/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import ws from '@kalm/ws';

/**
* Creates a kalm server that uses the Websocket transport.
* It is bound to local IP 0.0.0.0 and listens on port 3938.
* It is bound to local IP 127.0.0.1 and listens on port 3938.
*
* The tick routine will emit messages to clients at a frequency no higher than 5hz, or no shorter than 20ms
*
Expand All @@ -13,7 +13,7 @@ const provider = listen({
transport: ws(),
port: 3938,
routine: routines.tick({ hz: 5 }),
host: '0.0.0.0',
host: '127.0.0.1',
});

/**
Expand Down
43 changes: 43 additions & 0 deletions examples/typescript_webtransport/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Typescript webtransport example

This example shows how to create a webtransport server and client in Typescript.

# Requirements

- The clients must in the browser.
- The server must run in a Node.js environment.
- NPM or other package manager to install `kalm` and `@kalm/webtransport`
- **Important** Generate an ssl certificate for localhost

# Certificate

WebTransport requires servers to have a valid SSL certificate to work. We can generate one for `localhost` using this script ([src repo](https://github.com/moq-dev/moq/blob/261d6927c156ab3efec8f59c75b6e337e7f4d107/cert/generate)):


```
./cert/mkcert.sh
```

This will output certificate files to that directory.

You will need to grab the SHA-256 fingerprint and place it in the client.html file for `serverCertificateHashes`.

# Testing

Launch the server first:

```
node ./server.ts
```

It should log that the server is ready to receive new connections. Now we need to serve the html file:

```
node ./static_serve.ts
```

And open as many browser tabs at the address listed by the command. eg: https://localhost:8000/examples/typescript_webtransport/client.html

Each will behave as a distinct client. The clients should connect to the server and send an "hello world!" message.

In turn, the server will both respond to that client: "hello from the server!" and broadcast to all clients "A new client has connected!"
14 changes: 14 additions & 0 deletions examples/typescript_webtransport/cert/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/kixelated/warp/cert

go 1.18

require (
filippo.io/mkcert v1.4.4 // indirect
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 // indirect
golang.org/x/text v0.3.7 // indirect
howett.net/plist v1.0.0 // indirect
software.sslmate.com/src/go-pkcs12 v0.2.0 // indirect
)

replace filippo.io/mkcert => github.com/kixelated/mkcert v1.4.4-days
22 changes: 22 additions & 0 deletions examples/typescript_webtransport/cert/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/kixelated/mkcert v1.4.4-days h1:T2P9W4ruEfgLHOl5UljPwh0d79FbFWkSe2IONcUBxG8=
github.com/kixelated/mkcert v1.4.4-days/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8=
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
software.sslmate.com/src/go-pkcs12 v0.2.0 h1:nlFkj7bTysH6VkC4fGphtjXRbezREPgrHuJG20hBGPE=
software.sslmate.com/src/go-pkcs12 v0.2.0/go.mod h1:23rNcYsMabIc1otwLpTkCCPwUq6kQsTyowttG/as0kQ=
20 changes: 20 additions & 0 deletions examples/typescript_webtransport/cert/mkcert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
set -euo pipefail

cd "$(dirname "${BASH_SOURCE[0]}")"

# Generate a new RSA key/cert for local development
HOST="localhost"
CRT="$HOST.crt"
KEY="$HOST.key"

# Install the system certificate if it's not already
# NOTE: The ecdsa flag does nothing but I wish it did
go run filippo.io/mkcert -ecdsa -install

# Generate a new certificate for localhost
# This fork of mkcert supports the -days flag.
go run filippo.io/mkcert -ecdsa -days 10 -cert-file "$CRT" -key-file "$KEY" localhost 0.0.0.0 127.0.0.1 ::1

# Compute the sha256 fingerprint of the certificate for WebTransport
openssl x509 -in "$CRT" -outform der | openssl dgst -sha256 > ./fingerprint.hex
Loading
Loading