@letsscrapedata/controller 0.0.38 → 0.0.40

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
@@ -76,7 +76,6 @@ var PlaywrightElement = class _PlaywrightElement {
76
76
  return names;
77
77
  }
78
78
  /*
79
- // 如果不存在指定的子iframe,则返回null
80
79
  async #getChildFrame(parentFrame: Frame, iframeOption: IframeOption): Promise<Frame | null> {
81
80
  if (!parentFrame) {
82
81
  throw new Error("Invalid parent frame");
@@ -268,6 +267,13 @@ var PlaywrightElement = class _PlaywrightElement {
268
267
  await this.#locator.press(key, options);
269
268
  return true;
270
269
  }
270
+ async screenshot(options) {
271
+ return await this.#locator.screenshot(options);
272
+ }
273
+ async scrollIntoView() {
274
+ await this.#locator.scrollIntoViewIfNeeded();
275
+ return true;
276
+ }
271
277
  async select(options) {
272
278
  const { type, values = [], labels = [], indexes = [] } = options;
273
279
  switch (type) {
@@ -307,13 +313,15 @@ var PlaywrightElement = class _PlaywrightElement {
307
313
  }
308
314
  return true;
309
315
  }
310
- async screenshot(options) {
311
- return await this.#locator.screenshot(options);
312
- }
313
- async scrollIntoView() {
314
- await this.#locator.scrollIntoViewIfNeeded();
316
+ async setAttribute(attributeName, newValue) {
317
+ await this.#locator.evaluate((node) => {
318
+ node.setAttribute(attributeName, newValue);
319
+ });
315
320
  return true;
316
321
  }
322
+ _origElement() {
323
+ return this.#locator;
324
+ }
317
325
  };
318
326
 
319
327
  // src/playwright/page.ts
@@ -420,7 +428,6 @@ var PlaywrightPage = class extends import_node_events.default {
420
428
  return true;
421
429
  }
422
430
  /*
423
- // 如果不存在指定的子iframe,则返回null
424
431
  async #getChildFrame(parentFrame: Frame, iframeOption: IframeOption): Promise<Frame | null> {
425
432
  if (!parentFrame) {
426
433
  throw new Error("Invalid parent frame");
@@ -1354,6 +1361,13 @@ var PlaywrightBrowserContext = class extends import_node_events2.default {
1354
1361
  return false;
1355
1362
  }
1356
1363
  }
1364
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
1365
+ if (!this.#lsdBrowser.doesMeetBrowserContextRequirements(browserContextRequirements)) {
1366
+ return false;
1367
+ }
1368
+ const { incognitos } = browserContextRequirements;
1369
+ return incognitos.length === 0 || incognitos.includes(this.#incognito);
1370
+ }
1357
1371
  async getPage(always = false) {
1358
1372
  if (!this.#browserContext) {
1359
1373
  throw new Error("Invalid browserContext");
@@ -1491,7 +1505,7 @@ var PlaywrightBrowser = class extends import_node_events3.default {
1491
1505
  #maxPageFreeSeconds() {
1492
1506
  return this.#options.maxPageFreeSeconds ? this.#options.maxPageFreeSeconds : 900;
1493
1507
  }
1494
- // 构造函数:缺省只能由LsdBrowserController.launch/connect调用创建实例!!!
1508
+ // constructor: called only by LsdBrowserController.launch/connect
1495
1509
  constructor(browser, browerType, browserCreateMethod, options, browserIdx = 0, pid = 0) {
1496
1510
  if (!browser || typeof browser.contexts !== "function") {
1497
1511
  throw new Error(`Invalid playwright browser parameter`);
@@ -1557,7 +1571,6 @@ var PlaywrightBrowser = class extends import_node_events3.default {
1557
1571
  await lsdBrowserContext.closeFreePages();
1558
1572
  }
1559
1573
  }
1560
- // 常用方法(按常见调用顺序排序)
1561
1574
  async newBrowserContext(options) {
1562
1575
  if (this.#lsdBrowserContexts.length >= this.#maxBrowserContextsPerBrowser()) {
1563
1576
  (0, import_utils4.logwarn)(`##browser ${this.id()} can not create more new browserContext`);
@@ -1592,7 +1605,6 @@ var PlaywrightBrowser = class extends import_node_events3.default {
1592
1605
  await this.#browser.close();
1593
1606
  return true;
1594
1607
  }
1595
- // 其它方法(按字母顺序排序)
1596
1608
  browserContexts() {
1597
1609
  return this.#lsdBrowserContexts;
1598
1610
  }
@@ -1605,6 +1617,10 @@ var PlaywrightBrowser = class extends import_node_events3.default {
1605
1617
  browserType() {
1606
1618
  return this.#browserType;
1607
1619
  }
1620
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
1621
+ const { browserControllerTypes, browserTypes, headlesses } = browserContextRequirements;
1622
+ return (browserControllerTypes.length === 0 || browserControllerTypes.includes(this.#browserControllerType)) && (browserTypes.length === 0 && browserTypes.includes(this.#browserType)) && (headlesses.length === 0 && headlesses.includes(this.#headless));
1623
+ }
1608
1624
  executablePath() {
1609
1625
  return this.#executablePath;
1610
1626
  }
@@ -1669,7 +1685,6 @@ var PuppeteerElement = class _PuppeteerElement {
1669
1685
  const names = await this.#frame.evaluate((ele) => ele.getAttributeNames(), this.#$ele);
1670
1686
  return names;
1671
1687
  }
1672
- // 如果不存在指定的子iframe,则返回null
1673
1688
  async #getChildFrame(parentFrame, iframeOption) {
1674
1689
  if (!parentFrame) {
1675
1690
  throw new Error("Invalid parent frame");
@@ -1847,6 +1862,15 @@ var PuppeteerElement = class _PuppeteerElement {
1847
1862
  await this.#$ele.press(key, options);
1848
1863
  return true;
1849
1864
  }
1865
+ async screenshot(options) {
1866
+ return await this.#$ele.screenshot(options);
1867
+ }
1868
+ async scrollIntoView() {
1869
+ await this.#frame.evaluate((ele) => {
1870
+ ele.scrollIntoView();
1871
+ }, this.#$ele);
1872
+ return true;
1873
+ }
1850
1874
  async select(options) {
1851
1875
  const { type, values = [], labels = [], indexes = [] } = options;
1852
1876
  switch (type) {
@@ -1901,15 +1925,15 @@ var PuppeteerElement = class _PuppeteerElement {
1901
1925
  }
1902
1926
  return true;
1903
1927
  }
1904
- async screenshot(options) {
1905
- return await this.#$ele.screenshot(options);
1906
- }
1907
- async scrollIntoView() {
1908
- await this.#frame.evaluate((ele) => {
1909
- ele.scrollIntoView();
1910
- }, this.#$ele);
1928
+ async setAttribute(attributeName, newValue) {
1929
+ await this.#frame.evaluate((ele, name, value) => {
1930
+ ele.setAttribute(name, value);
1931
+ }, this.#$ele, attributeName, newValue);
1911
1932
  return true;
1912
1933
  }
1934
+ _origElement() {
1935
+ return this.#$ele;
1936
+ }
1913
1937
  };
1914
1938
 
1915
1939
  // src/puppeteer/page.ts
@@ -1993,7 +2017,6 @@ var PuppeteerPage = class extends import_node_events4.default {
1993
2017
  });
1994
2018
  return true;
1995
2019
  }
1996
- // 如果不存在指定的子iframe,则返回null
1997
2020
  async #getChildFrame(parentFrame, iframeOption) {
1998
2021
  if (!parentFrame) {
1999
2022
  throw new Error("Invalid parent frame");
@@ -2875,6 +2898,13 @@ var PuppeteerBrowserContext = class extends import_node_events5.default {
2875
2898
  return false;
2876
2899
  }
2877
2900
  }
2901
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
2902
+ if (!this.#lsdBrowser.doesMeetBrowserContextRequirements(browserContextRequirements)) {
2903
+ return false;
2904
+ }
2905
+ const { incognitos } = browserContextRequirements;
2906
+ return incognitos.length === 0 || incognitos.includes(this.#incognito);
2907
+ }
2878
2908
  async getPage(always = false) {
2879
2909
  if (!this.#browserContext) {
2880
2910
  throw new Error("Invalid browserContext");
@@ -3017,7 +3047,7 @@ var PuppeteerBrowser = class extends import_node_events6.default {
3017
3047
  #userAgent() {
3018
3048
  return this.#options.userAgent ? this.#options.userAgent : "";
3019
3049
  }
3020
- // 构造函数:缺省只能由LsdBrowserController.launch/connect调用创建实例!!!
3050
+ // constructor: called only by LsdBrowserController.launch/connect
3021
3051
  constructor(browser, browerType, browserCreateMethod, options, browserIdx = 0, pid = 0) {
3022
3052
  if (!browser || typeof browser.browserContexts !== "function") {
3023
3053
  throw new Error(`Invalid puppeteer browser parameter`);
@@ -3080,7 +3110,6 @@ var PuppeteerBrowser = class extends import_node_events6.default {
3080
3110
  await lsdBrowserContext.closeFreePages();
3081
3111
  }
3082
3112
  }
3083
- // 常用方法(按常见调用顺序排序)
3084
3113
  async newBrowserContext(options) {
3085
3114
  if (this.#lsdBrowserContexts.length >= this.#maxBrowserContextsPerBrowser()) {
3086
3115
  (0, import_utils8.logwarn)(`##browser ${this.id()} can not create more new browserContext`);
@@ -3111,7 +3140,6 @@ var PuppeteerBrowser = class extends import_node_events6.default {
3111
3140
  await this.#browser.close();
3112
3141
  return true;
3113
3142
  }
3114
- // 其它方法(按字母顺序排序)
3115
3143
  browserContexts() {
3116
3144
  return this.#lsdBrowserContexts;
3117
3145
  }
@@ -3124,6 +3152,10 @@ var PuppeteerBrowser = class extends import_node_events6.default {
3124
3152
  browserType() {
3125
3153
  return this.#browserType;
3126
3154
  }
3155
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
3156
+ const { browserControllerTypes, browserTypes, headlesses } = browserContextRequirements;
3157
+ return (browserControllerTypes.length === 0 || browserControllerTypes.includes(this.#browserControllerType)) && (browserTypes.length === 0 && browserTypes.includes(this.#browserType)) && (headlesses.length === 0 && headlesses.includes(this.#headless));
3158
+ }
3127
3159
  executablePath() {
3128
3160
  return this.#executablePath;
3129
3161
  }
@@ -3265,13 +3297,19 @@ var CheerioElement = class _CheerioElement {
3265
3297
  async press() {
3266
3298
  throw new Error("Not supported in CheerioElement.");
3267
3299
  }
3300
+ async screenshot() {
3301
+ throw new Error("Not supported in CheerioElement.");
3302
+ }
3303
+ async scrollIntoView() {
3304
+ throw new Error("Not supported in CheerioElement.");
3305
+ }
3268
3306
  async select() {
3269
3307
  throw new Error("Not supported in CheerioElement.");
3270
3308
  }
3271
- async screenshot() {
3309
+ async setAttribute() {
3272
3310
  throw new Error("Not supported in CheerioElement.");
3273
3311
  }
3274
- async scrollIntoView() {
3312
+ _origElement() {
3275
3313
  throw new Error("Not supported in CheerioElement.");
3276
3314
  }
3277
3315
  };
package/dist/index.d.cts CHANGED
@@ -1,23 +1,24 @@
1
1
  import EventEmitter from 'node:events';
2
- import { Browser as Browser$1, BrowserContext as BrowserContext$1, Frame as Frame$1, Page as Page$1, HTTPResponse, PuppeteerNode, ElementHandle } from 'puppeteer';
3
- import { Browser, BrowserContext, Frame, Page, Response, APIRequestContext, BrowserType, Locator, FrameLocator } from 'playwright';
4
-
5
- /**
6
- * 命名规则:为了与playwright/puppeteer中的同名区别
7
- * 1. name of type:AllXxxYyy,如AllBrowserContext
8
- * 2. 接口的实现类class的名称: LsdXxxYyy,如LsdBrowserContext
9
- */
2
+ import { Browser as Browser$1, BrowserContext as BrowserContext$1, Frame as Frame$1, Page as Page$1, ElementHandle, HTTPResponse, PuppeteerNode } from 'puppeteer';
3
+ import { Browser, BrowserContext, Frame, Page, Locator, Response, APIRequestContext, BrowserType, FrameLocator } from 'playwright';
10
4
 
11
5
  type AllBrowser = Browser | Browser$1;
12
6
  type AllBrowserContext = BrowserContext | BrowserContext$1;
13
7
  type AllFrame = Frame | Frame$1;
14
8
  type AllPage = Page | Page$1;
9
+ type AllElement = Locator | ElementHandle;
15
10
  type AllResponse = Response | HTTPResponse;
16
11
  type AllApiRequestContext = APIRequestContext;
17
12
  type CheerioNode = cheerio.Cheerio;
18
13
  type BrowserControllerType = "puppeteer" | "playwright";
19
14
  type BrowserCreationMethod = "launch" | "connect";
20
15
  type LsdBrowserType = "chromium" | "firefox" | "webkit";
16
+ interface BrowserContextRequirements {
17
+ browserControllerTypes: BrowserControllerType[];
18
+ browserTypes: LsdBrowserType[];
19
+ headlesses: boolean[];
20
+ incognitos: boolean[];
21
+ }
21
22
  interface ProxyInController {
22
23
  proxyUrl: string;
23
24
  username?: string;
@@ -208,7 +209,7 @@ type LsdBrowserContextOptions = {
208
209
  type PageStatus = "free" | "busy" | "closed";
209
210
  /**
210
211
  * newpage: open by browserContext.newPage()
211
- * popup: open by clicking etc, 主要关注此类
212
+ * popup: open by clicking etc, important
212
213
  * manual: open by manual operation
213
214
  * launch: open by puppeteer.launch
214
215
  * connect: opened pages before connecting to browser
@@ -245,17 +246,16 @@ interface PageInfo {
245
246
  */
246
247
  openType: PageOpenType;
247
248
  /**
248
- * page添加时间:针对非connect场景,也是page打开时间
249
249
  * @default current unix time
250
250
  */
251
251
  openTime: number;
252
252
  /**
253
- * 上次status变化时间:如果status为free,表示空闲开始时间;如果status为busy,表示TE开始数据
253
+ * page's status: free or busy
254
254
  * @default current unix time
255
255
  */
256
256
  lastStatusUpdateTime: number;
257
257
  /**
258
- * 正在执行的task的ID,参见enumSpecialTaskId
258
+ * taskId that are using this page
259
259
  * @default 0
260
260
  */
261
261
  taskId: number;
@@ -270,12 +270,12 @@ interface PageInfo {
270
270
  }
271
271
  interface UpdatablePageInfo {
272
272
  /**
273
- * 上次status变化时间:如果status为free,表示空闲开始时间;如果status为busy,表示TE开始数据
273
+ * page's status: free or busy
274
274
  * @default current unix time
275
275
  */
276
276
  lastStatusUpdateTime?: number;
277
277
  /**
278
- * 正在执行的task的ID,参见enumSpecialTaskId
278
+ * taskId that are using this page
279
279
  * @default 0
280
280
  */
281
281
  taskId?: number;
@@ -455,9 +455,11 @@ interface LsdElement {
455
455
  */
456
456
  input(value: string, options?: InputOptions): Promise<boolean>;
457
457
  press(key: KeyInput, options: KeyPressOptions): Promise<boolean>;
458
- select(options: SelectOptions): Promise<boolean>;
459
458
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
460
459
  scrollIntoView(): Promise<boolean>;
460
+ select(options: SelectOptions): Promise<boolean>;
461
+ setAttribute(attributeName: string, newValue: string): Promise<boolean>;
462
+ _origElement(): AllElement;
461
463
  }
462
464
  interface ViewportSize {
463
465
  height: number;
@@ -949,7 +951,7 @@ interface LsdPage extends EventEmitter {
949
951
  title(): Promise<string>;
950
952
  url(): string;
951
953
  /**
952
- * 开始使用该page(当前状态必须为free)
954
+ * start to use this free page
953
955
  */
954
956
  use(): boolean;
955
957
  /**
@@ -985,6 +987,11 @@ interface LsdBrowserContext extends EventEmitter {
985
987
  * @default 0 the default maxPageFreeSeconds of the browserContext will be used
986
988
  */
987
989
  closeFreePages(maxPageFreeSeconds?: number): Promise<boolean>;
990
+ /**
991
+ * doest this browser meet browserContextRequirements (incognitos ignored in browser)?
992
+ * @param browserContextRequirements
993
+ */
994
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
988
995
  /**
989
996
  * get a free page from current pages or by creating a new page
990
997
  */
@@ -1016,6 +1023,11 @@ interface LsdBrowser extends EventEmitter {
1016
1023
  browserControllerType(): BrowserControllerType;
1017
1024
  browserCreationMethod(): BrowserCreationMethod;
1018
1025
  browserType(): LsdBrowserType;
1026
+ /**
1027
+ * doest this browser meet browserContextRequirements (incognitos ignored in browser)?
1028
+ * @param browserContextRequirements
1029
+ */
1030
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1019
1031
  /**
1020
1032
  * @returns
1021
1033
  * 1. launched: actual executable path
@@ -1074,33 +1086,6 @@ interface LsdBrowserController$1 {
1074
1086
  */
1075
1087
  newApiContext(options?: LsdApiContextOptions): Promise<LsdApiContext>;
1076
1088
  }
1077
- /**
1078
- * globObj.cfg.XXX:
1079
- * 1. 最大browser数:
1080
- * 2. 最大browserContext数/browser:
1081
- * 3. 最大page数/browserContext:
1082
- *
1083
- * 影响一个browserContext是否满足执行某TE(taskCfg)要求的因素包括:
1084
- * 1. domainCfg/taskCfg对代理的要求:proxyTypes:
1085
- * 2. domainCfg/taskCfg对浏览器的要求:
1086
- * * browserControllerTypes: playwright | puppeteer
1087
- * * browserTypes: chromium | firefox | webkit
1088
- * * browserModes: normal | incognito
1089
- * * browserHeads: headless | headful
1090
- * * APP支持的浏览器因素:globObj.cfg.supportedBrowserControllerTypes/supportedBrowserTypes(尝试启动新浏览器时判断)
1091
- * 3. 能力账号:capName
1092
- *
1093
- * 连接已有浏览器:
1094
- * * endpoint:
1095
- * * browserControllerTypes: playwright | puppeteer
1096
- * * browserType: chromium | firefox | webkit
1097
- * * browserMode: normal
1098
- * * browserHead: headful
1099
- * * proxyTypes:
1100
- */
1101
- interface BrowserManager {
1102
- getPage(): any;
1103
- }
1104
1089
 
1105
1090
  declare class PlaywrightBrowser extends EventEmitter implements LsdBrowser {
1106
1091
  #private;
@@ -1111,6 +1096,7 @@ declare class PlaywrightBrowser extends EventEmitter implements LsdBrowser {
1111
1096
  browserControllerType(): BrowserControllerType;
1112
1097
  browserCreationMethod(): BrowserCreationMethod;
1113
1098
  browserType(): LsdBrowserType;
1099
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1114
1100
  executablePath(): string;
1115
1101
  id(): string;
1116
1102
  isConnected(): boolean;
@@ -1132,6 +1118,7 @@ declare class PlaywrightBrowserContext extends EventEmitter implements LsdBrowse
1132
1118
  browser(): LsdBrowser;
1133
1119
  close(): Promise<boolean>;
1134
1120
  closeFreePages(maxPageFreeSeconds?: number): Promise<boolean>;
1121
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1135
1122
  getPage(always?: boolean): Promise<LsdPage | null>;
1136
1123
  hasFreePage(pageNum?: number): boolean;
1137
1124
  id(): string;
@@ -1214,9 +1201,11 @@ declare class PlaywrightElement implements LsdElement {
1214
1201
  hover(): Promise<boolean>;
1215
1202
  input(value: string, options?: InputOptions): Promise<boolean>;
1216
1203
  press(key: KeyInput, options?: KeyPressOptions): Promise<boolean>;
1217
- select(options: SelectOptions): Promise<boolean>;
1218
1204
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
1219
1205
  scrollIntoView(): Promise<boolean>;
1206
+ select(options: SelectOptions): Promise<boolean>;
1207
+ setAttribute(attributeName: string, newValue: string): Promise<boolean>;
1208
+ _origElement(): AllElement;
1220
1209
  }
1221
1210
 
1222
1211
  declare class PuppeteerBrowser extends EventEmitter implements LsdBrowser {
@@ -1228,6 +1217,7 @@ declare class PuppeteerBrowser extends EventEmitter implements LsdBrowser {
1228
1217
  browserControllerType(): BrowserControllerType;
1229
1218
  browserCreationMethod(): BrowserCreationMethod;
1230
1219
  browserType(): LsdBrowserType;
1220
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1231
1221
  executablePath(): string;
1232
1222
  id(): string;
1233
1223
  isConnected(): boolean;
@@ -1249,6 +1239,7 @@ declare class PuppeteerBrowserContext extends EventEmitter implements LsdBrowser
1249
1239
  browser(): LsdBrowser;
1250
1240
  close(): Promise<boolean>;
1251
1241
  closeFreePages(maxPageFreeSeconds?: number): Promise<boolean>;
1242
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1252
1243
  getPage(always?: boolean): Promise<LsdPage | null>;
1253
1244
  hasFreePage(pageNum?: number): boolean;
1254
1245
  id(): string;
@@ -1331,9 +1322,11 @@ declare class PuppeteerElement implements LsdElement {
1331
1322
  hover(): Promise<boolean>;
1332
1323
  input(value: string, options?: InputOptions): Promise<boolean>;
1333
1324
  press(key: KeyInput, options?: KeyPressOptions): Promise<boolean>;
1334
- select(options: SelectOptions): Promise<boolean>;
1335
1325
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
1336
1326
  scrollIntoView(): Promise<boolean>;
1327
+ select(options: SelectOptions): Promise<boolean>;
1328
+ setAttribute(attributeName: string, newValue: string): Promise<boolean>;
1329
+ _origElement(): AllElement;
1337
1330
  }
1338
1331
 
1339
1332
  declare class CheerioPage extends EventEmitter implements LsdPage {
@@ -1411,9 +1404,11 @@ declare class CheerioElement implements LsdElement {
1411
1404
  hover(): Promise<boolean>;
1412
1405
  input(): Promise<boolean>;
1413
1406
  press(): Promise<boolean>;
1414
- select(): Promise<boolean>;
1415
1407
  screenshot(): Promise<Buffer>;
1416
1408
  scrollIntoView(): Promise<boolean>;
1409
+ select(): Promise<boolean>;
1410
+ setAttribute(): Promise<boolean>;
1411
+ _origElement(): AllElement;
1417
1412
  }
1418
1413
 
1419
1414
  declare class LsdBrowserController implements LsdBrowserController$1 {
@@ -1427,4 +1422,4 @@ declare class LsdBrowserController implements LsdBrowserController$1 {
1427
1422
  }
1428
1423
  declare const controller: LsdBrowserController;
1429
1424
 
1430
- export { type AllApiRequestContext, type AllBrowser, type AllBrowserContext, type AllFrame, type AllPage, type AllResponse, type BrowserControllerType, type BrowserCreationMethod, type BrowserLaunchMethod, type BrowserManager, type BrowserStateData, CheerioElement, type CheerioNode, CheerioPage, type ClientCertificate, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdApiContext, type LsdApiContextOptions, type LsdApiResponse, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController$1 as LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdFetchOptions, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type MouseClickType, type NavigationWaitUntil, type PDFMargin, type PDFOptions, type PageEvent, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, type PlaywrightBrowserTypes, PlaywrightElement, PlaywrightPage, type ProxyInController, 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 ResponsePageData, type ScreenshotOptions, type SelectOptions, type UpdatablePageInfo, type ViewportSize, type WaitElementOptions, type WaitElementState, type WaitNavigationOptions, controller };
1425
+ export { type AllApiRequestContext, type AllBrowser, type AllBrowserContext, type AllElement, type AllFrame, type AllPage, type AllResponse, type BrowserContextRequirements, type BrowserControllerType, type BrowserCreationMethod, type BrowserLaunchMethod, type BrowserStateData, CheerioElement, type CheerioNode, CheerioPage, type ClientCertificate, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdApiContext, type LsdApiContextOptions, type LsdApiResponse, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController$1 as LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdFetchOptions, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type MouseClickType, type NavigationWaitUntil, type PDFMargin, type PDFOptions, type PageEvent, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, type PlaywrightBrowserTypes, PlaywrightElement, PlaywrightPage, type ProxyInController, 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 ResponsePageData, type ScreenshotOptions, type SelectOptions, type UpdatablePageInfo, type ViewportSize, type WaitElementOptions, type WaitElementState, type WaitNavigationOptions, controller };
package/dist/index.d.ts CHANGED
@@ -1,23 +1,24 @@
1
1
  import EventEmitter from 'node:events';
2
- import { Browser as Browser$1, BrowserContext as BrowserContext$1, Frame as Frame$1, Page as Page$1, HTTPResponse, PuppeteerNode, ElementHandle } from 'puppeteer';
3
- import { Browser, BrowserContext, Frame, Page, Response, APIRequestContext, BrowserType, Locator, FrameLocator } from 'playwright';
4
-
5
- /**
6
- * 命名规则:为了与playwright/puppeteer中的同名区别
7
- * 1. name of type:AllXxxYyy,如AllBrowserContext
8
- * 2. 接口的实现类class的名称: LsdXxxYyy,如LsdBrowserContext
9
- */
2
+ import { Browser as Browser$1, BrowserContext as BrowserContext$1, Frame as Frame$1, Page as Page$1, ElementHandle, HTTPResponse, PuppeteerNode } from 'puppeteer';
3
+ import { Browser, BrowserContext, Frame, Page, Locator, Response, APIRequestContext, BrowserType, FrameLocator } from 'playwright';
10
4
 
11
5
  type AllBrowser = Browser | Browser$1;
12
6
  type AllBrowserContext = BrowserContext | BrowserContext$1;
13
7
  type AllFrame = Frame | Frame$1;
14
8
  type AllPage = Page | Page$1;
9
+ type AllElement = Locator | ElementHandle;
15
10
  type AllResponse = Response | HTTPResponse;
16
11
  type AllApiRequestContext = APIRequestContext;
17
12
  type CheerioNode = cheerio.Cheerio;
18
13
  type BrowserControllerType = "puppeteer" | "playwright";
19
14
  type BrowserCreationMethod = "launch" | "connect";
20
15
  type LsdBrowserType = "chromium" | "firefox" | "webkit";
16
+ interface BrowserContextRequirements {
17
+ browserControllerTypes: BrowserControllerType[];
18
+ browserTypes: LsdBrowserType[];
19
+ headlesses: boolean[];
20
+ incognitos: boolean[];
21
+ }
21
22
  interface ProxyInController {
22
23
  proxyUrl: string;
23
24
  username?: string;
@@ -208,7 +209,7 @@ type LsdBrowserContextOptions = {
208
209
  type PageStatus = "free" | "busy" | "closed";
209
210
  /**
210
211
  * newpage: open by browserContext.newPage()
211
- * popup: open by clicking etc, 主要关注此类
212
+ * popup: open by clicking etc, important
212
213
  * manual: open by manual operation
213
214
  * launch: open by puppeteer.launch
214
215
  * connect: opened pages before connecting to browser
@@ -245,17 +246,16 @@ interface PageInfo {
245
246
  */
246
247
  openType: PageOpenType;
247
248
  /**
248
- * page添加时间:针对非connect场景,也是page打开时间
249
249
  * @default current unix time
250
250
  */
251
251
  openTime: number;
252
252
  /**
253
- * 上次status变化时间:如果status为free,表示空闲开始时间;如果status为busy,表示TE开始数据
253
+ * page's status: free or busy
254
254
  * @default current unix time
255
255
  */
256
256
  lastStatusUpdateTime: number;
257
257
  /**
258
- * 正在执行的task的ID,参见enumSpecialTaskId
258
+ * taskId that are using this page
259
259
  * @default 0
260
260
  */
261
261
  taskId: number;
@@ -270,12 +270,12 @@ interface PageInfo {
270
270
  }
271
271
  interface UpdatablePageInfo {
272
272
  /**
273
- * 上次status变化时间:如果status为free,表示空闲开始时间;如果status为busy,表示TE开始数据
273
+ * page's status: free or busy
274
274
  * @default current unix time
275
275
  */
276
276
  lastStatusUpdateTime?: number;
277
277
  /**
278
- * 正在执行的task的ID,参见enumSpecialTaskId
278
+ * taskId that are using this page
279
279
  * @default 0
280
280
  */
281
281
  taskId?: number;
@@ -455,9 +455,11 @@ interface LsdElement {
455
455
  */
456
456
  input(value: string, options?: InputOptions): Promise<boolean>;
457
457
  press(key: KeyInput, options: KeyPressOptions): Promise<boolean>;
458
- select(options: SelectOptions): Promise<boolean>;
459
458
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
460
459
  scrollIntoView(): Promise<boolean>;
460
+ select(options: SelectOptions): Promise<boolean>;
461
+ setAttribute(attributeName: string, newValue: string): Promise<boolean>;
462
+ _origElement(): AllElement;
461
463
  }
462
464
  interface ViewportSize {
463
465
  height: number;
@@ -949,7 +951,7 @@ interface LsdPage extends EventEmitter {
949
951
  title(): Promise<string>;
950
952
  url(): string;
951
953
  /**
952
- * 开始使用该page(当前状态必须为free)
954
+ * start to use this free page
953
955
  */
954
956
  use(): boolean;
955
957
  /**
@@ -985,6 +987,11 @@ interface LsdBrowserContext extends EventEmitter {
985
987
  * @default 0 the default maxPageFreeSeconds of the browserContext will be used
986
988
  */
987
989
  closeFreePages(maxPageFreeSeconds?: number): Promise<boolean>;
990
+ /**
991
+ * doest this browser meet browserContextRequirements (incognitos ignored in browser)?
992
+ * @param browserContextRequirements
993
+ */
994
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
988
995
  /**
989
996
  * get a free page from current pages or by creating a new page
990
997
  */
@@ -1016,6 +1023,11 @@ interface LsdBrowser extends EventEmitter {
1016
1023
  browserControllerType(): BrowserControllerType;
1017
1024
  browserCreationMethod(): BrowserCreationMethod;
1018
1025
  browserType(): LsdBrowserType;
1026
+ /**
1027
+ * doest this browser meet browserContextRequirements (incognitos ignored in browser)?
1028
+ * @param browserContextRequirements
1029
+ */
1030
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1019
1031
  /**
1020
1032
  * @returns
1021
1033
  * 1. launched: actual executable path
@@ -1074,33 +1086,6 @@ interface LsdBrowserController$1 {
1074
1086
  */
1075
1087
  newApiContext(options?: LsdApiContextOptions): Promise<LsdApiContext>;
1076
1088
  }
1077
- /**
1078
- * globObj.cfg.XXX:
1079
- * 1. 最大browser数:
1080
- * 2. 最大browserContext数/browser:
1081
- * 3. 最大page数/browserContext:
1082
- *
1083
- * 影响一个browserContext是否满足执行某TE(taskCfg)要求的因素包括:
1084
- * 1. domainCfg/taskCfg对代理的要求:proxyTypes:
1085
- * 2. domainCfg/taskCfg对浏览器的要求:
1086
- * * browserControllerTypes: playwright | puppeteer
1087
- * * browserTypes: chromium | firefox | webkit
1088
- * * browserModes: normal | incognito
1089
- * * browserHeads: headless | headful
1090
- * * APP支持的浏览器因素:globObj.cfg.supportedBrowserControllerTypes/supportedBrowserTypes(尝试启动新浏览器时判断)
1091
- * 3. 能力账号:capName
1092
- *
1093
- * 连接已有浏览器:
1094
- * * endpoint:
1095
- * * browserControllerTypes: playwright | puppeteer
1096
- * * browserType: chromium | firefox | webkit
1097
- * * browserMode: normal
1098
- * * browserHead: headful
1099
- * * proxyTypes:
1100
- */
1101
- interface BrowserManager {
1102
- getPage(): any;
1103
- }
1104
1089
 
1105
1090
  declare class PlaywrightBrowser extends EventEmitter implements LsdBrowser {
1106
1091
  #private;
@@ -1111,6 +1096,7 @@ declare class PlaywrightBrowser extends EventEmitter implements LsdBrowser {
1111
1096
  browserControllerType(): BrowserControllerType;
1112
1097
  browserCreationMethod(): BrowserCreationMethod;
1113
1098
  browserType(): LsdBrowserType;
1099
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1114
1100
  executablePath(): string;
1115
1101
  id(): string;
1116
1102
  isConnected(): boolean;
@@ -1132,6 +1118,7 @@ declare class PlaywrightBrowserContext extends EventEmitter implements LsdBrowse
1132
1118
  browser(): LsdBrowser;
1133
1119
  close(): Promise<boolean>;
1134
1120
  closeFreePages(maxPageFreeSeconds?: number): Promise<boolean>;
1121
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1135
1122
  getPage(always?: boolean): Promise<LsdPage | null>;
1136
1123
  hasFreePage(pageNum?: number): boolean;
1137
1124
  id(): string;
@@ -1214,9 +1201,11 @@ declare class PlaywrightElement implements LsdElement {
1214
1201
  hover(): Promise<boolean>;
1215
1202
  input(value: string, options?: InputOptions): Promise<boolean>;
1216
1203
  press(key: KeyInput, options?: KeyPressOptions): Promise<boolean>;
1217
- select(options: SelectOptions): Promise<boolean>;
1218
1204
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
1219
1205
  scrollIntoView(): Promise<boolean>;
1206
+ select(options: SelectOptions): Promise<boolean>;
1207
+ setAttribute(attributeName: string, newValue: string): Promise<boolean>;
1208
+ _origElement(): AllElement;
1220
1209
  }
1221
1210
 
1222
1211
  declare class PuppeteerBrowser extends EventEmitter implements LsdBrowser {
@@ -1228,6 +1217,7 @@ declare class PuppeteerBrowser extends EventEmitter implements LsdBrowser {
1228
1217
  browserControllerType(): BrowserControllerType;
1229
1218
  browserCreationMethod(): BrowserCreationMethod;
1230
1219
  browserType(): LsdBrowserType;
1220
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1231
1221
  executablePath(): string;
1232
1222
  id(): string;
1233
1223
  isConnected(): boolean;
@@ -1249,6 +1239,7 @@ declare class PuppeteerBrowserContext extends EventEmitter implements LsdBrowser
1249
1239
  browser(): LsdBrowser;
1250
1240
  close(): Promise<boolean>;
1251
1241
  closeFreePages(maxPageFreeSeconds?: number): Promise<boolean>;
1242
+ doesMeetBrowserContextRequirements(browserContextRequirements: BrowserContextRequirements): boolean;
1252
1243
  getPage(always?: boolean): Promise<LsdPage | null>;
1253
1244
  hasFreePage(pageNum?: number): boolean;
1254
1245
  id(): string;
@@ -1331,9 +1322,11 @@ declare class PuppeteerElement implements LsdElement {
1331
1322
  hover(): Promise<boolean>;
1332
1323
  input(value: string, options?: InputOptions): Promise<boolean>;
1333
1324
  press(key: KeyInput, options?: KeyPressOptions): Promise<boolean>;
1334
- select(options: SelectOptions): Promise<boolean>;
1335
1325
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
1336
1326
  scrollIntoView(): Promise<boolean>;
1327
+ select(options: SelectOptions): Promise<boolean>;
1328
+ setAttribute(attributeName: string, newValue: string): Promise<boolean>;
1329
+ _origElement(): AllElement;
1337
1330
  }
1338
1331
 
1339
1332
  declare class CheerioPage extends EventEmitter implements LsdPage {
@@ -1411,9 +1404,11 @@ declare class CheerioElement implements LsdElement {
1411
1404
  hover(): Promise<boolean>;
1412
1405
  input(): Promise<boolean>;
1413
1406
  press(): Promise<boolean>;
1414
- select(): Promise<boolean>;
1415
1407
  screenshot(): Promise<Buffer>;
1416
1408
  scrollIntoView(): Promise<boolean>;
1409
+ select(): Promise<boolean>;
1410
+ setAttribute(): Promise<boolean>;
1411
+ _origElement(): AllElement;
1417
1412
  }
1418
1413
 
1419
1414
  declare class LsdBrowserController implements LsdBrowserController$1 {
@@ -1427,4 +1422,4 @@ declare class LsdBrowserController implements LsdBrowserController$1 {
1427
1422
  }
1428
1423
  declare const controller: LsdBrowserController;
1429
1424
 
1430
- export { type AllApiRequestContext, type AllBrowser, type AllBrowserContext, type AllFrame, type AllPage, type AllResponse, type BrowserControllerType, type BrowserCreationMethod, type BrowserLaunchMethod, type BrowserManager, type BrowserStateData, CheerioElement, type CheerioNode, CheerioPage, type ClientCertificate, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdApiContext, type LsdApiContextOptions, type LsdApiResponse, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController$1 as LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdFetchOptions, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type MouseClickType, type NavigationWaitUntil, type PDFMargin, type PDFOptions, type PageEvent, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, type PlaywrightBrowserTypes, PlaywrightElement, PlaywrightPage, type ProxyInController, 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 ResponsePageData, type ScreenshotOptions, type SelectOptions, type UpdatablePageInfo, type ViewportSize, type WaitElementOptions, type WaitElementState, type WaitNavigationOptions, controller };
1425
+ export { type AllApiRequestContext, type AllBrowser, type AllBrowserContext, type AllElement, type AllFrame, type AllPage, type AllResponse, type BrowserContextRequirements, type BrowserControllerType, type BrowserCreationMethod, type BrowserLaunchMethod, type BrowserStateData, CheerioElement, type CheerioNode, CheerioPage, type ClientCertificate, type CookieItem, type GotoOptions, type IframeOption, type InputOptions, type KeyInput, type KeyPressOptions, type LocalStorageItem, type LocalStorageOrigin, type LowerCasePaperFormat, type LsdApiContext, type LsdApiContextOptions, type LsdApiResponse, type LsdBrowser, type LsdBrowserContext, type LsdBrowserContextOptions, type LsdBrowserController$1 as LsdBrowserController, type LsdBrowserType, type LsdConnectOptions, type LsdElement, type LsdFetchOptions, type LsdLaunchOptions, type LsdPage, type MouseClickOptions, type MouseClickType, type NavigationWaitUntil, type PDFMargin, type PDFOptions, type PageEvent, type PageExtInPlaywright, type PageExtInPuppeteer, type PageInfo, type PageOpenType, type PageStatus, type PaperFormat, PlaywrightBrowser, PlaywrightBrowserContext, type PlaywrightBrowserTypes, PlaywrightElement, PlaywrightPage, type ProxyInController, 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 ResponsePageData, type ScreenshotOptions, type SelectOptions, type UpdatablePageInfo, type ViewportSize, type WaitElementOptions, type WaitElementState, type WaitNavigationOptions, controller };
package/dist/index.js CHANGED
@@ -30,7 +30,6 @@ var PlaywrightElement = class _PlaywrightElement {
30
30
  return names;
31
31
  }
32
32
  /*
33
- // 如果不存在指定的子iframe,则返回null
34
33
  async #getChildFrame(parentFrame: Frame, iframeOption: IframeOption): Promise<Frame | null> {
35
34
  if (!parentFrame) {
36
35
  throw new Error("Invalid parent frame");
@@ -222,6 +221,13 @@ var PlaywrightElement = class _PlaywrightElement {
222
221
  await this.#locator.press(key, options);
223
222
  return true;
224
223
  }
224
+ async screenshot(options) {
225
+ return await this.#locator.screenshot(options);
226
+ }
227
+ async scrollIntoView() {
228
+ await this.#locator.scrollIntoViewIfNeeded();
229
+ return true;
230
+ }
225
231
  async select(options) {
226
232
  const { type, values = [], labels = [], indexes = [] } = options;
227
233
  switch (type) {
@@ -261,13 +267,15 @@ var PlaywrightElement = class _PlaywrightElement {
261
267
  }
262
268
  return true;
263
269
  }
264
- async screenshot(options) {
265
- return await this.#locator.screenshot(options);
266
- }
267
- async scrollIntoView() {
268
- await this.#locator.scrollIntoViewIfNeeded();
270
+ async setAttribute(attributeName, newValue) {
271
+ await this.#locator.evaluate((node) => {
272
+ node.setAttribute(attributeName, newValue);
273
+ });
269
274
  return true;
270
275
  }
276
+ _origElement() {
277
+ return this.#locator;
278
+ }
271
279
  };
272
280
 
273
281
  // src/playwright/page.ts
@@ -374,7 +382,6 @@ var PlaywrightPage = class extends EventEmitter {
374
382
  return true;
375
383
  }
376
384
  /*
377
- // 如果不存在指定的子iframe,则返回null
378
385
  async #getChildFrame(parentFrame: Frame, iframeOption: IframeOption): Promise<Frame | null> {
379
386
  if (!parentFrame) {
380
387
  throw new Error("Invalid parent frame");
@@ -1308,6 +1315,13 @@ var PlaywrightBrowserContext = class extends EventEmitter2 {
1308
1315
  return false;
1309
1316
  }
1310
1317
  }
1318
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
1319
+ if (!this.#lsdBrowser.doesMeetBrowserContextRequirements(browserContextRequirements)) {
1320
+ return false;
1321
+ }
1322
+ const { incognitos } = browserContextRequirements;
1323
+ return incognitos.length === 0 || incognitos.includes(this.#incognito);
1324
+ }
1311
1325
  async getPage(always = false) {
1312
1326
  if (!this.#browserContext) {
1313
1327
  throw new Error("Invalid browserContext");
@@ -1445,7 +1459,7 @@ var PlaywrightBrowser = class extends EventEmitter3 {
1445
1459
  #maxPageFreeSeconds() {
1446
1460
  return this.#options.maxPageFreeSeconds ? this.#options.maxPageFreeSeconds : 900;
1447
1461
  }
1448
- // 构造函数:缺省只能由LsdBrowserController.launch/connect调用创建实例!!!
1462
+ // constructor: called only by LsdBrowserController.launch/connect
1449
1463
  constructor(browser, browerType, browserCreateMethod, options, browserIdx = 0, pid = 0) {
1450
1464
  if (!browser || typeof browser.contexts !== "function") {
1451
1465
  throw new Error(`Invalid playwright browser parameter`);
@@ -1511,7 +1525,6 @@ var PlaywrightBrowser = class extends EventEmitter3 {
1511
1525
  await lsdBrowserContext.closeFreePages();
1512
1526
  }
1513
1527
  }
1514
- // 常用方法(按常见调用顺序排序)
1515
1528
  async newBrowserContext(options) {
1516
1529
  if (this.#lsdBrowserContexts.length >= this.#maxBrowserContextsPerBrowser()) {
1517
1530
  logwarn3(`##browser ${this.id()} can not create more new browserContext`);
@@ -1546,7 +1559,6 @@ var PlaywrightBrowser = class extends EventEmitter3 {
1546
1559
  await this.#browser.close();
1547
1560
  return true;
1548
1561
  }
1549
- // 其它方法(按字母顺序排序)
1550
1562
  browserContexts() {
1551
1563
  return this.#lsdBrowserContexts;
1552
1564
  }
@@ -1559,6 +1571,10 @@ var PlaywrightBrowser = class extends EventEmitter3 {
1559
1571
  browserType() {
1560
1572
  return this.#browserType;
1561
1573
  }
1574
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
1575
+ const { browserControllerTypes, browserTypes, headlesses } = browserContextRequirements;
1576
+ return (browserControllerTypes.length === 0 || browserControllerTypes.includes(this.#browserControllerType)) && (browserTypes.length === 0 && browserTypes.includes(this.#browserType)) && (headlesses.length === 0 && headlesses.includes(this.#headless));
1577
+ }
1562
1578
  executablePath() {
1563
1579
  return this.#executablePath;
1564
1580
  }
@@ -1623,7 +1639,6 @@ var PuppeteerElement = class _PuppeteerElement {
1623
1639
  const names = await this.#frame.evaluate((ele) => ele.getAttributeNames(), this.#$ele);
1624
1640
  return names;
1625
1641
  }
1626
- // 如果不存在指定的子iframe,则返回null
1627
1642
  async #getChildFrame(parentFrame, iframeOption) {
1628
1643
  if (!parentFrame) {
1629
1644
  throw new Error("Invalid parent frame");
@@ -1801,6 +1816,15 @@ var PuppeteerElement = class _PuppeteerElement {
1801
1816
  await this.#$ele.press(key, options);
1802
1817
  return true;
1803
1818
  }
1819
+ async screenshot(options) {
1820
+ return await this.#$ele.screenshot(options);
1821
+ }
1822
+ async scrollIntoView() {
1823
+ await this.#frame.evaluate((ele) => {
1824
+ ele.scrollIntoView();
1825
+ }, this.#$ele);
1826
+ return true;
1827
+ }
1804
1828
  async select(options) {
1805
1829
  const { type, values = [], labels = [], indexes = [] } = options;
1806
1830
  switch (type) {
@@ -1855,15 +1879,15 @@ var PuppeteerElement = class _PuppeteerElement {
1855
1879
  }
1856
1880
  return true;
1857
1881
  }
1858
- async screenshot(options) {
1859
- return await this.#$ele.screenshot(options);
1860
- }
1861
- async scrollIntoView() {
1862
- await this.#frame.evaluate((ele) => {
1863
- ele.scrollIntoView();
1864
- }, this.#$ele);
1882
+ async setAttribute(attributeName, newValue) {
1883
+ await this.#frame.evaluate((ele, name, value) => {
1884
+ ele.setAttribute(name, value);
1885
+ }, this.#$ele, attributeName, newValue);
1865
1886
  return true;
1866
1887
  }
1888
+ _origElement() {
1889
+ return this.#$ele;
1890
+ }
1867
1891
  };
1868
1892
 
1869
1893
  // src/puppeteer/page.ts
@@ -1947,7 +1971,6 @@ var PuppeteerPage = class extends EventEmitter4 {
1947
1971
  });
1948
1972
  return true;
1949
1973
  }
1950
- // 如果不存在指定的子iframe,则返回null
1951
1974
  async #getChildFrame(parentFrame, iframeOption) {
1952
1975
  if (!parentFrame) {
1953
1976
  throw new Error("Invalid parent frame");
@@ -2829,6 +2852,13 @@ var PuppeteerBrowserContext = class extends EventEmitter5 {
2829
2852
  return false;
2830
2853
  }
2831
2854
  }
2855
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
2856
+ if (!this.#lsdBrowser.doesMeetBrowserContextRequirements(browserContextRequirements)) {
2857
+ return false;
2858
+ }
2859
+ const { incognitos } = browserContextRequirements;
2860
+ return incognitos.length === 0 || incognitos.includes(this.#incognito);
2861
+ }
2832
2862
  async getPage(always = false) {
2833
2863
  if (!this.#browserContext) {
2834
2864
  throw new Error("Invalid browserContext");
@@ -2971,7 +3001,7 @@ var PuppeteerBrowser = class extends EventEmitter6 {
2971
3001
  #userAgent() {
2972
3002
  return this.#options.userAgent ? this.#options.userAgent : "";
2973
3003
  }
2974
- // 构造函数:缺省只能由LsdBrowserController.launch/connect调用创建实例!!!
3004
+ // constructor: called only by LsdBrowserController.launch/connect
2975
3005
  constructor(browser, browerType, browserCreateMethod, options, browserIdx = 0, pid = 0) {
2976
3006
  if (!browser || typeof browser.browserContexts !== "function") {
2977
3007
  throw new Error(`Invalid puppeteer browser parameter`);
@@ -3034,7 +3064,6 @@ var PuppeteerBrowser = class extends EventEmitter6 {
3034
3064
  await lsdBrowserContext.closeFreePages();
3035
3065
  }
3036
3066
  }
3037
- // 常用方法(按常见调用顺序排序)
3038
3067
  async newBrowserContext(options) {
3039
3068
  if (this.#lsdBrowserContexts.length >= this.#maxBrowserContextsPerBrowser()) {
3040
3069
  logwarn5(`##browser ${this.id()} can not create more new browserContext`);
@@ -3065,7 +3094,6 @@ var PuppeteerBrowser = class extends EventEmitter6 {
3065
3094
  await this.#browser.close();
3066
3095
  return true;
3067
3096
  }
3068
- // 其它方法(按字母顺序排序)
3069
3097
  browserContexts() {
3070
3098
  return this.#lsdBrowserContexts;
3071
3099
  }
@@ -3078,6 +3106,10 @@ var PuppeteerBrowser = class extends EventEmitter6 {
3078
3106
  browserType() {
3079
3107
  return this.#browserType;
3080
3108
  }
3109
+ doesMeetBrowserContextRequirements(browserContextRequirements) {
3110
+ const { browserControllerTypes, browserTypes, headlesses } = browserContextRequirements;
3111
+ return (browserControllerTypes.length === 0 || browserControllerTypes.includes(this.#browserControllerType)) && (browserTypes.length === 0 && browserTypes.includes(this.#browserType)) && (headlesses.length === 0 && headlesses.includes(this.#headless));
3112
+ }
3081
3113
  executablePath() {
3082
3114
  return this.#executablePath;
3083
3115
  }
@@ -3219,13 +3251,19 @@ var CheerioElement = class _CheerioElement {
3219
3251
  async press() {
3220
3252
  throw new Error("Not supported in CheerioElement.");
3221
3253
  }
3254
+ async screenshot() {
3255
+ throw new Error("Not supported in CheerioElement.");
3256
+ }
3257
+ async scrollIntoView() {
3258
+ throw new Error("Not supported in CheerioElement.");
3259
+ }
3222
3260
  async select() {
3223
3261
  throw new Error("Not supported in CheerioElement.");
3224
3262
  }
3225
- async screenshot() {
3263
+ async setAttribute() {
3226
3264
  throw new Error("Not supported in CheerioElement.");
3227
3265
  }
3228
- async scrollIntoView() {
3266
+ _origElement() {
3229
3267
  throw new Error("Not supported in CheerioElement.");
3230
3268
  }
3231
3269
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letsscrapedata/controller",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
4
4
  "description": "Unified browser / HTML controller interfaces that support playwright, puppeteer and cheerio",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",