effect-playwright 0.1.0 → 0.1.1

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 CHANGED
@@ -1,10 +1,14 @@
1
1
  # effect-playwright
2
2
 
3
+ [![NPM Version](https://img.shields.io/npm/v/effect-playwright)](https://www.npmjs.com/package/effect-playwright)
3
4
  [![GitHub License](https://img.shields.io/github/license/Jobflow-io/effect-playwright)](https://github.com/Jobflow-io/effect-playwright/blob/main/LICENSE)
4
5
  [![Effect: yes](https://img.shields.io/badge/effect-yes-blue)](https://effect.website/)
5
6
 
6
7
  A Playwright wrapper for the Effect ecosystem. This library provides a set of services and layers to interact with Playwright in a type-safe way using Effect.
7
8
 
9
+ > [!NOTE]
10
+ > This library is currently focused on using Playwright for **automation** and **scraping**. It does not provide a wrapper for `@playwright/test` (the test runner).
11
+
8
12
  ## Installation
9
13
 
10
14
  ```bash
@@ -17,6 +21,8 @@ or
17
21
  npm install effect-playwright playwright-core
18
22
  ```
19
23
 
24
+ You can also install `playwright` instead of `playwright-core` if you want the post-build auto install of the browsers.
25
+
20
26
  ## Quick Start
21
27
 
22
28
  ```ts
@@ -49,6 +55,36 @@ const program = Effect.gen(function* () {
49
55
  }).pipe(Effect.scoped);
50
56
  ```
51
57
 
58
+ ## Connecting via CDP
59
+
60
+ You can connect to an existing browser instance using the Chrome DevTools Protocol (CDP).
61
+
62
+ ```ts
63
+ const program = Effect.gen(function* () {
64
+ const playwright = yield* Playwright;
65
+
66
+ // Use connectCDPScoped to automatically close the CONNECTION when the scope ends
67
+ // Note: This does NOT close the browser process itself, only the CDP connection.
68
+ const browser = yield* playwright.connectCDPScoped("http://localhost:9222");
69
+
70
+ const page = yield* browser.newPage();
71
+ // ...
72
+ }).pipe(Effect.scoped);
73
+ ```
74
+
75
+ If you need to manage the connection lifecycle manually, use `connectCDP`:
76
+
77
+ ```ts
78
+ const program = Effect.gen(function* () {
79
+ const playwright = yield* Playwright;
80
+ const browser = yield* playwright.connectCDP("http://localhost:9222");
81
+
82
+ // ... use browser ...
83
+
84
+ yield* browser.close;
85
+ });
86
+ ```
87
+
52
88
  ## PlaywrightEnvironment (Experimental)
53
89
 
54
90
  The `PlaywrightEnvironment` simplifies setup by allowing you to configure the browser type and launch options once and reuse them across your application.
@@ -75,6 +111,20 @@ const program = Effect.gen(function* () {
75
111
  await Effect.runPromise(program.pipe(Effect.provide(liveLayer)));
76
112
  ```
77
113
 
114
+ ### `PlaywrightEnvironment.withBrowser`
115
+
116
+ The `withBrowser` utility provides the `PlaywrightBrowser` service to your effect. It internally manages a `Scope`, which means the browser will be launched when the effect starts and closed automatically when the effect finishes (including on failure or interruption).
117
+
118
+ ```ts
119
+ const program = Effect.gen(function* () {
120
+ const browser = yield* PlaywrightBrowser; // Now available in context
121
+ const page = yield* browser.newPage();
122
+
123
+ // ...
124
+ // Browser close is ensured
125
+ }).pipe(PlaywrightEnvironment.withBrowser);
126
+ ```
127
+
78
128
  ## Accessing Native Playwright
79
129
 
80
130
  If you need to access functionality from the underlying Playwright objects that isn't directly exposed, you can use the `use` method available on most services/objects (browsers, pages, locators).
@@ -1,4 +1,4 @@
1
- import { d as PlaywrightError, o as PlaywrightBrowser } from "../index-aR0Fa_4Y.mjs";
1
+ import { d as PlaywrightError, o as PlaywrightBrowser } from "../index-DnbVDccF.mjs";
2
2
  import { Context, Effect, Layer } from "effect";
3
3
  import { BrowserType, LaunchOptions } from "playwright-core";
4
4
  import { Scope as Scope$1 } from "effect/Scope";
@@ -35,10 +35,11 @@ declare class PlaywrightEnvironment extends PlaywrightEnvironment_base {}
35
35
  *
36
36
  * // use the layer
37
37
  * const program = Effect.gen(function* () {
38
- * const browser = yield* PlaywrightEnvironment.browser;
38
+ * const playwright = yield* PlaywrightEnvironment;
39
+ * const browser = yield* playwright.browser;
39
40
  * const page = yield* browser.newPage();
40
41
  * yield* page.goto("https://example.com");
41
- * }).pipe(PlaywrightEnvironment.withBrowser, Effect.provide(playwrightEnv));
42
+ * }).pipe(Effect.scoped, Effect.provide(playwrightEnv));
42
43
  * ```
43
44
  *
44
45
  * @param browser - The Playwright BrowserType implementation (e.g. `chromium`, `firefox`, `webkit`).
@@ -59,12 +60,13 @@ declare const layer: (browser: BrowserType, launchOptions?: LaunchOptions) => La
59
60
  * import { PlaywrightEnvironment } from "effect-playwright/experimental";
60
61
  * import { chromium } from "playwright-core";
61
62
  *
62
- * const layer = PlaywrightEnvironment.layer(chromium);
63
+ * const env = PlaywrightEnvironment.layer(chromium);
64
+ *
63
65
  * const program = Effect.gen(function* () {
64
66
  * const browser = yield* PlaywrightBrowser;
65
67
  * const page = yield* browser.newPage();
66
68
  * yield* page.goto("https://example.com");
67
- * }).pipe(PlaywrightEnvironment.withBrowser);
69
+ * }).pipe(PlaywrightEnvironment.withBrowser, Effect.provide(env));
68
70
  * ```
69
71
  *
70
72
  * @since 0.1.0
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "../chunk-BiucMVzj.mjs";
2
- import { n as PlaywrightBrowser, t as Playwright } from "../src-DveiwW4g.mjs";
2
+ import { n as PlaywrightBrowser, t as Playwright } from "../src-BGGNNney.mjs";
3
3
  import { Context, Effect, Layer } from "effect";
4
4
 
5
5
  //#region src/experimental/environment.ts
@@ -33,10 +33,11 @@ var PlaywrightEnvironment = class extends Context.Tag("effect-playwright/experim
33
33
  *
34
34
  * // use the layer
35
35
  * const program = Effect.gen(function* () {
36
- * const browser = yield* PlaywrightEnvironment.browser;
36
+ * const playwright = yield* PlaywrightEnvironment;
37
+ * const browser = yield* playwright.browser;
37
38
  * const page = yield* browser.newPage();
38
39
  * yield* page.goto("https://example.com");
39
- * }).pipe(PlaywrightEnvironment.withBrowser, Effect.provide(playwrightEnv));
40
+ * }).pipe(Effect.scoped, Effect.provide(playwrightEnv));
40
41
  * ```
41
42
  *
42
43
  * @param browser - The Playwright BrowserType implementation (e.g. `chromium`, `firefox`, `webkit`).
@@ -61,12 +62,13 @@ const layer = (browser, launchOptions) => {
61
62
  * import { PlaywrightEnvironment } from "effect-playwright/experimental";
62
63
  * import { chromium } from "playwright-core";
63
64
  *
64
- * const layer = PlaywrightEnvironment.layer(chromium);
65
+ * const env = PlaywrightEnvironment.layer(chromium);
66
+ *
65
67
  * const program = Effect.gen(function* () {
66
68
  * const browser = yield* PlaywrightBrowser;
67
69
  * const page = yield* browser.newPage();
68
70
  * yield* page.goto("https://example.com");
69
- * }).pipe(PlaywrightEnvironment.withBrowser);
71
+ * }).pipe(PlaywrightEnvironment.withBrowser, Effect.provide(env));
70
72
  * ```
71
73
  *
72
74
  * @since 0.1.0
@@ -1,5 +1,5 @@
1
- import { Context, Effect, Layer, Scope, Stream } from "effect";
2
- import { Browser, BrowserContext, BrowserType, ConnectOverCDPOptions, ConsoleMessage, Dialog, Download, ElementHandle, FileChooser, Frame, JSHandle, Locator, Page, Request, Response, WebSocket, Worker, chromium } from "playwright-core";
1
+ import { Context, Effect, Layer, Option, Scope, Stream } from "effect";
2
+ import { Browser, BrowserContext, BrowserType, ConnectOverCDPOptions, ConsoleMessage, Dialog, Download, ElementHandle, FileChooser, Frame, JSHandle, Locator, Page, Request as Request$1, Response as Response$1, WebSocket, Worker as Worker$1, chromium } from "playwright-core";
3
3
  import { Scope as Scope$1 } from "effect/Scope";
4
4
  import * as effect_Types0 from "effect/Types";
5
5
  import * as effect_Cause0 from "effect/Cause";
@@ -23,6 +23,117 @@ type NoHandles<Arg> = Arg extends JSHandle ? never : Arg extends object ? { [Key
23
23
  type Unboxed<Arg> = Arg extends ElementHandle<infer T> ? T : Arg extends JSHandle<infer T> ? T : Arg extends NoHandles<Arg> ? Arg : Arg extends [infer A0] ? [Unboxed<A0>] : Arg extends [infer A0, infer A1] ? [Unboxed<A0>, Unboxed<A1>] : Arg extends [infer A0, infer A1, infer A2] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>] : Arg extends [infer A0, infer A1, infer A2, infer A3] ? [Unboxed<A0>, Unboxed<A1>, Unboxed<A2>, Unboxed<A3>] : Arg extends Array<infer T> ? Array<Unboxed<T>> : Arg extends object ? { [Key in keyof Arg]: Unboxed<Arg[Key]> } : Arg;
24
24
  type PageFunction<Arg, R> = string | ((arg: Unboxed<Arg>) => R | Promise<R>);
25
25
  //#endregion
26
+ //#region src/common.d.ts
27
+ declare const PlaywrightFrame_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
28
+ readonly _tag: "PlaywrightFrame";
29
+ };
30
+ declare class PlaywrightFrame extends PlaywrightFrame_base<{
31
+ use: <A>(f: (frame: Frame) => Promise<A>) => Effect.Effect<A, PlaywrightError>;
32
+ }> {
33
+ static make(frame: Frame): PlaywrightFrame;
34
+ }
35
+ declare const PlaywrightRequest_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
36
+ readonly _tag: "PlaywrightRequest";
37
+ };
38
+ declare class PlaywrightRequest extends PlaywrightRequest_base<{
39
+ allHeaders: Effect.Effect<Awaited<ReturnType<Request$1["allHeaders"]>>, PlaywrightError>;
40
+ failure: () => Option.Option<NonNullable<ReturnType<Request$1["failure"]>>>;
41
+ frame: Effect.Effect<PlaywrightFrame>;
42
+ headerValue: (name: string) => Effect.Effect<Option.Option<string>, PlaywrightError>;
43
+ headers: Effect.Effect<ReturnType<Request$1["headers"]>>;
44
+ headersArray: Effect.Effect<Awaited<ReturnType<Request$1["headersArray"]>>, PlaywrightError>;
45
+ isNavigationRequest: Effect.Effect<boolean>;
46
+ method: Effect.Effect<string>;
47
+ postData: () => Option.Option<string>;
48
+ postDataBuffer: () => Option.Option<NonNullable<ReturnType<Request$1["postDataBuffer"]>>>;
49
+ postDataJSON: Effect.Effect<Option.Option<NonNullable<Awaited<ReturnType<Request$1["postDataJSON"]>>>>, PlaywrightError>;
50
+ redirectedFrom: () => Option.Option<PlaywrightRequest>;
51
+ redirectedTo: () => Option.Option<PlaywrightRequest>;
52
+ resourceType: Effect.Effect<ReturnType<Request$1["resourceType"]>>;
53
+ response: Effect.Effect<Option.Option<PlaywrightResponse>, PlaywrightError>;
54
+ serviceWorker: () => Option.Option<PlaywrightWorker>;
55
+ sizes: Effect.Effect<Awaited<ReturnType<Request$1["sizes"]>>, PlaywrightError>;
56
+ timing: Effect.Effect<ReturnType<Request$1["timing"]>>;
57
+ url: Effect.Effect<string>;
58
+ }> {
59
+ static make(request: Request$1): PlaywrightRequest;
60
+ }
61
+ declare const PlaywrightResponse_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
62
+ readonly _tag: "PlaywrightResponse";
63
+ };
64
+ declare class PlaywrightResponse extends PlaywrightResponse_base<{
65
+ allHeaders: Effect.Effect<Awaited<ReturnType<Response$1["allHeaders"]>>, PlaywrightError>;
66
+ body: Effect.Effect<Awaited<ReturnType<Response$1["body"]>>, PlaywrightError>;
67
+ finished: Effect.Effect<Awaited<ReturnType<Response$1["finished"]>>, PlaywrightError>;
68
+ frame: Effect.Effect<PlaywrightFrame>;
69
+ fromServiceWorker: Effect.Effect<boolean>;
70
+ headers: Effect.Effect<ReturnType<Response$1["headers"]>>;
71
+ headersArray: Effect.Effect<Awaited<ReturnType<Response$1["headersArray"]>>, PlaywrightError>;
72
+ headerValue: (name: string) => Effect.Effect<Option.Option<string>, PlaywrightError>;
73
+ headerValues: (name: string) => Effect.Effect<Awaited<ReturnType<Response$1["headerValues"]>>, PlaywrightError>;
74
+ json: Effect.Effect<Awaited<ReturnType<Response$1["json"]>>, PlaywrightError>;
75
+ ok: Effect.Effect<boolean>;
76
+ request: () => PlaywrightRequest;
77
+ securityDetails: Effect.Effect<Option.Option<NonNullable<Awaited<ReturnType<Response$1["securityDetails"]>>>>, PlaywrightError>;
78
+ serverAddr: Effect.Effect<Option.Option<NonNullable<Awaited<ReturnType<Response$1["serverAddr"]>>>>, PlaywrightError>;
79
+ status: Effect.Effect<number>;
80
+ statusText: Effect.Effect<string>;
81
+ text: Effect.Effect<Awaited<ReturnType<Response$1["text"]>>, PlaywrightError>;
82
+ url: Effect.Effect<string>;
83
+ }> {
84
+ static make(response: Response$1): PlaywrightResponse;
85
+ }
86
+ declare const PlaywrightWorker_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
87
+ readonly _tag: "PlaywrightWorker";
88
+ };
89
+ declare class PlaywrightWorker extends PlaywrightWorker_base<{
90
+ evaluate: <R, Arg = void>(pageFunction: PageFunction<Arg, R>, arg?: Arg) => Effect.Effect<R, PlaywrightError>;
91
+ url: Effect.Effect<string>;
92
+ }> {
93
+ static make(worker: Worker$1): PlaywrightWorker;
94
+ }
95
+ declare const PlaywrightDialog_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
96
+ readonly _tag: "PlaywrightDialog";
97
+ };
98
+ declare class PlaywrightDialog extends PlaywrightDialog_base<{
99
+ accept: (promptText?: string) => Effect.Effect<void, PlaywrightError>;
100
+ defaultValue: Effect.Effect<string>;
101
+ dismiss: Effect.Effect<void, PlaywrightError>;
102
+ message: Effect.Effect<string>;
103
+ page: () => Option.Option<PlaywrightPageService>;
104
+ type: Effect.Effect<string>;
105
+ }> {
106
+ static make(dialog: Dialog): PlaywrightDialog;
107
+ }
108
+ declare const PlaywrightFileChooser_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
109
+ readonly _tag: "PlaywrightFileChooser";
110
+ };
111
+ declare class PlaywrightFileChooser extends PlaywrightFileChooser_base<{
112
+ element: () => ElementHandle;
113
+ isMultiple: Effect.Effect<boolean>;
114
+ page: () => PlaywrightPageService;
115
+ setFiles: (files: Parameters<FileChooser["setFiles"]>[0], options?: Parameters<FileChooser["setFiles"]>[1]) => Effect.Effect<void, PlaywrightError>;
116
+ }> {
117
+ static make(fileChooser: FileChooser): PlaywrightFileChooser;
118
+ }
119
+ declare const PlaywrightDownload_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => Readonly<A> & {
120
+ readonly _tag: "PlaywrightDownload";
121
+ };
122
+ declare class PlaywrightDownload extends PlaywrightDownload_base<{
123
+ cancel: Effect.Effect<void, PlaywrightError>;
124
+ createReadStream: Stream.Stream<Uint8Array, PlaywrightError>;
125
+ delete: Effect.Effect<void, PlaywrightError>;
126
+ failure: Effect.Effect<Option.Option<string | null>, PlaywrightError>;
127
+ page: () => PlaywrightPageService;
128
+ path: Effect.Effect<Option.Option<string | null>, PlaywrightError>;
129
+ saveAs: (path: string) => Effect.Effect<void, PlaywrightError>;
130
+ suggestedFilename: Effect.Effect<string>;
131
+ url: Effect.Effect<string>;
132
+ use: <R>(f: (download: Download) => Promise<R>) => Effect.Effect<R, PlaywrightError>;
133
+ }> {
134
+ static make(download: Download): PlaywrightDownload;
135
+ }
136
+ //#endregion
26
137
  //#region src/locator.d.ts
27
138
  /**
28
139
  * Interface for a Playwright locator.
@@ -171,27 +282,6 @@ declare class PlaywrightLocator extends PlaywrightLocator_base {
171
282
  }
172
283
  //#endregion
173
284
  //#region src/page.d.ts
174
- interface PlaywrightPageEvents {
175
- close: Page;
176
- console: ConsoleMessage;
177
- crash: Page;
178
- dialog: Dialog;
179
- domcontentloaded: Page;
180
- download: Download;
181
- filechooser: FileChooser;
182
- frameattached: Frame;
183
- framedetached: Frame;
184
- framenavigated: Frame;
185
- load: Page;
186
- pageerror: Error;
187
- popup: Page;
188
- request: Request;
189
- requestfailed: Request;
190
- requestfinished: Request;
191
- response: Response;
192
- websocket: WebSocket;
193
- worker: Worker;
194
- }
195
285
  interface PlaywrightPageService {
196
286
  /**
197
287
  * Navigates the page to the given URL.
@@ -329,7 +419,7 @@ interface PlaywrightPageService {
329
419
  * @see {@link Page.on}
330
420
  * @since 0.1.0
331
421
  */
332
- readonly eventStream: <K extends keyof PlaywrightPageEvents>(event: K) => Stream.Stream<PlaywrightPageEvents[K]>;
422
+ readonly eventStream: <K extends keyof typeof eventMappings>(event: K) => Stream.Stream<ReturnType<(typeof eventMappings)[K]>>;
333
423
  /**
334
424
  * Clicks an element matching the given selector.
335
425
  *
@@ -355,7 +445,60 @@ declare class PlaywrightPage extends PlaywrightPage_base {
355
445
  * @param page - The Playwright `Page` instance to wrap.
356
446
  * @since 0.1.0
357
447
  */
358
- static make(page: Page): PlaywrightPageService;
448
+ static make(page: PageWithPatchedEvents): PlaywrightPageService;
449
+ }
450
+ interface PageEvents {
451
+ close: Page;
452
+ console: ConsoleMessage;
453
+ crash: Page;
454
+ dialog: Dialog;
455
+ domcontentloaded: Page;
456
+ download: Download;
457
+ filechooser: FileChooser;
458
+ frameattached: Frame;
459
+ framedetached: Frame;
460
+ framenavigated: Frame;
461
+ load: Page;
462
+ pageerror: Error;
463
+ popup: Page;
464
+ request: Request;
465
+ requestfailed: Request;
466
+ requestfinished: Request;
467
+ response: Response;
468
+ websocket: WebSocket;
469
+ worker: Worker;
470
+ }
471
+ type PageEvent = keyof PageEvents;
472
+ declare const eventMappings: {
473
+ readonly close: typeof PlaywrightPage.make;
474
+ readonly console: (a: ConsoleMessage) => ConsoleMessage;
475
+ readonly crash: typeof PlaywrightPage.make;
476
+ readonly dialog: typeof PlaywrightDialog.make;
477
+ readonly domcontentloaded: typeof PlaywrightPage.make;
478
+ readonly download: typeof PlaywrightDownload.make;
479
+ readonly filechooser: typeof PlaywrightFileChooser.make;
480
+ readonly frameattached: typeof PlaywrightFrame.make;
481
+ readonly framedetached: typeof PlaywrightFrame.make;
482
+ readonly framenavigated: typeof PlaywrightFrame.make;
483
+ readonly load: typeof PlaywrightPage.make;
484
+ readonly pageerror: (a: Error) => Error;
485
+ readonly popup: typeof PlaywrightPage.make;
486
+ readonly request: typeof PlaywrightRequest.make;
487
+ readonly requestfailed: typeof PlaywrightRequest.make;
488
+ readonly requestfinished: typeof PlaywrightRequest.make;
489
+ readonly response: typeof PlaywrightResponse.make;
490
+ readonly websocket: (a: WebSocket) => WebSocket;
491
+ readonly worker: typeof PlaywrightWorker.make;
492
+ };
493
+ /**
494
+ * Page interface with generic on/off methods.
495
+ * Playwright's Page uses overloads for on/off, making generic event handling impossible.
496
+ * This interface provides a unified signature for our event map.
497
+ * @internal
498
+ */
499
+ interface PageWithPatchedEvents extends Page {
500
+ on<K extends PageEvent>(event: K, listener: (arg: PageEvents[K]) => void): this;
501
+ off<K extends PageEvent>(event: K, listener: (arg: PageEvents[K]) => void): this;
359
502
  }
360
503
  //#endregion
361
504
  //#region src/browser-context.d.ts
@@ -549,18 +692,19 @@ interface PlaywrightService {
549
692
  /**
550
693
  * Connects to a browser instance via Chrome DevTools Protocol (CDP).
551
694
  *
552
- * Unlike {@link launchScoped}, this method does **not** close the browser when the
553
- * scope is closed. It is the caller's responsibility to manage the browser's
695
+ * Unlike {@link connectCDPScoped}, this method does **not** close the connection when the
696
+ * scope is closed. It is the caller's responsibility to manage the connection's
554
697
  * lifecycle.
555
698
  *
556
- * If you want to close the browser using a scope simply add a finalizer:
699
+ * If you want to close the connection using a scope simply add a finalizer:
557
700
  *
558
701
  * ```ts
559
702
  * import { Effect } from "effect";
560
703
  * import { Playwright } from "effect-playwright";
561
704
  *
562
705
  * const program = Effect.gen(function* () {
563
- * const browser = yield* Playwright.connectCDP(cdpUrl);
706
+ * const playwright = yield* Playwright;
707
+ * const browser = yield* playwright.connectCDP(cdpUrl);
564
708
  * yield* Effect.addFinalizer(() => browser.close.pipe(Effect.ignore));
565
709
  * });
566
710
  *
@@ -572,6 +716,32 @@ interface PlaywrightService {
572
716
  * @since 0.1.0
573
717
  */
574
718
  connectCDP: (cdpUrl: string, options?: ConnectOverCDPOptions) => Effect.Effect<typeof PlaywrightBrowser.Service, PlaywrightError>;
719
+ /**
720
+ * Connects to a browser instance via Chrome DevTools Protocol (CDP) managed by a Scope.
721
+ *
722
+ * This method automatically closes the connection when the scope is closed.
723
+ *
724
+ * Note that closing a CDP connection does **not** close the browser instance itself,
725
+ * only the CDP connection.
726
+ *
727
+ * ```ts
728
+ * import { Effect } from "effect";
729
+ * import { Playwright } from "effect-playwright";
730
+ *
731
+ * const program = Effect.gen(function* () {
732
+ * const playwright = yield* Playwright;
733
+ * const browser = yield* playwright.connectCDPScoped(cdpUrl);
734
+ * // Connection will be closed automatically when scope closes
735
+ * });
736
+ *
737
+ * await Effect.runPromise(program);
738
+ * ```
739
+ *
740
+ * @param cdpUrl - The CDP URL to connect to.
741
+ * @param options - Optional options for connecting to the CDP URL.
742
+ * @since 0.1.1
743
+ */
744
+ connectCDPScoped: (cdpUrl: string, options?: ConnectOverCDPOptions) => Effect.Effect<typeof PlaywrightBrowser.Service, PlaywrightError, Scope.Scope>;
575
745
  }
576
746
  declare const Playwright_base: Context.TagClass<Playwright, "effect-playwright/index/Playwright", PlaywrightService>;
577
747
  declare class Playwright extends Playwright_base {
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as NewPageOptions, c as PlaywrightPageService, i as NewContextOptions, l as PlaywrightLocator, n as PlaywrightService, o as PlaywrightBrowser, r as LaunchOptions, s as PlaywrightPage, t as Playwright, u as PlaywrightLocatorService } from "./index-aR0Fa_4Y.mjs";
1
+ import { a as NewPageOptions, c as PlaywrightPageService, i as NewContextOptions, l as PlaywrightLocator, n as PlaywrightService, o as PlaywrightBrowser, r as LaunchOptions, s as PlaywrightPage, t as Playwright, u as PlaywrightLocatorService } from "./index-DnbVDccF.mjs";
2
2
  export { LaunchOptions, NewContextOptions, NewPageOptions, Playwright, PlaywrightBrowser, PlaywrightLocator, PlaywrightLocatorService, PlaywrightPage, PlaywrightPageService, PlaywrightService };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { i as PlaywrightLocator, n as PlaywrightBrowser, r as PlaywrightPage, t as Playwright } from "./src-DveiwW4g.mjs";
1
+ import { i as PlaywrightLocator, n as PlaywrightBrowser, r as PlaywrightPage, t as Playwright } from "./src-BGGNNney.mjs";
2
2
 
3
3
  export { Playwright, PlaywrightBrowser, PlaywrightLocator, PlaywrightPage };
@@ -0,0 +1,310 @@
1
+ import { Context, Data, Effect, Layer, Option, Stream, identity } from "effect";
2
+ import { chromium, errors } from "playwright-core";
3
+
4
+ //#region src/errors.ts
5
+ var PlaywrightError = class extends Data.TaggedError("PlaywrightError") {};
6
+ function wrapError(error) {
7
+ if (error instanceof errors.TimeoutError) return new PlaywrightError({
8
+ reason: "Timeout",
9
+ cause: error
10
+ });
11
+ else return new PlaywrightError({
12
+ reason: "Unknown",
13
+ cause: error
14
+ });
15
+ }
16
+
17
+ //#endregion
18
+ //#region src/utils.ts
19
+ /** @internal */
20
+ const useHelper = (api) => (userFunction) => Effect.tryPromise(() => userFunction(api)).pipe(Effect.mapError(wrapError));
21
+
22
+ //#endregion
23
+ //#region src/common.ts
24
+ var PlaywrightFrame = class PlaywrightFrame extends Data.TaggedClass("PlaywrightFrame") {
25
+ static make(frame) {
26
+ return new PlaywrightFrame({ use: useHelper(frame) });
27
+ }
28
+ };
29
+ var PlaywrightRequest = class PlaywrightRequest extends Data.TaggedClass("PlaywrightRequest") {
30
+ static make(request) {
31
+ const use = useHelper(request);
32
+ return new PlaywrightRequest({
33
+ allHeaders: use(() => request.allHeaders()),
34
+ failure: Option.liftNullable(request.failure),
35
+ frame: Effect.sync(() => PlaywrightFrame.make(request.frame())),
36
+ headerValue: (name) => use(() => request.headerValue(name)).pipe(Effect.map(Option.fromNullable)),
37
+ headers: Effect.sync(() => request.headers()),
38
+ headersArray: use(() => request.headersArray()),
39
+ isNavigationRequest: Effect.sync(() => request.isNavigationRequest()),
40
+ method: Effect.sync(() => request.method()),
41
+ postData: Option.liftNullable(request.postData),
42
+ postDataBuffer: Option.liftNullable(request.postDataBuffer),
43
+ postDataJSON: use(() => request.postDataJSON()).pipe(Effect.map(Option.fromNullable)),
44
+ redirectedFrom: () => Option.fromNullable(request.redirectedFrom()).pipe(Option.map(PlaywrightRequest.make)),
45
+ redirectedTo: () => Option.fromNullable(request.redirectedTo()).pipe(Option.map(PlaywrightRequest.make)),
46
+ resourceType: Effect.sync(() => request.resourceType()),
47
+ response: use(() => request.response()).pipe(Effect.map(Option.fromNullable), Effect.map(Option.map(PlaywrightResponse.make))),
48
+ serviceWorker: () => Option.fromNullable(request.serviceWorker()).pipe(Option.map(PlaywrightWorker.make)),
49
+ sizes: use(() => request.sizes()),
50
+ timing: Effect.sync(() => request.timing()),
51
+ url: Effect.sync(() => request.url())
52
+ });
53
+ }
54
+ };
55
+ var PlaywrightResponse = class PlaywrightResponse extends Data.TaggedClass("PlaywrightResponse") {
56
+ static make(response) {
57
+ const use = useHelper(response);
58
+ return new PlaywrightResponse({
59
+ allHeaders: use(() => response.allHeaders()),
60
+ body: use(() => response.body()),
61
+ finished: use(() => response.finished()),
62
+ frame: Effect.sync(() => PlaywrightFrame.make(response.frame())),
63
+ fromServiceWorker: Effect.sync(() => response.fromServiceWorker()),
64
+ headers: Effect.sync(() => response.headers()),
65
+ headersArray: use(() => response.headersArray()),
66
+ headerValue: (name) => use(() => response.headerValue(name)).pipe(Effect.map(Option.fromNullable)),
67
+ headerValues: (name) => use(() => response.headerValues(name)),
68
+ json: use(() => response.json()),
69
+ ok: Effect.sync(() => response.ok()),
70
+ request: () => PlaywrightRequest.make(response.request()),
71
+ securityDetails: use(() => response.securityDetails()).pipe(Effect.map(Option.fromNullable)),
72
+ serverAddr: use(() => response.serverAddr()).pipe(Effect.map(Option.fromNullable)),
73
+ status: Effect.sync(() => response.status()),
74
+ statusText: Effect.sync(() => response.statusText()),
75
+ text: use(() => response.text()),
76
+ url: Effect.sync(() => response.url())
77
+ });
78
+ }
79
+ };
80
+ var PlaywrightWorker = class PlaywrightWorker extends Data.TaggedClass("PlaywrightWorker") {
81
+ static make(worker) {
82
+ const use = useHelper(worker);
83
+ return new PlaywrightWorker({
84
+ evaluate: (f, arg) => use((w) => w.evaluate(f, arg)),
85
+ url: Effect.sync(() => worker.url())
86
+ });
87
+ }
88
+ };
89
+ var PlaywrightDialog = class PlaywrightDialog extends Data.TaggedClass("PlaywrightDialog") {
90
+ static make(dialog) {
91
+ const use = useHelper(dialog);
92
+ return new PlaywrightDialog({
93
+ accept: (promptText) => use(() => dialog.accept(promptText)),
94
+ defaultValue: Effect.sync(() => dialog.defaultValue()),
95
+ dismiss: use(() => dialog.dismiss()),
96
+ message: Effect.sync(() => dialog.message()),
97
+ page: () => Option.fromNullable(dialog.page()).pipe(Option.map(PlaywrightPage.make)),
98
+ type: Effect.sync(() => dialog.type())
99
+ });
100
+ }
101
+ };
102
+ var PlaywrightFileChooser = class PlaywrightFileChooser extends Data.TaggedClass("PlaywrightFileChooser") {
103
+ static make(fileChooser) {
104
+ const use = useHelper(fileChooser);
105
+ return new PlaywrightFileChooser({
106
+ element: () => fileChooser.element(),
107
+ isMultiple: Effect.sync(() => fileChooser.isMultiple()),
108
+ page: () => PlaywrightPage.make(fileChooser.page()),
109
+ setFiles: (files, options) => use(() => fileChooser.setFiles(files, options))
110
+ });
111
+ }
112
+ };
113
+ var PlaywrightDownload = class PlaywrightDownload extends Data.TaggedClass("PlaywrightDownload") {
114
+ static make(download) {
115
+ const use = useHelper(download);
116
+ return new PlaywrightDownload({
117
+ cancel: use(() => download.cancel()),
118
+ createReadStream: Stream.empty,
119
+ delete: use(() => download.delete()),
120
+ failure: use(() => download.failure()).pipe(Effect.map(Option.fromNullable)),
121
+ page: () => PlaywrightPage.make(download.page()),
122
+ path: use(() => download.path()).pipe(Effect.map(Option.fromNullable)),
123
+ saveAs: (path) => use(() => download.saveAs(path)),
124
+ suggestedFilename: Effect.sync(() => download.suggestedFilename()),
125
+ url: Effect.sync(() => download.url()),
126
+ use
127
+ });
128
+ }
129
+ };
130
+
131
+ //#endregion
132
+ //#region src/locator.ts
133
+ /**
134
+ * A service that provides a `PlaywrightLocator` instance.
135
+ *
136
+ * @since 0.1.0
137
+ * @category tag
138
+ */
139
+ var PlaywrightLocator = class PlaywrightLocator extends Context.Tag("effect-playwright/PlaywrightLocator")() {
140
+ /**
141
+ * Creates a `PlaywrightLocator` from a Playwright `Locator` instance. This is mostly for internal use.
142
+ * But you could use this if you have used `use` or similar to wrap the locator.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * const playwrightNativeLocator = yield* page.use((p) => p.locator("button"));
147
+ * const locator = PlaywrightLocator.make(playwrightNativeLocator);
148
+ * ```
149
+ *
150
+ * @param locator - The Playwright `Locator` instance to wrap.
151
+ * @since 0.1.0
152
+ * @category constructor
153
+ */
154
+ static make(locator) {
155
+ const use = useHelper(locator);
156
+ return PlaywrightLocator.of({
157
+ click: (options) => use((l) => l.click(options)),
158
+ fill: (value, options) => use((l) => l.fill(value, options)),
159
+ getAttribute: (name, options) => use((l) => l.getAttribute(name, options)),
160
+ innerText: (options) => use((l) => l.innerText(options)),
161
+ innerHTML: (options) => use((l) => l.innerHTML(options)),
162
+ inputValue: (options) => use((l) => l.inputValue(options)),
163
+ textContent: (options) => use((l) => l.textContent(options)),
164
+ count: use((l) => l.count()),
165
+ first: () => PlaywrightLocator.make(locator.first()),
166
+ last: () => PlaywrightLocator.make(locator.last()),
167
+ nth: (index) => PlaywrightLocator.make(locator.nth(index)),
168
+ evaluate: (pageFunction, arg, options) => use((l) => l.evaluate(pageFunction, arg, options)),
169
+ use
170
+ });
171
+ }
172
+ };
173
+
174
+ //#endregion
175
+ //#region src/page.ts
176
+ /**
177
+ * @category tag
178
+ */
179
+ var PlaywrightPage = class PlaywrightPage extends Context.Tag("effect-playwright/PlaywrightPage")() {
180
+ /**
181
+ * Creates a `PlaywrightPage` from a Playwright `Page` instance.
182
+ *
183
+ * @param page - The Playwright `Page` instance to wrap.
184
+ * @since 0.1.0
185
+ */
186
+ static make(page) {
187
+ const use = useHelper(page);
188
+ return PlaywrightPage.of({
189
+ goto: (url, options) => use((p) => p.goto(url, options)),
190
+ waitForURL: (url, options) => use((p) => p.waitForURL(url, options)),
191
+ title: use((p) => p.title()),
192
+ evaluate: (f, arg) => use((p) => p.evaluate(f, arg)),
193
+ locator: (selector, options) => PlaywrightLocator.make(page.locator(selector, options)),
194
+ getByRole: (role, options) => PlaywrightLocator.make(page.getByRole(role, options)),
195
+ getByText: (text, options) => PlaywrightLocator.make(page.getByText(text, options)),
196
+ getByLabel: (label, options) => PlaywrightLocator.make(page.getByLabel(label, options)),
197
+ getByTestId: (testId) => PlaywrightLocator.make(page.getByTestId(testId)),
198
+ url: Effect.sync(() => page.url()),
199
+ reload: use((p) => p.reload()),
200
+ close: use((p) => p.close()),
201
+ click: (selector, options) => use((p) => p.click(selector, options)),
202
+ eventStream: (event) => Stream.asyncPush((emit) => Effect.acquireRelease(Effect.sync(() => {
203
+ const callback = emit.single;
204
+ const closeCallback = emit.end;
205
+ page.on(event, callback);
206
+ page.once("close", closeCallback);
207
+ return {
208
+ callback,
209
+ closeCallback
210
+ };
211
+ }), ({ callback, closeCallback }) => Effect.sync(() => {
212
+ page.off(event, callback);
213
+ page.off("close", closeCallback);
214
+ }))).pipe(Stream.map((e) => {
215
+ const mapper = eventMappings[event];
216
+ return mapper(e);
217
+ })),
218
+ use
219
+ });
220
+ }
221
+ };
222
+ const eventMappings = {
223
+ close: PlaywrightPage.make,
224
+ console: identity,
225
+ crash: PlaywrightPage.make,
226
+ dialog: PlaywrightDialog.make,
227
+ domcontentloaded: PlaywrightPage.make,
228
+ download: PlaywrightDownload.make,
229
+ filechooser: PlaywrightFileChooser.make,
230
+ frameattached: PlaywrightFrame.make,
231
+ framedetached: PlaywrightFrame.make,
232
+ framenavigated: PlaywrightFrame.make,
233
+ load: PlaywrightPage.make,
234
+ pageerror: identity,
235
+ popup: PlaywrightPage.make,
236
+ request: PlaywrightRequest.make,
237
+ requestfailed: PlaywrightRequest.make,
238
+ requestfinished: PlaywrightRequest.make,
239
+ response: PlaywrightResponse.make,
240
+ websocket: identity,
241
+ worker: PlaywrightWorker.make
242
+ };
243
+
244
+ //#endregion
245
+ //#region src/browser-context.ts
246
+ var PlaywrightBrowserContext = class PlaywrightBrowserContext extends Context.Tag("cehs/backend/lib/playwright/PlaywrightBrowserContext")() {
247
+ static make(context) {
248
+ const use = useHelper(context);
249
+ return PlaywrightBrowserContext.of({
250
+ pages: Effect.sync(() => context.pages().map(PlaywrightPage.make)),
251
+ newPage: use((c) => c.newPage().then(PlaywrightPage.make)),
252
+ close: use((c) => c.close())
253
+ });
254
+ }
255
+ };
256
+
257
+ //#endregion
258
+ //#region src/browser.ts
259
+ /**
260
+ * @category tag
261
+ */
262
+ var PlaywrightBrowser = class PlaywrightBrowser extends Context.Tag("cehs/backend/lib/playwright/PlaywrightBrowser")() {
263
+ /**
264
+ * @category constructor
265
+ */
266
+ static make(browser) {
267
+ const use = useHelper(browser);
268
+ return PlaywrightBrowser.of({
269
+ newPage: (options) => use((browser$1) => browser$1.newPage(options).then(PlaywrightPage.make)),
270
+ close: use((browser$1) => browser$1.close()),
271
+ contexts: Effect.sync(() => browser.contexts().map(PlaywrightBrowserContext.make)),
272
+ newContext: (options) => Effect.acquireRelease(use((browser$1) => browser$1.newContext(options).then(PlaywrightBrowserContext.make)), (context) => context.close.pipe(Effect.ignoreLogged)),
273
+ browserType: Effect.sync(() => browser.browserType()),
274
+ version: Effect.sync(() => browser.version()),
275
+ isConnected: Effect.sync(() => browser.isConnected()),
276
+ use
277
+ });
278
+ }
279
+ };
280
+
281
+ //#endregion
282
+ //#region src/playwright.ts
283
+ const launch = Effect.fn(function* (browserType, options) {
284
+ const rawBrowser = yield* Effect.tryPromise({
285
+ try: () => browserType.launch(options),
286
+ catch: wrapError
287
+ });
288
+ return PlaywrightBrowser.make(rawBrowser);
289
+ });
290
+ const connectCDP = Effect.fn(function* (cdpUrl, options) {
291
+ const browser = yield* Effect.tryPromise({
292
+ try: () => chromium.connectOverCDP(cdpUrl, options),
293
+ catch: wrapError
294
+ });
295
+ return PlaywrightBrowser.make(browser);
296
+ });
297
+ var Playwright = class Playwright extends Context.Tag("effect-playwright/index/Playwright")() {
298
+ /**
299
+ * @category layer
300
+ */
301
+ static layer = Layer.succeed(Playwright, {
302
+ launch,
303
+ launchScoped: (browserType, options) => Effect.acquireRelease(launch(browserType, options), (browser) => browser.close.pipe(Effect.ignore)),
304
+ connectCDP,
305
+ connectCDPScoped: (cdpUrl, options) => Effect.acquireRelease(connectCDP(cdpUrl, options), (browser) => browser.close.pipe(Effect.ignore))
306
+ });
307
+ };
308
+
309
+ //#endregion
310
+ export { PlaywrightLocator as i, PlaywrightBrowser as n, PlaywrightPage as r, Playwright as t };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "effect-playwright",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "description": "An Effect-based Playwright library.",
6
6
  "author": "Jobflow GmbH",
7
7
  "license": "ISC",
@@ -37,16 +37,17 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@biomejs/biome": "2.3.11",
40
- "@effect/language-service": "^0.64.1",
40
+ "@effect/language-service": "^0.65.0",
41
41
  "@effect/platform": "^0.94.1",
42
42
  "@effect/platform-node": "^0.104.0",
43
43
  "@effect/vitest": "^0.27.0",
44
+ "@types/node": "^25.0.8",
44
45
  "effect": "^3.19.14",
45
46
  "playwright": "^1.57.0",
46
- "tsdown": "^0.19.0",
47
+ "tsdown": "0.20.0-beta.1",
47
48
  "tsx": "^4.21.0",
48
49
  "typescript": "^5.9.3",
49
- "vitest": "^4.0.16"
50
+ "vitest": "^4.0.17"
50
51
  },
51
52
  "types": "./dist/index.d.mts",
52
53
  "scripts": {
@@ -1,167 +0,0 @@
1
- import { Context, Data, Effect, Layer, Stream } from "effect";
2
- import { chromium, errors } from "playwright-core";
3
-
4
- //#region src/errors.ts
5
- var PlaywrightError = class extends Data.TaggedError("PlaywrightError") {};
6
- function wrapError(error) {
7
- if (error instanceof errors.TimeoutError) return new PlaywrightError({
8
- reason: "Timeout",
9
- cause: error
10
- });
11
- else return new PlaywrightError({
12
- reason: "Unknown",
13
- cause: error
14
- });
15
- }
16
-
17
- //#endregion
18
- //#region src/utils.ts
19
- /** @internal */
20
- const useHelper = (api) => (userFunction) => Effect.tryPromise(() => userFunction(api)).pipe(Effect.mapError(wrapError));
21
-
22
- //#endregion
23
- //#region src/locator.ts
24
- /**
25
- * A service that provides a `PlaywrightLocator` instance.
26
- *
27
- * @since 0.1.0
28
- * @category tag
29
- */
30
- var PlaywrightLocator = class PlaywrightLocator extends Context.Tag("effect-playwright/PlaywrightLocator")() {
31
- /**
32
- * Creates a `PlaywrightLocator` from a Playwright `Locator` instance. This is mostly for internal use.
33
- * But you could use this if you have used `use` or similar to wrap the locator.
34
- *
35
- * @example
36
- * ```ts
37
- * const playwrightNativeLocator = yield* page.use((p) => p.locator("button"));
38
- * const locator = PlaywrightLocator.make(playwrightNativeLocator);
39
- * ```
40
- *
41
- * @param locator - The Playwright `Locator` instance to wrap.
42
- * @since 0.1.0
43
- * @category constructor
44
- */
45
- static make(locator) {
46
- const use = useHelper(locator);
47
- return PlaywrightLocator.of({
48
- click: (options) => use((l) => l.click(options)),
49
- fill: (value, options) => use((l) => l.fill(value, options)),
50
- getAttribute: (name, options) => use((l) => l.getAttribute(name, options)),
51
- innerText: (options) => use((l) => l.innerText(options)),
52
- innerHTML: (options) => use((l) => l.innerHTML(options)),
53
- inputValue: (options) => use((l) => l.inputValue(options)),
54
- textContent: (options) => use((l) => l.textContent(options)),
55
- count: use((l) => l.count()),
56
- first: () => PlaywrightLocator.make(locator.first()),
57
- last: () => PlaywrightLocator.make(locator.last()),
58
- nth: (index) => PlaywrightLocator.make(locator.nth(index)),
59
- evaluate: (pageFunction, arg, options) => use((l) => l.evaluate(pageFunction, arg, options)),
60
- use
61
- });
62
- }
63
- };
64
-
65
- //#endregion
66
- //#region src/page.ts
67
- /**
68
- * @category tag
69
- */
70
- var PlaywrightPage = class PlaywrightPage extends Context.Tag("effect-playwright/PlaywrightPage")() {
71
- /**
72
- * Creates a `PlaywrightPage` from a Playwright `Page` instance.
73
- *
74
- * @param page - The Playwright `Page` instance to wrap.
75
- * @since 0.1.0
76
- */
77
- static make(page) {
78
- const use = useHelper(page);
79
- return PlaywrightPage.of({
80
- goto: (url, options) => use((p) => p.goto(url, options)),
81
- waitForURL: (url, options) => use((p) => p.waitForURL(url, options)),
82
- title: use((p) => p.title()),
83
- evaluate: (f, arg) => use((p) => p.evaluate(f, arg)),
84
- locator: (selector, options) => PlaywrightLocator.make(page.locator(selector, options)),
85
- getByRole: (role, options) => PlaywrightLocator.make(page.getByRole(role, options)),
86
- getByText: (text, options) => PlaywrightLocator.make(page.getByText(text, options)),
87
- getByLabel: (label, options) => PlaywrightLocator.make(page.getByLabel(label, options)),
88
- getByTestId: (testId) => PlaywrightLocator.make(page.getByTestId(testId)),
89
- url: Effect.sync(() => page.url()),
90
- reload: use((p) => p.reload()),
91
- close: use((p) => p.close()),
92
- click: (selector, options) => use((p) => p.click(selector, options)),
93
- eventStream: (event) => Stream.asyncPush((emit) => Effect.acquireRelease(Effect.sync(() => page.on(event, emit.single)), () => Effect.sync(() => page.off(event, emit.single)))),
94
- use
95
- });
96
- }
97
- };
98
-
99
- //#endregion
100
- //#region src/browser-context.ts
101
- var PlaywrightBrowserContext = class PlaywrightBrowserContext extends Context.Tag("cehs/backend/lib/playwright/PlaywrightBrowserContext")() {
102
- static make(context) {
103
- const use = useHelper(context);
104
- return PlaywrightBrowserContext.of({
105
- pages: Effect.sync(() => context.pages().map(PlaywrightPage.make)),
106
- newPage: use((c) => c.newPage().then(PlaywrightPage.make)),
107
- close: use((c) => c.close())
108
- });
109
- }
110
- };
111
-
112
- //#endregion
113
- //#region src/browser.ts
114
- /**
115
- * @category tag
116
- */
117
- var PlaywrightBrowser = class PlaywrightBrowser extends Context.Tag("cehs/backend/lib/playwright/PlaywrightBrowser")() {
118
- /**
119
- * @category constructor
120
- */
121
- static make(browser) {
122
- const use = useHelper(browser);
123
- return PlaywrightBrowser.of({
124
- newPage: (options) => use((browser$1) => browser$1.newPage(options).then(PlaywrightPage.make)),
125
- close: use((browser$1) => browser$1.close()),
126
- contexts: Effect.sync(() => browser.contexts().map(PlaywrightBrowserContext.make)),
127
- newContext: (options) => Effect.acquireRelease(use((browser$1) => browser$1.newContext(options).then(PlaywrightBrowserContext.make)), (context) => context.close.pipe(Effect.ignoreLogged)),
128
- browserType: Effect.sync(() => browser.browserType()),
129
- version: Effect.sync(() => browser.version()),
130
- isConnected: Effect.sync(() => browser.isConnected()),
131
- use
132
- });
133
- }
134
- };
135
-
136
- //#endregion
137
- //#region src/playwright.ts
138
- const launch = Effect.fn(function* (browserType, options) {
139
- const rawBrowser = yield* Effect.tryPromise({
140
- try: () => browserType.launch(options),
141
- catch: wrapError
142
- });
143
- return PlaywrightBrowser.make(rawBrowser);
144
- });
145
- var Playwright = class Playwright extends Context.Tag("effect-playwright/index/Playwright")() {
146
- /**
147
- * @category layer
148
- */
149
- static layer = Layer.succeed(Playwright, {
150
- launch,
151
- launchScoped: Effect.fn(function* (browserType, options) {
152
- const browser = yield* launch(browserType, options);
153
- yield* Effect.addFinalizer(() => browser.close.pipe(Effect.ignore));
154
- return browser;
155
- }),
156
- connectCDP: Effect.fn(function* (cdpUrl, options) {
157
- const browser = yield* Effect.tryPromise({
158
- try: () => chromium.connectOverCDP(cdpUrl, options),
159
- catch: wrapError
160
- });
161
- return PlaywrightBrowser.make(browser);
162
- })
163
- });
164
- };
165
-
166
- //#endregion
167
- export { PlaywrightLocator as i, PlaywrightBrowser as n, PlaywrightPage as r, Playwright as t };