@melra/browser-runtime 0.3.0-alpha.11 → 0.3.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/bounded.d.ts +27 -0
  2. package/dist/bounded.d.ts.map +1 -0
  3. package/dist/bounded.js +50 -0
  4. package/dist/bounded.js.map +1 -0
  5. package/dist/browser-connection.d.ts.map +1 -1
  6. package/dist/browser-connection.js +22 -7
  7. package/dist/browser-connection.js.map +1 -1
  8. package/dist/index.d.ts +106 -4
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +429 -57
  11. package/dist/index.js.map +1 -1
  12. package/dist/pinning-proxy.d.ts.map +1 -1
  13. package/dist/pinning-proxy.js +7 -8
  14. package/dist/pinning-proxy.js.map +1 -1
  15. package/dist/stable-dom.d.ts +13 -1
  16. package/dist/stable-dom.d.ts.map +1 -1
  17. package/dist/stable-dom.js +22 -3
  18. package/dist/stable-dom.js.map +1 -1
  19. package/package.json +6 -6
  20. package/dist/browser-connection.test.d.ts +0 -2
  21. package/dist/browser-connection.test.d.ts.map +0 -1
  22. package/dist/browser-connection.test.js +0 -210
  23. package/dist/browser-connection.test.js.map +0 -1
  24. package/dist/dialogs.test.d.ts +0 -2
  25. package/dist/dialogs.test.d.ts.map +0 -1
  26. package/dist/dialogs.test.js +0 -165
  27. package/dist/dialogs.test.js.map +0 -1
  28. package/dist/frames.test.d.ts +0 -2
  29. package/dist/frames.test.d.ts.map +0 -1
  30. package/dist/frames.test.js +0 -157
  31. package/dist/frames.test.js.map +0 -1
  32. package/dist/history-tabs.test.d.ts +0 -2
  33. package/dist/history-tabs.test.d.ts.map +0 -1
  34. package/dist/history-tabs.test.js +0 -176
  35. package/dist/history-tabs.test.js.map +0 -1
  36. package/dist/input-fidelity.test.d.ts +0 -2
  37. package/dist/input-fidelity.test.d.ts.map +0 -1
  38. package/dist/input-fidelity.test.js +0 -260
  39. package/dist/input-fidelity.test.js.map +0 -1
  40. package/dist/pinning-proxy.test.d.ts +0 -2
  41. package/dist/pinning-proxy.test.d.ts.map +0 -1
  42. package/dist/pinning-proxy.test.js +0 -80
  43. package/dist/pinning-proxy.test.js.map +0 -1
  44. package/dist/popups-profile.test.d.ts +0 -2
  45. package/dist/popups-profile.test.d.ts.map +0 -1
  46. package/dist/popups-profile.test.js +0 -170
  47. package/dist/popups-profile.test.js.map +0 -1
  48. package/dist/see-act.test.d.ts +0 -2
  49. package/dist/see-act.test.d.ts.map +0 -1
  50. package/dist/see-act.test.js +0 -152
  51. package/dist/see-act.test.js.map +0 -1
  52. package/dist/selector.test.d.ts +0 -2
  53. package/dist/selector.test.d.ts.map +0 -1
  54. package/dist/selector.test.js +0 -34
  55. package/dist/selector.test.js.map +0 -1
  56. package/dist/stable-dom.test.d.ts +0 -2
  57. package/dist/stable-dom.test.d.ts.map +0 -1
  58. package/dist/stable-dom.test.js +0 -22
  59. package/dist/stable-dom.test.js.map +0 -1
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A browser call that did not answer within its bound.
3
+ *
4
+ * Its own type so the code that swallows a detached frame or a closed page can
5
+ * tell "this went away" from "this stopped answering" — the second is never an
6
+ * answer, and treating it as one would hide a wedged renderer behind a
7
+ * plausible empty result.
8
+ */
9
+ export declare class BrowserCallTimeoutError extends Error {
10
+ constructor(what: string);
11
+ }
12
+ /**
13
+ * Settle with `call`, or fail once `ms` passes or `signal` aborts.
14
+ *
15
+ * Several Playwright calls — `title()`, `evaluate()`, `count()`, `close()`, a
16
+ * CDP `send` — take no timeout of their own, so a renderer that stopped
17
+ * answering held the action until the task budget ran out, or forever where no
18
+ * budget was armed. The call itself cannot be cancelled; it is left to finish
19
+ * or not, and its eventual rejection is consumed here rather than surfacing as
20
+ * an unhandled one. The timer and the abort listener are both released the
21
+ * moment either side wins, so nothing is left holding the process open.
22
+ *
23
+ * `ms` may be `Infinity` for a call whose only legitimate bound is the task's
24
+ * own budget.
25
+ */
26
+ export declare function bounded<T>(call: Promise<T>, ms: number, what: string, signal?: AbortSignal): Promise<T>;
27
+ //# sourceMappingURL=bounded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded.d.ts","sourceRoot":"","sources":["../src/bounded.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,IAAI,EAAE,MAAM;CAIzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,CAAC,CAAC,CAoBZ"}
@@ -0,0 +1,50 @@
1
+ // Copyright 2026 XAGI Labs Private Limited
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * A browser call that did not answer within its bound.
5
+ *
6
+ * Its own type so the code that swallows a detached frame or a closed page can
7
+ * tell "this went away" from "this stopped answering" — the second is never an
8
+ * answer, and treating it as one would hide a wedged renderer behind a
9
+ * plausible empty result.
10
+ */
11
+ export class BrowserCallTimeoutError extends Error {
12
+ constructor(what) {
13
+ super(`browser_call_timeout:${what}`);
14
+ this.name = "BrowserCallTimeoutError";
15
+ }
16
+ }
17
+ /**
18
+ * Settle with `call`, or fail once `ms` passes or `signal` aborts.
19
+ *
20
+ * Several Playwright calls — `title()`, `evaluate()`, `count()`, `close()`, a
21
+ * CDP `send` — take no timeout of their own, so a renderer that stopped
22
+ * answering held the action until the task budget ran out, or forever where no
23
+ * budget was armed. The call itself cannot be cancelled; it is left to finish
24
+ * or not, and its eventual rejection is consumed here rather than surfacing as
25
+ * an unhandled one. The timer and the abort listener are both released the
26
+ * moment either side wins, so nothing is left holding the process open.
27
+ *
28
+ * `ms` may be `Infinity` for a call whose only legitimate bound is the task's
29
+ * own budget.
30
+ */
31
+ export function bounded(call, ms, what, signal) {
32
+ return new Promise((resolve, reject) => {
33
+ const finish = (settle) => {
34
+ clearTimeout(timer);
35
+ signal?.removeEventListener("abort", aborted);
36
+ settle();
37
+ };
38
+ const aborted = () => {
39
+ finish(() => reject(signal?.reason ?? new Error("task_cancelled")));
40
+ };
41
+ const timer = Number.isFinite(ms)
42
+ ? setTimeout(() => finish(() => reject(new BrowserCallTimeoutError(what))), ms)
43
+ : undefined;
44
+ signal?.addEventListener("abort", aborted, { once: true });
45
+ call.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
46
+ if (signal?.aborted === true)
47
+ aborted();
48
+ });
49
+ }
50
+ //# sourceMappingURL=bounded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded.js","sourceRoot":"","sources":["../src/bounded.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,IAAY;QACtB,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CACrB,IAAgB,EAChB,EAAU,EACV,IAAY,EACZ,MAAoB;IAEpB,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAE,EAAE;YACpC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,EAAE,CAAC;QACX,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC/E,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,CACP,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EACvC,CAAC,KAAc,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAChD,CAAC;QACF,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"browser-connection.d.ts","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAuB/D,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU3E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CAkF5B"}
1
+ {"version":3,"file":"browser-connection.d.ts","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA+B/D,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU3E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CA+F5B"}
@@ -3,6 +3,13 @@
3
3
  import { constants } from "node:fs";
4
4
  import { access } from "node:fs/promises";
5
5
  import { chromium } from "playwright-core";
6
+ import { bounded } from "./bounded.js";
7
+ /**
8
+ * Bound on creating the first context in a browser MELRA just launched. Matches
9
+ * Playwright's default action timeout; a fresh browser that cannot open a
10
+ * context in that long is not going to.
11
+ */
12
+ const NEW_CONTEXT_TIMEOUT_MS = 30_000;
6
13
  const CHROME_PATHS = {
7
14
  darwin: [
8
15
  "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
@@ -107,13 +114,21 @@ export async function connectBrowser(options) {
107
114
  throw new Error("browser_persistent_profile_unavailable");
108
115
  return { browser, context, ownsBrowser: true, ownsContext: true };
109
116
  }
117
+ // `launch` carries Playwright's own 180s timeout; `newContext` carries none.
110
118
  const browser = await chromium.launch(launchOptions);
111
- const context = await browser.newContext(contextOptions);
112
- return {
113
- browser,
114
- context,
115
- ownsBrowser: true,
116
- ownsContext: true,
117
- };
119
+ try {
120
+ const context = await bounded(browser.newContext(contextOptions), NEW_CONTEXT_TIMEOUT_MS, "new_context");
121
+ return {
122
+ browser,
123
+ context,
124
+ ownsBrowser: true,
125
+ ownsContext: true,
126
+ };
127
+ }
128
+ catch (error) {
129
+ // Nobody else holds this browser yet, so a failure here would leak it.
130
+ await bounded(browser.close(), NEW_CONTEXT_TIMEOUT_MS, "close_browser").catch(() => undefined);
131
+ throw error;
132
+ }
118
133
  }
119
134
  //# sourceMappingURL=browser-connection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser-connection.js","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-connection.js","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -41,6 +41,32 @@ export interface BrowserRuntimeOptions extends NetworkPolicy {
41
41
  * Returns nothing when the page is clear, so a normal snapshot is unchanged.
42
42
  */
43
43
  export declare function captchaReport(frameUrls: string[]): Record<string, unknown>;
44
+ /**
45
+ * Whether a Playwright action failed after its input had already been sent.
46
+ *
47
+ * A click's own timeout covers more than waiting for the element: after the
48
+ * mouse events go out, Playwright still asks the page to stop its hit-target
49
+ * check. When the click handler stalls the page, that request is what times
50
+ * out — with the click already delivered. Playwright logs `performing <name>
51
+ * action` immediately before dispatching, and the call log is part of the
52
+ * error, so that line is Playwright's own record that the input left. Keyboard,
53
+ * fill, select, and upload calls log no such line; their timeouts stay plain
54
+ * failures, which for them is overwhelmingly a field that never became ready.
55
+ *
56
+ * Playwright paints the call log dim when colour is on (a TTY, FORCE_COLOR),
57
+ * so each line can end in an escape code; those are stripped first. Without
58
+ * that, a click delivered under colour read as never sent: a plain failure
59
+ * where the outcome was unknown, seen first on the Windows CI runners.
60
+ */
61
+ export declare function inputSent(error: unknown): boolean;
62
+ /**
63
+ * A URL as policy names a browser target, without query or fragment. Chrome
64
+ * escapes two path characters Node's URL can keep raw: `|` on every Node, `^`
65
+ * on Node 22. Both are escaped on both sides. Nothing is decoded: no two paths
66
+ * a server tells apart compare equal, and no escape becomes a raw character in
67
+ * a message. Exported for unit testing.
68
+ */
69
+ export declare function pageAddress(url: string): string;
44
70
  export declare class BrowserRuntime {
45
71
  private readonly options;
46
72
  private browser;
@@ -50,13 +76,20 @@ export declare class BrowserRuntime {
50
76
  private proxy;
51
77
  private routeHandler;
52
78
  /**
53
- * Dialogs raised by the action currently running, cleared by `execute`.
79
+ * Dialogs raised since the last action reported, emptied when one does.
54
80
  *
55
81
  * One buffer on the runtime rather than one per page because the handler is
56
- * registered on the context, and because operations execute one at a time —
57
- * a task owns its runtime for the length of one action.
82
+ * registered on the context, and because operations execute one at a time:
83
+ * `execute` queues them, so a task owns its runtime for one action. A dialog
84
+ * a page raised between actions is reported by the next one, marked
85
+ * `betweenActions`, rather than dropped: the transfer a late `confirm()`
86
+ * gated still went ahead, and the caller has to hear that it was asked.
58
87
  */
59
88
  private dialogs;
89
+ /** Whether an action is running, so a dialog or popup can say when it came. */
90
+ private acting;
91
+ /** The tail of the action queue; see `execute`. */
92
+ private queue;
60
93
  /**
61
94
  * Windows the page opened during the action currently running, same lifetime
62
95
  * as `dialogs` and reported the same way.
@@ -66,9 +99,56 @@ export declare class BrowserRuntime {
66
99
  private closing;
67
100
  /** True only while `tab_new` is opening the tab the caller asked for. */
68
101
  private openingTab;
102
+ /**
103
+ * Browser-level session that hears about a new window the moment Chromium
104
+ * creates it, which is what lets an action wait for a popup it knows exists
105
+ * instead of guessing how long one might take. Absent if the browser would
106
+ * not grant one; popups are then reported on Playwright's timing alone.
107
+ */
108
+ private targets;
109
+ /** Windows Chromium has created since tracking began, by browser context. */
110
+ private windowsCreated;
111
+ /** Windows Playwright has handed to the `page` handler, popup or not. */
112
+ private windowsAdopted;
113
+ /** This context's id in CDP, resolved on first use and then fixed. */
114
+ private contextId;
115
+ /**
116
+ * The running action's cancel signal and `timeoutMs`, read by `call`. Same
117
+ * per-action lifetime as `dialogs`, set by `execute`.
118
+ */
119
+ private signal;
120
+ private callMs;
121
+ /**
122
+ * Set once the running action's effect call has returned. From then on the
123
+ * page may have acted on it, so a failure is no longer evidence that nothing
124
+ * happened — see `execute`.
125
+ */
126
+ private dispatched;
69
127
  constructor(options: BrowserRuntimeOptions);
128
+ /**
129
+ * Bound a Playwright call that takes no timeout of its own by the running
130
+ * action's `timeoutMs` and cancel signal.
131
+ *
132
+ * `title()`, `evaluate()`, `count()`, `isVisible()`, `close()` and CDP
133
+ * `send` all wait for the renderer or the browser to answer, and one that
134
+ * stopped answering held the action until the task budget ran out — or
135
+ * forever, where nothing armed one. Failing with `browser_call_timeout:<what>`
136
+ * instead spends the budget on something that can still answer.
137
+ */
138
+ private call;
70
139
  private uploadPaths;
71
140
  private ensureContext;
141
+ /**
142
+ * Hold the action's result until Playwright has handed over every window
143
+ * Chromium created, so the action that opened a window is the one that
144
+ * reports it.
145
+ *
146
+ * Costs one round trip when nothing was opened. Waits only while a window is
147
+ * known to exist and is still unreported, bounded by the action's own
148
+ * timeout: the window is part of what the action did. A window still pending
149
+ * after that is reported by the action running when Playwright delivers it.
150
+ */
151
+ private awaitOpenedWindows;
72
152
  /**
73
153
  * Opens a page MELRA asked for, not one the site opened by itself.
74
154
  *
@@ -116,6 +196,10 @@ export declare class BrowserRuntime {
116
196
  *
117
197
  * A target that matches nothing is reported as such instead of being handed to
118
198
  * Playwright to fail as an opaque action timeout thirty seconds later.
199
+ *
200
+ * Resolution only reads the page and always runs before an action's effect,
201
+ * so a `count` that times out here fails a click or a fill cleanly: nothing
202
+ * was sent, and `execute` does not report it as an unknown outcome.
119
203
  */
120
204
  private locator;
121
205
  /**
@@ -146,6 +230,15 @@ export declare class BrowserRuntime {
146
230
  * reliably no matter what is in it.
147
231
  */
148
232
  private typeInto;
233
+ /**
234
+ * An attached CDP browser has no pinning proxy, and Chromium follows a
235
+ * redirect without showing the hop to the route guard, so an allowed page
236
+ * that redirects to 169.254.169.254 or a LAN address loads there. The request
237
+ * cannot be stopped from here; what can be is reading it back. A page whose
238
+ * address the guard refuses is blanked and the action fails, and a frame
239
+ * the guard refuses is left out.
240
+ */
241
+ private refusedFrames;
149
242
  private snapshot;
150
243
  /**
151
244
  * Read one element rather than the whole page.
@@ -157,7 +250,15 @@ export declare class BrowserRuntime {
157
250
  */
158
251
  private extract;
159
252
  private settledSnapshot;
160
- execute(operation: BrowserOperation): Promise<Record<string, unknown>>;
253
+ /**
254
+ * One action at a time, in arrival order. A single runtime serves every task,
255
+ * and a parallel workflow node or two concurrent MCP calls used to run here
256
+ * at once: the second reset the first's cancel signal, timeout and
257
+ * `dispatched` flag mid-flight, so a click that landed was reported as a
258
+ * plain failure, and one task's cancel stopped another's action.
259
+ */
260
+ execute(operation: BrowserOperation, signal?: AbortSignal): Promise<Record<string, unknown>>;
261
+ private executeOne;
161
262
  private run;
162
263
  close(): Promise<void>;
163
264
  }
@@ -166,4 +267,5 @@ export * from "./pinning-proxy.js";
166
267
  export * from "./selector.js";
167
268
  export * from "./stable-dom.js";
168
269
  export * from "./browser-connection.js";
270
+ export * from "./bounded.js";
169
271
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,iBAAiB,CAAC;AAKvE,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAK5B,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;CAC5B;AA6CD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB1E;AAgGD,qBAAa,cAAc;IAyBb,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBpC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,YAAY,CAAgD;IACpE;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,CAAiC;IAChD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAiC;IAC/C,2EAA2E;IAC3E,OAAO,CAAC,OAAO,CAA0B;IACzC,yEAAyE;IACzE,OAAO,CAAC,UAAU,CAAS;gBAEE,OAAO,EAAE,qBAAqB;YAE7C,WAAW;YA8BX,aAAa;IA0J3B;;;;;;OAMG;YACW,QAAQ;YASR,IAAI;IASlB;;;;;;OAMG;YACW,YAAY;IAa1B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM;IAId;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAwBlB;;;;;;;;;;;OAWG;YACW,OAAO;IAarB;;;;;;;;;;;;;;OAcG;YACW,aAAa;IAsC3B;;;;;;;;;;OAUG;YACW,QAAQ;YAeR,QAAQ;IAwCtB;;;;;;;OAOG;YACW,OAAO;YAqBP,eAAe;IAcvB,OAAO,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAuB9D,GAAG;IAsTX,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA0B7B;AAKD,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}