@letsscrapedata/controller 0.0.2 → 0.0.4

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/index.cjs CHANGED
@@ -497,17 +497,19 @@ var PlaywrightPage = class extends import_node_events.default {
497
497
  });
498
498
  page.on("popup", (p) => {
499
499
  if (p) {
500
+ let evtData = null;
500
501
  const pageInfo = p.pageInfo;
501
502
  let popupPageId = "page";
502
503
  if (pageInfo) {
503
504
  const { browserIdx, browserContextIdx, pageIdx } = pageInfo;
504
505
  popupPageId = `page-${browserIdx}-${browserContextIdx}-${pageIdx}`;
505
506
  pageInfo.openType = "popup";
507
+ evtData = this.browserContext().page(pageIdx);
506
508
  } else {
507
509
  (0, import_utils2.logerr)(`##browser ${pageId} has popup without page.pageInfo`);
508
510
  }
509
511
  (0, import_utils2.loginfo)(`##browser ${pageId} has popup ${popupPageId}`);
510
- this.emit("pagePopup", pageInfo);
512
+ this.emit("pagePopup", evtData);
511
513
  } else {
512
514
  (0, import_utils2.logerr)(`##browser ${pageId} has popup page with null page`);
513
515
  }
@@ -667,12 +669,19 @@ var PlaywrightPage = class extends import_node_events.default {
667
669
  await this.clearResponseInterceptions();
668
670
  return true;
669
671
  }
672
+ #getWaitUntil(origWaitUntil) {
673
+ if (origWaitUntil === "networkidle0" || origWaitUntil === "networkidle2") {
674
+ return "networkidle";
675
+ } else {
676
+ return origWaitUntil;
677
+ }
678
+ }
670
679
  async goto(url, options) {
671
680
  if (!this.#page) {
672
681
  throw new Error("No valid page");
673
682
  }
674
683
  if (options) {
675
- const { referer, timeout, waitUntil } = options;
684
+ const { referer, timeout, waitUntil = "load" } = options;
676
685
  const newOptions = {};
677
686
  if (referer) {
678
687
  newOptions.referer = referer;
@@ -680,9 +689,7 @@ var PlaywrightPage = class extends import_node_events.default {
680
689
  if (timeout) {
681
690
  newOptions.timeout = timeout;
682
691
  }
683
- if (waitUntil && waitUntil !== "commit") {
684
- newOptions.waitUntil = waitUntil === "networkidle" ? "networkidle0" : waitUntil;
685
- }
692
+ newOptions.waitUntil = this.#getWaitUntil(waitUntil);
686
693
  await this.#page.goto(url, newOptions);
687
694
  } else {
688
695
  await this.#page.goto(url);
@@ -1015,6 +1022,30 @@ var PlaywrightPage = class extends import_node_events.default {
1015
1022
  this.#status = "busy";
1016
1023
  return true;
1017
1024
  }
1025
+ async waitForElement(selector, options = {}) {
1026
+ if (!this.#page) {
1027
+ throw new Error("No valid page");
1028
+ }
1029
+ const locator = this.#page.locator(selector);
1030
+ const { timeout = 3e4, state = "visible" } = options;
1031
+ await locator.waitFor({ state, timeout });
1032
+ return true;
1033
+ }
1034
+ async waitForNavigation(options) {
1035
+ if (!this.#page) {
1036
+ throw new Error("No valid page");
1037
+ }
1038
+ const { url = "", timeout = 3e4, waitUntil = "load" } = options;
1039
+ const newWaitUntil = this.#getWaitUntil(waitUntil);
1040
+ if (url) {
1041
+ await this.#page.waitForURL(url, { timeout, waitUntil: newWaitUntil });
1042
+ } else if (newWaitUntil === "commit") {
1043
+ throw new Error("commit is not supported in PlaywrightPage.waitForNavigation");
1044
+ } else {
1045
+ await this.#page.waitForLoadState(newWaitUntil, { timeout });
1046
+ }
1047
+ return true;
1048
+ }
1018
1049
  async windowMember(keys) {
1019
1050
  if (!this.#page) {
1020
1051
  throw new Error("No valid page");
@@ -1237,6 +1268,10 @@ var PlaywrightBrowserContext = class extends import_node_events2.default {
1237
1268
  isIncognito() {
1238
1269
  return this.#incognito;
1239
1270
  }
1271
+ page(pageIdx) {
1272
+ const lsdPage = this.#lsdPages.find((p) => p.pageInfo().pageIdx === pageIdx);
1273
+ return lsdPage ? lsdPage : null;
1274
+ }
1240
1275
  pages() {
1241
1276
  return this.#lsdPages;
1242
1277
  }
@@ -1873,17 +1908,19 @@ var PuppeteerPage = class extends import_node_events4.default {
1873
1908
  });
1874
1909
  page.on("popup", (p) => {
1875
1910
  if (p) {
1911
+ let evtData = null;
1876
1912
  const pageInfo = p.pageInfo;
1877
1913
  let popupPageId = "page";
1878
1914
  if (pageInfo) {
1879
1915
  const { browserIdx, browserContextIdx, pageIdx } = pageInfo;
1880
1916
  popupPageId = `page-${browserIdx}-${browserContextIdx}-${pageIdx}`;
1881
1917
  pageInfo.openType = "popup";
1918
+ evtData = this.browserContext().page(pageIdx);
1882
1919
  } else {
1883
1920
  (0, import_utils6.logerr)(`##browser ${pageId} has popup without page.pageInfo`);
1884
1921
  }
1885
1922
  (0, import_utils6.loginfo)(`##browser ${pageId} has popup ${popupPageId}`);
1886
- this.emit("pagePopup", pageInfo);
1923
+ this.emit("pagePopup", evtData);
1887
1924
  } else {
1888
1925
  (0, import_utils6.logerr)(`##browser ${pageId} has popup page with null page`);
1889
1926
  }
@@ -2042,12 +2079,21 @@ var PuppeteerPage = class extends import_node_events4.default {
2042
2079
  await this.clearResponseInterceptions();
2043
2080
  return true;
2044
2081
  }
2082
+ #getWaitUntil(origWaitUntil) {
2083
+ if (origWaitUntil === "networkidle") {
2084
+ return "networkidle0";
2085
+ } else if (origWaitUntil === "commit") {
2086
+ throw new Error("commit is not supported in PuppeteerPage");
2087
+ } else {
2088
+ return origWaitUntil;
2089
+ }
2090
+ }
2045
2091
  async goto(url, options) {
2046
2092
  if (!this.#page) {
2047
2093
  throw new Error("No valid page");
2048
2094
  }
2049
2095
  if (options) {
2050
- const { referer, timeout, waitUntil } = options;
2096
+ const { referer, timeout, waitUntil = "load" } = options;
2051
2097
  const newOptions = {};
2052
2098
  if (referer) {
2053
2099
  newOptions.referer = referer;
@@ -2056,7 +2102,7 @@ var PuppeteerPage = class extends import_node_events4.default {
2056
2102
  newOptions.timeout = timeout;
2057
2103
  }
2058
2104
  if (waitUntil && waitUntil !== "commit") {
2059
- newOptions.waitUntil = waitUntil === "networkidle" ? "networkidle0" : waitUntil;
2105
+ newOptions.waitUntil = this.#getWaitUntil(waitUntil);
2060
2106
  }
2061
2107
  await this.#page.goto(url, newOptions);
2062
2108
  } else {
@@ -2370,6 +2416,33 @@ var PuppeteerPage = class extends import_node_events4.default {
2370
2416
  this.#status = "busy";
2371
2417
  return true;
2372
2418
  }
2419
+ async waitForElement(selector, options = {}) {
2420
+ if (!this.#page) {
2421
+ throw new Error("No valid page");
2422
+ }
2423
+ const { timeout = 3e4, state = "visible" } = options;
2424
+ if (state === "visible") {
2425
+ await this.#page.waitForSelector(selector, { timeout, visible: true });
2426
+ } else if (state === "hidden") {
2427
+ await this.#page.waitForSelector(selector, { timeout, hidden: true });
2428
+ } else {
2429
+ throw new Error(`${state} is not supported in PuppeteerPage.waitForElement`);
2430
+ }
2431
+ return true;
2432
+ }
2433
+ async waitForNavigation(options) {
2434
+ if (!this.#page) {
2435
+ throw new Error("No valid page");
2436
+ }
2437
+ const { url = "", timeout = 3e4, waitUntil = "load" } = options;
2438
+ const newWaitUntil = this.#getWaitUntil(waitUntil);
2439
+ if (url) {
2440
+ throw new Error("url is not supported in PuppeteerPage.waitForNavigation");
2441
+ } else {
2442
+ await this.#page.waitForNavigation({ timeout, waitUntil: newWaitUntil });
2443
+ }
2444
+ return true;
2445
+ }
2373
2446
  async windowMember(keys) {
2374
2447
  if (!this.#page) {
2375
2448
  throw new Error("No valid page");
@@ -2610,6 +2683,10 @@ var PuppeteerBrowserContext = class extends import_node_events5.default {
2610
2683
  isIncognito() {
2611
2684
  return this.#incognito;
2612
2685
  }
2686
+ page(pageIdx) {
2687
+ const lsdPage = this.#lsdPages.find((p) => p.pageInfo().pageIdx === pageIdx);
2688
+ return lsdPage ? lsdPage : null;
2689
+ }
2613
2690
  pages() {
2614
2691
  return this.#lsdPages;
2615
2692
  }
@@ -16946,6 +17023,12 @@ var CheerioPage = class extends import_node_events7.default {
16946
17023
  use() {
16947
17024
  throw new Error("Not supported in CheerioPage.");
16948
17025
  }
17026
+ waitForElement() {
17027
+ throw new Error("Not supported in CheerioPage.");
17028
+ }
17029
+ waitForNavigation() {
17030
+ throw new Error("Not supported in CheerioPage.");
17031
+ }
16949
17032
  async windowMember() {
16950
17033
  throw new Error("Not supported in CheerioPage.");
16951
17034
  }
package/dist/index.d.cts CHANGED
@@ -243,14 +243,15 @@ interface SelectOptions {
243
243
  */
244
244
  labels?: string[];
245
245
  }
246
+ /**
247
+ * * playwright: "load" | "domcontentloaded" | "networkidle" | "commit", "networkidle0" | "networkidle2" => "networkidle";
248
+ * * puppeteer: "load" | "domcontentloaded" | "networkidle0" | "networkidle2", "networkidle" => "networkidle0", "commit" ignored;
249
+ */
250
+ type NavigationWaitUntil = "load" | "domcontentloaded" | "networkidle" | "commit" | "networkidle0" | "networkidle2";
246
251
  interface GotoOptions {
247
252
  referer?: string;
248
253
  timeout?: number;
249
- /**
250
- * playwright: "load" | "domcontentloaded" | "networkidle" | "commit", "networkidle0" | "networkidle2" => "networkidle";
251
- * puppeteer: "load" | "domcontentloaded" | "networkidle0" | "networkidle2", "networkidle" => "networkidle0", "commit" ignored;
252
- */
253
- waitUntil?: "load" | "domcontentloaded" | "networkidle" | "commit" | "networkidle0" | "networkidle2";
254
+ waitUntil?: NavigationWaitUntil;
254
255
  }
255
256
  /**
256
257
  * * src takes precedence over selector, at least one of them must be defined
@@ -684,6 +685,33 @@ interface ScreenshotOptions {
684
685
  */
685
686
  type?: 'png' | 'jpeg';
686
687
  }
688
+ type WaitElementState = "attached" | "detached" | "hidden" | "visible";
689
+ interface WaitElementOptions {
690
+ /**
691
+ * @default 30_000 ms
692
+ */
693
+ timeout?: number;
694
+ /**
695
+ * @default "visible"
696
+ */
697
+ state?: WaitElementState;
698
+ }
699
+ interface WaitNavigationOptions {
700
+ /**
701
+ * only supported in playwright by now
702
+ * @default ""
703
+ */
704
+ url?: string | RegExp;
705
+ /**
706
+ * @default 30_000 ms
707
+ */
708
+ timeout?: number;
709
+ /**
710
+ * @default "visible"
711
+ */
712
+ waitUntil?: NavigationWaitUntil;
713
+ }
714
+ type PageEvent = "pageClose" | "pagePopup";
687
715
  interface LsdPage extends EventEmitter {
688
716
  bringToFront(): Promise<boolean>;
689
717
  browserContext(): LsdBrowserContext;
@@ -778,6 +806,17 @@ interface LsdPage extends EventEmitter {
778
806
  * 开始使用该page(当前状态必须为free)
779
807
  */
780
808
  use(): boolean;
809
+ /**
810
+ *
811
+ * @param selector CSS selector, not XPath
812
+ * @param options
813
+ */
814
+ waitForElement(selector: string, options?: WaitElementOptions): Promise<boolean>;
815
+ /**
816
+ *
817
+ * @param options
818
+ */
819
+ waitForNavigation(options: WaitNavigationOptions): Promise<boolean>;
781
820
  /**
782
821
  * obj=window?.[key1]...?.[keyn]
783
822
  * @return obj ? JSON.stringify(obj) : ""
@@ -806,6 +845,7 @@ interface LsdBrowserContext extends EventEmitter {
806
845
  hasNewPage(pageNum?: number): boolean;
807
846
  id(): string;
808
847
  isIncognito(): boolean;
848
+ page(pageIdx: number): LsdPage | null;
809
849
  pages(): LsdPage[];
810
850
  proxy(): Proxy | null;
811
851
  setStateData(stateData: StateData): Promise<boolean>;
@@ -886,6 +926,7 @@ declare class PlaywrightBrowserContext extends EventEmitter implements LsdBrowse
886
926
  hasNewPage(pageNum?: number): boolean;
887
927
  id(): string;
888
928
  isIncognito(): boolean;
929
+ page(pageIdx: number): LsdPage | null;
889
930
  pages(): LsdPage[];
890
931
  proxy(): Proxy | null;
891
932
  setStateData(stateData: StateData): Promise<boolean>;
@@ -937,6 +978,8 @@ declare class PlaywrightPage extends EventEmitter implements LsdPage {
937
978
  title(): Promise<string>;
938
979
  url(): string;
939
980
  use(): boolean;
981
+ waitForElement(selector: string, options?: WaitElementOptions): Promise<boolean>;
982
+ waitForNavigation(options: WaitNavigationOptions): Promise<boolean>;
940
983
  windowMember(keys: string[]): Promise<string>;
941
984
  }
942
985
 
@@ -990,6 +1033,7 @@ declare class PuppeteerBrowserContext extends EventEmitter implements LsdBrowser
990
1033
  hasNewPage(pageNum?: number): boolean;
991
1034
  id(): string;
992
1035
  isIncognito(): boolean;
1036
+ page(pageIdx: number): LsdPage | null;
993
1037
  pages(): LsdPage[];
994
1038
  proxy(): Proxy | null;
995
1039
  setStateData(stateData: StateData): Promise<boolean>;
@@ -1041,6 +1085,8 @@ declare class PuppeteerPage extends EventEmitter implements LsdPage {
1041
1085
  title(): Promise<string>;
1042
1086
  url(): string;
1043
1087
  use(): boolean;
1088
+ waitForElement(selector: string, options?: WaitElementOptions): Promise<boolean>;
1089
+ waitForNavigation(options: WaitNavigationOptions): Promise<boolean>;
1044
1090
  windowMember(keys: string[]): Promise<string>;
1045
1091
  }
1046
1092
 
@@ -1110,6 +1156,8 @@ declare class CheerioPage extends EventEmitter implements LsdPage {
1110
1156
  title(): Promise<string>;
1111
1157
  url(): string;
1112
1158
  use(): boolean;
1159
+ waitForElement(): Promise<boolean>;
1160
+ waitForNavigation(): Promise<boolean>;
1113
1161
  windowMember(): Promise<string>;
1114
1162
  }
1115
1163
 
@@ -1135,4 +1183,4 @@ declare class CheerioElement implements LsdElement {
1135
1183
  scrollIntoView(): Promise<boolean>;
1136
1184
  }
1137
1185
 
1138
- export { type AllBrowser, type AllBrowserContext, type AllFrame, type AllPage, type AllResponse, type BrowserControllerOptions, type BrowserControllerType, type BrowserCreationMethod, type BrowserManager, CheerioElement, type CheerioNode, CheerioPage, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type PDFMargin, type PDFOptions, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, PlaywrightElement, PlaywrightPage, type Proxy, PuppeteerBrowser, PuppeteerBrowserContext, PuppeteerElement, PuppeteerPage, type RequestInterceptionAction, type RequestInterceptionOption, type RequestMatch, type RequestMethod, type RequestResourceType, type ResponseHandler, type ResponseHandlerOptions, type ResponseInterceptionItem, type ResponseInterceptionOption, type ResponseMatch, type ScreenshotOptions, type SelectOptions, type StateData, type ViewportSize, defaultProxy };
1186
+ export { type AllBrowser, type AllBrowserContext, type AllFrame, type AllPage, type AllResponse, type BrowserControllerOptions, type BrowserControllerType, type BrowserCreationMethod, type BrowserManager, CheerioElement, type CheerioNode, CheerioPage, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type NavigationWaitUntil, type PDFMargin, type PDFOptions, type PageEvent, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, PlaywrightElement, PlaywrightPage, type Proxy, PuppeteerBrowser, PuppeteerBrowserContext, PuppeteerElement, PuppeteerPage, type RequestInterceptionAction, type RequestInterceptionOption, type RequestMatch, type RequestMethod, type RequestResourceType, type ResponseHandler, type ResponseHandlerOptions, type ResponseInterceptionItem, type ResponseInterceptionOption, type ResponseMatch, type ScreenshotOptions, type SelectOptions, type StateData, type ViewportSize, type WaitElementOptions, type WaitElementState, type WaitNavigationOptions, defaultProxy };
package/dist/index.d.ts CHANGED
@@ -243,14 +243,15 @@ interface SelectOptions {
243
243
  */
244
244
  labels?: string[];
245
245
  }
246
+ /**
247
+ * * playwright: "load" | "domcontentloaded" | "networkidle" | "commit", "networkidle0" | "networkidle2" => "networkidle";
248
+ * * puppeteer: "load" | "domcontentloaded" | "networkidle0" | "networkidle2", "networkidle" => "networkidle0", "commit" ignored;
249
+ */
250
+ type NavigationWaitUntil = "load" | "domcontentloaded" | "networkidle" | "commit" | "networkidle0" | "networkidle2";
246
251
  interface GotoOptions {
247
252
  referer?: string;
248
253
  timeout?: number;
249
- /**
250
- * playwright: "load" | "domcontentloaded" | "networkidle" | "commit", "networkidle0" | "networkidle2" => "networkidle";
251
- * puppeteer: "load" | "domcontentloaded" | "networkidle0" | "networkidle2", "networkidle" => "networkidle0", "commit" ignored;
252
- */
253
- waitUntil?: "load" | "domcontentloaded" | "networkidle" | "commit" | "networkidle0" | "networkidle2";
254
+ waitUntil?: NavigationWaitUntil;
254
255
  }
255
256
  /**
256
257
  * * src takes precedence over selector, at least one of them must be defined
@@ -684,6 +685,33 @@ interface ScreenshotOptions {
684
685
  */
685
686
  type?: 'png' | 'jpeg';
686
687
  }
688
+ type WaitElementState = "attached" | "detached" | "hidden" | "visible";
689
+ interface WaitElementOptions {
690
+ /**
691
+ * @default 30_000 ms
692
+ */
693
+ timeout?: number;
694
+ /**
695
+ * @default "visible"
696
+ */
697
+ state?: WaitElementState;
698
+ }
699
+ interface WaitNavigationOptions {
700
+ /**
701
+ * only supported in playwright by now
702
+ * @default ""
703
+ */
704
+ url?: string | RegExp;
705
+ /**
706
+ * @default 30_000 ms
707
+ */
708
+ timeout?: number;
709
+ /**
710
+ * @default "visible"
711
+ */
712
+ waitUntil?: NavigationWaitUntil;
713
+ }
714
+ type PageEvent = "pageClose" | "pagePopup";
687
715
  interface LsdPage extends EventEmitter {
688
716
  bringToFront(): Promise<boolean>;
689
717
  browserContext(): LsdBrowserContext;
@@ -778,6 +806,17 @@ interface LsdPage extends EventEmitter {
778
806
  * 开始使用该page(当前状态必须为free)
779
807
  */
780
808
  use(): boolean;
809
+ /**
810
+ *
811
+ * @param selector CSS selector, not XPath
812
+ * @param options
813
+ */
814
+ waitForElement(selector: string, options?: WaitElementOptions): Promise<boolean>;
815
+ /**
816
+ *
817
+ * @param options
818
+ */
819
+ waitForNavigation(options: WaitNavigationOptions): Promise<boolean>;
781
820
  /**
782
821
  * obj=window?.[key1]...?.[keyn]
783
822
  * @return obj ? JSON.stringify(obj) : ""
@@ -806,6 +845,7 @@ interface LsdBrowserContext extends EventEmitter {
806
845
  hasNewPage(pageNum?: number): boolean;
807
846
  id(): string;
808
847
  isIncognito(): boolean;
848
+ page(pageIdx: number): LsdPage | null;
809
849
  pages(): LsdPage[];
810
850
  proxy(): Proxy | null;
811
851
  setStateData(stateData: StateData): Promise<boolean>;
@@ -886,6 +926,7 @@ declare class PlaywrightBrowserContext extends EventEmitter implements LsdBrowse
886
926
  hasNewPage(pageNum?: number): boolean;
887
927
  id(): string;
888
928
  isIncognito(): boolean;
929
+ page(pageIdx: number): LsdPage | null;
889
930
  pages(): LsdPage[];
890
931
  proxy(): Proxy | null;
891
932
  setStateData(stateData: StateData): Promise<boolean>;
@@ -937,6 +978,8 @@ declare class PlaywrightPage extends EventEmitter implements LsdPage {
937
978
  title(): Promise<string>;
938
979
  url(): string;
939
980
  use(): boolean;
981
+ waitForElement(selector: string, options?: WaitElementOptions): Promise<boolean>;
982
+ waitForNavigation(options: WaitNavigationOptions): Promise<boolean>;
940
983
  windowMember(keys: string[]): Promise<string>;
941
984
  }
942
985
 
@@ -990,6 +1033,7 @@ declare class PuppeteerBrowserContext extends EventEmitter implements LsdBrowser
990
1033
  hasNewPage(pageNum?: number): boolean;
991
1034
  id(): string;
992
1035
  isIncognito(): boolean;
1036
+ page(pageIdx: number): LsdPage | null;
993
1037
  pages(): LsdPage[];
994
1038
  proxy(): Proxy | null;
995
1039
  setStateData(stateData: StateData): Promise<boolean>;
@@ -1041,6 +1085,8 @@ declare class PuppeteerPage extends EventEmitter implements LsdPage {
1041
1085
  title(): Promise<string>;
1042
1086
  url(): string;
1043
1087
  use(): boolean;
1088
+ waitForElement(selector: string, options?: WaitElementOptions): Promise<boolean>;
1089
+ waitForNavigation(options: WaitNavigationOptions): Promise<boolean>;
1044
1090
  windowMember(keys: string[]): Promise<string>;
1045
1091
  }
1046
1092
 
@@ -1110,6 +1156,8 @@ declare class CheerioPage extends EventEmitter implements LsdPage {
1110
1156
  title(): Promise<string>;
1111
1157
  url(): string;
1112
1158
  use(): boolean;
1159
+ waitForElement(): Promise<boolean>;
1160
+ waitForNavigation(): Promise<boolean>;
1113
1161
  windowMember(): Promise<string>;
1114
1162
  }
1115
1163
 
@@ -1135,4 +1183,4 @@ declare class CheerioElement implements LsdElement {
1135
1183
  scrollIntoView(): Promise<boolean>;
1136
1184
  }
1137
1185
 
1138
- export { type AllBrowser, type AllBrowserContext, type AllFrame, type AllPage, type AllResponse, type BrowserControllerOptions, type BrowserControllerType, type BrowserCreationMethod, type BrowserManager, CheerioElement, type CheerioNode, CheerioPage, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type PDFMargin, type PDFOptions, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, PlaywrightElement, PlaywrightPage, type Proxy, PuppeteerBrowser, PuppeteerBrowserContext, PuppeteerElement, PuppeteerPage, type RequestInterceptionAction, type RequestInterceptionOption, type RequestMatch, type RequestMethod, type RequestResourceType, type ResponseHandler, type ResponseHandlerOptions, type ResponseInterceptionItem, type ResponseInterceptionOption, type ResponseMatch, type ScreenshotOptions, type SelectOptions, type StateData, type ViewportSize, defaultProxy };
1186
+ export { type AllBrowser, type AllBrowserContext, type AllFrame, type AllPage, type AllResponse, type BrowserControllerOptions, type BrowserControllerType, type BrowserCreationMethod, type BrowserManager, CheerioElement, type CheerioNode, CheerioPage, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type NavigationWaitUntil, type PDFMargin, type PDFOptions, type PageEvent, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, PlaywrightElement, PlaywrightPage, type Proxy, PuppeteerBrowser, PuppeteerBrowserContext, PuppeteerElement, PuppeteerPage, type RequestInterceptionAction, type RequestInterceptionOption, type RequestMatch, type RequestMethod, type RequestResourceType, type ResponseHandler, type ResponseHandlerOptions, type ResponseInterceptionItem, type ResponseInterceptionOption, type ResponseMatch, type ScreenshotOptions, type SelectOptions, type StateData, type ViewportSize, type WaitElementOptions, type WaitElementState, type WaitNavigationOptions, defaultProxy };
package/dist/index.js CHANGED
@@ -478,17 +478,19 @@ var PlaywrightPage = class extends EventEmitter {
478
478
  });
479
479
  page.on("popup", (p) => {
480
480
  if (p) {
481
+ let evtData = null;
481
482
  const pageInfo = p.pageInfo;
482
483
  let popupPageId = "page";
483
484
  if (pageInfo) {
484
485
  const { browserIdx, browserContextIdx, pageIdx } = pageInfo;
485
486
  popupPageId = `page-${browserIdx}-${browserContextIdx}-${pageIdx}`;
486
487
  pageInfo.openType = "popup";
488
+ evtData = this.browserContext().page(pageIdx);
487
489
  } else {
488
490
  logerr(`##browser ${pageId} has popup without page.pageInfo`);
489
491
  }
490
492
  loginfo(`##browser ${pageId} has popup ${popupPageId}`);
491
- this.emit("pagePopup", pageInfo);
493
+ this.emit("pagePopup", evtData);
492
494
  } else {
493
495
  logerr(`##browser ${pageId} has popup page with null page`);
494
496
  }
@@ -648,12 +650,19 @@ var PlaywrightPage = class extends EventEmitter {
648
650
  await this.clearResponseInterceptions();
649
651
  return true;
650
652
  }
653
+ #getWaitUntil(origWaitUntil) {
654
+ if (origWaitUntil === "networkidle0" || origWaitUntil === "networkidle2") {
655
+ return "networkidle";
656
+ } else {
657
+ return origWaitUntil;
658
+ }
659
+ }
651
660
  async goto(url, options) {
652
661
  if (!this.#page) {
653
662
  throw new Error("No valid page");
654
663
  }
655
664
  if (options) {
656
- const { referer, timeout, waitUntil } = options;
665
+ const { referer, timeout, waitUntil = "load" } = options;
657
666
  const newOptions = {};
658
667
  if (referer) {
659
668
  newOptions.referer = referer;
@@ -661,9 +670,7 @@ var PlaywrightPage = class extends EventEmitter {
661
670
  if (timeout) {
662
671
  newOptions.timeout = timeout;
663
672
  }
664
- if (waitUntil && waitUntil !== "commit") {
665
- newOptions.waitUntil = waitUntil === "networkidle" ? "networkidle0" : waitUntil;
666
- }
673
+ newOptions.waitUntil = this.#getWaitUntil(waitUntil);
667
674
  await this.#page.goto(url, newOptions);
668
675
  } else {
669
676
  await this.#page.goto(url);
@@ -996,6 +1003,30 @@ var PlaywrightPage = class extends EventEmitter {
996
1003
  this.#status = "busy";
997
1004
  return true;
998
1005
  }
1006
+ async waitForElement(selector, options = {}) {
1007
+ if (!this.#page) {
1008
+ throw new Error("No valid page");
1009
+ }
1010
+ const locator = this.#page.locator(selector);
1011
+ const { timeout = 3e4, state = "visible" } = options;
1012
+ await locator.waitFor({ state, timeout });
1013
+ return true;
1014
+ }
1015
+ async waitForNavigation(options) {
1016
+ if (!this.#page) {
1017
+ throw new Error("No valid page");
1018
+ }
1019
+ const { url = "", timeout = 3e4, waitUntil = "load" } = options;
1020
+ const newWaitUntil = this.#getWaitUntil(waitUntil);
1021
+ if (url) {
1022
+ await this.#page.waitForURL(url, { timeout, waitUntil: newWaitUntil });
1023
+ } else if (newWaitUntil === "commit") {
1024
+ throw new Error("commit is not supported in PlaywrightPage.waitForNavigation");
1025
+ } else {
1026
+ await this.#page.waitForLoadState(newWaitUntil, { timeout });
1027
+ }
1028
+ return true;
1029
+ }
999
1030
  async windowMember(keys) {
1000
1031
  if (!this.#page) {
1001
1032
  throw new Error("No valid page");
@@ -1218,6 +1249,10 @@ var PlaywrightBrowserContext = class extends EventEmitter2 {
1218
1249
  isIncognito() {
1219
1250
  return this.#incognito;
1220
1251
  }
1252
+ page(pageIdx) {
1253
+ const lsdPage = this.#lsdPages.find((p) => p.pageInfo().pageIdx === pageIdx);
1254
+ return lsdPage ? lsdPage : null;
1255
+ }
1221
1256
  pages() {
1222
1257
  return this.#lsdPages;
1223
1258
  }
@@ -1854,17 +1889,19 @@ var PuppeteerPage = class extends EventEmitter4 {
1854
1889
  });
1855
1890
  page.on("popup", (p) => {
1856
1891
  if (p) {
1892
+ let evtData = null;
1857
1893
  const pageInfo = p.pageInfo;
1858
1894
  let popupPageId = "page";
1859
1895
  if (pageInfo) {
1860
1896
  const { browserIdx, browserContextIdx, pageIdx } = pageInfo;
1861
1897
  popupPageId = `page-${browserIdx}-${browserContextIdx}-${pageIdx}`;
1862
1898
  pageInfo.openType = "popup";
1899
+ evtData = this.browserContext().page(pageIdx);
1863
1900
  } else {
1864
1901
  logerr5(`##browser ${pageId} has popup without page.pageInfo`);
1865
1902
  }
1866
1903
  loginfo4(`##browser ${pageId} has popup ${popupPageId}`);
1867
- this.emit("pagePopup", pageInfo);
1904
+ this.emit("pagePopup", evtData);
1868
1905
  } else {
1869
1906
  logerr5(`##browser ${pageId} has popup page with null page`);
1870
1907
  }
@@ -2023,12 +2060,21 @@ var PuppeteerPage = class extends EventEmitter4 {
2023
2060
  await this.clearResponseInterceptions();
2024
2061
  return true;
2025
2062
  }
2063
+ #getWaitUntil(origWaitUntil) {
2064
+ if (origWaitUntil === "networkidle") {
2065
+ return "networkidle0";
2066
+ } else if (origWaitUntil === "commit") {
2067
+ throw new Error("commit is not supported in PuppeteerPage");
2068
+ } else {
2069
+ return origWaitUntil;
2070
+ }
2071
+ }
2026
2072
  async goto(url, options) {
2027
2073
  if (!this.#page) {
2028
2074
  throw new Error("No valid page");
2029
2075
  }
2030
2076
  if (options) {
2031
- const { referer, timeout, waitUntil } = options;
2077
+ const { referer, timeout, waitUntil = "load" } = options;
2032
2078
  const newOptions = {};
2033
2079
  if (referer) {
2034
2080
  newOptions.referer = referer;
@@ -2037,7 +2083,7 @@ var PuppeteerPage = class extends EventEmitter4 {
2037
2083
  newOptions.timeout = timeout;
2038
2084
  }
2039
2085
  if (waitUntil && waitUntil !== "commit") {
2040
- newOptions.waitUntil = waitUntil === "networkidle" ? "networkidle0" : waitUntil;
2086
+ newOptions.waitUntil = this.#getWaitUntil(waitUntil);
2041
2087
  }
2042
2088
  await this.#page.goto(url, newOptions);
2043
2089
  } else {
@@ -2351,6 +2397,33 @@ var PuppeteerPage = class extends EventEmitter4 {
2351
2397
  this.#status = "busy";
2352
2398
  return true;
2353
2399
  }
2400
+ async waitForElement(selector, options = {}) {
2401
+ if (!this.#page) {
2402
+ throw new Error("No valid page");
2403
+ }
2404
+ const { timeout = 3e4, state = "visible" } = options;
2405
+ if (state === "visible") {
2406
+ await this.#page.waitForSelector(selector, { timeout, visible: true });
2407
+ } else if (state === "hidden") {
2408
+ await this.#page.waitForSelector(selector, { timeout, hidden: true });
2409
+ } else {
2410
+ throw new Error(`${state} is not supported in PuppeteerPage.waitForElement`);
2411
+ }
2412
+ return true;
2413
+ }
2414
+ async waitForNavigation(options) {
2415
+ if (!this.#page) {
2416
+ throw new Error("No valid page");
2417
+ }
2418
+ const { url = "", timeout = 3e4, waitUntil = "load" } = options;
2419
+ const newWaitUntil = this.#getWaitUntil(waitUntil);
2420
+ if (url) {
2421
+ throw new Error("url is not supported in PuppeteerPage.waitForNavigation");
2422
+ } else {
2423
+ await this.#page.waitForNavigation({ timeout, waitUntil: newWaitUntil });
2424
+ }
2425
+ return true;
2426
+ }
2354
2427
  async windowMember(keys) {
2355
2428
  if (!this.#page) {
2356
2429
  throw new Error("No valid page");
@@ -2591,6 +2664,10 @@ var PuppeteerBrowserContext = class extends EventEmitter5 {
2591
2664
  isIncognito() {
2592
2665
  return this.#incognito;
2593
2666
  }
2667
+ page(pageIdx) {
2668
+ const lsdPage = this.#lsdPages.find((p) => p.pageInfo().pageIdx === pageIdx);
2669
+ return lsdPage ? lsdPage : null;
2670
+ }
2594
2671
  pages() {
2595
2672
  return this.#lsdPages;
2596
2673
  }
@@ -16927,6 +17004,12 @@ var CheerioPage = class extends EventEmitter7 {
16927
17004
  use() {
16928
17005
  throw new Error("Not supported in CheerioPage.");
16929
17006
  }
17007
+ waitForElement() {
17008
+ throw new Error("Not supported in CheerioPage.");
17009
+ }
17010
+ waitForNavigation() {
17011
+ throw new Error("Not supported in CheerioPage.");
17012
+ }
16930
17013
  async windowMember() {
16931
17014
  throw new Error("Not supported in CheerioPage.");
16932
17015
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letsscrapedata/controller",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Unified browser / HTML controller interfaces that support playwright, puppeteer and cheerio",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",