@nyirusu/nact-websocket-server 0.0.0-stage → 1.0.4

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,33 @@
1
+ import http from 'node:http';
2
+ import type { ServerHandle, ServerProvider, Channel } from '@nyirusu/nasdk/NACT';
3
+ export type WebSocketServerOptions = {
4
+ host: string;
5
+ port: number;
6
+ path?: string;
7
+ noServer?: false;
8
+ } | {
9
+ noServer: true;
10
+ path?: never;
11
+ host?: never;
12
+ port?: never;
13
+ };
14
+ export interface WebSocketServerTransportSpec {
15
+ type: 'websocket';
16
+ provider: WebSocketServerOptions;
17
+ nact?: {
18
+ chunkSize?: number;
19
+ };
20
+ }
21
+ export default class WebSocketServerProvider implements ServerProvider<'websocket', WebSocketServerOptions> {
22
+ readonly type = "websocket";
23
+ readonly role = "server";
24
+ readonly defaultChunkSize: number;
25
+ private websocket?;
26
+ private detach;
27
+ attach(server: http.Server, options?: {
28
+ path?: string;
29
+ }): () => void;
30
+ private attachServer;
31
+ listen(options: WebSocketServerOptions, accept: (channel: Channel) => void): Promise<ServerHandle>;
32
+ }
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAG5B,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAEhF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB,GAAG;IACF,QAAQ,EAAE,IAAI,CAAA;IACd,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,IAAI,CAAC,EAAE,KAAK,CAAA;CACb,CAAA;AACD,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,sBAAsB,CAAA;IAChC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9B;AAgCD,MAAM,CAAC,OAAO,OAAO,uBACnB,YAAW,cAAc,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC9D,QAAQ,CAAC,IAAI,eAAc;IAC3B,QAAQ,CAAC,IAAI,YAAW;IACxB,QAAQ,CAAC,gBAAgB,SAAoB;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAiB;IACnC,OAAO,CAAC,MAAM,CAAwB;IAEtC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,MAAM,IAAI;IAKxE,OAAO,CAAC,YAAY;IAed,MAAM,CAAC,OAAO,EAAE,sBAAsB,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;CAiCzG"}
package/dist/index.js ADDED
@@ -0,0 +1,108 @@
1
+ import http from 'node:http';
2
+ import { WebSocketServer } from 'ws';
3
+ class WebSocketChannel {
4
+ socket;
5
+ errorHandlers = new Set();
6
+ constructor(socket) {
7
+ this.socket = socket;
8
+ }
9
+ send(frame) {
10
+ if (this.socket.readyState !== 1)
11
+ throw Object.assign(new Error('transport-closed'), { code: 'transport-closed' });
12
+ const size = frame.reduce((sum, part) => sum + part.byteLength, 0);
13
+ const bytes = new Uint8Array(size);
14
+ let offset = 0;
15
+ for (const part of frame) {
16
+ bytes.set(part, offset);
17
+ offset += part.byteLength;
18
+ }
19
+ this.socket.send(bytes);
20
+ }
21
+ close() { this.socket.close(); }
22
+ terminate() { this.socket.terminate(); }
23
+ onReceive(handler) {
24
+ const listener = (data, isBinary) => {
25
+ if (!isBinary)
26
+ return this.fail('non-binary-frame');
27
+ handler([data]); // default binaryType 'nodebuffer': one Buffer per message
28
+ };
29
+ this.socket.on('message', listener);
30
+ return () => this.socket.off('message', listener);
31
+ }
32
+ onClose(handler) { this.socket.on('close', handler); return () => this.socket.off('close', handler); }
33
+ onError(handler) {
34
+ this.errorHandlers.add(handler);
35
+ this.socket.on('error', handler);
36
+ return () => { this.errorHandlers.delete(handler); this.socket.off('error', handler); };
37
+ }
38
+ fail(reason) { for (const handler of this.errorHandlers)
39
+ handler(reason); }
40
+ }
41
+ export default class WebSocketServerProvider {
42
+ type = 'websocket';
43
+ role = 'server';
44
+ defaultChunkSize = 100 * 1024 * 1024;
45
+ websocket;
46
+ detach = new Set();
47
+ attach(server, options = {}) {
48
+ if (!this.websocket)
49
+ throw Object.assign(new Error('provider-not-listening'), { code: 'provider-not-listening' });
50
+ return this.attachServer(server, options);
51
+ }
52
+ attachServer(server, options, owned = false) {
53
+ const websocket = this.websocket;
54
+ const upgrade = (request, socket, head) => {
55
+ if (options.path && new URL(request.url ?? '/', 'http://localhost').pathname !== options.path) {
56
+ if (owned)
57
+ socket.end('HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n');
58
+ return;
59
+ }
60
+ websocket.handleUpgrade(request, socket, head, ws => websocket.emit('connection', ws, request));
61
+ };
62
+ const detach = () => { server.off('upgrade', upgrade); this.detach.delete(detach); };
63
+ server.on('upgrade', upgrade);
64
+ this.detach.add(detach);
65
+ return detach;
66
+ }
67
+ async listen(options, accept) {
68
+ if (this.websocket)
69
+ throw Object.assign(new Error('provider-already-listening'), { code: 'provider-already-listening' });
70
+ const server = options.noServer ? undefined : http.createServer();
71
+ const websocket = new WebSocketServer({ noServer: true, perMessageDeflate: false });
72
+ this.websocket = websocket;
73
+ websocket.on('connection', socket => accept(new WebSocketChannel(socket)));
74
+ if (server && !options.noServer) {
75
+ this.attachServer(server, options, true);
76
+ try {
77
+ await new Promise((resolve, reject) => {
78
+ server.once('error', reject);
79
+ server.listen(options.port, options.host, () => { server.off('error', reject); resolve(); });
80
+ });
81
+ }
82
+ catch (reason) {
83
+ for (const detach of this.detach)
84
+ detach();
85
+ this.websocket = undefined;
86
+ websocket.close();
87
+ throw reason;
88
+ }
89
+ }
90
+ let closing;
91
+ return {
92
+ close: () => closing ??= new Promise(resolve => {
93
+ this.websocket = undefined;
94
+ for (const detach of this.detach)
95
+ detach();
96
+ for (const socket of websocket.clients)
97
+ socket.terminate();
98
+ websocket.close(() => {
99
+ if (server)
100
+ server.close(() => resolve());
101
+ else
102
+ resolve();
103
+ });
104
+ }),
105
+ };
106
+ }
107
+ }
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "name": "@nyirusu/nact-websocket-server",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.4",
4
+ "type": "module",
5
+ "files": ["dist/index.js", "dist/index.js.map", "dist/index.d.ts", "dist/index.d.ts.map"],
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } },
9
+ "scripts": { "build": "tsc -p tsconfig.build.json", "typecheck": "tsc -p tsconfig.json --noEmit", "test": "npm run test:simple", "test:simple": "node --import tsx --test test/simple.test.mjs", "test:full": "node --import tsx --test test/full.test.mjs", "test:edge": "node --import tsx --test test/edge.test.mjs" },
10
+ "dependencies": { "ws": "8.21.3" },
11
+ "devDependencies": { "@types/ws": "8.18.1" },
12
+ "peerDependencies": { "@nyirusu/nasdk": ">=1.0.4" },
13
+ "peerDependenciesMeta": { "@nyirusu/nasdk": { "optional": true } }
14
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.