effect-playwright 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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";
2
- export { LaunchOptions, NewContextOptions, NewPageOptions, Playwright, PlaywrightBrowser, PlaywrightLocator, PlaywrightLocatorService, PlaywrightPage, PlaywrightPageService, PlaywrightService };
1
+ import { S as PlaywrightErrorReason, _ as PlaywrightFrame, a as NewPageOptions, b as PlaywrightWorker, c as PlaywrightBrowserContext, d as PlaywrightPageService, f as PlaywrightLocator, g as PlaywrightFileChooser, h as PlaywrightDownload, i as NewContextOptions, l as PlaywrightBrowserContextService, m as PlaywrightDialog, n as PlaywrightService, o as PlaywrightBrowser, p as PlaywrightLocatorService, r as LaunchOptions, s as PlaywrightBrowserService, t as Playwright, u as PlaywrightPage, v as PlaywrightRequest, x as PlaywrightError, y as PlaywrightResponse } from "./index-BTxElyN5.mjs";
2
+ export { LaunchOptions, NewContextOptions, NewPageOptions, Playwright, PlaywrightBrowser, PlaywrightBrowserContext, PlaywrightBrowserContextService, PlaywrightBrowserService, PlaywrightDialog, PlaywrightDownload, PlaywrightError, PlaywrightErrorReason, PlaywrightFileChooser, PlaywrightFrame, PlaywrightLocator, PlaywrightLocatorService, PlaywrightPage, PlaywrightPageService, PlaywrightRequest, PlaywrightResponse, PlaywrightService, PlaywrightWorker };
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 { a as PlaywrightDownload, c as PlaywrightRequest, d as PlaywrightPage, f as PlaywrightLocator, i as PlaywrightDialog, l as PlaywrightResponse, n as PlaywrightBrowser, o as PlaywrightFileChooser, p as PlaywrightError, r as PlaywrightBrowserContext, s as PlaywrightFrame, t as Playwright, u as PlaywrightWorker } from "./src-D0uXY5ik.mjs";
2
2
 
3
- export { Playwright, PlaywrightBrowser, PlaywrightLocator, PlaywrightPage };
3
+ export { Playwright, PlaywrightBrowser, PlaywrightBrowserContext, PlaywrightDialog, PlaywrightDownload, PlaywrightError, PlaywrightFileChooser, PlaywrightFrame, PlaywrightLocator, PlaywrightPage, PlaywrightRequest, PlaywrightResponse, PlaywrightWorker };
@@ -0,0 +1,389 @@
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
+ /**
6
+ * Error type that is returned when a Playwright error occurs.
7
+ * Reason can either be "Timeout" or "Unknown".
8
+ *
9
+ * Timeout errors occur when a timeout is reached. All other errors are
10
+ * grouped under "Unknown".
11
+ *
12
+ * @category error
13
+ * @since 0.1.0
14
+ */
15
+ var PlaywrightError = class extends Data.TaggedError("PlaywrightError") {};
16
+ function wrapError(error) {
17
+ if (error instanceof errors.TimeoutError) return new PlaywrightError({
18
+ reason: "Timeout",
19
+ cause: error
20
+ });
21
+ else return new PlaywrightError({
22
+ reason: "Unknown",
23
+ cause: error
24
+ });
25
+ }
26
+
27
+ //#endregion
28
+ //#region src/utils.ts
29
+ /** @internal */
30
+ const useHelper = (api) => (userFunction) => Effect.tryPromise(() => userFunction(api)).pipe(Effect.mapError(wrapError));
31
+
32
+ //#endregion
33
+ //#region src/locator.ts
34
+ /**
35
+ * A service that provides a `PlaywrightLocator` instance.
36
+ *
37
+ * @since 0.1.0
38
+ * @category tag
39
+ */
40
+ var PlaywrightLocator = class PlaywrightLocator extends Context.Tag("effect-playwright/PlaywrightLocator")() {
41
+ /**
42
+ * Creates a `PlaywrightLocator` from a Playwright `Locator` instance. This is mostly for internal use.
43
+ * But you could use this if you have used `use` or similar to wrap the locator.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const playwrightNativeLocator = yield* page.use((p) => p.locator("button"));
48
+ * const locator = PlaywrightLocator.make(playwrightNativeLocator);
49
+ * ```
50
+ *
51
+ * @param locator - The Playwright `Locator` instance to wrap.
52
+ * @since 0.1.0
53
+ * @category constructor
54
+ */
55
+ static make(locator) {
56
+ const use = useHelper(locator);
57
+ return PlaywrightLocator.of({
58
+ click: (options) => use((l) => l.click(options)),
59
+ fill: (value, options) => use((l) => l.fill(value, options)),
60
+ getAttribute: (name, options) => use((l) => l.getAttribute(name, options)),
61
+ innerText: (options) => use((l) => l.innerText(options)),
62
+ innerHTML: (options) => use((l) => l.innerHTML(options)),
63
+ inputValue: (options) => use((l) => l.inputValue(options)),
64
+ textContent: (options) => use((l) => l.textContent(options)),
65
+ count: use((l) => l.count()),
66
+ first: () => PlaywrightLocator.make(locator.first()),
67
+ last: () => PlaywrightLocator.make(locator.last()),
68
+ nth: (index) => PlaywrightLocator.make(locator.nth(index)),
69
+ evaluate: (pageFunction, arg, options) => use((l) => l.evaluate(pageFunction, arg, options)),
70
+ use
71
+ });
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ //#region src/page.ts
77
+ const eventMappings$2 = {
78
+ close: (page) => PlaywrightPage.make(page),
79
+ console: identity,
80
+ crash: (page) => PlaywrightPage.make(page),
81
+ dialog: (dialog) => PlaywrightDialog.make(dialog),
82
+ domcontentloaded: (page) => PlaywrightPage.make(page),
83
+ download: (download) => PlaywrightDownload.make(download),
84
+ filechooser: (fileChooser) => PlaywrightFileChooser.make(fileChooser),
85
+ frameattached: (frame) => PlaywrightFrame.make(frame),
86
+ framedetached: (frame) => PlaywrightFrame.make(frame),
87
+ framenavigated: (frame) => PlaywrightFrame.make(frame),
88
+ load: (page) => PlaywrightPage.make(page),
89
+ pageerror: identity,
90
+ popup: (page) => PlaywrightPage.make(page),
91
+ request: (request) => PlaywrightRequest.make(request),
92
+ requestfailed: (request) => PlaywrightRequest.make(request),
93
+ requestfinished: (request) => PlaywrightRequest.make(request),
94
+ response: (response) => PlaywrightResponse.make(response),
95
+ websocket: identity,
96
+ worker: (worker) => PlaywrightWorker.make(worker)
97
+ };
98
+ /**
99
+ * @category tag
100
+ */
101
+ var PlaywrightPage = class PlaywrightPage extends Context.Tag("effect-playwright/PlaywrightPage")() {
102
+ /**
103
+ * Creates a `PlaywrightPage` from a Playwright `Page` instance.
104
+ *
105
+ * @param page - The Playwright `Page` instance to wrap.
106
+ * @since 0.1.0
107
+ */
108
+ static make(page) {
109
+ const use = useHelper(page);
110
+ return PlaywrightPage.of({
111
+ goto: (url, options) => use((p) => p.goto(url, options)),
112
+ waitForURL: (url, options) => use((p) => p.waitForURL(url, options)),
113
+ title: use((p) => p.title()),
114
+ evaluate: (f, arg) => use((p) => p.evaluate(f, arg)),
115
+ locator: (selector, options) => PlaywrightLocator.make(page.locator(selector, options)),
116
+ getByRole: (role, options) => PlaywrightLocator.make(page.getByRole(role, options)),
117
+ getByText: (text, options) => PlaywrightLocator.make(page.getByText(text, options)),
118
+ getByLabel: (label, options) => PlaywrightLocator.make(page.getByLabel(label, options)),
119
+ getByTestId: (testId) => PlaywrightLocator.make(page.getByTestId(testId)),
120
+ url: Effect.sync(() => page.url()),
121
+ reload: use((p) => p.reload()),
122
+ close: use((p) => p.close()),
123
+ click: (selector, options) => use((p) => p.click(selector, options)),
124
+ eventStream: (event) => Stream.asyncPush((emit) => Effect.acquireRelease(Effect.sync(() => {
125
+ page.on(event, emit.single);
126
+ page.once("close", emit.end);
127
+ }), () => Effect.sync(() => {
128
+ page.off(event, emit.single);
129
+ page.off("close", emit.end);
130
+ }))).pipe(Stream.map((e) => {
131
+ const mapping = eventMappings$2[event];
132
+ return mapping(e);
133
+ })),
134
+ use
135
+ });
136
+ }
137
+ };
138
+
139
+ //#endregion
140
+ //#region src/common.ts
141
+ /**
142
+ * @category model
143
+ * @since 0.1.2
144
+ */
145
+ var PlaywrightFrame = class PlaywrightFrame extends Data.TaggedClass("PlaywrightFrame") {
146
+ static make(frame) {
147
+ return new PlaywrightFrame({ use: useHelper(frame) });
148
+ }
149
+ };
150
+ /**
151
+ * @category model
152
+ * @since 0.1.2
153
+ */
154
+ var PlaywrightRequest = class PlaywrightRequest extends Data.TaggedClass("PlaywrightRequest") {
155
+ static make(request) {
156
+ const use = useHelper(request);
157
+ return new PlaywrightRequest({
158
+ allHeaders: use(() => request.allHeaders()),
159
+ failure: Option.liftNullable(request.failure),
160
+ frame: Effect.sync(() => PlaywrightFrame.make(request.frame())),
161
+ headerValue: (name) => use(() => request.headerValue(name)).pipe(Effect.map(Option.fromNullable)),
162
+ headers: Effect.sync(() => request.headers()),
163
+ headersArray: use(() => request.headersArray()),
164
+ isNavigationRequest: Effect.sync(() => request.isNavigationRequest()),
165
+ method: Effect.sync(() => request.method()),
166
+ postData: Option.liftNullable(request.postData),
167
+ postDataBuffer: Option.liftNullable(request.postDataBuffer),
168
+ postDataJSON: use(() => request.postDataJSON()).pipe(Effect.map(Option.fromNullable)),
169
+ redirectedFrom: () => Option.fromNullable(request.redirectedFrom()).pipe(Option.map(PlaywrightRequest.make)),
170
+ redirectedTo: () => Option.fromNullable(request.redirectedTo()).pipe(Option.map(PlaywrightRequest.make)),
171
+ resourceType: Effect.sync(() => request.resourceType()),
172
+ response: use(() => request.response()).pipe(Effect.map(Option.fromNullable), Effect.map(Option.map(PlaywrightResponse.make))),
173
+ serviceWorker: () => Option.fromNullable(request.serviceWorker()).pipe(Option.map(PlaywrightWorker.make)),
174
+ sizes: use(() => request.sizes()),
175
+ timing: Effect.sync(() => request.timing()),
176
+ url: Effect.sync(() => request.url())
177
+ });
178
+ }
179
+ };
180
+ /**
181
+ * @category model
182
+ * @since 0.1.2
183
+ */
184
+ var PlaywrightResponse = class PlaywrightResponse extends Data.TaggedClass("PlaywrightResponse") {
185
+ static make(response) {
186
+ const use = useHelper(response);
187
+ return new PlaywrightResponse({
188
+ allHeaders: use(() => response.allHeaders()),
189
+ body: use(() => response.body()),
190
+ finished: use(() => response.finished()),
191
+ frame: Effect.sync(() => PlaywrightFrame.make(response.frame())),
192
+ fromServiceWorker: Effect.sync(() => response.fromServiceWorker()),
193
+ headers: Effect.sync(() => response.headers()),
194
+ headersArray: use(() => response.headersArray()),
195
+ headerValue: (name) => use(() => response.headerValue(name)).pipe(Effect.map(Option.fromNullable)),
196
+ headerValues: (name) => use(() => response.headerValues(name)),
197
+ json: use(() => response.json()),
198
+ ok: Effect.sync(() => response.ok()),
199
+ request: () => PlaywrightRequest.make(response.request()),
200
+ securityDetails: use(() => response.securityDetails()).pipe(Effect.map(Option.fromNullable)),
201
+ serverAddr: use(() => response.serverAddr()).pipe(Effect.map(Option.fromNullable)),
202
+ status: Effect.sync(() => response.status()),
203
+ statusText: Effect.sync(() => response.statusText()),
204
+ text: use(() => response.text()),
205
+ url: Effect.sync(() => response.url())
206
+ });
207
+ }
208
+ };
209
+ /**
210
+ * @category model
211
+ * @since 0.1.2
212
+ */
213
+ var PlaywrightWorker = class PlaywrightWorker extends Data.TaggedClass("PlaywrightWorker") {
214
+ static make(worker) {
215
+ const use = useHelper(worker);
216
+ return new PlaywrightWorker({
217
+ evaluate: (f, arg) => use((w) => w.evaluate(f, arg)),
218
+ url: Effect.sync(() => worker.url())
219
+ });
220
+ }
221
+ };
222
+ /**
223
+ * @category model
224
+ * @since 0.1.2
225
+ */
226
+ var PlaywrightDialog = class PlaywrightDialog extends Data.TaggedClass("PlaywrightDialog") {
227
+ static make(dialog) {
228
+ const use = useHelper(dialog);
229
+ return new PlaywrightDialog({
230
+ accept: (promptText) => use(() => dialog.accept(promptText)),
231
+ defaultValue: Effect.sync(() => dialog.defaultValue()),
232
+ dismiss: use(() => dialog.dismiss()),
233
+ message: Effect.sync(() => dialog.message()),
234
+ page: () => Option.fromNullable(dialog.page()).pipe(Option.map(PlaywrightPage.make)),
235
+ type: Effect.sync(() => dialog.type())
236
+ });
237
+ }
238
+ };
239
+ /**
240
+ * @category model
241
+ * @since 0.1.2
242
+ */
243
+ var PlaywrightFileChooser = class PlaywrightFileChooser extends Data.TaggedClass("PlaywrightFileChooser") {
244
+ static make(fileChooser) {
245
+ const use = useHelper(fileChooser);
246
+ return new PlaywrightFileChooser({
247
+ element: () => fileChooser.element(),
248
+ isMultiple: Effect.sync(() => fileChooser.isMultiple()),
249
+ page: () => PlaywrightPage.make(fileChooser.page()),
250
+ setFiles: (files, options) => use(() => fileChooser.setFiles(files, options))
251
+ });
252
+ }
253
+ };
254
+ /**
255
+ * @category model
256
+ * @since 0.1.2
257
+ */
258
+ var PlaywrightDownload = class PlaywrightDownload extends Data.TaggedClass("PlaywrightDownload") {
259
+ static make(download) {
260
+ const use = useHelper(download);
261
+ return new PlaywrightDownload({
262
+ cancel: use(() => download.cancel()),
263
+ createReadStream: Stream.empty,
264
+ delete: use(() => download.delete()),
265
+ failure: use(() => download.failure()).pipe(Effect.map(Option.fromNullable)),
266
+ page: () => PlaywrightPage.make(download.page()),
267
+ path: use(() => download.path()).pipe(Effect.map(Option.fromNullable)),
268
+ saveAs: (path) => use(() => download.saveAs(path)),
269
+ suggestedFilename: Effect.sync(() => download.suggestedFilename()),
270
+ url: Effect.sync(() => download.url()),
271
+ use
272
+ });
273
+ }
274
+ };
275
+
276
+ //#endregion
277
+ //#region src/browser-context.ts
278
+ const eventMappings$1 = {
279
+ backgroundpage: (page) => PlaywrightPage.make(page),
280
+ close: (context) => PlaywrightBrowserContext.make(context),
281
+ console: identity,
282
+ dialog: (dialog) => PlaywrightDialog.make(dialog),
283
+ page: (page) => PlaywrightPage.make(page),
284
+ request: (request) => PlaywrightRequest.make(request),
285
+ requestfailed: (request) => PlaywrightRequest.make(request),
286
+ requestfinished: (request) => PlaywrightRequest.make(request),
287
+ response: (response) => PlaywrightResponse.make(response),
288
+ serviceworker: (worker) => PlaywrightWorker.make(worker),
289
+ weberror: identity
290
+ };
291
+ /**
292
+ * @category tag
293
+ */
294
+ var PlaywrightBrowserContext = class PlaywrightBrowserContext extends Context.Tag("effect-playwright/PlaywrightBrowserContext")() {
295
+ /**
296
+ * Creates a `PlaywrightBrowserContext` from a Playwright `BrowserContext` instance.
297
+ *
298
+ * @param context - The Playwright `BrowserContext` instance to wrap.
299
+ * @since 0.1.0
300
+ */
301
+ static make(context) {
302
+ const use = useHelper(context);
303
+ return PlaywrightBrowserContext.of({
304
+ pages: Effect.sync(() => context.pages().map(PlaywrightPage.make)),
305
+ newPage: use((c) => c.newPage().then(PlaywrightPage.make)),
306
+ close: use((c) => c.close()),
307
+ eventStream: (event) => Stream.asyncPush((emit) => Effect.acquireRelease(Effect.sync(() => {
308
+ context.on(event, emit.single);
309
+ context.once("close", emit.end);
310
+ }), () => Effect.sync(() => {
311
+ context.off(event, emit.single);
312
+ context.off("close", emit.end);
313
+ }))).pipe(Stream.map((e) => {
314
+ const mapping = eventMappings$1[event];
315
+ return mapping(e);
316
+ }))
317
+ });
318
+ }
319
+ };
320
+
321
+ //#endregion
322
+ //#region src/browser.ts
323
+ const eventMappings = { disconnected: (browser) => PlaywrightBrowser.make(browser) };
324
+ /**
325
+ * @category tag
326
+ */
327
+ var PlaywrightBrowser = class PlaywrightBrowser extends Context.Tag("effect-playwright/PlaywrightBrowser")() {
328
+ /**
329
+ * @category constructor
330
+ */
331
+ static make(browser) {
332
+ const use = useHelper(browser);
333
+ return PlaywrightBrowser.of({
334
+ newPage: (options) => use((browser$1) => browser$1.newPage(options).then(PlaywrightPage.make)),
335
+ close: use((browser$1) => browser$1.close()),
336
+ contexts: Effect.sync(() => browser.contexts().map(PlaywrightBrowserContext.make)),
337
+ newContext: (options) => Effect.acquireRelease(use((browser$1) => browser$1.newContext(options).then(PlaywrightBrowserContext.make)), (context) => context.close.pipe(Effect.ignoreLogged)),
338
+ browserType: Effect.sync(() => browser.browserType()),
339
+ version: Effect.sync(() => browser.version()),
340
+ isConnected: Effect.sync(() => browser.isConnected()),
341
+ eventStream: (event) => Stream.asyncPush((emit) => Effect.acquireRelease(Effect.sync(() => {
342
+ browser.on(event, emit.single);
343
+ browser.once("disconnected", emit.end);
344
+ }), () => Effect.sync(() => {
345
+ browser.off(event, emit.single);
346
+ browser.off("disconnected", emit.end);
347
+ }))).pipe(Stream.map((e) => {
348
+ const mapping = eventMappings[event];
349
+ return mapping(e);
350
+ })),
351
+ use
352
+ });
353
+ }
354
+ };
355
+
356
+ //#endregion
357
+ //#region src/playwright.ts
358
+ const launch = Effect.fn(function* (browserType, options) {
359
+ const rawBrowser = yield* Effect.tryPromise({
360
+ try: () => browserType.launch(options),
361
+ catch: wrapError
362
+ });
363
+ return PlaywrightBrowser.make(rawBrowser);
364
+ });
365
+ const connectCDP = Effect.fn(function* (cdpUrl, options) {
366
+ const browser = yield* Effect.tryPromise({
367
+ try: () => chromium.connectOverCDP(cdpUrl, options),
368
+ catch: wrapError
369
+ });
370
+ return PlaywrightBrowser.make(browser);
371
+ });
372
+ /**
373
+ * @category tag
374
+ * @since 0.1.0
375
+ */
376
+ var Playwright = class Playwright extends Context.Tag("effect-playwright/index/Playwright")() {
377
+ /**
378
+ * @category layer
379
+ */
380
+ static layer = Layer.succeed(Playwright, {
381
+ launch,
382
+ launchScoped: (browserType, options) => Effect.acquireRelease(launch(browserType, options), (browser) => browser.close.pipe(Effect.ignore)),
383
+ connectCDP,
384
+ connectCDPScoped: (cdpUrl, options) => Effect.acquireRelease(connectCDP(cdpUrl, options), (browser) => browser.close.pipe(Effect.ignore))
385
+ });
386
+ };
387
+
388
+ //#endregion
389
+ export { PlaywrightDownload as a, PlaywrightRequest as c, PlaywrightPage as d, PlaywrightLocator as f, PlaywrightDialog as i, PlaywrightResponse as l, PlaywrightBrowser as n, PlaywrightFileChooser as o, PlaywrightError as p, PlaywrightBrowserContext as r, PlaywrightFrame as s, Playwright as t, PlaywrightWorker as u };
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.2",
5
5
  "description": "An Effect-based Playwright library.",
6
6
  "author": "Jobflow GmbH",
7
7
  "license": "ISC",
@@ -37,21 +37,25 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@biomejs/biome": "2.3.11",
40
- "@effect/language-service": "^0.64.1",
40
+ "@effect/language-service": "^0.69.2",
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.9",
44
45
  "effect": "^3.19.14",
45
46
  "playwright": "^1.57.0",
46
- "tsdown": "^0.19.0",
47
+ "tsdown": "0.20.0-beta.3",
47
48
  "tsx": "^4.21.0",
49
+ "typedoc": "^0.28.16",
48
50
  "typescript": "^5.9.3",
49
- "vitest": "^4.0.16"
51
+ "vitest": "^4.0.17"
50
52
  },
51
53
  "types": "./dist/index.d.mts",
52
54
  "scripts": {
53
55
  "build": "tsdown",
54
56
  "test": "vitest run",
55
- "type-check": "tsc --noEmit"
57
+ "type-check": "tsc --noEmit",
58
+ "generate-docs": "typedoc",
59
+ "format-fix": "biome format --fix"
56
60
  }
57
61
  }