effect-browser 0.2.0-beta.9 → 0.3.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/README.md +861 -1161
  2. package/dist/Browser-B4qncxe7.mjs +628 -0
  3. package/dist/Browser-B4qncxe7.mjs.map +1 -0
  4. package/dist/Browser.d.mts +129 -3
  5. package/dist/Browser.mjs +2 -22
  6. package/dist/BrowserError-Coy7EW1N.d.mts +140 -0
  7. package/dist/BrowserError.d.mts +2 -0
  8. package/dist/BrowserError.mjs +211 -0
  9. package/dist/BrowserError.mjs.map +1 -0
  10. package/dist/BrowserEvent-BRu2juEz.d.mts +279 -0
  11. package/dist/BrowserEvent.d.mts +2 -0
  12. package/dist/BrowserEvent.mjs +297 -0
  13. package/dist/BrowserEvent.mjs.map +1 -0
  14. package/dist/Cdp.d.mts +32 -0
  15. package/dist/Cdp.mjs +61 -0
  16. package/dist/Cdp.mjs.map +1 -0
  17. package/dist/Change-DNvztNLu.mjs +138 -0
  18. package/dist/Change-DNvztNLu.mjs.map +1 -0
  19. package/dist/Change-iMlcuzVD.d.mts +71 -0
  20. package/dist/Change.d.mts +2 -0
  21. package/dist/Change.mjs +2 -0
  22. package/dist/Chromium.d.mts +29 -81
  23. package/dist/Chromium.mjs +57 -392
  24. package/dist/Chromium.mjs.map +1 -1
  25. package/dist/Expect.d.mts +62 -0
  26. package/dist/Expect.mjs +114 -0
  27. package/dist/Expect.mjs.map +1 -0
  28. package/dist/Frame-Di2PxyF7.d.mts +119 -0
  29. package/dist/Frame.d.mts +2 -0
  30. package/dist/Frame.mjs +125 -0
  31. package/dist/Frame.mjs.map +1 -0
  32. package/dist/Moment.d.mts +2 -0
  33. package/dist/Moment.mjs +288 -0
  34. package/dist/Moment.mjs.map +1 -0
  35. package/dist/Motion.d.mts +40 -0
  36. package/dist/Motion.mjs +122 -0
  37. package/dist/Motion.mjs.map +1 -0
  38. package/dist/Page-B5cjaUp5.mjs +618 -0
  39. package/dist/Page-B5cjaUp5.mjs.map +1 -0
  40. package/dist/Page-B7X6DQUn.d.mts +595 -0
  41. package/dist/Page.d.mts +2 -0
  42. package/dist/Page.mjs +2 -0
  43. package/dist/Plan-Akcac63g.d.mts +209 -0
  44. package/dist/Plan-D1wrJVs8.mjs +508 -0
  45. package/dist/Plan-D1wrJVs8.mjs.map +1 -0
  46. package/dist/Plan.d.mts +2 -3
  47. package/dist/Plan.mjs +2 -2
  48. package/dist/Policy.d.mts +76 -0
  49. package/dist/Policy.mjs +237 -0
  50. package/dist/Policy.mjs.map +1 -0
  51. package/dist/Presentation.d.mts +48 -0
  52. package/dist/Presentation.mjs +117 -0
  53. package/dist/Presentation.mjs.map +1 -0
  54. package/dist/Snapshot-B34hZ4Jl.d.mts +68 -0
  55. package/dist/Snapshot.d.mts +2 -0
  56. package/dist/Snapshot.mjs +79 -0
  57. package/dist/Snapshot.mjs.map +1 -0
  58. package/dist/Stage.d.mts +64 -0
  59. package/dist/Stage.mjs +237 -0
  60. package/dist/Stage.mjs.map +1 -0
  61. package/dist/Supervisor-CYWFK3vM.d.mts +280 -0
  62. package/dist/Supervisor-TNKNOVzu.mjs +599 -0
  63. package/dist/Supervisor-TNKNOVzu.mjs.map +1 -0
  64. package/dist/Supervisor.d.mts +2 -0
  65. package/dist/Supervisor.mjs +2 -0
  66. package/dist/context-B6xr8nVi.mjs +261 -0
  67. package/dist/context-B6xr8nVi.mjs.map +1 -0
  68. package/dist/index.d.mts +17 -14
  69. package/dist/index.mjs +18 -13
  70. package/dist/match.inpage-xOe9LNO0.mjs +48 -0
  71. package/dist/match.inpage-xOe9LNO0.mjs.map +1 -0
  72. package/dist/page-BAf__WKX.mjs +5075 -0
  73. package/dist/page-BAf__WKX.mjs.map +1 -0
  74. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  75. package/dist/url-Cd04Okid.mjs +264 -0
  76. package/dist/url-Cd04Okid.mjs.map +1 -0
  77. package/package.json +96 -61
  78. package/src/Browser.ts +672 -0
  79. package/src/BrowserError.ts +234 -0
  80. package/src/BrowserEvent.ts +296 -0
  81. package/src/Cdp.ts +101 -0
  82. package/src/Change.ts +88 -0
  83. package/src/Chromium.ts +102 -0
  84. package/src/Expect.ts +180 -0
  85. package/src/Frame.ts +132 -0
  86. package/src/Moment.ts +479 -0
  87. package/src/Motion.ts +166 -0
  88. package/src/Page.ts +522 -0
  89. package/src/Plan.ts +663 -0
  90. package/src/Policy.ts +325 -0
  91. package/src/Presentation.ts +195 -0
  92. package/src/Snapshot.ts +89 -0
  93. package/src/Stage.ts +467 -0
  94. package/src/Supervisor.ts +599 -0
  95. package/src/index.ts +20 -0
  96. package/src/internal/input/actions.ts +610 -0
  97. package/src/internal/input/dispatch.ts +161 -0
  98. package/src/internal/input/edit.inpage.ts +162 -0
  99. package/src/internal/input/evidence.inpage.ts +164 -0
  100. package/src/internal/input/gate.ts +224 -0
  101. package/src/internal/input/guard.inpage.ts +605 -0
  102. package/src/internal/input/guard.ts +184 -0
  103. package/src/internal/input/keyboard.ts +112 -0
  104. package/src/internal/input/keys.ts +127 -0
  105. package/src/internal/input/perform.ts +376 -0
  106. package/src/internal/input/pointer.ts +153 -0
  107. package/src/internal/input/replies.ts +195 -0
  108. package/src/internal/input/settle.ts +50 -0
  109. package/src/internal/input/style.ts +186 -0
  110. package/src/internal/input/targets.inpage.ts +293 -0
  111. package/src/internal/input/targets.ts +148 -0
  112. package/src/internal/page/bridge.ts +391 -0
  113. package/src/internal/page/context.ts +314 -0
  114. package/src/internal/page/identity.ts +35 -0
  115. package/src/internal/page/lane.ts +311 -0
  116. package/src/internal/page/navigation.ts +183 -0
  117. package/src/internal/page/openings.ts +87 -0
  118. package/src/internal/page/page.ts +165 -0
  119. package/src/internal/page/url.ts +100 -0
  120. package/src/internal/page/viewport.ts +43 -0
  121. package/src/internal/pictures/capture.ts +776 -0
  122. package/src/internal/pictures/clock.ts +141 -0
  123. package/src/internal/pictures/counts.ts +92 -0
  124. package/src/internal/pictures/pictures.ts +521 -0
  125. package/src/internal/pictures/transport.ts +243 -0
  126. package/src/internal/reading/choose.ts +100 -0
  127. package/src/internal/reading/context.inpage.ts +201 -0
  128. package/src/internal/reading/controls.inpage.ts +158 -0
  129. package/src/internal/reading/expect.inpage.ts +70 -0
  130. package/src/internal/reading/match.inpage.ts +92 -0
  131. package/src/internal/reading/names.inpage.ts +306 -0
  132. package/src/internal/reading/outline.inpage.ts +260 -0
  133. package/src/internal/reading/reading.ts +223 -0
  134. package/src/internal/reading/ready.inpage.ts +164 -0
  135. package/src/internal/reading/ready.ts +111 -0
  136. package/src/internal/reading/subjects.inpage.ts +188 -0
  137. package/src/internal/reading/text.inpage.ts +135 -0
  138. package/src/internal/reading/walk.inpage.ts +220 -0
  139. package/src/internal/supervisor/lifecycle.ts +416 -0
  140. package/src/internal/timeline/changes.inpage.ts +216 -0
  141. package/src/internal/timeline/changes.ts +100 -0
  142. package/src/internal/timeline/events.ts +94 -0
  143. package/src/internal/timeline/fold.inpage.ts +123 -0
  144. package/src/internal/timeline/history.inpage.ts +229 -0
  145. package/src/internal/timeline/marks.inpage.ts +207 -0
  146. package/src/internal/timeline/record.inpage.ts +133 -0
  147. package/src/internal/timeline/sight.inpage.ts +122 -0
  148. package/src/internal/timeline/window.ts +96 -0
  149. package/src/internal/timeline/words.ts +65 -0
  150. package/dist/Bootstrap-B9UUXsvF.d.mts +0 -183
  151. package/dist/Bootstrap-CeQOWBy6.mjs +0 -189
  152. package/dist/Bootstrap-CeQOWBy6.mjs.map +0 -1
  153. package/dist/Bootstrap.d.mts +0 -3
  154. package/dist/Bootstrap.mjs +0 -2
  155. package/dist/Browser-BF9_sORP.d.mts +0 -388
  156. package/dist/Browser.mjs.map +0 -1
  157. package/dist/BrowserData-CPIIIHol.d.mts +0 -585
  158. package/dist/BrowserData.d.mts +0 -3
  159. package/dist/BrowserData.mjs +0 -695
  160. package/dist/BrowserData.mjs.map +0 -1
  161. package/dist/BrowserRuntime-B6nT1G4X.d.mts +0 -148
  162. package/dist/BrowserRuntime-C1r2aSRK.mjs +0 -6820
  163. package/dist/BrowserRuntime-C1r2aSRK.mjs.map +0 -1
  164. package/dist/BrowserRuntime.d.mts +0 -3
  165. package/dist/BrowserRuntime.mjs +0 -3
  166. package/dist/Capture.d.mts +0 -56
  167. package/dist/Capture.mjs +0 -678
  168. package/dist/Capture.mjs.map +0 -1
  169. package/dist/CaptureData-CYriZHX1.mjs +0 -201
  170. package/dist/CaptureData-CYriZHX1.mjs.map +0 -1
  171. package/dist/CaptureData.d.mts +0 -219
  172. package/dist/CaptureData.mjs +0 -2
  173. package/dist/Errors.d.mts +0 -158
  174. package/dist/Errors.mjs +0 -207
  175. package/dist/Errors.mjs.map +0 -1
  176. package/dist/Images-yCG9BmRU.mjs +0 -76
  177. package/dist/Images-yCG9BmRU.mjs.map +0 -1
  178. package/dist/OperationOptions-DAeRS6O9.mjs +0 -55
  179. package/dist/OperationOptions-DAeRS6O9.mjs.map +0 -1
  180. package/dist/PageControl.d.mts +0 -15
  181. package/dist/PageControl.mjs +0 -34
  182. package/dist/PageControl.mjs.map +0 -1
  183. package/dist/PageRegistry-B3q9DS3g.mjs +0 -164
  184. package/dist/PageRegistry-B3q9DS3g.mjs.map +0 -1
  185. package/dist/Plan-Dyxu2q8C.mjs +0 -543
  186. package/dist/Plan-Dyxu2q8C.mjs.map +0 -1
  187. package/dist/PlanData-B668RxbQ.d.mts +0 -4831
  188. package/dist/PlanData.d.mts +0 -3
  189. package/dist/PlanData.mjs +0 -268
  190. package/dist/PlanData.mjs.map +0 -1
  191. package/dist/PlanInput-BJcPPncs.mjs +0 -75
  192. package/dist/PlanInput-BJcPPncs.mjs.map +0 -1
  193. package/dist/PublicSession-DCSMMqOj.mjs +0 -5602
  194. package/dist/PublicSession-DCSMMqOj.mjs.map +0 -1
  195. package/dist/Testing.d.mts +0 -479
  196. package/dist/Testing.mjs +0 -2147
  197. package/dist/Testing.mjs.map +0 -1
  198. package/dist/Timeline-fV22Xk-S.d.mts +0 -29
  199. package/dist/Timeline.d.mts +0 -4
  200. package/dist/Timeline.mjs +0 -20
  201. package/dist/Timeline.mjs.map +0 -1
  202. package/dist/TimelineData-BsOn-YGZ.d.mts +0 -3818
  203. package/dist/TimelineData.d.mts +0 -3
  204. package/dist/TimelineData.mjs +0 -482
  205. package/dist/TimelineData.mjs.map +0 -1
@@ -0,0 +1,71 @@
1
+ import { b as Subject } from "./BrowserEvent-BRu2juEz.mjs";
2
+ import { Schema } from "effect";
3
+ declare namespace Change_d_exports {
4
+ export { Change, Changes, Kind, describe };
5
+ }
6
+ /**
7
+ * `text` changed; `appeared` and `disappeared`, whether added or removed or shown or hidden;
8
+ * `brief`, appeared and gone again by the window's end; `value`, a field's; `title`, the document's.
9
+ */
10
+ declare const Kind: Schema.Literals<readonly ["text", "appeared", "disappeared", "brief", "value", "title"]>;
11
+ type Kind = typeof Kind.Type;
12
+ declare const Change_base: Schema.Class<Change, Schema.Struct<{
13
+ readonly kind: Schema.Literals<readonly ["text", "appeared", "disappeared", "brief", "value", "title"]>;
14
+ /**
15
+ * What changed, as the page names it now, or where it was for what went. Its own words are what
16
+ * changed, so its name is empty unless something else names it, as a field's label does.
17
+ */
18
+ readonly subject: typeof Subject;
19
+ /** When it first changed in the window, in host monotonic milliseconds on the browser's clock. */
20
+ readonly startedAt: Schema.Finite;
21
+ /** When it last changed in the window. */
22
+ readonly at: Schema.Finite;
23
+ /**
24
+ * What it showed at the window's start; absent for what appeared and where the record let that go.
25
+ * What disappeared says what it showed as it went. A field's value reads `••••` unless unmasked.
26
+ */
27
+ readonly before: Schema.optional<Schema.String>;
28
+ /** What it showed at the window's end; absent for what disappeared. What came and went says what it showed. */
29
+ readonly after: Schema.optional<Schema.String>;
30
+ /** How many times what it showed changed in the window. */
31
+ readonly count: Schema.Int;
32
+ /** For a number that changed more than once, its lowest and highest, as shown. */
33
+ readonly lowest: Schema.optional<Schema.String>;
34
+ readonly highest: Schema.optional<Schema.String>;
35
+ /** When it last changed before the window, as far back as the record keeps: in flux, not news. */
36
+ readonly earlier: Schema.optional<Schema.Finite>;
37
+ /**
38
+ * When the trusted input it followed reached the page, where it was that input's doing. It was not
39
+ * in flux: in the 10 s before the input it had not changed, and nothing had come into or left what
40
+ * it sits in, so a ticker's tick or a feed's line is not. Then it changed within 3 s inside what
41
+ * the input acted on or its row, form, dialog or controlled element; or, elsewhere, within 500 ms
42
+ * of an input on a page where nothing had changed in the 2 s before, as a menu a portal puts at
43
+ * the end of the page does. What holds the input's target, as a menu holds its item, does not
44
+ * count against it. The page's `Action` that sent it holds that time.
45
+ */
46
+ readonly cause: Schema.optional<Schema.Finite>;
47
+ }>, {}>;
48
+ declare class Change extends Change_base {}
49
+ declare const Changes_base: Schema.Class<Changes, Schema.Struct<{
50
+ /** The page's document these changes belong to, as `Navigated` counts them. */
51
+ readonly document: Schema.Int;
52
+ /** Where the record is whole: before it, changes may be missing. */
53
+ readonly from: Schema.Finite;
54
+ /** Where the window ends: its `until`, or when the page was read. */
55
+ readonly until: Schema.Finite;
56
+ /**
57
+ * Where the window ends on the page's own clock. Give these changes as the next read's `since` and
58
+ * the two windows meet exactly, whatever the clock mapping does meanwhile.
59
+ */
60
+ readonly cursor: Schema.Finite;
61
+ /** Changes in the window the record let go, at least; 0 when it kept them all. */
62
+ readonly dropped: Schema.Int;
63
+ /** Oldest first, by when each began to change. */
64
+ readonly changes: Schema.$Array<typeof Change>;
65
+ }>, {}>;
66
+ declare class Changes extends Changes_base {}
67
+ /** A change in words for a model, such as `"$61,240" became "$62,010" (row "Bitcoin", column "Price")`. */
68
+ declare const describe: (change: Change) => string;
69
+ //#endregion
70
+ export { describe as a, Kind as i, Change_d_exports as n, Changes as r, Change as t };
71
+ //# sourceMappingURL=Change-iMlcuzVD.d.mts.map
@@ -0,0 +1,2 @@
1
+ import { a as describe, i as Kind, r as Changes, t as Change } from "./Change-iMlcuzVD.mjs";
2
+ export { Change, Changes, Kind, describe };
@@ -0,0 +1,2 @@
1
+ import { a as describe, i as Kind, r as Changes, t as Change } from "./Change-DNvztNLu.mjs";
2
+ export { Change, Changes, Kind, describe };
@@ -1,85 +1,33 @@
1
- import { BrowserError, InitializationError } from "./Errors.mjs";
2
- import { it as Viewport, o as BrowserPolicy, r as AutomationOptions } from "./BrowserData-CPIIIHol.mjs";
3
- import { c as OpenOptions, i as BrowserSession } from "./Browser-BF9_sORP.mjs";
4
- import { Context, Crypto, Effect, Layer, Option, Redacted, Schema, Scope } from "effect";
5
- //#region src/internal/chromium/Data.d.ts
6
- declare const ChromiumReference_base: Schema.Class<ChromiumReference, Schema.Struct<{
7
- readonly provider: Schema.Literal<"chromium">;
8
- readonly id: Schema.NonEmptyString;
9
- }>, {}>;
10
- /** Identifies this Chromium ownership lifetime, not a reusable endpoint. */
11
- export declare class ChromiumReference extends ChromiumReference_base {}
12
- declare const ChromiumCleanupIssue_base: Schema.Class<ChromiumCleanupIssue, Schema.Struct<{
13
- readonly step: Schema.Literals<readonly ["fence", "capture", "initialization", "disconnect", "terminate", "profile"]>;
14
- readonly reason: Schema.Literals<readonly ["timeout", "failed", "interrupted"]>;
15
- }>, {}>;
16
- export declare class ChromiumCleanupIssue extends ChromiumCleanupIssue_base {}
17
- declare const ChromiumCleanupResult_base: Schema.Class<ChromiumCleanupResult, Schema.Struct<{
18
- readonly reference: typeof ChromiumReference;
19
- readonly ownership: Schema.Literals<readonly ["owned", "borrowed"]>;
20
- readonly connection: Schema.Literals<readonly ["closed", "failed", "not-connected", "pending"]>;
21
- readonly process: Schema.Literals<readonly ["terminated", "unknown", "not-owned"]>;
22
- readonly issues: Schema.$Array<typeof ChromiumCleanupIssue>;
23
- }>, {}>;
24
- /** Connection teardown and observed process exit are separate facts; no provider status exists. */
25
- export declare class ChromiumCleanupResult extends ChromiumCleanupResult_base {}
26
- export declare const ChromiumLaunch: Schema.Struct<{
27
- readonly executablePath: Schema.optionalKey<Schema.NonEmptyString>;
28
- readonly headless: Schema.optionalKey<Schema.Boolean>;
29
- /** Enabled by default; a trusted host must explicitly choose a sandbox exception. */
30
- readonly chromiumSandbox: Schema.optionalKey<Schema.Boolean>;
31
- readonly args: Schema.optionalKey<Schema.$Array<Schema.NonEmptyString>>;
32
- readonly proxy: Schema.optionalKey<Schema.Struct<{
33
- readonly server: Schema.NonEmptyString;
34
- readonly bypass: Schema.optionalKey<Schema.NonEmptyString>;
35
- }>>;
36
- readonly startupTimeoutMillis: Schema.optionalKey<Schema.Int>;
37
- }>;
38
- export type ChromiumLaunch = typeof ChromiumLaunch.Type;
39
- //#endregion
40
- //#region src/Chromium.d.ts
41
- /** Host-only process configuration. Building this layer neither loads Playwright nor starts Chromium. */
42
- export interface ChromiumOptions extends AutomationOptions {
43
- readonly launch?: ChromiumLaunch;
44
- readonly viewport?: Viewport;
45
- readonly onCleanup?: (result: ChromiumCleanupResult) => Effect.Effect<void>;
46
- }
47
- /** An owned or borrowed Chromium lifetime with one modeled browser connection. */
48
- export interface ChromiumSession<E = never> extends BrowserSession<E> {
49
- readonly reference: ChromiumReference;
50
- readonly closeChecked: Effect.Effect<ChromiumCleanupResult, BrowserError>;
51
- readonly close: Effect.Effect<ChromiumCleanupResult>;
52
- readonly cleanupResult: Effect.Effect<Option.Option<ChromiumCleanupResult>>;
53
- }
54
- export interface ChromiumAcquisition<E = never> {
55
- readonly reference: ChromiumReference;
56
- readonly failure: Effect.Effect<never, E | InitializationError>;
57
- readonly connect: Effect.Effect<ChromiumSession<E>, BrowserError | InitializationError | E>;
58
- readonly close: Effect.Effect<ChromiumCleanupResult>;
59
- }
60
- export interface ChromiumAttachRequest<E = never, R = never> extends OpenOptions<E, R> {
61
- readonly policy: BrowserPolicy;
62
- /** Resolve this exact target; without it, multiple open pages are an ambiguity error. */
63
- readonly target?: {
64
- readonly targetId: string;
65
- };
1
+ import { t as BrowserError } from "./BrowserError-Coy7EW1N.mjs";
2
+ import { Browser, Options as Options$1, Service, t as Browser_d_exports } from "./Browser.mjs";
3
+ import { Effect, Layer } from "effect";
4
+ declare namespace Chromium_d_exports {
5
+ export { Options, layer, open };
66
6
  }
67
- declare const Chromium_base: Context.ServiceClass<Chromium, "effect-browser/Chromium", {
68
- readonly acquire: <E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) => Effect.Effect<ChromiumAcquisition<E>, BrowserError, Scope.Scope | Exclude<R, Scope.Scope>>;
69
- readonly launch: <E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) => Effect.Effect<ChromiumSession<E>, BrowserError | InitializationError | E, Scope.Scope | Exclude<R, Scope.Scope>>;
70
- /** A concrete loopback ws://.../devtools/browser/... endpoint; this scope owns only its connection. */
71
- readonly attach: <E = never, R = never>(endpoint: Redacted.Redacted<string>, request: ChromiumAttachRequest<E, R>) => Effect.Effect<ChromiumSession<E>, BrowserError | InitializationError | E, Scope.Scope | Exclude<R, Scope.Scope>>;
72
- }>;
73
- export declare class Chromium extends Chromium_base {
74
- /** Launch through the configured service; compose with Browser.scoped for supervised ownership. */
75
- static launch<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>): Effect.Effect<ChromiumSession<E>, E | BrowserError | InitializationError, Chromium | Scope.Scope | Exclude<R, Scope.Scope>>;
76
- /** Acquire the process lifetime before connecting, using the caller's scope. */
77
- static acquire<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>): Effect.Effect<ChromiumAcquisition<E>, BrowserError, Chromium | Scope.Scope | Exclude<R, Scope.Scope>>;
78
- /** Borrow a concrete loopback endpoint; cleanup never terminates its external process. */
79
- static attach<E = never, R = never>(endpoint: Redacted.Redacted<string>, request: ChromiumAttachRequest<E, R>): Effect.Effect<ChromiumSession<E>, E | BrowserError | InitializationError, Chromium | Scope.Scope | Exclude<R, Scope.Scope>>;
80
- /** Chromium references, connection ids and handoff tokens come from the required `Crypto`. */
81
- static layer(options?: ChromiumOptions): Layer.Layer<Chromium, BrowserError, Crypto.Crypto>;
7
+ export interface Options extends Options$1 {
8
+ /** Defaults to true. */
9
+ readonly headless?: boolean | undefined;
10
+ /**
11
+ * Run Chromium's sandbox. Defaults to false, as in Playwright, so an exploit in a page's renderer
12
+ * runs with this process's privileges. Hosts that don't allow unprivileged user namespaces, such
13
+ * as many containers and Ubuntu 23.10 or later by default, can't start the sandbox; opening then
14
+ * fails and says so.
15
+ */
16
+ readonly sandbox?: boolean | undefined;
17
+ /** Defaults to 1280x720 CSS pixels at a device scale factor of 1. */
18
+ readonly viewport?: {
19
+ readonly width: number;
20
+ readonly height: number;
21
+ } | undefined;
22
+ readonly executablePath?: string | undefined;
23
+ readonly args?: ReadonlyArray<string> | undefined;
24
+ readonly userAgent?: string | undefined;
25
+ readonly locale?: string | undefined;
82
26
  }
27
+ /** Launch Chromium and open a `Browser` over a fresh context. */
28
+ export declare const open: (options?: Options | undefined) => Effect.Effect<Service, BrowserError, import("effect/Scope").Scope>;
29
+ /** A `Browser` Layer that launches Chromium when built and closes it when released. */
30
+ export declare const layer: (options?: Options) => Layer.Layer<Browser, BrowserError>;
83
31
  //#endregion
84
- export {};
32
+ export { Chromium_d_exports as t };
85
33
  //# sourceMappingURL=Chromium.d.mts.map
package/dist/Chromium.mjs CHANGED
@@ -1,399 +1,64 @@
1
- import { BrowserError, Reasons } from "./Errors.mjs";
2
- import { Identifier } from "./BrowserData.mjs";
3
- import { n as make } from "./BrowserRuntime-C1r2aSRK.mjs";
4
- import { O as span, T as annotate, l as reported, o as randomUuid, s as cleanupStep, t as checked } from "./PublicSession-DCSMMqOj.mjs";
5
- import { Clock, Context, Crypto, Duration, Effect, Exit, Layer, Option, Path, Redacted, Schema } from "effect";
6
- import { spawn } from "node:child_process";
7
- import { mkdtemp, readFile, rm } from "node:fs/promises";
8
- import { tmpdir } from "node:os";
9
- //#region src/internal/chromium/Data.ts
10
- /** Identifies this Chromium ownership lifetime, not a reusable endpoint. */
11
- var ChromiumReference = class extends Schema.Class("ChromiumReference")({
12
- provider: Schema.Literal("chromium"),
13
- id: Identifier
14
- }) {};
15
- var ChromiumCleanupIssue = class extends Schema.Class("ChromiumCleanupIssue")({
16
- step: Schema.Literals([
17
- "fence",
18
- "capture",
19
- "initialization",
20
- "disconnect",
21
- "terminate",
22
- "profile"
23
- ]),
24
- reason: Schema.Literals([
25
- "timeout",
26
- "failed",
27
- "interrupted"
28
- ])
29
- }) {};
30
- /** Connection teardown and observed process exit are separate facts; no provider status exists. */
31
- var ChromiumCleanupResult = class extends Schema.Class("ChromiumCleanupResult")({
32
- reference: ChromiumReference,
33
- ownership: Schema.Literals(["owned", "borrowed"]),
34
- connection: Schema.Literals([
35
- "closed",
36
- "failed",
37
- "not-connected",
38
- "pending"
39
- ]),
40
- process: Schema.Literals([
41
- "terminated",
42
- "unknown",
43
- "not-owned"
44
- ]),
45
- issues: Schema.Array(ChromiumCleanupIssue).check(Schema.isMaxLength(16))
46
- }) {};
47
- const Text = Schema.NonEmptyString.check(Schema.isMaxLength(4096), Schema.isPattern(/^[^\u0000\r\n]+$/u));
48
- const Port = Schema.Int.check(Schema.isBetween({
49
- minimum: 1,
50
- maximum: 65535
51
- }));
52
- /** Only a concrete loopback WebSocket is admitted: no HTTP discovery redirects or remote DNS. */
53
- const ChromiumEndpoint = Text.check(Schema.makeFilter((value) => {
54
- try {
55
- const url = new URL(value);
56
- return url.protocol === "ws:" && ["127.0.0.1", "[::1]"].includes(url.hostname) && Schema.is(Port)(Number(url.port)) && !url.username && !url.password && !url.search && !url.hash && /^\/devtools\/browser\/[A-Za-z0-9_-]+$/u.test(url.pathname);
57
- } catch {
58
- return false;
59
- }
60
- }));
61
- const ProxyServer = Text.check(Schema.makeFilter((value) => {
62
- try {
63
- const url = new URL(value);
64
- return [
65
- "http:",
66
- "https:",
67
- "socks5:"
68
- ].includes(url.protocol) && url.hostname.length > 0 && !url.username && !url.password && !url.search && !url.hash && ["", "/"].includes(url.pathname);
69
- } catch {
70
- return false;
71
- }
72
- }));
73
- /** These arguments belong to the launcher; silently overriding them would change ownership. */
74
- const Argument = Text.check(Schema.makeFilter((value) => value.startsWith("--") && !/^--(?:user-data-dir|remote-debugging[^=]*|headless|no-sandbox|disable-setuid-sandbox|single-process|proxy-server|proxy-bypass-list|no-startup-window)(?:=|$)/u.test(value)));
75
- const ChromiumLaunch = Schema.Struct({
76
- executablePath: Schema.optionalKey(Text),
77
- headless: Schema.optionalKey(Schema.Boolean),
78
- /** Enabled by default; a trusted host must explicitly choose a sandbox exception. */
79
- chromiumSandbox: Schema.optionalKey(Schema.Boolean),
80
- args: Schema.optionalKey(Schema.Array(Argument).check(Schema.isMaxLength(64))),
81
- proxy: Schema.optionalKey(Schema.Struct({
82
- server: ProxyServer,
83
- bypass: Schema.optionalKey(Text)
84
- })),
85
- startupTimeoutMillis: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
86
- minimum: 1,
87
- maximum: 6e4
88
- })))
89
- });
90
- //#endregion
91
- //#region src/internal/chromium/Process.ts
92
- /** Explicit host sandbox/proxy choices; the owned profile and debugger endpoint cannot be replaced. */
93
- const launchArguments = (options, directory) => [
94
- "--no-first-run",
95
- "--no-default-browser-check",
96
- "--remote-debugging-address=127.0.0.1",
97
- "--remote-debugging-port=0",
98
- "--remote-debugging-pipe",
99
- `--user-data-dir=${directory}`,
100
- ...options.headless === false ? [] : ["--headless=new"],
101
- ...options.chromiumSandbox === false ? ["--no-sandbox"] : [],
102
- ...options.proxy === void 0 ? [] : [`--proxy-server=${options.proxy.server}`, `--proxy-bypass-list=${options.proxy.bypass ?? "<-loopback>"}`],
103
- ...options.args ?? [],
104
- "--no-startup-window"
105
- ];
106
- const failure = (operation, reason) => BrowserError.make({
107
- operation,
108
- reason,
109
- outcome: operation === "close" ? "unknown" : "undispatched"
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { Failed } from "./BrowserError.mjs";
3
+ import { i as make, t as Browser } from "./Browser-B4qncxe7.mjs";
4
+ import { o as reasonOf, s as undispatched } from "./context-B6xr8nVi.mjs";
5
+ import { Effect, Layer } from "effect";
6
+ import { chromium } from "playwright-core";
7
+ //#region src/Chromium.ts
8
+ /**
9
+ * A local Chromium, launched for the scope and closed with it.
10
+ *
11
+ * It uses the Chromium build that `playwright-core` installs
12
+ * (`npx playwright-core install chromium`), unless `executablePath` names another.
13
+ *
14
+ * Signals are the program's to handle: run it with `NodeRuntime.runMain`, which interrupts it on
15
+ * SIGINT and SIGTERM, so the browser closes with its scope.
16
+ *
17
+ * @since 0.3.0
18
+ */
19
+ var Chromium_exports = /* @__PURE__ */ __exportAll({
20
+ layer: () => layer,
21
+ open: () => open
110
22
  });
111
- const exited = (child) => child.exitCode !== null || child.signalCode !== null;
112
- /** POSIX groups keep Chromium's helpers inside the same owned termination boundary. */
113
- const alive = (pid) => {
114
- try {
115
- process.kill(-pid, 0);
116
- return true;
117
- } catch (error) {
118
- if (error instanceof Error && "code" in error && error.code === "ESRCH") return false;
119
- throw error;
120
- }
121
- };
122
- const signalGroup = (pid, signal) => {
123
- try {
124
- process.kill(-pid, signal);
125
- } catch (error) {
126
- if (!(error instanceof Error && "code" in error && error.code === "ESRCH")) throw error;
127
- }
128
- };
129
- /** Called once; observes parent and helper exit, rather than treating a sent signal as cleanup. */
130
- const terminate = Effect.fnUntraced(function* (child, pid, clock) {
131
- const stopped = Effect.try({
132
- try: () => exited(child) && !alive(pid),
133
- catch: () => failure("close", Reasons.Failed.make({}))
134
- });
135
- const signal = (value) => Effect.try({
136
- try: () => signalGroup(pid, value),
137
- catch: () => failure("close", Reasons.Failed.make({}))
138
- });
139
- const pause = clock.sleep(Duration.millis(20));
140
- yield* signal("SIGTERM");
141
- const graceful = clock.monotonicTimeNanosUnsafe() + 1500000000n;
142
- while (!(yield* stopped) && clock.monotonicTimeNanosUnsafe() < graceful) yield* pause;
143
- if (yield* stopped) return;
144
- yield* signal("SIGKILL");
145
- const forced = clock.monotonicTimeNanosUnsafe() + 1000000000n;
146
- while (!(yield* stopped) && clock.monotonicTimeNanosUnsafe() < forced) yield* pause;
147
- if (!(yield* stopped)) return yield* failure("close", Reasons.Timeout.make({}));
148
- }, span("Chromium.terminate"));
149
- /** Start only Chromium's process. The shared owner later opens its sole CDP connection. */
150
- const launch = Effect.fnUntraced(function* (options) {
151
- if (process.platform === "win32") return yield* failure("launch", Reasons.Unsupported.make({}));
152
- const path = yield* Path.Path.pipe(Effect.provide(Path.layer));
153
- const clock = yield* Clock.Clock;
154
- const executable = options.executablePath ?? (yield* Effect.tryPromise({
155
- try: () => import("playwright-core").then(({ chromium }) => chromium.executablePath()),
156
- catch: () => failure("launch", Reasons.Failed.make({}))
157
- }));
158
- const directory = yield* Effect.tryPromise({
159
- try: () => mkdtemp(path.join(tmpdir(), "effect-browser-chromium-")),
160
- catch: () => failure("launch", Reasons.Failed.make({}))
161
- });
162
- const removeProfile = Effect.tryPromise({
163
- try: () => rm(directory, {
164
- recursive: true,
165
- force: true,
166
- maxRetries: 5,
167
- retryDelay: 50
23
+ const launchTimeoutMillis = 18e4;
24
+ const failed = (operation, timeoutMillis) => (cause) => undispatched(operation, reasonOf(cause, timeoutMillis));
25
+ const sandboxFailed = /Chromium sandboxing failed|No usable sandbox/;
26
+ const launchFailed = (cause) => sandboxFailed.test(String(cause)) ? undispatched("launch", new Failed({ detail: "Chromium's sandbox could not start on this host: it needs unprivileged user namespaces, and a user other than root" })) : failed("launch", launchTimeoutMillis)(cause);
27
+ /** Launch Chromium and open a `Browser` over a fresh context. */
28
+ const open = Effect.fn("Chromium.open")(function* (options = {}) {
29
+ const launched = yield* Effect.acquireRelease(Effect.tryPromise({
30
+ try: () => chromium.launch({
31
+ headless: options.headless ?? true,
32
+ chromiumSandbox: options.sandbox ?? false,
33
+ timeout: launchTimeoutMillis,
34
+ handleSIGINT: false,
35
+ handleSIGTERM: false,
36
+ handleSIGHUP: false,
37
+ ...options.executablePath === void 0 ? {} : { executablePath: options.executablePath },
38
+ ...options.args === void 0 ? {} : { args: [...options.args] }
168
39
  }),
169
- catch: () => failure("close", Reasons.Failed.make({}))
40
+ catch: launchFailed
41
+ }).pipe(Effect.withSpan("Chromium.launch", {}, { captureStackTrace: false })), (browser) => Effect.tryPromise(() => browser.close()).pipe(Effect.ignore));
42
+ const context = yield* Effect.tryPromise({
43
+ try: () => launched.newContext({
44
+ viewport: options.viewport ?? {
45
+ width: 1280,
46
+ height: 720
47
+ },
48
+ deviceScaleFactor: 1,
49
+ ...options.userAgent === void 0 ? {} : { userAgent: options.userAgent },
50
+ ...options.locale === void 0 ? {} : { locale: options.locale }
51
+ }),
52
+ catch: failed("launch")
170
53
  });
171
- let child;
172
- return yield* Effect.gen(function* () {
173
- const launched = yield* Effect.callback((resume) => {
174
- const failed = () => resume(Effect.fail(failure("launch", Reasons.Failed.make({}))));
175
- let spawned;
176
- try {
177
- spawned = spawn(executable, launchArguments(options, directory), {
178
- cwd: directory,
179
- stdio: [
180
- "ignore",
181
- "ignore",
182
- "ignore",
183
- "pipe",
184
- "pipe"
185
- ],
186
- detached: true
187
- });
188
- } catch {
189
- failed();
190
- return;
191
- }
192
- child = spawned;
193
- spawned.once("spawn", () => resume(Effect.succeed(spawned)));
194
- spawned.once("error", failed);
195
- });
196
- const pid = launched.pid;
197
- if (pid === void 0) return yield* failure("launch", Reasons.Failed.make({}));
198
- return {
199
- connection: (timeoutMillis) => Effect.gen(function* () {
200
- const deadline = clock.monotonicTimeNanosUnsafe() + BigInt(Math.ceil(Math.min(timeoutMillis, options.startupTimeoutMillis ?? 15e3))) * 1000000n;
201
- while (clock.monotonicTimeNanosUnsafe() < deadline) {
202
- if (exited(launched)) return yield* failure("connect", Reasons.Closed.make({}));
203
- const portFile = yield* Effect.tryPromise({
204
- try: (signal) => readFile(path.join(directory, "DevToolsActivePort"), {
205
- encoding: "utf8",
206
- signal
207
- }).catch((error) => {
208
- if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
209
- throw error;
210
- }),
211
- catch: () => failure("connect", Reasons.Transport.make({}))
212
- });
213
- const lines = portFile === void 0 ? [] : portFile.trim().split("\n");
214
- if (lines.length >= 2) {
215
- const endpoint = `ws://127.0.0.1:${lines[0]}${lines[1]}`;
216
- if (!Schema.is(ChromiumEndpoint)(endpoint)) return yield* failure("connect", Reasons.Malformed.make({}));
217
- return Redacted.make(endpoint);
218
- }
219
- yield* clock.sleep(Duration.millis(20));
220
- }
221
- return yield* failure("connect", Reasons.Timeout.make({}));
222
- }).pipe(span("Chromium.ready")),
223
- terminate: yield* Effect.cached(terminate(launched, pid, clock).pipe(Effect.uninterruptible)),
224
- removeProfile
225
- };
226
- }).pipe(Effect.onExit((exit) => Exit.isSuccess(exit) ? Effect.void : Effect.gen(function* () {
227
- if (child?.pid === void 0) {
228
- yield* removeProfile.pipe(Effect.ignore);
229
- return;
230
- }
231
- const stopped = yield* terminate(child, child.pid, clock).pipe(Effect.exit);
232
- if (Exit.isSuccess(stopped)) yield* removeProfile.pipe(Effect.ignore);
233
- })));
234
- }, span("Chromium.launch"));
235
- //#endregion
236
- //#region src/internal/chromium/Session.ts
237
- /** Each teardown step runs even when a preceding step fails. Only observed exit permits profile removal. */
238
- const makeChromiumCleanup = Effect.fnUntraced(function* (reference, local, process) {
239
- let latest;
240
- return {
241
- close: yield* Effect.cached(Effect.uninterruptible(Effect.gen(function* () {
242
- const issues = [];
243
- const step = (name, action) => cleanupStep(action.pipe(span(`Chromium.cleanup.${name}`)), 3e3).pipe(Effect.tap((result) => Effect.sync(() => {
244
- if (result._tag === "Failure") issues.push(ChromiumCleanupIssue.make({
245
- step: name,
246
- reason: result.reason
247
- }));
248
- })));
249
- yield* step("fence", local.fence);
250
- yield* step("capture", local.capture);
251
- yield* step("initialization", local.initialization);
252
- const disconnected = yield* step("disconnect", local.disconnect);
253
- const terminated = process === void 0 ? void 0 : yield* step("terminate", process.terminate);
254
- if (process !== void 0 && terminated !== void 0 && terminated._tag === "Success") yield* step("profile", process.removeProfile);
255
- const result = ChromiumCleanupResult.make({
256
- reference,
257
- ownership: process === void 0 ? "borrowed" : "owned",
258
- connection: disconnected._tag === "Success" ? disconnected.value : "failed",
259
- process: terminated === void 0 ? "not-owned" : terminated._tag === "Success" ? "terminated" : "unknown",
260
- issues
261
- });
262
- Object.freeze(result.issues);
263
- latest = Object.freeze(result);
264
- yield* annotate({
265
- "browser.cleanup.connection": result.connection,
266
- "browser.cleanup.process": result.process,
267
- "browser.cleanup.issues": issues.length
268
- });
269
- return latest;
270
- }).pipe(span("Chromium.cleanup")))),
271
- result: Effect.sync(() => Option.fromNullishOr(latest))
272
- };
54
+ return yield* make(context, {
55
+ id: `chromium-${launched.version()}`,
56
+ provider: "chromium"
57
+ }, options);
273
58
  });
274
- const acquireChromium = (endpoint, options, onCleanup) => (local) => Effect.uninterruptible(Effect.gen(function* () {
275
- const id = yield* randomUuid(yield* Crypto.Crypto);
276
- const process = endpoint === void 0 ? yield* launch(options) : void 0;
277
- const reference = Object.freeze(ChromiumReference.make({
278
- provider: "chromium",
279
- id
280
- }));
281
- const cleanup = yield* makeChromiumCleanup(reference, local, process);
282
- let closing = false;
283
- const release = yield* Effect.cached(Effect.gen(function* () {
284
- closing = true;
285
- const result = yield* cleanup.close;
286
- if (onCleanup !== void 0) yield* reported(Effect.suspend(() => onCleanup(result)));
287
- return result;
288
- }).pipe(span("Chromium.release"), Effect.uninterruptible));
289
- yield* Effect.addFinalizer(() => release.pipe(Effect.asVoid));
290
- return {
291
- reference,
292
- connection: (timeoutMillis) => Effect.suspend(() => {
293
- if (closing) return Effect.fail(BrowserError.make({
294
- operation: "connect",
295
- reason: Reasons.Closed.make({}),
296
- outcome: "undispatched"
297
- }));
298
- if (process !== void 0) return process.connection(timeoutMillis);
299
- return endpoint === void 0 ? Effect.fail(BrowserError.make({
300
- operation: "connect",
301
- reason: Reasons.Configuration.make({}),
302
- outcome: "undispatched"
303
- })) : checked(ChromiumEndpoint, Redacted.value(endpoint), "connect").pipe(Effect.map(Redacted.make));
304
- }),
305
- release,
306
- closeChecked: release.pipe(Effect.filterOrFail((result) => result.connection === "closed" && result.issues.length === 0 && (result.ownership === "borrowed" ? result.process === "not-owned" : result.process === "terminated"), () => BrowserError.make({
307
- operation: "close",
308
- reason: Reasons.Failed.make({}),
309
- outcome: "unknown"
310
- })), span("Chromium.close")),
311
- cleanupResult: cleanup.result,
312
- controlRetired: cleanup.result.pipe(Effect.map((result) => Option.isSome(result) && result.value.ownership === "owned" && result.value.process === "terminated"))
313
- };
314
- }));
315
- const ownedChromium = (options, onCleanup) => acquireChromium(void 0, options, onCleanup);
316
- const borrowedChromium = (endpoint, onCleanup) => acquireChromium(endpoint, {}, onCleanup);
317
- //#endregion
318
- //#region src/Chromium.ts
319
- var Chromium = class Chromium extends Context.Service()("effect-browser/Chromium") {
320
- /** Launch through the configured service; compose with Browser.scoped for supervised ownership. */
321
- static launch(policy, request) {
322
- return Effect.flatMap(Chromium, (browser) => browser.launch(policy, request));
323
- }
324
- /** Acquire the process lifetime before connecting, using the caller's scope. */
325
- static acquire(policy, request) {
326
- return Effect.flatMap(Chromium, (browser) => browser.acquire(policy, request));
327
- }
328
- /** Borrow a concrete loopback endpoint; cleanup never terminates its external process. */
329
- static attach(endpoint, request) {
330
- return Effect.flatMap(Chromium, (browser) => browser.attach(endpoint, request));
331
- }
332
- /** Chromium references, connection ids and handoff tokens come from the required `Crypto`. */
333
- static layer(options = {}) {
334
- return Layer.effect(Chromium, Effect.gen(function* () {
335
- const launchInput = yield* checked(ChromiumLaunch, options.launch ?? {}, "configure");
336
- const launch = Object.freeze({
337
- ...launchInput,
338
- ...launchInput.args === void 0 ? {} : { args: Object.freeze([...launchInput.args]) },
339
- ...launchInput.proxy === void 0 ? {} : { proxy: Object.freeze({ ...launchInput.proxy }) }
340
- });
341
- if (Object.prototype.hasOwnProperty.call(options, "bootstrap")) return yield* BrowserError.make({
342
- operation: "configure",
343
- reason: Reasons.Configuration.make({}),
344
- outcome: "undispatched"
345
- });
346
- const runtime = yield* make({
347
- implementation: "chromium-playwright-cdp",
348
- ...options.viewport === void 0 ? {} : { viewport: options.viewport },
349
- automation: {
350
- ...options.timelineLimits === void 0 ? {} : { timelineLimits: options.timelineLimits },
351
- ...options.admissionLimits === void 0 ? {} : { admissionLimits: options.admissionLimits },
352
- ...options.observationLimits === void 0 ? {} : { observationLimits: options.observationLimits },
353
- ...options.actionTimeoutMillis === void 0 ? {} : { actionTimeoutMillis: options.actionTimeoutMillis },
354
- ...options.maxPages === void 0 ? {} : { maxPages: options.maxPages },
355
- ...options.maxHostReads === void 0 ? {} : { maxHostReads: options.maxHostReads },
356
- ...options.initialPage === void 0 ? {} : { initialPage: options.initialPage },
357
- ...options.popupPolicy === void 0 ? {} : { popupPolicy: options.popupPolicy },
358
- ...options.dialogPolicy === void 0 ? {} : { dialogPolicy: options.dialogPolicy },
359
- ...options.pageControl === void 0 ? {} : { pageControl: options.pageControl }
360
- }
361
- });
362
- const crypto = yield* Crypto.Crypto;
363
- const acquire = Effect.fnUntraced(function* (policy, request = {}, attachment) {
364
- const source = attachment === void 0 ? ownedChromium(launch, options.onCleanup) : borrowedChromium(attachment.endpoint, options.onCleanup);
365
- const acquired = yield* runtime.acquire(policy, (cleanup, deadline) => source(cleanup, deadline).pipe(Effect.provideService(Crypto.Crypto, crypto)), {
366
- ...request,
367
- ...attachment === void 0 ? {} : { existingTarget: attachment.targetId === void 0 ? {} : { targetId: attachment.targetId } }
368
- });
369
- const connected = yield* Effect.cached(acquired.connect.pipe(Effect.map(({ session }) => Object.assign(session, {
370
- reference: acquired.reference,
371
- closeChecked: session.closeChecked.pipe(Effect.andThen(acquired.lifetime.closeChecked)),
372
- close: acquired.close,
373
- cleanupResult: acquired.lifetime.cleanupResult
374
- }))));
375
- return {
376
- reference: acquired.reference,
377
- failure: acquired.failure,
378
- close: acquired.close,
379
- connect: acquired.connect.pipe(Effect.andThen(connected))
380
- };
381
- });
382
- return Chromium.of({
383
- acquire,
384
- launch: (policy, request) => acquire(policy, request).pipe(Effect.flatMap((acquired) => acquired.connect)),
385
- attach: (endpoint, request) => Effect.gen(function* () {
386
- const address = yield* checked(ChromiumEndpoint, Redacted.value(endpoint), "connect");
387
- return yield* (yield* acquire(request.policy, request, {
388
- endpoint: Redacted.make(address),
389
- ...request.target === void 0 ? {} : { targetId: request.target.targetId }
390
- })).connect;
391
- })
392
- });
393
- }));
394
- }
395
- };
59
+ /** A `Browser` Layer that launches Chromium when built and closes it when released. */
60
+ const layer = (options = {}) => Layer.effect(Browser, open(options));
396
61
  //#endregion
397
- export { Chromium, ChromiumCleanupIssue, ChromiumCleanupResult, ChromiumLaunch, ChromiumReference };
62
+ export { layer, open, Chromium_exports as t };
398
63
 
399
64
  //# sourceMappingURL=Chromium.mjs.map