@atcute/xrpc-server-deno 0.1.0 → 1.0.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 +10 -3
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/lib/index.ts +43 -3
- package/package.json +10 -6
package/README.md
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
# @atcute/xrpc-server-deno
|
|
2
2
|
|
|
3
|
-
Deno WebSocket adapter for `@atcute/xrpc-server
|
|
3
|
+
Deno WebSocket adapter for [`@atcute/xrpc-server`](../xrpc-server/).
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
deno add npm:@atcute/xrpc-server-deno
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
see the [subscriptions section](../xrpc-server/#subscriptions) in the main package for usage
|
|
10
|
+
details.
|
|
4
11
|
|
|
5
12
|
```ts
|
|
6
13
|
import { XRPCRouter } from '@atcute/xrpc-server';
|
|
7
14
|
import { createDenoWebSocket } from '@atcute/xrpc-server-deno';
|
|
8
15
|
|
|
9
|
-
import {
|
|
16
|
+
import { ComExampleSubscribe } from './lexicons/index.ts';
|
|
10
17
|
|
|
11
18
|
const adapter = createDenoWebSocket();
|
|
12
19
|
const router = new XRPCRouter({ websocket: adapter });
|
|
13
20
|
|
|
14
|
-
router.addSubscription(
|
|
21
|
+
router.addSubscription(ComExampleSubscribe.mainSchema, {
|
|
15
22
|
async *handler({ params, signal }) {
|
|
16
23
|
while (!signal.aborted) {
|
|
17
24
|
yield {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import type { WebSocketAdapter } from '@atcute/xrpc-server';
|
|
2
|
-
export
|
|
2
|
+
export interface CreateDenoWebSocketOptions {
|
|
3
|
+
/** backpressure high water mark in bytes; defaults to 250 KB. */
|
|
4
|
+
highWaterMark?: number;
|
|
5
|
+
/** backpressure low water mark in bytes; defaults to 50 KB. */
|
|
6
|
+
lowWaterMark?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const createDenoWebSocket: ({ highWaterMark, lowWaterMark, }?: CreateDenoWebSocketOptions) => WebSocketAdapter;
|
|
3
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,qBAAqB,CAAC;AAEjF,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,qBAAqB,CAAC;AAEjF,MAAM,WAAW,0BAA0B;IAC1C,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,mBAAmB,sCAG7B,0BAA0B,KAAQ,gBAyCpC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
export const createDenoWebSocket = () => {
|
|
1
|
+
export const createDenoWebSocket = ({ highWaterMark = 250_000, lowWaterMark = 50_000, } = {}) => {
|
|
2
2
|
return {
|
|
3
3
|
async upgrade(request, handler) {
|
|
4
4
|
const { response, socket } = Deno.upgradeWebSocket(request);
|
|
5
5
|
const controller = new AbortController();
|
|
6
|
+
const signal = controller.signal;
|
|
6
7
|
const connection = {
|
|
7
|
-
signal:
|
|
8
|
+
signal: signal,
|
|
8
9
|
send(data) {
|
|
9
10
|
socket.send(data);
|
|
10
11
|
},
|
|
12
|
+
async drain() {
|
|
13
|
+
if (socket.bufferedAmount <= highWaterMark) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
while (!signal.aborted &&
|
|
17
|
+
socket.readyState === WebSocket.OPEN &&
|
|
18
|
+
socket.bufferedAmount > lowWaterMark) {
|
|
19
|
+
await sleep(10, signal);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
11
22
|
close(code, reason) {
|
|
12
23
|
socket.close(code, reason);
|
|
13
24
|
},
|
|
@@ -22,4 +33,17 @@ export const createDenoWebSocket = () => {
|
|
|
22
33
|
},
|
|
23
34
|
};
|
|
24
35
|
};
|
|
36
|
+
const sleep = (ms, signal) => {
|
|
37
|
+
return new Promise((resolve) => {
|
|
38
|
+
const timer = setTimeout(() => {
|
|
39
|
+
signal.removeEventListener('abort', onAbort);
|
|
40
|
+
resolve();
|
|
41
|
+
}, ms);
|
|
42
|
+
const onAbort = () => {
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
resolve();
|
|
45
|
+
};
|
|
46
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
47
|
+
});
|
|
48
|
+
};
|
|
25
49
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EACnC,aAAa,GAAG,OAAO,EACvB,YAAY,GAAG,MAAM,GACrB,GAA+B,EAAE,EAAoB,EAAE;IACvD,OAAO;QACN,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO;YAC7B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAE5D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;YACjC,MAAM,UAAU,GAAwB;gBACvC,MAAM,EAAE,MAAM;gBACd,IAAI,CAAC,IAAgB;oBACpB,MAAM,CAAC,IAAI,CAAC,IAA+B,CAAC,CAAC;gBAC9C,CAAC;gBACD,KAAK,CAAC,KAAK;oBACV,IAAI,MAAM,CAAC,cAAc,IAAI,aAAa,EAAE,CAAC;wBAC5C,OAAO;oBACR,CAAC;oBAED,OACC,CAAC,MAAM,CAAC,OAAO;wBACf,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;wBACpC,MAAM,CAAC,cAAc,GAAG,YAAY,EACnC,CAAC;wBACF,MAAM,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;oBACzB,CAAC;gBACF,CAAC;gBACD,KAAK,CAAC,IAAa,EAAE,MAAe;oBACnC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC5B,CAAC;aACD,CAAC;YAEF,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;gBACpB,OAAO,CAAC,UAAU,CAAC,CAAC;YACrB,CAAC,CAAC;YAEF,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE;gBACvB,UAAU,CAAC,KAAK,CAAC,yCAAyC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YACtE,CAAC,CAAC;YAEF,OAAO,QAAQ,CAAC;QACjB,CAAC;KACD,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,MAAmB,EAAiB,EAAE;IAChE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,EAAE,CAAC;QACX,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,GAAG,GAAG,EAAE;YACpB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACX,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
package/lib/index.ts
CHANGED
|
@@ -1,15 +1,39 @@
|
|
|
1
1
|
import type { WebSocketAdapter, WebSocketConnection } from '@atcute/xrpc-server';
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export interface CreateDenoWebSocketOptions {
|
|
4
|
+
/** backpressure high water mark in bytes; defaults to 250 KB. */
|
|
5
|
+
highWaterMark?: number;
|
|
6
|
+
/** backpressure low water mark in bytes; defaults to 50 KB. */
|
|
7
|
+
lowWaterMark?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const createDenoWebSocket = ({
|
|
11
|
+
highWaterMark = 250_000,
|
|
12
|
+
lowWaterMark = 50_000,
|
|
13
|
+
}: CreateDenoWebSocketOptions = {}): WebSocketAdapter => {
|
|
4
14
|
return {
|
|
5
15
|
async upgrade(request, handler) {
|
|
6
16
|
const { response, socket } = Deno.upgradeWebSocket(request);
|
|
7
17
|
|
|
8
18
|
const controller = new AbortController();
|
|
19
|
+
const signal = controller.signal;
|
|
9
20
|
const connection: WebSocketConnection = {
|
|
10
|
-
signal:
|
|
21
|
+
signal: signal,
|
|
11
22
|
send(data: Uint8Array) {
|
|
12
|
-
socket.send(data);
|
|
23
|
+
socket.send(data as Uint8Array<ArrayBuffer>);
|
|
24
|
+
},
|
|
25
|
+
async drain() {
|
|
26
|
+
if (socket.bufferedAmount <= highWaterMark) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
while (
|
|
31
|
+
!signal.aborted &&
|
|
32
|
+
socket.readyState === WebSocket.OPEN &&
|
|
33
|
+
socket.bufferedAmount > lowWaterMark
|
|
34
|
+
) {
|
|
35
|
+
await sleep(10, signal);
|
|
36
|
+
}
|
|
13
37
|
},
|
|
14
38
|
close(code?: number, reason?: string) {
|
|
15
39
|
socket.close(code, reason);
|
|
@@ -28,3 +52,19 @@ export const createDenoWebSocket = (): WebSocketAdapter => {
|
|
|
28
52
|
},
|
|
29
53
|
};
|
|
30
54
|
};
|
|
55
|
+
|
|
56
|
+
const sleep = (ms: number, signal: AbortSignal): Promise<void> => {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const timer = setTimeout(() => {
|
|
59
|
+
signal.removeEventListener('abort', onAbort);
|
|
60
|
+
resolve();
|
|
61
|
+
}, ms);
|
|
62
|
+
|
|
63
|
+
const onAbort = () => {
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
resolve();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
69
|
+
});
|
|
70
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"type": "module",
|
|
3
2
|
"name": "@atcute/xrpc-server-deno",
|
|
4
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
5
4
|
"description": "Deno WebSocket adapter for @atcute/xrpc-server",
|
|
6
5
|
"license": "0BSD",
|
|
7
6
|
"repository": {
|
|
@@ -12,19 +11,24 @@
|
|
|
12
11
|
"dist/",
|
|
13
12
|
"lib/",
|
|
14
13
|
"!lib/**/*.bench.ts",
|
|
15
|
-
"!lib/**/*.test.ts"
|
|
14
|
+
"!lib/**/*.test.ts",
|
|
15
|
+
"!dist/**/*.{test,bench}.*"
|
|
16
16
|
],
|
|
17
|
+
"type": "module",
|
|
17
18
|
"exports": {
|
|
18
19
|
".": "./dist/index.js"
|
|
19
20
|
},
|
|
20
|
-
"
|
|
21
|
-
"
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/deno": "^2.5.0"
|
|
25
26
|
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@atcute/xrpc-server": "^1.0.0"
|
|
29
|
+
},
|
|
26
30
|
"scripts": {
|
|
27
|
-
"build": "
|
|
31
|
+
"build": "tsgo",
|
|
28
32
|
"prepublish": "rm -rf dist; pnpm run build"
|
|
29
33
|
}
|
|
30
34
|
}
|