@hira-core/sdk 1.0.7 → 1.0.9
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 +32 -11
- package/dist/index.d.ts +149 -6
- package/dist/index.js +87 -17623
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -188,17 +188,22 @@ const utils = new BrowserUtils(context);
|
|
|
188
188
|
|
|
189
189
|
#### Navigation & Interaction
|
|
190
190
|
|
|
191
|
-
| Method | Description
|
|
192
|
-
| ------------------------------------------ |
|
|
193
|
-
| `utils.goto(url)` | Navigate to URL
|
|
194
|
-
| `utils.click(selector)` | Wait + scroll + click
|
|
195
|
-
| `utils.
|
|
196
|
-
| `utils.
|
|
197
|
-
| `utils.
|
|
198
|
-
| `utils.
|
|
199
|
-
| `utils.
|
|
200
|
-
| `utils.
|
|
201
|
-
| `utils.
|
|
191
|
+
| Method | Description |
|
|
192
|
+
| ------------------------------------------ | -------------------------------------- |
|
|
193
|
+
| `utils.goto(url)` | Navigate to URL |
|
|
194
|
+
| `utils.click(selector)` | Wait + scroll + click |
|
|
195
|
+
| `utils.click({ x, y })` | Click at specific coordinates |
|
|
196
|
+
| `utils.type(selector, text)` | Wait + clear + type |
|
|
197
|
+
| `utils.select(selector, value)` | Select dropdown option (native `<select>`) |
|
|
198
|
+
| `utils.getText(selector)` | Get text content |
|
|
199
|
+
| `utils.getPosition(selector)` | Get element center coordinates |
|
|
200
|
+
| `utils.exists(selector, timeout?)` | Check element exists |
|
|
201
|
+
| `utils.waitForElement(selector, timeout?)` | Wait for element |
|
|
202
|
+
| `utils.waitForNavigation()` | Wait for page navigation |
|
|
203
|
+
| `utils.screenshot(path?)` | Take screenshot |
|
|
204
|
+
| `utils.sleep(ms)` | Delay (respects abort signal) |
|
|
205
|
+
| `utils.scroll({ deltaY })` | Smooth 60fps scroll (ease-in-out) |
|
|
206
|
+
| `utils.scroll({ deltaY, container })` | Smooth scroll inside overflow container|
|
|
202
207
|
|
|
203
208
|
#### Tab Management
|
|
204
209
|
|
|
@@ -344,6 +349,22 @@ npx @hira-core/cli build
|
|
|
344
349
|
|
|
345
350
|
---
|
|
346
351
|
|
|
352
|
+
## Virtual Cursor
|
|
353
|
+
|
|
354
|
+
The SDK includes a **virtual cursor** — a visible SVG cursor overlay that shows mouse movement, clicks, and scrolling in real-time. This is enabled by default and can be toggled via `IExecutionConfig.virtualCursor`:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
// In flow runner params
|
|
358
|
+
execution: {
|
|
359
|
+
virtualCursor: true, // default — show cursor overlay
|
|
360
|
+
// virtualCursor: false, // disable cursor overlay
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
When enabled, `BrowserUtils.click()`, `scroll()`, and other interaction methods will show realistic Bézier curve mouse movement with human-like timing.
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
347
368
|
## License
|
|
348
369
|
|
|
349
370
|
ISC
|
package/dist/index.d.ts
CHANGED
|
@@ -237,6 +237,12 @@ interface IExecutionConfig {
|
|
|
237
237
|
* Dev mode: dùng constructor `super(AntidetectProvider.GPM, ...)` trong flow class.
|
|
238
238
|
*/
|
|
239
239
|
antidetectProvider?: 'gpm' | 'hidemium' | 'genlogin' | 'adspower';
|
|
240
|
+
/**
|
|
241
|
+
* Enable virtual cursor — SVG arrow with Bézier curve mouse movement.
|
|
242
|
+
* When true, click() and type() will move cursor naturally before interacting.
|
|
243
|
+
* Default: true
|
|
244
|
+
*/
|
|
245
|
+
virtualCursor?: boolean;
|
|
240
246
|
}
|
|
241
247
|
interface IBrowserWindowConfig {
|
|
242
248
|
width: number;
|
|
@@ -314,6 +320,8 @@ interface IScriptContext<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
314
320
|
page: Page;
|
|
315
321
|
profile: IAntidetectProfile;
|
|
316
322
|
index: number;
|
|
323
|
+
/** Execution config — includes virtualCursor flag etc. */
|
|
324
|
+
execution: IExecutionConfig;
|
|
317
325
|
globalInput: InferGlobalInput<TConfig>;
|
|
318
326
|
profileInput: InferProfileInput<TConfig>;
|
|
319
327
|
/**
|
|
@@ -616,13 +624,26 @@ declare class BrowserUtils<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
616
624
|
private activePage;
|
|
617
625
|
/** Currently active iframe — null means main frame. Changed via activeIframe() */
|
|
618
626
|
private activeFrame;
|
|
627
|
+
/** Virtual cursor — Bézier movement + SVG visualization */
|
|
628
|
+
private readonly hiraCursor;
|
|
619
629
|
constructor(context: IScriptContext<TConfig>);
|
|
620
630
|
/**
|
|
621
|
-
* CDP trick — Chromium
|
|
622
|
-
*
|
|
631
|
+
* CDP trick — Chromium thinks tab is always focused, not throttled
|
|
632
|
+
* when user switches to another tab or clicks elsewhere.
|
|
623
633
|
*/
|
|
624
634
|
private enableFocusEmulation;
|
|
635
|
+
/**
|
|
636
|
+
* Apply stealth scripts to remove automation fingerprints.
|
|
637
|
+
* Uses evaluateOnNewDocument — runs BEFORE any page scripts on every navigation.
|
|
638
|
+
* Persists across navigations on the same page instance.
|
|
639
|
+
*/
|
|
640
|
+
private applyStealthScripts;
|
|
625
641
|
private checkAbort;
|
|
642
|
+
/**
|
|
643
|
+
* Scroll element vào viewport mượt mà — segments + delay.
|
|
644
|
+
* Chỉ scroll nếu element nằm ngoài viewport.
|
|
645
|
+
*/
|
|
646
|
+
private smoothScrollToElement;
|
|
626
647
|
/**
|
|
627
648
|
* Pause execution for the given duration.
|
|
628
649
|
*
|
|
@@ -650,10 +671,11 @@ declare class BrowserUtils<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
650
671
|
*/
|
|
651
672
|
private resolveElement;
|
|
652
673
|
/**
|
|
653
|
-
* Click on an element
|
|
674
|
+
* Click on an element or at specific coordinates.
|
|
675
|
+
* Scrolls the element into view before clicking.
|
|
654
676
|
* Throws if the element is not found.
|
|
655
677
|
*
|
|
656
|
-
* @param target - CSS selector, XPath, or
|
|
678
|
+
* @param target - CSS selector, XPath, ElementHandle, or `{ x, y }` coordinates
|
|
657
679
|
* @param options.delay - Delay in ms before clicking (default: 1000)
|
|
658
680
|
* @param options.waitTimeout - Max wait time for element to appear (default: 2000)
|
|
659
681
|
* @param options.frame - Optional Frame to search within
|
|
@@ -662,9 +684,58 @@ declare class BrowserUtils<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
662
684
|
* @example
|
|
663
685
|
* await utils.click("#submit-btn");
|
|
664
686
|
* await utils.click("#btn", { delay: 0 }); // click immediately
|
|
665
|
-
* await utils.click(
|
|
687
|
+
* await utils.click({ x: 500, y: 300 }); // click at coordinates
|
|
688
|
+
* const pos = await utils.getPosition("#btn", { randomXY: true });
|
|
689
|
+
* await utils.click(pos!); // click random point inside element
|
|
666
690
|
*/
|
|
667
|
-
click(target: string | ElementHandle
|
|
691
|
+
click(target: string | ElementHandle | {
|
|
692
|
+
x: number;
|
|
693
|
+
y: number;
|
|
694
|
+
}, options?: {
|
|
695
|
+
delay?: number;
|
|
696
|
+
waitTimeout?: number;
|
|
697
|
+
frame?: Frame;
|
|
698
|
+
}): Promise<boolean>;
|
|
699
|
+
/**
|
|
700
|
+
* Get the position (x, y) of an element.
|
|
701
|
+
* Returns center point by default, or a random point within bounds with `randomXY`.
|
|
702
|
+
*
|
|
703
|
+
* @param selector - CSS selector or XPath
|
|
704
|
+
* @param options.randomXY - If true, returns random point within element (10% margin from edges)
|
|
705
|
+
* @param options.waitTimeout - Max wait time for element (default: 2000ms)
|
|
706
|
+
* @param options.frame - Optional Frame to search within
|
|
707
|
+
* @returns `{ x, y }` or null if element not found / no bounding box
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* const center = await utils.getPosition("#btn");
|
|
711
|
+
* const rand = await utils.getPosition("#btn", { randomXY: true });
|
|
712
|
+
* if (rand) await utils.click(rand);
|
|
713
|
+
*/
|
|
714
|
+
getPosition(selector: string, options?: {
|
|
715
|
+
randomXY?: boolean;
|
|
716
|
+
waitTimeout?: number;
|
|
717
|
+
frame?: Frame;
|
|
718
|
+
}): Promise<{
|
|
719
|
+
x: number;
|
|
720
|
+
y: number;
|
|
721
|
+
} | null>;
|
|
722
|
+
/**
|
|
723
|
+
* Select a value from a `<select>` dropdown.
|
|
724
|
+
* Human-like flow: cursor moves to select → click to open → page.select() → close.
|
|
725
|
+
*
|
|
726
|
+
* NOTE: Native `<option>` elements CAN NOT be clicked via Puppeteer
|
|
727
|
+
* ("Node is either not clickable or not an Element").
|
|
728
|
+
* `page.select()` is the ONLY reliable method.
|
|
729
|
+
*
|
|
730
|
+
* @param selector - CSS selector or XPath of the `<select>` element
|
|
731
|
+
* @param value - The `value` attribute of the option to select
|
|
732
|
+
* @param options.delay - Delay before clicking (default: 500ms)
|
|
733
|
+
* @param options.waitTimeout - Max wait for element (default: 2000ms)
|
|
734
|
+
*
|
|
735
|
+
* @example
|
|
736
|
+
* await utils.select("#country", "vn");
|
|
737
|
+
*/
|
|
738
|
+
select(selector: string, value: string, options?: {
|
|
668
739
|
delay?: number;
|
|
669
740
|
waitTimeout?: number;
|
|
670
741
|
frame?: Frame;
|
|
@@ -741,6 +812,78 @@ declare class BrowserUtils<TConfig extends IFlowConfig = IFlowConfig> {
|
|
|
741
812
|
goto(url: string, options?: {
|
|
742
813
|
waitUntil?: "load" | "domcontentloaded" | "networkidle0" | "networkidle2";
|
|
743
814
|
}): Promise<boolean>;
|
|
815
|
+
/**
|
|
816
|
+
* Scroll the page or a container by a specific amount.
|
|
817
|
+
* Uses CDP mouseWheel events (human-like, not JS scrollBy).
|
|
818
|
+
*
|
|
819
|
+
* @param direction - "up" or "down"
|
|
820
|
+
* @param amount - Pixels to scroll
|
|
821
|
+
* @param options.container - CSS selector of scroll container
|
|
822
|
+
* @param options.speed - Scroll speed 1-100 (default: 50)
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* await utils.scroll("down", 500);
|
|
826
|
+
* await utils.scroll("up", 200, { container: "#chat-messages" });
|
|
827
|
+
*/
|
|
828
|
+
scroll(direction: "up" | "down", amount: number, options?: {
|
|
829
|
+
container?: string;
|
|
830
|
+
speed?: number;
|
|
831
|
+
}): Promise<void>;
|
|
832
|
+
/**
|
|
833
|
+
* Scroll to the top or bottom of the page.
|
|
834
|
+
* Scrolls in segments with pauses — giống người lướt dần đến đích.
|
|
835
|
+
*
|
|
836
|
+
* @param position - "top" or "bottom"
|
|
837
|
+
* @param options.speed - Scroll speed 1-100 (default: 50)
|
|
838
|
+
*
|
|
839
|
+
* @example
|
|
840
|
+
* await utils.scrollTo("bottom");
|
|
841
|
+
* await utils.scrollTo("top");
|
|
842
|
+
*/
|
|
843
|
+
scrollTo(position: "top" | "bottom", options?: {
|
|
844
|
+
speed?: number;
|
|
845
|
+
}): Promise<void>;
|
|
846
|
+
/**
|
|
847
|
+
* Scroll an element into the viewport.
|
|
848
|
+
* Scrolls in segments with pauses — không nhảy tới đích.
|
|
849
|
+
*
|
|
850
|
+
* @param selector - CSS selector or XPath of the element
|
|
851
|
+
* @param options.speed - Scroll speed 1-100 (default: 50)
|
|
852
|
+
* @returns true if element found and scrolled
|
|
853
|
+
*
|
|
854
|
+
* @example
|
|
855
|
+
* await utils.scrollToElement("#footer");
|
|
856
|
+
* await utils.scrollToElement("//button[text()='Load more']");
|
|
857
|
+
*/
|
|
858
|
+
scrollToElement(selector: string, options?: {
|
|
859
|
+
speed?: number;
|
|
860
|
+
}): Promise<boolean>;
|
|
861
|
+
/**
|
|
862
|
+
* Simulate natural browsing scroll — cuộn xuống xen kẽ lướt ngược, delay random.
|
|
863
|
+
* Giống người đang đọc/lướt web tự nhiên.
|
|
864
|
+
*
|
|
865
|
+
* @param options.duration - Thời gian scroll tính bằng giây (default: 5)
|
|
866
|
+
* @param options.direction - Main direction (default: "down")
|
|
867
|
+
* @param options.backChance - Chance to scroll back 0-1 (default: 0.15)
|
|
868
|
+
* @param options.backAmount - [min, max] px to scroll back (default: [50, 150])
|
|
869
|
+
* @param options.stepSize - [min, max] px per step (default: [200, 400])
|
|
870
|
+
* @param options.stepDelay - [min, max] ms delay between steps (default: [300, 800])
|
|
871
|
+
* @param options.container - CSS selector of scroll container
|
|
872
|
+
*
|
|
873
|
+
* @example
|
|
874
|
+
* await utils.randomScroll(); // 5s lướt xuống
|
|
875
|
+
* await utils.randomScroll({ duration: 10 }); // 10s
|
|
876
|
+
* await utils.randomScroll({ backChance: 0.3, container: "#feed" });
|
|
877
|
+
*/
|
|
878
|
+
randomScroll(options?: {
|
|
879
|
+
duration?: number;
|
|
880
|
+
direction?: "down" | "up";
|
|
881
|
+
backChance?: number;
|
|
882
|
+
backAmount?: [number, number];
|
|
883
|
+
stepSize?: [number, number];
|
|
884
|
+
stepDelay?: [number, number];
|
|
885
|
+
container?: string;
|
|
886
|
+
}): Promise<void>;
|
|
744
887
|
/**
|
|
745
888
|
* Wait for the current page to complete a navigation (e.g. after a form submit).
|
|
746
889
|
* Throws on timeout.
|