sx-peerjs-http-util 1.0.1

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 ADDED
@@ -0,0 +1,172 @@
1
+ # sx-peerjs-http-util
2
+
3
+ 一个浏览器端库,将 PeerJS 封装成简单易用的类似 HTTP 的 API。
4
+
5
+ ## 特性
6
+
7
+ - 简单的请求-响应 API,类似 HTTP
8
+ - 基于 PeerJS (WebRTC) 实现 P2P 通信
9
+ - TypeScript 支持
10
+ - 完整的 E2E 测试
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ npm install sx-peerjs-http-util peerjs
16
+ ```
17
+
18
+ ## API
19
+
20
+ ### Request
21
+
22
+ ```typescript
23
+ interface Request {
24
+ method?: string;
25
+ data?: unknown;
26
+ }
27
+ ```
28
+
29
+ ### Response
30
+
31
+ ```typescript
32
+ interface Response {
33
+ status: number;
34
+ data: unknown;
35
+ }
36
+ ```
37
+
38
+ ### request(options: RequestOptions): Promise<Response>
39
+
40
+ 发送请求到指定 Peer。
41
+
42
+ ```typescript
43
+ import { request } from 'sx-peerjs-http-util';
44
+
45
+ const response = await request({
46
+ peerId: 'remote-peer-id',
47
+ request: {
48
+ method: 'GET',
49
+ data: { message: 'Hello' },
50
+ },
51
+ });
52
+
53
+ console.log(response.status); // 200
54
+ console.log(response.data); // { message: 'Response from server' }
55
+ ```
56
+
57
+ ### createServer(peer: Peer, handler: RequestHandler): () => void
58
+
59
+ 创建一个 PeerJS HTTP 服务器。
60
+
61
+ ```typescript
62
+ import { createServer } from 'sx-peerjs-http-util';
63
+ import { Peer } from 'peerjs';
64
+
65
+ const peer = new Peer();
66
+
67
+ const handler = async (request) => {
68
+ return {
69
+ status: 200,
70
+ data: {
71
+ message: 'Hello from server',
72
+ received: request.data,
73
+ },
74
+ };
75
+ };
76
+
77
+ const cleanup = createServer(peer, handler);
78
+
79
+ // 清理时调用
80
+ cleanup();
81
+ ```
82
+
83
+ ## 完整示例
84
+
85
+ ### 服务器端
86
+
87
+ ```html
88
+ <!DOCTYPE html>
89
+ <html>
90
+ <head>
91
+ <script src="https://unpkg.com/peerjs@1.5.5/dist/peerjs.min.js"></script>
92
+ <script type="module">
93
+ import { createServer } from './dist/index.js';
94
+
95
+ const peer = new Peer();
96
+
97
+ peer.on('open', (id) => {
98
+ console.log('My Peer ID:', id);
99
+ });
100
+
101
+ const handler = async (request) => {
102
+ // 处理请求
103
+ if (request.method === 'ECHO') {
104
+ return {
105
+ status: 200,
106
+ data: request.data,
107
+ };
108
+ }
109
+
110
+ return {
111
+ status: 200,
112
+ data: { message: 'OK' },
113
+ };
114
+ };
115
+
116
+ createServer(peer, handler);
117
+ </script>
118
+ </head>
119
+ <body>
120
+ <h1>Server</h1>
121
+ <div id="peer-id"></div>
122
+ </body>
123
+ </html>
124
+ ```
125
+
126
+ ### 客户端
127
+
128
+ ```html
129
+ <!DOCTYPE html>
130
+ <html>
131
+ <head>
132
+ <script src="https://unpkg.com/peerjs@1.5.5/dist/peerjs.min.js"></script>
133
+ <script type="module">
134
+ import { request } from './dist/index.js';
135
+
136
+ async function sendRequest() {
137
+ const response = await request({
138
+ peerId: 'server-peer-id',
139
+ request: {
140
+ method: 'ECHO',
141
+ data: { test: 'data' },
142
+ },
143
+ });
144
+
145
+ console.log('Response:', response);
146
+ }
147
+
148
+ // 调用
149
+ sendRequest();
150
+ </script>
151
+ </head>
152
+ <body>
153
+ <h1>Client</h1>
154
+ <button onclick="sendRequest()">Send Request</button>
155
+ </body>
156
+ </html>
157
+ ```
158
+
159
+ ## E2E 测试
160
+
161
+ 运行端到端测试:
162
+
163
+ ```bash
164
+ npm run test:e2e
165
+ ```
166
+
167
+ ## 注意事项
168
+
169
+ - 每次请求都会创建新的 Peer 连接,请求完成后会自动清理
170
+ - 请求超时时间为 30 秒
171
+ - 此库仅用于浏览器环境
172
+ - 需要使用 PeerJS 信令服务器(默认使用公共服务器)
@@ -0,0 +1,17 @@
1
+ import type { Request, Response, RequestOptions, ServerOptions, RequestHandler, ConnectionData } from './types';
2
+ /**
3
+ * 发送 HTTP 请求到指定 Peer
4
+ * @param options 请求选项
5
+ * @returns Promise<Response>
6
+ */
7
+ export declare function request(options: RequestOptions): Promise<Response>;
8
+ /**
9
+ * 创建 PeerJS HTTP 服务器
10
+ * @param options 服务端选项
11
+ * @param handler 请求处理器
12
+ * @returns 清理函数
13
+ */
14
+ export declare function createServer(peer: any, // Peer 实例
15
+ handler: RequestHandler): () => void;
16
+ export type { Request, Response, RequestOptions, ServerOptions, RequestHandler, ConnectionData };
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAUhH;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiExE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,GAAG,EAAE,UAAU;AACrB,OAAO,EAAE,cAAc,GACtB,MAAM,IAAI,CAuDZ;AAGD,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,116 @@
1
+ import { Peer } from 'peerjs';
2
+ /**
3
+ * 发送 HTTP 请求到指定 Peer
4
+ * @param options 请求选项
5
+ * @returns Promise<Response>
6
+ */
7
+ export async function request(options) {
8
+ const { peerId, request } = options;
9
+ return new Promise((resolve, reject) => {
10
+ // 创建临时 Peer 用于发送请求
11
+ const tempPeer = new Peer();
12
+ // 超时处理
13
+ const timeout = setTimeout(() => {
14
+ conn.close();
15
+ tempPeer.destroy();
16
+ reject(new Error('Request timeout'));
17
+ }, 30000);
18
+ let conn;
19
+ let requestId;
20
+ tempPeer.on('open', (id) => {
21
+ // 连接到对端 Peer
22
+ conn = tempPeer.connect(peerId, {
23
+ reliable: true,
24
+ });
25
+ conn.on('open', () => {
26
+ // 生成请求 ID
27
+ requestId = `${tempPeer.id}-${Date.now()}`;
28
+ // 发送请求
29
+ const message = {
30
+ type: 'request',
31
+ id: requestId,
32
+ request,
33
+ };
34
+ conn.send(message);
35
+ });
36
+ conn.on('data', (data) => {
37
+ const message = data;
38
+ if (message.type === 'response' && message.id === requestId) {
39
+ clearTimeout(timeout);
40
+ conn.close();
41
+ tempPeer.destroy();
42
+ resolve(message.response);
43
+ }
44
+ });
45
+ conn.on('error', (err) => {
46
+ clearTimeout(timeout);
47
+ tempPeer.destroy();
48
+ reject(err);
49
+ });
50
+ conn.on('close', () => {
51
+ clearTimeout(timeout);
52
+ tempPeer.destroy();
53
+ });
54
+ });
55
+ tempPeer.on('error', (err) => {
56
+ clearTimeout(timeout);
57
+ reject(err);
58
+ });
59
+ });
60
+ }
61
+ /**
62
+ * 创建 PeerJS HTTP 服务器
63
+ * @param options 服务端选项
64
+ * @param handler 请求处理器
65
+ * @returns 清理函数
66
+ */
67
+ export function createServer(peer, // Peer 实例
68
+ handler) {
69
+ const connections = new Set();
70
+ // 处理传入连接
71
+ peer.on('connection', (conn) => {
72
+ connections.add(conn);
73
+ conn.on('data', async (data) => {
74
+ const message = data;
75
+ if (message.type === 'request') {
76
+ try {
77
+ // 调用处理器处理请求
78
+ const response = await handler(message.request);
79
+ // 发送响应
80
+ const responseMessage = {
81
+ type: 'response',
82
+ id: message.id,
83
+ response,
84
+ };
85
+ conn.send(responseMessage);
86
+ }
87
+ catch (error) {
88
+ // 发送错误响应
89
+ const errorResponse = {
90
+ type: 'response',
91
+ id: message.id,
92
+ response: {
93
+ status: 500,
94
+ data: { error: error instanceof Error ? error.message : 'Unknown error' },
95
+ },
96
+ };
97
+ conn.send(errorResponse);
98
+ }
99
+ }
100
+ });
101
+ conn.on('close', () => {
102
+ connections.delete(conn);
103
+ });
104
+ conn.on('error', () => {
105
+ connections.delete(conn);
106
+ });
107
+ });
108
+ // 返回清理函数
109
+ return () => {
110
+ for (const conn of connections) {
111
+ conn.close();
112
+ }
113
+ connections.clear();
114
+ };
115
+ }
116
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 请求数据结构
3
+ */
4
+ export interface Request {
5
+ /** 请求方法 */
6
+ method?: string;
7
+ /** 请求数据 */
8
+ data?: unknown;
9
+ }
10
+ /**
11
+ * 响应数据结构
12
+ */
13
+ export interface Response {
14
+ /** 响应状态码 */
15
+ status: number;
16
+ /** 响应数据 */
17
+ data: unknown;
18
+ }
19
+ /**
20
+ * PeerJS HTTP 请求选项
21
+ */
22
+ export interface RequestOptions {
23
+ /** 对端设备的 Peer ID */
24
+ peerId: string;
25
+ /** 请求数据 */
26
+ request: Request;
27
+ }
28
+ /**
29
+ * PeerJS HTTP 服务端选项
30
+ */
31
+ export interface ServerOptions {
32
+ /** PeerJS 实例 */
33
+ peer: any;
34
+ }
35
+ /**
36
+ * 请求处理器函数类型
37
+ */
38
+ export type RequestHandler = (request: Request) => Promise<Response> | Response;
39
+ /**
40
+ * 连接事件数据
41
+ */
42
+ export interface ConnectionData {
43
+ /** 发送请求 */
44
+ send: (request: Request) => Promise<Response>;
45
+ /** 关闭连接 */
46
+ close: () => void;
47
+ }
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW;IACX,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,YAAY;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB;IAChB,IAAI,EAAE,GAAG,CAAC;CACX;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW;IACX,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,WAAW;IACX,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "sx-peerjs-http-util",
3
+ "version": "1.0.1",
4
+ "description": "A browser library that wraps PeerJS with a simple HTTP-like API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test:e2e": "playwright test",
11
+ "prepare": "npm run build"
12
+ },
13
+ "keywords": [
14
+ "peerjs",
15
+ "webrtc",
16
+ "p2p",
17
+ "http",
18
+ "browser",
19
+ "e2e"
20
+ ],
21
+ "author": "",
22
+ "license": "ISC",
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "dependencies": {
27
+ "peerjs": "^1.5.5"
28
+ },
29
+ "devDependencies": {
30
+ "@playwright/test": "^1.50.0",
31
+ "@types/node": "^22.14.0",
32
+ "typescript": "^5.8.3"
33
+ }
34
+ }