effect-playwright 0.1.1 → 0.2.0

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
@@ -3,6 +3,7 @@
3
3
  [![NPM Version](https://img.shields.io/npm/v/effect-playwright)](https://www.npmjs.com/package/effect-playwright)
4
4
  [![GitHub License](https://img.shields.io/github/license/Jobflow-io/effect-playwright)](https://github.com/Jobflow-io/effect-playwright/blob/main/LICENSE)
5
5
  [![Effect: yes](https://img.shields.io/badge/effect-yes-blue)](https://effect.website/)
6
+ [![Documentation](https://img.shields.io/badge/view_documentation-purple)](https://jobflow-io.github.io/effect-playwright/modules/index.html)
6
7
 
7
8
  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.
8
9
 
@@ -125,6 +126,41 @@ const program = Effect.gen(function* () {
125
126
  }).pipe(PlaywrightEnvironment.withBrowser);
126
127
  ```
127
128
 
129
+ ## Event Handling
130
+
131
+ You can listen to Playwright events using the `eventStream` method. This returns an Effect `Stream` that emits events as they occur.
132
+
133
+ > [!NOTE]
134
+ > `eventStream` emits "Effectified" wrappers (e.g., `PlaywrightRequest`, `PlaywrightResponse`, `PlaywrightPage`) for most events. This allows you to continue using the Effect ecosystem seamlessly within your event handlers.
135
+
136
+ The stream is automatically managed and will close when the underlying resource (like the Page or Browser) is closed.
137
+
138
+ ### Example: Monitoring Network Requests
139
+
140
+ Since event streams run indefinitely until the resource closes, you often need to **fork** the resulting effect so it runs in the background without blocking your main program flow.
141
+
142
+ ```ts
143
+ const program = Effect.gen(function* () {
144
+ const browser = yield* PlaywrightBrowser;
145
+ const page = yield* browser.newPage();
146
+
147
+ // Create a stream of request events
148
+ yield* page.eventStream("request").pipe(
149
+ Stream.runForEach((request) =>
150
+ Effect.gen(function* () {
151
+ const url = yield* request.url;
152
+ yield* Effect.log(`Request: ${url}`);
153
+ }),
154
+ ),
155
+
156
+ // Fork to run it in the background
157
+ Effect.fork,
158
+ );
159
+
160
+ yield* page.goto("https://example.com");
161
+ }).pipe(PlaywrightEnvironment.withBrowser);
162
+ ```
163
+
128
164
  ## Accessing Native Playwright
129
165
 
130
166
  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,9 +1,28 @@
1
- import { d as PlaywrightError, o as PlaywrightBrowser } from "../index-DnbVDccF.mjs";
2
- import { Context, Effect, Layer } from "effect";
1
+ import { d as PlaywrightPageService, o as PlaywrightBrowser, s as PlaywrightBrowserService, v as PlaywrightFrameService, x as PlaywrightError } from "../index-K6LNMeXC.mjs";
2
+ import { Context, Effect, Layer, Stream } from "effect";
3
3
  import { BrowserType, LaunchOptions } from "playwright-core";
4
4
  import { Scope as Scope$1 } from "effect/Scope";
5
5
 
6
- //#region src/experimental/environment.d.ts
6
+ //#region src/experimental/browser-utils.d.ts
7
+ declare namespace browser_utils_d_exports {
8
+ export { allFrameNavigatedEventStream, allFrames, allPages };
9
+ }
10
+ /**
11
+ * Returns all pages in the browser from all contexts.
12
+ * @category util
13
+ */
14
+ declare const allPages: (browser: PlaywrightBrowserService) => Effect.Effect<PlaywrightPageService[], never, never>;
15
+ /**
16
+ * Returns all frames in the browser from all pages in all contexts.
17
+ * @category util
18
+ */
19
+ declare const allFrames: (browser: PlaywrightBrowserService) => Effect.Effect<(readonly PlaywrightFrameService[])[], PlaywrightError, never>;
20
+ /**
21
+ * Returns a stream of all framenavigated events for all current and future pages in the browser.
22
+ * In all current contexts (but not future contexts).
23
+ * @category util
24
+ */
25
+ declare const allFrameNavigatedEventStream: (browser: PlaywrightBrowserService) => Stream.Stream<PlaywrightFrameService, never, never>;
7
26
  declare namespace environment_d_exports {
8
27
  export { PlaywrightEnvironment, layer, withBrowser };
9
28
  }
@@ -13,9 +32,9 @@ declare const PlaywrightEnvironment_base: Context.TagClass<PlaywrightEnvironment
13
32
  /**
14
33
  * Most of the time you want to use the same kind of browser and configuration every time you use Playwright.
15
34
  * `PlaywrightEnvironment` is a service that allows you to configure how browsers are launched once. You can then
16
- * use {@link PlaywrightEnvironment.browser} to start browsers scoped to the current lifetime. They will be closed when the scope is closed.
35
+ * use `PlaywrightEnvironment.browser` to start browsers scoped to the current lifetime. They will be closed when the scope is closed.
17
36
  *
18
- * You can use {@link PlaywrightEnvironment.withBrowser} to provide the `PlaywrightBrowser` service to the wrapped effect. This
37
+ * You can use {@link withBrowser} to provide the `PlaywrightBrowser` service to the wrapped effect. This
19
38
  * also allows you to re-use the same browser as many times as you want.
20
39
  *
21
40
  * @since 0.1.0
@@ -70,7 +89,8 @@ declare const layer: (browser: BrowserType, launchOptions?: LaunchOptions) => La
70
89
  * ```
71
90
  *
72
91
  * @since 0.1.0
92
+ * @category util
73
93
  */
74
94
  declare const withBrowser: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, PlaywrightError | E, PlaywrightEnvironment | Exclude<R, PlaywrightBrowser>>;
75
95
  //#endregion
76
- export { environment_d_exports as PlaywrightEnvironment };
96
+ export { browser_utils_d_exports as BrowserUtils, environment_d_exports as PlaywrightEnvironment };
@@ -1,7 +1,36 @@
1
1
  import { t as __exportAll } from "../chunk-BiucMVzj.mjs";
2
- import { n as PlaywrightBrowser, t as Playwright } from "../src-BGGNNney.mjs";
3
- import { Context, Effect, Layer } from "effect";
2
+ import { n as PlaywrightBrowser, t as Playwright } from "../src-Bf0XqK7M.mjs";
3
+ import { Array, Context, Effect, Layer, Stream, pipe } from "effect";
4
4
 
5
+ //#region src/experimental/browser-utils.ts
6
+ var browser_utils_exports = /* @__PURE__ */ __exportAll({
7
+ allFrameNavigatedEventStream: () => allFrameNavigatedEventStream,
8
+ allFrames: () => allFrames,
9
+ allPages: () => allPages
10
+ });
11
+ /**
12
+ * Returns all pages in the browser from all contexts.
13
+ * @category util
14
+ */
15
+ const allPages = (browser) => browser.contexts.pipe(Effect.flatMap((contexts) => Effect.all(contexts.map((context) => context.pages))), Effect.map(Array.flatten));
16
+ /**
17
+ * Returns all frames in the browser from all pages in all contexts.
18
+ * @category util
19
+ */
20
+ const allFrames = (browser) => allPages(browser).pipe(Effect.flatMap((pages) => Effect.all(pages.map((page) => page.frames))));
21
+ /**
22
+ * Returns a stream of all framenavigated events for all current and future pages in the browser.
23
+ * In all current contexts (but not future contexts).
24
+ * @category util
25
+ */
26
+ const allFrameNavigatedEventStream = (browser) => Effect.gen(function* () {
27
+ const contexts = yield* browser.contexts;
28
+ const currentPages = (yield* pipe(contexts.map((c) => c.pages), Effect.all, Effect.map(Array.flatten))).map((page) => page.eventStream("framenavigated"));
29
+ const newPages = pipe(contexts.map((c) => c.eventStream("page")), Stream.mergeAll({ concurrency: "unbounded" }), Stream.flatMap((page) => page.eventStream("framenavigated"), { concurrency: "unbounded" }));
30
+ return Stream.mergeAll([newPages, ...currentPages], { concurrency: "unbounded" });
31
+ }).pipe(Stream.unwrap);
32
+
33
+ //#endregion
5
34
  //#region src/experimental/environment.ts
6
35
  var environment_exports = /* @__PURE__ */ __exportAll({
7
36
  PlaywrightEnvironment: () => PlaywrightEnvironment,
@@ -11,9 +40,9 @@ var environment_exports = /* @__PURE__ */ __exportAll({
11
40
  /**
12
41
  * Most of the time you want to use the same kind of browser and configuration every time you use Playwright.
13
42
  * `PlaywrightEnvironment` is a service that allows you to configure how browsers are launched once. You can then
14
- * use {@link PlaywrightEnvironment.browser} to start browsers scoped to the current lifetime. They will be closed when the scope is closed.
43
+ * use `PlaywrightEnvironment.browser` to start browsers scoped to the current lifetime. They will be closed when the scope is closed.
15
44
  *
16
- * You can use {@link PlaywrightEnvironment.withBrowser} to provide the `PlaywrightBrowser` service to the wrapped effect. This
45
+ * You can use {@link withBrowser} to provide the `PlaywrightBrowser` service to the wrapped effect. This
17
46
  * also allows you to re-use the same browser as many times as you want.
18
47
  *
19
48
  * @since 0.1.0
@@ -72,8 +101,9 @@ const layer = (browser, launchOptions) => {
72
101
  * ```
73
102
  *
74
103
  * @since 0.1.0
104
+ * @category util
75
105
  */
76
106
  const withBrowser = Effect.provide(PlaywrightEnvironment.pipe(Effect.map((e) => e.browser), Effect.flatten, Layer.scoped(PlaywrightBrowser)));
77
107
 
78
108
  //#endregion
79
- export { environment_exports as PlaywrightEnvironment };
109
+ export { browser_utils_exports as BrowserUtils, environment_exports as PlaywrightEnvironment };