@weifuwujs/weifuwu 0.9.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.
Files changed (122) hide show
  1. package/README.md +605 -0
  2. package/dist/app.d.ts +122 -0
  3. package/dist/app.d.ts.map +1 -0
  4. package/dist/app.js +484 -0
  5. package/dist/app.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +506 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/compose.d.ts +12 -0
  11. package/dist/compose.d.ts.map +1 -0
  12. package/dist/compose.js +29 -0
  13. package/dist/compose.js.map +1 -0
  14. package/dist/env.d.ts +12 -0
  15. package/dist/env.d.ts.map +1 -0
  16. package/dist/env.js +46 -0
  17. package/dist/env.js.map +1 -0
  18. package/dist/group.d.ts +32 -0
  19. package/dist/group.d.ts.map +1 -0
  20. package/dist/group.js +66 -0
  21. package/dist/group.js.map +1 -0
  22. package/dist/helpers.d.ts +37 -0
  23. package/dist/helpers.d.ts.map +1 -0
  24. package/dist/helpers.js +101 -0
  25. package/dist/helpers.js.map +1 -0
  26. package/dist/index.d.ts +15 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +9 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/ioredis.d.ts +16 -0
  31. package/dist/ioredis.d.ts.map +1 -0
  32. package/dist/ioredis.js +42 -0
  33. package/dist/ioredis.js.map +1 -0
  34. package/dist/methods.d.ts +3 -0
  35. package/dist/methods.d.ts.map +1 -0
  36. package/dist/methods.js +10 -0
  37. package/dist/methods.js.map +1 -0
  38. package/dist/middleware/cors.d.ts +24 -0
  39. package/dist/middleware/cors.d.ts.map +1 -0
  40. package/dist/middleware/cors.js +77 -0
  41. package/dist/middleware/cors.js.map +1 -0
  42. package/dist/middleware/index.d.ts +7 -0
  43. package/dist/middleware/index.d.ts.map +1 -0
  44. package/dist/middleware/index.js +4 -0
  45. package/dist/middleware/index.js.map +1 -0
  46. package/dist/middleware/logger.d.ts +27 -0
  47. package/dist/middleware/logger.d.ts.map +1 -0
  48. package/dist/middleware/logger.js +48 -0
  49. package/dist/middleware/logger.js.map +1 -0
  50. package/dist/middleware/static.d.ts +27 -0
  51. package/dist/middleware/static.d.ts.map +1 -0
  52. package/dist/middleware/static.js +150 -0
  53. package/dist/middleware/static.js.map +1 -0
  54. package/dist/node.d.ts +27 -0
  55. package/dist/node.d.ts.map +1 -0
  56. package/dist/node.js +193 -0
  57. package/dist/node.js.map +1 -0
  58. package/dist/path.d.ts +9 -0
  59. package/dist/path.d.ts.map +1 -0
  60. package/dist/path.js +31 -0
  61. package/dist/path.js.map +1 -0
  62. package/dist/postgres.d.ts +19 -0
  63. package/dist/postgres.d.ts.map +1 -0
  64. package/dist/postgres.js +27 -0
  65. package/dist/postgres.js.map +1 -0
  66. package/dist/react-router.d.ts +31 -0
  67. package/dist/react-router.d.ts.map +1 -0
  68. package/dist/react-router.js +25 -0
  69. package/dist/react-router.js.map +1 -0
  70. package/dist/resources.d.ts +35 -0
  71. package/dist/resources.d.ts.map +1 -0
  72. package/dist/resources.js +54 -0
  73. package/dist/resources.js.map +1 -0
  74. package/dist/router.d.ts +30 -0
  75. package/dist/router.d.ts.map +1 -0
  76. package/dist/router.js +122 -0
  77. package/dist/router.js.map +1 -0
  78. package/dist/types.d.ts +124 -0
  79. package/dist/types.d.ts.map +1 -0
  80. package/dist/types.js +2 -0
  81. package/dist/types.js.map +1 -0
  82. package/dist/vite.d.ts +21 -0
  83. package/dist/vite.d.ts.map +1 -0
  84. package/dist/vite.js +101 -0
  85. package/dist/vite.js.map +1 -0
  86. package/dist/websocket/accept.d.ts +22 -0
  87. package/dist/websocket/accept.d.ts.map +1 -0
  88. package/dist/websocket/accept.js +104 -0
  89. package/dist/websocket/accept.js.map +1 -0
  90. package/dist/websocket/close-code.d.ts +22 -0
  91. package/dist/websocket/close-code.d.ts.map +1 -0
  92. package/dist/websocket/close-code.js +35 -0
  93. package/dist/websocket/close-code.js.map +1 -0
  94. package/dist/websocket/connection.d.ts +71 -0
  95. package/dist/websocket/connection.d.ts.map +1 -0
  96. package/dist/websocket/connection.js +287 -0
  97. package/dist/websocket/connection.js.map +1 -0
  98. package/dist/websocket/index.d.ts +7 -0
  99. package/dist/websocket/index.d.ts.map +1 -0
  100. package/dist/websocket/index.js +4 -0
  101. package/dist/websocket/index.js.map +1 -0
  102. package/dist/websocket/types.d.ts +66 -0
  103. package/dist/websocket/types.d.ts.map +1 -0
  104. package/dist/websocket/types.js +2 -0
  105. package/dist/websocket/types.js.map +1 -0
  106. package/docs/ai.md +175 -0
  107. package/docs/data.md +81 -0
  108. package/docs/migrating.md +116 -0
  109. package/docs/react-router.md +187 -0
  110. package/docs/styling.md +69 -0
  111. package/package.json +144 -0
  112. package/templates/react-router/_gitignore +3 -0
  113. package/templates/react-router/app/app.css +1 -0
  114. package/templates/react-router/app/context.ts +4 -0
  115. package/templates/react-router/app/root.tsx +50 -0
  116. package/templates/react-router/app/routes/home.tsx +17 -0
  117. package/templates/react-router/app/routes.ts +3 -0
  118. package/templates/react-router/app/server.ts +29 -0
  119. package/templates/react-router/package.json +29 -0
  120. package/templates/react-router/react-router.config.ts +5 -0
  121. package/templates/react-router/tsconfig.json +19 -0
  122. package/templates/react-router/vite.config.ts +6 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * WebSocket 关闭码与校验(RFC 6455 §7.4)。
3
+ *
4
+ * 引擎实现已交给 `ws`,这里只保留框架公开 API 需要的最小常量与校验。
5
+ */
6
+ export declare const CLOSE_CODE: {
7
+ readonly NORMAL: 1000;
8
+ readonly GOING_AWAY: 1001;
9
+ readonly PROTOCOL_ERROR: 1002;
10
+ readonly UNSUPPORTED_DATA: 1003;
11
+ readonly NO_STATUS: 1005;
12
+ readonly ABNORMAL: 1006;
13
+ readonly INVALID_PAYLOAD: 1007;
14
+ readonly POLICY_VIOLATION: 1008;
15
+ readonly MESSAGE_TOO_BIG: 1009;
16
+ readonly MANDATORY_EXTENSION: 1010;
17
+ readonly INTERNAL_ERROR: 1011;
18
+ readonly TLS_HANDSHAKE: 1015;
19
+ };
20
+ /** 关闭码是否允许由应用主动发送 */
21
+ export declare function isValidCloseCode(code: number): boolean;
22
+ //# sourceMappingURL=close-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-code.d.ts","sourceRoot":"","sources":["../../src/websocket/close-code.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;CAab,CAAA;AAEV,qBAAqB;AACrB,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWtD"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * WebSocket 关闭码与校验(RFC 6455 §7.4)。
3
+ *
4
+ * 引擎实现已交给 `ws`,这里只保留框架公开 API 需要的最小常量与校验。
5
+ */
6
+ export const CLOSE_CODE = {
7
+ NORMAL: 1000,
8
+ GOING_AWAY: 1001,
9
+ PROTOCOL_ERROR: 1002,
10
+ UNSUPPORTED_DATA: 1003,
11
+ NO_STATUS: 1005,
12
+ ABNORMAL: 1006,
13
+ INVALID_PAYLOAD: 1007,
14
+ POLICY_VIOLATION: 1008,
15
+ MESSAGE_TOO_BIG: 1009,
16
+ MANDATORY_EXTENSION: 1010,
17
+ INTERNAL_ERROR: 1011,
18
+ TLS_HANDSHAKE: 1015,
19
+ };
20
+ /** 关闭码是否允许由应用主动发送 */
21
+ export function isValidCloseCode(code) {
22
+ if (code >= 3000 && code <= 4999)
23
+ return true;
24
+ if (code < 1000)
25
+ return false;
26
+ switch (code) {
27
+ case CLOSE_CODE.NO_STATUS:
28
+ case CLOSE_CODE.ABNORMAL:
29
+ case CLOSE_CODE.TLS_HANDSHAKE:
30
+ return false;
31
+ default:
32
+ return true;
33
+ }
34
+ }
35
+ //# sourceMappingURL=close-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-code.js","sourceRoot":"","sources":["../../src/websocket/close-code.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,IAAI;IAChB,cAAc,EAAE,IAAI;IACpB,gBAAgB,EAAE,IAAI;IACtB,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,IAAI;IACd,eAAe,EAAE,IAAI;IACrB,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,IAAI;IACrB,mBAAmB,EAAE,IAAI;IACzB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,IAAI;CACX,CAAA;AAEV,qBAAqB;AACrB,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAC7C,IAAI,IAAI,GAAG,IAAI;QAAE,OAAO,KAAK,CAAA;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU,CAAC,SAAS,CAAC;QAC1B,KAAK,UAAU,CAAC,QAAQ,CAAC;QACzB,KAAK,UAAU,CAAC,aAAa;YAC3B,OAAO,KAAK,CAAA;QACd;YACE,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,71 @@
1
+ import type { WebSocket as WsSocket } from 'ws';
2
+ export type WebSocketReadyState = 'open' | 'closing' | 'closed';
3
+ export interface WebSocketMessage {
4
+ data: string | Uint8Array;
5
+ binary: boolean;
6
+ }
7
+ export interface WebSocketEventMap {
8
+ message: (data: string | Uint8Array, isBinary: boolean) => void;
9
+ close: (code: number, reason: string) => void;
10
+ error: (error: Error) => void;
11
+ ping: (data: Uint8Array) => void;
12
+ pong: (data: Uint8Array) => void;
13
+ }
14
+ export interface WebSocketConnectionOptions {
15
+ /** 协商出的子协议 */
16
+ protocol?: string;
17
+ /** 单条消息最大字节数(已在 `ws` 握手层生效,此处仅记录) */
18
+ maxMessageSize?: number;
19
+ /** 自动回 pong(由 `ws` 内核负责),默认 true */
20
+ autoPong?: boolean;
21
+ /** close 握手超时后强制断开,默认 5000ms(由 `ws` 负责) */
22
+ closeTimeout?: number;
23
+ /** 服务端主动 ping 间隔(ms),默认关闭 */
24
+ pingInterval?: number;
25
+ /** 空闲超时(ms),默认关闭 */
26
+ idleTimeout?: number;
27
+ /** @deprecated 升级时多读到的字节已由 `ws` 处理 */
28
+ head?: Uint8Array;
29
+ }
30
+ /**
31
+ * 服务端 WebSocket 连接。
32
+ *
33
+ * ```ts
34
+ * app.ws('/chat', (socket) => ({
35
+ * onMessage: (socket, message) => socket.send(message.data),
36
+ * }))
37
+ * ```
38
+ *
39
+ * 握手、帧编解码、协议协商、关闭握手与自动 pong 都由 `ws` 完成;
40
+ * 本类只做事件与消息形状的适配。
41
+ */
42
+ export declare class WebSocketConnection implements AsyncIterable<WebSocketMessage> {
43
+ #private;
44
+ constructor(ws: WsSocket, options?: WebSocketConnectionOptions);
45
+ get readyState(): WebSocketReadyState;
46
+ get protocol(): string;
47
+ get bufferedAmount(): number;
48
+ get remoteAddress(): string | undefined;
49
+ on<E extends keyof WebSocketEventMap>(event: E, listener: WebSocketEventMap[E]): this;
50
+ off<E extends keyof WebSocketEventMap>(event: E, listener: WebSocketEventMap[E]): this;
51
+ once<E extends keyof WebSocketEventMap>(event: E, listener: WebSocketEventMap[E]): this;
52
+ /** 发送文本或二进制消息,返回 false 表示内核缓冲区已满 */
53
+ send(data: string | Uint8Array | ArrayBuffer | ArrayBufferView): boolean;
54
+ /** 发送 ping 控制帧 */
55
+ ping(data?: Uint8Array): boolean;
56
+ /** 发送 pong 控制帧 */
57
+ pong(data?: Uint8Array): boolean;
58
+ /** 发起关闭握手;不传 code 表示 1000 */
59
+ close(code?: number, reason?: string): void;
60
+ /** 立即断开,不进行关闭握手 */
61
+ terminate(): void;
62
+ [Symbol.asyncIterator](): AsyncIterableIterator<WebSocketMessage>;
63
+ /** @internal 由框架在业务 handler 执行前调用,补发升级后立即到达的消息 */
64
+ start(): void;
65
+ /**
66
+ * @internal dev 护栏:连接是否已有消息消费者
67
+ * (`onMessage` 会经 `message` 事件派发;也计入用户监听器与活跃迭代)
68
+ */
69
+ hasMessageConsumer(): boolean;
70
+ }
71
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/websocket/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,SAAS,IAAI,QAAQ,EAAE,MAAM,IAAI,CAAA;AAGxD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,UAAU,CAAA;IACzB,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC/D,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7C,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;IAChC,IAAI,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sCAAsC;IACtC,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,mBAAoB,YAAW,aAAa,CAAC,gBAAgB,CAAC;;gBAwB7D,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAE,0BAA+B;IAmBlE,IAAI,UAAU,IAAI,mBAAmB,CASpC;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAKtC;IAED,EAAE,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAClC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC7B,IAAI;IAUP,GAAG,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACnC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC7B,IAAI;IAKP,IAAI,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACpC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC7B,IAAI;IAQP,oCAAoC;IACpC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,eAAe,GAAG,OAAO;IAQxE,kBAAkB;IAClB,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO;IAUhC,kBAAkB;IAClB,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO;IAUhC,6BAA6B;IAC7B,KAAK,CAAC,IAAI,GAAE,MAA0B,EAAE,MAAM,SAAK,GAAG,IAAI;IAa1D,mBAAmB;IACnB,SAAS,IAAI,IAAI;IAOV,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,gBAAgB,CAAC;IAgBxE,kDAAkD;IAClD,KAAK,IAAI,IAAI;IAab;;;OAGG;IACH,kBAAkB,IAAI,OAAO;CAkG9B"}
@@ -0,0 +1,287 @@
1
+ import { CLOSE_CODE, isValidCloseCode } from "./close-code.js";
2
+ /**
3
+ * 服务端 WebSocket 连接。
4
+ *
5
+ * ```ts
6
+ * app.ws('/chat', (socket) => ({
7
+ * onMessage: (socket, message) => socket.send(message.data),
8
+ * }))
9
+ * ```
10
+ *
11
+ * 握手、帧编解码、协议协商、关闭握手与自动 pong 都由 `ws` 完成;
12
+ * 本类只做事件与消息形状的适配。
13
+ */
14
+ export class WebSocketConnection {
15
+ #ws;
16
+ #listeners = new Map();
17
+ /** `start()` 之后因异步迭代而积压的消息 */
18
+ #queue = [];
19
+ /** `start()` 之前收到的消息,按序补发 */
20
+ #early = [];
21
+ #waiters = [];
22
+ #state = 'open';
23
+ #protocol;
24
+ #pingInterval;
25
+ #idleTimeout;
26
+ #closeCode = CLOSE_CODE.NO_STATUS;
27
+ #closeReason = '';
28
+ #started = false;
29
+ #flushed = false;
30
+ #iterating = false;
31
+ #pending = [];
32
+ #pingTimer;
33
+ #idleTimer;
34
+ constructor(ws, options = {}) {
35
+ this.#ws = ws;
36
+ this.#protocol = options.protocol ?? ws.protocol ?? '';
37
+ this.#pingInterval = options.pingInterval;
38
+ this.#idleTimeout = options.idleTimeout;
39
+ ws.on('message', (data, isBinary) => this.#onMessage(data, isBinary));
40
+ ws.on('close', (code, reason) => this.#onClose(code, reason.toString()));
41
+ ws.on('error', (error) => this.#onError(error));
42
+ ws.on('ping', (data) => {
43
+ this.#resetIdleTimer();
44
+ this.#emit('ping', toUint8(data));
45
+ });
46
+ ws.on('pong', (data) => {
47
+ this.#resetIdleTimer();
48
+ this.#emit('pong', toUint8(data));
49
+ });
50
+ }
51
+ get readyState() {
52
+ switch (this.#ws.readyState) {
53
+ case 2:
54
+ return 'closing';
55
+ case 3:
56
+ return 'closed';
57
+ default:
58
+ return this.#state;
59
+ }
60
+ }
61
+ get protocol() {
62
+ return this.#protocol;
63
+ }
64
+ get bufferedAmount() {
65
+ return this.#ws.bufferedAmount;
66
+ }
67
+ get remoteAddress() {
68
+ const socket = this.#ws._socket;
69
+ return socket?.remoteAddress;
70
+ }
71
+ on(event, listener) {
72
+ let set = this.#listeners.get(event);
73
+ if (!set) {
74
+ set = new Set();
75
+ this.#listeners.set(event, set);
76
+ }
77
+ set.add(listener);
78
+ return this;
79
+ }
80
+ off(event, listener) {
81
+ this.#listeners.get(event)?.delete(listener);
82
+ return this;
83
+ }
84
+ once(event, listener) {
85
+ const wrapped = ((...args) => {
86
+ this.off(event, wrapped);
87
+ listener(...args);
88
+ });
89
+ return this.on(event, wrapped);
90
+ }
91
+ /** 发送文本或二进制消息,返回 false 表示内核缓冲区已满 */
92
+ send(data) {
93
+ if (this.readyState !== 'open') {
94
+ throw new Error('WebSocket is not open');
95
+ }
96
+ this.#ws.send(data);
97
+ return this.#ws.bufferedAmount === 0;
98
+ }
99
+ /** 发送 ping 控制帧 */
100
+ ping(data) {
101
+ if (this.#state === 'closed' || this.#ws.readyState !== 1)
102
+ return false;
103
+ const payload = data ?? new Uint8Array(0);
104
+ if (payload.byteLength > 125) {
105
+ throw new RangeError('Control frame payload must be <= 125 bytes');
106
+ }
107
+ this.#ws.ping(payload);
108
+ return true;
109
+ }
110
+ /** 发送 pong 控制帧 */
111
+ pong(data) {
112
+ if (this.#state === 'closed' || this.#ws.readyState !== 1)
113
+ return false;
114
+ const payload = data ?? new Uint8Array(0);
115
+ if (payload.byteLength > 125) {
116
+ throw new RangeError('Control frame payload must be <= 125 bytes');
117
+ }
118
+ this.#ws.pong(payload);
119
+ return true;
120
+ }
121
+ /** 发起关闭握手;不传 code 表示 1000 */
122
+ close(code = CLOSE_CODE.NORMAL, reason = '') {
123
+ if (this.#state !== 'open' || this.#ws.readyState !== 1)
124
+ return;
125
+ if (!isValidCloseCode(code)) {
126
+ throw new RangeError(`Invalid WebSocket close code: ${code}`);
127
+ }
128
+ this.#state = 'closing';
129
+ this.#closeCode = code;
130
+ this.#closeReason = reason;
131
+ this.#stopKeepalive();
132
+ this.#ws.close(code, reason);
133
+ }
134
+ /** 立即断开,不进行关闭握手 */
135
+ terminate() {
136
+ if (this.#state === 'closed')
137
+ return;
138
+ this.#state = 'closed';
139
+ this.#stopTimers();
140
+ this.#ws.terminate();
141
+ }
142
+ async *[Symbol.asyncIterator]() {
143
+ this.#iterating = true;
144
+ while (true) {
145
+ if (this.#queue.length > 0) {
146
+ yield this.#queue.shift();
147
+ continue;
148
+ }
149
+ if (this.readyState === 'closed')
150
+ return;
151
+ const result = await new Promise((resolve, reject) => this.#waiters.push({ resolve, reject }));
152
+ if (result.done)
153
+ return;
154
+ yield result.value;
155
+ }
156
+ }
157
+ /** @internal 由框架在业务 handler 执行前调用,补发升级后立即到达的消息 */
158
+ start() {
159
+ if (this.#started)
160
+ return;
161
+ this.#started = true;
162
+ for (const message of this.#early.splice(0))
163
+ this.#pushMessage(message);
164
+ this.#flushPending();
165
+ if (this.#pingInterval && this.#pingInterval > 0) {
166
+ this.#pingTimer = setInterval(() => this.ping(), this.#pingInterval);
167
+ this.#pingTimer.unref?.();
168
+ }
169
+ this.#resetIdleTimer();
170
+ }
171
+ /**
172
+ * @internal dev 护栏:连接是否已有消息消费者
173
+ * (`onMessage` 会经 `message` 事件派发;也计入用户监听器与活跃迭代)
174
+ */
175
+ hasMessageConsumer() {
176
+ return (this.#listeners.get('message')?.size ?? 0) > 0 || this.#iterating;
177
+ }
178
+ // -------------------------------------------------------------------------
179
+ #onMessage(data, isBinary) {
180
+ this.#resetIdleTimer();
181
+ const message = isBinary
182
+ ? { data: toUint8(data), binary: true }
183
+ : { data: decodeText(data), binary: false };
184
+ if (this.#started)
185
+ this.#pushMessage(message);
186
+ else
187
+ this.#early.push(message);
188
+ }
189
+ #onClose(code, reason) {
190
+ this.#closeCode = code;
191
+ this.#closeReason = reason;
192
+ this.#state = 'closed';
193
+ this.#stopTimers();
194
+ this.#finish();
195
+ }
196
+ #onError(error) {
197
+ this.#emit('error', error);
198
+ if (this.readyState === 'closed' && this.#state !== 'closed') {
199
+ this.#onClose(this.#closeCode, this.#closeReason);
200
+ }
201
+ }
202
+ #pushMessage(message) {
203
+ const waiter = this.#waiters.shift();
204
+ if (waiter) {
205
+ waiter.resolve({ value: message, done: false });
206
+ }
207
+ else if (this.#iterating) {
208
+ this.#queue.push(message);
209
+ }
210
+ this.#emit('message', message.data, message.binary);
211
+ }
212
+ #finish() {
213
+ if (this.#flushed)
214
+ return;
215
+ this.#flushed = true;
216
+ for (const waiter of this.#waiters.splice(0)) {
217
+ waiter.resolve({ value: undefined, done: true });
218
+ }
219
+ this.#emit('close', this.#closeCode, this.#closeReason);
220
+ }
221
+ #resetIdleTimer() {
222
+ if (!this.#idleTimeout || this.#idleTimeout <= 0)
223
+ return;
224
+ if (this.#idleTimer)
225
+ clearTimeout(this.#idleTimer);
226
+ this.#idleTimer = setTimeout(() => {
227
+ this.close(CLOSE_CODE.GOING_AWAY, 'Idle timeout');
228
+ }, this.#idleTimeout);
229
+ this.#idleTimer.unref?.();
230
+ }
231
+ #stopTimers() {
232
+ this.#stopKeepalive();
233
+ }
234
+ #stopKeepalive() {
235
+ if (this.#pingTimer)
236
+ clearInterval(this.#pingTimer);
237
+ if (this.#idleTimer)
238
+ clearTimeout(this.#idleTimer);
239
+ this.#pingTimer = undefined;
240
+ this.#idleTimer = undefined;
241
+ }
242
+ #emit(event, ...args) {
243
+ const dispatch = () => {
244
+ const listeners = this.#listeners.get(event);
245
+ if (!listeners)
246
+ return;
247
+ for (const listener of listeners) {
248
+ try {
249
+ listener(...args);
250
+ }
251
+ catch (error) {
252
+ if (event !== 'error') {
253
+ this.#emit('error', error instanceof Error ? error : new Error(String(error)));
254
+ }
255
+ else {
256
+ console.error(error);
257
+ }
258
+ }
259
+ }
260
+ };
261
+ if (this.#started)
262
+ dispatch();
263
+ else
264
+ this.#pending.push(dispatch);
265
+ }
266
+ #flushPending() {
267
+ const pending = this.#pending;
268
+ this.#pending = [];
269
+ for (const task of pending)
270
+ task();
271
+ }
272
+ }
273
+ function toUint8(data) {
274
+ if (Array.isArray(data))
275
+ return new Uint8Array(Buffer.concat(data));
276
+ if (data instanceof ArrayBuffer)
277
+ return new Uint8Array(data);
278
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
279
+ }
280
+ function decodeText(data) {
281
+ if (Array.isArray(data))
282
+ return Buffer.concat(data).toString('utf8');
283
+ if (data instanceof ArrayBuffer)
284
+ return Buffer.from(data).toString('utf8');
285
+ return data.toString('utf8');
286
+ }
287
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/websocket/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { acceptWebSocket, validateUpgradeRequest } from './accept.ts';
2
+ export type { AcceptOptions } from './accept.ts';
3
+ export { CLOSE_CODE, isValidCloseCode } from './close-code.ts';
4
+ export { WebSocketConnection } from './connection.ts';
5
+ export type { WebSocketConnectionOptions, WebSocketEventMap, WebSocketMessage, WebSocketReadyState, } from './connection.ts';
6
+ export type { WebSocketHandler, WebSocketHandlers, WebSocketLifecycle, WebSocketMiddleware, WebSocketNext, WebSocketOptions, WsRegistrar, } from './types.ts';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACrE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,WAAW,GACZ,MAAM,YAAY,CAAA"}
@@ -0,0 +1,4 @@
1
+ export { acceptWebSocket, validateUpgradeRequest } from "./accept.js";
2
+ export { CLOSE_CODE, isValidCloseCode } from "./close-code.js";
3
+ export { WebSocketConnection } from "./connection.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAErE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,66 @@
1
+ import type { Context, ContextWithParams, Middleware, Next } from '../types.ts';
2
+ import type { WebSocketConnection, WebSocketMessage } from './connection.ts';
3
+ /** 每条 WS 路由 / 升级请求的选项 */
4
+ export interface WebSocketOptions {
5
+ /** 服务端支持的子协议,按客户端优先级挑选第一个匹配项 */
6
+ protocols?: string[];
7
+ /** 单条消息(分片合并后)最大字节数,默认 4 MiB */
8
+ maxMessageSize?: number;
9
+ /** 自动回 pong,默认 true */
10
+ autoPong?: boolean;
11
+ /** close 握手超时(ms),默认 5000 */
12
+ closeTimeout?: number;
13
+ /** 服务端主动 ping 间隔(ms),默认关闭 */
14
+ pingInterval?: number;
15
+ /** 空闲超时(ms),默认关闭 */
16
+ idleTimeout?: number;
17
+ /** 追加到 101 响应里的头 */
18
+ headers?: Record<string, string>;
19
+ }
20
+ /**
21
+ * 连接的生命周期回调。三者都可选;回调抛错会走 `onError` →
22
+ * `app.onError` → `console.error`,并默认以 1011 关闭连接。
23
+ */
24
+ export interface WebSocketLifecycle<C extends Context = Context> {
25
+ /** 每条消息按到达顺序串行 await(天然背压) */
26
+ onMessage?(socket: WebSocketConnection, message: WebSocketMessage, ctx: C): void | Promise<void>;
27
+ /** 恰好调用一次(正常关闭 / 错误 / terminate) */
28
+ onClose?(socket: WebSocketConnection, code: number, reason: string, ctx: C): void | Promise<void>;
29
+ /** 消息/关闭回调或底层连接出错;抛错则回落 `app.onError` → `console.error` */
30
+ onError?(socket: WebSocketConnection, error: Error, ctx: C): void | Promise<void>;
31
+ }
32
+ /**
33
+ * WebSocket 终端:**工厂**,每连接调用一次(可异步)。
34
+ *
35
+ * - 工厂体就是 open 钩子(欢迎语、异步加入房间都写在这里)
36
+ * - 闭包就是连接级状态(定时器、房间订阅……),无需外部 WeakMap
37
+ * - 返回生命周期对象;返回 `void` 表示纯流式模式(自行 `socket.on` / `for await`)
38
+ * - 工厂结算前到达的消息由框架缓冲,不会丢
39
+ */
40
+ export type WebSocketHandler<C extends Context = Context> = (socket: WebSocketConnection, ctx: C) => WebSocketLifecycle<C> | void | Promise<WebSocketLifecycle<C> | void>;
41
+ /** WS 中间件的 `next`:返回 HTTP `Response` 表示拒绝升级 */
42
+ export type WebSocketNext<Out extends Context = Context> = Next<Out, Response | void>;
43
+ /**
44
+ * WebSocket 中间件:与 HTTP 中间件是同一个 {@link Middleware} 类型,
45
+ * 结果类型固定为 `Response | void`(同一个实例可以同时用于 `app.use` 与 `app.ws`,
46
+ * 但需要把中间件注解为 `Middleware<In, Out, Response | void>`)。
47
+ */
48
+ export type WebSocketMiddleware<In extends Context = Context, Out extends Context = In> = Middleware<In, Out, Response | void>;
49
+ /** 一条 WS 路由的处理链:任意个中间件 + 最后的处理器工厂 */
50
+ export type WebSocketHandlers<C extends Context, Path extends string> = [
51
+ ...middlewares: WebSocketMiddleware<ContextWithParams<C, Path>>[],
52
+ handler: WebSocketHandler<ContextWithParams<C, Path>>
53
+ ];
54
+ /** `app.ws(path, ...)` 的调用签名 */
55
+ export interface WsRegistrar<C extends Context, Prefix extends string, R> {
56
+ <P extends string>(path: P, handler: WebSocketHandler<ContextWithParams<C, `${Prefix}${P}`>>): R;
57
+ <P extends string, O1 extends Context>(path: P, middleware: WebSocketMiddleware<ContextWithParams<C, `${Prefix}${P}`>, O1>, handler: WebSocketHandler<O1 & ContextWithParams<C, `${Prefix}${P}`>>): R;
58
+ <P extends string, O1 extends Context, O2 extends Context>(path: P, middleware1: WebSocketMiddleware<ContextWithParams<C, `${Prefix}${P}`>, O1>, middleware2: WebSocketMiddleware<O1 & ContextWithParams<C, `${Prefix}${P}`>, O2>, handler: WebSocketHandler<O2 & ContextWithParams<C, `${Prefix}${P}`>>): R;
59
+ <P extends string>(path: P, options: WebSocketOptions, handler: WebSocketHandler<ContextWithParams<C, `${Prefix}${P}`>>): R;
60
+ <P extends string, O1 extends Context>(path: P, options: WebSocketOptions, middleware: WebSocketMiddleware<ContextWithParams<C, `${Prefix}${P}`>, O1>, handler: WebSocketHandler<O1 & ContextWithParams<C, `${Prefix}${P}`>>): R;
61
+ /** 带选项、3 个及以上中间件:类型不再逐步累积 */
62
+ <P extends string>(path: P, options: WebSocketOptions, ...handlers: WebSocketHandlers<C, `${Prefix}${P}`>): R;
63
+ /** 3 个及以上中间件:类型不再逐步累积 */
64
+ <P extends string>(path: P, ...handlers: WebSocketHandlers<C, `${Prefix}${P}`>): R;
65
+ }
66
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/websocket/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/websocket/types.ts"],"names":[],"mappings":""}