browserscale-ts 1.1.0 → 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 +2 -2
- package/dist/browser.js +2 -2
- package/dist/browserscale.browser.js +263 -88
- package/dist/client.d.ts +34 -25
- package/dist/client.js +42 -44
- package/dist/errors.d.ts +153 -4
- package/dist/errors.js +120 -4
- package/dist/gen/wrc_pb.d.ts +578 -4
- package/dist/gen/wrc_pb.js +132 -57
- package/dist/index.d.ts +26 -2
- package/dist/index.js +31 -2
- package/dist/internal/convert.d.ts +16 -5
- package/dist/internal/convert.js +126 -10
- package/dist/types.d.ts +61 -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/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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browserscale-ts",
|
|
3
|
-
"version": "1.
|
|
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",
|