effect-browser 0.2.0-beta.8 → 0.3.0-beta.5
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 +705 -1166
- package/dist/Browser-CM65Uo7f.mjs +437 -0
- package/dist/Browser-CM65Uo7f.mjs.map +1 -0
- package/dist/Browser.d.mts +115 -3
- package/dist/Browser.mjs +2 -22
- package/dist/BrowserError-DXXIA6Rk.d.mts +135 -0
- package/dist/BrowserError.d.mts +2 -0
- package/dist/BrowserError.mjs +202 -0
- package/dist/BrowserError.mjs.map +1 -0
- package/dist/BrowserEvent-DzdNdvoh.d.mts +277 -0
- package/dist/BrowserEvent.d.mts +2 -0
- package/dist/BrowserEvent.mjs +295 -0
- package/dist/BrowserEvent.mjs.map +1 -0
- package/dist/Cdp.d.mts +32 -0
- package/dist/Cdp.mjs +61 -0
- package/dist/Cdp.mjs.map +1 -0
- package/dist/Change-DNvztNLu.mjs +138 -0
- package/dist/Change-DNvztNLu.mjs.map +1 -0
- package/dist/Change-DVP2IJWm.d.mts +71 -0
- package/dist/Change.d.mts +2 -0
- package/dist/Change.mjs +2 -0
- package/dist/Chromium.d.mts +29 -81
- package/dist/Chromium.mjs +57 -392
- package/dist/Chromium.mjs.map +1 -1
- package/dist/Expect.d.mts +62 -0
- package/dist/Expect.mjs +114 -0
- package/dist/Expect.mjs.map +1 -0
- package/dist/Frame-BERmf_gM.d.mts +117 -0
- package/dist/Frame.d.mts +2 -0
- package/dist/Frame.mjs +123 -0
- package/dist/Frame.mjs.map +1 -0
- package/dist/Moment.d.mts +2 -0
- package/dist/Moment.mjs +288 -0
- package/dist/Moment.mjs.map +1 -0
- package/dist/Motion.d.mts +40 -0
- package/dist/Motion.mjs +122 -0
- package/dist/Motion.mjs.map +1 -0
- package/dist/Page-D4281dIi.mjs +618 -0
- package/dist/Page-D4281dIi.mjs.map +1 -0
- package/dist/Page-DYTdVhYa.d.mts +593 -0
- package/dist/Page.d.mts +2 -0
- package/dist/Page.mjs +2 -0
- package/dist/Plan-CNNOU1Tx.d.mts +112 -0
- package/dist/Plan-Dtrb-8im.mjs +311 -0
- package/dist/Plan-Dtrb-8im.mjs.map +1 -0
- package/dist/Plan.d.mts +2 -3
- package/dist/Plan.mjs +2 -2
- package/dist/Policy.d.mts +76 -0
- package/dist/Policy.mjs +237 -0
- package/dist/Policy.mjs.map +1 -0
- package/dist/Presentation.d.mts +48 -0
- package/dist/Presentation.mjs +117 -0
- package/dist/Presentation.mjs.map +1 -0
- package/dist/Snapshot-B34hZ4Jl.d.mts +68 -0
- package/dist/Snapshot.d.mts +2 -0
- package/dist/Snapshot.mjs +79 -0
- package/dist/Snapshot.mjs.map +1 -0
- package/dist/Stage.d.mts +54 -0
- package/dist/Stage.mjs +133 -0
- package/dist/Stage.mjs.map +1 -0
- package/dist/Supervisor-BtEG93gR.mjs +420 -0
- package/dist/Supervisor-BtEG93gR.mjs.map +1 -0
- package/dist/Supervisor-Im6-wbg5.d.mts +230 -0
- package/dist/Supervisor.d.mts +2 -0
- package/dist/Supervisor.mjs +2 -0
- package/dist/context-DAYjATgC.mjs +137 -0
- package/dist/context-DAYjATgC.mjs.map +1 -0
- package/dist/index.d.mts +17 -14
- package/dist/index.mjs +18 -13
- package/dist/match.inpage-xOe9LNO0.mjs +48 -0
- package/dist/match.inpage-xOe9LNO0.mjs.map +1 -0
- package/dist/page-Banfm_zc.mjs +5097 -0
- package/dist/page-Banfm_zc.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/url-CcL0K7S0.mjs +262 -0
- package/dist/url-CcL0K7S0.mjs.map +1 -0
- package/package.json +96 -61
- package/src/Browser.ts +625 -0
- package/src/BrowserError.ts +225 -0
- package/src/BrowserEvent.ts +294 -0
- package/src/Cdp.ts +101 -0
- package/src/Change.ts +88 -0
- package/src/Chromium.ts +102 -0
- package/src/Expect.ts +180 -0
- package/src/Frame.ts +130 -0
- package/src/Moment.ts +479 -0
- package/src/Motion.ts +166 -0
- package/src/Page.ts +520 -0
- package/src/Plan.ts +350 -0
- package/src/Policy.ts +325 -0
- package/src/Presentation.ts +195 -0
- package/src/Snapshot.ts +89 -0
- package/src/Stage.ts +223 -0
- package/src/Supervisor.ts +353 -0
- package/src/index.ts +20 -0
- package/src/internal/input/actions.ts +607 -0
- package/src/internal/input/dispatch.ts +161 -0
- package/src/internal/input/edit.inpage.ts +162 -0
- package/src/internal/input/evidence.inpage.ts +164 -0
- package/src/internal/input/guard.inpage.ts +605 -0
- package/src/internal/input/guard.ts +183 -0
- package/src/internal/input/keyboard.ts +112 -0
- package/src/internal/input/keys.ts +127 -0
- package/src/internal/input/perform.ts +322 -0
- package/src/internal/input/pointer.ts +153 -0
- package/src/internal/input/replies.ts +159 -0
- package/src/internal/input/settle.ts +50 -0
- package/src/internal/input/style.ts +186 -0
- package/src/internal/input/targets.inpage.ts +293 -0
- package/src/internal/input/targets.ts +148 -0
- package/src/internal/page/bridge.ts +386 -0
- package/src/internal/page/context.ts +302 -0
- package/src/internal/page/lane.ts +301 -0
- package/src/internal/page/navigation.ts +183 -0
- package/src/internal/page/openings.ts +87 -0
- package/src/internal/page/page.ts +137 -0
- package/src/internal/page/url.ts +100 -0
- package/src/internal/page/viewport.ts +43 -0
- package/src/internal/pictures/capture.ts +778 -0
- package/src/internal/pictures/clock.ts +141 -0
- package/src/internal/pictures/pictures.ts +520 -0
- package/src/internal/pictures/transport.ts +242 -0
- package/src/internal/reading/choose.ts +100 -0
- package/src/internal/reading/context.inpage.ts +201 -0
- package/src/internal/reading/controls.inpage.ts +158 -0
- package/src/internal/reading/expect.inpage.ts +70 -0
- package/src/internal/reading/match.inpage.ts +92 -0
- package/src/internal/reading/names.inpage.ts +306 -0
- package/src/internal/reading/outline.inpage.ts +260 -0
- package/src/internal/reading/reading.ts +223 -0
- package/src/internal/reading/ready.inpage.ts +154 -0
- package/src/internal/reading/ready.ts +105 -0
- package/src/internal/reading/subjects.inpage.ts +188 -0
- package/src/internal/reading/text.inpage.ts +135 -0
- package/src/internal/reading/walk.inpage.ts +220 -0
- package/src/internal/supervisor/lifecycle.ts +265 -0
- package/src/internal/timeline/changes.inpage.ts +216 -0
- package/src/internal/timeline/changes.ts +100 -0
- package/src/internal/timeline/events.ts +93 -0
- package/src/internal/timeline/fold.inpage.ts +123 -0
- package/src/internal/timeline/history.inpage.ts +229 -0
- package/src/internal/timeline/marks.inpage.ts +207 -0
- package/src/internal/timeline/record.inpage.ts +133 -0
- package/src/internal/timeline/sight.inpage.ts +122 -0
- package/src/internal/timeline/window.ts +96 -0
- package/src/internal/timeline/words.ts +65 -0
- package/dist/Bootstrap-B9UUXsvF.d.mts +0 -183
- package/dist/Bootstrap-CeQOWBy6.mjs +0 -189
- package/dist/Bootstrap-CeQOWBy6.mjs.map +0 -1
- package/dist/Bootstrap.d.mts +0 -3
- package/dist/Bootstrap.mjs +0 -2
- package/dist/Browser-n-bKgBNN.d.mts +0 -372
- package/dist/Browser.mjs.map +0 -1
- package/dist/BrowserData-CPIIIHol.d.mts +0 -585
- package/dist/BrowserData.d.mts +0 -3
- package/dist/BrowserData.mjs +0 -695
- package/dist/BrowserData.mjs.map +0 -1
- package/dist/BrowserRuntime-CFe9uUTv.d.mts +0 -148
- package/dist/BrowserRuntime-HJ1yYlFS.mjs +0 -6741
- package/dist/BrowserRuntime-HJ1yYlFS.mjs.map +0 -1
- package/dist/BrowserRuntime.d.mts +0 -3
- package/dist/BrowserRuntime.mjs +0 -3
- package/dist/Capture.d.mts +0 -56
- package/dist/Capture.mjs +0 -678
- package/dist/Capture.mjs.map +0 -1
- package/dist/CaptureData-CYriZHX1.mjs +0 -201
- package/dist/CaptureData-CYriZHX1.mjs.map +0 -1
- package/dist/CaptureData.d.mts +0 -219
- package/dist/CaptureData.mjs +0 -2
- package/dist/Errors.d.mts +0 -158
- package/dist/Errors.mjs +0 -207
- package/dist/Errors.mjs.map +0 -1
- package/dist/Images-CaaPNeed.mjs +0 -76
- package/dist/Images-CaaPNeed.mjs.map +0 -1
- package/dist/OperationOptions-DAeRS6O9.mjs +0 -55
- package/dist/OperationOptions-DAeRS6O9.mjs.map +0 -1
- package/dist/PageControl.d.mts +0 -15
- package/dist/PageControl.mjs +0 -34
- package/dist/PageControl.mjs.map +0 -1
- package/dist/PageRegistry-B3q9DS3g.mjs +0 -164
- package/dist/PageRegistry-B3q9DS3g.mjs.map +0 -1
- package/dist/Plan-D8qQ48Ic.mjs +0 -512
- package/dist/Plan-D8qQ48Ic.mjs.map +0 -1
- package/dist/PlanData-B668RxbQ.d.mts +0 -4831
- package/dist/PlanData.d.mts +0 -3
- package/dist/PlanData.mjs +0 -268
- package/dist/PlanData.mjs.map +0 -1
- package/dist/PlanInput-BJcPPncs.mjs +0 -75
- package/dist/PlanInput-BJcPPncs.mjs.map +0 -1
- package/dist/PublicSession-Bs61Eal8.mjs +0 -5601
- package/dist/PublicSession-Bs61Eal8.mjs.map +0 -1
- package/dist/Testing.d.mts +0 -479
- package/dist/Testing.mjs +0 -2147
- package/dist/Testing.mjs.map +0 -1
- package/dist/Timeline-fV22Xk-S.d.mts +0 -29
- package/dist/Timeline.d.mts +0 -4
- package/dist/Timeline.mjs +0 -20
- package/dist/Timeline.mjs.map +0 -1
- package/dist/TimelineData-BsOn-YGZ.d.mts +0 -3818
- package/dist/TimelineData.d.mts +0 -3
- package/dist/TimelineData.mjs +0 -482
- package/dist/TimelineData.mjs.map +0 -1
package/dist/Chromium.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chromium.mjs","names":["Trace.span","Trace.span","Trace.annotate","BrowserRuntime.make"],"sources":["../src/internal/chromium/Data.ts","../src/internal/chromium/Process.ts","../src/internal/chromium/Session.ts","../src/Chromium.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nimport { Identifier } from \"../../BrowserData.ts\";\n\n/** Identifies this Chromium ownership lifetime, not a reusable endpoint. */\nexport class ChromiumReference extends Schema.Class<ChromiumReference>(\"ChromiumReference\")({\n provider: Schema.Literal(\"chromium\"),\n id: Identifier,\n}) {}\n\nexport class ChromiumCleanupIssue extends Schema.Class<ChromiumCleanupIssue>(\n \"ChromiumCleanupIssue\",\n)({\n step: Schema.Literals([\n \"fence\",\n \"capture\",\n \"initialization\",\n \"disconnect\",\n \"terminate\",\n \"profile\",\n ]),\n reason: Schema.Literals([\"timeout\", \"failed\", \"interrupted\"]),\n}) {}\n\n/** Connection teardown and observed process exit are separate facts; no provider status exists. */\nexport class ChromiumCleanupResult extends Schema.Class<ChromiumCleanupResult>(\n \"ChromiumCleanupResult\",\n)({\n reference: ChromiumReference,\n ownership: Schema.Literals([\"owned\", \"borrowed\"]),\n connection: Schema.Literals([\"closed\", \"failed\", \"not-connected\", \"pending\"]),\n process: Schema.Literals([\"terminated\", \"unknown\", \"not-owned\"]),\n issues: Schema.Array(ChromiumCleanupIssue).check(Schema.isMaxLength(16)),\n}) {}\n\nconst Text = Schema.NonEmptyString.check(\n Schema.isMaxLength(4096),\n // oxlint-disable-next-line eslint/no-control-regex -- NUL is one of the characters it rejects\n Schema.isPattern(/^[^\\u0000\\r\\n]+$/u),\n);\n\nconst Port = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65535 }));\n\n/** Only a concrete loopback WebSocket is admitted: no HTTP discovery redirects or remote DNS. */\nexport const ChromiumEndpoint = Text.check(\n Schema.makeFilter((value) => {\n try {\n const url = new URL(value);\n\n return (\n url.protocol === \"ws:\" &&\n [\"127.0.0.1\", \"[::1]\"].includes(url.hostname) &&\n Schema.is(Port)(Number(url.port)) &&\n !url.username &&\n !url.password &&\n !url.search &&\n !url.hash &&\n /^\\/devtools\\/browser\\/[A-Za-z0-9_-]+$/u.test(url.pathname)\n );\n } catch {\n return false;\n }\n }),\n);\n\nconst ProxyServer = Text.check(\n Schema.makeFilter((value) => {\n try {\n const url = new URL(value);\n\n return (\n [\"http:\", \"https:\", \"socks5:\"].includes(url.protocol) &&\n url.hostname.length > 0 &&\n !url.username &&\n !url.password &&\n !url.search &&\n !url.hash &&\n [\"\", \"/\"].includes(url.pathname)\n );\n } catch {\n return false;\n }\n }),\n);\n\n/** These arguments belong to the launcher; silently overriding them would change ownership. */\nconst Argument = Text.check(\n Schema.makeFilter(\n (value) =>\n value.startsWith(\"--\") &&\n !/^--(?:user-data-dir|remote-debugging[^=]*|headless|no-sandbox|disable-setuid-sandbox|single-process|proxy-server|proxy-bypass-list|no-startup-window)(?:=|$)/u.test(\n value,\n ),\n ),\n);\n\nexport const ChromiumLaunch = Schema.Struct({\n executablePath: Schema.optionalKey(Text),\n headless: Schema.optionalKey(Schema.Boolean),\n /** Enabled by default; a trusted host must explicitly choose a sandbox exception. */\n chromiumSandbox: Schema.optionalKey(Schema.Boolean),\n args: Schema.optionalKey(Schema.Array(Argument).check(Schema.isMaxLength(64))),\n proxy: Schema.optionalKey(\n Schema.Struct({\n server: ProxyServer,\n bypass: Schema.optionalKey(Text),\n }),\n ),\n startupTimeoutMillis: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 60000 })),\n ),\n});\n\nexport type ChromiumLaunch = typeof ChromiumLaunch.Type;\n","// rc.115's NodeChildProcessSpawner exposes leader exit, but its bounded group wait can\n// succeed with surviving members. This boundary must observe the leader AND group gone.\n// @effect-diagnostics-next-line nodeBuiltinImport:off\nimport { spawn, type ChildProcess } from \"node:child_process\";\n// FileSystem.remove exposes recursive/force only, not rm's per-entry OS-error retries.\n// Keep native profile creation/read/removal together; removal follows confirmed group exit.\n// @effect-diagnostics-next-line nodeBuiltinImport:off\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\n\nimport { Clock, Duration, Effect, Exit, Path, Redacted, Schema } from \"effect\";\n\nimport { Reasons, BrowserError } from \"../../Errors.ts\";\nimport * as Trace from \"../Trace.ts\";\nimport { ChromiumEndpoint, type ChromiumLaunch } from \"./Data.ts\";\n\nexport interface ChromiumProcess {\n readonly connection: (\n timeoutMillis: number,\n ) => Effect.Effect<Redacted.Redacted<string>, BrowserError>;\n readonly terminate: Effect.Effect<void, BrowserError>;\n readonly removeProfile: Effect.Effect<void, BrowserError>;\n}\n\n/** Explicit host sandbox/proxy choices; the owned profile and debugger endpoint cannot be replaced. */\nexport const launchArguments = (options: ChromiumLaunch, directory: string): string[] => [\n \"--no-first-run\",\n \"--no-default-browser-check\",\n \"--remote-debugging-address=127.0.0.1\",\n \"--remote-debugging-port=0\",\n \"--remote-debugging-pipe\",\n `--user-data-dir=${directory}`,\n ...(options.headless === false ? [] : [\"--headless=new\"]),\n ...(options.chromiumSandbox === false ? [\"--no-sandbox\"] : []),\n ...(options.proxy === undefined\n ? []\n : [\n `--proxy-server=${options.proxy.server}`,\n // Chromium otherwise bypasses proxies for loopback. The host may deliberately override it.\n `--proxy-bypass-list=${options.proxy.bypass ?? \"<-loopback>\"}`,\n ]),\n ...(options.args ?? []),\n // The shared driver creates its initial Page on the sole connection. Chromium's launch\n // Page can arrive after the debugger endpoint and race that creation.\n \"--no-startup-window\",\n];\n\nconst failure = (operation: \"launch\" | \"connect\" | \"close\", reason: BrowserError[\"reason\"]) =>\n BrowserError.make({\n operation,\n reason,\n outcome: operation === \"close\" ? \"unknown\" : \"undispatched\",\n });\n\nconst exited = (child: ChildProcess) => child.exitCode !== null || child.signalCode !== null;\n\n/** POSIX groups keep Chromium's helpers inside the same owned termination boundary. */\nconst alive = (pid: number): boolean => {\n try {\n process.kill(-pid, 0);\n\n return true;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ESRCH\") return false;\n throw error;\n }\n};\n\nconst signalGroup = (pid: number, signal: NodeJS.Signals) => {\n try {\n process.kill(-pid, signal);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ESRCH\")) throw error;\n }\n};\n\n/** Called once; observes parent and helper exit, rather than treating a sent signal as cleanup. */\nconst terminate = Effect.fnUntraced(function* (\n child: ChildProcess,\n pid: number,\n clock: Clock.Clock,\n): Effect.fn.Return<void, BrowserError> {\n const stopped = Effect.try({\n try: () => exited(child) && !alive(pid),\n catch: () => failure(\"close\", Reasons.Failed.make({})),\n });\n\n const signal = (value: NodeJS.Signals) =>\n Effect.try({\n try: () => signalGroup(pid, value),\n catch: () => failure(\"close\", Reasons.Failed.make({})),\n });\n\n const pause = clock.sleep(Duration.millis(20));\n\n yield* signal(\"SIGTERM\");\n const graceful = clock.monotonicTimeNanosUnsafe() + 1_500_000_000n;\n\n while (!(yield* stopped) && clock.monotonicTimeNanosUnsafe() < graceful) yield* pause;\n if (yield* stopped) return;\n yield* signal(\"SIGKILL\");\n const forced = clock.monotonicTimeNanosUnsafe() + 1_000_000_000n;\n\n while (!(yield* stopped) && clock.monotonicTimeNanosUnsafe() < forced) yield* pause;\n if (!(yield* stopped)) return yield* failure(\"close\", Reasons.Timeout.make({}));\n}, Trace.span(\"Chromium.terminate\"));\n\n/** Start only Chromium's process. The shared owner later opens its sole CDP connection. */\nexport const launch = Effect.fnUntraced(function* (\n options: ChromiumLaunch,\n): Effect.fn.Return<ChromiumProcess, BrowserError> {\n if (process.platform === \"win32\") return yield* failure(\"launch\", Reasons.Unsupported.make({}));\n const path = yield* Path.Path.pipe(Effect.provide(Path.layer));\n const clock = yield* Clock.Clock;\n\n const executable =\n options.executablePath ??\n (yield* Effect.tryPromise({\n try: () => import(\"playwright-core\").then(({ chromium }) => chromium.executablePath()),\n catch: () => failure(\"launch\", Reasons.Failed.make({})),\n }));\n\n const directory = yield* Effect.tryPromise({\n try: () => mkdtemp(path.join(tmpdir(), \"effect-browser-chromium-\")),\n catch: () => failure(\"launch\", Reasons.Failed.make({})),\n });\n\n const removeProfile = Effect.tryPromise({\n try: () => rm(directory, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 }),\n catch: () => failure(\"close\", Reasons.Failed.make({})),\n });\n\n let child: ChildProcess | undefined;\n\n return yield* Effect.gen(function* () {\n // Node reports a spawn's outcome on a later tick, so its listeners attach in the same turn.\n const launched = yield* Effect.callback<ChildProcess, BrowserError>((resume) => {\n const failed = () => resume(Effect.fail(failure(\"launch\", Reasons.Failed.make({}))));\n let spawned: ChildProcess;\n\n try {\n spawned = spawn(executable, launchArguments(options, directory), {\n cwd: directory,\n // Chromium watches fd 3 for EOF and closes the browser when the host dies, including\n // SIGKILL before connect. Keep its fd 3/4 pipe pair owned by this ChildProcess; send no\n // commands on it. The shared Playwright driver still controls the loopback endpoint.\n stdio: [\"ignore\", \"ignore\", \"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n });\n } catch {\n failed();\n\n return;\n }\n\n child = spawned;\n spawned.once(\"spawn\", () => resume(Effect.succeed(spawned)));\n spawned.once(\"error\", failed);\n });\n\n const pid = launched.pid;\n\n if (pid === undefined) return yield* failure(\"launch\", Reasons.Failed.make({}));\n\n // One termination continues to its own bounded group-exit decision even if a waiter cancels.\n const closing = yield* Effect.cached(\n terminate(launched, pid, clock).pipe(Effect.uninterruptible),\n );\n\n return {\n connection: (timeoutMillis) =>\n Effect.gen(function* () {\n const deadline =\n clock.monotonicTimeNanosUnsafe() +\n BigInt(Math.ceil(Math.min(timeoutMillis, options.startupTimeoutMillis ?? 15000))) *\n 1_000_000n;\n\n while (clock.monotonicTimeNanosUnsafe() < deadline) {\n if (exited(launched)) return yield* failure(\"connect\", Reasons.Closed.make({}));\n\n const portFile = yield* Effect.tryPromise({\n try: (signal) =>\n readFile(path.join(directory, \"DevToolsActivePort\"), {\n encoding: \"utf8\",\n signal,\n }).catch((error: unknown) => {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\")\n return undefined;\n throw error;\n }),\n catch: () => failure(\"connect\", Reasons.Transport.make({})),\n });\n\n // Chromium creates DevToolsActivePort before it writes the port and path into it. A\n // file without both lines is startup still in progress, not an endpoint; only a\n // complete file that is not a loopback DevTools endpoint is malformed.\n const lines = portFile === undefined ? [] : portFile.trim().split(\"\\n\");\n\n if (lines.length >= 2) {\n const endpoint = `ws://127.0.0.1:${lines[0]}${lines[1]}`;\n\n if (!Schema.is(ChromiumEndpoint)(endpoint))\n return yield* failure(\"connect\", Reasons.Malformed.make({}));\n\n return Redacted.make(endpoint);\n }\n yield* clock.sleep(Duration.millis(20));\n }\n\n return yield* failure(\"connect\", Reasons.Timeout.make({}));\n }).pipe(Trace.span(\"Chromium.ready\")),\n terminate: closing,\n removeProfile,\n } satisfies ChromiumProcess;\n }).pipe(\n Effect.onExit((exit) =>\n Exit.isSuccess(exit)\n ? Effect.void\n : Effect.gen(function* () {\n if (child?.pid === undefined) {\n yield* removeProfile.pipe(Effect.ignore);\n\n return;\n }\n const stopped = yield* terminate(child, child.pid, clock).pipe(Effect.exit);\n\n if (Exit.isSuccess(stopped)) yield* removeProfile.pipe(Effect.ignore);\n }),\n ),\n );\n}, Trace.span(\"Chromium.launch\"));\n","import { Crypto, Effect, Option, Redacted } from \"effect\";\n\nimport type { Lifetime, Source } from \"../../BrowserRuntime.ts\";\nimport { BrowserError, Reasons } from \"../../Errors.ts\";\nimport { cleanupStep, reported, type ConnectionCleanup } from \"../browser/ConnectionCleanup.ts\";\nimport { checked } from \"../browser/PublicSession.ts\";\nimport { randomUuid } from \"../browser/Random.ts\";\nimport * as Trace from \"../Trace.ts\";\nimport {\n ChromiumCleanupIssue,\n ChromiumCleanupResult,\n ChromiumEndpoint,\n ChromiumReference,\n type ChromiumLaunch,\n} from \"./Data.ts\";\nimport { launch, type ChromiumProcess } from \"./Process.ts\";\n\nexport interface ChromiumLease extends Lifetime {\n readonly reference: ChromiumReference;\n readonly closeChecked: Effect.Effect<ChromiumCleanupResult, BrowserError>;\n readonly release: Effect.Effect<ChromiumCleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<ChromiumCleanupResult>>;\n}\n\n/** Each teardown step runs even when a preceding step fails. Only observed exit permits profile removal. */\nexport const makeChromiumCleanup = Effect.fnUntraced(function* (\n reference: ChromiumReference,\n local: ConnectionCleanup,\n process: ChromiumProcess | undefined,\n) {\n let latest: ChromiumCleanupResult | undefined;\n\n const close = yield* Effect.cached(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const issues: ChromiumCleanupIssue[] = [];\n\n const step = <A, E>(name: ChromiumCleanupIssue[\"step\"], action: Effect.Effect<A, E>) =>\n cleanupStep(action.pipe(Trace.span(`Chromium.cleanup.${name}`)), 3000).pipe(\n Effect.tap((result) =>\n Effect.sync(() => {\n if (result._tag === \"Failure\")\n issues.push(ChromiumCleanupIssue.make({ step: name, reason: result.reason }));\n }),\n ),\n );\n\n yield* step(\"fence\", local.fence);\n yield* step(\"capture\", local.capture);\n yield* step(\"initialization\", local.initialization);\n const disconnected = yield* step(\"disconnect\", local.disconnect);\n\n const terminated =\n process === undefined ? undefined : yield* step(\"terminate\", process.terminate);\n\n if (process !== undefined && terminated !== undefined && terminated._tag === \"Success\")\n yield* step(\"profile\", process.removeProfile);\n\n const result = ChromiumCleanupResult.make({\n reference,\n ownership: process === undefined ? \"borrowed\" : \"owned\",\n connection: disconnected._tag === \"Success\" ? disconnected.value : \"failed\",\n process:\n terminated === undefined\n ? \"not-owned\"\n : terminated._tag === \"Success\"\n ? \"terminated\"\n : \"unknown\",\n issues,\n });\n\n Object.freeze(result.issues);\n latest = Object.freeze(result);\n yield* Trace.annotate({\n \"browser.cleanup.connection\": result.connection,\n \"browser.cleanup.process\": result.process,\n \"browser.cleanup.issues\": issues.length,\n });\n\n return latest;\n }).pipe(Trace.span(\"Chromium.cleanup\")),\n ),\n );\n\n return { close, result: Effect.sync(() => Option.fromNullishOr(latest)) };\n});\n\nconst acquireChromium =\n (\n endpoint: Redacted.Redacted<string> | undefined,\n options: ChromiumLaunch,\n onCleanup?: (result: ChromiumCleanupResult) => Effect.Effect<void>,\n ): Source<ChromiumLease, BrowserError, Crypto.Crypto> =>\n (local) =>\n Effect.uninterruptible(\n Effect.gen(function* () {\n // Drawn first: a draw after the spawn would sit between it and finalizer registration.\n const id = yield* randomUuid(yield* Crypto.Crypto);\n // The process cannot escape between spawn and finalizer registration. Startup waiting happens\n // later in connect, where it is interruptible and the owning finalizer is already installed.\n const process = endpoint === undefined ? yield* launch(options) : undefined;\n const reference = Object.freeze(ChromiumReference.make({ provider: \"chromium\", id }));\n\n const cleanup = yield* makeChromiumCleanup(reference, local, process);\n let closing = false;\n\n const release = yield* Effect.cached(\n Effect.gen(function* () {\n closing = true;\n const result = yield* cleanup.close;\n\n if (onCleanup !== undefined) yield* reported(Effect.suspend(() => onCleanup(result)));\n\n return result;\n }).pipe(Trace.span(\"Chromium.release\"), Effect.uninterruptible),\n );\n\n yield* Effect.addFinalizer(() => release.pipe(Effect.asVoid));\n\n return {\n reference,\n connection: (timeoutMillis) =>\n Effect.suspend(() => {\n if (closing)\n return Effect.fail(\n BrowserError.make({\n operation: \"connect\",\n reason: Reasons.Closed.make({}),\n outcome: \"undispatched\",\n }),\n );\n if (process !== undefined) return process.connection(timeoutMillis);\n\n return endpoint === undefined\n ? Effect.fail(\n BrowserError.make({\n operation: \"connect\",\n reason: Reasons.Configuration.make({}),\n outcome: \"undispatched\",\n }),\n )\n : checked(ChromiumEndpoint, Redacted.value(endpoint), \"connect\").pipe(\n Effect.map(Redacted.make),\n );\n }),\n release,\n closeChecked: release.pipe(\n Effect.filterOrFail(\n (result) =>\n result.connection === \"closed\" &&\n result.issues.length === 0 &&\n (result.ownership === \"borrowed\"\n ? result.process === \"not-owned\"\n : result.process === \"terminated\"),\n () =>\n BrowserError.make({\n operation: \"close\",\n reason: Reasons.Failed.make({}),\n outcome: \"unknown\",\n }),\n ),\n Trace.span(\"Chromium.close\"),\n ),\n cleanupResult: cleanup.result,\n controlRetired: cleanup.result.pipe(\n Effect.map(\n (result) =>\n Option.isSome(result) &&\n result.value.ownership === \"owned\" &&\n result.value.process === \"terminated\",\n ),\n ),\n } satisfies ChromiumLease;\n }),\n );\n\nexport const ownedChromium = (\n options: ChromiumLaunch,\n onCleanup?: (result: ChromiumCleanupResult) => Effect.Effect<void>,\n) => acquireChromium(undefined, options, onCleanup);\n\nexport const borrowedChromium = (\n endpoint: Redacted.Redacted<string>,\n onCleanup?: (result: ChromiumCleanupResult) => Effect.Effect<void>,\n) => acquireChromium(endpoint, {}, onCleanup);\n","import { Context, Crypto, Effect, Layer, type Option, Redacted, type Scope } from \"effect\";\n\nimport type { BrowserSession, OpenOptions } from \"./Browser.ts\";\nimport type { AutomationOptions, BrowserPolicy, Viewport } from \"./BrowserData.ts\";\nimport * as BrowserRuntime from \"./BrowserRuntime.ts\";\nimport { BrowserError, Reasons, type InitializationError } from \"./Errors.ts\";\nimport { checked } from \"./internal/browser/PublicSession.ts\";\nimport {\n ChromiumEndpoint,\n ChromiumLaunch,\n type ChromiumCleanupResult,\n type ChromiumReference,\n} from \"./internal/chromium/Data.ts\";\nimport { borrowedChromium, ownedChromium } from \"./internal/chromium/Session.ts\";\n\nexport {\n ChromiumCleanupIssue,\n ChromiumCleanupResult,\n ChromiumLaunch,\n ChromiumReference,\n} from \"./internal/chromium/Data.ts\";\n\n/** Host-only process configuration. Building this layer neither loads Playwright nor starts Chromium. */\nexport interface ChromiumOptions extends AutomationOptions {\n readonly launch?: ChromiumLaunch;\n readonly viewport?: Viewport;\n readonly onCleanup?: (result: ChromiumCleanupResult) => Effect.Effect<void>;\n}\n\n/** An owned or borrowed Chromium lifetime with one modeled browser connection. */\nexport interface ChromiumSession<E = never> extends BrowserSession<E> {\n readonly reference: ChromiumReference;\n readonly closeChecked: Effect.Effect<ChromiumCleanupResult, BrowserError>;\n readonly close: Effect.Effect<ChromiumCleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<ChromiumCleanupResult>>;\n}\n\nexport interface ChromiumAcquisition<E = never> {\n readonly reference: ChromiumReference;\n readonly failure: Effect.Effect<never, E | InitializationError>;\n readonly connect: Effect.Effect<ChromiumSession<E>, BrowserError | InitializationError | E>;\n readonly close: Effect.Effect<ChromiumCleanupResult>;\n}\n\nexport interface ChromiumAttachRequest<E = never, R = never> extends OpenOptions<E, R> {\n readonly policy: BrowserPolicy;\n /** Resolve this exact target; without it, multiple open pages are an ambiguity error. */\n readonly target?: { readonly targetId: string };\n}\n\nexport class Chromium extends Context.Service<\n Chromium,\n {\n readonly acquire: <E = never, R = never>(\n policy: BrowserPolicy,\n request?: OpenOptions<E, R>,\n ) => Effect.Effect<ChromiumAcquisition<E>, BrowserError, Scope.Scope | Exclude<R, Scope.Scope>>;\n readonly launch: <E = never, R = never>(\n policy: BrowserPolicy,\n request?: OpenOptions<E, R>,\n ) => Effect.Effect<\n ChromiumSession<E>,\n BrowserError | InitializationError | E,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n /** A concrete loopback ws://.../devtools/browser/... endpoint; this scope owns only its connection. */\n readonly attach: <E = never, R = never>(\n endpoint: Redacted.Redacted<string>,\n request: ChromiumAttachRequest<E, R>,\n ) => Effect.Effect<\n ChromiumSession<E>,\n BrowserError | InitializationError | E,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n }\n>()(\"effect-browser/Chromium\") {\n /** Launch through the configured service; compose with Browser.scoped for supervised ownership. */\n static launch<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) {\n return Effect.flatMap(Chromium, (browser) => browser.launch(policy, request));\n }\n\n /** Acquire the process lifetime before connecting, using the caller's scope. */\n static acquire<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) {\n return Effect.flatMap(Chromium, (browser) => browser.acquire(policy, request));\n }\n\n /** Borrow a concrete loopback endpoint; cleanup never terminates its external process. */\n static attach<E = never, R = never>(\n endpoint: Redacted.Redacted<string>,\n request: ChromiumAttachRequest<E, R>,\n ) {\n return Effect.flatMap(Chromium, (browser) => browser.attach(endpoint, request));\n }\n\n /** Chromium references, connection ids and handoff tokens come from the required `Crypto`. */\n static layer(options: ChromiumOptions = {}): Layer.Layer<Chromium, BrowserError, Crypto.Crypto> {\n return Layer.effect(\n Chromium,\n Effect.gen(function* () {\n const launchInput = yield* checked(ChromiumLaunch, options.launch ?? {}, \"configure\");\n\n const launch = Object.freeze({\n ...launchInput,\n ...(launchInput.args === undefined ? {} : { args: Object.freeze([...launchInput.args]) }),\n ...(launchInput.proxy === undefined\n ? {}\n : { proxy: Object.freeze({ ...launchInput.proxy }) }),\n });\n\n if (Object.prototype.hasOwnProperty.call(options, \"bootstrap\"))\n return yield* BrowserError.make({\n operation: \"configure\",\n reason: Reasons.Configuration.make({}),\n outcome: \"undispatched\",\n });\n\n const runtime = yield* BrowserRuntime.make({\n implementation: \"chromium-playwright-cdp\",\n ...(options.viewport === undefined ? {} : { viewport: options.viewport }),\n automation: {\n ...(options.timelineLimits === undefined\n ? {}\n : { timelineLimits: options.timelineLimits }),\n ...(options.admissionLimits === undefined\n ? {}\n : { admissionLimits: options.admissionLimits }),\n ...(options.observationLimits === undefined\n ? {}\n : { observationLimits: options.observationLimits }),\n ...(options.actionTimeoutMillis === undefined\n ? {}\n : { actionTimeoutMillis: options.actionTimeoutMillis }),\n ...(options.maxPages === undefined ? {} : { maxPages: options.maxPages }),\n ...(options.maxHostReads === undefined ? {} : { maxHostReads: options.maxHostReads }),\n ...(options.initialPage === undefined ? {} : { initialPage: options.initialPage }),\n ...(options.popupPolicy === undefined ? {} : { popupPolicy: options.popupPolicy }),\n ...(options.dialogPolicy === undefined ? {} : { dialogPolicy: options.dialogPolicy }),\n ...(options.pageControl === undefined ? {} : { pageControl: options.pageControl }),\n },\n });\n\n const crypto = yield* Crypto.Crypto;\n\n const acquire = Effect.fnUntraced(function* <E = never, R = never>(\n policy: BrowserPolicy,\n request: OpenOptions<E, R> = {},\n attachment?: { readonly endpoint: Redacted.Redacted<string>; readonly targetId?: string },\n ) {\n const source =\n attachment === undefined\n ? ownedChromium(launch, options.onCleanup)\n : borrowedChromium(attachment.endpoint, options.onCleanup);\n\n const acquired = yield* runtime.acquire(\n policy,\n (cleanup, deadline) =>\n source(cleanup, deadline).pipe(Effect.provideService(Crypto.Crypto, crypto)),\n {\n ...request,\n ...(attachment === undefined\n ? {}\n : {\n existingTarget:\n attachment.targetId === undefined ? {} : { targetId: attachment.targetId },\n }),\n },\n );\n\n const connected = yield* Effect.cached(\n acquired.connect.pipe(\n Effect.map(({ session }): ChromiumSession<E> =>\n Object.assign(session, {\n reference: acquired.reference,\n closeChecked: session.closeChecked.pipe(\n Effect.andThen(acquired.lifetime.closeChecked),\n ),\n close: acquired.close,\n cleanupResult: acquired.lifetime.cleanupResult,\n }),\n ),\n ),\n );\n\n return {\n reference: acquired.reference,\n failure: acquired.failure,\n close: acquired.close,\n connect: acquired.connect.pipe(Effect.andThen(connected)),\n } satisfies ChromiumAcquisition<E>;\n });\n\n return Chromium.of({\n acquire,\n launch: (policy, request) =>\n acquire(policy, request).pipe(Effect.flatMap((acquired) => acquired.connect)),\n attach: (endpoint, request) =>\n Effect.gen(function* () {\n const address = yield* checked(ChromiumEndpoint, Redacted.value(endpoint), \"connect\");\n\n return yield* (yield* acquire(request.policy, request, {\n endpoint: Redacted.make(address),\n ...(request.target === undefined ? {} : { targetId: request.target.targetId }),\n })).connect;\n }),\n });\n }),\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Chromium.mjs","names":["Browser.make","Browser.Browser"],"sources":["../src/Chromium.ts"],"sourcesContent":["/**\n * A local Chromium, launched for the scope and closed with it.\n *\n * It uses the Chromium build that `playwright-core` installs\n * (`npx playwright-core install chromium`), unless `executablePath` names another.\n *\n * Signals are the program's to handle: run it with `NodeRuntime.runMain`, which interrupts it on\n * SIGINT and SIGTERM, so the browser closes with its scope.\n *\n * @since 0.3.0\n */\nimport { Effect, Layer } from \"effect\";\nimport { chromium } from \"playwright-core\";\n\nimport * as Browser from \"./Browser.ts\";\nimport { type BrowserError, Failed } from \"./BrowserError.ts\";\nimport { reasonOf, undispatched } from \"./internal/page/context.ts\";\n\nexport interface Options extends Browser.Options {\n /** Defaults to true. */\n readonly headless?: boolean | undefined;\n /**\n * Run Chromium's sandbox. Defaults to false, as in Playwright, so an exploit in a page's renderer\n * runs with this process's privileges. Hosts that don't allow unprivileged user namespaces, such\n * as many containers and Ubuntu 23.10 or later by default, can't start the sandbox; opening then\n * fails and says so.\n */\n readonly sandbox?: boolean | undefined;\n /** Defaults to 1280x720 CSS pixels at a device scale factor of 1. */\n readonly viewport?: { readonly width: number; readonly height: number } | undefined;\n readonly executablePath?: string | undefined;\n readonly args?: ReadonlyArray<string> | undefined;\n readonly userAgent?: string | undefined;\n readonly locale?: string | undefined;\n}\n\n// Playwright's own default, stated so that a launch timeout reports the bound it exceeded.\nconst launchTimeoutMillis = 180_000;\n\nconst failed = (operation: string, timeoutMillis?: number) => (cause: unknown) =>\n undispatched(operation, reasonOf(cause, timeoutMillis));\n\n// Playwright puts this in place of Chromium's startup log when the sandbox could not start, in an\n// error that otherwise reads as a closed browser.\nconst sandboxFailed = /Chromium sandboxing failed|No usable sandbox/;\n\nconst launchFailed = (cause: unknown) =>\n sandboxFailed.test(String(cause))\n ? undispatched(\n \"launch\",\n new Failed({\n detail:\n \"Chromium's sandbox could not start on this host: it needs unprivileged user namespaces, and a user other than root\",\n }),\n )\n : failed(\"launch\", launchTimeoutMillis)(cause);\n\n/** Launch Chromium and open a `Browser` over a fresh context. */\nexport const open = Effect.fn(\"Chromium.open\")(function* (options: Options = {}) {\n const launched = yield* Effect.acquireRelease(\n Effect.tryPromise({\n try: () =>\n chromium.launch({\n headless: options.headless ?? true,\n chromiumSandbox: options.sandbox ?? false,\n timeout: launchTimeoutMillis,\n // The program owns its signals. Playwright's handlers close every browser on any of\n // these, and on SIGINT then exit the process, so no finalizer would run.\n handleSIGINT: false,\n handleSIGTERM: false,\n handleSIGHUP: false,\n ...(options.executablePath === undefined\n ? {}\n : { executablePath: options.executablePath }),\n ...(options.args === undefined ? {} : { args: [...options.args] }),\n }),\n catch: launchFailed,\n }).pipe(Effect.withSpan(\"Chromium.launch\", {}, { captureStackTrace: false })),\n (browser) => Effect.tryPromise(() => browser.close()).pipe(Effect.ignore),\n );\n\n const context = yield* Effect.tryPromise({\n try: () =>\n launched.newContext({\n viewport: options.viewport ?? { width: 1280, height: 720 },\n deviceScaleFactor: 1,\n ...(options.userAgent === undefined ? {} : { userAgent: options.userAgent }),\n ...(options.locale === undefined ? {} : { locale: options.locale }),\n }),\n catch: failed(\"launch\"),\n });\n\n return yield* Browser.make(\n context,\n { id: `chromium-${launched.version()}`, provider: \"chromium\" },\n options,\n );\n});\n\n/** A `Browser` Layer that launches Chromium when built and closes it when released. */\nexport const layer = (options: Options = {}): Layer.Layer<Browser.Browser, BrowserError> =>\n Layer.effect(Browser.Browser, open(options));\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAM,sBAAsB;AAE5B,MAAM,UAAU,WAAmB,mBAA4B,UAC7D,aAAa,WAAW,SAAS,OAAO,aAAa,CAAC;AAIxD,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB,UACpB,cAAc,KAAK,OAAO,KAAK,CAAC,IAC5B,aACE,UACA,IAAI,OAAO,EACT,QACE,qHACJ,CAAC,CACH,IACA,OAAO,UAAU,mBAAmB,CAAC,CAAC,KAAK;;AAGjD,MAAa,OAAO,OAAO,GAAG,eAAe,CAAC,CAAC,WAAW,UAAmB,CAAC,GAAG;CAC/E,MAAM,WAAW,OAAO,OAAO,eAC7B,OAAO,WAAW;EAChB,WACE,SAAS,OAAO;GACd,UAAU,QAAQ,YAAY;GAC9B,iBAAiB,QAAQ,WAAW;GACpC,SAAS;GAGT,cAAc;GACd,eAAe;GACf,cAAc;GACd,GAAI,QAAQ,mBAAmB,KAAA,IAC3B,CAAC,IACD,EAAE,gBAAgB,QAAQ,eAAe;GAC7C,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,QAAQ,IAAI,EAAE;EAClE,CAAC;EACH,OAAO;CACT,CAAC,CAAC,CAAC,KAAK,OAAO,SAAS,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,MAAM,CAAC,CAAC,IAC3E,YAAY,OAAO,iBAAiB,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM,CAC1E;CAEA,MAAM,UAAU,OAAO,OAAO,WAAW;EACvC,WACE,SAAS,WAAW;GAClB,UAAU,QAAQ,YAAY;IAAE,OAAO;IAAM,QAAQ;GAAI;GACzD,mBAAmB;GACnB,GAAI,QAAQ,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;GAC1E,GAAI,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;EACnE,CAAC;EACH,OAAO,OAAO,QAAQ;CACxB,CAAC;CAED,OAAO,OAAOA,KACZ,SACA;EAAE,IAAI,YAAY,SAAS,QAAQ;EAAK,UAAU;CAAW,GAC7D,OACF;AACF,CAAC;;AAGD,MAAa,SAAS,UAAmB,CAAC,MACxC,MAAM,OAAOC,SAAiB,KAAK,OAAO,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { t as BrowserError } from "./BrowserError-DXXIA6Rk.mjs";
|
|
2
|
+
import { a as FindQuery, u as Page } from "./Page-DYTdVhYa.mjs";
|
|
3
|
+
import { Duration, Effect } from "effect";
|
|
4
|
+
declare namespace Expect_d_exports {
|
|
5
|
+
export { Attempt, Expectation, Options, Outcome, appeared, attempt, changed, gone, navigated };
|
|
6
|
+
}
|
|
7
|
+
/** What an action is for, as the page can tell it. */
|
|
8
|
+
export type Expectation = {
|
|
9
|
+
readonly _tag: "Appeared";
|
|
10
|
+
readonly query: FindQuery;
|
|
11
|
+
} | {
|
|
12
|
+
readonly _tag: "Gone";
|
|
13
|
+
readonly query: FindQuery;
|
|
14
|
+
} | {
|
|
15
|
+
readonly _tag: "Changed";
|
|
16
|
+
readonly query: FindQuery;
|
|
17
|
+
} | {
|
|
18
|
+
readonly _tag: "Navigated";
|
|
19
|
+
readonly url: string | RegExp | undefined;
|
|
20
|
+
};
|
|
21
|
+
/** Something the query finds. */
|
|
22
|
+
export declare const appeared: (query: FindQuery) => Expectation;
|
|
23
|
+
/** Nothing the query finds. */
|
|
24
|
+
export declare const gone: (query: FindQuery) => Expectation;
|
|
25
|
+
/**
|
|
26
|
+
* What the query finds shows something other than it did as the attempt began: other elements, or
|
|
27
|
+
* their text, values or states.
|
|
28
|
+
*/
|
|
29
|
+
export declare const changed: (query: FindQuery) => Expectation;
|
|
30
|
+
/**
|
|
31
|
+
* The page is at `url`, the whole address or a pattern; without one, at an address or in a
|
|
32
|
+
* document other than the attempt's first.
|
|
33
|
+
*/
|
|
34
|
+
export declare const navigated: (url?: string | RegExp) => Expectation;
|
|
35
|
+
/**
|
|
36
|
+
* `Done`: the action ran, and what it was for came. `AlreadyDone`: it held before the action was
|
|
37
|
+
* sent, so it was not. `NotDone`: the action ran, and it did not come within the attempt's wait.
|
|
38
|
+
*/
|
|
39
|
+
export type Outcome = "Done" | "AlreadyDone" | "NotDone";
|
|
40
|
+
export interface Options {
|
|
41
|
+
/** How long an action's effect may take to show. Defaults to 5 seconds. */
|
|
42
|
+
readonly wait?: Duration.Input | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface Attempt {
|
|
45
|
+
readonly expectation: Expectation;
|
|
46
|
+
/** Whether the expectation holds on `page` now. */
|
|
47
|
+
readonly holds: (page: Page) => Effect.Effect<boolean, BrowserError>;
|
|
48
|
+
/**
|
|
49
|
+
* `act` on `page`, unless the expectation holds there already: see the module's comment. A
|
|
50
|
+
* failure before its input went is the action's own, and nothing is checked.
|
|
51
|
+
*/
|
|
52
|
+
readonly run: (page: Page, act: (page: Page) => Effect.Effect<unknown, BrowserError>) => Effect.Effect<Outcome, BrowserError>;
|
|
53
|
+
}
|
|
54
|
+
/** Begin an attempt at `expectation` on `page`, which takes its baseline from the page now. */
|
|
55
|
+
export declare const attempt: (page: Page, expectation: Expectation, options?: Options | undefined) => Effect.Effect<{
|
|
56
|
+
expectation: Expectation;
|
|
57
|
+
holds: (target: Page) => Effect.Effect<boolean, BrowserError, never>;
|
|
58
|
+
run: (target: Page, act: (page: Page) => Effect.Effect<unknown, BrowserError>) => Effect.Effect<"AlreadyDone" | "Done" | "NotDone", BrowserError, never>;
|
|
59
|
+
}, BrowserError, never>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Expect_d_exports as t };
|
|
62
|
+
//# sourceMappingURL=Expect.d.mts.map
|
package/dist/Expect.mjs
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { InvalidRequest } from "./BrowserError.mjs";
|
|
3
|
+
import { s as undispatched } from "./context-DAYjATgC.mjs";
|
|
4
|
+
import { t as internalsOf } from "./page-Banfm_zc.mjs";
|
|
5
|
+
import { Cause, Duration, Effect, Exit, Option, Schedule } from "effect";
|
|
6
|
+
//#region src/Expect.ts
|
|
7
|
+
/**
|
|
8
|
+
* Expectations: what an action is for, checked on the page, so that an action whose outcome is
|
|
9
|
+
* uncertain is sent again only where it did not take effect. An action that failed after its input
|
|
10
|
+
* went, a `Timeout` or a `Closed` with `dispatched`, may have done what it was for; repeating it
|
|
11
|
+
* blindly may do it twice, such as placing an order twice.
|
|
12
|
+
*
|
|
13
|
+
* An attempt takes its expectation's baseline from the page once, as it begins. Each `run` then
|
|
14
|
+
* checks first: where the expectation holds already, it sends nothing and is `AlreadyDone`.
|
|
15
|
+
* Otherwise it acts, and waits for the expectation: `Done`, or `NotDone` when it did not come in
|
|
16
|
+
* time. An action that fails after its input went is checked too, `Done` if its effect came, and
|
|
17
|
+
* otherwise fails as it did, so a later `run` of the same attempt checks before it acts again,
|
|
18
|
+
* on the same page or on the one a reconnect finds by its id.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const placing = yield* Expect.attempt(page, Expect.appeared({ text: "Order placed" }))
|
|
22
|
+
* const outcome = yield* placing.run(page, (page) => page.click("e12"))
|
|
23
|
+
* // After a Timeout that left `dispatched`, the same call clicks again only if no order shows.
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* A query is `Page.find`'s, over the whole document unless it says otherwise, and each check is one
|
|
27
|
+
* call to the page, a wait included; `navigated` reads the page's address and document, at no
|
|
28
|
+
* call. What `changed` compares stays in the page: text, field values and states, focus aside.
|
|
29
|
+
*
|
|
30
|
+
* @since 0.3.0
|
|
31
|
+
*/
|
|
32
|
+
var Expect_exports = /* @__PURE__ */ __exportAll({
|
|
33
|
+
appeared: () => appeared,
|
|
34
|
+
attempt: () => attempt,
|
|
35
|
+
changed: () => changed,
|
|
36
|
+
gone: () => gone,
|
|
37
|
+
navigated: () => navigated
|
|
38
|
+
});
|
|
39
|
+
/** Something the query finds. */
|
|
40
|
+
const appeared = (query) => ({
|
|
41
|
+
_tag: "Appeared",
|
|
42
|
+
query
|
|
43
|
+
});
|
|
44
|
+
/** Nothing the query finds. */
|
|
45
|
+
const gone = (query) => ({
|
|
46
|
+
_tag: "Gone",
|
|
47
|
+
query
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* What the query finds shows something other than it did as the attempt began: other elements, or
|
|
51
|
+
* their text, values or states.
|
|
52
|
+
*/
|
|
53
|
+
const changed = (query) => ({
|
|
54
|
+
_tag: "Changed",
|
|
55
|
+
query
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* The page is at `url`, the whole address or a pattern; without one, at an address or in a
|
|
59
|
+
* document other than the attempt's first.
|
|
60
|
+
*/
|
|
61
|
+
const navigated = (url) => ({
|
|
62
|
+
_tag: "Navigated",
|
|
63
|
+
url
|
|
64
|
+
});
|
|
65
|
+
const refused = (detail) => undispatched("expect", new InvalidRequest({ detail }));
|
|
66
|
+
const internalsFor = (page) => {
|
|
67
|
+
const internals = internalsOf(page);
|
|
68
|
+
return internals === void 0 ? Effect.fail(refused("only a page a Browser opened, or a presenter's view of one, can be checked")) : Effect.succeed(internals);
|
|
69
|
+
};
|
|
70
|
+
const atUrl = (url, wanted) => typeof wanted === "string" ? url === wanted : new RegExp(wanted.source, wanted.flags).test(url);
|
|
71
|
+
/** Begin an attempt at `expectation` on `page`, which takes its baseline from the page now. */
|
|
72
|
+
const attempt = Effect.fn("Expect.attempt")(function* (page, expectation, options = {}) {
|
|
73
|
+
const wait = Duration.fromInput(options.wait ?? Duration.seconds(5));
|
|
74
|
+
if (Option.isNone(wait) || Duration.isNegative(wait.value)) return yield* refused("wait must be a duration, not negative");
|
|
75
|
+
const waitMillis = Duration.toMillis(wait.value);
|
|
76
|
+
const first = yield* page.state;
|
|
77
|
+
const internals = yield* internalsFor(page);
|
|
78
|
+
const from = expectation._tag === "Changed" ? (yield* internals.until(expectation.query, "some", 0)).mark : void 0;
|
|
79
|
+
const navigatedOn = (target, url) => Effect.map(target.state, (now) => url !== void 0 ? atUrl(now.url, url) : now.url !== first.url || internalsOf(target) === internals && now.document !== first.document);
|
|
80
|
+
const holdsWithin = (target, millis) => {
|
|
81
|
+
if (expectation._tag === "Navigated") {
|
|
82
|
+
const look = navigatedOn(target, expectation.url);
|
|
83
|
+
return look.pipe(Effect.repeat({
|
|
84
|
+
until: (held) => held,
|
|
85
|
+
schedule: Schedule.spaced(Duration.millis(50))
|
|
86
|
+
}), Effect.timeoutOrElse({
|
|
87
|
+
duration: Duration.millis(millis),
|
|
88
|
+
orElse: () => look
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
const want = expectation._tag === "Appeared" ? "some" : expectation._tag === "Gone" ? "none" : { other: from ?? "" };
|
|
92
|
+
return internalsFor(target).pipe(Effect.flatMap((own) => own.until(expectation.query, want, millis)), Effect.map(({ met }) => met));
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
expectation,
|
|
96
|
+
holds: (target) => holdsWithin(target, 0),
|
|
97
|
+
run: Effect.fn("Expect.run")(function* (target, act) {
|
|
98
|
+
if (yield* holdsWithin(target, 0)) return "AlreadyDone";
|
|
99
|
+
const acted = yield* Effect.exit(act(target));
|
|
100
|
+
if (Exit.isSuccess(acted)) return (yield* holdsWithin(target, waitMillis)) ? "Done" : "NotDone";
|
|
101
|
+
const error = Cause.findErrorOption(acted.cause);
|
|
102
|
+
if (Option.isNone(error) || !error.value.dispatched) return yield* Effect.failCause(acted.cause);
|
|
103
|
+
const held = yield* Effect.exit(holdsWithin(target, waitMillis));
|
|
104
|
+
return Exit.isSuccess(held) && held.value ? "Done" : yield* Effect.failCause(acted.cause);
|
|
105
|
+
}, Effect.tap((outcome) => Effect.annotateCurrentSpan({
|
|
106
|
+
expectation: expectation._tag,
|
|
107
|
+
outcome
|
|
108
|
+
})))
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
//#endregion
|
|
112
|
+
export { appeared, attempt, changed, gone, navigated, Expect_exports as t };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=Expect.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Expect.mjs","names":[],"sources":["../src/Expect.ts"],"sourcesContent":["/**\n * Expectations: what an action is for, checked on the page, so that an action whose outcome is\n * uncertain is sent again only where it did not take effect. An action that failed after its input\n * went, a `Timeout` or a `Closed` with `dispatched`, may have done what it was for; repeating it\n * blindly may do it twice, such as placing an order twice.\n *\n * An attempt takes its expectation's baseline from the page once, as it begins. Each `run` then\n * checks first: where the expectation holds already, it sends nothing and is `AlreadyDone`.\n * Otherwise it acts, and waits for the expectation: `Done`, or `NotDone` when it did not come in\n * time. An action that fails after its input went is checked too, `Done` if its effect came, and\n * otherwise fails as it did, so a later `run` of the same attempt checks before it acts again,\n * on the same page or on the one a reconnect finds by its id.\n *\n * ```ts\n * const placing = yield* Expect.attempt(page, Expect.appeared({ text: \"Order placed\" }))\n * const outcome = yield* placing.run(page, (page) => page.click(\"e12\"))\n * // After a Timeout that left `dispatched`, the same call clicks again only if no order shows.\n * ```\n *\n * A query is `Page.find`'s, over the whole document unless it says otherwise, and each check is one\n * call to the page, a wait included; `navigated` reads the page's address and document, at no\n * call. What `changed` compares stays in the page: text, field values and states, focus aside.\n *\n * @since 0.3.0\n */\nimport { Cause, Duration, Effect, Exit, Option, Schedule } from \"effect\";\n\nimport { type BrowserError, InvalidRequest } from \"./BrowserError.ts\";\nimport { undispatched } from \"./internal/page/context.ts\";\nimport { type Internals, internalsOf } from \"./internal/page/page.ts\";\nimport type { FindQuery, Page } from \"./Page.ts\";\n\n/** What an action is for, as the page can tell it. */\nexport type Expectation =\n | { readonly _tag: \"Appeared\"; readonly query: FindQuery }\n | { readonly _tag: \"Gone\"; readonly query: FindQuery }\n | { readonly _tag: \"Changed\"; readonly query: FindQuery }\n | { readonly _tag: \"Navigated\"; readonly url: string | RegExp | undefined };\n\n/** Something the query finds. */\nexport const appeared = (query: FindQuery): Expectation => ({ _tag: \"Appeared\", query });\n\n/** Nothing the query finds. */\nexport const gone = (query: FindQuery): Expectation => ({ _tag: \"Gone\", query });\n\n/**\n * What the query finds shows something other than it did as the attempt began: other elements, or\n * their text, values or states.\n */\nexport const changed = (query: FindQuery): Expectation => ({ _tag: \"Changed\", query });\n\n/**\n * The page is at `url`, the whole address or a pattern; without one, at an address or in a\n * document other than the attempt's first.\n */\nexport const navigated = (url?: string | RegExp): Expectation => ({ _tag: \"Navigated\", url });\n\n/**\n * `Done`: the action ran, and what it was for came. `AlreadyDone`: it held before the action was\n * sent, so it was not. `NotDone`: the action ran, and it did not come within the attempt's wait.\n */\nexport type Outcome = \"Done\" | \"AlreadyDone\" | \"NotDone\";\n\nexport interface Options {\n /** How long an action's effect may take to show. Defaults to 5 seconds. */\n readonly wait?: Duration.Input | undefined;\n}\n\nexport interface Attempt {\n readonly expectation: Expectation;\n /** Whether the expectation holds on `page` now. */\n readonly holds: (page: Page) => Effect.Effect<boolean, BrowserError>;\n /**\n * `act` on `page`, unless the expectation holds there already: see the module's comment. A\n * failure before its input went is the action's own, and nothing is checked.\n */\n readonly run: (\n page: Page,\n act: (page: Page) => Effect.Effect<unknown, BrowserError>,\n ) => Effect.Effect<Outcome, BrowserError>;\n}\n\nconst refused = (detail: string) => undispatched(\"expect\", new InvalidRequest({ detail }));\n\nconst internalsFor = (page: Page): Effect.Effect<Internals, BrowserError> => {\n const internals = internalsOf(page);\n\n return internals === undefined\n ? Effect.fail(\n refused(\"only a page a Browser opened, or a presenter's view of one, can be checked\"),\n )\n : Effect.succeed(internals);\n};\n\nconst atUrl = (url: string, wanted: string | RegExp) =>\n typeof wanted === \"string\" ? url === wanted : new RegExp(wanted.source, wanted.flags).test(url);\n\n/** Begin an attempt at `expectation` on `page`, which takes its baseline from the page now. */\nexport const attempt = Effect.fn(\"Expect.attempt\")(function* (\n page: Page,\n expectation: Expectation,\n options: Options = {},\n) {\n const wait = Duration.fromInput(options.wait ?? Duration.seconds(5));\n\n if (Option.isNone(wait) || Duration.isNegative(wait.value))\n return yield* refused(\"wait must be a duration, not negative\");\n const waitMillis = Duration.toMillis(wait.value);\n const first = yield* page.state;\n const internals = yield* internalsFor(page);\n\n // What `changed` compares with: the mark of what the query found as the attempt began.\n const from =\n expectation._tag === \"Changed\"\n ? (yield* internals.until(expectation.query, \"some\", 0)).mark\n : undefined;\n\n // Navigated: at the address asked, or, without one, somewhere other than the attempt's first,\n // where a document counts only on the page that counted it, not on one a reconnect found.\n const navigatedOn = (target: Page, url: string | RegExp | undefined) =>\n Effect.map(target.state, (now) =>\n url !== undefined\n ? atUrl(now.url, url)\n : now.url !== first.url ||\n (internalsOf(target) === internals && now.document !== first.document),\n );\n\n const holdsWithin = (target: Page, millis: number): Effect.Effect<boolean, BrowserError> => {\n if (expectation._tag === \"Navigated\") {\n const look = navigatedOn(target, expectation.url);\n\n return look.pipe(\n Effect.repeat({\n until: (held) => held,\n schedule: Schedule.spaced(Duration.millis(50)),\n }),\n Effect.timeoutOrElse({ duration: Duration.millis(millis), orElse: () => look }),\n );\n }\n\n const want =\n expectation._tag === \"Appeared\"\n ? \"some\"\n : expectation._tag === \"Gone\"\n ? \"none\"\n : { other: from ?? \"\" };\n\n return internalsFor(target).pipe(\n Effect.flatMap((own) => own.until(expectation.query, want, millis)),\n Effect.map(({ met }) => met),\n );\n };\n\n const run = Effect.fn(\"Expect.run\")(\n function* (target: Page, act: (page: Page) => Effect.Effect<unknown, BrowserError>) {\n if (yield* holdsWithin(target, 0)) return \"AlreadyDone\" as const;\n const acted = yield* Effect.exit(act(target));\n\n if (Exit.isSuccess(acted))\n return (yield* holdsWithin(target, waitMillis)) ? (\"Done\" as const) : (\"NotDone\" as const);\n const error = Cause.findErrorOption(acted.cause);\n\n // A failure before the input went did nothing; one after it may have done what it was for.\n if (Option.isNone(error) || !error.value.dispatched)\n return yield* Effect.failCause(acted.cause);\n const held = yield* Effect.exit(holdsWithin(target, waitMillis));\n\n return Exit.isSuccess(held) && held.value\n ? (\"Done\" as const)\n : yield* Effect.failCause(acted.cause);\n },\n Effect.tap((outcome) => Effect.annotateCurrentSpan({ expectation: expectation._tag, outcome })),\n );\n\n return {\n expectation,\n holds: (target) => holdsWithin(target, 0),\n run,\n } satisfies Attempt;\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
declare namespace Frame_d_exports {
|
|
3
|
+
export { BrowserPaint, CaptureStats, Frame, Image, ScreencastOptions, Screenshot };
|
|
4
|
+
}
|
|
5
|
+
declare const Image_base: Schema.Class<Image, Schema.Struct<{
|
|
6
|
+
readonly data: Schema.Uint8Array;
|
|
7
|
+
readonly mediaType: Schema.Literals<readonly ["image/jpeg", "image/png"]>;
|
|
8
|
+
readonly width: Schema.Finite;
|
|
9
|
+
readonly height: Schema.Finite;
|
|
10
|
+
}>, {}>;
|
|
11
|
+
/** An encoded picture with its pixel dimensions. Crops also need their viewport origin. */
|
|
12
|
+
declare class Image extends Image_base {}
|
|
13
|
+
declare const BrowserPaint_base: Schema.Class<BrowserPaint, Schema.TaggedStruct<"BrowserPaint", {
|
|
14
|
+
readonly timestamp: Schema.Finite;
|
|
15
|
+
readonly hostTime: Schema.Finite;
|
|
16
|
+
readonly uncertaintyMillis: Schema.Finite;
|
|
17
|
+
}>, {}>;
|
|
18
|
+
/** Native CDP paint time mapped to the owning host clock, with transport uncertainty retained. */
|
|
19
|
+
declare class BrowserPaint extends BrowserPaint_base {}
|
|
20
|
+
declare const Screenshot_base: Schema.Class<Screenshot, Schema.TaggedStruct<"Screenshot", {
|
|
21
|
+
readonly hostTime: Schema.Finite;
|
|
22
|
+
readonly uncertaintyMillis: Schema.Finite;
|
|
23
|
+
}>, {}>;
|
|
24
|
+
/** A screenshot's host capture interval; it has no native browser paint timestamp. */
|
|
25
|
+
declare class Screenshot extends Screenshot_base {}
|
|
26
|
+
declare const Frame_base: Schema.Class<Frame, Schema.Struct<{
|
|
27
|
+
readonly page: Schema.String;
|
|
28
|
+
/** The page's browser session: its provider's session id, as `Browser.Service.id` gives it. */
|
|
29
|
+
readonly session: Schema.String;
|
|
30
|
+
readonly data: Schema.Uint8Array;
|
|
31
|
+
readonly timing: Schema.Union<readonly [typeof BrowserPaint, typeof Screenshot]>;
|
|
32
|
+
readonly receivedAt: Schema.Finite;
|
|
33
|
+
readonly width: Schema.Finite;
|
|
34
|
+
readonly height: Schema.Finite;
|
|
35
|
+
/**
|
|
36
|
+
* The page's document committed before the frame arrived, as `Navigated` counts them. Just
|
|
37
|
+
* after a commit a browser can still show the old document's paint, so a frame may show the
|
|
38
|
+
* document before its own, never one after it.
|
|
39
|
+
*/
|
|
40
|
+
readonly document: Schema.Int;
|
|
41
|
+
/** The page's address when the frame arrived. */
|
|
42
|
+
readonly url: Schema.String;
|
|
43
|
+
}>, {}>;
|
|
44
|
+
/**
|
|
45
|
+
* An image and its timing evidence. Paint time and screenshot capture time cannot be confused in
|
|
46
|
+
* serialized data. `receivedAt` records delivery on the owning host's monotonic clock; it does
|
|
47
|
+
* not make an old paint current.
|
|
48
|
+
*/
|
|
49
|
+
declare class Frame extends Frame_base {
|
|
50
|
+
get timestamp(): number | undefined;
|
|
51
|
+
get hostTime(): number;
|
|
52
|
+
get image(): Image;
|
|
53
|
+
}
|
|
54
|
+
declare const CaptureStats_base: Schema.Class<CaptureStats, Schema.Struct<{
|
|
55
|
+
readonly received: Schema.Int;
|
|
56
|
+
readonly accepted: Schema.Int;
|
|
57
|
+
/**
|
|
58
|
+
* Frames Chromium finished encoding after a newer one, dropped rather than reordered. It encodes
|
|
59
|
+
* several at once, so a busy machine makes more of them; none was a paint readers missed.
|
|
60
|
+
*/
|
|
61
|
+
readonly late: Schema.Int;
|
|
62
|
+
readonly missingTimestamp: Schema.Int;
|
|
63
|
+
/**
|
|
64
|
+
* Frames dropped for their size. Most are other captures' frames, which a clipped screenshot
|
|
65
|
+
* draws into a screencast. The rest are the page's own frames of a new size, dropped while still
|
|
66
|
+
* unconfirmed: when another size replaced it, when its capture stopped, or beyond the 16 held.
|
|
67
|
+
*/
|
|
68
|
+
readonly foreignSize: Schema.Int;
|
|
69
|
+
/**
|
|
70
|
+
* Frames dropped because they may have been painted, or arrived, while the library took a clipped
|
|
71
|
+
* or scaled picture of the page, such as a zoom: Chromium draws those into the screencast too.
|
|
72
|
+
* Where Playwright emulates the viewport, the page's own frames from that time are among them; a
|
|
73
|
+
* crop on the page's own session leaves out only frames of another size than the page's.
|
|
74
|
+
*/
|
|
75
|
+
readonly duringPictures: Schema.Int;
|
|
76
|
+
/**
|
|
77
|
+
* Frames a reader missed by falling behind. Each reader counts its own, so with several readers
|
|
78
|
+
* this can exceed the frames accepted.
|
|
79
|
+
*/
|
|
80
|
+
readonly lost: Schema.Int;
|
|
81
|
+
/**
|
|
82
|
+
* Acknowledgements of frames sent and not yet answered, now, whatever the window. Chromium sends
|
|
83
|
+
* a frame only while few are unacknowledged, so a backlog means fewer frames.
|
|
84
|
+
*/
|
|
85
|
+
readonly ackBacklog: Schema.Int;
|
|
86
|
+
/** Paint-time gaps between consecutive accepted frames. */
|
|
87
|
+
readonly gaps: Schema.Struct<{
|
|
88
|
+
readonly count: Schema.Int;
|
|
89
|
+
readonly totalMillis: Schema.Finite;
|
|
90
|
+
readonly minMillis: Schema.NullOr<Schema.Finite>;
|
|
91
|
+
readonly maxMillis: Schema.NullOr<Schema.Finite>;
|
|
92
|
+
readonly lastMillis: Schema.NullOr<Schema.Finite>;
|
|
93
|
+
}>;
|
|
94
|
+
}>, {}>;
|
|
95
|
+
/**
|
|
96
|
+
* A page's capture counts, over its life or a window of the latest minute: what Chromium sent,
|
|
97
|
+
* what readers got, and why the rest went no further. Frames that came late are counted apart from
|
|
98
|
+
* those a reader lost.
|
|
99
|
+
*/
|
|
100
|
+
declare class CaptureStats extends CaptureStats_base {}
|
|
101
|
+
/**
|
|
102
|
+
* Settings for a page's one native capture. Readers that join a running capture share its
|
|
103
|
+
* settings: one without options accepts them, and one whose explicit options differ fails with
|
|
104
|
+
* `InvalidRequest`.
|
|
105
|
+
*/
|
|
106
|
+
interface ScreencastOptions {
|
|
107
|
+
/** JPEG quality, 0 to 100. Defaults to 80. */
|
|
108
|
+
readonly quality?: number | undefined;
|
|
109
|
+
/** Frames are scaled down to fit this box. Defaults to the viewport in CSS pixels. */
|
|
110
|
+
readonly size?: {
|
|
111
|
+
readonly width: number;
|
|
112
|
+
readonly height: number;
|
|
113
|
+
} | undefined;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { Image as a, Frame_d_exports as i, CaptureStats as n, ScreencastOptions as o, Frame as r, Screenshot as s, BrowserPaint as t };
|
|
117
|
+
//# sourceMappingURL=Frame-BERmf_gM.d.mts.map
|
package/dist/Frame.d.mts
ADDED
package/dist/Frame.mjs
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
//#region src/Frame.ts
|
|
4
|
+
/**
|
|
5
|
+
* Pictures of a page: screenshots, and screencast frames stamped with the browser's clock.
|
|
6
|
+
*
|
|
7
|
+
* @since 0.3.0
|
|
8
|
+
*/
|
|
9
|
+
var Frame_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
+
BrowserPaint: () => BrowserPaint,
|
|
11
|
+
CaptureStats: () => CaptureStats,
|
|
12
|
+
Frame: () => Frame,
|
|
13
|
+
Image: () => Image,
|
|
14
|
+
Screenshot: () => Screenshot
|
|
15
|
+
});
|
|
16
|
+
/** An encoded picture with its pixel dimensions. Crops also need their viewport origin. */
|
|
17
|
+
var Image = class extends Schema.Class("effect-browser/Image")({
|
|
18
|
+
data: Schema.Uint8Array,
|
|
19
|
+
mediaType: Schema.Literals(["image/jpeg", "image/png"]),
|
|
20
|
+
width: Schema.Finite,
|
|
21
|
+
height: Schema.Finite
|
|
22
|
+
}) {};
|
|
23
|
+
const Nonnegative = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0));
|
|
24
|
+
const Count = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
25
|
+
/** Native CDP paint time mapped to the owning host clock, with transport uncertainty retained. */
|
|
26
|
+
var BrowserPaint = class extends Schema.TaggedClass()("BrowserPaint", {
|
|
27
|
+
timestamp: Schema.Finite,
|
|
28
|
+
hostTime: Schema.Finite,
|
|
29
|
+
uncertaintyMillis: Nonnegative
|
|
30
|
+
}) {};
|
|
31
|
+
/** A screenshot's host capture interval; it has no native browser paint timestamp. */
|
|
32
|
+
var Screenshot = class extends Schema.TaggedClass()("Screenshot", {
|
|
33
|
+
hostTime: Schema.Finite,
|
|
34
|
+
uncertaintyMillis: Nonnegative
|
|
35
|
+
}) {};
|
|
36
|
+
/**
|
|
37
|
+
* An image and its timing evidence. Paint time and screenshot capture time cannot be confused in
|
|
38
|
+
* serialized data. `receivedAt` records delivery on the owning host's monotonic clock; it does
|
|
39
|
+
* not make an old paint current.
|
|
40
|
+
*/
|
|
41
|
+
var Frame = class extends Schema.Class("effect-browser/Frame")({
|
|
42
|
+
page: Schema.String,
|
|
43
|
+
/** The page's browser session: its provider's session id, as `Browser.Service.id` gives it. */
|
|
44
|
+
session: Schema.String,
|
|
45
|
+
data: Schema.Uint8Array,
|
|
46
|
+
timing: Schema.Union([BrowserPaint, Screenshot]),
|
|
47
|
+
receivedAt: Schema.Finite,
|
|
48
|
+
width: Schema.Finite,
|
|
49
|
+
height: Schema.Finite,
|
|
50
|
+
/**
|
|
51
|
+
* The page's document committed before the frame arrived, as `Navigated` counts them. Just
|
|
52
|
+
* after a commit a browser can still show the old document's paint, so a frame may show the
|
|
53
|
+
* document before its own, never one after it.
|
|
54
|
+
*/
|
|
55
|
+
document: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
56
|
+
/** The page's address when the frame arrived. */
|
|
57
|
+
url: Schema.String
|
|
58
|
+
}) {
|
|
59
|
+
get timestamp() {
|
|
60
|
+
return this.timing._tag === "BrowserPaint" ? this.timing.timestamp : void 0;
|
|
61
|
+
}
|
|
62
|
+
get hostTime() {
|
|
63
|
+
return this.timing.hostTime;
|
|
64
|
+
}
|
|
65
|
+
get image() {
|
|
66
|
+
return new Image({
|
|
67
|
+
data: this.data,
|
|
68
|
+
mediaType: "image/jpeg",
|
|
69
|
+
width: this.width,
|
|
70
|
+
height: this.height
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A page's capture counts, over its life or a window of the latest minute: what Chromium sent,
|
|
76
|
+
* what readers got, and why the rest went no further. Frames that came late are counted apart from
|
|
77
|
+
* those a reader lost.
|
|
78
|
+
*/
|
|
79
|
+
var CaptureStats = class extends Schema.Class("effect-browser/CaptureStats")({
|
|
80
|
+
received: Count,
|
|
81
|
+
accepted: Count,
|
|
82
|
+
/**
|
|
83
|
+
* Frames Chromium finished encoding after a newer one, dropped rather than reordered. It encodes
|
|
84
|
+
* several at once, so a busy machine makes more of them; none was a paint readers missed.
|
|
85
|
+
*/
|
|
86
|
+
late: Count,
|
|
87
|
+
missingTimestamp: Count,
|
|
88
|
+
/**
|
|
89
|
+
* Frames dropped for their size. Most are other captures' frames, which a clipped screenshot
|
|
90
|
+
* draws into a screencast. The rest are the page's own frames of a new size, dropped while still
|
|
91
|
+
* unconfirmed: when another size replaced it, when its capture stopped, or beyond the 16 held.
|
|
92
|
+
*/
|
|
93
|
+
foreignSize: Count,
|
|
94
|
+
/**
|
|
95
|
+
* Frames dropped because they may have been painted, or arrived, while the library took a clipped
|
|
96
|
+
* or scaled picture of the page, such as a zoom: Chromium draws those into the screencast too.
|
|
97
|
+
* Where Playwright emulates the viewport, the page's own frames from that time are among them; a
|
|
98
|
+
* crop on the page's own session leaves out only frames of another size than the page's.
|
|
99
|
+
*/
|
|
100
|
+
duringPictures: Count,
|
|
101
|
+
/**
|
|
102
|
+
* Frames a reader missed by falling behind. Each reader counts its own, so with several readers
|
|
103
|
+
* this can exceed the frames accepted.
|
|
104
|
+
*/
|
|
105
|
+
lost: Count,
|
|
106
|
+
/**
|
|
107
|
+
* Acknowledgements of frames sent and not yet answered, now, whatever the window. Chromium sends
|
|
108
|
+
* a frame only while few are unacknowledged, so a backlog means fewer frames.
|
|
109
|
+
*/
|
|
110
|
+
ackBacklog: Count,
|
|
111
|
+
/** Paint-time gaps between consecutive accepted frames. */
|
|
112
|
+
gaps: Schema.Struct({
|
|
113
|
+
count: Count,
|
|
114
|
+
totalMillis: Nonnegative,
|
|
115
|
+
minMillis: Schema.NullOr(Nonnegative),
|
|
116
|
+
maxMillis: Schema.NullOr(Nonnegative),
|
|
117
|
+
lastMillis: Schema.NullOr(Nonnegative)
|
|
118
|
+
})
|
|
119
|
+
}) {};
|
|
120
|
+
//#endregion
|
|
121
|
+
export { BrowserPaint, CaptureStats, Frame, Image, Screenshot, Frame_exports as t };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=Frame.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Frame.mjs","names":[],"sources":["../src/Frame.ts"],"sourcesContent":["/**\n * Pictures of a page: screenshots, and screencast frames stamped with the browser's clock.\n *\n * @since 0.3.0\n */\nimport { Schema } from \"effect\";\n\n/** An encoded picture with its pixel dimensions. Crops also need their viewport origin. */\nexport class Image extends Schema.Class<Image>(\"effect-browser/Image\")({\n data: Schema.Uint8Array,\n mediaType: Schema.Literals([\"image/jpeg\", \"image/png\"]),\n width: Schema.Finite,\n height: Schema.Finite,\n}) {}\n\nconst Nonnegative = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0));\nconst Count = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));\n\n/** Native CDP paint time mapped to the owning host clock, with transport uncertainty retained. */\nexport class BrowserPaint extends Schema.TaggedClass<BrowserPaint>()(\"BrowserPaint\", {\n timestamp: Schema.Finite,\n hostTime: Schema.Finite,\n uncertaintyMillis: Nonnegative,\n}) {}\n\n/** A screenshot's host capture interval; it has no native browser paint timestamp. */\nexport class Screenshot extends Schema.TaggedClass<Screenshot>()(\"Screenshot\", {\n hostTime: Schema.Finite,\n uncertaintyMillis: Nonnegative,\n}) {}\n\n/**\n * An image and its timing evidence. Paint time and screenshot capture time cannot be confused in\n * serialized data. `receivedAt` records delivery on the owning host's monotonic clock; it does\n * not make an old paint current.\n */\nexport class Frame extends Schema.Class<Frame>(\"effect-browser/Frame\")({\n page: Schema.String,\n /** The page's browser session: its provider's session id, as `Browser.Service.id` gives it. */\n session: Schema.String,\n data: Schema.Uint8Array,\n timing: Schema.Union([BrowserPaint, Screenshot]),\n receivedAt: Schema.Finite,\n width: Schema.Finite,\n height: Schema.Finite,\n /**\n * The page's document committed before the frame arrived, as `Navigated` counts them. Just\n * after a commit a browser can still show the old document's paint, so a frame may show the\n * document before its own, never one after it.\n */\n document: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** The page's address when the frame arrived. */\n url: Schema.String,\n}) {\n get timestamp(): number | undefined {\n return this.timing._tag === \"BrowserPaint\" ? this.timing.timestamp : undefined;\n }\n\n get hostTime(): number {\n return this.timing.hostTime;\n }\n\n get image(): Image {\n return new Image({\n data: this.data,\n mediaType: \"image/jpeg\",\n width: this.width,\n height: this.height,\n });\n }\n}\n\n/**\n * A page's capture counts, over its life or a window of the latest minute: what Chromium sent,\n * what readers got, and why the rest went no further. Frames that came late are counted apart from\n * those a reader lost.\n */\nexport class CaptureStats extends Schema.Class<CaptureStats>(\"effect-browser/CaptureStats\")({\n received: Count,\n accepted: Count,\n /**\n * Frames Chromium finished encoding after a newer one, dropped rather than reordered. It encodes\n * several at once, so a busy machine makes more of them; none was a paint readers missed.\n */\n late: Count,\n missingTimestamp: Count,\n /**\n * Frames dropped for their size. Most are other captures' frames, which a clipped screenshot\n * draws into a screencast. The rest are the page's own frames of a new size, dropped while still\n * unconfirmed: when another size replaced it, when its capture stopped, or beyond the 16 held.\n */\n foreignSize: Count,\n /**\n * Frames dropped because they may have been painted, or arrived, while the library took a clipped\n * or scaled picture of the page, such as a zoom: Chromium draws those into the screencast too.\n * Where Playwright emulates the viewport, the page's own frames from that time are among them; a\n * crop on the page's own session leaves out only frames of another size than the page's.\n */\n duringPictures: Count,\n /**\n * Frames a reader missed by falling behind. Each reader counts its own, so with several readers\n * this can exceed the frames accepted.\n */\n lost: Count,\n /**\n * Acknowledgements of frames sent and not yet answered, now, whatever the window. Chromium sends\n * a frame only while few are unacknowledged, so a backlog means fewer frames.\n */\n ackBacklog: Count,\n /** Paint-time gaps between consecutive accepted frames. */\n gaps: Schema.Struct({\n count: Count,\n totalMillis: Nonnegative,\n minMillis: Schema.NullOr(Nonnegative),\n maxMillis: Schema.NullOr(Nonnegative),\n lastMillis: Schema.NullOr(Nonnegative),\n }),\n}) {}\n\n/**\n * Settings for a page's one native capture. Readers that join a running capture share its\n * settings: one without options accepts them, and one whose explicit options differ fails with\n * `InvalidRequest`.\n */\nexport interface ScreencastOptions {\n /** JPEG quality, 0 to 100. Defaults to 80. */\n readonly quality?: number | undefined;\n /** Frames are scaled down to fit this box. Defaults to the viewport in CSS pixels. */\n readonly size?: { readonly width: number; readonly height: number } | undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAQA,IAAa,QAAb,cAA2B,OAAO,MAAa,sBAAsB,CAAC,CAAC;CACrE,MAAM,OAAO;CACb,WAAW,OAAO,SAAS,CAAC,cAAc,WAAW,CAAC;CACtD,OAAO,OAAO;CACd,QAAQ,OAAO;AACjB,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAM,cAAc,OAAO,OAAO,MAAM,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,QAAQ,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC;;AAG/D,IAAa,eAAb,cAAkC,OAAO,YAA0B,CAAC,CAAC,gBAAgB;CACnF,WAAW,OAAO;CAClB,UAAU,OAAO;CACjB,mBAAmB;AACrB,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,aAAb,cAAgC,OAAO,YAAwB,CAAC,CAAC,cAAc;CAC7E,UAAU,OAAO;CACjB,mBAAmB;AACrB,CAAC,CAAC,CAAC,CAAC;;;;;;AAOJ,IAAa,QAAb,cAA2B,OAAO,MAAa,sBAAsB,CAAC,CAAC;CACrE,MAAM,OAAO;;CAEb,SAAS,OAAO;CAChB,MAAM,OAAO;CACb,QAAQ,OAAO,MAAM,CAAC,cAAc,UAAU,CAAC;CAC/C,YAAY,OAAO;CACnB,OAAO,OAAO;CACd,QAAQ,OAAO;;;;;;CAMf,UAAU,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC;;CAE3D,KAAK,OAAO;AACd,CAAC,CAAC,CAAC;CACD,IAAI,YAAgC;EAClC,OAAO,KAAK,OAAO,SAAS,iBAAiB,KAAK,OAAO,YAAY,KAAA;CACvE;CAEA,IAAI,WAAmB;EACrB,OAAO,KAAK,OAAO;CACrB;CAEA,IAAI,QAAe;EACjB,OAAO,IAAI,MAAM;GACf,MAAM,KAAK;GACX,WAAW;GACX,OAAO,KAAK;GACZ,QAAQ,KAAK;EACf,CAAC;CACH;AACF;;;;;;AAOA,IAAa,eAAb,cAAkC,OAAO,MAAoB,6BAA6B,CAAC,CAAC;CAC1F,UAAU;CACV,UAAU;;;;;CAKV,MAAM;CACN,kBAAkB;;;;;;CAMlB,aAAa;;;;;;;CAOb,gBAAgB;;;;;CAKhB,MAAM;;;;;CAKN,YAAY;;CAEZ,MAAM,OAAO,OAAO;EAClB,OAAO;EACP,aAAa;EACb,WAAW,OAAO,OAAO,WAAW;EACpC,WAAW,OAAO,OAAO,WAAW;EACpC,YAAY,OAAO,OAAO,WAAW;CACvC,CAAC;AACH,CAAC,CAAC,CAAC,CAAC"}
|