browserscale-ts 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +2 -2
- package/dist/browserscale.browser.js +322 -87
- package/dist/client.d.ts +70 -27
- package/dist/client.js +106 -45
- package/dist/errors.d.ts +153 -4
- package/dist/errors.js +120 -4
- package/dist/gen/wrc_pb.d.ts +716 -4
- package/dist/gen/wrc_pb.js +140 -55
- package/dist/index.d.ts +27 -3
- package/dist/index.js +31 -2
- package/dist/internal/convert.d.ts +16 -5
- package/dist/internal/convert.js +126 -10
- package/dist/options.d.ts +25 -0
- package/dist/types.d.ts +77 -0
- package/package.json +1 -1
package/dist/internal/convert.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// implementation detail and is NOT exported from the package entrypoints.
|
|
3
3
|
import { create } from "@bufbuild/protobuf";
|
|
4
4
|
import { HeaderModificationSchema, CookiePartitionKeySchema, CookieParamSchema, HeaderSchema, StorageItemSchema, StorageOriginEntrySchema, } from "../gen/wrc_pb.js";
|
|
5
|
+
import { ClickError, DragError, FillError, MoveError, ScrollError, SelectOptionError, WaitError, } from "../errors.js";
|
|
5
6
|
import { pickFrame } from "../locator.js";
|
|
6
7
|
export function elementFields(target, optsInFrame) {
|
|
7
8
|
const out = {};
|
|
@@ -28,22 +29,95 @@ export function rectFromProto(r) {
|
|
|
28
29
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
29
30
|
return { x: r.x, y: r.y, width: r.width, height: r.height };
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
-
// Element / Drag / Wait results
|
|
33
|
-
// ──────────────────────────────────────────────────────────────────────
|
|
34
|
-
export function elementResultFromProto(r) {
|
|
32
|
+
function elementResult(r, isVisible, bounds, rootX, rootY) {
|
|
35
33
|
return {
|
|
36
34
|
success: r.success,
|
|
37
35
|
frameId: r.frameId,
|
|
38
36
|
backendNodeId: r.backendNodeId,
|
|
39
|
-
isVisible
|
|
40
|
-
bounds
|
|
41
|
-
rootX
|
|
42
|
-
rootY
|
|
37
|
+
isVisible,
|
|
38
|
+
bounds,
|
|
39
|
+
rootX,
|
|
40
|
+
rootY,
|
|
43
41
|
};
|
|
44
42
|
}
|
|
45
|
-
|
|
43
|
+
function occluderFromProto(o) {
|
|
44
|
+
if (!o)
|
|
45
|
+
return undefined;
|
|
46
46
|
return {
|
|
47
|
+
backendNodeId: o.backendNodeId,
|
|
48
|
+
frameId: o.frameId,
|
|
49
|
+
tagName: o.tagName,
|
|
50
|
+
id: o.id ?? "",
|
|
51
|
+
className: o.className ?? "",
|
|
52
|
+
text: o.text ?? "",
|
|
53
|
+
bounds: rectFromProto(o.bounds),
|
|
54
|
+
pointerEvents: o.pointerEvents ?? "",
|
|
55
|
+
visibility: o.visibility ?? "",
|
|
56
|
+
opacity: o.opacity ?? 0,
|
|
57
|
+
zIndex: o.zIndex ?? "",
|
|
58
|
+
hittableWhileInvisible: o.hittableWhileInvisible ?? false,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Nested click-core detail (no standalone result) surfaced inside a FillError
|
|
62
|
+
// or DragError as the underlying click failure that blocked the action.
|
|
63
|
+
function clickDetailFromProto(e) {
|
|
64
|
+
if (!e)
|
|
65
|
+
return undefined;
|
|
66
|
+
return new ClickError({
|
|
67
|
+
code: e.code,
|
|
68
|
+
message: e.message,
|
|
69
|
+
occluder: occluderFromProto(e.occluder),
|
|
70
|
+
evadeAttempted: e.evadeAttempted ?? false,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Maps a ClickResult to ElementResult; throws {@link ClickError} when the click did not land. */
|
|
74
|
+
export function unwrapClick(r) {
|
|
75
|
+
const res = elementResult(r, r.isVisible, rectFromProto(r.bounds), r.rootX, r.rootY);
|
|
76
|
+
if (!r.success && r.error) {
|
|
77
|
+
throw new ClickError({
|
|
78
|
+
code: r.error.code,
|
|
79
|
+
message: r.error.message,
|
|
80
|
+
occluder: occluderFromProto(r.error.occluder),
|
|
81
|
+
evadeAttempted: r.error.evadeAttempted ?? false,
|
|
82
|
+
result: res,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return res;
|
|
86
|
+
}
|
|
87
|
+
/** Maps a FillResult to ElementResult; throws {@link FillError} when the fill failed. */
|
|
88
|
+
export function unwrapFill(r) {
|
|
89
|
+
// Fill omits is_visible/bounds from its contract; they stay zero.
|
|
90
|
+
const res = elementResult(r, false, rectFromProto(undefined), r.rootX, r.rootY);
|
|
91
|
+
if (!r.success && r.error) {
|
|
92
|
+
throw new FillError({
|
|
93
|
+
code: r.error.code,
|
|
94
|
+
message: r.error.message,
|
|
95
|
+
clickError: clickDetailFromProto(r.error.clickError),
|
|
96
|
+
result: res,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return res;
|
|
100
|
+
}
|
|
101
|
+
/** Maps a MoveResult to ElementResult; throws {@link MoveError} when the target was not found. */
|
|
102
|
+
export function unwrapMove(r) {
|
|
103
|
+
const res = elementResult(r, r.isVisible, rectFromProto(r.bounds), r.rootX, r.rootY);
|
|
104
|
+
if (!r.success && r.error) {
|
|
105
|
+
throw new MoveError({ code: r.error.code, message: r.error.message, result: res });
|
|
106
|
+
}
|
|
107
|
+
return res;
|
|
108
|
+
}
|
|
109
|
+
/** Maps a ScrollResult to ElementResult; throws {@link ScrollError} when the target could not be scrolled. */
|
|
110
|
+
export function unwrapScroll(r) {
|
|
111
|
+
// scrollTo returns no root_x/root_y; they stay zero.
|
|
112
|
+
const res = elementResult(r, r.isVisible, rectFromProto(r.bounds), 0, 0);
|
|
113
|
+
if (!r.success && r.error) {
|
|
114
|
+
throw new ScrollError({ code: r.error.code, message: r.error.message, result: res });
|
|
115
|
+
}
|
|
116
|
+
return res;
|
|
117
|
+
}
|
|
118
|
+
/** Maps a DragResult; throws {@link DragError} when the source pickup failed. */
|
|
119
|
+
export function unwrapDrag(r) {
|
|
120
|
+
const res = {
|
|
47
121
|
success: r.success,
|
|
48
122
|
frameId: r.frameId,
|
|
49
123
|
backendNodeId: r.backendNodeId,
|
|
@@ -52,15 +126,57 @@ export function dragResultFromProto(r) {
|
|
|
52
126
|
endX: r.endX,
|
|
53
127
|
endY: r.endY,
|
|
54
128
|
};
|
|
129
|
+
if (!r.success && r.error) {
|
|
130
|
+
throw new DragError({
|
|
131
|
+
code: r.error.code,
|
|
132
|
+
message: r.error.message,
|
|
133
|
+
clickError: clickDetailFromProto(r.error.clickError),
|
|
134
|
+
result: res,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return res;
|
|
55
138
|
}
|
|
56
|
-
|
|
139
|
+
/** Maps a SelectOptionResult; throws {@link SelectOptionError} when no option was selected. */
|
|
140
|
+
export function unwrapSelect(r) {
|
|
141
|
+
const res = {
|
|
142
|
+
selectedIndex: r.selectedIndex,
|
|
143
|
+
selectedValue: r.selectedValue,
|
|
144
|
+
selectedText: r.selectedText,
|
|
145
|
+
};
|
|
146
|
+
if (!r.success && r.error) {
|
|
147
|
+
throw new SelectOptionError({ code: r.error.code, message: r.error.message, result: res });
|
|
148
|
+
}
|
|
149
|
+
return res;
|
|
150
|
+
}
|
|
151
|
+
function waitConditionStatusFromProto(c) {
|
|
57
152
|
return {
|
|
153
|
+
index: c.index,
|
|
154
|
+
state: c.state,
|
|
155
|
+
backendNodeId: c.backendNodeId,
|
|
156
|
+
frameId: c.frameId,
|
|
157
|
+
isVisible: c.isVisible,
|
|
158
|
+
bounds: c.bounds ? rectFromProto(c.bounds) : undefined,
|
|
159
|
+
occluder: occluderFromProto(c.occluder),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/** Maps a WaitResult; throws {@link WaitError} when no condition matched before the deadline. */
|
|
163
|
+
export function unwrapWait(r) {
|
|
164
|
+
const res = {
|
|
58
165
|
index: r.index,
|
|
59
166
|
frameId: r.frameId,
|
|
60
167
|
backendNodeId: r.backendNodeId,
|
|
61
168
|
isVisible: r.isVisible,
|
|
62
169
|
bounds: rectFromProto(r.bounds),
|
|
63
170
|
};
|
|
171
|
+
if (r.error) {
|
|
172
|
+
throw new WaitError({
|
|
173
|
+
code: r.error.code,
|
|
174
|
+
message: r.error.message,
|
|
175
|
+
conditions: r.error.conditions.map(waitConditionStatusFromProto),
|
|
176
|
+
result: res,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return res;
|
|
64
180
|
}
|
|
65
181
|
// ──────────────────────────────────────────────────────────────────────
|
|
66
182
|
// FrameInfo / PageInfo
|
package/dist/options.d.ts
CHANGED
|
@@ -101,3 +101,28 @@ export interface ScreenshotOpts {
|
|
|
101
101
|
/** Encode quality 0-100 for "jpeg"/"webp" (ignored for "png"). Default 90. */
|
|
102
102
|
quality?: number;
|
|
103
103
|
}
|
|
104
|
+
/** Optional customization for {@link CloudBrowser.readCanvas}. */
|
|
105
|
+
export interface ReadCanvasOpts {
|
|
106
|
+
/**
|
|
107
|
+
* Override the locator's frame. Omit to use the locator's own
|
|
108
|
+
* {@link Locator.inFrame} (or the main frame). Pass a specific
|
|
109
|
+
* `frameId` or {@link AllFrames} to search elsewhere.
|
|
110
|
+
*/
|
|
111
|
+
inFrame?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Output encoding: `"png"` (default), `"jpeg"`, `"webp"`, or `"rgba"` for
|
|
114
|
+
* the raw unpremultiplied RGBA pixel buffer.
|
|
115
|
+
*/
|
|
116
|
+
format?: "png" | "jpeg" | "webp" | "rgba";
|
|
117
|
+
/** Encode quality 0-100 for "jpeg"/"webp" (ignored otherwise). Default 90. */
|
|
118
|
+
quality?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Optional sub-rectangle in canvas pixels (mirrors
|
|
121
|
+
* `getImageData(sx, sy, sw, sh)`). The full canvas is read when `sw`/`sh`
|
|
122
|
+
* are omitted or <= 0.
|
|
123
|
+
*/
|
|
124
|
+
sx?: number;
|
|
125
|
+
sy?: number;
|
|
126
|
+
sw?: number;
|
|
127
|
+
sh?: number;
|
|
128
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -64,6 +64,67 @@ export interface WaitResult {
|
|
|
64
64
|
isVisible: boolean;
|
|
65
65
|
bounds: Rect;
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* OccluderInfo describes the element that intercepted a click — the element
|
|
69
|
+
* sitting on top of the target at the intended click point. Coordinates are in
|
|
70
|
+
* root-viewport CSS pixels. Populated on {@link ClickError} for occlusion
|
|
71
|
+
* failures so the caller can locate and clear the blocker (e.g. find its close
|
|
72
|
+
* button).
|
|
73
|
+
*/
|
|
74
|
+
export interface OccluderInfo {
|
|
75
|
+
backendNodeId: number;
|
|
76
|
+
frameId: string;
|
|
77
|
+
tagName: string;
|
|
78
|
+
id: string;
|
|
79
|
+
className: string;
|
|
80
|
+
text: string;
|
|
81
|
+
bounds: Rect;
|
|
82
|
+
/**
|
|
83
|
+
* Computed pointer-events keyword (e.g. "auto", "none", "all"). Lets you tell
|
|
84
|
+
* an invisible pass-through layer from one that genuinely swallows the click.
|
|
85
|
+
*/
|
|
86
|
+
pointerEvents: string;
|
|
87
|
+
/** Computed visibility keyword ("visible", "hidden", "collapse"). */
|
|
88
|
+
visibility: string;
|
|
89
|
+
/**
|
|
90
|
+
* Computed opacity (0..1). 0 means visually invisible but it may still
|
|
91
|
+
* intercept clicks depending on pointerEvents.
|
|
92
|
+
*/
|
|
93
|
+
opacity: number;
|
|
94
|
+
/** Computed effective z-index as a string ("0" when auto / not stacked). */
|
|
95
|
+
zIndex: string;
|
|
96
|
+
/**
|
|
97
|
+
* True when the blocker intercepts clicks even while invisible (computed
|
|
98
|
+
* pointer-events in {all, painted, fill, stroke}): a real click is swallowed
|
|
99
|
+
* even at visibility:hidden / opacity:0. When false and the element is
|
|
100
|
+
* invisible, a real click would fall through.
|
|
101
|
+
*/
|
|
102
|
+
hittableWhileInvisible: boolean;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* WaitConditionStatus is the per-condition diagnostic carried by
|
|
106
|
+
* {@link WaitError} when a {@link CloudBrowser.wait} times out: one entry per
|
|
107
|
+
* condition (in the order they were passed) explaining why it never matched.
|
|
108
|
+
*/
|
|
109
|
+
export interface WaitConditionStatus {
|
|
110
|
+
/** Index into the condition list this entry describes. */
|
|
111
|
+
index: number;
|
|
112
|
+
/**
|
|
113
|
+
* Last observed state: `"not_found"`, `"found_hidden"`, `"found_occluded"`
|
|
114
|
+
* (only when the condition required visibility), or `"pending_steady"`.
|
|
115
|
+
*/
|
|
116
|
+
state: string;
|
|
117
|
+
/** backendNodeId last seen for this condition (0 if never found). */
|
|
118
|
+
backendNodeId: number;
|
|
119
|
+
/** frameId where it was last seen (empty if never found). */
|
|
120
|
+
frameId: string;
|
|
121
|
+
/** Whether it was CSS-visible at the last observation. */
|
|
122
|
+
isVisible: boolean;
|
|
123
|
+
/** Last known rect in root-viewport coordinates (undefined if never found). */
|
|
124
|
+
bounds?: Rect;
|
|
125
|
+
/** The intercepting element, present iff state === `"found_occluded"`. */
|
|
126
|
+
occluder?: OccluderInfo;
|
|
127
|
+
}
|
|
67
128
|
/** NavigateResult reports where a {@link CloudBrowser.navigate} call ended up after redirects. */
|
|
68
129
|
export interface NavigateResult {
|
|
69
130
|
frameId: string;
|
|
@@ -139,6 +200,22 @@ export interface ScreenshotResult {
|
|
|
139
200
|
width: number;
|
|
140
201
|
height: number;
|
|
141
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* ReadCanvasResult is the pixel readback of a <canvas>, returned by
|
|
205
|
+
* {@link CloudBrowser.readCanvas}. `dataBase64` holds the encoded image bytes
|
|
206
|
+
* (PNG by default) or the raw RGBA buffer when `format` is `"rgba"`.
|
|
207
|
+
* `originClean` reports whether the canvas was untainted (informational — the
|
|
208
|
+
* read succeeds either way).
|
|
209
|
+
*/
|
|
210
|
+
export interface ReadCanvasResult {
|
|
211
|
+
success: boolean;
|
|
212
|
+
frameId: string;
|
|
213
|
+
backendNodeId: number;
|
|
214
|
+
dataBase64: string;
|
|
215
|
+
width: number;
|
|
216
|
+
height: number;
|
|
217
|
+
originClean: boolean;
|
|
218
|
+
}
|
|
142
219
|
/**
|
|
143
220
|
* DOMResult is the full-tree DOM snapshot returned by
|
|
144
221
|
* {@link CloudBrowser.getDOM}, plus its sha256[:8] hash for cheap
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browserscale-ts",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Official SDK for browserscale — undetected stealth browsers in the cloud. Rent real Chromium sessions with unique fingerprints, built-in proxies, captcha solving, human-like input and live video — scale web scraping and automation without running a single browser yourself.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|