@effect-agent/platform-cloudflare 0.1.0-beta.121 → 0.1.0-beta.122
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/dist/{InteractiveBrowser-DhOkdUx9.mjs → InteractiveBrowser-DXwmvWdA.mjs} +189 -48
- package/dist/InteractiveBrowser-DXwmvWdA.mjs.map +1 -0
- package/dist/InteractiveBrowser.mjs +1 -1
- package/dist/ProtectedBrowser.d.mts +14 -0
- package/dist/ProtectedBrowser.mjs +193 -152
- package/dist/ProtectedBrowser.mjs.map +1 -1
- package/package.json +1 -1
- package/src/InteractiveBrowser.ts +1 -1
- package/src/internal/browser-binding.ts +244 -56
- package/src/protected-browser/binding.ts +129 -50
- package/src/protected-browser/host.ts +16 -0
- package/dist/InteractiveBrowser-DhOkdUx9.mjs.map +0 -1
|
@@ -49,9 +49,41 @@ const reportBrowserCause = (operation, cause) => ErrorReporter.report(Cause.from
|
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/internal/browser-binding.ts
|
|
51
51
|
const Acquired = Schema.Struct({ sessionId: Schema.String.check(Schema.isUUID()) });
|
|
52
|
+
const VersionReply = Schema.fromJsonString(Schema.Struct({
|
|
53
|
+
id: Schema.optionalKey(Schema.Int),
|
|
54
|
+
result: Schema.optionalKey(Schema.Unknown),
|
|
55
|
+
error: Schema.optionalKey(Schema.Unknown)
|
|
56
|
+
}));
|
|
57
|
+
const Version = Schema.Struct({
|
|
58
|
+
product: Schema.NonEmptyString,
|
|
59
|
+
protocolVersion: Schema.NonEmptyString
|
|
60
|
+
});
|
|
52
61
|
/** Native transport port shared by both scoped adapters; the Layer owns the foreign binding. */
|
|
53
62
|
var BrowserRunBinding = class extends Context.Service()("@effect-agent/platform-cloudflare/internal/BrowserRunBinding") {
|
|
54
63
|
static layer(browser) {
|
|
64
|
+
const upgrade = async (sessionId, operation, signal) => {
|
|
65
|
+
const response = await browser.fetch(`https://browser-rendering.cloudflare.com/v1/devtools/browser/${sessionId}`, {
|
|
66
|
+
headers: { Upgrade: "websocket" },
|
|
67
|
+
...signal === void 0 ? {} : { signal }
|
|
68
|
+
});
|
|
69
|
+
if (response.status !== 101) {
|
|
70
|
+
const failure = new BrowserRunFailure({
|
|
71
|
+
operation,
|
|
72
|
+
reason: "provider",
|
|
73
|
+
status: response.status
|
|
74
|
+
});
|
|
75
|
+
try {
|
|
76
|
+
await response.body?.cancel();
|
|
77
|
+
} catch {}
|
|
78
|
+
throw failure;
|
|
79
|
+
}
|
|
80
|
+
const socket = response.webSocket;
|
|
81
|
+
if (socket === null) throw new BrowserRunFailure({
|
|
82
|
+
operation,
|
|
83
|
+
reason: "malformed"
|
|
84
|
+
});
|
|
85
|
+
return socket;
|
|
86
|
+
};
|
|
55
87
|
return Layer.succeed(this)({
|
|
56
88
|
acquire: async (keepAliveMillis, operation) => {
|
|
57
89
|
const response = await browser.fetch(`https://browser-rendering.cloudflare.com/v1/devtools/browser?keep_alive=${keepAliveMillis}&recording=false`, { method: "POST" });
|
|
@@ -68,62 +100,171 @@ var BrowserRunBinding = class extends Context.Service()("@effect-agent/platform-
|
|
|
68
100
|
}
|
|
69
101
|
return Schema.decodeUnknownSync(Acquired)(await response.json()).sessionId;
|
|
70
102
|
},
|
|
71
|
-
connect:
|
|
103
|
+
connect: (sessionId, operation, signal) => {
|
|
72
104
|
let socket;
|
|
105
|
+
let retired = false;
|
|
73
106
|
let closedByAbort = false;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (response.status !== 101) {
|
|
80
|
-
const failure = new BrowserRunFailure({
|
|
107
|
+
let retirementFailure;
|
|
108
|
+
const disconnectOperation = operation === "protected.connect" ? "protected.disconnect" : "interactive.disconnect";
|
|
109
|
+
const transport = {
|
|
110
|
+
send: (message) => {
|
|
111
|
+
if (retired || socket === void 0) throw new BrowserRunFailure({
|
|
81
112
|
operation,
|
|
82
|
-
reason: "provider"
|
|
83
|
-
status: response.status
|
|
113
|
+
reason: "provider"
|
|
84
114
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
socket.send(message);
|
|
116
|
+
},
|
|
117
|
+
close: () => retireNow()
|
|
118
|
+
};
|
|
119
|
+
const onMessage = (event) => {
|
|
120
|
+
if (!retired) transport.onmessage?.(event.data);
|
|
121
|
+
};
|
|
122
|
+
const fence = () => {
|
|
123
|
+
if (retired) return;
|
|
124
|
+
retired = true;
|
|
125
|
+
const notify = transport.onclose;
|
|
126
|
+
transport.onmessage = void 0;
|
|
127
|
+
transport.onclose = void 0;
|
|
128
|
+
try {
|
|
129
|
+
notify?.();
|
|
130
|
+
} finally {
|
|
131
|
+
socket?.removeEventListener("message", onMessage);
|
|
89
132
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
133
|
+
};
|
|
134
|
+
const retireNow = () => {
|
|
135
|
+
try {
|
|
136
|
+
fence();
|
|
137
|
+
} catch (cause) {
|
|
138
|
+
retirementFailure ??= browserFailure(disconnectOperation, cause);
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
if (socket !== void 0 && socket.readyState < WebSocket.CLOSING) socket.close();
|
|
142
|
+
} catch (cause) {
|
|
143
|
+
retirementFailure ??= browserFailure(disconnectOperation, cause);
|
|
144
|
+
}
|
|
145
|
+
if (retirementFailure !== void 0) throw retirementFailure;
|
|
146
|
+
};
|
|
147
|
+
const abort = () => {
|
|
148
|
+
closedByAbort = socket?.readyState === WebSocket.OPEN;
|
|
149
|
+
try {
|
|
150
|
+
retireNow();
|
|
151
|
+
} catch {}
|
|
152
|
+
};
|
|
153
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
154
|
+
return {
|
|
155
|
+
browser: (async () => {
|
|
156
|
+
try {
|
|
157
|
+
signal?.throwIfAborted();
|
|
158
|
+
socket = await upgrade(sessionId, operation, signal);
|
|
159
|
+
socket.accept();
|
|
160
|
+
if (retired || signal?.aborted) {
|
|
161
|
+
retireNow();
|
|
162
|
+
signal?.throwIfAborted();
|
|
163
|
+
throw new BrowserRunFailure({
|
|
164
|
+
operation,
|
|
165
|
+
reason: "provider"
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
socket.addEventListener("message", onMessage);
|
|
169
|
+
socket.addEventListener("close", () => {
|
|
170
|
+
try {
|
|
171
|
+
fence();
|
|
172
|
+
} catch (cause) {
|
|
173
|
+
retirementFailure ??= browserFailure(disconnectOperation, cause);
|
|
174
|
+
}
|
|
175
|
+
}, { once: true });
|
|
176
|
+
return await puppeteer.connect({ transport });
|
|
177
|
+
} catch (cause) {
|
|
178
|
+
try {
|
|
179
|
+
retireNow();
|
|
180
|
+
} catch {}
|
|
181
|
+
const failure = browserFailure(operation, cause);
|
|
182
|
+
throw cause instanceof Error && signal?.aborted === true && (cause === signal.reason || closedByAbort && cause.name === "TargetCloseError") ? reportedBrowserError(failure) : failure;
|
|
183
|
+
} finally {
|
|
184
|
+
signal?.removeEventListener("abort", abort);
|
|
185
|
+
}
|
|
186
|
+
})(),
|
|
187
|
+
retire: Effect.callback((resume) => {
|
|
188
|
+
const connected = socket;
|
|
189
|
+
const onClose = () => resume(Effect.void);
|
|
190
|
+
try {
|
|
191
|
+
retireNow();
|
|
192
|
+
if (connected === void 0 || connected.readyState === WebSocket.CLOSED) resume(Effect.void);
|
|
193
|
+
else connected.addEventListener("close", onClose, { once: true });
|
|
194
|
+
} catch (cause) {
|
|
195
|
+
resume(Effect.fail(browserFailure(disconnectOperation, cause)));
|
|
196
|
+
}
|
|
197
|
+
return Effect.sync(() => connected?.removeEventListener("close", onClose));
|
|
198
|
+
})
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
keepAlive: Effect.fnUntraced(function* (sessionId) {
|
|
202
|
+
const operation = "protected.keepAlive";
|
|
203
|
+
const runReport = Effect.runPromiseWith(yield* Effect.context());
|
|
204
|
+
const release = (socket) => Effect.sync(() => socket.close()).pipe(Effect.catchCause((cause) => reportBrowserCause(operation, cause)));
|
|
205
|
+
const socket = yield* Effect.acquireRelease(Effect.tryPromise({
|
|
206
|
+
try: async (signal) => {
|
|
207
|
+
let acquired;
|
|
208
|
+
try {
|
|
209
|
+
acquired = await upgrade(sessionId, operation, signal);
|
|
210
|
+
acquired.accept();
|
|
211
|
+
signal.throwIfAborted();
|
|
212
|
+
return acquired;
|
|
213
|
+
} catch (cause) {
|
|
214
|
+
if (acquired !== void 0) await runReport(release(acquired));
|
|
215
|
+
if (signal.aborted && cause !== signal.reason) await runReport(reportBrowserCause(operation, Cause.fail(cause)));
|
|
216
|
+
throw cause;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
catch: (cause) => browserFailure(operation, cause)
|
|
220
|
+
}), release, { interruptible: true });
|
|
221
|
+
yield* Effect.callback((resume) => {
|
|
222
|
+
const finish = (result) => {
|
|
223
|
+
removeListeners();
|
|
224
|
+
resume(result);
|
|
99
225
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const abort = () => {
|
|
226
|
+
const fail = (reason) => finish(Effect.fail(new BrowserRunFailure({
|
|
227
|
+
operation,
|
|
228
|
+
reason
|
|
229
|
+
})));
|
|
230
|
+
const onMessage = (event) => {
|
|
106
231
|
try {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
232
|
+
if (typeof event.data !== "string" || event.data.length > 16384) {
|
|
233
|
+
fail("malformed");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const reply = Schema.decodeSync(VersionReply)(event.data);
|
|
237
|
+
if (reply.id !== 1) return;
|
|
238
|
+
if (reply.error !== void 0) {
|
|
239
|
+
fail("provider");
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
Schema.decodeUnknownSync(Version)(reply.result);
|
|
243
|
+
finish(Effect.void);
|
|
244
|
+
} catch {
|
|
245
|
+
fail("malformed");
|
|
246
|
+
}
|
|
111
247
|
};
|
|
112
|
-
|
|
248
|
+
const onClose = () => fail("provider");
|
|
249
|
+
const removeListeners = () => {
|
|
250
|
+
socket.removeEventListener("message", onMessage);
|
|
251
|
+
socket.removeEventListener("close", onClose);
|
|
252
|
+
socket.removeEventListener("error", onClose);
|
|
253
|
+
};
|
|
254
|
+
socket.addEventListener("message", onMessage);
|
|
255
|
+
socket.addEventListener("close", onClose);
|
|
256
|
+
socket.addEventListener("error", onClose);
|
|
113
257
|
try {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
258
|
+
socket.send(JSON.stringify({
|
|
259
|
+
id: 1,
|
|
260
|
+
method: "Browser.getVersion"
|
|
261
|
+
}));
|
|
262
|
+
} catch (cause) {
|
|
263
|
+
finish(Effect.fail(browserFailure(operation, cause)));
|
|
118
264
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} catch {}
|
|
123
|
-
const failure = browserFailure(operation, cause);
|
|
124
|
-
throw cause instanceof Error && signal?.aborted === true && (cause === signal.reason || closedByAbort && cause.name === "TargetCloseError") ? reportedBrowserError(failure) : failure;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
265
|
+
return Effect.sync(removeListeners);
|
|
266
|
+
});
|
|
267
|
+
}, Effect.scoped)
|
|
127
268
|
});
|
|
128
269
|
}
|
|
129
270
|
};
|
|
@@ -443,7 +584,7 @@ var BrowserRunInteractiveBinding = class BrowserRunInteractiveBinding extends Co
|
|
|
443
584
|
const viewport = options.viewport === void 0 ? void 0 : yield* decodeViewport(options.viewport);
|
|
444
585
|
return {
|
|
445
586
|
acquire: async (keepAliveMillis) => binding.acquire(keepAliveMillis, "interactive.acquire"),
|
|
446
|
-
connect: async (sessionId, signal) => makeProductionBrowser(await binding.connect(sessionId, "interactive.connect", signal), sessionId, viewport),
|
|
587
|
+
connect: async (sessionId, signal) => makeProductionBrowser(await binding.connect(sessionId, "interactive.connect", signal).browser, sessionId, viewport),
|
|
447
588
|
closeSession: (sessionId) => lifecycle.close(sessionId).pipe(Effect.mapError((cause) => actionError("close", cause)))
|
|
448
589
|
};
|
|
449
590
|
})).pipe(Layer.provide(BrowserRunBinding.layer(options.browser)));
|
|
@@ -1777,4 +1918,4 @@ const CloudflareInteractiveBrowser = {
|
|
|
1777
1918
|
//#endregion
|
|
1778
1919
|
export { reportBrowserCause as C, inheritBrowserReport as S, BrowserRunCleanupError as _, BrowserRunInteractiveCheckpoint as a, BrowserRunFailure as b, BrowserRunLiveViewResult as c, BrowserRunViewport as d, CloudflareInteractiveBrowser as f, isBrowserRunUndispatchedActionError as g, browserRunInteractiveLayer as h, BrowserRunInteractiveBinding as i, BrowserRunPageIdentity as l, browserRunInteractiveImplementation as m, BrowserRunHandoffResult as n, BrowserRunInteractiveHost as o, browserRunInteractiveHostLayer as p, BrowserRunHandoffState as r, BrowserRunLiveViewRequest as s, BrowserRunHandoffRequest as t, BrowserRunPageObservation as u, BrowserRunSessionLifecycle as v, reportedBrowserError as w, browserFailure as x, BrowserRunBinding as y };
|
|
1779
1920
|
|
|
1780
|
-
//# sourceMappingURL=InteractiveBrowser-
|
|
1921
|
+
//# sourceMappingURL=InteractiveBrowser-DXwmvWdA.mjs.map
|