request-iframe 0.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.
Files changed (96) hide show
  1. package/QUICKSTART.CN.md +269 -0
  2. package/QUICKSTART.md +269 -0
  3. package/README.CN.md +1369 -0
  4. package/README.md +1016 -0
  5. package/library/__tests__/interceptors.test.ts +124 -0
  6. package/library/__tests__/requestIframe.test.ts +2216 -0
  7. package/library/__tests__/stream.test.ts +650 -0
  8. package/library/__tests__/utils.test.ts +433 -0
  9. package/library/api/client.d.ts +16 -0
  10. package/library/api/client.d.ts.map +1 -0
  11. package/library/api/client.js +72 -0
  12. package/library/api/server.d.ts +16 -0
  13. package/library/api/server.d.ts.map +1 -0
  14. package/library/api/server.js +44 -0
  15. package/library/constants/index.d.ts +209 -0
  16. package/library/constants/index.d.ts.map +1 -0
  17. package/library/constants/index.js +260 -0
  18. package/library/constants/messages.d.ts +80 -0
  19. package/library/constants/messages.d.ts.map +1 -0
  20. package/library/constants/messages.js +123 -0
  21. package/library/core/client.d.ts +99 -0
  22. package/library/core/client.d.ts.map +1 -0
  23. package/library/core/client.js +440 -0
  24. package/library/core/message-handler.d.ts +110 -0
  25. package/library/core/message-handler.d.ts.map +1 -0
  26. package/library/core/message-handler.js +320 -0
  27. package/library/core/request-response.d.ts +59 -0
  28. package/library/core/request-response.d.ts.map +1 -0
  29. package/library/core/request-response.js +337 -0
  30. package/library/core/request.d.ts +17 -0
  31. package/library/core/request.d.ts.map +1 -0
  32. package/library/core/request.js +34 -0
  33. package/library/core/response.d.ts +51 -0
  34. package/library/core/response.d.ts.map +1 -0
  35. package/library/core/response.js +323 -0
  36. package/library/core/server-base.d.ts +86 -0
  37. package/library/core/server-base.d.ts.map +1 -0
  38. package/library/core/server-base.js +257 -0
  39. package/library/core/server-client.d.ts +99 -0
  40. package/library/core/server-client.d.ts.map +1 -0
  41. package/library/core/server-client.js +256 -0
  42. package/library/core/server.d.ts +82 -0
  43. package/library/core/server.d.ts.map +1 -0
  44. package/library/core/server.js +338 -0
  45. package/library/index.d.ts +16 -0
  46. package/library/index.d.ts.map +1 -0
  47. package/library/index.js +211 -0
  48. package/library/interceptors/index.d.ts +41 -0
  49. package/library/interceptors/index.d.ts.map +1 -0
  50. package/library/interceptors/index.js +126 -0
  51. package/library/message/channel.d.ts +107 -0
  52. package/library/message/channel.d.ts.map +1 -0
  53. package/library/message/channel.js +184 -0
  54. package/library/message/dispatcher.d.ts +119 -0
  55. package/library/message/dispatcher.d.ts.map +1 -0
  56. package/library/message/dispatcher.js +249 -0
  57. package/library/message/index.d.ts +5 -0
  58. package/library/message/index.d.ts.map +1 -0
  59. package/library/message/index.js +25 -0
  60. package/library/stream/file-stream.d.ts +48 -0
  61. package/library/stream/file-stream.d.ts.map +1 -0
  62. package/library/stream/file-stream.js +240 -0
  63. package/library/stream/index.d.ts +15 -0
  64. package/library/stream/index.d.ts.map +1 -0
  65. package/library/stream/index.js +83 -0
  66. package/library/stream/readable-stream.d.ts +83 -0
  67. package/library/stream/readable-stream.d.ts.map +1 -0
  68. package/library/stream/readable-stream.js +249 -0
  69. package/library/stream/types.d.ts +165 -0
  70. package/library/stream/types.d.ts.map +1 -0
  71. package/library/stream/types.js +5 -0
  72. package/library/stream/writable-stream.d.ts +60 -0
  73. package/library/stream/writable-stream.d.ts.map +1 -0
  74. package/library/stream/writable-stream.js +348 -0
  75. package/library/types/index.d.ts +408 -0
  76. package/library/types/index.d.ts.map +1 -0
  77. package/library/types/index.js +5 -0
  78. package/library/utils/cache.d.ts +19 -0
  79. package/library/utils/cache.d.ts.map +1 -0
  80. package/library/utils/cache.js +83 -0
  81. package/library/utils/cookie.d.ts +117 -0
  82. package/library/utils/cookie.d.ts.map +1 -0
  83. package/library/utils/cookie.js +365 -0
  84. package/library/utils/debug.d.ts +11 -0
  85. package/library/utils/debug.d.ts.map +1 -0
  86. package/library/utils/debug.js +162 -0
  87. package/library/utils/index.d.ts +13 -0
  88. package/library/utils/index.d.ts.map +1 -0
  89. package/library/utils/index.js +132 -0
  90. package/library/utils/path-match.d.ts +17 -0
  91. package/library/utils/path-match.d.ts.map +1 -0
  92. package/library/utils/path-match.js +90 -0
  93. package/library/utils/protocol.d.ts +61 -0
  94. package/library/utils/protocol.d.ts.map +1 -0
  95. package/library/utils/protocol.js +169 -0
  96. package/package.json +58 -0
@@ -0,0 +1,269 @@
1
+ # 快速开始
2
+
3
+ 5 分钟上手 request-iframe,像发送 HTTP 请求一样与 iframe 通信!
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install request-iframe
9
+ # 或
10
+ yarn add request-iframe
11
+ ```
12
+
13
+ ## 场景说明
14
+
15
+ 假设你有一个父页面需要和嵌入的 iframe 通信:
16
+
17
+ ```
18
+ ┌─────────────────────────────────────────┐
19
+ │ 父页面 (parent.html) │
20
+ │ ┌───────────────────────────────────┐ │
21
+ │ │ iframe (child.html) │ │
22
+ │ │ │ │
23
+ │ │ 需要获取 iframe 内的数据 │ │
24
+ │ │ │ │
25
+ │ └───────────────────────────────────┘ │
26
+ └─────────────────────────────────────────┘
27
+ ```
28
+
29
+ ## Step 1: 父页面创建 Client
30
+
31
+ ```typescript
32
+ // parent.html
33
+ import { requestIframeClient } from 'request-iframe';
34
+
35
+ // 获取 iframe 元素
36
+ const iframe = document.getElementById('my-iframe') as HTMLIFrameElement;
37
+
38
+ // 创建 client(用于发送请求)
39
+ const client = requestIframeClient(iframe, {
40
+ secretKey: 'my-app' // 消息隔离标识,需要和 iframe 内保持一致
41
+ });
42
+
43
+ // 发送请求并等待响应
44
+ async function getUserInfo(userId: number) {
45
+ const response = await client.send('/api/getUserInfo', { userId });
46
+ return response.data;
47
+ }
48
+
49
+ // 使用
50
+ const user = await getUserInfo(123);
51
+ console.log(user); // { name: 'Tom', age: 18 }
52
+ ```
53
+
54
+ ## Step 2: iframe 内创建 Server
55
+
56
+ ```typescript
57
+ // child.html (iframe 内)
58
+ import { requestIframeServer } from 'request-iframe';
59
+
60
+ // 创建 server(用于接收请求)
61
+ const server = requestIframeServer({
62
+ secretKey: 'my-app' // 必须和父页面的 client 保持一致!
63
+ });
64
+
65
+ // 注册请求处理器
66
+ server.on('/api/getUserInfo', (req, res) => {
67
+ const { userId } = req.body;
68
+
69
+ // 模拟从数据库获取用户信息
70
+ const user = { name: 'Tom', age: 18 };
71
+
72
+ // 返回响应
73
+ res.send(user);
74
+ });
75
+ ```
76
+
77
+ **就是这么简单!** 🎉
78
+
79
+ ---
80
+
81
+ ## 更多示例
82
+
83
+ ### 异步处理
84
+
85
+ ```typescript
86
+ // Server 端
87
+ server.on('/api/fetchData', async (req, res) => {
88
+ // 异步操作(如网络请求)
89
+ const data = await fetch('https://api.example.com/data').then(r => r.json());
90
+ res.send(data);
91
+ });
92
+ ```
93
+
94
+ 当处理器返回 Promise 时,框架会自动:
95
+ 1. 通知 Client 这是异步任务
96
+ 2. 将超时时间从 5 秒切换到 120 秒
97
+
98
+ ### 错误处理
99
+
100
+ ```typescript
101
+ // Server 端
102
+ server.on('/api/getData', (req, res) => {
103
+ if (!req.body.id) {
104
+ return res.status(400).send({ error: '缺少 id 参数' });
105
+ }
106
+ res.send({ data: '...' });
107
+ });
108
+
109
+ // Client 端
110
+ try {
111
+ const response = await client.send('/api/getData', {});
112
+ } catch (error) {
113
+ if (error.response?.status === 400) {
114
+ console.error('参数错误:', error.response.data.error);
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### 添加鉴权
120
+
121
+ ```typescript
122
+ // Server 端添加中间件
123
+ server.use((req, res, next) => {
124
+ const token = req.headers['authorization'];
125
+
126
+ if (!token || !isValidToken(token)) {
127
+ return res.status(401).send({ error: '未授权' });
128
+ }
129
+
130
+ next(); // 继续执行
131
+ });
132
+
133
+ // Client 端添加请求拦截器
134
+ client.interceptors.request.use((config) => {
135
+ config.headers = {
136
+ ...config.headers,
137
+ 'Authorization': `Bearer ${getToken()}`
138
+ };
139
+ return config;
140
+ });
141
+ ```
142
+
143
+ ### 批量注册接口
144
+
145
+ ```typescript
146
+ server.map({
147
+ '/api/users/list': (req, res) => {
148
+ res.send([{ id: 1, name: 'Tom' }, { id: 2, name: 'Jerry' }]);
149
+ },
150
+ '/api/users/create': async (req, res) => {
151
+ const user = await createUser(req.body);
152
+ res.status(201).send(user);
153
+ },
154
+ '/api/users/delete': async (req, res) => {
155
+ await deleteUser(req.body.id);
156
+ res.send({ success: true });
157
+ }
158
+ });
159
+ ```
160
+
161
+ ### 文件下载
162
+
163
+ ```typescript
164
+ // Server 端
165
+ server.on('/api/download', async (req, res) => {
166
+ const content = '这是文件内容';
167
+ await res.sendFile(content, {
168
+ mimeType: 'text/plain',
169
+ fileName: 'example.txt'
170
+ });
171
+ });
172
+
173
+ // Client 端
174
+ const response = await client.send('/api/download', {});
175
+ if (response.fileData) {
176
+ // 创建下载链接
177
+ const blob = new Blob(
178
+ [atob(response.fileData.content)],
179
+ { type: response.fileData.mimeType }
180
+ );
181
+ const url = URL.createObjectURL(blob);
182
+
183
+ // 触发下载
184
+ const a = document.createElement('a');
185
+ a.href = url;
186
+ a.download = response.fileData.fileName || 'download';
187
+ a.click();
188
+ }
189
+ ```
190
+
191
+ ### 调试模式
192
+
193
+ 开启 trace 模式查看详细日志:
194
+
195
+ ```typescript
196
+ const client = requestIframeClient(iframe, {
197
+ secretKey: 'my-app',
198
+ trace: true // 开启调试日志
199
+ });
200
+
201
+ const server = requestIframeServer({
202
+ secretKey: 'my-app',
203
+ trace: true
204
+ });
205
+ ```
206
+
207
+ 控制台会输出:
208
+ ```
209
+ [request-iframe] [INFO] 📤 Request Start { path: '/api/getData', body: {...} }
210
+ [request-iframe] [INFO] 📨 ACK Received { requestId: 'req_xxx' }
211
+ [request-iframe] [INFO] ✅ Request Success { status: 200, data: {...} }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## 常见问题
217
+
218
+ ### Q: 为什么请求一直超时?
219
+
220
+ 检查以下几点:
221
+ 1. iframe 是否已加载完成
222
+ 2. Client 和 Server 的 `secretKey` 是否一致
223
+ 3. Server 的处理器路径是否正确
224
+
225
+ ### Q: 如何在 iframe 内向父页面发送请求?
226
+
227
+ ```typescript
228
+ // iframe 内
229
+ const client = requestIframeClient(window.parent, { secretKey: 'reverse' });
230
+ await client.send('/notify', { event: 'ready' });
231
+
232
+ // 父页面
233
+ const server = requestIframeServer({ secretKey: 'reverse' });
234
+ server.on('/notify', (req, res) => {
235
+ console.log('iframe 已就绪');
236
+ res.send({ ok: true });
237
+ });
238
+ ```
239
+
240
+ ### Q: 支持 TypeScript 吗?
241
+
242
+ 完全支持!所有 API 都有完整的类型定义。
243
+
244
+ ```typescript
245
+ import {
246
+ requestIframeClient,
247
+ requestIframeServer,
248
+ Response,
249
+ ServerRequest,
250
+ ServerResponse
251
+ } from 'request-iframe';
252
+
253
+ // 泛型支持
254
+ interface User {
255
+ id: number;
256
+ name: string;
257
+ }
258
+
259
+ const response = await client.send<User>('/api/user', { id: 1 });
260
+ console.log(response.data.name); // TypeScript 知道这是 string
261
+ ```
262
+
263
+ ---
264
+
265
+ ## 下一步
266
+
267
+ - 查看 [README.CN.md](./README.CN.md) 了解完整 API(中文)
268
+ - 查看 [README.md](./README.md) 了解完整 API(English)
269
+ - 查看 [src/__tests__](./src/__tests__) 目录下的测试用例获取更多示例
package/QUICKSTART.md ADDED
@@ -0,0 +1,269 @@
1
+ # Quick Start
2
+
3
+ Get started with request-iframe in 5 minutes - communicate with iframes like sending HTTP requests!
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install request-iframe
9
+ # or
10
+ yarn add request-iframe
11
+ ```
12
+
13
+ ## Scenario
14
+
15
+ Suppose you have a parent page that needs to communicate with an embedded iframe:
16
+
17
+ ```
18
+ ┌─────────────────────────────────────────┐
19
+ │ Parent Page (parent.html) │
20
+ │ ┌───────────────────────────────────┐ │
21
+ │ │ iframe (child.html) │ │
22
+ │ │ │ │
23
+ │ │ Need to get data from iframe │ │
24
+ │ │ │ │
25
+ │ └───────────────────────────────────┘ │
26
+ └─────────────────────────────────────────┘
27
+ ```
28
+
29
+ ## Step 1: Create Client in Parent Page
30
+
31
+ ```typescript
32
+ // parent.html
33
+ import { requestIframeClient } from 'request-iframe';
34
+
35
+ // Get iframe element
36
+ const iframe = document.getElementById('my-iframe') as HTMLIFrameElement;
37
+
38
+ // Create client (for sending requests)
39
+ const client = requestIframeClient(iframe, {
40
+ secretKey: 'my-app' // Message isolation identifier, must match iframe
41
+ });
42
+
43
+ // Send request and wait for response
44
+ async function getUserInfo(userId: number) {
45
+ const response = await client.send('/api/getUserInfo', { userId });
46
+ return response.data;
47
+ }
48
+
49
+ // Use
50
+ const user = await getUserInfo(123);
51
+ console.log(user); // { name: 'Tom', age: 18 }
52
+ ```
53
+
54
+ ## Step 2: Create Server in iframe
55
+
56
+ ```typescript
57
+ // child.html (inside iframe)
58
+ import { requestIframeServer } from 'request-iframe';
59
+
60
+ // Create server (for receiving requests)
61
+ const server = requestIframeServer({
62
+ secretKey: 'my-app' // Must match parent page's client!
63
+ });
64
+
65
+ // Register request handler
66
+ server.on('/api/getUserInfo', (req, res) => {
67
+ const { userId } = req.body;
68
+
69
+ // Simulate fetching user info from database
70
+ const user = { name: 'Tom', age: 18 };
71
+
72
+ // Return response
73
+ res.send(user);
74
+ });
75
+ ```
76
+
77
+ **That's it!** 🎉
78
+
79
+ ---
80
+
81
+ ## More Examples
82
+
83
+ ### Async Processing
84
+
85
+ ```typescript
86
+ // Server side
87
+ server.on('/api/fetchData', async (req, res) => {
88
+ // Async operation (like network request)
89
+ const data = await fetch('https://api.example.com/data').then(r => r.json());
90
+ res.send(data);
91
+ });
92
+ ```
93
+
94
+ When the handler returns a Promise, the framework automatically:
95
+ 1. Notifies Client this is an async task
96
+ 2. Switches timeout from 5 seconds to 120 seconds
97
+
98
+ ### Error Handling
99
+
100
+ ```typescript
101
+ // Server side
102
+ server.on('/api/getData', (req, res) => {
103
+ if (!req.body.id) {
104
+ return res.status(400).send({ error: 'Missing id parameter' });
105
+ }
106
+ res.send({ data: '...' });
107
+ });
108
+
109
+ // Client side
110
+ try {
111
+ const response = await client.send('/api/getData', {});
112
+ } catch (error) {
113
+ if (error.response?.status === 400) {
114
+ console.error('Parameter error:', error.response.data.error);
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Add Authentication
120
+
121
+ ```typescript
122
+ // Server side: Add middleware
123
+ server.use((req, res, next) => {
124
+ const token = req.headers['authorization'];
125
+
126
+ if (!token || !isValidToken(token)) {
127
+ return res.status(401).send({ error: 'Unauthorized' });
128
+ }
129
+
130
+ next(); // Continue execution
131
+ });
132
+
133
+ // Client side: Add request interceptor
134
+ client.interceptors.request.use((config) => {
135
+ config.headers = {
136
+ ...config.headers,
137
+ 'Authorization': `Bearer ${getToken()}`
138
+ };
139
+ return config;
140
+ });
141
+ ```
142
+
143
+ ### Batch Register Interfaces
144
+
145
+ ```typescript
146
+ server.map({
147
+ '/api/users/list': (req, res) => {
148
+ res.send([{ id: 1, name: 'Tom' }, { id: 2, name: 'Jerry' }]);
149
+ },
150
+ '/api/users/create': async (req, res) => {
151
+ const user = await createUser(req.body);
152
+ res.status(201).send(user);
153
+ },
154
+ '/api/users/delete': async (req, res) => {
155
+ await deleteUser(req.body.id);
156
+ res.send({ success: true });
157
+ }
158
+ });
159
+ ```
160
+
161
+ ### File Download
162
+
163
+ ```typescript
164
+ // Server side
165
+ server.on('/api/download', async (req, res) => {
166
+ const content = 'This is file content';
167
+ await res.sendFile(content, {
168
+ mimeType: 'text/plain',
169
+ fileName: 'example.txt'
170
+ });
171
+ });
172
+
173
+ // Client side
174
+ const response = await client.send('/api/download', {});
175
+ if (response.fileData) {
176
+ // Create download link
177
+ const blob = new Blob(
178
+ [atob(response.fileData.content)],
179
+ { type: response.fileData.mimeType }
180
+ );
181
+ const url = URL.createObjectURL(blob);
182
+
183
+ // Trigger download
184
+ const a = document.createElement('a');
185
+ a.href = url;
186
+ a.download = response.fileData.fileName || 'download';
187
+ a.click();
188
+ }
189
+ ```
190
+
191
+ ### Debug Mode
192
+
193
+ Enable trace mode to view detailed logs:
194
+
195
+ ```typescript
196
+ const client = requestIframeClient(iframe, {
197
+ secretKey: 'my-app',
198
+ trace: true // Enable debug logs
199
+ });
200
+
201
+ const server = requestIframeServer({
202
+ secretKey: 'my-app',
203
+ trace: true
204
+ });
205
+ ```
206
+
207
+ Console will output:
208
+ ```
209
+ [request-iframe] [INFO] 📤 Request Start { path: '/api/getData', body: {...} }
210
+ [request-iframe] [INFO] 📨 ACK Received { requestId: 'req_xxx' }
211
+ [request-iframe] [INFO] ✅ Request Success { status: 200, data: {...} }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Common Questions
217
+
218
+ ### Q: Why does the request keep timing out?
219
+
220
+ Check the following:
221
+ 1. Is the iframe fully loaded?
222
+ 2. Do Client and Server have the same `secretKey`?
223
+ 3. Is the Server handler path correct?
224
+
225
+ ### Q: How to send requests from iframe to parent page?
226
+
227
+ ```typescript
228
+ // Inside iframe
229
+ const client = requestIframeClient(window.parent, { secretKey: 'reverse' });
230
+ await client.send('/notify', { event: 'ready' });
231
+
232
+ // Parent page
233
+ const server = requestIframeServer({ secretKey: 'reverse' });
234
+ server.on('/notify', (req, res) => {
235
+ console.log('iframe is ready');
236
+ res.send({ ok: true });
237
+ });
238
+ ```
239
+
240
+ ### Q: Does it support TypeScript?
241
+
242
+ Fully supported! All APIs have complete type definitions.
243
+
244
+ ```typescript
245
+ import {
246
+ requestIframeClient,
247
+ requestIframeServer,
248
+ Response,
249
+ ServerRequest,
250
+ ServerResponse
251
+ } from 'request-iframe';
252
+
253
+ // Generic support
254
+ interface User {
255
+ id: number;
256
+ name: string;
257
+ }
258
+
259
+ const response = await client.send<User>('/api/user', { id: 1 });
260
+ console.log(response.data.name); // TypeScript knows this is string
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Next Steps
266
+
267
+ - View [README.md](./README.md) for complete API documentation (English)
268
+ - View [README.CN.md](./README.CN.md) for complete API documentation (中文)
269
+ - Check [src/__tests__](./src/__tests__) directory for more examples from test cases