durablews 1.0.0 → 2.0.0-alpha.0
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.
- package/README.md +43 -87
- package/dist/binding-bZNBe2Bz.d.cts +11 -0
- package/dist/binding-gyPQiK9i.d.ts +11 -0
- package/dist/chunk-GIDTCSPD.js +22 -0
- package/dist/chunk-GIDTCSPD.js.map +1 -0
- package/dist/chunk-MG4TK53H.js +590 -0
- package/dist/chunk-MG4TK53H.js.map +1 -0
- package/dist/compat.cjs +765 -0
- package/dist/compat.cjs.map +1 -0
- package/dist/compat.d.cts +72 -0
- package/dist/compat.d.ts +72 -0
- package/dist/compat.js +177 -0
- package/dist/compat.js.map +1 -0
- package/dist/index.cjs +612 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +81 -0
- package/dist/index.d.ts +81 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +646 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +66 -0
- package/dist/react.d.ts +66 -0
- package/dist/react.js +42 -0
- package/dist/react.js.map +1 -0
- package/dist/types-BDvztGcG.d.cts +410 -0
- package/dist/types-BDvztGcG.d.ts +410 -0
- package/dist/vue.cjs +650 -0
- package/dist/vue.cjs.map +1 -0
- package/dist/vue.d.cts +72 -0
- package/dist/vue.d.ts +72 -0
- package/dist/vue.js +43 -0
- package/dist/vue.js.map +1 -0
- package/package.json +128 -66
- package/dist/client.d.ts +0 -2
- package/dist/durablews.js +0 -120
- package/dist/durablews.umd.cjs +0 -1
- package/dist/types.d.ts +0 -34
package/README.md
CHANGED
|
@@ -1,118 +1,74 @@
|
|
|
1
|
-
# DurableWS
|
|
1
|
+
# DurableWS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> A resilient, modern, zero-dependency WebSocket **client** for TypeScript — built on the standard `WebSocket`, durable by default, and the same in every modern runtime.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> ⚠️ **v2 is under active development (`2.0.0-alpha`).** The API is changing and several headline features below are still being built. See the [v2 architecture RFC](https://github.com/imnsco/DurableWS/blob/main/rfcs/0001-v2-architecture.md) for the design and live status. The current npm release (`1.x`) predates this redesign.
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- **Idle Detection**: Automatically detects idle states and triggers custom handlers.
|
|
9
|
-
- **Message Queueing**: Outgoing messages are queued when the connection is down and sent when it's restored.
|
|
10
|
-
- **Subscription Management**: Simplifies subscribing to topics/channels with ease.
|
|
11
|
-
- **TypeScript Support**: Fully typed interfaces for a better development experience.
|
|
7
|
+
DurableWS aims to be "the Hono of WebSockets": tiny, ergonomic, Web-Standards-based, and **durable by default** — automatic reconnection, message queueing, and idle detection out of the box — with a middleware + codec pipeline for extensibility (custom wire formats, auth, a socket.io-compatibility layer, and more).
|
|
12
8
|
|
|
13
|
-
##
|
|
9
|
+
## Status
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
npm install durablews
|
|
17
|
-
```
|
|
11
|
+
DurableWS v2 is being built in the open. To be accurate about what exists today vs. what's planned:
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
**Working now**
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
- Connect / send / close and incoming-message handling over the standard `WebSocket`
|
|
16
|
+
- Event subscriptions (`on` / `off`)
|
|
17
|
+
- A middleware pipeline (`use`)
|
|
18
|
+
- Built-in JSON-safe message parsing and a ping/pong middleware
|
|
24
19
|
|
|
25
|
-
|
|
20
|
+
**Planned for v2 (not yet implemented)**
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
- Automatic reconnection with exponential backoff
|
|
23
|
+
- Message queueing while disconnected, flushed on reconnect
|
|
24
|
+
- Idle detection
|
|
25
|
+
- A typed connection state machine
|
|
26
|
+
- Pluggable codecs (msgpack, socket.io framing, …) and an authentication helper
|
|
27
|
+
- Channels / subscriptions
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
import { createClient } from "durablews";
|
|
31
|
-
```
|
|
29
|
+
Until these land, treat the durability features as a roadmap, not a guarantee.
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
## Requirements
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
maxReconnectAttempts: 5,
|
|
40
|
-
maxQueueSize: 50,
|
|
41
|
-
idleTimeout: 300000, // 5 minutes
|
|
42
|
-
getToken: async () => {
|
|
43
|
-
const response = await fetch("/my/token/issuer").then((r) => r.json());
|
|
44
|
-
return response.token;
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
```
|
|
33
|
+
DurableWS targets the **standard global `WebSocket`** and ships **zero runtime dependencies**. That means:
|
|
34
|
+
|
|
35
|
+
- **Node.js ≥ 22** — the first release where the global `WebSocket` is available unflagged. (There is no `ws` dependency, by design.)
|
|
36
|
+
- Any modern runtime with a global `WebSocket`: current browsers, Deno, Bun, and Cloudflare Workers.
|
|
48
37
|
|
|
49
|
-
|
|
38
|
+
## Installation
|
|
50
39
|
|
|
51
|
-
```
|
|
52
|
-
|
|
40
|
+
```bash
|
|
41
|
+
# v2 is not yet published; once the alpha ships it will be:
|
|
42
|
+
npm install durablews@alpha
|
|
53
43
|
```
|
|
54
44
|
|
|
55
|
-
|
|
45
|
+
## Quick start
|
|
56
46
|
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
console.log("Received message:", message);
|
|
60
|
-
});
|
|
47
|
+
```ts
|
|
48
|
+
import { defineClient } from "durablews";
|
|
61
49
|
|
|
62
|
-
client
|
|
63
|
-
console.log("Connection opened");
|
|
64
|
-
});
|
|
50
|
+
const client = defineClient({ url: "wss://example.com/socket" });
|
|
65
51
|
|
|
66
|
-
client.
|
|
67
|
-
console.
|
|
52
|
+
client.on("message", (data) => {
|
|
53
|
+
console.log("received:", data);
|
|
68
54
|
});
|
|
69
55
|
|
|
70
|
-
client.
|
|
71
|
-
|
|
72
|
-
});
|
|
56
|
+
await client.connect();
|
|
57
|
+
client.send({ type: "hello", message: "world" });
|
|
73
58
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
});
|
|
59
|
+
// later
|
|
60
|
+
client.close();
|
|
77
61
|
```
|
|
78
62
|
|
|
79
|
-
##
|
|
63
|
+
## Documentation
|
|
80
64
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Initializes and returns a WebSocket client instance.
|
|
84
|
-
|
|
85
|
-
#### Config Options
|
|
86
|
-
|
|
87
|
-
- `url`: WebSocket server URL.
|
|
88
|
-
- `accessToken` (optional): Token for authentication.
|
|
89
|
-
- `autoConnect` (optional): Whether to connect immediately upon instantiation.
|
|
90
|
-
- `maxReconnectAttempts` (optional): Maximum number of reconnection attempts.
|
|
91
|
-
- `maxQueueSize` (optional): Maximum size of the message queue.
|
|
92
|
-
- `idleTimeout` (optional): Duration in milliseconds before the client is considered idle.
|
|
93
|
-
- `authTokenURL` (optional): A URL for token issuance.
|
|
94
|
-
- `getToken (optional): Function that returns a token for authentication. Can be synchronous or asynchronous.
|
|
95
|
-
|
|
96
|
-
### WebSocketClient Methods
|
|
97
|
-
|
|
98
|
-
- `send(message: Record<string, unknown>)`: Send a message through the WebSocket connection.
|
|
99
|
-
- `subscribe(channelName: string)`: Subscribe to a channel.
|
|
100
|
-
- `connect()`: Manually initiate the connection.
|
|
101
|
-
- `disconnect()`: Disconnect the WebSocket connection.
|
|
102
|
-
- `isReady()`: Returns a promise that resolves when the connection is ready.
|
|
103
|
-
- `getStatus()`: Returns the current connection status.
|
|
104
|
-
- `onMessage(listener: OnMessageHandler)`: Register a message event listener.
|
|
105
|
-
- `onError(listener: OnErrorHandler)`: Register an error event listener.
|
|
106
|
-
- `onOpen(listener: OnOpenHandler)`: Register an open event listener.
|
|
107
|
-
- `onClose(listener: OnCloseHandler)`: Register a close event listener.
|
|
108
|
-
- `onIdle(listener: OnIdleHandler)`: Register an idle event listener.
|
|
65
|
+
- [v2 architecture RFC](https://github.com/imnsco/DurableWS/blob/main/rfcs/0001-v2-architecture.md)
|
|
66
|
+
- A full documentation site (Astro + Starlight) is coming as part of v2.
|
|
109
67
|
|
|
110
68
|
## Contributing
|
|
111
69
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
For major changes, please open an issue first to discuss what you would like to change.
|
|
70
|
+
Contributions are welcome — see [CONTRIBUTING](https://github.com/imnsco/DurableWS/blob/main/CONTRIBUTING.md).
|
|
115
71
|
|
|
116
72
|
## License
|
|
117
73
|
|
|
118
|
-
[
|
|
74
|
+
[MPL-2.0](./LICENSE) © Nate Smith
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { a as WebSocketClientConfig, W as WebSocketClient } from './types-BDvztGcG.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What a framework binding accepts: either a config (the binding creates and
|
|
5
|
+
* **owns** the client — connecting it and closing it with the component) or an
|
|
6
|
+
* existing client (the binding only **observes** it — sharing one connection
|
|
7
|
+
* across many components without any binding taking over its lifecycle).
|
|
8
|
+
*/
|
|
9
|
+
type UseWebSocketSource<TIn = unknown, TOut = unknown> = WebSocketClientConfig | WebSocketClient<TIn, TOut>;
|
|
10
|
+
|
|
11
|
+
export type { UseWebSocketSource as U };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { a as WebSocketClientConfig, W as WebSocketClient } from './types-BDvztGcG.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What a framework binding accepts: either a config (the binding creates and
|
|
5
|
+
* **owns** the client — connecting it and closing it with the component) or an
|
|
6
|
+
* existing client (the binding only **observes** it — sharing one connection
|
|
7
|
+
* across many components without any binding taking over its lifecycle).
|
|
8
|
+
*/
|
|
9
|
+
type UseWebSocketSource<TIn = unknown, TOut = unknown> = WebSocketClientConfig | WebSocketClient<TIn, TOut>;
|
|
10
|
+
|
|
11
|
+
export type { UseWebSocketSource as U };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { client } from './chunk-MG4TK53H.js';
|
|
2
|
+
|
|
3
|
+
// src/helpers/binding.ts
|
|
4
|
+
function resolveSource(source) {
|
|
5
|
+
if (isClient(source)) {
|
|
6
|
+
return { client: source, owned: false };
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
client: client(source),
|
|
10
|
+
owned: true
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function isClient(source) {
|
|
14
|
+
return typeof source.subscribe === "function";
|
|
15
|
+
}
|
|
16
|
+
function canConnect() {
|
|
17
|
+
return typeof WebSocket !== "undefined";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { canConnect, resolveSource };
|
|
21
|
+
//# sourceMappingURL=chunk-GIDTCSPD.js.map
|
|
22
|
+
//# sourceMappingURL=chunk-GIDTCSPD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers/binding.ts"],"names":[],"mappings":";;;AAuBO,SAAS,cACZ,MAAA,EACyB;AACzB,EAAA,IAAI,QAAA,CAAS,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAM;AAAA,EAC1C;AACA,EAAA,OAAO;AAAA,IACH,MAAA,EAAQ,OAAO,MAAM,CAAA;AAAA,IACrB,KAAA,EAAO;AAAA,GACX;AACJ;AAEA,SAAS,SACL,MAAA,EACoC;AACpC,EAAA,OAAO,OAAQ,OAA2B,SAAA,KAAc,UAAA;AAC5D;AAOO,SAAS,UAAA,GAAsB;AAClC,EAAA,OAAO,OAAO,SAAA,KAAc,WAAA;AAChC","file":"chunk-GIDTCSPD.js","sourcesContent":["import { client } from \"@/client\";\nimport type { WebSocketClient, WebSocketClientConfig } from \"@/types\";\n\n/**\n * What a framework binding accepts: either a config (the binding creates and\n * **owns** the client — connecting it and closing it with the component) or an\n * existing client (the binding only **observes** it — sharing one connection\n * across many components without any binding taking over its lifecycle).\n */\nexport type UseWebSocketSource<TIn = unknown, TOut = unknown> =\n | WebSocketClientConfig\n | WebSocketClient<TIn, TOut>;\n\nexport interface ResolvedSource<TIn = unknown, TOut = unknown> {\n readonly client: WebSocketClient<TIn, TOut>;\n /** Whether the binding created the client and therefore owns its lifecycle. */\n readonly owned: boolean;\n}\n\n/**\n * Resolves a binding source into a client plus ownership. A config produces a\n * fresh, owned client; a passed-in client is borrowed as-is.\n */\nexport function resolveSource<TIn = unknown, TOut = unknown>(\n source: UseWebSocketSource<TIn, TOut>\n): ResolvedSource<TIn, TOut> {\n if (isClient(source)) {\n return { client: source, owned: false };\n }\n return {\n client: client(source) as WebSocketClient<TIn, TOut>,\n owned: true\n };\n}\n\nfunction isClient<TIn, TOut>(\n source: UseWebSocketSource<TIn, TOut>\n): source is WebSocketClient<TIn, TOut> {\n return typeof (source as WebSocketClient).subscribe === \"function\";\n}\n\n/**\n * Whether a standard `WebSocket` global exists. Bindings skip auto-connect in\n * its absence (e.g. SSR), so creating a component server-side never throws —\n * the client connects when setup runs again in the browser.\n */\nexport function canConnect(): boolean {\n return typeof WebSocket !== \"undefined\";\n}\n"]}
|