crx-rpc 1.0.4 → 1.0.6
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 +29 -23
- package/README.zh-CN.md +30 -24
- package/dist/background.d.ts +2 -1
- package/dist/background.js +60 -20
- package/package.json +1 -1
- package/src/background.ts +60 -20
package/README.md
CHANGED
|
@@ -67,8 +67,9 @@ class MathService implements IMathService {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// Register service
|
|
71
|
-
const rpc = new BackgroundRPC();
|
|
70
|
+
// Register service with optional logging
|
|
71
|
+
const rpc = new BackgroundRPC(true); // Enable logging
|
|
72
|
+
// const rpc = new BackgroundRPC(); // Disable logging (default)
|
|
72
73
|
rpc.register(IMathService, new MathService());
|
|
73
74
|
```
|
|
74
75
|
|
|
@@ -179,35 +180,40 @@ async function calculate() {
|
|
|
179
180
|
- **BackgroundRPC**: Service registry and handler in the background script
|
|
180
181
|
- **RPCClient**: Base client with service proxy generation
|
|
181
182
|
|
|
182
|
-
##
|
|
183
|
+
## Logging Support
|
|
184
|
+
|
|
185
|
+
The framework includes built-in logging support for debugging and monitoring RPC calls.
|
|
183
186
|
|
|
184
|
-
|
|
187
|
+
### Enable Logging
|
|
185
188
|
|
|
186
189
|
```typescript
|
|
187
|
-
|
|
188
|
-
const
|
|
190
|
+
// Enable logging in BackgroundRPC
|
|
191
|
+
const rpc = new BackgroundRPC(true); // Enable logging
|
|
192
|
+
// const rpc = new BackgroundRPC(); // Disable logging (default)
|
|
189
193
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
// Error preserves original stack trace and error type from the background script
|
|
197
|
-
}
|
|
194
|
+
// Example output:
|
|
195
|
+
// [RPC] Call: MathService.add { id: "123", args: [5, 3], senderId: 456, timestamp: "2025-09-01T10:00:00.000Z" }
|
|
196
|
+
// [RPC] Success: MathService.add { id: "123", result: 8, timestamp: "2025-09-01T10:00:00.001Z" }
|
|
197
|
+
|
|
198
|
+
// For errors:
|
|
199
|
+
// [RPC] Error: MathService.divide { id: "124", error: "Division by zero", timestamp: "2025-09-01T10:00:01.000Z" }
|
|
198
200
|
```
|
|
199
201
|
|
|
200
|
-
###
|
|
202
|
+
### Log Output
|
|
201
203
|
|
|
202
|
-
|
|
204
|
+
When logging is enabled, the following information is logged:
|
|
203
205
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
206
|
+
- **Function Calls**: Service name, method name, arguments, sender ID, and timestamp
|
|
207
|
+
- **Success Responses**: Service name, method name, result, and timestamp
|
|
208
|
+
- **Error Responses**: Service name, method name, error message, and timestamp
|
|
209
|
+
- **Unknown Services/Methods**: Warnings for invalid service or method calls
|
|
210
|
+
|
|
211
|
+
### Use Cases
|
|
212
|
+
|
|
213
|
+
- **Development**: Debug RPC communication during development
|
|
214
|
+
- **Production Monitoring**: Track RPC usage patterns and performance
|
|
215
|
+
- **Troubleshooting**: Identify failed calls and error patterns
|
|
216
|
+
- **Security Auditing**: Monitor RPC access patterns
|
|
211
217
|
|
|
212
218
|
## Observable Support
|
|
213
219
|
|
package/README.zh-CN.md
CHANGED
|
@@ -62,13 +62,14 @@ class MathService implements IMathService {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
async divide(a: number, b: number): Promise<number> {
|
|
65
|
-
if (b === 0) throw new Error('
|
|
65
|
+
if (b === 0) throw new Error('Division by zero');
|
|
66
66
|
return a / b;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
//
|
|
71
|
-
const rpc = new BackgroundRPC();
|
|
70
|
+
// 注册服务,可选择启用日志
|
|
71
|
+
const rpc = new BackgroundRPC(true); // 启用日志
|
|
72
|
+
// const rpc = new BackgroundRPC(); // 禁用日志(默认)
|
|
72
73
|
rpc.register(IMathService, new MathService());
|
|
73
74
|
```
|
|
74
75
|
|
|
@@ -195,35 +196,40 @@ async function calculate() {
|
|
|
195
196
|
- **BackgroundRPC**: 背景脚本中的服务注册表和处理器
|
|
196
197
|
- **RPCClient**: 具有服务代理生成功能的基础客户端
|
|
197
198
|
|
|
198
|
-
##
|
|
199
|
+
## 日志支持
|
|
200
|
+
|
|
201
|
+
框架包含内置的日志支持,用于调试和监控RPC调用。
|
|
199
202
|
|
|
200
|
-
|
|
203
|
+
### 启用日志
|
|
201
204
|
|
|
202
205
|
```typescript
|
|
203
|
-
|
|
204
|
-
const
|
|
206
|
+
// 在BackgroundRPC中启用日志
|
|
207
|
+
const rpc = new BackgroundRPC(true); // 启用日志
|
|
208
|
+
// const rpc = new BackgroundRPC(); // 禁用日志(默认)
|
|
205
209
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// 错误保留了来自背景脚本的原始堆栈跟踪和错误类型
|
|
213
|
-
}
|
|
210
|
+
// 示例输出:
|
|
211
|
+
// [RPC] Call: MathService.add { id: "123", args: [5, 3], senderId: 456, timestamp: "2025-09-01T10:00:00.000Z" }
|
|
212
|
+
// [RPC] Success: MathService.add { id: "123", result: 8, timestamp: "2025-09-01T10:00:00.001Z" }
|
|
213
|
+
|
|
214
|
+
// 对于错误:
|
|
215
|
+
// [RPC] Error: MathService.divide { id: "124", error: "Division by zero", timestamp: "2025-09-01T10:00:01.000Z" }
|
|
214
216
|
```
|
|
215
217
|
|
|
216
|
-
###
|
|
218
|
+
### 日志输出
|
|
217
219
|
|
|
218
|
-
|
|
220
|
+
启用日志时,会记录以下信息:
|
|
219
221
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
- **函数调用**: 服务名、方法名、参数、发送者ID和时间戳
|
|
223
|
+
- **成功响应**: 服务名、方法名、结果和时间戳
|
|
224
|
+
- **错误响应**: 服务名、方法名、错误消息和时间戳
|
|
225
|
+
- **未知服务/方法**: 无效服务或方法调用的警告
|
|
226
|
+
|
|
227
|
+
### 使用场景
|
|
228
|
+
|
|
229
|
+
- **开发**: 在开发期间调试RPC通信
|
|
230
|
+
- **生产监控**: 跟踪RPC使用模式和性能
|
|
231
|
+
- **故障排除**: 识别失败的调用和错误模式
|
|
232
|
+
- **安全审计**: 监控RPC访问模式
|
|
227
233
|
|
|
228
234
|
## Observable支持
|
|
229
235
|
|
package/dist/background.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import type { Identifier } from './id';
|
|
|
2
2
|
import type { SubjectLike, RpcObservableUpdateMessage } from './types';
|
|
3
3
|
import { Disposable } from './disposable';
|
|
4
4
|
export declare class BackgroundRPC extends Disposable {
|
|
5
|
+
private log;
|
|
5
6
|
private services;
|
|
6
|
-
constructor();
|
|
7
|
+
constructor(log?: boolean);
|
|
7
8
|
register<T>(service: Identifier<T>, serviceInstance: T): void;
|
|
8
9
|
}
|
|
9
10
|
export declare class RemoteSubject<T> extends Disposable implements SubjectLike<T> {
|
package/dist/background.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { OBSERVABLE_EVENT, RPC_EVENT_NAME, RPC_RESPONSE_EVENT_NAME, SUBSCRIBABLE_OBSERVABLE, UNSUBSCRIBE_OBSERVABLE } from './const';
|
|
2
2
|
import { Disposable } from './disposable';
|
|
3
3
|
export class BackgroundRPC extends Disposable {
|
|
4
|
+
log;
|
|
4
5
|
services = {};
|
|
5
|
-
constructor() {
|
|
6
|
+
constructor(log = false) {
|
|
6
7
|
super();
|
|
8
|
+
this.log = log;
|
|
7
9
|
const handler = ((msg, sender) => {
|
|
8
10
|
if (msg.type !== RPC_EVENT_NAME)
|
|
9
11
|
return;
|
|
10
|
-
const senderId = sender.tab
|
|
12
|
+
const senderId = sender.tab?.id;
|
|
13
|
+
if (!senderId) {
|
|
14
|
+
console.warn('Received RPC request from unknown sender, ignoring.', msg);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
11
17
|
const sendResponse = (response) => {
|
|
12
18
|
chrome.tabs.sendMessage(senderId, {
|
|
13
19
|
...response,
|
|
@@ -16,7 +22,18 @@ export class BackgroundRPC extends Disposable {
|
|
|
16
22
|
};
|
|
17
23
|
const { id, method, args, service } = msg;
|
|
18
24
|
const serviceInstance = this.services[service];
|
|
25
|
+
if (this.log) {
|
|
26
|
+
console.log(`[RPC] Call: ${service}.${method}`, {
|
|
27
|
+
id,
|
|
28
|
+
args,
|
|
29
|
+
senderId,
|
|
30
|
+
timestamp: new Date().toISOString()
|
|
31
|
+
});
|
|
32
|
+
}
|
|
19
33
|
if (!serviceInstance) {
|
|
34
|
+
if (this.log) {
|
|
35
|
+
console.warn(`[RPC] Unknown service: ${service}`);
|
|
36
|
+
}
|
|
20
37
|
const resp = {
|
|
21
38
|
id,
|
|
22
39
|
error: { message: `Unknown service: ${service}` },
|
|
@@ -27,6 +44,9 @@ export class BackgroundRPC extends Disposable {
|
|
|
27
44
|
return true;
|
|
28
45
|
}
|
|
29
46
|
if (!(method in serviceInstance)) {
|
|
47
|
+
if (this.log) {
|
|
48
|
+
console.warn(`[RPC] Unknown method: ${service}.${method}`);
|
|
49
|
+
}
|
|
30
50
|
const resp = {
|
|
31
51
|
id,
|
|
32
52
|
error: { message: `Unknown method: ${method}` },
|
|
@@ -38,22 +58,40 @@ export class BackgroundRPC extends Disposable {
|
|
|
38
58
|
}
|
|
39
59
|
Promise.resolve()
|
|
40
60
|
.then(() => serviceInstance[method](...args))
|
|
41
|
-
.then((result) =>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
.then((result) => {
|
|
62
|
+
if (this.log) {
|
|
63
|
+
console.log(`[RPC] Success: ${service}.${method}`, {
|
|
64
|
+
id,
|
|
65
|
+
result,
|
|
66
|
+
timestamp: new Date().toISOString()
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
sendResponse({
|
|
70
|
+
id,
|
|
71
|
+
result,
|
|
72
|
+
service,
|
|
73
|
+
method
|
|
74
|
+
});
|
|
75
|
+
})
|
|
76
|
+
.catch((err) => {
|
|
77
|
+
if (this.log) {
|
|
78
|
+
console.error(`[RPC] Error: ${service}.${method}`, {
|
|
79
|
+
id,
|
|
80
|
+
error: err.message,
|
|
81
|
+
timestamp: new Date().toISOString()
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
sendResponse({
|
|
85
|
+
id,
|
|
86
|
+
error: {
|
|
87
|
+
message: err.message,
|
|
88
|
+
stack: err.stack,
|
|
89
|
+
name: err.name
|
|
90
|
+
},
|
|
91
|
+
service,
|
|
92
|
+
method
|
|
93
|
+
});
|
|
94
|
+
});
|
|
57
95
|
return true; // 异步 sendResponse
|
|
58
96
|
});
|
|
59
97
|
chrome.runtime.onMessage.addListener(handler);
|
|
@@ -115,9 +153,11 @@ export class RemoteSubjectManager extends Disposable {
|
|
|
115
153
|
constructor() {
|
|
116
154
|
super();
|
|
117
155
|
const handleMessage = (msg, sender) => {
|
|
118
|
-
const senderId = sender.tab
|
|
119
|
-
if (!senderId)
|
|
156
|
+
const senderId = sender.tab?.id;
|
|
157
|
+
if (!senderId) {
|
|
158
|
+
console.warn('Received RPC request from unknown sender, ignoring.', msg);
|
|
120
159
|
return;
|
|
160
|
+
}
|
|
121
161
|
if (msg.type === SUBSCRIBABLE_OBSERVABLE) {
|
|
122
162
|
const { key } = msg;
|
|
123
163
|
this.handleSubscription(key, senderId);
|
package/package.json
CHANGED
package/src/background.ts
CHANGED
|
@@ -6,11 +6,15 @@ import { Disposable } from './disposable';
|
|
|
6
6
|
export class BackgroundRPC extends Disposable {
|
|
7
7
|
private services: Record<string, RpcService> = {};
|
|
8
8
|
|
|
9
|
-
constructor() {
|
|
9
|
+
constructor(private log: boolean = false) {
|
|
10
10
|
super();
|
|
11
11
|
const handler = ((msg: RpcRequest & { type?: string }, sender: chrome.runtime.MessageSender) => {
|
|
12
12
|
if (msg.type !== RPC_EVENT_NAME) return;
|
|
13
|
-
const senderId = sender.tab
|
|
13
|
+
const senderId = sender.tab?.id;
|
|
14
|
+
if (!senderId) {
|
|
15
|
+
console.warn('Received RPC request from unknown sender, ignoring.', msg);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
14
18
|
const sendResponse = (response: RpcResponse) => {
|
|
15
19
|
chrome.tabs.sendMessage(senderId, {
|
|
16
20
|
...response,
|
|
@@ -21,7 +25,19 @@ export class BackgroundRPC extends Disposable {
|
|
|
21
25
|
const { id, method, args, service } = msg;
|
|
22
26
|
const serviceInstance = this.services[service];
|
|
23
27
|
|
|
28
|
+
if (this.log) {
|
|
29
|
+
console.log(`[RPC] Call: ${service}.${method}`, {
|
|
30
|
+
id,
|
|
31
|
+
args,
|
|
32
|
+
senderId,
|
|
33
|
+
timestamp: new Date().toISOString()
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
if (!serviceInstance) {
|
|
38
|
+
if (this.log) {
|
|
39
|
+
console.warn(`[RPC] Unknown service: ${service}`);
|
|
40
|
+
}
|
|
25
41
|
const resp: RpcResponse = {
|
|
26
42
|
id,
|
|
27
43
|
error: { message: `Unknown service: ${service}` },
|
|
@@ -33,6 +49,9 @@ export class BackgroundRPC extends Disposable {
|
|
|
33
49
|
}
|
|
34
50
|
|
|
35
51
|
if (!(method in serviceInstance)) {
|
|
52
|
+
if (this.log) {
|
|
53
|
+
console.warn(`[RPC] Unknown method: ${service}.${method}`);
|
|
54
|
+
}
|
|
36
55
|
const resp: RpcResponse = {
|
|
37
56
|
id,
|
|
38
57
|
error: { message: `Unknown method: ${method}` },
|
|
@@ -45,22 +64,40 @@ export class BackgroundRPC extends Disposable {
|
|
|
45
64
|
|
|
46
65
|
Promise.resolve()
|
|
47
66
|
.then(() => serviceInstance[method](...args))
|
|
48
|
-
.then((result) =>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
.then((result) => {
|
|
68
|
+
if (this.log) {
|
|
69
|
+
console.log(`[RPC] Success: ${service}.${method}`, {
|
|
70
|
+
id,
|
|
71
|
+
result,
|
|
72
|
+
timestamp: new Date().toISOString()
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
sendResponse({
|
|
76
|
+
id,
|
|
77
|
+
result,
|
|
78
|
+
service,
|
|
79
|
+
method
|
|
80
|
+
});
|
|
81
|
+
})
|
|
82
|
+
.catch((err) => {
|
|
83
|
+
if (this.log) {
|
|
84
|
+
console.error(`[RPC] Error: ${service}.${method}`, {
|
|
85
|
+
id,
|
|
86
|
+
error: err.message,
|
|
87
|
+
timestamp: new Date().toISOString()
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
sendResponse({
|
|
91
|
+
id,
|
|
92
|
+
error: {
|
|
93
|
+
message: err.message,
|
|
94
|
+
stack: err.stack,
|
|
95
|
+
name: err.name
|
|
96
|
+
},
|
|
97
|
+
service,
|
|
98
|
+
method
|
|
99
|
+
});
|
|
100
|
+
});
|
|
64
101
|
|
|
65
102
|
return true; // 异步 sendResponse
|
|
66
103
|
});
|
|
@@ -130,8 +167,11 @@ export class RemoteSubjectManager extends Disposable {
|
|
|
130
167
|
super();
|
|
131
168
|
|
|
132
169
|
const handleMessage = (msg: RpcObservableSubscribeMessage, sender: chrome.runtime.MessageSender) => {
|
|
133
|
-
const senderId = sender.tab
|
|
134
|
-
if (!senderId)
|
|
170
|
+
const senderId = sender.tab?.id;
|
|
171
|
+
if (!senderId) {
|
|
172
|
+
console.warn('Received RPC request from unknown sender, ignoring.', msg);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
135
175
|
|
|
136
176
|
if (msg.type === SUBSCRIBABLE_OBSERVABLE) {
|
|
137
177
|
const { key } = msg;
|