@lark-base-open/base-site-channel 0.1.2 → 0.1.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/README.md +206 -206
- package/dist/client.mjs +1 -1
- package/dist/index.mjs +2 -37
- package/dist/runtime.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
# @lark-base-open/base-site-channel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Bidirectional communication between a host page and an iframe page.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## When to use it
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- iframe
|
|
10
|
-
-
|
|
7
|
+
- A host page embeds an iframe page.
|
|
8
|
+
- The host needs to call APIs exposed by the iframe.
|
|
9
|
+
- The iframe also needs to call APIs exposed by the host.
|
|
10
|
+
- Both sides need one consistent communication model.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Public capabilities
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
- Host
|
|
16
|
-
- Host
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- Client
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
14
|
+
- Create an iframe container and load its page from the Host.
|
|
15
|
+
- Observe the iframe load status from the Host.
|
|
16
|
+
- Register Host methods that the Client can call.
|
|
17
|
+
- Call Client methods from the Host.
|
|
18
|
+
- Subscribe to Client events from the Host.
|
|
19
|
+
- Emit events to the Client from the Host.
|
|
20
|
+
- Register Client methods that the Host can call.
|
|
21
|
+
- Call Host methods from the Client.
|
|
22
|
+
- Subscribe to Host events from the Client.
|
|
23
|
+
- Emit events to the Host from the Client.
|
|
24
|
+
- Use the built-in batch binary fetch API to fetch a URL list through the Host's internal worker.
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Exports
|
|
27
27
|
|
|
28
28
|
```ts
|
|
29
29
|
import { Host, LoadStatus, client } from "@lark-base-open/base-site-channel";
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Quick start
|
|
33
33
|
|
|
34
|
-
### 1.
|
|
34
|
+
### 1. Create a channel in the Host page
|
|
35
35
|
|
|
36
|
-
Host
|
|
36
|
+
The Host is responsible for:
|
|
37
37
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
38
|
+
- Creating the iframe.
|
|
39
|
+
- Loading the Client page URL.
|
|
40
|
+
- Observing the load status.
|
|
41
|
+
- Registering methods for the Client.
|
|
42
|
+
- Calling Client methods.
|
|
43
|
+
- Subscribing to Client events.
|
|
44
|
+
- Emitting events to the Client.
|
|
45
45
|
|
|
46
46
|
```ts
|
|
47
47
|
import { Host, LoadStatus } from "@lark-base-open/base-site-channel";
|
|
@@ -56,7 +56,7 @@ const host = new Host(
|
|
|
56
56
|
container,
|
|
57
57
|
(status, errorInfo) => {
|
|
58
58
|
if (status === LoadStatus.ERROR) {
|
|
59
|
-
console.error("
|
|
59
|
+
console.error("Page failed to load", errorInfo);
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"demo-block",
|
|
@@ -65,7 +65,7 @@ const host = new Host(
|
|
|
65
65
|
host.setClientUrl("https://example.com/view");
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
### 2.
|
|
68
|
+
### 2. Register Host methods callable by the Client
|
|
69
69
|
|
|
70
70
|
```ts
|
|
71
71
|
host.registerApi<{ userId: string }, { name: string }>(
|
|
@@ -78,7 +78,7 @@ host.registerApi<{ userId: string }, { name: string }>(
|
|
|
78
78
|
);
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
### 3.
|
|
81
|
+
### 3. Call a Client method from the Host
|
|
82
82
|
|
|
83
83
|
```ts
|
|
84
84
|
const result = await host.invokeApi<{ keyword: string }, { total: number }>(
|
|
@@ -89,22 +89,22 @@ const result = await host.invokeApi<{ keyword: string }, { total: number }>(
|
|
|
89
89
|
);
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
### 4.
|
|
92
|
+
### 4. Subscribe to Client events from the Host
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
95
|
const unsubscribe = host.subscribeEvent<{ count: number }>(
|
|
96
96
|
"dataChange",
|
|
97
97
|
(payload) => {
|
|
98
|
-
//
|
|
98
|
+
// Handle an event emitted by the Client.
|
|
99
99
|
console.log("host receive dataChange", payload.count);
|
|
100
100
|
},
|
|
101
101
|
);
|
|
102
102
|
|
|
103
|
-
//
|
|
103
|
+
// Unsubscribe when this listener is no longer needed.
|
|
104
104
|
unsubscribe();
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
### 5.
|
|
107
|
+
### 5. Emit an event to the Client from the Host
|
|
108
108
|
|
|
109
109
|
```ts
|
|
110
110
|
await host.emitEvent("themeChange", {
|
|
@@ -112,11 +112,11 @@ await host.emitEvent("themeChange", {
|
|
|
112
112
|
});
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
## Client
|
|
115
|
+
## Using the Client in an iframe page
|
|
116
116
|
|
|
117
|
-
Client
|
|
117
|
+
The Client can use the exported `client` singleton directly in an iframe page.
|
|
118
118
|
|
|
119
|
-
### 1.
|
|
119
|
+
### 1. Register Client methods callable by the Host
|
|
120
120
|
|
|
121
121
|
```ts
|
|
122
122
|
import { client } from "@lark-base-open/base-site-channel";
|
|
@@ -131,7 +131,7 @@ client.registerApi<{ keyword: string }, { total: number }>(
|
|
|
131
131
|
);
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
### 2.
|
|
134
|
+
### 2. Call a Host method from the Client
|
|
135
135
|
|
|
136
136
|
```ts
|
|
137
137
|
const userInfo = await client.invokeApi<{ userId: string }, { name: string }>(
|
|
@@ -142,22 +142,22 @@ const userInfo = await client.invokeApi<{ userId: string }, { name: string }>(
|
|
|
142
142
|
);
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
### 3.
|
|
145
|
+
### 3. Subscribe to Host events from the Client
|
|
146
146
|
|
|
147
147
|
```ts
|
|
148
148
|
const unsubscribe = client.subscribeEvent<{ theme: string }>(
|
|
149
149
|
"themeChange",
|
|
150
150
|
(payload) => {
|
|
151
|
-
//
|
|
151
|
+
// Handle an event emitted by the Host.
|
|
152
152
|
console.log("client receive themeChange", payload.theme);
|
|
153
153
|
},
|
|
154
154
|
);
|
|
155
155
|
|
|
156
|
-
//
|
|
156
|
+
// Unsubscribe when this listener is no longer needed.
|
|
157
157
|
unsubscribe();
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
-
### 4.
|
|
160
|
+
### 4. Emit an event to the Host from the Client
|
|
161
161
|
|
|
162
162
|
```ts
|
|
163
163
|
await client.emitEvent("dataChange", {
|
|
@@ -165,63 +165,63 @@ await client.emitEvent("dataChange", {
|
|
|
165
165
|
});
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
##
|
|
168
|
+
## Recommended flow
|
|
169
169
|
|
|
170
|
-
### Host
|
|
170
|
+
### Host flow
|
|
171
171
|
|
|
172
|
-
1.
|
|
173
|
-
2.
|
|
174
|
-
3.
|
|
175
|
-
4.
|
|
176
|
-
5.
|
|
177
|
-
6.
|
|
178
|
-
7.
|
|
172
|
+
1. Prepare a container element for the iframe.
|
|
173
|
+
2. Create a `Host` instance with a unique `instanceId`.
|
|
174
|
+
3. Expose Host methods with `registerApi` before loading the iframe.
|
|
175
|
+
4. Load the iframe page with `setClientUrl`.
|
|
176
|
+
5. Subscribe to Client state changes with `subscribeEvent` when needed.
|
|
177
|
+
6. Call Client methods with `invokeApi` or emit events with `emitEvent` as needed.
|
|
178
|
+
7. Call `destroy` when the page unmounts.
|
|
179
179
|
|
|
180
|
-
### Client
|
|
180
|
+
### Client flow
|
|
181
181
|
|
|
182
|
-
1.
|
|
183
|
-
2.
|
|
184
|
-
3.
|
|
185
|
-
4.
|
|
182
|
+
1. Import `client` in the iframe page.
|
|
183
|
+
2. Expose iframe methods with `registerApi`.
|
|
184
|
+
3. Subscribe to Host state changes with `subscribeEvent` when needed.
|
|
185
|
+
4. Call Host methods with `invokeApi` or emit events with `emitEvent` as needed.
|
|
186
186
|
|
|
187
|
-
##
|
|
187
|
+
## Load status
|
|
188
188
|
|
|
189
|
-
`LoadStatus`
|
|
189
|
+
`LoadStatus` has these values:
|
|
190
190
|
|
|
191
|
-
- `pending
|
|
192
|
-
- `loading
|
|
193
|
-
- `loaded
|
|
194
|
-
- `error
|
|
191
|
+
- `pending`: Initial state.
|
|
192
|
+
- `loading`: The iframe page is loading.
|
|
193
|
+
- `loaded`: The page can communicate with the Host.
|
|
194
|
+
- `error`: Loading failed or communication is unavailable.
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
Typical handling:
|
|
197
197
|
|
|
198
|
-
- `loading
|
|
199
|
-
-
|
|
200
|
-
- `error
|
|
198
|
+
- Show a loading state while `loading`.
|
|
199
|
+
- Run iframe-dependent operations only after `loaded`.
|
|
200
|
+
- Show an error and offer a retry when the status is `error`.
|
|
201
201
|
|
|
202
|
-
##
|
|
202
|
+
## Constructor options
|
|
203
203
|
|
|
204
204
|
`new Host(containerEl, onLoadStatusChange, instanceId, allowedOrigin, extraAttributes, options)`
|
|
205
205
|
|
|
206
|
-
- `containerEl
|
|
207
|
-
- `onLoadStatusChange
|
|
208
|
-
- `instanceId
|
|
209
|
-
- `allowedOrigin
|
|
210
|
-
- `extraAttributes
|
|
211
|
-
- `options
|
|
212
|
-
- `options.enableBinaryFetch
|
|
206
|
+
- `containerEl`: Element that contains the iframe.
|
|
207
|
+
- `onLoadStatusChange`: Callback for page status changes.
|
|
208
|
+
- `instanceId`: Identifier for this channel instance; keep it unique.
|
|
209
|
+
- `allowedOrigin`: Allowed absolute URLs or origins. Invalid settings are rejected; regular expressions and wildcards are unsupported.
|
|
210
|
+
- `extraAttributes`: Additional iframe attributes.
|
|
211
|
+
- `options`: Optional Host settings.
|
|
212
|
+
- `options.enableBinaryFetch`: Whether the Client may use built-in binary fetching. Defaults to `false` and must stay disabled for Site Runtime integration.
|
|
213
213
|
|
|
214
|
-
##
|
|
214
|
+
## Communication logs
|
|
215
215
|
|
|
216
|
-
Host
|
|
216
|
+
Info-level communication logs are disabled for Host, Client, and the binary-fetch worker in every environment. Host and Client warnings and errors use `window.BearWebSlardarWeb` when available, reporting through `sendLog` with `event_name=Runtime_SiteChannel_Message` and redacted fields such as `channel_side`, `channel_message`, and `key`. If Slardar is unavailable or fails, they fall back to `console.warn` and `console.error`. Worker warnings and errors use the console.
|
|
217
217
|
|
|
218
|
-
Client
|
|
218
|
+
The Client assigns a `logId` when it sends an `invokeApi` request, and the Host reuses it in the response. Warning and error logs can contain the `logId`, method key, status, and error type, but no request parameters or response body. Other transport identifiers are logged only as present or absent.
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
Successful requests, responses, handshakes, events, and teardown do not emit Channel logs.
|
|
221
221
|
|
|
222
222
|
## Site Runtime
|
|
223
223
|
|
|
224
|
-
|
|
224
|
+
The package also provides a Site iframe Runtime interface so business pages do not need to use the low-level Channel directly:
|
|
225
225
|
|
|
226
226
|
```ts
|
|
227
227
|
import {
|
|
@@ -239,74 +239,74 @@ await logout();
|
|
|
239
239
|
await siteRuntime.ready();
|
|
240
240
|
```
|
|
241
241
|
|
|
242
|
-
- `./runtime
|
|
243
|
-
- `./runtime-contract
|
|
244
|
-
- `requestEdit()
|
|
245
|
-
- `getCurrentUser()
|
|
246
|
-
- `logout()
|
|
247
|
-
-
|
|
242
|
+
- `./runtime`: HTTP, Function, lifecycle, and Chatbot stream APIs for the child page.
|
|
243
|
+
- `./runtime-contract`: Shared `site.v1` keys, payloads, types, and stable error codes.
|
|
244
|
+
- `requestEdit()`: Ask the parent page to enter edit mode.
|
|
245
|
+
- `getCurrentUser()`: Read the signed-in user from the parent page; always includes `name` and `avatarUrl`.
|
|
246
|
+
- `logout()`: Ask the parent page to sign out the current user.
|
|
247
|
+
- These three methods use the built-in Runtime Functions through `site.v1.function.invoke`; they do not add peer Channel APIs.
|
|
248
248
|
|
|
249
|
-
##
|
|
249
|
+
## Common methods
|
|
250
250
|
|
|
251
251
|
### Host
|
|
252
252
|
|
|
253
|
-
- `setClientUrl(url)
|
|
254
|
-
- `registerApi(key, handler)
|
|
255
|
-
- `invokeApi(key, params)
|
|
256
|
-
- `subscribeEvent(key, handler)
|
|
257
|
-
- `unsubscribeEvent(key, handler?)
|
|
258
|
-
- `emitEvent(key, params)
|
|
259
|
-
- `destroy()
|
|
253
|
+
- `setClientUrl(url)`: Set and load the Client page URL.
|
|
254
|
+
- `registerApi(key, handler)`: Register a method callable by the Client.
|
|
255
|
+
- `invokeApi(key, params)`: Call a Client method.
|
|
256
|
+
- `subscribeEvent(key, handler)`: Subscribe to Client events; returns an unsubscribe function.
|
|
257
|
+
- `unsubscribeEvent(key, handler?)`: Remove a subscription, or all subscriptions for the event if `handler` is omitted.
|
|
258
|
+
- `emitEvent(key, params)`: Emit an event to the Client.
|
|
259
|
+
- `destroy()`: Destroy the instance and release its resources.
|
|
260
260
|
|
|
261
261
|
### Client
|
|
262
262
|
|
|
263
|
-
- `registerApi(key, handler)
|
|
264
|
-
- `invokeApi(key, params)
|
|
265
|
-
- `subscribeEvent(key, handler)
|
|
266
|
-
- `unsubscribeEvent(key, handler?)
|
|
267
|
-
- `emitEvent(key, params)
|
|
268
|
-
- `fetchBinaryList(params)
|
|
269
|
-
- `subscribeBinaryFetchProgress(handler)
|
|
270
|
-
- `cancelBinaryFetch(jobId)
|
|
263
|
+
- `registerApi(key, handler)`: Register a method callable by the Host.
|
|
264
|
+
- `invokeApi(key, params)`: Call a Host method.
|
|
265
|
+
- `subscribeEvent(key, handler)`: Subscribe to Host events; returns an unsubscribe function.
|
|
266
|
+
- `unsubscribeEvent(key, handler?)`: Remove a subscription, or all subscriptions for the event if `handler` is omitted.
|
|
267
|
+
- `emitEvent(key, params)`: Emit an event to the Host.
|
|
268
|
+
- `fetchBinaryList(params)`: Start a batch binary fetch job and return its `{ jobId }`.
|
|
269
|
+
- `subscribeBinaryFetchProgress(handler)`: Subscribe to binary fetch progress.
|
|
270
|
+
- `cancelBinaryFetch(jobId)`: Cancel a binary fetch job.
|
|
271
271
|
|
|
272
|
-
##
|
|
272
|
+
## Built-in batch binary fetching
|
|
273
273
|
|
|
274
|
-
|
|
274
|
+
Use this API to transfer large files, encrypted images, or encrypted attachments between a Host and an iframe.
|
|
275
275
|
|
|
276
|
-
###
|
|
276
|
+
### Why direct iframe downloads can fail
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
A common integration has these constraints:
|
|
279
279
|
|
|
280
|
-
- iframe
|
|
281
|
-
-
|
|
282
|
-
-
|
|
280
|
+
- The iframe runs on an external sandbox origin.
|
|
281
|
+
- Download URLs point to internal domains or restricted CDN origins.
|
|
282
|
+
- A direct `fetch(url).arrayBuffer()` from the iframe is blocked by browser CORS.
|
|
283
283
|
|
|
284
|
-
|
|
284
|
+
A download URL alone does not grant access from the iframe origin; the browser can still reject the request.
|
|
285
285
|
|
|
286
|
-
###
|
|
286
|
+
### Why the Host performs the fetch
|
|
287
287
|
|
|
288
|
-
Host
|
|
288
|
+
The Host often runs in an environment that can reach those internal or restricted origins. The flow is:
|
|
289
289
|
|
|
290
|
-
1. iframe
|
|
291
|
-
2. Host
|
|
292
|
-
3.
|
|
293
|
-
4. iframe
|
|
290
|
+
1. The iframe describes which URLs to fetch.
|
|
291
|
+
2. The Host downloads them in an internal worker.
|
|
292
|
+
3. After each download, the Host progressively transfers the complete `ArrayBuffer` to the iframe.
|
|
293
|
+
4. The iframe decrypts the bytes and creates a `Blob` or `blobUrl` as needed.
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
Business code does not need another Host worker or a custom `postMessage` protocol.
|
|
296
296
|
|
|
297
|
-
###
|
|
297
|
+
### Why responses use Transferable objects
|
|
298
298
|
|
|
299
|
-
|
|
299
|
+
Large binary files are expensive to copy between the main thread and an iframe. The built-in API uses:
|
|
300
300
|
|
|
301
301
|
```ts
|
|
302
302
|
postMessage(message, "*", [arrayBuffer]);
|
|
303
303
|
```
|
|
304
304
|
|
|
305
|
-
|
|
305
|
+
The `ArrayBuffer` is transferred as a `Transferable`, avoiding another large copy for encrypted images and attachments.
|
|
306
306
|
|
|
307
|
-
###
|
|
307
|
+
### Public API
|
|
308
308
|
|
|
309
|
-
Client
|
|
309
|
+
The Client or iframe calls these built-in APIs:
|
|
310
310
|
|
|
311
311
|
```ts
|
|
312
312
|
type BinaryFetchItem = {
|
|
@@ -355,18 +355,18 @@ client.subscribeBinaryFetchProgress(handler: (progress: BinaryFetchProgress) =>
|
|
|
355
355
|
client.cancelBinaryFetch(jobId: string): Promise<void>;
|
|
356
356
|
```
|
|
357
357
|
|
|
358
|
-
|
|
358
|
+
Notes:
|
|
359
359
|
|
|
360
|
-
-
|
|
361
|
-
- Host
|
|
362
|
-
-
|
|
363
|
-
-
|
|
364
|
-
-
|
|
365
|
-
- `credentials`
|
|
366
|
-
-
|
|
367
|
-
-
|
|
360
|
+
- Business code does not need to call `registerApi` for this feature.
|
|
361
|
+
- The Host starts the dedicated worker internally.
|
|
362
|
+
- Concurrency is controlled by default.
|
|
363
|
+
- Each job defaults to `4` concurrent downloads.
|
|
364
|
+
- A single worker defaults to a global maximum of `6` concurrent downloads.
|
|
365
|
+
- `credentials` is optional and defaults to `same-origin`.
|
|
366
|
+
- Each completed file transfers its full `ArrayBuffer` once.
|
|
367
|
+
- `fetchBinaryList` and `cancelBinaryFetch` reject before the handshake completes, like `invokeApi`.
|
|
368
368
|
|
|
369
|
-
###
|
|
369
|
+
### Start a URL-list fetch
|
|
370
370
|
|
|
371
371
|
```ts
|
|
372
372
|
import { client } from "@lark-base-open/base-site-channel";
|
|
@@ -387,7 +387,7 @@ const { jobId } = await client.fetchBinaryList({
|
|
|
387
387
|
});
|
|
388
388
|
```
|
|
389
389
|
|
|
390
|
-
###
|
|
390
|
+
### Subscribe to progress
|
|
391
391
|
|
|
392
392
|
```ts
|
|
393
393
|
const unsubscribe = client.subscribeBinaryFetchProgress((progress) => {
|
|
@@ -426,21 +426,21 @@ const unsubscribe = client.subscribeBinaryFetchProgress((progress) => {
|
|
|
426
426
|
});
|
|
427
427
|
```
|
|
428
428
|
|
|
429
|
-
###
|
|
429
|
+
### Cancel a job
|
|
430
430
|
|
|
431
431
|
```ts
|
|
432
432
|
await client.cancelBinaryFetch(jobId);
|
|
433
433
|
unsubscribe();
|
|
434
434
|
```
|
|
435
435
|
|
|
436
|
-
###
|
|
436
|
+
### Complete example
|
|
437
437
|
|
|
438
|
-
|
|
438
|
+
This example shows how to:
|
|
439
439
|
|
|
440
|
-
-
|
|
441
|
-
-
|
|
442
|
-
-
|
|
443
|
-
-
|
|
440
|
+
- Start `fetchBinaryList` from the Client.
|
|
441
|
+
- Receive `item-complete` progress events.
|
|
442
|
+
- Use `itemId` to associate each complete `ArrayBuffer` with its request.
|
|
443
|
+
- Decrypt the bytes and create a `blobUrl` in the iframe.
|
|
444
444
|
|
|
445
445
|
```ts
|
|
446
446
|
import { client } from "@lark-base-open/base-site-channel";
|
|
@@ -503,7 +503,7 @@ function decryptFileBytes(
|
|
|
503
503
|
return Promise.resolve(buffer);
|
|
504
504
|
}
|
|
505
505
|
|
|
506
|
-
//
|
|
506
|
+
// Cancel when the business flow no longer needs this job.
|
|
507
507
|
if (shouldCancelJob(jobId)) {
|
|
508
508
|
await client.cancelBinaryFetch(jobId);
|
|
509
509
|
}
|
|
@@ -513,9 +513,9 @@ function shouldCancelJob(targetJobId: string) {
|
|
|
513
513
|
}
|
|
514
514
|
```
|
|
515
515
|
|
|
516
|
-
###
|
|
516
|
+
### Progress message shape
|
|
517
517
|
|
|
518
|
-
|
|
518
|
+
Built-in progress messages have these types:
|
|
519
519
|
|
|
520
520
|
```ts
|
|
521
521
|
type BinaryFetchProgress =
|
|
@@ -549,70 +549,70 @@ type BinaryFetchProgress =
|
|
|
549
549
|
};
|
|
550
550
|
```
|
|
551
551
|
|
|
552
|
-
##
|
|
552
|
+
## Events
|
|
553
553
|
|
|
554
|
-
|
|
554
|
+
Use events for one-way state changes that need no return value, for example:
|
|
555
555
|
|
|
556
|
-
-
|
|
557
|
-
- iframe
|
|
558
|
-
-
|
|
556
|
+
- Notify the iframe to update its style when the Host theme changes.
|
|
557
|
+
- Notify the Host to refresh outer-page state when iframe data changes.
|
|
558
|
+
- Synchronize lightweight selection, form, or visibility state.
|
|
559
559
|
|
|
560
|
-
|
|
560
|
+
How they differ from `invokeApi`:
|
|
561
561
|
|
|
562
|
-
- `invokeApi`
|
|
563
|
-
- `emitEvent`
|
|
564
|
-
- `subscribeEvent`
|
|
562
|
+
- Use `invokeApi` for request-response operations that need a result.
|
|
563
|
+
- Use `emitEvent` for one-way notifications; it does not await a business result.
|
|
564
|
+
- Use `subscribeEvent` to receive events emitted by the other side.
|
|
565
565
|
|
|
566
|
-
###
|
|
566
|
+
### Subscribe to Client events from the Host
|
|
567
567
|
|
|
568
568
|
```ts
|
|
569
569
|
const stopListenDataChange = host.subscribeEvent<{ count: number }>(
|
|
570
570
|
"dataChange",
|
|
571
571
|
(payload) => {
|
|
572
|
-
//
|
|
572
|
+
// Refresh Host state after data changes in the iframe.
|
|
573
573
|
console.log("host receive dataChange", payload.count);
|
|
574
574
|
},
|
|
575
575
|
);
|
|
576
576
|
```
|
|
577
577
|
|
|
578
|
-
###
|
|
578
|
+
### Emit an event to the Host from the Client
|
|
579
579
|
|
|
580
580
|
```ts
|
|
581
581
|
client.emitEvent("dataChange", {
|
|
582
|
-
//
|
|
582
|
+
// Tell the Host that data changed.
|
|
583
583
|
count: 1,
|
|
584
584
|
});
|
|
585
585
|
```
|
|
586
586
|
|
|
587
|
-
###
|
|
587
|
+
### Subscribe to Host events from the Client
|
|
588
588
|
|
|
589
589
|
```ts
|
|
590
590
|
const stopListenThemeChange = client.subscribeEvent<{
|
|
591
591
|
theme: "light" | "dark";
|
|
592
592
|
}>("themeChange", (payload) => {
|
|
593
|
-
//
|
|
593
|
+
// Handle a Host theme change.
|
|
594
594
|
document.body.dataset.theme = payload.theme;
|
|
595
595
|
});
|
|
596
596
|
```
|
|
597
597
|
|
|
598
|
-
###
|
|
598
|
+
### Emit an event to the Client from the Host
|
|
599
599
|
|
|
600
600
|
```ts
|
|
601
601
|
client.emitEvent("themeChange", {
|
|
602
|
-
//
|
|
602
|
+
// Ask the Client to apply the new theme.
|
|
603
603
|
theme: "dark",
|
|
604
604
|
});
|
|
605
605
|
```
|
|
606
606
|
|
|
607
|
-
###
|
|
607
|
+
### Unsubscribe
|
|
608
608
|
|
|
609
|
-
|
|
609
|
+
Prefer the cleanup function returned by `subscribeEvent`:
|
|
610
610
|
|
|
611
611
|
```ts
|
|
612
612
|
const unsubscribe = client.subscribeEvent<{ visible: boolean }>(
|
|
613
613
|
"visibleChange",
|
|
614
614
|
(payload) => {
|
|
615
|
-
//
|
|
615
|
+
// Handle a visibility change.
|
|
616
616
|
console.log(payload.visible);
|
|
617
617
|
},
|
|
618
618
|
);
|
|
@@ -620,11 +620,11 @@ const unsubscribe = client.subscribeEvent<{ visible: boolean }>(
|
|
|
620
620
|
unsubscribe();
|
|
621
621
|
```
|
|
622
622
|
|
|
623
|
-
|
|
623
|
+
You can also remove a listener with `unsubscribeEvent`:
|
|
624
624
|
|
|
625
625
|
```ts
|
|
626
626
|
const onVisibleChange = (payload: { visible: boolean }) => {
|
|
627
|
-
//
|
|
627
|
+
// Handle a visibility change.
|
|
628
628
|
console.log(payload.visible);
|
|
629
629
|
};
|
|
630
630
|
|
|
@@ -632,16 +632,16 @@ client.subscribeEvent("visibleChange", onVisibleChange);
|
|
|
632
632
|
client.unsubscribeEvent("visibleChange", onVisibleChange);
|
|
633
633
|
```
|
|
634
634
|
|
|
635
|
-
|
|
635
|
+
Recommendations:
|
|
636
636
|
|
|
637
|
-
-
|
|
638
|
-
-
|
|
639
|
-
-
|
|
640
|
-
-
|
|
637
|
+
- Give event `key` values clear business names, such as `themeChange` or `dataChange`.
|
|
638
|
+
- Use events for notifications, not as substitutes for calls that return values.
|
|
639
|
+
- Unsubscribe when a page or component unmounts to avoid duplicate listeners.
|
|
640
|
+
- Keep event payloads small and stable; avoid values that are difficult to serialize.
|
|
641
641
|
|
|
642
|
-
## invokeApi
|
|
642
|
+
## Errors from invokeApi
|
|
643
643
|
|
|
644
|
-
`invokeApi`
|
|
644
|
+
A failed `invokeApi` call rejects its Promise with an error object shaped like this:
|
|
645
645
|
|
|
646
646
|
```ts
|
|
647
647
|
type InvokeApiError = {
|
|
@@ -650,7 +650,7 @@ type InvokeApiError = {
|
|
|
650
650
|
};
|
|
651
651
|
```
|
|
652
652
|
|
|
653
|
-
|
|
653
|
+
Handle failures with `try/catch`:
|
|
654
654
|
|
|
655
655
|
```ts
|
|
656
656
|
try {
|
|
@@ -664,44 +664,44 @@ try {
|
|
|
664
664
|
} catch (error) {
|
|
665
665
|
const invokeError = error;
|
|
666
666
|
console.error(
|
|
667
|
-
"
|
|
667
|
+
"Request failed",
|
|
668
668
|
invokeError?.code,
|
|
669
669
|
invokeError?.msg || invokeError?.message,
|
|
670
670
|
);
|
|
671
671
|
}
|
|
672
672
|
```
|
|
673
673
|
|
|
674
|
-
|
|
674
|
+
Common failure cases:
|
|
675
675
|
|
|
676
|
-
-
|
|
677
|
-
- iframe
|
|
678
|
-
-
|
|
679
|
-
-
|
|
680
|
-
-
|
|
676
|
+
- A business API fails.
|
|
677
|
+
- The iframe page fails to load.
|
|
678
|
+
- The current page URL is outside the allowed origins.
|
|
679
|
+
- Page initialization has not completed before the call times out.
|
|
680
|
+
- The remote method fails and returns a business error.
|
|
681
681
|
|
|
682
|
-
|
|
682
|
+
Common error codes:
|
|
683
683
|
|
|
684
|
-
-
|
|
685
|
-
- `-1
|
|
686
|
-
- `10001
|
|
687
|
-
- `10002
|
|
688
|
-
- `10003
|
|
689
|
-
- `10004
|
|
690
|
-
- `10005
|
|
691
|
-
- `10006
|
|
692
|
-
- `10007
|
|
693
|
-
- `10008
|
|
694
|
-
- `10009
|
|
684
|
+
- Codes returned by business APIs.
|
|
685
|
+
- `-1`: Unknown error.
|
|
686
|
+
- `10001`: Iframe load failed.
|
|
687
|
+
- `10002`: The current page URL is not allowed to communicate.
|
|
688
|
+
- `10003`: Page initialization timed out.
|
|
689
|
+
- `10004`: The remote API is not registered.
|
|
690
|
+
- `10005`: The call timed out.
|
|
691
|
+
- `10006`: The channel has been destroyed.
|
|
692
|
+
- `10007`: Built-in binary downloading is disabled.
|
|
693
|
+
- `10008`: Another request replaced one with the same ID.
|
|
694
|
+
- `10009`: The environment cannot establish a channel (for example, not an iframe, no Host origin, or `setClientUrl` has not been called).
|
|
695
695
|
|
|
696
|
-
|
|
696
|
+
Handling recommendations:
|
|
697
697
|
|
|
698
|
-
-
|
|
699
|
-
- Host
|
|
700
|
-
-
|
|
698
|
+
- Call `invokeApi` only after the status becomes `loaded`.
|
|
699
|
+
- On the Host, finish `registerApi` calls before `setClientUrl`.
|
|
700
|
+
- Convert business failures into specific `code` and `msg` values for consistent handling by callers.
|
|
701
701
|
|
|
702
|
-
##
|
|
702
|
+
## Complete example
|
|
703
703
|
|
|
704
|
-
### Host
|
|
704
|
+
### Host page
|
|
705
705
|
|
|
706
706
|
```ts
|
|
707
707
|
import { Host, LoadStatus } from "@lark-base-open/base-site-channel";
|
|
@@ -716,7 +716,7 @@ const host = new Host(
|
|
|
716
716
|
container,
|
|
717
717
|
(status) => {
|
|
718
718
|
if (status === LoadStatus.LOADED) {
|
|
719
|
-
console.log("
|
|
719
|
+
console.log("Client page is ready");
|
|
720
720
|
}
|
|
721
721
|
},
|
|
722
722
|
"demo-block",
|
|
@@ -754,7 +754,7 @@ host.emitEvent("themeChange", {
|
|
|
754
754
|
stopListenDataChange();
|
|
755
755
|
```
|
|
756
756
|
|
|
757
|
-
### Client
|
|
757
|
+
### Client page
|
|
758
758
|
|
|
759
759
|
```ts
|
|
760
760
|
import { client } from "@lark-base-open/base-site-channel";
|
|
@@ -789,9 +789,9 @@ client.emitEvent("dataChange", {
|
|
|
789
789
|
stopListenThemeChange();
|
|
790
790
|
```
|
|
791
791
|
|
|
792
|
-
##
|
|
792
|
+
## Recommendations
|
|
793
793
|
|
|
794
|
-
- `key`
|
|
795
|
-
- `instanceId`
|
|
796
|
-
-
|
|
797
|
-
-
|
|
794
|
+
- Name each `key` by its business purpose and avoid duplicates.
|
|
795
|
+
- Keep `instanceId` unique for each iframe instance.
|
|
796
|
+
- Call `destroy` when the Host page unmounts, navigates away, or remounts.
|
|
797
|
+
- Start business calls only after the iframe is ready.
|
package/dist/client.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var V=Object.defineProperty,q=Object.defineProperties;var J=Object.getOwnPropertyDescriptors;var N=Object.getOwnPropertySymbols;var $=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var B=(n,e,t)=>e in n?V(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,o=(n,e)=>{for(var t in e||(e={}))$.call(e,t)&&B(n,t,e[t]);if(N)for(var t of N(e))G.call(e,t)&&B(n,t,e[t]);return n},I=(n,e)=>q(n,J(e));var p=(n,e,t)=>new Promise((r,s)=>{var i=l=>{try{h(t.next(l))}catch(v){s(v)}},a=l=>{try{h(t.throw(l))}catch(v){s(v)}},h=l=>l.done?r(l.value):Promise.resolve(l.value).then(i,a);h((t=t.apply(n,e)).next())});import{uniqueId as H}from"lodash-es";var k="same-origin",w="__internal_fetchBinaryList__",F="__internal_cancelBinaryFetch__",O="__internal_binaryFetchProgress__";function A(n){return Number.isFinite(n)?Math.max(1,Math.floor(n)):4}function T(n){return n==="omit"||n==="include"?n:k}var m=(s=>(s.IFRAME_LOAD_ERROR="iframeLoadError",s.NOT_ALLOWED_URL="notAllowedUrl",s.HANDSHAKE_TIME_OUT="handshakeTimeout",s.CHANNEL_UNAVAILABLE="channelUnavailable",s))(m||{});var c=class extends Error{constructor(t,r){super(r);this.code=t,this.name="ChannelCallbackError"}};function D(n){return new c(10004,`api "${n}" is not registered`)}function K(n){return new c(10005,`api "${n}" timed out`)}function b(){return new c(10006,"channel has been destroyed")}function U(n){return new c(10008,`request "${n}" was superseded by a new one`)}var X="unknown error";function j(n){return typeof n=="object"&&n!==null}function Z(n){if(typeof n=="string"&&n)return n;if(n instanceof c&&n.message||n instanceof Error&&n.message)return n.message;if(j(n)){let{msg:e,message:t}=n;if(typeof e=="string"&&e)return e;if(typeof t=="string"&&t)return t}return X}function ee(n){if(n instanceof c)return n.code;if(!j(n))return-1;let{code:e}=n;return typeof e=="string"&&e||typeof e=="number"&&Number.isFinite(e)?e:-1}function d(n){return{code:ee(n),msg:Z(n)}}function S(n){return n instanceof ArrayBuffer||ArrayBuffer.isView(n)||typeof Blob!="undefined"&&n instanceof Blob}function te(n){return S(n)||Object.values(n).some(e=>S(e))}function W(n){return n&&typeof n=="object"?te(n)?n:JSON.parse(JSON.stringify(n)):n}var ne={["iframeLoadError"]:10001,["notAllowedUrl"]:10002,["handshakeTimeout"]:10003,["channelUnavailable"]:10009};function re(n){return typeof n=="object"&&n!==null}function se(n){if(!re(n))return!1;let{type:e}=n;return typeof e=="string"&&Object.values(m).includes(e)}function x(n){return se(n)?{code:ne[n.type],msg:n.message||n.type}:d(n)}function M(n){let e=Promise.reject(n);return e.catch(()=>{}),e}var E=class{constructor(e,t){this._target=e,this._options=t}sendMsg(e,t){if(!this._target)throw new Error("target window is not found");this._target.postMessage(e,this._options.targetOrigin,t!=null?t:[])}listenMsg(e){this._eventHandler=t=>{t.source===this._options.sourceWindow&&this._options.allowedOrigins.includes(t.origin)&&e(t)},typeof window!="undefined"&&window.addEventListener("message",this._eventHandler)}destroy(){typeof window!="undefined"&&this._eventHandler&&window.removeEventListener("message",this._eventHandler),this._eventHandler=void 0}};var f=class{constructor(e,t,r){e==="host"?this.channelManager=new E(t,r):e==="client"&&(this.channelManager=new E(window.parent,r))}static createInstance(e,t,r){return new f(e,t,r)}sendMsg(e,t){var r;(r=this.channelManager)==null||r.sendMsg(e,t)}listenMsg(e){var t;(t=this.channelManager)==null||t.listenMsg(e)}destroy(){var e;(e=this.channelManager)==null||e.destroy()}};var _=class{constructor(){this.requests=new Map}create(e,t,r=3e4){return this.reject(e,d(U(e))),new Promise((s,i)=>{let a=setTimeout(()=>{var h;((h=this.requests.get(e))==null?void 0:h.timeout)===a&&(this.requests.delete(e),i(d(K(t))))},r);this.requests.set(e,{reject:i,resolve:s,timeout:a})})}resolve(e,t){let r=this.take(e);return r?(r.resolve(t),!0):!1}reject(e,t){let r=this.take(e);return r?(r.reject(t),!0):!1}rejectAll(e){for(let t of this.requests.keys())this.reject(t,e)}take(e){let t=this.requests.get(e);if(t)return this.requests.delete(e),clearTimeout(t.timeout),t}};var L=n=>typeof n=="object"&&n!==null,oe=new Set(["blockId","expectedPrefixId","id","jobId","prefixId","url"]),u=n=>{let e={};for(let[t,r]of Object.entries(n))if(!(t==="inputParams"||t==="outputParams")){if(oe.has(t)){e[`${t}Present`]=!!r;continue}if(t==="error"){Object.assign(e,g(r));continue}if(t==="errorInfo"&&L(r)){e.errorType=typeof r.type=="string"?r.type:"object";continue}(typeof r=="string"||typeof r=="number"||typeof r=="boolean")&&(e[t]=r)}return e},y=n=>{let e={idPresent:!!n.id,type:n.type},t=L(n.payload)?n.payload:{};return typeof t.key=="string"&&(e.key=t.key),n.type==="callback"&&typeof t.code=="number"&&(e.callbackCode=t.code),n.type==="handshake"&&typeof t.proactive=="boolean"&&(e.proactive=t.proactive),e},R=n=>n.type!=="invoke"&&n.type!=="callback",g=n=>{if(!L(n))return{errorType:typeof n};let e={errorType:n instanceof Error?n.name:"object"};return(typeof n.code=="number"||typeof n.code=="string")&&(e.errorCode=n.code),e};var le=()=>{let n=Reflect.get(globalThis,"BearWebSlardarWeb");return typeof n=="function"?n:void 0},he=n=>{let e={};for(let[t,r]of Object.entries(u(n)))typeof r=="string"||typeof r=="number"?e[t]=r:typeof r=="boolean"&&(e[t]=String(r));return e},Y=(n,e,t,r)=>{console[e](`[base-site-channel][${n}]`,t,r)},C=(n,e,t,r={})=>{let s=u(r),i=le();if(!i){Y(n,e,t,s);return}try{i("sendLog",{content:`[base-site-channel][${n}] ${t}`,extra:o({event_name:"Runtime_SiteChannel_Message",bizType:"Runtime",subType:"SiteChannel",action:"Message",channel_side:n,channel_message:t},he(s)),level:e})}catch(a){Y(n,e,t,I(o({},s),{slardarFallback:!0,slardarErrorType:a instanceof Error?a.name:typeof a}))}};var pe=()=>{var t;if(typeof window=="undefined")return null;let e=((t=window.location.ancestorOrigins)==null?void 0:t[0])||document.referrer;if(!e)return null;try{return new URL(e).origin}catch(r){return null}},ue=n=>{try{return new URL(n).origin}catch(e){return null}},P=class{constructor(e={}){this.pendingRequests=new _;this.eventMap=new Map;this.eventHandlerMap=new Map;this._msgChannel=null;this._invokeId="";this._handshakePromise=M({type:"channelUnavailable",message:"channel handshake is not initialized"});this._handshakeResolve=null;this._handshakeReject=null;this._handshakeRetryTimes=0;this._handshakeStatus=0;this._handshakeTimeout=null;this._prefixId="";this._destroyed=!1;let t=e.hostOrigin?ue(e.hostOrigin):null;if(this.hostOrigin=t!=null?t:pe(),e.hostOrigin&&!t&&this.logWarn("invalid hostOrigin, fallback to parent origin"),typeof window=="undefined"||window.parent===window){this.failHandshake("invalid window context",{hasWindow:typeof window!="undefined",isTopWindow:typeof window!="undefined"?window.parent===window:!0});return}if(!this.hostOrigin){this.failHandshake("host origin unavailable");return}this._msgChannel=f.createInstance("client",window.parent,{allowedOrigins:[this.hostOrigin],sourceWindow:window.parent,targetOrigin:this.hostOrigin}),this.listeningHostMsg(),this.startHandshake()}logInfo(e,t={}){C("client","info",e,o({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},u(t)))}logWarn(e,t={}){C("client","warn",e,o({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},u(t)))}logError(e,t={}){C("client","error",e,o({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},u(t)))}failHandshake(e,t={}){this._handshakeStatus=2,this._handshakePromise=M({type:"channelUnavailable",message:e}),this.logError(`init failed: ${e}`,t)}sendProactiveHandshakeMsg(){var t;let e={id:H("handshake-"),type:"handshake",payload:{proactive:!0}};this.logInfo("send proactive handshake",y(e)),(t=this._msgChannel)==null||t.sendMsg(e)}_initHandshake(){this._handshakeRetryTimes=0,clearTimeout(this._handshakeTimeout),this._handshakeStatus=0,this.logInfo("init handshake"),this._handshakePromise=new Promise((e,t)=>{this._handshakeResolve=e,this._handshakeReject=t,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(t),2e3)})}startHandshake(){this._initHandshake(),this._handshakePromise.then(()=>{this._handshakeStatus=1,this.logInfo("handshake success")}).catch(e=>{this._handshakeStatus=2,this.logError("handshake failed",{error:e})}),this.sendProactiveHandshakeMsg()}retryHandshake(e){this._handshakeStatus===0&&(this._handshakeRetryTimes<5?(this.logWarn("retry handshake",{retryTimes:this._handshakeRetryTimes+1}),this.sendProactiveHandshakeMsg(),this._handshakeRetryTimes++,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(e),2e3+2**this._handshakeRetryTimes)):(this.logError("handshake retry timeout",{retryTimes:this._handshakeRetryTimes}),e({type:"handshakeTimeout",message:"iframe handshake time out"})))}updateInvokeId(){this._invokeId=H(`${this._prefixId}-invoke-`)}handleChannelMessage(e){let{data:t}=e;R(t)&&this.logInfo("receive host message",y(t));let{type:r}=t;r==="callback"?this.handleHostCallback(t):r==="handshake"?this.handleHandshakeCallback(t):r==="invoke"?this.handleHostInvoke(t).catch(s=>{this.logError("handle host invoke error",o(o({},y(t)),g(s)))}):r==="event"&&this.handleHostEvent(t).catch(s=>{this.logError("handle host event error",o(o({},y(t)),g(s)))})}handleHostCallback(e){let{id:t,payload:r}=e,s={logId:t,key:r.key,callbackCode:r.code};if(r.code===1){if(this.pendingRequests.reject(t,r.res)){this.logWarn("api response received",s);return}}else if(this.pendingRequests.resolve(t,r.res)){this.logInfo("api response received",s);return}this.logWarn("host callback request not found",{id:t,key:r.key})}handleHostInvoke(e){return p(this,null,function*(){yield this._handshakePromise;let{id:t,payload:r}=e,{key:s,params:i,prefixId:a}=r;if(a!==this._prefixId){this.logWarn("ignore host invoke because prefixId mismatch",{id:t,key:s,prefixId:a,expectedPrefixId:this._prefixId});return}let h=this.eventMap.get(s);if(typeof h!="function"){this.logWarn("host invoke handler not found",{id:t,key:s}),this.sendMsg2Host({id:t,type:"callback",payload:{key:s,res:d(D(s)),code:1}});return}this.logInfo("handle host invoke",{id:t,key:s});try{let l=W(yield h(i));this.sendMsg2Host({id:t,type:"callback",payload:{key:s,res:l,code:0}}),this.logInfo("host invoke success",{id:t,key:s})}catch(l){this.logError("host invoke failed",o({id:t,key:s},g(l))),this.sendMsg2Host({id:t,type:"callback",payload:{key:s,res:d(l),code:1}})}})}handleHostEvent(e){return p(this,null,function*(){yield this._handshakePromise;let{payload:t}=e,{key:r,params:s,prefixId:i}=t;if(i!==this._prefixId){this.logWarn("ignore host event because prefixId mismatch",{key:r,prefixId:i,expectedPrefixId:this._prefixId});return}let a=this.eventHandlerMap.get(r);if(!(a!=null&&a.size)){this.logWarn("host event handler not found",{key:r});return}this.logInfo("handle host event",{key:r,handlerCount:a.size}),yield Promise.allSettled(Array.from(a,h=>h(s)))})}handleHandshakeCallback(e){var i,a;let{id:t,payload:r}=e;this._prefixId=(i=r==null?void 0:r.prefixId)!=null?i:"",this.logInfo("receive handshake callback",{id:t,prefixId:this._prefixId}),(a=this._handshakeResolve)==null||a.call(this);let s={id:t,type:"handshake",payload:{proactive:!1,info:{isHandshakeSuccess:!0}}};this.sendMsg2Host(s)}listeningHostMsg(){var e;this.logInfo("start listening host messages"),(e=this._msgChannel)==null||e.listenMsg(this.handleChannelMessage.bind(this))}sendMsg2Host(e,t){var r;R(e)&&this.logInfo("send message to host",y(e)),(r=this._msgChannel)==null||r.sendMsg(e,t)}invokeApi(e,t,r){return p(this,null,function*(){if(this._destroyed)return Promise.reject(d(b()));try{yield this._handshakePromise}catch(a){return this.logError("invoke api blocked by handshake error",o({key:e},g(a))),Promise.reject(x(a))}this._invokeId||this.updateInvokeId();let s=this._invokeId,i=this.pendingRequests.create(s,e,r==null?void 0:r.timeoutMs);return this.logInfo("api request sent",{key:e,logId:s}),this.sendMsg2Host({type:"invoke",id:s,payload:{key:e,params:t,prefixId:this._prefixId}}),this.updateInvokeId(),i})}registerApi(e,t){if(this.eventMap.has(e)){this.logWarn("register api ignored because key already exists",{key:e});return}this.eventMap.set(e,t),this.logInfo("register api",{key:e})}emitEvent(e,t){return p(this,null,function*(){try{yield this._handshakePromise}catch(r){return this.logError("emit event blocked by handshake error",o({key:e},g(r))),Promise.reject(x(r))}this.logInfo("emit event",{key:e}),this.sendMsg2Host({type:"event",id:H(`${this._prefixId}-event-`),payload:{key:e,params:t,prefixId:this._prefixId}})})}fetchBinaryList(e){return p(this,null,function*(){var t;return this.logInfo("invoke built-in binary fetch",{status:"start",itemCount:e.items.length,concurrency:A(e.concurrency),credentials:T(e.credentials)}),this.invokeApi(w,{items:e.items,concurrency:A(e.concurrency),credentials:T((t=e.credentials)!=null?t:k)})})}subscribeBinaryFetchProgress(e){return this.subscribeEvent(O,e)}cancelBinaryFetch(e){return p(this,null,function*(){this.logInfo("invoke built-in binary fetch cancel",{jobId:e,status:"cancel-requested"}),yield this.invokeApi(F,{jobId:e})})}destroy(){var t,r;if(this._destroyed)return;this._destroyed=!0,this.logInfo("destroy client"),(t=this._msgChannel)==null||t.destroy(),clearTimeout(this._handshakeTimeout);let e=d(b());(r=this._handshakeReject)==null||r.call(this,{type:"handshakeTimeout",message:e.msg}),this.pendingRequests.rejectAll(e),this.eventMap.clear(),this.eventHandlerMap.clear()}subscribeEvent(e,t){var s;let r=(s=this.eventHandlerMap.get(e))!=null?s:new Set;return r.add(t),this.eventHandlerMap.set(e,r),this.logInfo("subscribe event",{key:e,handlerCount:r.size}),()=>this.unsubscribeEvent(e,t)}unsubscribeEvent(e,t){let r=this.eventHandlerMap.get(e);if(!r){this.logWarn("unsubscribe event ignored because key is not subscribed",{key:e});return}if(!t){this.eventHandlerMap.delete(e),this.logInfo("unsubscribe all event handlers",{key:e,handlerCount:0});return}r.delete(t),r.size===0&&this.eventHandlerMap.delete(e),this.logInfo("unsubscribe event",{key:e,handlerCount:r.size})}},ge=n=>new P(n),_t=ge();export{P as Client,_t as client,ge as createClient};
|
|
1
|
+
var V=Object.defineProperty,q=Object.defineProperties;var J=Object.getOwnPropertyDescriptors;var N=Object.getOwnPropertySymbols;var $=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var B=(n,e,t)=>e in n?V(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,o=(n,e)=>{for(var t in e||(e={}))$.call(e,t)&&B(n,t,e[t]);if(N)for(var t of N(e))G.call(e,t)&&B(n,t,e[t]);return n},v=(n,e)=>q(n,J(e));var p=(n,e,t)=>new Promise((r,s)=>{var i=l=>{try{h(t.next(l))}catch(I){s(I)}},a=l=>{try{h(t.throw(l))}catch(I){s(I)}},h=l=>l.done?r(l.value):Promise.resolve(l.value).then(i,a);h((t=t.apply(n,e)).next())});import{uniqueId as H}from"lodash-es";var k="same-origin",w="__internal_fetchBinaryList__",F="__internal_cancelBinaryFetch__",O="__internal_binaryFetchProgress__";function A(n){return Number.isFinite(n)?Math.max(1,Math.floor(n)):4}function T(n){return n==="omit"||n==="include"?n:k}var m=(s=>(s.IFRAME_LOAD_ERROR="iframeLoadError",s.NOT_ALLOWED_URL="notAllowedUrl",s.HANDSHAKE_TIME_OUT="handshakeTimeout",s.CHANNEL_UNAVAILABLE="channelUnavailable",s))(m||{});var c=class extends Error{constructor(t,r){super(r);this.code=t,this.name="ChannelCallbackError"}};function D(n){return new c(10004,`api "${n}" is not registered`)}function K(n){return new c(10005,`api "${n}" timed out`)}function b(){return new c(10006,"channel has been destroyed")}function U(n){return new c(10008,`request "${n}" was superseded by a new one`)}var X="unknown error";function j(n){return typeof n=="object"&&n!==null}function Z(n){if(typeof n=="string"&&n)return n;if(n instanceof c&&n.message||n instanceof Error&&n.message)return n.message;if(j(n)){let{msg:e,message:t}=n;if(typeof e=="string"&&e)return e;if(typeof t=="string"&&t)return t}return X}function ee(n){if(n instanceof c)return n.code;if(!j(n))return-1;let{code:e}=n;return typeof e=="string"&&e||typeof e=="number"&&Number.isFinite(e)?e:-1}function d(n){return{code:ee(n),msg:Z(n)}}function S(n){return n instanceof ArrayBuffer||ArrayBuffer.isView(n)||typeof Blob!="undefined"&&n instanceof Blob}function te(n){return S(n)||Object.values(n).some(e=>S(e))}function W(n){return n&&typeof n=="object"?te(n)?n:JSON.parse(JSON.stringify(n)):n}var ne={["iframeLoadError"]:10001,["notAllowedUrl"]:10002,["handshakeTimeout"]:10003,["channelUnavailable"]:10009};function re(n){return typeof n=="object"&&n!==null}function se(n){if(!re(n))return!1;let{type:e}=n;return typeof e=="string"&&Object.values(m).includes(e)}function x(n){return se(n)?{code:ne[n.type],msg:n.message||n.type}:d(n)}function M(n){let e=Promise.reject(n);return e.catch(()=>{}),e}var E=class{constructor(e,t){this._target=e,this._options=t}sendMsg(e,t){if(!this._target)throw new Error("target window is not found");this._target.postMessage(e,this._options.targetOrigin,t!=null?t:[])}listenMsg(e){this._eventHandler=t=>{t.source===this._options.sourceWindow&&this._options.allowedOrigins.includes(t.origin)&&e(t)},typeof window!="undefined"&&window.addEventListener("message",this._eventHandler)}destroy(){typeof window!="undefined"&&this._eventHandler&&window.removeEventListener("message",this._eventHandler),this._eventHandler=void 0}};var f=class{constructor(e,t,r){e==="host"?this.channelManager=new E(t,r):e==="client"&&(this.channelManager=new E(window.parent,r))}static createInstance(e,t,r){return new f(e,t,r)}sendMsg(e,t){var r;(r=this.channelManager)==null||r.sendMsg(e,t)}listenMsg(e){var t;(t=this.channelManager)==null||t.listenMsg(e)}destroy(){var e;(e=this.channelManager)==null||e.destroy()}};var _=class{constructor(){this.requests=new Map}create(e,t,r=3e4){return this.reject(e,d(U(e))),new Promise((s,i)=>{let a=setTimeout(()=>{var h;((h=this.requests.get(e))==null?void 0:h.timeout)===a&&(this.requests.delete(e),i(d(K(t))))},r);this.requests.set(e,{reject:i,resolve:s,timeout:a})})}resolve(e,t){let r=this.take(e);return r?(r.resolve(t),!0):!1}reject(e,t){let r=this.take(e);return r?(r.reject(t),!0):!1}rejectAll(e){for(let t of this.requests.keys())this.reject(t,e)}take(e){let t=this.requests.get(e);if(t)return this.requests.delete(e),clearTimeout(t.timeout),t}};var L=n=>typeof n=="object"&&n!==null,oe=new Set(["blockId","expectedPrefixId","id","jobId","prefixId","url"]),u=n=>{let e={};for(let[t,r]of Object.entries(n))if(!(t==="inputParams"||t==="outputParams")){if(oe.has(t)){e[`${t}Present`]=!!r;continue}if(t==="error"){Object.assign(e,g(r));continue}if(t==="errorInfo"&&L(r)){e.errorType=typeof r.type=="string"?r.type:"object";continue}(typeof r=="string"||typeof r=="number"||typeof r=="boolean")&&(e[t]=r)}return e},y=n=>{let e={idPresent:!!n.id,type:n.type},t=L(n.payload)?n.payload:{};return typeof t.key=="string"&&(e.key=t.key),n.type==="callback"&&typeof t.code=="number"&&(e.callbackCode=t.code),n.type==="handshake"&&typeof t.proactive=="boolean"&&(e.proactive=t.proactive),e},R=n=>n.type!=="invoke"&&n.type!=="callback",g=n=>{if(!L(n))return{errorType:typeof n};let e={errorType:n instanceof Error?n.name:"object"};return(typeof n.code=="number"||typeof n.code=="string")&&(e.errorCode=n.code),e};var le=()=>{let n=Reflect.get(globalThis,"BearWebSlardarWeb");return typeof n=="function"?n:void 0},he=n=>{let e={};for(let[t,r]of Object.entries(u(n)))typeof r=="string"||typeof r=="number"?e[t]=r:typeof r=="boolean"&&(e[t]=String(r));return e},Y=(n,e,t,r)=>{console[e](`[base-site-channel][${n}]`,t,r)},C=(n,e,t,r={})=>{if(e==="info")return;let s=u(r),i=le();if(!i){Y(n,e,t,s);return}try{i("sendLog",{content:`[base-site-channel][${n}] ${t}`,extra:o({event_name:"Runtime_SiteChannel_Message",bizType:"Runtime",subType:"SiteChannel",action:"Message",channel_side:n,channel_message:t},he(s)),level:e})}catch(a){Y(n,e,t,v(o({},s),{slardarFallback:!0,slardarErrorType:a instanceof Error?a.name:typeof a}))}};var pe=()=>{var t;if(typeof window=="undefined")return null;let e=((t=window.location.ancestorOrigins)==null?void 0:t[0])||document.referrer;if(!e)return null;try{return new URL(e).origin}catch(r){return null}},ue=n=>{try{return new URL(n).origin}catch(e){return null}},P=class{constructor(e={}){this.pendingRequests=new _;this.eventMap=new Map;this.eventHandlerMap=new Map;this._msgChannel=null;this._invokeId="";this._handshakePromise=M({type:"channelUnavailable",message:"channel handshake is not initialized"});this._handshakeResolve=null;this._handshakeReject=null;this._handshakeRetryTimes=0;this._handshakeStatus=0;this._handshakeTimeout=null;this._prefixId="";this._destroyed=!1;let t=e.hostOrigin?ue(e.hostOrigin):null;if(this.hostOrigin=t!=null?t:pe(),e.hostOrigin&&!t&&this.logWarn("invalid hostOrigin, fallback to parent origin"),typeof window=="undefined"||window.parent===window){this.failHandshake("invalid window context",{hasWindow:typeof window!="undefined",isTopWindow:typeof window!="undefined"?window.parent===window:!0});return}if(!this.hostOrigin){this.failHandshake("host origin unavailable");return}this._msgChannel=f.createInstance("client",window.parent,{allowedOrigins:[this.hostOrigin],sourceWindow:window.parent,targetOrigin:this.hostOrigin}),this.listeningHostMsg(),this.startHandshake()}logInfo(e,t={}){C("client","info",e,o({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},u(t)))}logWarn(e,t={}){C("client","warn",e,o({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},u(t)))}logError(e,t={}){C("client","error",e,o({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},u(t)))}failHandshake(e,t={}){this._handshakeStatus=2,this._handshakePromise=M({type:"channelUnavailable",message:e}),this.logError(`init failed: ${e}`,t)}sendProactiveHandshakeMsg(){var t;let e={id:H("handshake-"),type:"handshake",payload:{proactive:!0}};this.logInfo("send proactive handshake",y(e)),(t=this._msgChannel)==null||t.sendMsg(e)}_initHandshake(){this._handshakeRetryTimes=0,clearTimeout(this._handshakeTimeout),this._handshakeStatus=0,this.logInfo("init handshake"),this._handshakePromise=new Promise((e,t)=>{this._handshakeResolve=e,this._handshakeReject=t,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(t),2e3)})}startHandshake(){this._initHandshake(),this._handshakePromise.then(()=>{this._handshakeStatus=1,this.logInfo("handshake success")}).catch(e=>{this._handshakeStatus=2,this.logError("handshake failed",{error:e})}),this.sendProactiveHandshakeMsg()}retryHandshake(e){this._handshakeStatus===0&&(this._handshakeRetryTimes<5?(this.logWarn("retry handshake",{retryTimes:this._handshakeRetryTimes+1}),this.sendProactiveHandshakeMsg(),this._handshakeRetryTimes++,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(e),2e3+2**this._handshakeRetryTimes)):(this.logError("handshake retry timeout",{retryTimes:this._handshakeRetryTimes}),e({type:"handshakeTimeout",message:"iframe handshake time out"})))}updateInvokeId(){this._invokeId=H(`${this._prefixId}-invoke-`)}handleChannelMessage(e){let{data:t}=e;R(t)&&this.logInfo("receive host message",y(t));let{type:r}=t;r==="callback"?this.handleHostCallback(t):r==="handshake"?this.handleHandshakeCallback(t):r==="invoke"?this.handleHostInvoke(t).catch(s=>{this.logError("handle host invoke error",o(o({},y(t)),g(s)))}):r==="event"&&this.handleHostEvent(t).catch(s=>{this.logError("handle host event error",o(o({},y(t)),g(s)))})}handleHostCallback(e){let{id:t,payload:r}=e,s={logId:t,key:r.key,callbackCode:r.code};if(r.code===1){if(this.pendingRequests.reject(t,r.res)){this.logWarn("api response received",s);return}}else if(this.pendingRequests.resolve(t,r.res)){this.logInfo("api response received",s);return}this.logWarn("host callback request not found",{id:t,key:r.key})}handleHostInvoke(e){return p(this,null,function*(){yield this._handshakePromise;let{id:t,payload:r}=e,{key:s,params:i,prefixId:a}=r;if(a!==this._prefixId){this.logWarn("ignore host invoke because prefixId mismatch",{id:t,key:s,prefixId:a,expectedPrefixId:this._prefixId});return}let h=this.eventMap.get(s);if(typeof h!="function"){this.logWarn("host invoke handler not found",{id:t,key:s}),this.sendMsg2Host({id:t,type:"callback",payload:{key:s,res:d(D(s)),code:1}});return}this.logInfo("handle host invoke",{id:t,key:s});try{let l=W(yield h(i));this.sendMsg2Host({id:t,type:"callback",payload:{key:s,res:l,code:0}}),this.logInfo("host invoke success",{id:t,key:s})}catch(l){this.logError("host invoke failed",o({id:t,key:s},g(l))),this.sendMsg2Host({id:t,type:"callback",payload:{key:s,res:d(l),code:1}})}})}handleHostEvent(e){return p(this,null,function*(){yield this._handshakePromise;let{payload:t}=e,{key:r,params:s,prefixId:i}=t;if(i!==this._prefixId){this.logWarn("ignore host event because prefixId mismatch",{key:r,prefixId:i,expectedPrefixId:this._prefixId});return}let a=this.eventHandlerMap.get(r);if(!(a!=null&&a.size)){this.logWarn("host event handler not found",{key:r});return}this.logInfo("handle host event",{key:r,handlerCount:a.size}),yield Promise.allSettled(Array.from(a,h=>h(s)))})}handleHandshakeCallback(e){var i,a;let{id:t,payload:r}=e;this._prefixId=(i=r==null?void 0:r.prefixId)!=null?i:"",this.logInfo("receive handshake callback",{id:t,prefixId:this._prefixId}),(a=this._handshakeResolve)==null||a.call(this);let s={id:t,type:"handshake",payload:{proactive:!1,info:{isHandshakeSuccess:!0}}};this.sendMsg2Host(s)}listeningHostMsg(){var e;this.logInfo("start listening host messages"),(e=this._msgChannel)==null||e.listenMsg(this.handleChannelMessage.bind(this))}sendMsg2Host(e,t){var r;R(e)&&this.logInfo("send message to host",y(e)),(r=this._msgChannel)==null||r.sendMsg(e,t)}invokeApi(e,t,r){return p(this,null,function*(){if(this._destroyed)return Promise.reject(d(b()));try{yield this._handshakePromise}catch(a){return this.logError("invoke api blocked by handshake error",o({key:e},g(a))),Promise.reject(x(a))}this._invokeId||this.updateInvokeId();let s=this._invokeId,i=this.pendingRequests.create(s,e,r==null?void 0:r.timeoutMs);return this.logInfo("api request sent",{key:e,logId:s}),this.sendMsg2Host({type:"invoke",id:s,payload:{key:e,params:t,prefixId:this._prefixId}}),this.updateInvokeId(),i})}registerApi(e,t){if(this.eventMap.has(e)){this.logWarn("register api ignored because key already exists",{key:e});return}this.eventMap.set(e,t),this.logInfo("register api",{key:e})}emitEvent(e,t){return p(this,null,function*(){try{yield this._handshakePromise}catch(r){return this.logError("emit event blocked by handshake error",o({key:e},g(r))),Promise.reject(x(r))}this.logInfo("emit event",{key:e}),this.sendMsg2Host({type:"event",id:H(`${this._prefixId}-event-`),payload:{key:e,params:t,prefixId:this._prefixId}})})}fetchBinaryList(e){return p(this,null,function*(){var t;return this.logInfo("invoke built-in binary fetch",{status:"start",itemCount:e.items.length,concurrency:A(e.concurrency),credentials:T(e.credentials)}),this.invokeApi(w,{items:e.items,concurrency:A(e.concurrency),credentials:T((t=e.credentials)!=null?t:k)})})}subscribeBinaryFetchProgress(e){return this.subscribeEvent(O,e)}cancelBinaryFetch(e){return p(this,null,function*(){this.logInfo("invoke built-in binary fetch cancel",{jobId:e,status:"cancel-requested"}),yield this.invokeApi(F,{jobId:e})})}destroy(){var t,r;if(this._destroyed)return;this._destroyed=!0,this.logInfo("destroy client"),(t=this._msgChannel)==null||t.destroy(),clearTimeout(this._handshakeTimeout);let e=d(b());(r=this._handshakeReject)==null||r.call(this,{type:"handshakeTimeout",message:e.msg}),this.pendingRequests.rejectAll(e),this.eventMap.clear(),this.eventHandlerMap.clear()}subscribeEvent(e,t){var s;let r=(s=this.eventHandlerMap.get(e))!=null?s:new Set;return r.add(t),this.eventHandlerMap.set(e,r),this.logInfo("subscribe event",{key:e,handlerCount:r.size}),()=>this.unsubscribeEvent(e,t)}unsubscribeEvent(e,t){let r=this.eventHandlerMap.get(e);if(!r){this.logWarn("unsubscribe event ignored because key is not subscribed",{key:e});return}if(!t){this.eventHandlerMap.delete(e),this.logInfo("unsubscribe all event handlers",{key:e,handlerCount:0});return}r.delete(t),r.size===0&&this.eventHandlerMap.delete(e),this.logInfo("unsubscribe event",{key:e,handlerCount:r.size})}},ge=n=>new P(n),_t=ge();export{P as Client,_t as client,ge as createClient};
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var Q=Object.defineProperty,X=Object.defineProperties;var Z=Object.getOwnPropertyDescriptors;var P=Object.getOwnPropertySymbols;var ee=Object.prototype.hasOwnProperty,te=Object.prototype.propertyIsEnumerable;var H=(r,e,t)=>e in r?Q(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,c=(r,e)=>{for(var t in e||(e={}))ee.call(e,t)&&H(r,t,e[t]);if(P)for(var t of P(e))te.call(e,t)&&H(r,t,e[t]);return r},R=(r,e)=>X(r,Z(e));var p=(r,e,t)=>new Promise((n,s)=>{var i=a=>{try{d(t.next(a))}catch(T){s(T)}},o=a=>{try{d(t.throw(a))}catch(T){s(T)}},d=a=>a.done?n(a.value):Promise.resolve(a.value).then(i,o);d((t=t.apply(r,e)).next())});import{uniqueId as j}from"lodash-es";var y="same-origin",L="__internal_fetchBinaryList__",M="__internal_cancelBinaryFetch__",w="__internal_binaryFetchProgress__";function O(r){if(r.type==="item-complete")return[r.buffer]}function S(r){return Number.isFinite(r)?Math.max(1,Math.floor(r)):4}function W(r){return r==="omit"||r==="include"?r:y}var m=(s=>(s.IFRAME_LOAD_ERROR="iframeLoadError",s.NOT_ALLOWED_URL="notAllowedUrl",s.HANDSHAKE_TIME_OUT="handshakeTimeout",s.CHANNEL_UNAVAILABLE="channelUnavailable",s))(m||{});var k=(l=>(l[l.UNKNOWN=-1]="UNKNOWN",l[l.IFRAME_LOAD_ERROR=10001]="IFRAME_LOAD_ERROR",l[l.NOT_ALLOWED_URL=10002]="NOT_ALLOWED_URL",l[l.HANDSHAKE_TIME_OUT=10003]="HANDSHAKE_TIME_OUT",l[l.API_NOT_FOUND=10004]="API_NOT_FOUND",l[l.REQUEST_TIMEOUT=10005]="REQUEST_TIMEOUT",l[l.CHANNEL_DESTROYED=10006]="CHANNEL_DESTROYED",l[l.BINARY_FETCH_DISABLED=10007]="BINARY_FETCH_DISABLED",l[l.DUPLICATED_REQUEST=10008]="DUPLICATED_REQUEST",l[l.CHANNEL_UNAVAILABLE=10009]="CHANNEL_UNAVAILABLE",l))(k||{});var u=class extends Error{constructor(t,n){super(n);this.code=t,this.name="ChannelCallbackError"}};function U(r){return new u(10004,`api "${r}" is not registered`)}function J(r){return new u(10005,`api "${r}" timed out`)}function E(){return new u(10006,"channel has been destroyed")}function K(r){return new u(10008,`request "${r}" was superseded by a new one`)}function Y(){return new u(10007,"built-in binary fetch is disabled")}var re="unknown error";function z(r){return typeof r=="object"&&r!==null}function ne(r){if(typeof r=="string"&&r)return r;if(r instanceof u&&r.message||r instanceof Error&&r.message)return r.message;if(z(r)){let{msg:e,message:t}=r;if(typeof e=="string"&&e)return e;if(typeof t=="string"&&t)return t}return re}function se(r){if(r instanceof u)return r.code;if(!z(r))return-1;let{code:e}=r;return typeof e=="string"&&e||typeof e=="number"&&Number.isFinite(e)?e:-1}function h(r){return{code:se(r),msg:ne(r)}}function D(r){return r instanceof ArrayBuffer||ArrayBuffer.isView(r)||typeof Blob!="undefined"&&r instanceof Blob}function oe(r){return D(r)||Object.values(r).some(e=>D(e))}function v(r){return r&&typeof r=="object"?oe(r)?r:JSON.parse(JSON.stringify(r)):r}var ie={["iframeLoadError"]:10001,["notAllowedUrl"]:10002,["handshakeTimeout"]:10003,["channelUnavailable"]:10009};function ae(r){return typeof r=="object"&&r!==null}function le(r){if(!ae(r))return!1;let{type:e}=r;return typeof e=="string"&&Object.values(m).includes(e)}function x(r){return le(r)?{code:ie[r.type],msg:r.message||r.type}:h(r)}function q(r){let e=Promise.reject(r);return e.catch(()=>{}),e}var C=class{constructor(e,t){this._target=e,this._options=t}sendMsg(e,t){if(!this._target)throw new Error("target window is not found");this._target.postMessage(e,this._options.targetOrigin,t!=null?t:[])}listenMsg(e){this._eventHandler=t=>{t.source===this._options.sourceWindow&&this._options.allowedOrigins.includes(t.origin)&&e(t)},typeof window!="undefined"&&window.addEventListener("message",this._eventHandler)}destroy(){typeof window!="undefined"&&this._eventHandler&&window.removeEventListener("message",this._eventHandler),this._eventHandler=void 0}};var b=class{constructor(e,t,n){e==="host"?this.channelManager=new C(t,n):e==="client"&&(this.channelManager=new C(window.parent,n))}static createInstance(e,t,n){return new b(e,t,n)}sendMsg(e,t){var n;(n=this.channelManager)==null||n.sendMsg(e,t)}listenMsg(e){var t;(t=this.channelManager)==null||t.listenMsg(e)}destroy(){var e;(e=this.channelManager)==null||e.destroy()}};var _=class{constructor(){this.requests=new Map}create(e,t,n=3e4){return this.reject(e,h(K(e))),new Promise((s,i)=>{let o=setTimeout(()=>{var d;((d=this.requests.get(e))==null?void 0:d.timeout)===o&&(this.requests.delete(e),i(h(J(t))))},n);this.requests.set(e,{reject:i,resolve:s,timeout:o})})}resolve(e,t){let n=this.take(e);return n?(n.resolve(t),!0):!1}reject(e,t){let n=this.take(e);return n?(n.reject(t),!0):!1}rejectAll(e){for(let t of this.requests.keys())this.reject(t,e)}take(e){let t=this.requests.get(e);if(t)return this.requests.delete(e),clearTimeout(t.timeout),t}};var F=r=>typeof r=="object"&&r!==null,de=new Set(["blockId","expectedPrefixId","id","jobId","prefixId","url"]),f=r=>{let e={};for(let[t,n]of Object.entries(r))if(!(t==="inputParams"||t==="outputParams")){if(de.has(t)){e[`${t}Present`]=!!n;continue}if(t==="error"){Object.assign(e,g(n));continue}if(t==="errorInfo"&&F(n)){e.errorType=typeof n.type=="string"?n.type:"object";continue}(typeof n=="string"||typeof n=="number"||typeof n=="boolean")&&(e[t]=n)}return e},I=r=>{let e={idPresent:!!r.id,type:r.type},t=F(r.payload)?r.payload:{};return typeof t.key=="string"&&(e.key=t.key),r.type==="callback"&&typeof t.code=="number"&&(e.callbackCode=t.code),r.type==="handshake"&&typeof t.proactive=="boolean"&&(e.proactive=t.proactive),e},B=r=>r.type!=="invoke"&&r.type!=="callback",g=r=>{if(!F(r))return{errorType:typeof r};let e={errorType:r instanceof Error?r.name:"object"};return(typeof r.code=="number"||typeof r.code=="string")&&(e.errorCode=r.code),e};var ue=()=>{let r=Reflect.get(globalThis,"BearWebSlardarWeb");return typeof r=="function"?r:void 0},ge=r=>{let e={};for(let[t,n]of Object.entries(f(r)))typeof n=="string"||typeof n=="number"?e[t]=n:typeof n=="boolean"&&(e[t]=String(n));return e},V=(r,e,t,n)=>{console[e](`[base-site-channel][${r}]`,t,n)},A=(r,e,t,n={})=>{if(e==="info")return;let s=f(n),i=ue();if(!i){V(r,e,t,s);return}try{i("sendLog",{content:`[base-site-channel][${r}] ${t}`,extra:c({event_name:"Runtime_SiteChannel_Message",bizType:"Runtime",subType:"SiteChannel",action:"Message",channel_side:r,channel_message:t},ge(s)),level:e})}catch(o){V(r,e,t,R(c({},s),{slardarFallback:!0,slardarErrorType:o instanceof Error?o.name:typeof o}))}};var G=`
|
|
2
2
|
(function () {
|
|
3
3
|
var DEFAULT_JOB_CONCURRENCY = ${4};
|
|
4
4
|
var DEFAULT_CREDENTIALS = '${y}';
|
|
@@ -7,9 +7,6 @@ var X=Object.defineProperty,Q=Object.defineProperties;var Z=Object.getOwnPropert
|
|
|
7
7
|
var scheduleCursor = 0;
|
|
8
8
|
var isScheduling = false;
|
|
9
9
|
|
|
10
|
-
function logInfo(message, extra) {
|
|
11
|
-
console.info('[base-site-channel][worker]', message, extra || {});
|
|
12
|
-
}
|
|
13
10
|
function logWarn(message, extra) {
|
|
14
11
|
console.warn('[base-site-channel][worker]', message, extra || {});
|
|
15
12
|
}
|
|
@@ -91,13 +88,6 @@ var X=Object.defineProperty,Q=Object.defineProperties;var Z=Object.getOwnPropert
|
|
|
91
88
|
}
|
|
92
89
|
job.finished = true;
|
|
93
90
|
jobMap.delete(job.jobId);
|
|
94
|
-
logInfo('job complete', {
|
|
95
|
-
jobId: job.jobId,
|
|
96
|
-
status: 'job-complete',
|
|
97
|
-
successCount: job.successCount,
|
|
98
|
-
failCount: job.failCount,
|
|
99
|
-
globalActiveCount: globalActiveCount,
|
|
100
|
-
});
|
|
101
91
|
postProgress({
|
|
102
92
|
type: 'job-complete',
|
|
103
93
|
jobId: job.jobId,
|
|
@@ -129,13 +119,6 @@ var X=Object.defineProperty,Q=Object.defineProperties;var Z=Object.getOwnPropert
|
|
|
129
119
|
if (job.aborted || job.finished) {
|
|
130
120
|
return { success: false, aborted: true };
|
|
131
121
|
}
|
|
132
|
-
logInfo('item complete', {
|
|
133
|
-
jobId: job.jobId,
|
|
134
|
-
itemId: item.itemId,
|
|
135
|
-
status: 'item-complete',
|
|
136
|
-
credentials: job.credentials,
|
|
137
|
-
totalBytes: buffer.byteLength,
|
|
138
|
-
});
|
|
139
122
|
postProgress(
|
|
140
123
|
{
|
|
141
124
|
type: 'item-complete',
|
|
@@ -185,16 +168,6 @@ var X=Object.defineProperty,Q=Object.defineProperties;var Z=Object.getOwnPropert
|
|
|
185
168
|
job.cursor += 1;
|
|
186
169
|
job.activeCount += 1;
|
|
187
170
|
globalActiveCount += 1;
|
|
188
|
-
logInfo('dispatch item', {
|
|
189
|
-
jobId: job.jobId,
|
|
190
|
-
itemId: item.itemId,
|
|
191
|
-
status: 'item-dispatched',
|
|
192
|
-
jobActiveCount: job.activeCount,
|
|
193
|
-
globalActiveCount: globalActiveCount,
|
|
194
|
-
jobConcurrency: job.concurrency,
|
|
195
|
-
credentials: job.credentials,
|
|
196
|
-
globalMaxConcurrency: GLOBAL_MAX_CONCURRENCY,
|
|
197
|
-
});
|
|
198
171
|
Promise.resolve(fetchItem(job, item))
|
|
199
172
|
.then(function (result) {
|
|
200
173
|
if (result.status === 'success') {
|
|
@@ -244,14 +217,6 @@ var X=Object.defineProperty,Q=Object.defineProperties;var Z=Object.getOwnPropert
|
|
|
244
217
|
controllers: new Set(),
|
|
245
218
|
};
|
|
246
219
|
jobMap.set(job.jobId, job);
|
|
247
|
-
logInfo('job start', {
|
|
248
|
-
jobId: job.jobId,
|
|
249
|
-
status: 'job-start',
|
|
250
|
-
total: job.items.length,
|
|
251
|
-
concurrency: job.concurrency,
|
|
252
|
-
credentials: job.credentials,
|
|
253
|
-
globalMaxConcurrency: GLOBAL_MAX_CONCURRENCY,
|
|
254
|
-
});
|
|
255
220
|
postProgress({
|
|
256
221
|
type: 'job-start',
|
|
257
222
|
jobId: job.jobId,
|
|
@@ -285,4 +250,4 @@ var X=Object.defineProperty,Q=Object.defineProperties;var Z=Object.getOwnPropert
|
|
|
285
250
|
if (data.type === 'cancel-job') return cancelJob(data);
|
|
286
251
|
});
|
|
287
252
|
})();
|
|
288
|
-
`;var $=(o=>(o.PENDING="pending",o.LOADING="loading",o.LOADED="loaded",o.ERROR="error",o))($||{}),Ee=n=>{let e=new Set;return n.forEach(t=>{try{e.add(new URL(t).origin)}catch(r){}}),e},N=class{constructor(e,t=()=>{},r,o=[],i,s={}){this._allowedOrigins=new Set;this.eventMap=new Map;this.eventHandlerMap=new Map;this.pendingRequests=new _;this._invokeId="";this._handshakePromise=q({type:"channelUnavailable",message:"client url is not set yet"});this._handshakeResolve=null;this._handshakeReject=null;this._handshakeRetryTimes=0;this._handshakeStatus=0;this._handshakeTimeout=null;this._binaryFetchWorker=null;this._binaryFetchWorkerUrl=null;this._binaryFetchJobMap=new Map;this._destroyed=!1;this._onLoadStatusChange=t,this._extraAttributes=i,this.createBlockContainer(e),this.blockId=r!=null?r:"",this._allowAllOrigins=o.length===0,this._allowedOrigins=Ee(o),!this._allowAllOrigins&&this._allowedOrigins.size!==o.length&&this.logWarn("invalid allowedOrigin entry ignored"),this._enableBinaryFetch=s.enableBinaryFetch===!0}logInfo(e,t={}){j("host","info",e,c({hasBlockId:!!this.blockId,handshakeStatus:this._handshakeStatus},p(t)))}logWarn(e,t={}){j("host","warn",e,c({hasBlockId:!!this.blockId,handshakeStatus:this._handshakeStatus},p(t)))}logError(e,t={}){j("host","error",e,c({hasBlockId:!!this.blockId,handshakeStatus:this._handshakeStatus},p(t)))}createBlockContainer(e){this.client=document==null?void 0:document.createElement("iframe"),this.client&&(this.client.className="base-site-iframe",this.client.style.setProperty("width","100%"),this._extraAttributes&&Object.entries(this._extraAttributes).forEach(([t,r])=>{this.client.setAttribute(t,r)}),this.client.style.setProperty("height","100%"),this.client.addEventListener("error",t=>{var r;this.rejectHandshake({type:"iframeLoadError",message:(r=t.message)!=null?r:JSON.stringify(t)})}),e.appendChild(this.client))}isOriginAllowed(e){return this._allowAllOrigins?!0:this._allowedOrigins.has(e)}initHandshake(){this._handshakeRetryTimes=0,this._handshakeStatus=0,this.logInfo("init handshake");let e=new Promise((t,r)=>{this._handshakeResolve=t,this._handshakeReject=r});e.then(()=>{this._handshakeStatus=1,this.logInfo("handshake success"),this._onLoadStatusChange("loaded")}).catch(t=>{this._handshakeStatus=2,this._onLoadStatusChange("error",t),this.logError("handshake failed",{errorInfo:t})}),this._handshakePromise=e}rejectHandshake(e){var t;this._handshakeStatus===0&&(this.logWarn("reject handshake",{errorInfo:e}),(t=this._handshakeReject)==null||t.call(this,e))}updateInvokeId(){this._invokeId=A(`${this.blockId}-invoke-`)}setClientUrl(e){if(!this.client||!e)return;clearTimeout(this._handshakeTimeout),this.initHandshake(),this._onLoadStatusChange("loading"),this._msgChannel&&(this.logInfo("destroy previous message channel"),this._msgChannel.destroy(),this.pendingRequests.rejectAll(h(E())));let t=new URL(e).origin;this.logInfo("set client url",{origin:t}),this.isOriginAllowed(t)?(this._msgChannel=f.createInstance("host",this.clientWin,{allowedOrigins:[t],sourceWindow:this.clientWin,targetOrigin:t}),this.client.src=e,this.listeningClientMessage()):(this.client.src=e,this.logWarn("client url origin not allowed",{origin:t}),this.rejectHandshake({type:"notAllowedUrl"}))}get clientWin(){var e;return(e=this.client)==null?void 0:e.contentWindow}listeningClientMessage(){this.clientMessageHandler=e=>{let{data:t}=e;B(t)&&this.logInfo("receive client message",I(t)),t.type==="invoke"?this.handleClientInvoke(t).catch(r=>{this.logError("handle client invoke error",c(c({},I(t)),g(r)))}):t.type==="callback"?this.handleClientCallback(t):t.type==="handshake"?this.handleHandshakeMsg(t):t.type==="event"&&this.handleClientEvent(t).catch(r=>{this.logError("handle client event error",c(c({},I(t)),g(r)))})},this._msgChannel.listenMsg(this.clientMessageHandler)}handleClientInvoke(e){return b(this,null,function*(){yield this._handshakePromise;let{id:t,payload:r}=e,{key:o,params:i,prefixId:s}=r;if(s!==this.blockId){this.logWarn("ignore client invoke because prefixId mismatch",{id:t,key:o,prefixId:s,expectedPrefixId:this.blockId});return}if(this.logInfo("api request received",{logId:t,key:o}),!this._enableBinaryFetch&&(o===L||o===M)){this.logWarn("built-in binary fetch invoke rejected because capability is disabled",{id:t,key:o}),this.sendClientInvokeResponse(t,o,h(Y()),1);return}if(o===L){this.logInfo("handle built-in binary fetch invoke",{id:t,key:o,status:"start"});try{let a=v(yield this.startBinaryFetchJob(i,s));this.sendClientInvokeResponse(t,o,a,0)}catch(a){this.logError("built-in binary fetch invoke failed",c({id:t,key:o},g(a))),this.sendClientInvokeResponse(t,o,h(a),1)}return}if(o===M){this.logInfo("handle built-in binary fetch cancel invoke",{id:t,key:o,status:"cancel-requested"});try{let a=v(yield this.cancelBinaryFetchJob(i,s));this.sendClientInvokeResponse(t,o,a,0)}catch(a){this.logError("built-in binary fetch cancel invoke failed",c({id:t,key:o},g(a))),this.sendClientInvokeResponse(t,o,h(a),1)}return}let d=this.eventMap.get(o);if(typeof d=="function")try{let a=v(yield d(i));this.sendClientInvokeResponse(t,o,a,0)}catch(a){this.logError("client invoke failed",c({id:t,key:o},g(a))),this.sendClientInvokeResponse(t,o,h(a),1)}else this.logWarn("client invoke handler not found",{id:t,key:o}),this.sendClientInvokeResponse(t,o,h(U(o)),1)})}handleClientCallback(e){let{id:t,payload:r}=e;if(r.code===1){if(this.pendingRequests.reject(t,r.res)){this.logWarn("client callback returned error",{id:t,key:r.key});return}}else if(this.pendingRequests.resolve(t,r.res)){this.logInfo("client callback success",{id:t,key:r.key});return}this.logWarn("client callback request not found",{id:t,key:r.key})}handleClientEvent(e){return b(this,null,function*(){yield this._handshakePromise;let{payload:t}=e,{key:r,params:o,prefixId:i}=t;if(i!==this.blockId){this.logWarn("ignore client event because prefixId mismatch",{key:r,prefixId:i,expectedPrefixId:this.blockId});return}let s=this.eventHandlerMap.get(r);if(!(s!=null&&s.size)){this.logWarn("client event handler not found",{key:r});return}this.logInfo("handle client event",{key:r,handlerCount:s.size}),yield Promise.allSettled(Array.from(s,d=>d(o)))})}sendCallbackHandshake(e){this.sendMsg2Client({id:e,type:"handshake",payload:{proactive:!1,prefixId:this.blockId}})}handleHandshakeMsg(e){return b(this,null,function*(){var t;e.payload.proactive?(clearTimeout(this._handshakeTimeout),this._handshakeRetryTimes=0,this.logInfo("receive proactive handshake",{id:e.id}),this.sendCallbackHandshake(e.id),this.retrySendHandshakeCallback(e.id)):(this.logInfo("receive handshake callback",{id:e.id}),(t=this._handshakeResolve)==null||t.call(this))})}retrySendHandshakeCallback(e){this._handshakeTimeout=setTimeout(()=>{if(this._handshakeStatus===0){if(this._handshakeRetryTimes>5){this.logError("handshake callback retry timeout",{handshakeId:e,retryTimes:this._handshakeRetryTimes}),this.rejectHandshake({type:"handshakeTimeout"});return}this.logWarn("retry handshake callback",{handshakeId:e,retryTimes:this._handshakeRetryTimes+1}),this.sendCallbackHandshake(e),this._handshakeRetryTimes++,this.retrySendHandshakeCallback(e)}},2e3*2**this._handshakeRetryTimes)}sendMsg2Client(e,t){B(e)&&this.logInfo("send message to client",I(e)),this._msgChannel.sendMsg(e,t)}sendClientInvokeResponse(e,t,r,o){let i={logId:e,key:t,callbackCode:o};o===1?this.logWarn("api response sent",i):this.logInfo("api response sent",i),this.sendMsg2Client({id:e,type:"callback",payload:{res:r,key:t,code:o}})}getBinaryFetchWorker(){if(this._binaryFetchWorker)return this._binaryFetchWorker;if(typeof Worker=="undefined")throw new Error("Worker is not supported in current environment");let e=new Blob([G],{type:"text/javascript"}),t=URL.createObjectURL(e),r=new Worker(t);return this._binaryFetchWorkerUrl=t,r.addEventListener("message",o=>{this.handleBinaryFetchWorkerMessage(o.data)}),r.addEventListener("error",o=>{this.logError("binary fetch worker runtime error",{status:"worker-error",error:o.message})}),this._binaryFetchWorker=r,this.logInfo("binary fetch worker created",{status:"worker-created"}),r}startBinaryFetchJob(e,t){return b(this,null,function*(){var s;let r=Array.isArray(e==null?void 0:e.items)?e.items:[],o=A(`${this.blockId}-binary-fetch-`);this._binaryFetchJobMap.set(o,{jobId:o,prefixId:t});let i={type:"start-job",jobId:o,items:r,concurrency:S(e==null?void 0:e.concurrency),credentials:W((s=e==null?void 0:e.credentials)!=null?s:y)};return this.getBinaryFetchWorker().postMessage(i),this.logInfo("binary fetch job dispatched to worker",{jobId:o,status:"job-dispatched",itemCount:r.length,concurrency:i.concurrency,credentials:i.credentials}),{jobId:o}})}cancelBinaryFetchJob(e,t){return b(this,null,function*(){let r=this._binaryFetchJobMap.get(e.jobId);if(!r){this.logWarn("binary fetch job not found when cancel",{jobId:e.jobId,status:"job-missing"});return}if(r.prefixId!==t){this.logWarn("ignore binary fetch cancel because prefixId mismatch",{jobId:e.jobId,prefixId:t,expectedPrefixId:r.prefixId});return}this.getBinaryFetchWorker().postMessage({type:"cancel-job",jobId:e.jobId}),this.logInfo("binary fetch cancel sent to worker",{jobId:e.jobId,status:"cancel-sent"})})}handleBinaryFetchWorkerMessage(e){let t=this._binaryFetchJobMap.get(e.jobId);if(!t){this.logWarn("ignore worker progress because job not found",{jobId:e.jobId,status:e.type});return}this.logInfo("receive binary fetch worker progress",{jobId:e.jobId,itemId:"itemId"in e?e.itemId:void 0,status:e.type});let r=O(e);this.sendMsg2Client({type:"event",id:A(`${this.blockId}-binary-fetch-event-`),payload:{key:w,params:e,prefixId:t.prefixId}},r),(e.type==="job-complete"||e.type==="job-cancelled")&&this._binaryFetchJobMap.delete(e.jobId)}registerApi(e,t){if(this.eventMap.has(e)){this.logWarn("register api ignored because key already exists",{key:e});return}this.eventMap.set(e,t),this.logInfo("register api",{key:e})}invokeApi(e,t,r){return b(this,null,function*(){if(this._destroyed)return Promise.reject(h(E()));try{yield this._handshakePromise}catch(s){return this.logError("invoke api blocked by handshake error",c({key:e},g(s))),Promise.reject(x(s))}this._invokeId||this.updateInvokeId();let o=this._invokeId,i=this.pendingRequests.create(o,e,r==null?void 0:r.timeoutMs);return this.logInfo("invoke api",{key:e,id:o}),this.sendMsg2Client({type:"invoke",id:o,payload:{key:e,params:t,prefixId:this.blockId}}),this.updateInvokeId(),i})}emitEvent(e,t){return b(this,null,function*(){try{yield this._handshakePromise}catch(r){return this.logError("emit event blocked by handshake error",c({key:e},g(r))),Promise.reject(x(r))}this.logInfo("emit event",{key:e}),this.sendMsg2Client({type:"event",id:A(`${this.blockId}-event-`),payload:{key:e,params:t,prefixId:this.blockId}})})}subscribeEvent(e,t){var o;let r=(o=this.eventHandlerMap.get(e))!=null?o:new Set;return r.add(t),this.eventHandlerMap.set(e,r),this.logInfo("subscribe event",{key:e,handlerCount:r.size}),()=>this.unsubscribeEvent(e,t)}unsubscribeEvent(e,t){let r=this.eventHandlerMap.get(e);if(!r){this.logWarn("unsubscribe event ignored because key is not subscribed",{key:e});return}if(!t){this.eventHandlerMap.delete(e),this.logInfo("unsubscribe all event handlers",{key:e,handlerCount:0});return}r.delete(t),r.size===0&&this.eventHandlerMap.delete(e),this.logInfo("unsubscribe event",{key:e,handlerCount:r.size})}destroy(){var e,t,r,o;this._destroyed||(this._destroyed=!0,this.logInfo("destroy host"),(e=this._msgChannel)==null||e.destroy(),clearTimeout(this._handshakeTimeout),(t=this._handshakeReject)==null||t.call(this,{type:"handshakeTimeout",message:E().message}),(r=this._binaryFetchWorker)==null||r.terminate(),this._binaryFetchWorker=null,this._binaryFetchWorkerUrl&&(URL.revokeObjectURL(this._binaryFetchWorkerUrl),this._binaryFetchWorkerUrl=null),this._binaryFetchJobMap.clear(),this.pendingRequests.rejectAll(h(E())),this.eventMap.clear(),this.eventHandlerMap.clear(),(o=this.client)==null||o.remove())}};export{u as ChannelCallbackError,k as ChannelErrorCode,m as ChannelErrorType,N as Host,$ as LoadStatus};
|
|
253
|
+
`;var $=(s=>(s.PENDING="pending",s.LOADING="loading",s.LOADED="loaded",s.ERROR="error",s))($||{}),Ee=r=>{let e=new Set;return r.forEach(t=>{try{e.add(new URL(t).origin)}catch(n){}}),e},N=class{constructor(e,t=()=>{},n,s=[],i,o={}){this._allowedOrigins=new Set;this.eventMap=new Map;this.eventHandlerMap=new Map;this.pendingRequests=new _;this._invokeId="";this._handshakePromise=q({type:"channelUnavailable",message:"client url is not set yet"});this._handshakeResolve=null;this._handshakeReject=null;this._handshakeRetryTimes=0;this._handshakeStatus=0;this._handshakeTimeout=null;this._binaryFetchWorker=null;this._binaryFetchWorkerUrl=null;this._binaryFetchJobMap=new Map;this._destroyed=!1;this._onLoadStatusChange=t,this._extraAttributes=i,this.createBlockContainer(e),this.blockId=n!=null?n:"",this._allowAllOrigins=s.length===0,this._allowedOrigins=Ee(s),!this._allowAllOrigins&&this._allowedOrigins.size!==s.length&&this.logWarn("invalid allowedOrigin entry ignored"),this._enableBinaryFetch=o.enableBinaryFetch===!0}logInfo(e,t={}){A("host","info",e,c({hasBlockId:!!this.blockId,handshakeStatus:this._handshakeStatus},f(t)))}logWarn(e,t={}){A("host","warn",e,c({hasBlockId:!!this.blockId,handshakeStatus:this._handshakeStatus},f(t)))}logError(e,t={}){A("host","error",e,c({hasBlockId:!!this.blockId,handshakeStatus:this._handshakeStatus},f(t)))}createBlockContainer(e){this.client=document==null?void 0:document.createElement("iframe"),this.client&&(this.client.className="base-site-iframe",this.client.style.setProperty("width","100%"),this._extraAttributes&&Object.entries(this._extraAttributes).forEach(([t,n])=>{this.client.setAttribute(t,n)}),this.client.style.setProperty("height","100%"),this.client.addEventListener("error",t=>{var n;this.rejectHandshake({type:"iframeLoadError",message:(n=t.message)!=null?n:JSON.stringify(t)})}),e.appendChild(this.client))}isOriginAllowed(e){return this._allowAllOrigins?!0:this._allowedOrigins.has(e)}initHandshake(){this._handshakeRetryTimes=0,this._handshakeStatus=0,this.logInfo("init handshake");let e=new Promise((t,n)=>{this._handshakeResolve=t,this._handshakeReject=n});e.then(()=>{this._handshakeStatus=1,this.logInfo("handshake success"),this._onLoadStatusChange("loaded")}).catch(t=>{this._handshakeStatus=2,this._onLoadStatusChange("error",t),this.logError("handshake failed",{errorInfo:t})}),this._handshakePromise=e}rejectHandshake(e){var t;this._handshakeStatus===0&&(this.logWarn("reject handshake",{errorInfo:e}),(t=this._handshakeReject)==null||t.call(this,e))}updateInvokeId(){this._invokeId=j(`${this.blockId}-invoke-`)}setClientUrl(e){if(!this.client||!e)return;clearTimeout(this._handshakeTimeout),this.initHandshake(),this._onLoadStatusChange("loading"),this._msgChannel&&(this.logInfo("destroy previous message channel"),this._msgChannel.destroy(),this.pendingRequests.rejectAll(h(E())));let t=new URL(e).origin;this.logInfo("set client url",{origin:t}),this.isOriginAllowed(t)?(this._msgChannel=b.createInstance("host",this.clientWin,{allowedOrigins:[t],sourceWindow:this.clientWin,targetOrigin:t}),this.client.src=e,this.listeningClientMessage()):(this.client.src=e,this.logWarn("client url origin not allowed",{origin:t}),this.rejectHandshake({type:"notAllowedUrl"}))}get clientWin(){var e;return(e=this.client)==null?void 0:e.contentWindow}listeningClientMessage(){this.clientMessageHandler=e=>{let{data:t}=e;B(t)&&this.logInfo("receive client message",I(t)),t.type==="invoke"?this.handleClientInvoke(t).catch(n=>{this.logError("handle client invoke error",c(c({},I(t)),g(n)))}):t.type==="callback"?this.handleClientCallback(t):t.type==="handshake"?this.handleHandshakeMsg(t):t.type==="event"&&this.handleClientEvent(t).catch(n=>{this.logError("handle client event error",c(c({},I(t)),g(n)))})},this._msgChannel.listenMsg(this.clientMessageHandler)}handleClientInvoke(e){return p(this,null,function*(){yield this._handshakePromise;let{id:t,payload:n}=e,{key:s,params:i,prefixId:o}=n;if(o!==this.blockId){this.logWarn("ignore client invoke because prefixId mismatch",{id:t,key:s,prefixId:o,expectedPrefixId:this.blockId});return}if(this.logInfo("api request received",{logId:t,key:s}),!this._enableBinaryFetch&&(s===L||s===M)){this.logWarn("built-in binary fetch invoke rejected because capability is disabled",{id:t,key:s}),this.sendClientInvokeResponse(t,s,h(Y()),1);return}if(s===L){this.logInfo("handle built-in binary fetch invoke",{id:t,key:s,status:"start"});try{let a=v(yield this.startBinaryFetchJob(i,o));this.sendClientInvokeResponse(t,s,a,0)}catch(a){this.logError("built-in binary fetch invoke failed",c({id:t,key:s},g(a))),this.sendClientInvokeResponse(t,s,h(a),1)}return}if(s===M){this.logInfo("handle built-in binary fetch cancel invoke",{id:t,key:s,status:"cancel-requested"});try{let a=v(yield this.cancelBinaryFetchJob(i,o));this.sendClientInvokeResponse(t,s,a,0)}catch(a){this.logError("built-in binary fetch cancel invoke failed",c({id:t,key:s},g(a))),this.sendClientInvokeResponse(t,s,h(a),1)}return}let d=this.eventMap.get(s);if(typeof d=="function")try{let a=v(yield d(i));this.sendClientInvokeResponse(t,s,a,0)}catch(a){this.logError("client invoke failed",c({id:t,key:s},g(a))),this.sendClientInvokeResponse(t,s,h(a),1)}else this.logWarn("client invoke handler not found",{id:t,key:s}),this.sendClientInvokeResponse(t,s,h(U(s)),1)})}handleClientCallback(e){let{id:t,payload:n}=e;if(n.code===1){if(this.pendingRequests.reject(t,n.res)){this.logWarn("client callback returned error",{id:t,key:n.key});return}}else if(this.pendingRequests.resolve(t,n.res)){this.logInfo("client callback success",{id:t,key:n.key});return}this.logWarn("client callback request not found",{id:t,key:n.key})}handleClientEvent(e){return p(this,null,function*(){yield this._handshakePromise;let{payload:t}=e,{key:n,params:s,prefixId:i}=t;if(i!==this.blockId){this.logWarn("ignore client event because prefixId mismatch",{key:n,prefixId:i,expectedPrefixId:this.blockId});return}let o=this.eventHandlerMap.get(n);if(!(o!=null&&o.size)){this.logWarn("client event handler not found",{key:n});return}this.logInfo("handle client event",{key:n,handlerCount:o.size}),yield Promise.allSettled(Array.from(o,d=>d(s)))})}sendCallbackHandshake(e){this.sendMsg2Client({id:e,type:"handshake",payload:{proactive:!1,prefixId:this.blockId}})}handleHandshakeMsg(e){return p(this,null,function*(){var t;e.payload.proactive?(clearTimeout(this._handshakeTimeout),this._handshakeRetryTimes=0,this.logInfo("receive proactive handshake",{id:e.id}),this.sendCallbackHandshake(e.id),this.retrySendHandshakeCallback(e.id)):(this.logInfo("receive handshake callback",{id:e.id}),(t=this._handshakeResolve)==null||t.call(this))})}retrySendHandshakeCallback(e){this._handshakeTimeout=setTimeout(()=>{if(this._handshakeStatus===0){if(this._handshakeRetryTimes>5){this.logError("handshake callback retry timeout",{handshakeId:e,retryTimes:this._handshakeRetryTimes}),this.rejectHandshake({type:"handshakeTimeout"});return}this.logWarn("retry handshake callback",{handshakeId:e,retryTimes:this._handshakeRetryTimes+1}),this.sendCallbackHandshake(e),this._handshakeRetryTimes++,this.retrySendHandshakeCallback(e)}},2e3*2**this._handshakeRetryTimes)}sendMsg2Client(e,t){B(e)&&this.logInfo("send message to client",I(e)),this._msgChannel.sendMsg(e,t)}sendClientInvokeResponse(e,t,n,s){let i={logId:e,key:t,callbackCode:s};s===1?this.logWarn("api response sent",i):this.logInfo("api response sent",i),this.sendMsg2Client({id:e,type:"callback",payload:{res:n,key:t,code:s}})}getBinaryFetchWorker(){if(this._binaryFetchWorker)return this._binaryFetchWorker;if(typeof Worker=="undefined")throw new Error("Worker is not supported in current environment");let e=new Blob([G],{type:"text/javascript"}),t=URL.createObjectURL(e),n=new Worker(t);return this._binaryFetchWorkerUrl=t,n.addEventListener("message",s=>{this.handleBinaryFetchWorkerMessage(s.data)}),n.addEventListener("error",s=>{this.logError("binary fetch worker runtime error",{status:"worker-error",error:s.message})}),this._binaryFetchWorker=n,this.logInfo("binary fetch worker created",{status:"worker-created"}),n}startBinaryFetchJob(e,t){return p(this,null,function*(){var o;let n=Array.isArray(e==null?void 0:e.items)?e.items:[],s=j(`${this.blockId}-binary-fetch-`);this._binaryFetchJobMap.set(s,{jobId:s,prefixId:t});let i={type:"start-job",jobId:s,items:n,concurrency:S(e==null?void 0:e.concurrency),credentials:W((o=e==null?void 0:e.credentials)!=null?o:y)};return this.getBinaryFetchWorker().postMessage(i),this.logInfo("binary fetch job dispatched to worker",{jobId:s,status:"job-dispatched",itemCount:n.length,concurrency:i.concurrency,credentials:i.credentials}),{jobId:s}})}cancelBinaryFetchJob(e,t){return p(this,null,function*(){let n=this._binaryFetchJobMap.get(e.jobId);if(!n){this.logWarn("binary fetch job not found when cancel",{jobId:e.jobId,status:"job-missing"});return}if(n.prefixId!==t){this.logWarn("ignore binary fetch cancel because prefixId mismatch",{jobId:e.jobId,prefixId:t,expectedPrefixId:n.prefixId});return}this.getBinaryFetchWorker().postMessage({type:"cancel-job",jobId:e.jobId}),this.logInfo("binary fetch cancel sent to worker",{jobId:e.jobId,status:"cancel-sent"})})}handleBinaryFetchWorkerMessage(e){let t=this._binaryFetchJobMap.get(e.jobId);if(!t){this.logWarn("ignore worker progress because job not found",{jobId:e.jobId,status:e.type});return}this.logInfo("receive binary fetch worker progress",{jobId:e.jobId,itemId:"itemId"in e?e.itemId:void 0,status:e.type});let n=O(e);this.sendMsg2Client({type:"event",id:j(`${this.blockId}-binary-fetch-event-`),payload:{key:w,params:e,prefixId:t.prefixId}},n),(e.type==="job-complete"||e.type==="job-cancelled")&&this._binaryFetchJobMap.delete(e.jobId)}registerApi(e,t){if(this.eventMap.has(e)){this.logWarn("register api ignored because key already exists",{key:e});return}this.eventMap.set(e,t),this.logInfo("register api",{key:e})}invokeApi(e,t,n){return p(this,null,function*(){if(this._destroyed)return Promise.reject(h(E()));try{yield this._handshakePromise}catch(o){return this.logError("invoke api blocked by handshake error",c({key:e},g(o))),Promise.reject(x(o))}this._invokeId||this.updateInvokeId();let s=this._invokeId,i=this.pendingRequests.create(s,e,n==null?void 0:n.timeoutMs);return this.logInfo("invoke api",{key:e,id:s}),this.sendMsg2Client({type:"invoke",id:s,payload:{key:e,params:t,prefixId:this.blockId}}),this.updateInvokeId(),i})}emitEvent(e,t){return p(this,null,function*(){try{yield this._handshakePromise}catch(n){return this.logError("emit event blocked by handshake error",c({key:e},g(n))),Promise.reject(x(n))}this.logInfo("emit event",{key:e}),this.sendMsg2Client({type:"event",id:j(`${this.blockId}-event-`),payload:{key:e,params:t,prefixId:this.blockId}})})}subscribeEvent(e,t){var s;let n=(s=this.eventHandlerMap.get(e))!=null?s:new Set;return n.add(t),this.eventHandlerMap.set(e,n),this.logInfo("subscribe event",{key:e,handlerCount:n.size}),()=>this.unsubscribeEvent(e,t)}unsubscribeEvent(e,t){let n=this.eventHandlerMap.get(e);if(!n){this.logWarn("unsubscribe event ignored because key is not subscribed",{key:e});return}if(!t){this.eventHandlerMap.delete(e),this.logInfo("unsubscribe all event handlers",{key:e,handlerCount:0});return}n.delete(t),n.size===0&&this.eventHandlerMap.delete(e),this.logInfo("unsubscribe event",{key:e,handlerCount:n.size})}destroy(){var e,t,n,s;this._destroyed||(this._destroyed=!0,this.logInfo("destroy host"),(e=this._msgChannel)==null||e.destroy(),clearTimeout(this._handshakeTimeout),(t=this._handshakeReject)==null||t.call(this,{type:"handshakeTimeout",message:E().message}),(n=this._binaryFetchWorker)==null||n.terminate(),this._binaryFetchWorker=null,this._binaryFetchWorkerUrl&&(URL.revokeObjectURL(this._binaryFetchWorkerUrl),this._binaryFetchWorkerUrl=null),this._binaryFetchJobMap.clear(),this.pendingRequests.rejectAll(h(E())),this.eventMap.clear(),this.eventHandlerMap.clear(),(s=this.client)==null||s.remove())}};export{u as ChannelCallbackError,k as ChannelErrorCode,m as ChannelErrorType,N as Host,$ as LoadStatus};
|
package/dist/runtime.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var ct=Object.defineProperty,dt=Object.defineProperties;var ut=Object.getOwnPropertyDescriptors;var N=Object.getOwnPropertySymbols;var ve=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var Ae=(t,e,n)=>e in t?ct(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,a=(t,e)=>{for(var n in e||(e={}))ve.call(e,n)&&Ae(t,n,e[n]);if(N)for(var n of N(e))be.call(e,n)&&Ae(t,n,e[n]);return t},f=(t,e)=>dt(t,ut(e));var Te=(t,e)=>{var n={};for(var r in t)ve.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(t!=null&&N)for(var r of N(t))e.indexOf(r)<0&&be.call(t,r)&&(n[r]=t[r]);return n};var p=(t,e,n)=>new Promise((r,i)=>{var o=c=>{try{d(n.next(c))}catch(m){i(m)}},s=c=>{try{d(n.throw(c))}catch(m){i(m)}},d=c=>c.done?r(c.value):Promise.resolve(c.value).then(o,s);d((n=n.apply(t,e)).next())});import{uniqueId as ee}from"lodash-es";var W="same-origin",Ce="__internal_fetchBinaryList__",ke="__internal_cancelBinaryFetch__",Re="__internal_binaryFetchProgress__";function $(t){return Number.isFinite(t)?Math.max(1,Math.floor(t)):4}function Y(t){return t==="omit"||t==="include"?t:W}var L=(i=>(i.IFRAME_LOAD_ERROR="iframeLoadError",i.NOT_ALLOWED_URL="notAllowedUrl",i.HANDSHAKE_TIME_OUT="handshakeTimeout",i.CHANNEL_UNAVAILABLE="channelUnavailable",i))(L||{});var b=class extends Error{constructor(n,r){super(r);this.code=n,this.name="ChannelCallbackError"}};function Me(t){return new b(10004,`api "${t}" is not registered`)}function Pe(t){return new b(10005,`api "${t}" timed out`)}function G(){return new b(10006,"channel has been destroyed")}function Fe(t){return new b(10008,`request "${t}" was superseded by a new one`)}var lt="unknown error";function we(t){return typeof t=="object"&&t!==null}function pt(t){if(typeof t=="string"&&t)return t;if(t instanceof b&&t.message||t instanceof Error&&t.message)return t.message;if(we(t)){let{msg:e,message:n}=t;if(typeof e=="string"&&e)return e;if(typeof n=="string"&&n)return n}return lt}function ht(t){if(t instanceof b)return t.code;if(!we(t))return-1;let{code:e}=t;return typeof e=="string"&&e||typeof e=="number"&&Number.isFinite(e)?e:-1}function A(t){return{code:ht(t),msg:pt(t)}}function xe(t){return t instanceof ArrayBuffer||ArrayBuffer.isView(t)||typeof Blob!="undefined"&&t instanceof Blob}function mt(t){return xe(t)||Object.values(t).some(e=>xe(e))}function He(t){return t&&typeof t=="object"?mt(t)?t:JSON.parse(JSON.stringify(t)):t}var ft={["iframeLoadError"]:10001,["notAllowedUrl"]:10002,["handshakeTimeout"]:10003,["channelUnavailable"]:10009};function gt(t){return typeof t=="object"&&t!==null}function It(t){if(!gt(t))return!1;let{type:e}=t;return typeof e=="string"&&Object.values(L).includes(e)}function J(t){return It(t)?{code:ft[t.type],msg:t.message||t.type}:A(t)}function X(t){let e=Promise.reject(t);return e.catch(()=>{}),e}var F=class{constructor(e,n){this._target=e,this._options=n}sendMsg(e,n){if(!this._target)throw new Error("target window is not found");this._target.postMessage(e,this._options.targetOrigin,n!=null?n:[])}listenMsg(e){this._eventHandler=n=>{n.source===this._options.sourceWindow&&this._options.allowedOrigins.includes(n.origin)&&e(n)},typeof window!="undefined"&&window.addEventListener("message",this._eventHandler)}destroy(){typeof window!="undefined"&&this._eventHandler&&window.removeEventListener("message",this._eventHandler),this._eventHandler=void 0}};var _=class{constructor(e,n,r){e==="host"?this.channelManager=new F(n,r):e==="client"&&(this.channelManager=new F(window.parent,r))}static createInstance(e,n,r){return new _(e,n,r)}sendMsg(e,n){var r;(r=this.channelManager)==null||r.sendMsg(e,n)}listenMsg(e){var n;(n=this.channelManager)==null||n.listenMsg(e)}destroy(){var e;(e=this.channelManager)==null||e.destroy()}};var O=class{constructor(){this.requests=new Map}create(e,n,r=3e4){return this.reject(e,A(Fe(e))),new Promise((i,o)=>{let s=setTimeout(()=>{var d;((d=this.requests.get(e))==null?void 0:d.timeout)===s&&(this.requests.delete(e),o(A(Pe(n))))},r);this.requests.set(e,{reject:o,resolve:i,timeout:s})})}resolve(e,n){let r=this.take(e);return r?(r.resolve(n),!0):!1}reject(e,n){let r=this.take(e);return r?(r.reject(n),!0):!1}rejectAll(e){for(let n of this.requests.keys())this.reject(n,e)}take(e){let n=this.requests.get(e);if(n)return this.requests.delete(e),clearTimeout(n.timeout),n}};var Q=t=>typeof t=="object"&&t!==null,Et=new Set(["blockId","expectedPrefixId","id","jobId","prefixId","url"]),C=t=>{let e={};for(let[n,r]of Object.entries(t))if(!(n==="inputParams"||n==="outputParams")){if(Et.has(n)){e[`${n}Present`]=!!r;continue}if(n==="error"){Object.assign(e,k(r));continue}if(n==="errorInfo"&&Q(r)){e.errorType=typeof r.type=="string"?r.type:"object";continue}(typeof r=="string"||typeof r=="number"||typeof r=="boolean")&&(e[n]=r)}return e},M=t=>{let e={idPresent:!!t.id,type:t.type},n=Q(t.payload)?t.payload:{};return typeof n.key=="string"&&(e.key=n.key),t.type==="callback"&&typeof n.code=="number"&&(e.callbackCode=n.code),t.type==="handshake"&&typeof n.proactive=="boolean"&&(e.proactive=n.proactive),e},Z=t=>t.type!=="invoke"&&t.type!=="callback",k=t=>{if(!Q(t))return{errorType:typeof t};let e={errorType:t instanceof Error?t.name:"object"};return(typeof t.code=="number"||typeof t.code=="string")&&(e.errorCode=t.code),e};var At=()=>{let t=Reflect.get(globalThis,"BearWebSlardarWeb");return typeof t=="function"?t:void 0},vt=t=>{let e={};for(let[n,r]of Object.entries(C(t)))typeof r=="string"||typeof r=="number"?e[n]=r:typeof r=="boolean"&&(e[n]=String(r));return e},Ne=(t,e,n,r)=>{console[e](`[base-site-channel][${t}]`,n,r)},U=(t,e,n,r={})=>{let i=C(r),o=At();if(!o){Ne(t,e,n,i);return}try{o("sendLog",{content:`[base-site-channel][${t}] ${n}`,extra:a({event_name:"Runtime_SiteChannel_Message",bizType:"Runtime",subType:"SiteChannel",action:"Message",channel_side:t,channel_message:n},vt(i)),level:e})}catch(s){Ne(t,e,n,f(a({},i),{slardarFallback:!0,slardarErrorType:s instanceof Error?s.name:typeof s}))}};var Ct=()=>{var n;if(typeof window=="undefined")return null;let e=((n=window.location.ancestorOrigins)==null?void 0:n[0])||document.referrer;if(!e)return null;try{return new URL(e).origin}catch(r){return null}},kt=t=>{try{return new URL(t).origin}catch(e){return null}},te=class{constructor(e={}){this.pendingRequests=new O;this.eventMap=new Map;this.eventHandlerMap=new Map;this._msgChannel=null;this._invokeId="";this._handshakePromise=X({type:"channelUnavailable",message:"channel handshake is not initialized"});this._handshakeResolve=null;this._handshakeReject=null;this._handshakeRetryTimes=0;this._handshakeStatus=0;this._handshakeTimeout=null;this._prefixId="";this._destroyed=!1;let n=e.hostOrigin?kt(e.hostOrigin):null;if(this.hostOrigin=n!=null?n:Ct(),e.hostOrigin&&!n&&this.logWarn("invalid hostOrigin, fallback to parent origin"),typeof window=="undefined"||window.parent===window){this.failHandshake("invalid window context",{hasWindow:typeof window!="undefined",isTopWindow:typeof window!="undefined"?window.parent===window:!0});return}if(!this.hostOrigin){this.failHandshake("host origin unavailable");return}this._msgChannel=_.createInstance("client",window.parent,{allowedOrigins:[this.hostOrigin],sourceWindow:window.parent,targetOrigin:this.hostOrigin}),this.listeningHostMsg(),this.startHandshake()}logInfo(e,n={}){U("client","info",e,a({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},C(n)))}logWarn(e,n={}){U("client","warn",e,a({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},C(n)))}logError(e,n={}){U("client","error",e,a({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},C(n)))}failHandshake(e,n={}){this._handshakeStatus=2,this._handshakePromise=X({type:"channelUnavailable",message:e}),this.logError(`init failed: ${e}`,n)}sendProactiveHandshakeMsg(){var n;let e={id:ee("handshake-"),type:"handshake",payload:{proactive:!0}};this.logInfo("send proactive handshake",M(e)),(n=this._msgChannel)==null||n.sendMsg(e)}_initHandshake(){this._handshakeRetryTimes=0,clearTimeout(this._handshakeTimeout),this._handshakeStatus=0,this.logInfo("init handshake"),this._handshakePromise=new Promise((e,n)=>{this._handshakeResolve=e,this._handshakeReject=n,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(n),2e3)})}startHandshake(){this._initHandshake(),this._handshakePromise.then(()=>{this._handshakeStatus=1,this.logInfo("handshake success")}).catch(e=>{this._handshakeStatus=2,this.logError("handshake failed",{error:e})}),this.sendProactiveHandshakeMsg()}retryHandshake(e){this._handshakeStatus===0&&(this._handshakeRetryTimes<5?(this.logWarn("retry handshake",{retryTimes:this._handshakeRetryTimes+1}),this.sendProactiveHandshakeMsg(),this._handshakeRetryTimes++,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(e),2e3+2**this._handshakeRetryTimes)):(this.logError("handshake retry timeout",{retryTimes:this._handshakeRetryTimes}),e({type:"handshakeTimeout",message:"iframe handshake time out"})))}updateInvokeId(){this._invokeId=ee(`${this._prefixId}-invoke-`)}handleChannelMessage(e){let{data:n}=e;Z(n)&&this.logInfo("receive host message",M(n));let{type:r}=n;r==="callback"?this.handleHostCallback(n):r==="handshake"?this.handleHandshakeCallback(n):r==="invoke"?this.handleHostInvoke(n).catch(i=>{this.logError("handle host invoke error",a(a({},M(n)),k(i)))}):r==="event"&&this.handleHostEvent(n).catch(i=>{this.logError("handle host event error",a(a({},M(n)),k(i)))})}handleHostCallback(e){let{id:n,payload:r}=e,i={logId:n,key:r.key,callbackCode:r.code};if(r.code===1){if(this.pendingRequests.reject(n,r.res)){this.logWarn("api response received",i);return}}else if(this.pendingRequests.resolve(n,r.res)){this.logInfo("api response received",i);return}this.logWarn("host callback request not found",{id:n,key:r.key})}handleHostInvoke(e){return p(this,null,function*(){yield this._handshakePromise;let{id:n,payload:r}=e,{key:i,params:o,prefixId:s}=r;if(s!==this._prefixId){this.logWarn("ignore host invoke because prefixId mismatch",{id:n,key:i,prefixId:s,expectedPrefixId:this._prefixId});return}let d=this.eventMap.get(i);if(typeof d!="function"){this.logWarn("host invoke handler not found",{id:n,key:i}),this.sendMsg2Host({id:n,type:"callback",payload:{key:i,res:A(Me(i)),code:1}});return}this.logInfo("handle host invoke",{id:n,key:i});try{let c=He(yield d(o));this.sendMsg2Host({id:n,type:"callback",payload:{key:i,res:c,code:0}}),this.logInfo("host invoke success",{id:n,key:i})}catch(c){this.logError("host invoke failed",a({id:n,key:i},k(c))),this.sendMsg2Host({id:n,type:"callback",payload:{key:i,res:A(c),code:1}})}})}handleHostEvent(e){return p(this,null,function*(){yield this._handshakePromise;let{payload:n}=e,{key:r,params:i,prefixId:o}=n;if(o!==this._prefixId){this.logWarn("ignore host event because prefixId mismatch",{key:r,prefixId:o,expectedPrefixId:this._prefixId});return}let s=this.eventHandlerMap.get(r);if(!(s!=null&&s.size)){this.logWarn("host event handler not found",{key:r});return}this.logInfo("handle host event",{key:r,handlerCount:s.size}),yield Promise.allSettled(Array.from(s,d=>d(i)))})}handleHandshakeCallback(e){var o,s;let{id:n,payload:r}=e;this._prefixId=(o=r==null?void 0:r.prefixId)!=null?o:"",this.logInfo("receive handshake callback",{id:n,prefixId:this._prefixId}),(s=this._handshakeResolve)==null||s.call(this);let i={id:n,type:"handshake",payload:{proactive:!1,info:{isHandshakeSuccess:!0}}};this.sendMsg2Host(i)}listeningHostMsg(){var e;this.logInfo("start listening host messages"),(e=this._msgChannel)==null||e.listenMsg(this.handleChannelMessage.bind(this))}sendMsg2Host(e,n){var r;Z(e)&&this.logInfo("send message to host",M(e)),(r=this._msgChannel)==null||r.sendMsg(e,n)}invokeApi(e,n,r){return p(this,null,function*(){if(this._destroyed)return Promise.reject(A(G()));try{yield this._handshakePromise}catch(s){return this.logError("invoke api blocked by handshake error",a({key:e},k(s))),Promise.reject(J(s))}this._invokeId||this.updateInvokeId();let i=this._invokeId,o=this.pendingRequests.create(i,e,r==null?void 0:r.timeoutMs);return this.logInfo("api request sent",{key:e,logId:i}),this.sendMsg2Host({type:"invoke",id:i,payload:{key:e,params:n,prefixId:this._prefixId}}),this.updateInvokeId(),o})}registerApi(e,n){if(this.eventMap.has(e)){this.logWarn("register api ignored because key already exists",{key:e});return}this.eventMap.set(e,n),this.logInfo("register api",{key:e})}emitEvent(e,n){return p(this,null,function*(){try{yield this._handshakePromise}catch(r){return this.logError("emit event blocked by handshake error",a({key:e},k(r))),Promise.reject(J(r))}this.logInfo("emit event",{key:e}),this.sendMsg2Host({type:"event",id:ee(`${this._prefixId}-event-`),payload:{key:e,params:n,prefixId:this._prefixId}})})}fetchBinaryList(e){return p(this,null,function*(){var n;return this.logInfo("invoke built-in binary fetch",{status:"start",itemCount:e.items.length,concurrency:$(e.concurrency),credentials:Y(e.credentials)}),this.invokeApi(Ce,{items:e.items,concurrency:$(e.concurrency),credentials:Y((n=e.credentials)!=null?n:W)})})}subscribeBinaryFetchProgress(e){return this.subscribeEvent(Re,e)}cancelBinaryFetch(e){return p(this,null,function*(){this.logInfo("invoke built-in binary fetch cancel",{jobId:e,status:"cancel-requested"}),yield this.invokeApi(ke,{jobId:e})})}destroy(){var n,r;if(this._destroyed)return;this._destroyed=!0,this.logInfo("destroy client"),(n=this._msgChannel)==null||n.destroy(),clearTimeout(this._handshakeTimeout);let e=A(G());(r=this._handshakeReject)==null||r.call(this,{type:"handshakeTimeout",message:e.msg}),this.pendingRequests.rejectAll(e),this.eventMap.clear(),this.eventHandlerMap.clear()}subscribeEvent(e,n){var i;let r=(i=this.eventHandlerMap.get(e))!=null?i:new Set;return r.add(n),this.eventHandlerMap.set(e,r),this.logInfo("subscribe event",{key:e,handlerCount:r.size}),()=>this.unsubscribeEvent(e,n)}unsubscribeEvent(e,n){let r=this.eventHandlerMap.get(e);if(!r){this.logWarn("unsubscribe event ignored because key is not subscribed",{key:e});return}if(!n){this.eventHandlerMap.delete(e),this.logInfo("unsubscribe all event handlers",{key:e,handlerCount:0});return}r.delete(n),r.size===0&&this.eventHandlerMap.delete(e),this.logInfo("unsubscribe event",{key:e,handlerCount:r.size})}},Rt=t=>new te(t),R=Rt();var Oe="site.v1",g={AIFunctionStreamClose:"site.v1.ai.function.stream.close",AIFunctionStreamOpen:"site.v1.ai.function.stream.open",AttachmentUpload:"site.v1.attachment.upload",AttachmentUploadCancel:"site.v1.attachment.upload.cancel",FunctionInvoke:"site.v1.function.invoke",HttpRequest:"site.v1.http.request",HttpRequestCancel:"site.v1.http.request.cancel",RuntimeContext:"site.v1.runtime.context",StreamClose:"site.v1.chatbot.stream.close",StreamOpen:"site.v1.chatbot.stream.open"},y={AIFunctionStreamDone:"site.v1.ai.function.stream.done",AIFunctionStreamError:"site.v1.ai.function.stream.error",AIFunctionStreamMessage:"site.v1.ai.function.stream.message",AttachmentUploadProgress:"site.v1.attachment.upload.progress",LifecycleLoadFailed:"site.v1.lifecycle.load-failed",LifecycleReady:"site.v1.lifecycle.ready",ModeChanged:"site.v1.runtime.mode-changed",StreamError:"site.v1.chatbot.stream.error",StreamMessage:"site.v1.chatbot.stream.message"},D={GetCurrentUser:"function.runtime.getCurrentUser",Logout:"function.runtime.logout",RequestEdit:"function.runtime.requestEdit"},u={AttachmentUnavailable:"ATTACHMENT_UNAVAILABLE",AttachmentUploadCanceled:"ATTACHMENT_UPLOAD_CANCELED",AttachmentUploadFailed:"ATTACHMENT_UPLOAD_FAILED",AttachmentUploadStalled:"ATTACHMENT_UPLOAD_STALLED",ChannelDestroyed:"CHANNEL_DESTROYED",FunctionNotAllowed:"FUNCTION_NOT_ALLOWED",FunctionRequestFailed:"FUNCTION_REQUEST_FAILED",InvalidAIFunctionTask:"INVALID_AI_FUNCTION_TASK",HttpRequestFailed:"HTTP_REQUEST_FAILED",HttpResponseTypeUnsupported:"HTTP_RESPONSE_TYPE_UNSUPPORTED",HttpRequestCanceled:"HTTP_REQUEST_CANCELED",InvalidAttachmentTarget:"INVALID_ATTACHMENT_TARGET",InvalidFunctionName:"INVALID_FUNCTION_NAME",InvalidHttpHeader:"INVALID_HTTP_HEADER",InvalidHttpUrl:"INVALID_HTTP_URL",LogoutFailed:"LOGOUT_FAILED",ProtocolMismatch:"PROTOCOL_MISMATCH",RequestTimeout:"REQUEST_TIMEOUT",StreamDisconnected:"STREAM_DISCONNECTED",StreamHealthTimeout:"STREAM_HEALTH_TIMEOUT",StreamInterrupted:"STREAM_INTERRUPTED",StreamOpenFailed:"STREAM_OPEN_FAILED",StreamSeqGap:"STREAM_SEQ_GAP",StreamUnavailable:"STREAM_UNAVAILABLE",UnsupportedHttpBody:"UNSUPPORTED_HTTP_BODY",UserInfoUnavailable:"USER_INFO_UNAVAILABLE"},xr=t=>{var e,n;return{answer:(e=t.content)!=null?e:"",reasoning:(n=t.reasoningContent)!=null?n:""}},xt=/^function(?:\.[A-Za-z_][A-Za-z0-9_]*)+$/,Ue=t=>xt.test(t);var _t=0,De=(i,o)=>p(void 0,[i,o],function*(t,{init:e,url:n,signal:r}){if((e==null?void 0:e.responseType)!==void 0&&!["text","arrayBuffer"].includes(e.responseType))throw new S(u.HttpResponseTypeUnsupported,"\u4E0D\u652F\u6301\u7684 HTTP \u54CD\u5E94\u7C7B\u578B");let s=()=>new DOMException("The operation was aborted","AbortError");if(r!=null&&r.aborted)throw s();let d=typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`http-${Date.now()}-${++_t}`,c=()=>{},m=new Promise((h,x)=>{c=()=>{x(s()),t.invokeApi(g.HttpRequestCancel,{requestId:d}).catch(()=>{})}});r==null||r.addEventListener("abort",c,{once:!0});try{let h=yield Promise.race([t.invokeApi(g.HttpRequest,{requestId:d,url:n,init:e},{timeoutMs:(e==null?void 0:e.timeoutMs)===void 0?void 0:Math.min(e.timeoutMs,6e4)+1e3}),m]);if((e==null?void 0:e.responseType)==="arrayBuffer"&&(h.bodyType!=="arrayBuffer"||!(h.body instanceof ArrayBuffer)))throw new S(u.HttpResponseTypeUnsupported,"\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301 HTTP \u4E8C\u8FDB\u5236\u54CD\u5E94\uFF0C\u8BF7\u5347\u7EA7\u5BBF\u4E3B");return new Response([204,205,304].includes(h.status)?null:h.body,{headers:h.headers,status:h.status,statusText:h.statusText})}finally{r==null||r.removeEventListener("abort",c)}});var S=class extends Error{constructor(n,r){super(r);this.code=n;this.name="SiteRuntimeInvocationError"}},Be=t=>typeof t=="string"&&t.trim().length>0,Mt=t=>typeof File!="undefined"&&t instanceof File,qe=12e4,Pt=2*60*60*1e3,je=0,Ft=()=>typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():(je+=1,`site-upload-${je}`),wt=t=>typeof t=="object"&&t!==null&&"code"in t?t.code:void 0,Ht=t=>{if(t instanceof Error&&t.message)return t.message;if(typeof t=="object"&&t!==null){if("message"in t&&typeof t.message=="string")return t.message;if("msg"in t&&typeof t.msg=="string")return t.msg}return String(t)},Nt=new Set([u.AttachmentUnavailable,u.AttachmentUploadCanceled,u.AttachmentUploadFailed,u.AttachmentUploadStalled,u.InvalidAttachmentTarget]),Lt=(t,e)=>{if(t instanceof S)return t;let n=wt(t),r=Ht(t);return String(n)===String(10004)?new S(u.AttachmentUnavailable,r):typeof n=="string"&&Nt.has(n)?new S(n,r):new S(e,r)},B=(t,e,n)=>p(void 0,null,function*(){if(!Ue(e))throw new S(u.InvalidFunctionName,"Function name \u5FC5\u987B\u4F7F\u7528 function \u5F00\u5934\u7684\u70B9\u53F7\u8DEF\u5F84");return t.invokeApi(g.FunctionInvoke,{functionName:e,params:n})}),q=class{constructor(e){this.channel=e;this.uploadAttachment=r=>p(this,null,function*(){var i=r,{onProgress:e}=i,n=Te(i,["onProgress"]);if(!Be(n==null?void 0:n.baseToken)||!Be(n==null?void 0:n.tableId)||!Mt(n==null?void 0:n.file))throw new S(u.InvalidAttachmentTarget,"\u9644\u4EF6\u4E0A\u4F20\u76EE\u6807\u5FC5\u987B\u5305\u542B baseToken\u3001tableId\uFF0C\u4E14 file \u4E3A File");let o=Ft(),s,d=()=>{},c=()=>{this.channel.invokeApi(g.AttachmentUploadCancel,{uploadId:o}).catch(()=>{})},m=new Promise((h,x)=>{let H=()=>{clearTimeout(s),s=setTimeout(()=>{c(),x(new S(u.AttachmentUploadStalled,`\u9644\u4EF6\u4E0A\u4F20\u5DF2\u505C\u6EDE\u8D85\u8FC7 ${qe/1e3}s`))},qe)};d=this.channel.subscribeEvent(y.AttachmentUploadProgress,T=>{(T==null?void 0:T.uploadId)===o&&(H(),Promise.resolve(e==null?void 0:e(T)).catch(()=>{console.error("[base-site-channel][runtime] Attachment progress callback failed")}))})});try{return yield Promise.race([this.channel.invokeApi(g.AttachmentUpload,f(a({},n),{uploadId:o}),{timeoutMs:Pt}),m])}catch(h){throw Lt(h,u.AttachmentUploadFailed)}finally{clearTimeout(s),d()}});this.invokeHttp=e=>De(this.channel,e);this.invokeApi=(e,n)=>B(this.channel,e,n);this.getRuntimeContext=()=>this.channel.invokeApi(g.RuntimeContext,void 0);this.getCurrentUser=()=>B(this.channel,D.GetCurrentUser,void 0);this.logout=()=>B(this.channel,D.Logout,void 0);this.requestEdit=()=>B(this.channel,D.RequestEdit,void 0);this.ready=()=>this.channel.emitEvent(y.LifecycleReady,{protocolVersion:Oe});this.reportLoadFailed=e=>this.channel.emitEvent(y.LifecycleLoadFailed,{code:e});this.subscribeModeChanged=e=>this.channel.subscribeEvent(y.ModeChanged,({mode:n})=>e(n))}},j=(t=R)=>new q(t),v=j(),Ot=v.invokeHttp,Ut=v.invokeApi,Dt=v.getCurrentUser,Bt=v.logout,qt=v.requestEdit,jt=v.uploadAttachment;var Kt=new Set(["open.feishu.cn","open.feishu-pre.cn","open.feishu-boe.cn"]),Ke="/open-apis",Vt="/base-site/api/openapi",zt=new Set(["DELETE","GET","PATCH","POST","PUT"]),Wt=()=>(typeof globalThis.location=="undefined"?"":globalThis.location.pathname).replace(/^\/+/,"").startsWith("preview")?[["x-project-env","preview"]]:[],$t=t=>{if(typeof Request!="undefined"&&t instanceof Request)throw new TypeError("Site Runtime fetch \u6682\u4E0D\u652F\u6301 Request \u5165\u53C2");let e=String(t);if(e.startsWith("//"))throw new TypeError("Site Runtime fetch \u4E0D\u652F\u6301 scheme-relative URL");if(e.startsWith("/"))return e;let n=new URL(e);if(Kt.has(n.hostname)&&n.pathname.startsWith(Ke))return`${Vt}${n.pathname.slice(Ke.length)}${n.search}`;throw new TypeError("Site Runtime fetch \u4EC5\u652F\u6301\u76F8\u5BF9\u4E1A\u52A1\u8DEF\u5F84")},Yt=t=>{let e=new Headers(t);Wt().forEach(([r,i])=>e.set(r,i));let n={};return e.forEach((r,i)=>{n[i]=r}),n},Gt=(t,e)=>{var r,i,o;let n=(i=(r=t==null?void 0:t.method)==null?void 0:r.toUpperCase())!=null?i:"GET";if(!zt.has(n))throw new TypeError(`Site Runtime fetch \u4E0D\u652F\u6301 ${n} \u65B9\u6CD5`);if((t==null?void 0:t.body)!==void 0&&t.body!==null&&typeof t.body!="string")throw new TypeError("Site Runtime fetch body \u4EC5\u652F\u6301\u5B57\u7B26\u4E32");if((o=t==null?void 0:t.signal)!=null&&o.aborted)throw new DOMException("The operation was aborted","AbortError");return{body:typeof(t==null?void 0:t.body)=="string"?t.body:void 0,headers:Yt(t==null?void 0:t.headers),method:n,timeoutMs:e}},K=(t=v,e)=>(n,r)=>t.invokeHttp(f(a({init:Gt(r,e)},r!=null&&r.signal?{signal:r.signal}:{}),{url:$t(n)})),Jt=K();var Ve=0,Xt=()=>typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():(Ve+=1,`site-chatbot-${Ve}`),V=(t,e)=>{try{t==null||t(e)}catch(n){console.error("[base-site-channel][runtime] Chatbot callback failed")}},P=class extends Error{constructor(n,r){super(`Chatbot stream error: ${n}`);this.code=n;this.retryable=r;this.name="SiteChatbotStreamError"}},ne=class{constructor(e){this.options=e;this.init=e=>{this.destroy();let n=Xt(),r={lastSeq:0,subscriptionId:n,unsubscribeError:()=>{},unsubscribeMessage:()=>{}};r.unsubscribeMessage=this.channel.subscribeEvent(y.StreamMessage,i=>{i.subscriptionId!==n||i.seq<=r.lastSeq||(i.seq>r.lastSeq+1&&V(this.onErrorCallback,new P(u.StreamSeqGap,!0)),r.lastSeq=i.seq,V(this.onMessageCallback,i.data))}),r.unsubscribeError=this.channel.subscribeEvent(y.StreamError,i=>{i.subscriptionId===n&&V(this.onErrorCallback,new P(i.code,i.retryable))}),this.current=r,this.channel.invokeApi(g.StreamOpen,{chatbotId:this.options.chatbotId,subscriptionId:n,threadId:e}).catch(()=>{var i;((i=this.current)==null?void 0:i.subscriptionId)===n&&V(this.onErrorCallback,new P(u.StreamOpenFailed,!0))})};this.onMessage=e=>{this.onMessageCallback=e};this.onError=e=>{this.onErrorCallback=e};this.destroy=()=>{let e=this.current;e&&(e.unsubscribeMessage(),e.unsubscribeError(),this.current=void 0,this.channel.invokeApi(g.StreamClose,{subscriptionId:e.subscriptionId}).catch(()=>console.error("[base-site-channel][runtime] Chatbot stream close failed")))};var n;this.channel=(n=e.channel)!=null?n:R}};var ie="prod",ze=0,Ye=()=>typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():(ze+=1,`site-ai-fn-${ze}`),E=(t,e)=>{try{t==null||t(e)}catch(n){console.error("[base-site-channel][runtime] AI function callback failed")}},l=(t,e)=>{let n=new Error(e||`AI function error: ${t}`);return n.name="SiteAIFunctionError",n.code=t,n},Ge=()=>l(u.InvalidHttpUrl,"siteToken is required to invoke site AI function"),oe=()=>typeof window!="undefined"&&window.parent!==window,se=t=>{if(typeof queueMicrotask=="function"){queueMicrotask(t);return}Promise.resolve().then(t)},ae=t=>{let e={data:[],event:"message"};for(let n of t.split(/\r?\n/))n.startsWith("event:")?e.event=n.slice(6).trim():n.startsWith("data:")&&e.data.push(n.slice(5).trimStart());return e},re=(t,e)=>{for(let n of e){let r=t[n];if(typeof r=="string")return r}},Je=t=>{let e=[t];if(t&&typeof t=="object"){let n=t;e.push(n.response,n.data)}for(let n of e){if(!n||typeof n!="object")continue;let r=re(n,["request_id","requestId","RequestID","id"]);if(r)return r}},Xe=t=>{if(!t||typeof t!="object")return{};let e=t;return{content:re(e,["content","text","answer"]),reasoningContent:re(e,["reasoning_content","reasoningContent","reasoning"])}},Qt=t=>{if(!t||typeof t!="object")return{};let e=t.choices;if(!Array.isArray(e))return{};for(let n of e){let r=n.delta,{content:i,reasoningContent:o}=Xe(r);if(i!==void 0||o!==void 0)return{content:i,reasoningContent:o}}return{}},Qe=t=>{var n;let e=[t];if(t&&typeof t=="object"){let r=t;e.push(r.response,r.data)}for(let r of e){let i=Qt(r);if(i.content!==void 0||i.reasoningContent!==void 0)return i;let o=Xe(r&&typeof r=="object"&&(n=r.delta)!=null?n:r);if(o.content!==void 0||o.reasoningContent!==void 0)return o}return{}},z=t=>{try{let e=JSON.parse(t),n=Qe(e),r=Je(e);return f(a(a(a({},n.content!==void 0?{content:n.content}:{}),n.reasoningContent!==void 0?{reasoningContent:n.reasoningContent}:{}),r?{requestId:r}:{}),{raw:e})}catch(e){return{content:t,raw:t}}},Ze=t=>{if(typeof t=="string")return z(t);let e=Qe(t),n=Je(t),r=t&&typeof t=="object"&&"raw"in t?t.raw:t;return f(a(a(a({},e.content!==void 0?{content:e.content}:{}),e.reasoningContent!==void 0?{reasoningContent:e.reasoningContent}:{}),n?{requestId:n}:{}),{raw:r})},Zt=t=>{var e,n;try{let r=JSON.parse(t),i=(e=r.Code)!=null?e:r.code,o=(n=r.Message)!=null?n:r.message,s=typeof i=="string"||typeof i=="number"?String(i):"STREAM_FAILED";return l(s||"STREAM_FAILED",typeof o=="string"&&o?o:t)}catch(r){return l("STREAM_FAILED",t)}},ce=()=>({text:""}),en=t=>/(^|\n)(data|event|id|retry):/.test(t),We=t=>{if(!t||t==="[DONE]")return!!t;try{return JSON.parse(t),!0}catch(e){return!1}},tn=t=>{if(t){if(en(t)){let n=ae(t).data.join(`
|
|
1
|
+
var ct=Object.defineProperty,dt=Object.defineProperties;var ut=Object.getOwnPropertyDescriptors;var N=Object.getOwnPropertySymbols;var ve=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var Ae=(t,e,n)=>e in t?ct(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,a=(t,e)=>{for(var n in e||(e={}))ve.call(e,n)&&Ae(t,n,e[n]);if(N)for(var n of N(e))be.call(e,n)&&Ae(t,n,e[n]);return t},f=(t,e)=>dt(t,ut(e));var Te=(t,e)=>{var n={};for(var r in t)ve.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(t!=null&&N)for(var r of N(t))e.indexOf(r)<0&&be.call(t,r)&&(n[r]=t[r]);return n};var p=(t,e,n)=>new Promise((r,i)=>{var o=c=>{try{d(n.next(c))}catch(m){i(m)}},s=c=>{try{d(n.throw(c))}catch(m){i(m)}},d=c=>c.done?r(c.value):Promise.resolve(c.value).then(o,s);d((n=n.apply(t,e)).next())});import{uniqueId as ee}from"lodash-es";var W="same-origin",Ce="__internal_fetchBinaryList__",Re="__internal_cancelBinaryFetch__",ke="__internal_binaryFetchProgress__";function $(t){return Number.isFinite(t)?Math.max(1,Math.floor(t)):4}function Y(t){return t==="omit"||t==="include"?t:W}var L=(i=>(i.IFRAME_LOAD_ERROR="iframeLoadError",i.NOT_ALLOWED_URL="notAllowedUrl",i.HANDSHAKE_TIME_OUT="handshakeTimeout",i.CHANNEL_UNAVAILABLE="channelUnavailable",i))(L||{});var b=class extends Error{constructor(n,r){super(r);this.code=n,this.name="ChannelCallbackError"}};function Me(t){return new b(10004,`api "${t}" is not registered`)}function Pe(t){return new b(10005,`api "${t}" timed out`)}function G(){return new b(10006,"channel has been destroyed")}function Fe(t){return new b(10008,`request "${t}" was superseded by a new one`)}var lt="unknown error";function we(t){return typeof t=="object"&&t!==null}function pt(t){if(typeof t=="string"&&t)return t;if(t instanceof b&&t.message||t instanceof Error&&t.message)return t.message;if(we(t)){let{msg:e,message:n}=t;if(typeof e=="string"&&e)return e;if(typeof n=="string"&&n)return n}return lt}function ht(t){if(t instanceof b)return t.code;if(!we(t))return-1;let{code:e}=t;return typeof e=="string"&&e||typeof e=="number"&&Number.isFinite(e)?e:-1}function A(t){return{code:ht(t),msg:pt(t)}}function xe(t){return t instanceof ArrayBuffer||ArrayBuffer.isView(t)||typeof Blob!="undefined"&&t instanceof Blob}function mt(t){return xe(t)||Object.values(t).some(e=>xe(e))}function He(t){return t&&typeof t=="object"?mt(t)?t:JSON.parse(JSON.stringify(t)):t}var ft={["iframeLoadError"]:10001,["notAllowedUrl"]:10002,["handshakeTimeout"]:10003,["channelUnavailable"]:10009};function gt(t){return typeof t=="object"&&t!==null}function It(t){if(!gt(t))return!1;let{type:e}=t;return typeof e=="string"&&Object.values(L).includes(e)}function J(t){return It(t)?{code:ft[t.type],msg:t.message||t.type}:A(t)}function X(t){let e=Promise.reject(t);return e.catch(()=>{}),e}var F=class{constructor(e,n){this._target=e,this._options=n}sendMsg(e,n){if(!this._target)throw new Error("target window is not found");this._target.postMessage(e,this._options.targetOrigin,n!=null?n:[])}listenMsg(e){this._eventHandler=n=>{n.source===this._options.sourceWindow&&this._options.allowedOrigins.includes(n.origin)&&e(n)},typeof window!="undefined"&&window.addEventListener("message",this._eventHandler)}destroy(){typeof window!="undefined"&&this._eventHandler&&window.removeEventListener("message",this._eventHandler),this._eventHandler=void 0}};var _=class{constructor(e,n,r){e==="host"?this.channelManager=new F(n,r):e==="client"&&(this.channelManager=new F(window.parent,r))}static createInstance(e,n,r){return new _(e,n,r)}sendMsg(e,n){var r;(r=this.channelManager)==null||r.sendMsg(e,n)}listenMsg(e){var n;(n=this.channelManager)==null||n.listenMsg(e)}destroy(){var e;(e=this.channelManager)==null||e.destroy()}};var O=class{constructor(){this.requests=new Map}create(e,n,r=3e4){return this.reject(e,A(Fe(e))),new Promise((i,o)=>{let s=setTimeout(()=>{var d;((d=this.requests.get(e))==null?void 0:d.timeout)===s&&(this.requests.delete(e),o(A(Pe(n))))},r);this.requests.set(e,{reject:o,resolve:i,timeout:s})})}resolve(e,n){let r=this.take(e);return r?(r.resolve(n),!0):!1}reject(e,n){let r=this.take(e);return r?(r.reject(n),!0):!1}rejectAll(e){for(let n of this.requests.keys())this.reject(n,e)}take(e){let n=this.requests.get(e);if(n)return this.requests.delete(e),clearTimeout(n.timeout),n}};var Q=t=>typeof t=="object"&&t!==null,Et=new Set(["blockId","expectedPrefixId","id","jobId","prefixId","url"]),C=t=>{let e={};for(let[n,r]of Object.entries(t))if(!(n==="inputParams"||n==="outputParams")){if(Et.has(n)){e[`${n}Present`]=!!r;continue}if(n==="error"){Object.assign(e,R(r));continue}if(n==="errorInfo"&&Q(r)){e.errorType=typeof r.type=="string"?r.type:"object";continue}(typeof r=="string"||typeof r=="number"||typeof r=="boolean")&&(e[n]=r)}return e},M=t=>{let e={idPresent:!!t.id,type:t.type},n=Q(t.payload)?t.payload:{};return typeof n.key=="string"&&(e.key=n.key),t.type==="callback"&&typeof n.code=="number"&&(e.callbackCode=n.code),t.type==="handshake"&&typeof n.proactive=="boolean"&&(e.proactive=n.proactive),e},Z=t=>t.type!=="invoke"&&t.type!=="callback",R=t=>{if(!Q(t))return{errorType:typeof t};let e={errorType:t instanceof Error?t.name:"object"};return(typeof t.code=="number"||typeof t.code=="string")&&(e.errorCode=t.code),e};var At=()=>{let t=Reflect.get(globalThis,"BearWebSlardarWeb");return typeof t=="function"?t:void 0},vt=t=>{let e={};for(let[n,r]of Object.entries(C(t)))typeof r=="string"||typeof r=="number"?e[n]=r:typeof r=="boolean"&&(e[n]=String(r));return e},Ne=(t,e,n,r)=>{console[e](`[base-site-channel][${t}]`,n,r)},U=(t,e,n,r={})=>{if(e==="info")return;let i=C(r),o=At();if(!o){Ne(t,e,n,i);return}try{o("sendLog",{content:`[base-site-channel][${t}] ${n}`,extra:a({event_name:"Runtime_SiteChannel_Message",bizType:"Runtime",subType:"SiteChannel",action:"Message",channel_side:t,channel_message:n},vt(i)),level:e})}catch(s){Ne(t,e,n,f(a({},i),{slardarFallback:!0,slardarErrorType:s instanceof Error?s.name:typeof s}))}};var Ct=()=>{var n;if(typeof window=="undefined")return null;let e=((n=window.location.ancestorOrigins)==null?void 0:n[0])||document.referrer;if(!e)return null;try{return new URL(e).origin}catch(r){return null}},Rt=t=>{try{return new URL(t).origin}catch(e){return null}},te=class{constructor(e={}){this.pendingRequests=new O;this.eventMap=new Map;this.eventHandlerMap=new Map;this._msgChannel=null;this._invokeId="";this._handshakePromise=X({type:"channelUnavailable",message:"channel handshake is not initialized"});this._handshakeResolve=null;this._handshakeReject=null;this._handshakeRetryTimes=0;this._handshakeStatus=0;this._handshakeTimeout=null;this._prefixId="";this._destroyed=!1;let n=e.hostOrigin?Rt(e.hostOrigin):null;if(this.hostOrigin=n!=null?n:Ct(),e.hostOrigin&&!n&&this.logWarn("invalid hostOrigin, fallback to parent origin"),typeof window=="undefined"||window.parent===window){this.failHandshake("invalid window context",{hasWindow:typeof window!="undefined",isTopWindow:typeof window!="undefined"?window.parent===window:!0});return}if(!this.hostOrigin){this.failHandshake("host origin unavailable");return}this._msgChannel=_.createInstance("client",window.parent,{allowedOrigins:[this.hostOrigin],sourceWindow:window.parent,targetOrigin:this.hostOrigin}),this.listeningHostMsg(),this.startHandshake()}logInfo(e,n={}){U("client","info",e,a({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},C(n)))}logWarn(e,n={}){U("client","warn",e,a({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},C(n)))}logError(e,n={}){U("client","error",e,a({hasPrefixId:!!this._prefixId,handshakeStatus:this._handshakeStatus},C(n)))}failHandshake(e,n={}){this._handshakeStatus=2,this._handshakePromise=X({type:"channelUnavailable",message:e}),this.logError(`init failed: ${e}`,n)}sendProactiveHandshakeMsg(){var n;let e={id:ee("handshake-"),type:"handshake",payload:{proactive:!0}};this.logInfo("send proactive handshake",M(e)),(n=this._msgChannel)==null||n.sendMsg(e)}_initHandshake(){this._handshakeRetryTimes=0,clearTimeout(this._handshakeTimeout),this._handshakeStatus=0,this.logInfo("init handshake"),this._handshakePromise=new Promise((e,n)=>{this._handshakeResolve=e,this._handshakeReject=n,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(n),2e3)})}startHandshake(){this._initHandshake(),this._handshakePromise.then(()=>{this._handshakeStatus=1,this.logInfo("handshake success")}).catch(e=>{this._handshakeStatus=2,this.logError("handshake failed",{error:e})}),this.sendProactiveHandshakeMsg()}retryHandshake(e){this._handshakeStatus===0&&(this._handshakeRetryTimes<5?(this.logWarn("retry handshake",{retryTimes:this._handshakeRetryTimes+1}),this.sendProactiveHandshakeMsg(),this._handshakeRetryTimes++,this._handshakeTimeout=setTimeout(()=>this.retryHandshake(e),2e3+2**this._handshakeRetryTimes)):(this.logError("handshake retry timeout",{retryTimes:this._handshakeRetryTimes}),e({type:"handshakeTimeout",message:"iframe handshake time out"})))}updateInvokeId(){this._invokeId=ee(`${this._prefixId}-invoke-`)}handleChannelMessage(e){let{data:n}=e;Z(n)&&this.logInfo("receive host message",M(n));let{type:r}=n;r==="callback"?this.handleHostCallback(n):r==="handshake"?this.handleHandshakeCallback(n):r==="invoke"?this.handleHostInvoke(n).catch(i=>{this.logError("handle host invoke error",a(a({},M(n)),R(i)))}):r==="event"&&this.handleHostEvent(n).catch(i=>{this.logError("handle host event error",a(a({},M(n)),R(i)))})}handleHostCallback(e){let{id:n,payload:r}=e,i={logId:n,key:r.key,callbackCode:r.code};if(r.code===1){if(this.pendingRequests.reject(n,r.res)){this.logWarn("api response received",i);return}}else if(this.pendingRequests.resolve(n,r.res)){this.logInfo("api response received",i);return}this.logWarn("host callback request not found",{id:n,key:r.key})}handleHostInvoke(e){return p(this,null,function*(){yield this._handshakePromise;let{id:n,payload:r}=e,{key:i,params:o,prefixId:s}=r;if(s!==this._prefixId){this.logWarn("ignore host invoke because prefixId mismatch",{id:n,key:i,prefixId:s,expectedPrefixId:this._prefixId});return}let d=this.eventMap.get(i);if(typeof d!="function"){this.logWarn("host invoke handler not found",{id:n,key:i}),this.sendMsg2Host({id:n,type:"callback",payload:{key:i,res:A(Me(i)),code:1}});return}this.logInfo("handle host invoke",{id:n,key:i});try{let c=He(yield d(o));this.sendMsg2Host({id:n,type:"callback",payload:{key:i,res:c,code:0}}),this.logInfo("host invoke success",{id:n,key:i})}catch(c){this.logError("host invoke failed",a({id:n,key:i},R(c))),this.sendMsg2Host({id:n,type:"callback",payload:{key:i,res:A(c),code:1}})}})}handleHostEvent(e){return p(this,null,function*(){yield this._handshakePromise;let{payload:n}=e,{key:r,params:i,prefixId:o}=n;if(o!==this._prefixId){this.logWarn("ignore host event because prefixId mismatch",{key:r,prefixId:o,expectedPrefixId:this._prefixId});return}let s=this.eventHandlerMap.get(r);if(!(s!=null&&s.size)){this.logWarn("host event handler not found",{key:r});return}this.logInfo("handle host event",{key:r,handlerCount:s.size}),yield Promise.allSettled(Array.from(s,d=>d(i)))})}handleHandshakeCallback(e){var o,s;let{id:n,payload:r}=e;this._prefixId=(o=r==null?void 0:r.prefixId)!=null?o:"",this.logInfo("receive handshake callback",{id:n,prefixId:this._prefixId}),(s=this._handshakeResolve)==null||s.call(this);let i={id:n,type:"handshake",payload:{proactive:!1,info:{isHandshakeSuccess:!0}}};this.sendMsg2Host(i)}listeningHostMsg(){var e;this.logInfo("start listening host messages"),(e=this._msgChannel)==null||e.listenMsg(this.handleChannelMessage.bind(this))}sendMsg2Host(e,n){var r;Z(e)&&this.logInfo("send message to host",M(e)),(r=this._msgChannel)==null||r.sendMsg(e,n)}invokeApi(e,n,r){return p(this,null,function*(){if(this._destroyed)return Promise.reject(A(G()));try{yield this._handshakePromise}catch(s){return this.logError("invoke api blocked by handshake error",a({key:e},R(s))),Promise.reject(J(s))}this._invokeId||this.updateInvokeId();let i=this._invokeId,o=this.pendingRequests.create(i,e,r==null?void 0:r.timeoutMs);return this.logInfo("api request sent",{key:e,logId:i}),this.sendMsg2Host({type:"invoke",id:i,payload:{key:e,params:n,prefixId:this._prefixId}}),this.updateInvokeId(),o})}registerApi(e,n){if(this.eventMap.has(e)){this.logWarn("register api ignored because key already exists",{key:e});return}this.eventMap.set(e,n),this.logInfo("register api",{key:e})}emitEvent(e,n){return p(this,null,function*(){try{yield this._handshakePromise}catch(r){return this.logError("emit event blocked by handshake error",a({key:e},R(r))),Promise.reject(J(r))}this.logInfo("emit event",{key:e}),this.sendMsg2Host({type:"event",id:ee(`${this._prefixId}-event-`),payload:{key:e,params:n,prefixId:this._prefixId}})})}fetchBinaryList(e){return p(this,null,function*(){var n;return this.logInfo("invoke built-in binary fetch",{status:"start",itemCount:e.items.length,concurrency:$(e.concurrency),credentials:Y(e.credentials)}),this.invokeApi(Ce,{items:e.items,concurrency:$(e.concurrency),credentials:Y((n=e.credentials)!=null?n:W)})})}subscribeBinaryFetchProgress(e){return this.subscribeEvent(ke,e)}cancelBinaryFetch(e){return p(this,null,function*(){this.logInfo("invoke built-in binary fetch cancel",{jobId:e,status:"cancel-requested"}),yield this.invokeApi(Re,{jobId:e})})}destroy(){var n,r;if(this._destroyed)return;this._destroyed=!0,this.logInfo("destroy client"),(n=this._msgChannel)==null||n.destroy(),clearTimeout(this._handshakeTimeout);let e=A(G());(r=this._handshakeReject)==null||r.call(this,{type:"handshakeTimeout",message:e.msg}),this.pendingRequests.rejectAll(e),this.eventMap.clear(),this.eventHandlerMap.clear()}subscribeEvent(e,n){var i;let r=(i=this.eventHandlerMap.get(e))!=null?i:new Set;return r.add(n),this.eventHandlerMap.set(e,r),this.logInfo("subscribe event",{key:e,handlerCount:r.size}),()=>this.unsubscribeEvent(e,n)}unsubscribeEvent(e,n){let r=this.eventHandlerMap.get(e);if(!r){this.logWarn("unsubscribe event ignored because key is not subscribed",{key:e});return}if(!n){this.eventHandlerMap.delete(e),this.logInfo("unsubscribe all event handlers",{key:e,handlerCount:0});return}r.delete(n),r.size===0&&this.eventHandlerMap.delete(e),this.logInfo("unsubscribe event",{key:e,handlerCount:r.size})}},kt=t=>new te(t),k=kt();var Oe="site.v1",g={AIFunctionStreamClose:"site.v1.ai.function.stream.close",AIFunctionStreamOpen:"site.v1.ai.function.stream.open",AttachmentUpload:"site.v1.attachment.upload",AttachmentUploadCancel:"site.v1.attachment.upload.cancel",FunctionInvoke:"site.v1.function.invoke",HttpRequest:"site.v1.http.request",HttpRequestCancel:"site.v1.http.request.cancel",RuntimeContext:"site.v1.runtime.context",StreamClose:"site.v1.chatbot.stream.close",StreamOpen:"site.v1.chatbot.stream.open"},y={AIFunctionStreamDone:"site.v1.ai.function.stream.done",AIFunctionStreamError:"site.v1.ai.function.stream.error",AIFunctionStreamMessage:"site.v1.ai.function.stream.message",AttachmentUploadProgress:"site.v1.attachment.upload.progress",LifecycleLoadFailed:"site.v1.lifecycle.load-failed",LifecycleReady:"site.v1.lifecycle.ready",ModeChanged:"site.v1.runtime.mode-changed",StreamError:"site.v1.chatbot.stream.error",StreamMessage:"site.v1.chatbot.stream.message"},D={GetCurrentUser:"function.runtime.getCurrentUser",Logout:"function.runtime.logout",RequestEdit:"function.runtime.requestEdit"},u={AttachmentUnavailable:"ATTACHMENT_UNAVAILABLE",AttachmentUploadCanceled:"ATTACHMENT_UPLOAD_CANCELED",AttachmentUploadFailed:"ATTACHMENT_UPLOAD_FAILED",AttachmentUploadStalled:"ATTACHMENT_UPLOAD_STALLED",ChannelDestroyed:"CHANNEL_DESTROYED",FunctionNotAllowed:"FUNCTION_NOT_ALLOWED",FunctionRequestFailed:"FUNCTION_REQUEST_FAILED",InvalidAIFunctionTask:"INVALID_AI_FUNCTION_TASK",HttpRequestFailed:"HTTP_REQUEST_FAILED",HttpResponseTypeUnsupported:"HTTP_RESPONSE_TYPE_UNSUPPORTED",HttpRequestCanceled:"HTTP_REQUEST_CANCELED",InvalidAttachmentTarget:"INVALID_ATTACHMENT_TARGET",InvalidFunctionName:"INVALID_FUNCTION_NAME",InvalidHttpHeader:"INVALID_HTTP_HEADER",InvalidHttpUrl:"INVALID_HTTP_URL",LogoutFailed:"LOGOUT_FAILED",ProtocolMismatch:"PROTOCOL_MISMATCH",RequestTimeout:"REQUEST_TIMEOUT",StreamDisconnected:"STREAM_DISCONNECTED",StreamHealthTimeout:"STREAM_HEALTH_TIMEOUT",StreamInterrupted:"STREAM_INTERRUPTED",StreamOpenFailed:"STREAM_OPEN_FAILED",StreamSeqGap:"STREAM_SEQ_GAP",StreamUnavailable:"STREAM_UNAVAILABLE",UnsupportedHttpBody:"UNSUPPORTED_HTTP_BODY",UserInfoUnavailable:"USER_INFO_UNAVAILABLE"},xr=t=>{var e,n;return{answer:(e=t.content)!=null?e:"",reasoning:(n=t.reasoningContent)!=null?n:""}},xt=/^function(?:\.[A-Za-z_][A-Za-z0-9_]*)+$/,Ue=t=>xt.test(t);var _t=0,De=(i,o)=>p(void 0,[i,o],function*(t,{init:e,url:n,signal:r}){if((e==null?void 0:e.responseType)!==void 0&&!["text","arrayBuffer"].includes(e.responseType))throw new S(u.HttpResponseTypeUnsupported,"Unsupported HTTP response type; use text or arrayBuffer");let s=()=>new DOMException("The operation was aborted","AbortError");if(r!=null&&r.aborted)throw s();let d=typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`http-${Date.now()}-${++_t}`,c=()=>{},m=new Promise((h,x)=>{c=()=>{x(s()),t.invokeApi(g.HttpRequestCancel,{requestId:d}).catch(()=>{})}});r==null||r.addEventListener("abort",c,{once:!0});try{let h=yield Promise.race([t.invokeApi(g.HttpRequest,{requestId:d,url:n,init:e},{timeoutMs:(e==null?void 0:e.timeoutMs)===void 0?void 0:Math.min(e.timeoutMs,6e4)+1e3}),m]);if((e==null?void 0:e.responseType)==="arrayBuffer"&&(h.bodyType!=="arrayBuffer"||!(h.body instanceof ArrayBuffer)))throw new S(u.HttpResponseTypeUnsupported,"The current host does not support binary HTTP responses; upgrade the host");return new Response([204,205,304].includes(h.status)?null:h.body,{headers:h.headers,status:h.status,statusText:h.statusText})}finally{r==null||r.removeEventListener("abort",c)}});var S=class extends Error{constructor(n,r){super(r);this.code=n;this.name="SiteRuntimeInvocationError"}},Be=t=>typeof t=="string"&&t.trim().length>0,Mt=t=>typeof File!="undefined"&&t instanceof File,qe=12e4,Pt=2*60*60*1e3,je=0,Ft=()=>typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():(je+=1,`site-upload-${je}`),wt=t=>typeof t=="object"&&t!==null&&"code"in t?t.code:void 0,Ht=t=>{if(t instanceof Error&&t.message)return t.message;if(typeof t=="object"&&t!==null){if("message"in t&&typeof t.message=="string")return t.message;if("msg"in t&&typeof t.msg=="string")return t.msg}return String(t)},Nt=new Set([u.AttachmentUnavailable,u.AttachmentUploadCanceled,u.AttachmentUploadFailed,u.AttachmentUploadStalled,u.InvalidAttachmentTarget]),Lt=(t,e)=>{if(t instanceof S)return t;let n=wt(t),r=Ht(t);return String(n)===String(10004)?new S(u.AttachmentUnavailable,r):typeof n=="string"&&Nt.has(n)?new S(n,r):new S(e,r)},B=(t,e,n)=>p(void 0,null,function*(){if(!Ue(e))throw new S(u.InvalidFunctionName,"Function name must be a dot-separated path beginning with function (for example, function.orders.list)");return t.invokeApi(g.FunctionInvoke,{functionName:e,params:n})}),q=class{constructor(e){this.channel=e;this.uploadAttachment=r=>p(this,null,function*(){var i=r,{onProgress:e}=i,n=Te(i,["onProgress"]);if(!Be(n==null?void 0:n.baseToken)||!Be(n==null?void 0:n.tableId)||!Mt(n==null?void 0:n.file))throw new S(u.InvalidAttachmentTarget,"Attachment upload requires nonempty baseToken and tableId values and a File");let o=Ft(),s,d=()=>{},c=()=>{this.channel.invokeApi(g.AttachmentUploadCancel,{uploadId:o}).catch(()=>{})},m=new Promise((h,x)=>{let H=()=>{clearTimeout(s),s=setTimeout(()=>{c(),x(new S(u.AttachmentUploadStalled,`Attachment upload made no progress for more than ${qe/1e3} seconds`))},qe)};d=this.channel.subscribeEvent(y.AttachmentUploadProgress,T=>{(T==null?void 0:T.uploadId)===o&&(H(),Promise.resolve(e==null?void 0:e(T)).catch(()=>{console.error("[base-site-channel][runtime] Attachment progress callback failed")}))})});try{return yield Promise.race([this.channel.invokeApi(g.AttachmentUpload,f(a({},n),{uploadId:o}),{timeoutMs:Pt}),m])}catch(h){throw Lt(h,u.AttachmentUploadFailed)}finally{clearTimeout(s),d()}});this.invokeHttp=e=>De(this.channel,e);this.invokeApi=(e,n)=>B(this.channel,e,n);this.getRuntimeContext=()=>this.channel.invokeApi(g.RuntimeContext,void 0);this.getCurrentUser=()=>B(this.channel,D.GetCurrentUser,void 0);this.logout=()=>B(this.channel,D.Logout,void 0);this.requestEdit=()=>B(this.channel,D.RequestEdit,void 0);this.ready=()=>this.channel.emitEvent(y.LifecycleReady,{protocolVersion:Oe});this.reportLoadFailed=e=>this.channel.emitEvent(y.LifecycleLoadFailed,{code:e});this.subscribeModeChanged=e=>this.channel.subscribeEvent(y.ModeChanged,({mode:n})=>e(n))}},j=(t=k)=>new q(t),v=j(),Ot=v.invokeHttp,Ut=v.invokeApi,Dt=v.getCurrentUser,Bt=v.logout,qt=v.requestEdit,jt=v.uploadAttachment;var Kt=new Set(["open.feishu.cn","open.feishu-pre.cn","open.feishu-boe.cn"]),Ke="/open-apis",Vt="/base-site/api/openapi",zt=new Set(["DELETE","GET","PATCH","POST","PUT"]),Wt=()=>(typeof globalThis.location=="undefined"?"":globalThis.location.pathname).replace(/^\/+/,"").startsWith("preview")?[["x-project-env","preview"]]:[],$t=t=>{if(typeof Request!="undefined"&&t instanceof Request)throw new TypeError("Site Runtime fetch does not accept a Request object; pass a URL instead");let e=String(t);if(e.startsWith("//"))throw new TypeError("Site Runtime fetch does not accept a scheme-relative URL");if(e.startsWith("/"))return e;let n=new URL(e);if(Kt.has(n.hostname)&&n.pathname.startsWith(Ke))return`${Vt}${n.pathname.slice(Ke.length)}${n.search}`;throw new TypeError("Site Runtime fetch accepts only relative business paths or supported Feishu OpenAPI URLs")},Yt=t=>{let e=new Headers(t);Wt().forEach(([r,i])=>e.set(r,i));let n={};return e.forEach((r,i)=>{n[i]=r}),n},Gt=(t,e)=>{var r,i,o;let n=(i=(r=t==null?void 0:t.method)==null?void 0:r.toUpperCase())!=null?i:"GET";if(!zt.has(n))throw new TypeError(`Site Runtime fetch does not support the ${n} method`);if((t==null?void 0:t.body)!==void 0&&t.body!==null&&typeof t.body!="string")throw new TypeError("Site Runtime fetch requires a string request body");if((o=t==null?void 0:t.signal)!=null&&o.aborted)throw new DOMException("The operation was aborted","AbortError");return{body:typeof(t==null?void 0:t.body)=="string"?t.body:void 0,headers:Yt(t==null?void 0:t.headers),method:n,timeoutMs:e}},K=(t=v,e)=>(n,r)=>t.invokeHttp(f(a({init:Gt(r,e)},r!=null&&r.signal?{signal:r.signal}:{}),{url:$t(n)})),Jt=K();var Ve=0,Xt=()=>typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():(Ve+=1,`site-chatbot-${Ve}`),V=(t,e)=>{try{t==null||t(e)}catch(n){console.error("[base-site-channel][runtime] Chatbot callback failed")}},P=class extends Error{constructor(n,r){super(`Chatbot stream error: ${n}`);this.code=n;this.retryable=r;this.name="SiteChatbotStreamError"}},ne=class{constructor(e){this.options=e;this.init=e=>{this.destroy();let n=Xt(),r={lastSeq:0,subscriptionId:n,unsubscribeError:()=>{},unsubscribeMessage:()=>{}};r.unsubscribeMessage=this.channel.subscribeEvent(y.StreamMessage,i=>{i.subscriptionId!==n||i.seq<=r.lastSeq||(i.seq>r.lastSeq+1&&V(this.onErrorCallback,new P(u.StreamSeqGap,!0)),r.lastSeq=i.seq,V(this.onMessageCallback,i.data))}),r.unsubscribeError=this.channel.subscribeEvent(y.StreamError,i=>{i.subscriptionId===n&&V(this.onErrorCallback,new P(i.code,i.retryable))}),this.current=r,this.channel.invokeApi(g.StreamOpen,{chatbotId:this.options.chatbotId,subscriptionId:n,threadId:e}).catch(()=>{var i;((i=this.current)==null?void 0:i.subscriptionId)===n&&V(this.onErrorCallback,new P(u.StreamOpenFailed,!0))})};this.onMessage=e=>{this.onMessageCallback=e};this.onError=e=>{this.onErrorCallback=e};this.destroy=()=>{let e=this.current;e&&(e.unsubscribeMessage(),e.unsubscribeError(),this.current=void 0,this.channel.invokeApi(g.StreamClose,{subscriptionId:e.subscriptionId}).catch(()=>console.error("[base-site-channel][runtime] Chatbot stream close failed")))};var n;this.channel=(n=e.channel)!=null?n:k}};var ie="prod",ze=0,Ye=()=>typeof crypto!="undefined"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():(ze+=1,`site-ai-fn-${ze}`),E=(t,e)=>{try{t==null||t(e)}catch(n){console.error("[base-site-channel][runtime] AI function callback failed")}},l=(t,e)=>{let n=new Error(e||`AI function error: ${t}`);return n.name="SiteAIFunctionError",n.code=t,n},Ge=()=>l(u.InvalidHttpUrl,"siteToken is required to invoke site AI function"),oe=()=>typeof window!="undefined"&&window.parent!==window,se=t=>{if(typeof queueMicrotask=="function"){queueMicrotask(t);return}Promise.resolve().then(t)},ae=t=>{let e={data:[],event:"message"};for(let n of t.split(/\r?\n/))n.startsWith("event:")?e.event=n.slice(6).trim():n.startsWith("data:")&&e.data.push(n.slice(5).trimStart());return e},re=(t,e)=>{for(let n of e){let r=t[n];if(typeof r=="string")return r}},Je=t=>{let e=[t];if(t&&typeof t=="object"){let n=t;e.push(n.response,n.data)}for(let n of e){if(!n||typeof n!="object")continue;let r=re(n,["request_id","requestId","RequestID","id"]);if(r)return r}},Xe=t=>{if(!t||typeof t!="object")return{};let e=t;return{content:re(e,["content","text","answer"]),reasoningContent:re(e,["reasoning_content","reasoningContent","reasoning"])}},Qt=t=>{if(!t||typeof t!="object")return{};let e=t.choices;if(!Array.isArray(e))return{};for(let n of e){let r=n.delta,{content:i,reasoningContent:o}=Xe(r);if(i!==void 0||o!==void 0)return{content:i,reasoningContent:o}}return{}},Qe=t=>{var n;let e=[t];if(t&&typeof t=="object"){let r=t;e.push(r.response,r.data)}for(let r of e){let i=Qt(r);if(i.content!==void 0||i.reasoningContent!==void 0)return i;let o=Xe(r&&typeof r=="object"&&(n=r.delta)!=null?n:r);if(o.content!==void 0||o.reasoningContent!==void 0)return o}return{}},z=t=>{try{let e=JSON.parse(t),n=Qe(e),r=Je(e);return f(a(a(a({},n.content!==void 0?{content:n.content}:{}),n.reasoningContent!==void 0?{reasoningContent:n.reasoningContent}:{}),r?{requestId:r}:{}),{raw:e})}catch(e){return{content:t,raw:t}}},Ze=t=>{if(typeof t=="string")return z(t);let e=Qe(t),n=Je(t),r=t&&typeof t=="object"&&"raw"in t?t.raw:t;return f(a(a(a({},e.content!==void 0?{content:e.content}:{}),e.reasoningContent!==void 0?{reasoningContent:e.reasoningContent}:{}),n?{requestId:n}:{}),{raw:r})},Zt=t=>{var e,n;try{let r=JSON.parse(t),i=(e=r.Code)!=null?e:r.code,o=(n=r.Message)!=null?n:r.message,s=typeof i=="string"||typeof i=="number"?String(i):"STREAM_FAILED";return l(s||"STREAM_FAILED",typeof o=="string"&&o?o:t)}catch(r){return l("STREAM_FAILED",t)}},ce=()=>({text:""}),en=t=>/(^|\n)(data|event|id|retry):/.test(t),We=t=>{if(!t||t==="[DONE]")return!!t;try{return JSON.parse(t),!0}catch(e){return!1}},tn=t=>{if(t){if(en(t)){let n=ae(t).data.join(`
|
|
2
2
|
`);return We(n)?n:void 0}return We(t)?t:void 0}},de=(t,e)=>{var o;t.text+=e;let n=t.text.split(/\r?\n\r?\n/);t.text=(o=n.pop())!=null?o:"";let r=n.map(s=>ae(s).data.join(`
|
|
3
3
|
`)).filter(Boolean),i=tn(t.text);return i!==void 0&&(r.push(i),t.text=""),r},nn=(t,e)=>t==="[DONE]"?(E(e.onDone,void 0),!0):(E(e.onMessage,z(t)),!1),$e=(t,e,n)=>{let r=ae(t);if(r.data.length===0)return!1;let i=r.data.join(`
|
|
4
|
-
`);if(r.event==="error")return E(n.onError,Zt(i)),!0;for(let o of de(e,i))if(nn(o,n))return!0;return!1},et=(t,e)=>p(void 0,null,function*(){var s;if(!t.body)throw l(u.StreamUnavailable,"SSE body missing");let n=t.body.getReader(),r=new TextDecoder,i=ce(),o="";try{for(;;){let{done:d,value:c}=yield n.read();o+=r.decode(c,{stream:!d});let m=o.split(/\r?\n\r?\n/);o=(s=m.pop())!=null?s:"";for(let h of m)if($e(h,i,e))return;if(d){if(o&&$e(o,i,e))return;E(e.onError,l(u.StreamInterrupted,"SSE stream ended without [DONE]"));return}}}finally{n.releaseLock()}}),ue=()=>{var n;let t=typeof globalThis.location=="undefined"?"":globalThis.location.pathname,e=/^\/?(preview\/)?app\/([^/]+)(\/|$)/.exec(t);return e?{env:e[1]?"preview":ie,siteToken:decodeURIComponent((n=e[2])!=null?n:"")}:{}},tt=(t,e,n)=>{if(!t.startsWith("/")||t.startsWith("//"))throw l(u.InvalidHttpUrl,"AI function endpoint must be a same-origin relative path");let r=t.replace("{siteToken}",encodeURIComponent(e.siteToken)).replace(":token",encodeURIComponent(e.siteToken)).replace("{functionKey}","").replace(":function_key",""),i=new URL(r,"https://base.site");if(i.searchParams.set("env",e.env),n)for(let[o,s]of Object.entries(n))i.searchParams.set(o,s);return`${i.pathname}${i.search}`};var rn="/space/api/bitable/streaming/site/v1/:token/ai_functions/:function_key/invoke",rt="/space/api/bitable/site/v1/:token/ai_functions/:function_key/tasks",on=6e4,sn=/^([1-9][0-9]{1,4})x([1-9][0-9]{1,4})$/i,an=3686400,cn=16777216,dn=14,un=t=>{let e=t.trim().replace("\xD7","x");if(/^[234]K$/i.test(e))return!0;let n=sn.exec(e);if(!n)return!1;let r=Number(n[1]),i=Number(n[2]),o=r*i;return o>=an&&o<=cn&&r<=i*16&&i<=r*16},ln=t=>{if(!t)return;let e=typeof t.image=="string"?[t.image]:t.image;if(e&&(e.length<1||e.length>dn||e.some(n=>!n.trim())))throw l(u.InvalidAIFunctionTask,"input.image must contain 1 to 14 non-empty strings");if(t.size!==void 0&&!un(t.size))throw l(u.InvalidAIFunctionTask,"input.size must follow the Seedream 5.0 lite size limits")},fe=t=>{var n;let e=(n=t.siteToken)==null?void 0:n.trim();return a(a(a({},t.env?{env:t.env}:{}),t.requestId?{requestId:t.requestId}:{}),e?{siteToken:e}:{})},ge=t=>{var r,i,o;let e=ue(),n=((r=t.siteToken)==null?void 0:r.trim())||e.siteToken;if(!n)throw Ge();return{env:(o=(i=t.env)!=null?i:e.env)!=null?o:ie,requestId:t.requestId,siteToken:n}},Ie=(t,e,n)=>tt(t.replace(":function_key",encodeURIComponent(e)),n),it=t=>f(a({},t.requestId?{"X-Request-Id":t.requestId}:{}),{Accept:"application/json","Content-Type":"application/json"}),ot=t=>{var e;return!t.channel&&!oe()?globalThis.fetch:K(j((e=t.channel)!=null?e:R),on)},pe=class{constructor(e,n){this.params=e;this.context=n;this.callbacks={};this.controller=new AbortController;this.closed=!1;this.onMessage=e=>{this.callbacks.onMessage=e};this.onError=e=>{this.callbacks.onError=e};this.onDone=e=>{this.callbacks.onDone=e};this.destroy=()=>{this.closed||(this.closed=!0,this.controller.abort())};se(()=>{this.start()})}start(){return p(this,null,function*(){var e;if(!this.closed)try{let n=yield fetch(Ie(rn,this.params.functionKey,this.context),{body:JSON.stringify({messages:this.params.messages,variables:(e=this.params.variables)!=null?e:{}}),credentials:"include",headers:f(a({},this.context.requestId?{"X-Request-Id":this.context.requestId}:{}),{Accept:"text/event-stream","Content-Type":"application/json"}),method:"POST",signal:this.controller.signal});if(!n.ok)throw l("HTTP_ERROR",`${n.status} ${n.statusText}`);yield et(n,this.callbacks)}catch(n){this.closed||E(this.callbacks.onError,n instanceof Error?n:l("STREAM_FAILED"))}})}},he=class{constructor(e){this.options=e;this.closed=!1;this.onMessage=e=>{this.onMessageCallback=e};this.onError=e=>{this.onErrorCallback=e};this.onDone=e=>{this.onDoneCallback=e};this.destroy=()=>{this.closed=!0;let e=this.current;e&&(this.cleanup(),this.channel.invokeApi(g.AIFunctionStreamClose,{subscriptionId:e.subscriptionId}).catch(()=>console.error("[base-site-channel][runtime] AI function stream close failed")))};var n;this.channel=(n=e.channel)!=null?n:R,se(()=>this.init())}init(){var i;if(this.closed)return;this.cleanup();let e=Ye(),n={lastSeq:0,subscriptionId:e,unsubscribeDone:()=>{},unsubscribeError:()=>{},unsubscribeMessage:()=>{},upstream:ce()};n.unsubscribeMessage=this.channel.subscribeEvent(y.AIFunctionStreamMessage,o=>this.handleMessage(o,n)),n.unsubscribeError=this.channel.subscribeEvent(y.AIFunctionStreamError,o=>this.handleError(o,e)),n.unsubscribeDone=this.channel.subscribeEvent(y.AIFunctionStreamDone,o=>this.handleDone(o,e)),this.current=n;let r=a(a(a({functionKey:this.options.params.functionKey,messages:this.options.params.messages,subscriptionId:e,variables:(i=this.options.params.variables)!=null?i:{}},this.options.context.env?{env:this.options.context.env}:{}),this.options.context.requestId?{requestId:this.options.context.requestId}:{}),this.options.context.siteToken?{siteToken:this.options.context.siteToken}:{});this.channel.invokeApi(g.AIFunctionStreamOpen,r).catch(()=>{var o;((o=this.current)==null?void 0:o.subscriptionId)===e&&E(this.onErrorCallback,l(u.StreamOpenFailed))})}handleMessage(e,n){if(e.subscriptionId===n.subscriptionId&&!(e.seq<=n.lastSeq)){if(e.seq>n.lastSeq+1&&E(this.onErrorCallback,l(u.StreamSeqGap)),n.lastSeq=e.seq,typeof e.data!="string"){E(this.onMessageCallback,Ze(e.data));return}de(n.upstream,e.data).forEach(r=>{r!=="[DONE]"&&E(this.onMessageCallback,z(r))})}}handleError(e,n){e.subscriptionId===n&&(E(this.onErrorCallback,l(e.code,e.message)),this.cleanup())}handleDone(e,n){e.subscriptionId===n&&(E(this.onDoneCallback,void 0),this.cleanup())}cleanup(){let e=this.current;e&&(e.unsubscribeMessage(),e.unsubscribeError(),e.unsubscribeDone(),this.current=void 0)}},st=(t,e={})=>{var r;if(!((r=t.functionKey)!=null&&r.trim()))throw l(u.InvalidFunctionName,"functionKey is required");let n=a(a({},ue()),fe(e));return e.channel||oe()?new he({channel:e.channel,context:n,params:t}):new pe(t,ge(e))},pn=t=>p(void 0,null,function*(){if(!t.ok){let e=yield t.text().catch(()=>"");throw l("HTTP_ERROR",`${t.status} ${t.statusText} ${e}`)}try{return yield t.json()}catch(e){throw l(u.InvalidAIFunctionTask,"AI function task response is invalid")}}),w=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),hn=t=>t==="cancelled"||t==="failed"||t==="queued"||t==="running"||t==="succeeded",I=(t,e)=>{for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}},mn=(t,e)=>{for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r}},fn=t=>{let e=I(t,["capabilityType","capability_type","CapabilityType"]);return e==="image"||e==="video"?e:void 0},gn=t=>{if(Array.isArray(t))return t.filter(w).map(e=>{var o;let n=I(e,["size","Size"]),r=I(e,["token","Token"]),i=I(e,["url","URL"]);return a(a(a({safetyStatus:(o=I(e,["safetyStatus","safety_status","SafetyStatus"]))!=null?o:""},n?{size:n}:{}),r?{token:r}:{}),i?{url:i}:{})})},In=t=>{var i,o;if(!w(t))return;let e=(o=(i=t.durationSeconds)!=null?i:t.duration_seconds)!=null?o:t.DurationSeconds,n=I(t,["token","Token"]),r=I(t,["url","URL"]);return a(a(a({},typeof e=="number"?{durationSeconds:e}:{}),n?{token:n}:{}),r?{url:r}:{})},le=t=>{var x,H,T,Se,ye,Ee;if(!w(t))throw l(u.InvalidAIFunctionTask,"AI function task response is invalid");let e=I(t,["type","Type"]),n=I(t,["taskId","task_id","TaskID"]),r=(x=t.status)!=null?x:t.Status;if(e!=="image_task"&&e!=="video_task"||!n||!hn(r))throw l(u.InvalidAIFunctionTask,"AI function task response is invalid");let i=(H=I(t,["requestId","request_id","RequestID"]))!=null?H:"",o=mn(t,["progress","Progress"]),s=fn(t),d=I(t,["errCode","err_code","ErrCode"]),c=I(t,["errMessage","err_message","ErrMessage"]),m=gn((Se=(T=t.imageAssets)!=null?T:t.image_assets)!=null?Se:t.ImageAssets),h=In((Ee=(ye=t.videoAsset)!=null?ye:t.video_asset)!=null?Ee:t.VideoAsset);return f(a(a(a(a(a(a({},s?{capabilityType:s}:{}),d?{errCode:d}:{}),c?{errMessage:c}:{}),m?{imageAssets:m}:{}),o!==void 0?{progress:o}:{}),h?{videoAsset:h}:{}),{requestId:i,status:r,taskId:n,type:e})},Sn=t=>{var i,o,s,d,c,m,h;let e=(i=t.code)!=null?i:t.Code;if(typeof e=="number"&&e!==0||typeof e=="string"&&e&&e!=="0")return{code:String(e),message:(o=I(t,["msg","message","Message"]))!=null?o:"AI function task failed"};let n=(d=(s=t.BaseResp)!=null?s:t.base_resp)!=null?d:t.baseResp;if(!w(n))return;let r=(m=(c=n.StatusCode)!=null?c:n.status_code)!=null?m:n.statusCode;if(typeof r=="number"&&r!==0||typeof r=="string"&&r&&r!=="0")return{code:String(r),message:(h=I(n,["StatusMessage","status_message","statusMessage"]))!=null?h:"AI function task failed"}},yn=t=>{if(!w(t))return le(t);let e=Sn(t);if(e)throw l(e.code,e.message);return"data"in t&&t.data!==void 0?le(t.data):le(t)},at=t=>p(void 0,null,function*(){return yn(yield pn(t))}),me=(n,...r)=>p(void 0,[n,...r],function*(t,e={}){var s,d,c;if(!((s=t.functionKey)!=null&&s.trim()))throw l(u.InvalidFunctionName,"functionKey is required");t.capability==="image"&&ln(t.input);let i=ge(a(a({},e),fe(e))),o=yield ot(e)(Ie(rt,t.functionKey,i),{body:JSON.stringify({input:(d=t.input)!=null?d:{},variables:(c=t.variables)!=null?c:{}}),credentials:"include",headers:it(i),method:"POST"});return at(o)}),En=(r,i,...o)=>p(void 0,[r,i,...o],function*(t,e,n={}){if(!(t!=null&&t.trim()))throw l(u.InvalidFunctionName,"functionKey is required");if(typeof e!="string"||!e.trim())throw l(u.InvalidAIFunctionTask,"taskId is required");let s=ge(a(a({},n),fe(n))),d=Ie(rt,t,s),c=d.includes("?")?`${d.replace("?",`/${encodeURIComponent(e)}?`)}`:`${d}/${encodeURIComponent(e)}`,m=yield ot(n)(c,{credentials:"include",headers:it(s),method:"GET"});return at(m)}),nt=(t,e)=>new Promise((n,r)=>{var d;let i="",o="",s=st({functionKey:t.functionKey,messages:(d=t.messages)!=null?d:[],variables:t.variables},e);s.onMessage(c=>{typeof c.content=="string"&&(i+=c.content),!o&&typeof c.requestId=="string"&&c.requestId&&(o=c.requestId)}),s.onError(c=>{s.destroy(),r(c)}),s.onDone(()=>{s.destroy(),n({content:i,requestId:o||e.requestId||"",type:"text"})})}),An=(n,...r)=>p(void 0,[n,...r],function*(t,e={}){var i;if(!((i=t.functionKey)!=null&&i.trim()))throw l(u.InvalidFunctionName,"functionKey is required");return t.capability==="image"||t.capability==="video"?me(t,e):t.capability==="text"||t.capability==="vision"?nt(t,e):t.input&&!t.messages?me(t,e):nt(t,e)});export{Oe as SITE_RUNTIME_PROTOCOL_VERSION,ne as SiteChatbotStreamAdapter,P as SiteChatbotStreamError,g as SiteRuntimeApi,q as SiteRuntimeClient,u as SiteRuntimeErrorCode,y as SiteRuntimeEvent,D as SiteRuntimeFunction,S as SiteRuntimeInvocationError,An as callSiteAIFunction,me as createSiteAIFunctionTask,j as createSiteRuntimeClient,K as createSiteRuntimeFetch,Jt as fetch,Dt as getCurrentUser,En as getSiteAIFunctionTask,Ut as invokeApi,Ot as invokeHttp,st as invokeSiteAIFunctionStream,Ue as isValidSiteFunctionName,Bt as logout,xr as readSiteAITextDelta,qt as requestEdit,v as siteRuntime,jt as uploadAttachment};
|
|
4
|
+
`);if(r.event==="error")return E(n.onError,Zt(i)),!0;for(let o of de(e,i))if(nn(o,n))return!0;return!1},et=(t,e)=>p(void 0,null,function*(){var s;if(!t.body)throw l(u.StreamUnavailable,"SSE body missing");let n=t.body.getReader(),r=new TextDecoder,i=ce(),o="";try{for(;;){let{done:d,value:c}=yield n.read();o+=r.decode(c,{stream:!d});let m=o.split(/\r?\n\r?\n/);o=(s=m.pop())!=null?s:"";for(let h of m)if($e(h,i,e))return;if(d){if(o&&$e(o,i,e))return;E(e.onError,l(u.StreamInterrupted,"SSE stream ended without [DONE]"));return}}}finally{n.releaseLock()}}),ue=()=>{var n;let t=typeof globalThis.location=="undefined"?"":globalThis.location.pathname,e=/^\/?(preview\/)?app\/([^/]+)(\/|$)/.exec(t);return e?{env:e[1]?"preview":ie,siteToken:decodeURIComponent((n=e[2])!=null?n:"")}:{}},tt=(t,e,n)=>{if(!t.startsWith("/")||t.startsWith("//"))throw l(u.InvalidHttpUrl,"AI function endpoint must be a same-origin relative path");let r=t.replace("{siteToken}",encodeURIComponent(e.siteToken)).replace(":token",encodeURIComponent(e.siteToken)).replace("{functionKey}","").replace(":function_key",""),i=new URL(r,"https://base.site");if(i.searchParams.set("env",e.env),n)for(let[o,s]of Object.entries(n))i.searchParams.set(o,s);return`${i.pathname}${i.search}`};var rn="/space/api/bitable/streaming/site/v1/:token/ai_functions/:function_key/invoke",rt="/space/api/bitable/site/v1/:token/ai_functions/:function_key/tasks",on=6e4,sn=/^([1-9][0-9]{1,4})x([1-9][0-9]{1,4})$/i,an=3686400,cn=16777216,dn=14,un=t=>{let e=t.trim().replace("\xD7","x");if(/^[234]K$/i.test(e))return!0;let n=sn.exec(e);if(!n)return!1;let r=Number(n[1]),i=Number(n[2]),o=r*i;return o>=an&&o<=cn&&r<=i*16&&i<=r*16},ln=t=>{if(!t)return;let e=typeof t.image=="string"?[t.image]:t.image;if(e&&(e.length<1||e.length>dn||e.some(n=>!n.trim())))throw l(u.InvalidAIFunctionTask,"input.image must contain 1 to 14 non-empty strings");if(t.size!==void 0&&!un(t.size))throw l(u.InvalidAIFunctionTask,"input.size must follow the Seedream 5.0 lite size limits")},fe=t=>{var n;let e=(n=t.siteToken)==null?void 0:n.trim();return a(a(a({},t.env?{env:t.env}:{}),t.requestId?{requestId:t.requestId}:{}),e?{siteToken:e}:{})},ge=t=>{var r,i,o;let e=ue(),n=((r=t.siteToken)==null?void 0:r.trim())||e.siteToken;if(!n)throw Ge();return{env:(o=(i=t.env)!=null?i:e.env)!=null?o:ie,requestId:t.requestId,siteToken:n}},Ie=(t,e,n)=>tt(t.replace(":function_key",encodeURIComponent(e)),n),it=t=>f(a({},t.requestId?{"X-Request-Id":t.requestId}:{}),{Accept:"application/json","Content-Type":"application/json"}),ot=t=>{var e;return!t.channel&&!oe()?globalThis.fetch:K(j((e=t.channel)!=null?e:k),on)},pe=class{constructor(e,n){this.params=e;this.context=n;this.callbacks={};this.controller=new AbortController;this.closed=!1;this.onMessage=e=>{this.callbacks.onMessage=e};this.onError=e=>{this.callbacks.onError=e};this.onDone=e=>{this.callbacks.onDone=e};this.destroy=()=>{this.closed||(this.closed=!0,this.controller.abort())};se(()=>{this.start()})}start(){return p(this,null,function*(){var e;if(!this.closed)try{let n=yield fetch(Ie(rn,this.params.functionKey,this.context),{body:JSON.stringify({messages:this.params.messages,variables:(e=this.params.variables)!=null?e:{}}),credentials:"include",headers:f(a({},this.context.requestId?{"X-Request-Id":this.context.requestId}:{}),{Accept:"text/event-stream","Content-Type":"application/json"}),method:"POST",signal:this.controller.signal});if(!n.ok)throw l("HTTP_ERROR",`${n.status} ${n.statusText}`);yield et(n,this.callbacks)}catch(n){this.closed||E(this.callbacks.onError,n instanceof Error?n:l("STREAM_FAILED"))}})}},he=class{constructor(e){this.options=e;this.closed=!1;this.onMessage=e=>{this.onMessageCallback=e};this.onError=e=>{this.onErrorCallback=e};this.onDone=e=>{this.onDoneCallback=e};this.destroy=()=>{this.closed=!0;let e=this.current;e&&(this.cleanup(),this.channel.invokeApi(g.AIFunctionStreamClose,{subscriptionId:e.subscriptionId}).catch(()=>console.error("[base-site-channel][runtime] AI function stream close failed")))};var n;this.channel=(n=e.channel)!=null?n:k,se(()=>this.init())}init(){var i;if(this.closed)return;this.cleanup();let e=Ye(),n={lastSeq:0,subscriptionId:e,unsubscribeDone:()=>{},unsubscribeError:()=>{},unsubscribeMessage:()=>{},upstream:ce()};n.unsubscribeMessage=this.channel.subscribeEvent(y.AIFunctionStreamMessage,o=>this.handleMessage(o,n)),n.unsubscribeError=this.channel.subscribeEvent(y.AIFunctionStreamError,o=>this.handleError(o,e)),n.unsubscribeDone=this.channel.subscribeEvent(y.AIFunctionStreamDone,o=>this.handleDone(o,e)),this.current=n;let r=a(a(a({functionKey:this.options.params.functionKey,messages:this.options.params.messages,subscriptionId:e,variables:(i=this.options.params.variables)!=null?i:{}},this.options.context.env?{env:this.options.context.env}:{}),this.options.context.requestId?{requestId:this.options.context.requestId}:{}),this.options.context.siteToken?{siteToken:this.options.context.siteToken}:{});this.channel.invokeApi(g.AIFunctionStreamOpen,r).catch(()=>{var o;((o=this.current)==null?void 0:o.subscriptionId)===e&&E(this.onErrorCallback,l(u.StreamOpenFailed))})}handleMessage(e,n){if(e.subscriptionId===n.subscriptionId&&!(e.seq<=n.lastSeq)){if(e.seq>n.lastSeq+1&&E(this.onErrorCallback,l(u.StreamSeqGap)),n.lastSeq=e.seq,typeof e.data!="string"){E(this.onMessageCallback,Ze(e.data));return}de(n.upstream,e.data).forEach(r=>{r!=="[DONE]"&&E(this.onMessageCallback,z(r))})}}handleError(e,n){e.subscriptionId===n&&(E(this.onErrorCallback,l(e.code,e.message)),this.cleanup())}handleDone(e,n){e.subscriptionId===n&&(E(this.onDoneCallback,void 0),this.cleanup())}cleanup(){let e=this.current;e&&(e.unsubscribeMessage(),e.unsubscribeError(),e.unsubscribeDone(),this.current=void 0)}},st=(t,e={})=>{var r;if(!((r=t.functionKey)!=null&&r.trim()))throw l(u.InvalidFunctionName,"functionKey is required");let n=a(a({},ue()),fe(e));return e.channel||oe()?new he({channel:e.channel,context:n,params:t}):new pe(t,ge(e))},pn=t=>p(void 0,null,function*(){if(!t.ok){let e=yield t.text().catch(()=>"");throw l("HTTP_ERROR",`${t.status} ${t.statusText} ${e}`)}try{return yield t.json()}catch(e){throw l(u.InvalidAIFunctionTask,"AI function task response is invalid")}}),w=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),hn=t=>t==="cancelled"||t==="failed"||t==="queued"||t==="running"||t==="succeeded",I=(t,e)=>{for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}},mn=(t,e)=>{for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r}},fn=t=>{let e=I(t,["capabilityType","capability_type","CapabilityType"]);return e==="image"||e==="video"?e:void 0},gn=t=>{if(Array.isArray(t))return t.filter(w).map(e=>{var o;let n=I(e,["size","Size"]),r=I(e,["token","Token"]),i=I(e,["url","URL"]);return a(a(a({safetyStatus:(o=I(e,["safetyStatus","safety_status","SafetyStatus"]))!=null?o:""},n?{size:n}:{}),r?{token:r}:{}),i?{url:i}:{})})},In=t=>{var i,o;if(!w(t))return;let e=(o=(i=t.durationSeconds)!=null?i:t.duration_seconds)!=null?o:t.DurationSeconds,n=I(t,["token","Token"]),r=I(t,["url","URL"]);return a(a(a({},typeof e=="number"?{durationSeconds:e}:{}),n?{token:n}:{}),r?{url:r}:{})},le=t=>{var x,H,T,Se,ye,Ee;if(!w(t))throw l(u.InvalidAIFunctionTask,"AI function task response is invalid");let e=I(t,["type","Type"]),n=I(t,["taskId","task_id","TaskID"]),r=(x=t.status)!=null?x:t.Status;if(e!=="image_task"&&e!=="video_task"||!n||!hn(r))throw l(u.InvalidAIFunctionTask,"AI function task response is invalid");let i=(H=I(t,["requestId","request_id","RequestID"]))!=null?H:"",o=mn(t,["progress","Progress"]),s=fn(t),d=I(t,["errCode","err_code","ErrCode"]),c=I(t,["errMessage","err_message","ErrMessage"]),m=gn((Se=(T=t.imageAssets)!=null?T:t.image_assets)!=null?Se:t.ImageAssets),h=In((Ee=(ye=t.videoAsset)!=null?ye:t.video_asset)!=null?Ee:t.VideoAsset);return f(a(a(a(a(a(a({},s?{capabilityType:s}:{}),d?{errCode:d}:{}),c?{errMessage:c}:{}),m?{imageAssets:m}:{}),o!==void 0?{progress:o}:{}),h?{videoAsset:h}:{}),{requestId:i,status:r,taskId:n,type:e})},Sn=t=>{var i,o,s,d,c,m,h;let e=(i=t.code)!=null?i:t.Code;if(typeof e=="number"&&e!==0||typeof e=="string"&&e&&e!=="0")return{code:String(e),message:(o=I(t,["msg","message","Message"]))!=null?o:"AI function task failed"};let n=(d=(s=t.BaseResp)!=null?s:t.base_resp)!=null?d:t.baseResp;if(!w(n))return;let r=(m=(c=n.StatusCode)!=null?c:n.status_code)!=null?m:n.statusCode;if(typeof r=="number"&&r!==0||typeof r=="string"&&r&&r!=="0")return{code:String(r),message:(h=I(n,["StatusMessage","status_message","statusMessage"]))!=null?h:"AI function task failed"}},yn=t=>{if(!w(t))return le(t);let e=Sn(t);if(e)throw l(e.code,e.message);return"data"in t&&t.data!==void 0?le(t.data):le(t)},at=t=>p(void 0,null,function*(){return yn(yield pn(t))}),me=(n,...r)=>p(void 0,[n,...r],function*(t,e={}){var s,d,c;if(!((s=t.functionKey)!=null&&s.trim()))throw l(u.InvalidFunctionName,"functionKey is required");t.capability==="image"&&ln(t.input);let i=ge(a(a({},e),fe(e))),o=yield ot(e)(Ie(rt,t.functionKey,i),{body:JSON.stringify({input:(d=t.input)!=null?d:{},variables:(c=t.variables)!=null?c:{}}),credentials:"include",headers:it(i),method:"POST"});return at(o)}),En=(r,i,...o)=>p(void 0,[r,i,...o],function*(t,e,n={}){if(!(t!=null&&t.trim()))throw l(u.InvalidFunctionName,"functionKey is required");if(typeof e!="string"||!e.trim())throw l(u.InvalidAIFunctionTask,"taskId is required");let s=ge(a(a({},n),fe(n))),d=Ie(rt,t,s),c=d.includes("?")?`${d.replace("?",`/${encodeURIComponent(e)}?`)}`:`${d}/${encodeURIComponent(e)}`,m=yield ot(n)(c,{credentials:"include",headers:it(s),method:"GET"});return at(m)}),nt=(t,e)=>new Promise((n,r)=>{var d;let i="",o="",s=st({functionKey:t.functionKey,messages:(d=t.messages)!=null?d:[],variables:t.variables},e);s.onMessage(c=>{typeof c.content=="string"&&(i+=c.content),!o&&typeof c.requestId=="string"&&c.requestId&&(o=c.requestId)}),s.onError(c=>{s.destroy(),r(c)}),s.onDone(()=>{s.destroy(),n({content:i,requestId:o||e.requestId||"",type:"text"})})}),An=(n,...r)=>p(void 0,[n,...r],function*(t,e={}){var i;if(!((i=t.functionKey)!=null&&i.trim()))throw l(u.InvalidFunctionName,"functionKey is required");return t.capability==="image"||t.capability==="video"?me(t,e):t.capability==="text"||t.capability==="vision"?nt(t,e):t.input&&!t.messages?me(t,e):nt(t,e)});export{Oe as SITE_RUNTIME_PROTOCOL_VERSION,ne as SiteChatbotStreamAdapter,P as SiteChatbotStreamError,g as SiteRuntimeApi,q as SiteRuntimeClient,u as SiteRuntimeErrorCode,y as SiteRuntimeEvent,D as SiteRuntimeFunction,S as SiteRuntimeInvocationError,An as callSiteAIFunction,me as createSiteAIFunctionTask,j as createSiteRuntimeClient,K as createSiteRuntimeFetch,Jt as fetch,Dt as getCurrentUser,En as getSiteAIFunctionTask,Ut as invokeApi,Ot as invokeHttp,st as invokeSiteAIFunctionStream,Ue as isValidSiteFunctionName,Bt as logout,xr as readSiteAITextDelta,qt as requestEdit,v as siteRuntime,jt as uploadAttachment};
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@lark-base-open/base-site-channel","version":"0.1.
|
|
1
|
+
{"name":"@lark-base-open/base-site-channel","version":"0.1.4","description":"","main":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.mjs"},"./runtime":{"types":"./dist/runtime.d.ts","import":"./dist/runtime.mjs"},"./runtime-contract":{"types":"./dist/runtime-contract.d.ts","import":"./dist/runtime-contract.mjs"}},"files":["dist"],"scripts":{"test":"npm run build && node --import tsx --test test/*.test.ts && npm run test:types","test:types":"tsc --noEmit --strict --skipLibCheck --module esnext --moduleResolution bundler --target es2022 test-types/function-map.ts","build":"tsup","dev":"NODE_ENV=development tsup --watch","upload:alpha":"pnpm build && npx @bitable/pack-dev-cli upload"},"keywords":[],"author":"","devDependencies":{"@types/node":"^22.15.0","tsup":"^6.7.0","tsx":"^4.20.3","typescript":"^5.8.3"},"dependencies":{"lodash-es":"^4.17.21"}}
|