@zimi/remote 0.2.1 → 0.2.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.
- package/LICENSE.md +21 -21
- package/README.md +289 -285
- package/dist/adaptor.d.mts +33 -0
- package/dist/adaptor.d.ts +5 -4
- package/dist/adaptor.js +1 -1
- package/dist/adaptor.js.map +1 -1
- package/dist/adaptor.mjs +1 -0
- package/dist/adaptor.mjs.map +1 -0
- package/dist/adaptors/dao3/client.d.mts +39 -0
- package/dist/adaptors/dao3/client.d.ts +5 -3
- package/dist/adaptors/dao3/client.js +1 -44
- package/dist/adaptors/dao3/client.js.map +1 -1
- package/dist/adaptors/dao3/client.mjs +2 -0
- package/dist/adaptors/dao3/client.mjs.map +1 -0
- package/dist/adaptors/dao3/server.d.mts +82 -0
- package/dist/adaptors/dao3/server.d.ts +5 -3
- package/dist/adaptors/dao3/server.js +1 -104
- package/dist/adaptors/dao3/server.js.map +1 -1
- package/dist/adaptors/dao3/server.mjs +2 -0
- package/dist/adaptors/dao3/server.mjs.map +1 -0
- package/dist/adaptors/electron/constants.d.mts +5 -0
- package/dist/adaptors/electron/constants.d.ts +5 -0
- package/dist/adaptors/electron/constants.js +2 -0
- package/dist/adaptors/electron/constants.js.map +1 -0
- package/dist/adaptors/electron/constants.mjs +2 -0
- package/dist/adaptors/electron/constants.mjs.map +1 -0
- package/dist/adaptors/electron/main.d.mts +10 -0
- package/dist/adaptors/electron/main.d.ts +10 -0
- package/dist/adaptors/electron/main.js +2 -0
- package/dist/adaptors/electron/main.js.map +1 -0
- package/dist/adaptors/electron/main.mjs +2 -0
- package/dist/adaptors/electron/main.mjs.map +1 -0
- package/dist/adaptors/electron/messenger.d.mts +8 -0
- package/dist/adaptors/electron/messenger.d.ts +8 -0
- package/dist/adaptors/electron/messenger.js +2 -0
- package/dist/adaptors/electron/messenger.js.map +1 -0
- package/dist/adaptors/electron/messenger.mjs +2 -0
- package/dist/adaptors/electron/messenger.mjs.map +1 -0
- package/dist/adaptors/electron/preload.d.mts +6 -0
- package/dist/adaptors/electron/preload.d.ts +6 -0
- package/dist/adaptors/electron/preload.js +2 -0
- package/dist/adaptors/electron/preload.js.map +1 -0
- package/dist/adaptors/electron/preload.mjs +2 -0
- package/dist/adaptors/electron/preload.mjs.map +1 -0
- package/dist/adaptors/electron/renderer.d.mts +9 -0
- package/dist/adaptors/electron/renderer.d.ts +9 -0
- package/dist/adaptors/electron/renderer.js +2 -0
- package/dist/adaptors/electron/renderer.js.map +1 -0
- package/dist/adaptors/electron/renderer.mjs +2 -0
- package/dist/adaptors/electron/renderer.mjs.map +1 -0
- package/dist/adaptors/http.d.mts +15 -0
- package/dist/adaptors/http.d.ts +6 -4
- package/dist/adaptors/http.js +1 -26
- package/dist/adaptors/http.js.map +1 -1
- package/dist/adaptors/http.mjs +2 -0
- package/dist/adaptors/http.mjs.map +1 -0
- package/dist/adaptors/iframe.d.mts +7 -0
- package/dist/adaptors/iframe.d.ts +5 -2
- package/dist/adaptors/iframe.js +1 -38
- package/dist/adaptors/iframe.js.map +1 -1
- package/dist/adaptors/iframe.mjs +2 -0
- package/dist/adaptors/iframe.mjs.map +1 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.d.ts +16 -10
- package/dist/index.js +1 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/remote.d.mts +81 -0
- package/dist/remote.d.ts +6 -4
- package/dist/remote.js +1 -196
- package/dist/remote.js.map +1 -1
- package/dist/remote.mjs +2 -0
- package/dist/remote.mjs.map +1 -0
- package/dist/remoteValue/exposeToRemote.d.mts +43 -0
- package/dist/remoteValue/exposeToRemote.d.ts +7 -5
- package/dist/remoteValue/exposeToRemote.js +1 -52
- package/dist/remoteValue/exposeToRemote.js.map +1 -1
- package/dist/remoteValue/exposeToRemote.mjs +2 -0
- package/dist/remoteValue/exposeToRemote.mjs.map +1 -0
- package/dist/remoteValue/remoteValue.d.mts +29 -0
- package/dist/remoteValue/remoteValue.d.ts +6 -4
- package/dist/remoteValue/remoteValue.js +1 -67
- package/dist/remoteValue/remoteValue.js.map +1 -1
- package/dist/remoteValue/remoteValue.mjs +2 -0
- package/dist/remoteValue/remoteValue.mjs.map +1 -0
- package/dist/remoteValue/type.d.mts +67 -0
- package/dist/remoteValue/type.d.ts +20 -19
- package/dist/remoteValue/type.js +1 -1
- package/dist/remoteValue/type.js.map +1 -1
- package/dist/remoteValue/type.mjs +1 -0
- package/dist/remoteValue/type.mjs.map +1 -0
- package/dist/response.d.mts +105 -0
- package/dist/response.d.ts +6 -5
- package/dist/response.js +1 -154
- package/dist/response.js.map +1 -1
- package/dist/response.mjs +2 -0
- package/dist/response.mjs.map +1 -0
- package/package.json +31 -24
- package/src/adaptor.ts +34 -34
- package/src/adaptors/dao3/client.ts +53 -53
- package/src/adaptors/dao3/server.ts +136 -136
- package/src/adaptors/electron/constants.ts +3 -0
- package/src/adaptors/electron/main.ts +59 -0
- package/src/adaptors/electron/messenger.ts +13 -0
- package/src/adaptors/electron/preload.ts +21 -0
- package/src/adaptors/electron/renderer.ts +52 -0
- package/src/adaptors/http.ts +31 -31
- package/src/adaptors/iframe.ts +47 -47
- package/src/index.ts +17 -12
- package/src/remote.ts +263 -260
- package/src/remoteValue/exposeToRemote.ts +102 -102
- package/src/remoteValue/remoteValue.ts +94 -94
- package/src/remoteValue/type.ts +124 -124
- package/src/response.ts +170 -170
package/src/remote.ts
CHANGED
|
@@ -1,260 +1,263 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RemoteError,
|
|
3
|
-
RemoteNotFoundError,
|
|
4
|
-
RemoteTimeoutError,
|
|
5
|
-
response,
|
|
6
|
-
} from './response'
|
|
7
|
-
|
|
8
|
-
import type { Adaptor, AdaptorCallback, AdaptorPackageData } from './adaptor'
|
|
9
|
-
|
|
10
|
-
const RESPONSE_PREFIX = '_response_'
|
|
11
|
-
|
|
12
|
-
type LogFunc = (...data: unknown[]) => void
|
|
13
|
-
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
-
type RemoteCallableFunc = (data: any) => Promise<any>
|
|
16
|
-
|
|
17
|
-
interface RemoteFuncRecords {
|
|
18
|
-
[key: string]: RemoteCallableFunc
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type FuncMapWithConfig<T extends RemoteFuncRecords> = {
|
|
22
|
-
[K in keyof T]: T[K] extends (data: infer Arg) => Promise<infer Ret>
|
|
23
|
-
? (
|
|
24
|
-
data: Arg,
|
|
25
|
-
config?: {
|
|
26
|
-
timeoutMs?: number
|
|
27
|
-
targetDeviceId?: string
|
|
28
|
-
}
|
|
29
|
-
) => Promise<Ret>
|
|
30
|
-
: never
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
type RegisteredFunc<T extends RemoteCallableFunc> = T extends (
|
|
34
|
-
data: infer Arg
|
|
35
|
-
) => infer Ret
|
|
36
|
-
? (
|
|
37
|
-
data: Arg,
|
|
38
|
-
ctx: {
|
|
39
|
-
/**
|
|
40
|
-
* 对方的设备 id
|
|
41
|
-
*/
|
|
42
|
-
deviceId: string
|
|
43
|
-
}
|
|
44
|
-
) => Ret
|
|
45
|
-
: never
|
|
46
|
-
|
|
47
|
-
function defaultLog(
|
|
48
|
-
this: Remote<
|
|
49
|
-
{
|
|
50
|
-
[key: string]: RemoteCallableFunc
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
[key: string]: RemoteCallableFunc
|
|
54
|
-
}
|
|
55
|
-
>,
|
|
56
|
-
...data: unknown[]
|
|
57
|
-
) {
|
|
58
|
-
if (!this.debug) {
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
console.log(`[remote of ${this.deviceId}]`, ...data)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export class Remote<
|
|
65
|
-
/**
|
|
66
|
-
* MF means my functions
|
|
67
|
-
*/
|
|
68
|
-
MF extends RemoteFuncRecords,
|
|
69
|
-
/**
|
|
70
|
-
* OF means others functions
|
|
71
|
-
*/
|
|
72
|
-
OF extends RemoteFuncRecords,
|
|
73
|
-
> {
|
|
74
|
-
debug = false
|
|
75
|
-
|
|
76
|
-
private log: LogFunc
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* (调用对方函数时的)默认超时时间,单位 ms
|
|
80
|
-
* @default 30000
|
|
81
|
-
*/
|
|
82
|
-
private defaultTimeoutMs = 30000
|
|
83
|
-
|
|
84
|
-
private map: {
|
|
85
|
-
[key: string]: {
|
|
86
|
-
callback: RegisteredFunc<RemoteCallableFunc>
|
|
87
|
-
}
|
|
88
|
-
} = {}
|
|
89
|
-
|
|
90
|
-
private deviceIdValue = ''
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* 设备 id 应该唯一,用于区分不同设备。
|
|
94
|
-
* 你可以在任何时候修改(更新)它。
|
|
95
|
-
* @default ''
|
|
96
|
-
*/
|
|
97
|
-
get deviceId() {
|
|
98
|
-
return this.deviceIdValue
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
set deviceId(deviceId: string) {
|
|
102
|
-
this.log(`deviceId set: from "${this.deviceIdValue}" to "${deviceId}"`)
|
|
103
|
-
this.deviceIdValue = deviceId
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
constructor(
|
|
107
|
-
private adaptor: Adaptor,
|
|
108
|
-
config?: {
|
|
109
|
-
/**
|
|
110
|
-
* 设备 id 应该唯一,用于区分不同设备。
|
|
111
|
-
* 你可以在任何时候修改(更新)它。
|
|
112
|
-
* @default ''
|
|
113
|
-
*/
|
|
114
|
-
deviceId?: string
|
|
115
|
-
/**
|
|
116
|
-
* (调用对方函数时的)默认超时时间,单位 ms
|
|
117
|
-
* @default 30000
|
|
118
|
-
*/
|
|
119
|
-
defaultTimeoutMs?: number
|
|
120
|
-
debug?: boolean
|
|
121
|
-
/**
|
|
122
|
-
* 格式化 AdaptorPackageData 的函数,
|
|
123
|
-
* 用于调试时输出日志。
|
|
124
|
-
* @default JSON.stringify
|
|
125
|
-
*/
|
|
126
|
-
log?: LogFunc
|
|
127
|
-
}
|
|
128
|
-
) {
|
|
129
|
-
this.debug = config?.debug ?? this.debug
|
|
130
|
-
this.defaultTimeoutMs = config?.defaultTimeoutMs ?? this.defaultTimeoutMs
|
|
131
|
-
this.log = config?.log ?? defaultLog.bind(this)
|
|
132
|
-
this.deviceId = config?.deviceId ?? this.deviceId
|
|
133
|
-
|
|
134
|
-
adaptor.every(async (e) => {
|
|
135
|
-
const { deviceId: selfDeviceId } = this
|
|
136
|
-
const { name, data, deviceId: targetDeviceId, callbackName } = e
|
|
137
|
-
const callback = this.map[name]?.callback
|
|
138
|
-
if (!callback) {
|
|
139
|
-
if (name.startsWith(RESPONSE_PREFIX)) {
|
|
140
|
-
// 这是响应,会在 callAsync once 中处理,这儿不用处理
|
|
141
|
-
this.log('[every] response received: ', e)
|
|
142
|
-
return
|
|
143
|
-
}
|
|
144
|
-
this.log('callback not found: ', name)
|
|
145
|
-
if (callbackName) {
|
|
146
|
-
adaptor.emit({
|
|
147
|
-
deviceId: selfDeviceId,
|
|
148
|
-
targetDeviceId,
|
|
149
|
-
name: callbackName,
|
|
150
|
-
data: response.error(
|
|
151
|
-
new RemoteNotFoundError(`callback not found: ${name}`)
|
|
152
|
-
),
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
return
|
|
156
|
-
}
|
|
157
|
-
if (!callbackName) {
|
|
158
|
-
this.log('should not respond: ', e)
|
|
159
|
-
void callback(data, { deviceId: targetDeviceId })
|
|
160
|
-
return
|
|
161
|
-
}
|
|
162
|
-
this.log(`callback: ${name}; respondName: ${callbackName}; data: `, data)
|
|
163
|
-
try {
|
|
164
|
-
const ret = await callback(data, { deviceId: targetDeviceId })
|
|
165
|
-
this.log('callback return: ', ret)
|
|
166
|
-
adaptor.emit({
|
|
167
|
-
deviceId: selfDeviceId,
|
|
168
|
-
targetDeviceId,
|
|
169
|
-
name: callbackName,
|
|
170
|
-
data: response.success(ret),
|
|
171
|
-
})
|
|
172
|
-
} catch (error) {
|
|
173
|
-
this.log('callback error: ', error)
|
|
174
|
-
adaptor.emit({
|
|
175
|
-
deviceId: selfDeviceId,
|
|
176
|
-
targetDeviceId,
|
|
177
|
-
name: callbackName,
|
|
178
|
-
data: response.error(RemoteError.fromError(error)),
|
|
179
|
-
})
|
|
180
|
-
}
|
|
181
|
-
})
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* 调用其他端的方法;会等待对方响应。
|
|
186
|
-
* 不能直接使用该方法,应该使用 proxy。
|
|
187
|
-
* @WARNING 不能用于响应其他端。
|
|
188
|
-
*/
|
|
189
|
-
private callAsync(
|
|
190
|
-
name: string,
|
|
191
|
-
data: unknown,
|
|
192
|
-
config?: {
|
|
193
|
-
timeoutMs?: number
|
|
194
|
-
targetDeviceId?: string
|
|
195
|
-
}
|
|
196
|
-
) {
|
|
197
|
-
const timeoutMs = config?.timeoutMs ?? this.defaultTimeoutMs
|
|
198
|
-
const { deviceId } = this
|
|
199
|
-
const randomStr = Math.random().toString(36).slice(2)
|
|
200
|
-
// 本条消息的响应名
|
|
201
|
-
const responseName = `${RESPONSE_PREFIX}-${name}-${deviceId}-${randomStr}`
|
|
202
|
-
return new Promise((resolve, reject) => {
|
|
203
|
-
let timer: NodeJS.Timeout | undefined
|
|
204
|
-
this.log(`callAsync ${name}: waiting for response: ${responseName}`)
|
|
205
|
-
const callback: AdaptorCallback = (e) => {
|
|
206
|
-
clearTimeout(timer)
|
|
207
|
-
this.log(`response received: ${responseName}`, e)
|
|
208
|
-
if (RemoteError.isRemoteError(e.data)) {
|
|
209
|
-
reject(RemoteError.fromError(e.data))
|
|
210
|
-
} else {
|
|
211
|
-
resolve((e.data as ReturnType<typeof response.success>)?.data)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
this.adaptor.once(responseName, callback)
|
|
215
|
-
timer = setTimeout(() => {
|
|
216
|
-
this.log(`timeout: ${responseName}`)
|
|
217
|
-
this.adaptor.off(responseName, callback)
|
|
218
|
-
reject(new RemoteTimeoutError(`timeout: ${name}`))
|
|
219
|
-
}, timeoutMs)
|
|
220
|
-
this.adaptor.emit({
|
|
221
|
-
deviceId,
|
|
222
|
-
targetDeviceId: config?.targetDeviceId ?? '',
|
|
223
|
-
name,
|
|
224
|
-
data,
|
|
225
|
-
callbackName: responseName,
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* 注册方法,供对方调用;
|
|
232
|
-
*/
|
|
233
|
-
register<K extends keyof MF>(name: K, callback: RegisteredFunc<MF[K]>): void {
|
|
234
|
-
this.map[name as string] = { callback }
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
_ = new Proxy<FuncMapWithConfig<OF>>({} as FuncMapWithConfig<OF>, {
|
|
238
|
-
get: (_, k) => this.callAsync.bind(this, k as string),
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
self = new Proxy<MF>({} as MF, {
|
|
242
|
-
get: (_, k) => (data: unknown) =>
|
|
243
|
-
this.map[k as string]?.callback(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
typeof data
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
1
|
+
import {
|
|
2
|
+
RemoteError,
|
|
3
|
+
RemoteNotFoundError,
|
|
4
|
+
RemoteTimeoutError,
|
|
5
|
+
response,
|
|
6
|
+
} from './response'
|
|
7
|
+
|
|
8
|
+
import type { Adaptor, AdaptorCallback, AdaptorPackageData } from './adaptor'
|
|
9
|
+
|
|
10
|
+
const RESPONSE_PREFIX = '_response_'
|
|
11
|
+
|
|
12
|
+
type LogFunc = (...data: unknown[]) => void
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
type RemoteCallableFunc = (data: any) => Promise<any>
|
|
16
|
+
|
|
17
|
+
interface RemoteFuncRecords {
|
|
18
|
+
[key: string]: RemoteCallableFunc
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type FuncMapWithConfig<T extends RemoteFuncRecords> = {
|
|
22
|
+
[K in keyof T]: T[K] extends (data: infer Arg) => Promise<infer Ret>
|
|
23
|
+
? (
|
|
24
|
+
data: Arg,
|
|
25
|
+
config?: {
|
|
26
|
+
timeoutMs?: number
|
|
27
|
+
targetDeviceId?: string
|
|
28
|
+
}
|
|
29
|
+
) => Promise<Ret>
|
|
30
|
+
: never
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type RegisteredFunc<T extends RemoteCallableFunc> = T extends (
|
|
34
|
+
data: infer Arg
|
|
35
|
+
) => infer Ret
|
|
36
|
+
? (
|
|
37
|
+
data: Arg,
|
|
38
|
+
ctx: {
|
|
39
|
+
/**
|
|
40
|
+
* 对方的设备 id
|
|
41
|
+
*/
|
|
42
|
+
deviceId: string
|
|
43
|
+
}
|
|
44
|
+
) => Ret
|
|
45
|
+
: never
|
|
46
|
+
|
|
47
|
+
function defaultLog(
|
|
48
|
+
this: Remote<
|
|
49
|
+
{
|
|
50
|
+
[key: string]: RemoteCallableFunc
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
[key: string]: RemoteCallableFunc
|
|
54
|
+
}
|
|
55
|
+
>,
|
|
56
|
+
...data: unknown[]
|
|
57
|
+
) {
|
|
58
|
+
if (!this.debug) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
console.log(`[remote of ${this.deviceId}]`, ...data)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class Remote<
|
|
65
|
+
/**
|
|
66
|
+
* MF means my functions
|
|
67
|
+
*/
|
|
68
|
+
MF extends RemoteFuncRecords,
|
|
69
|
+
/**
|
|
70
|
+
* OF means others functions
|
|
71
|
+
*/
|
|
72
|
+
OF extends RemoteFuncRecords,
|
|
73
|
+
> {
|
|
74
|
+
debug = false
|
|
75
|
+
|
|
76
|
+
private log: LogFunc
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* (调用对方函数时的)默认超时时间,单位 ms
|
|
80
|
+
* @default 30000
|
|
81
|
+
*/
|
|
82
|
+
private defaultTimeoutMs = 30000
|
|
83
|
+
|
|
84
|
+
private map: {
|
|
85
|
+
[key: string]: {
|
|
86
|
+
callback: RegisteredFunc<RemoteCallableFunc>
|
|
87
|
+
}
|
|
88
|
+
} = {}
|
|
89
|
+
|
|
90
|
+
private deviceIdValue = ''
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 设备 id 应该唯一,用于区分不同设备。
|
|
94
|
+
* 你可以在任何时候修改(更新)它。
|
|
95
|
+
* @default ''
|
|
96
|
+
*/
|
|
97
|
+
get deviceId() {
|
|
98
|
+
return this.deviceIdValue
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
set deviceId(deviceId: string) {
|
|
102
|
+
this.log(`deviceId set: from "${this.deviceIdValue}" to "${deviceId}"`)
|
|
103
|
+
this.deviceIdValue = deviceId
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
constructor(
|
|
107
|
+
private adaptor: Adaptor,
|
|
108
|
+
config?: {
|
|
109
|
+
/**
|
|
110
|
+
* 设备 id 应该唯一,用于区分不同设备。
|
|
111
|
+
* 你可以在任何时候修改(更新)它。
|
|
112
|
+
* @default ''
|
|
113
|
+
*/
|
|
114
|
+
deviceId?: string
|
|
115
|
+
/**
|
|
116
|
+
* (调用对方函数时的)默认超时时间,单位 ms
|
|
117
|
+
* @default 30000
|
|
118
|
+
*/
|
|
119
|
+
defaultTimeoutMs?: number
|
|
120
|
+
debug?: boolean
|
|
121
|
+
/**
|
|
122
|
+
* 格式化 AdaptorPackageData 的函数,
|
|
123
|
+
* 用于调试时输出日志。
|
|
124
|
+
* @default JSON.stringify
|
|
125
|
+
*/
|
|
126
|
+
log?: LogFunc
|
|
127
|
+
}
|
|
128
|
+
) {
|
|
129
|
+
this.debug = config?.debug ?? this.debug
|
|
130
|
+
this.defaultTimeoutMs = config?.defaultTimeoutMs ?? this.defaultTimeoutMs
|
|
131
|
+
this.log = config?.log ?? defaultLog.bind(this)
|
|
132
|
+
this.deviceId = config?.deviceId ?? this.deviceId
|
|
133
|
+
|
|
134
|
+
adaptor.every(async (e) => {
|
|
135
|
+
const { deviceId: selfDeviceId } = this
|
|
136
|
+
const { name, data, deviceId: targetDeviceId, callbackName } = e
|
|
137
|
+
const callback = this.map[name]?.callback
|
|
138
|
+
if (!callback) {
|
|
139
|
+
if (name.startsWith(RESPONSE_PREFIX)) {
|
|
140
|
+
// 这是响应,会在 callAsync once 中处理,这儿不用处理
|
|
141
|
+
this.log('[every] response received: ', e)
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
this.log('callback not found: ', name)
|
|
145
|
+
if (callbackName) {
|
|
146
|
+
adaptor.emit({
|
|
147
|
+
deviceId: selfDeviceId,
|
|
148
|
+
targetDeviceId,
|
|
149
|
+
name: callbackName,
|
|
150
|
+
data: response.error(
|
|
151
|
+
new RemoteNotFoundError(`callback not found: ${name}`)
|
|
152
|
+
),
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if (!callbackName) {
|
|
158
|
+
this.log('should not respond: ', e)
|
|
159
|
+
void callback(data, { deviceId: targetDeviceId })
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
this.log(`callback: ${name}; respondName: ${callbackName}; data: `, data)
|
|
163
|
+
try {
|
|
164
|
+
const ret = await callback(data, { deviceId: targetDeviceId })
|
|
165
|
+
this.log('callback return: ', ret)
|
|
166
|
+
adaptor.emit({
|
|
167
|
+
deviceId: selfDeviceId,
|
|
168
|
+
targetDeviceId,
|
|
169
|
+
name: callbackName,
|
|
170
|
+
data: response.success(ret),
|
|
171
|
+
})
|
|
172
|
+
} catch (error) {
|
|
173
|
+
this.log('callback error: ', error)
|
|
174
|
+
adaptor.emit({
|
|
175
|
+
deviceId: selfDeviceId,
|
|
176
|
+
targetDeviceId,
|
|
177
|
+
name: callbackName,
|
|
178
|
+
data: response.error(RemoteError.fromError(error)),
|
|
179
|
+
})
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 调用其他端的方法;会等待对方响应。
|
|
186
|
+
* 不能直接使用该方法,应该使用 proxy。
|
|
187
|
+
* @WARNING 不能用于响应其他端。
|
|
188
|
+
*/
|
|
189
|
+
private callAsync(
|
|
190
|
+
name: string,
|
|
191
|
+
data: unknown,
|
|
192
|
+
config?: {
|
|
193
|
+
timeoutMs?: number
|
|
194
|
+
targetDeviceId?: string
|
|
195
|
+
}
|
|
196
|
+
) {
|
|
197
|
+
const timeoutMs = config?.timeoutMs ?? this.defaultTimeoutMs
|
|
198
|
+
const { deviceId } = this
|
|
199
|
+
const randomStr = Math.random().toString(36).slice(2)
|
|
200
|
+
// 本条消息的响应名
|
|
201
|
+
const responseName = `${RESPONSE_PREFIX}-${name}-${deviceId}-${randomStr}`
|
|
202
|
+
return new Promise((resolve, reject) => {
|
|
203
|
+
let timer: NodeJS.Timeout | undefined
|
|
204
|
+
this.log(`callAsync ${name}: waiting for response: ${responseName}`)
|
|
205
|
+
const callback: AdaptorCallback = (e) => {
|
|
206
|
+
clearTimeout(timer)
|
|
207
|
+
this.log(`response received: ${responseName}`, e)
|
|
208
|
+
if (RemoteError.isRemoteError(e.data)) {
|
|
209
|
+
reject(RemoteError.fromError(e.data))
|
|
210
|
+
} else {
|
|
211
|
+
resolve((e.data as ReturnType<typeof response.success>)?.data)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
this.adaptor.once(responseName, callback)
|
|
215
|
+
timer = setTimeout(() => {
|
|
216
|
+
this.log(`timeout: ${responseName}`)
|
|
217
|
+
this.adaptor.off(responseName, callback)
|
|
218
|
+
reject(new RemoteTimeoutError(`timeout: ${name}`))
|
|
219
|
+
}, timeoutMs)
|
|
220
|
+
this.adaptor.emit({
|
|
221
|
+
deviceId,
|
|
222
|
+
targetDeviceId: config?.targetDeviceId ?? '',
|
|
223
|
+
name,
|
|
224
|
+
data,
|
|
225
|
+
callbackName: responseName,
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 注册方法,供对方调用;
|
|
232
|
+
*/
|
|
233
|
+
register<K extends keyof MF>(name: K, callback: RegisteredFunc<MF[K]>): void {
|
|
234
|
+
this.map[name as string] = { callback }
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
_ = new Proxy<FuncMapWithConfig<OF>>({} as FuncMapWithConfig<OF>, {
|
|
238
|
+
get: (_, k) => this.callAsync.bind(this, k as string),
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
self = new Proxy<MF>({} as MF, {
|
|
242
|
+
get: (_, k) => (data: unknown) =>
|
|
243
|
+
this.map[k as string]?.callback.apply(null, [
|
|
244
|
+
data,
|
|
245
|
+
{
|
|
246
|
+
deviceId: this.deviceId,
|
|
247
|
+
},
|
|
248
|
+
]),
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function isRemoteAdaptorData(data: unknown): data is AdaptorPackageData {
|
|
253
|
+
return (
|
|
254
|
+
!!data &&
|
|
255
|
+
typeof data === 'object' &&
|
|
256
|
+
'deviceId' in data &&
|
|
257
|
+
'name' in data &&
|
|
258
|
+
typeof data.deviceId === 'string' &&
|
|
259
|
+
typeof data.name === 'string' &&
|
|
260
|
+
!!data.deviceId &&
|
|
261
|
+
!!data.name
|
|
262
|
+
)
|
|
263
|
+
}
|