From 7001322cd1cf9f77ee2c370d50a6707e7aaad72d Mon Sep 17 00:00:00 2001 From: jrandolf <101637635+jrandolf@users.noreply.github.com> Date: Mon, 27 Jun 2022 09:24:23 +0200 Subject: [PATCH] feat: export public types only (#8584) --- .eslintignore | 2 +- .gitignore | 1 + .prettierignore | 4 +- api-extractor.json | 7 +- compat/cjs/compat.ts | 3 + compat/esm/compat.ts | 3 + package.json | 3 +- src/api-docs-entry.ts | 152 ------------------------ src/common/BrowserWebSocketTransport.ts | 3 + src/common/DOMWorld.ts | 4 +- src/common/Debug.ts | 9 +- src/common/DeviceDescriptors.ts | 30 ++++- src/common/ElementHandle.ts | 22 +++- src/common/EmulationManager.ts | 3 + src/common/Errors.ts | 29 ++++- src/common/Events.ts | 97 --------------- src/common/ExecutionContext.ts | 10 +- src/common/JSHandle.ts | 17 +-- src/common/NetworkConditions.ts | 33 +++-- src/common/NetworkEventManager.ts | 29 +++-- src/common/Page.ts | 25 ++-- src/common/Puppeteer.ts | 141 ++++++++-------------- src/common/QueryHandler.ts | 50 ++++++-- src/common/TaskQueue.ts | 3 + src/common/assert.ts | 11 +- src/common/fetch.ts | 6 +- src/common/types.ts | 20 +++- src/common/util.ts | 70 ++++++++++- src/constants.ts | 3 + src/environment.ts | 3 + src/generated/version.ts | 3 + src/initializePuppeteer.ts | 3 + src/node/BrowserFetcher.ts | 12 +- src/node/BrowserRunner.ts | 3 + src/node/NodeWebSocketTransport.ts | 3 + src/node/PipeTransport.ts | 3 + src/node/ProductLauncher.ts | 6 + src/node/Puppeteer.ts | 62 +++++----- src/node/install.ts | 12 ++ src/puppeteer-core.ts | 12 +- src/puppeteer.ts | 15 +-- src/revisions.ts | 3 + src/templates/version.ts.tmpl | 3 + src/types.ts | 71 +++++++++++ test/src/oopif.spec.ts | 4 +- utils/export_all.js | 30 +++++ 46 files changed, 537 insertions(+), 501 deletions(-) delete mode 100644 src/api-docs-entry.ts delete mode 100644 src/common/Events.ts create mode 100644 src/types.ts create mode 100644 utils/export_all.js diff --git a/.eslintignore b/.eslintignore index b52c3378..5de5cd4a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,4 +5,4 @@ doclint/ lib/ test-ts-types/ tsconfig.tsbuildinfo -vendor/ \ No newline at end of file +vendor/ diff --git a/.gitignore b/.gitignore index ffcf7306..d6552444 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ docs/api.html lib/ node_modules/ package-lock.json +puppeteer.api.json puppeteer*.tgz test-ts-types/**/dist/ test-ts-types/**/node_modules diff --git a/.prettierignore b/.prettierignore index 94574cbf..f6fdcd13 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,7 +5,6 @@ build/ CHANGELOG.md coverage/ doclint/ -docs-api-json/ lib/ node_modules/ package-lock.json @@ -14,4 +13,5 @@ test-ts-types/ test/assets/ tsconfig.tsbuildinfo vendor/ -yarn.lock \ No newline at end of file +yarn.lock +puppeteer.api.json \ No newline at end of file diff --git a/api-extractor.json b/api-extractor.json index 08a64da5..8a80ee1e 100644 --- a/api-extractor.json +++ b/api-extractor.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "mainEntryPointFilePath": "/lib/cjs/puppeteer/api-docs-entry.d.ts", + "mainEntryPointFilePath": "/lib/esm/puppeteer/types.d.ts", "bundledPackages": [], "apiReport": { @@ -9,12 +9,13 @@ "docModel": { "enabled": true, - "apiJsonFilePath": "/docs-api-json/.api.json" + "apiJsonFilePath": "/docs/.api.json" }, "dtsRollup": { "enabled": true, - "untrimmedFilePath": "lib/types.d.ts" + "untrimmedFilePath": "", + "alphaTrimmedFilePath": "lib/types.d.ts" }, "tsdocMetadata": { diff --git a/compat/cjs/compat.ts b/compat/cjs/compat.ts index 1d3a49c8..782727e0 100644 --- a/compat/cjs/compat.ts +++ b/compat/cjs/compat.ts @@ -1,5 +1,8 @@ import {dirname} from 'path'; +/** + * @internal + */ let puppeteerDirname: string; try { diff --git a/compat/esm/compat.ts b/compat/esm/compat.ts index c257160b..8d747658 100644 --- a/compat/esm/compat.ts +++ b/compat/esm/compat.ts @@ -4,6 +4,9 @@ import {fileURLToPath} from 'url'; const require = createRequire(import.meta.url); +/** + * @internal + */ let puppeteerDirname: string; try { diff --git a/package.json b/package.json index f549b41c..f272313b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "lint:eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)", "lint:eslint:fix": "eslint --ext js --ext ts --fix .", "install": "node install.js", - "generate:types": "npm run clean:docs && api-extractor run --local --verbose", + "generate:types": "node utils/export_all.js && api-extractor run --local --verbose", "generate:esm-package-json": "echo '{\"type\": \"module\"}' > lib/esm/package.json", "generate:docs": "npm run generate:types && node utils/remove-tag.js", "generate:docs:testing": "commonmark docs/api.md > docs/api.html", @@ -52,7 +52,6 @@ "doc": "node utils/doclint/cli.js", "commitlint": "commitlint --from=HEAD~1", "clean:lib": "rimraf lib", - "clean:docs": "rimraf docs-api-json", "build": "npm run build:tsc && npm run generate:types && npm run generate:esm-package-json", "build:test": "tsc -b test", "build:tsc": "npm run clean:lib && tsc --version && (npm run build:tsc:cjs && npm run build:tsc:esm)", diff --git a/src/api-docs-entry.ts b/src/api-docs-entry.ts deleted file mode 100644 index 77a22e0f..00000000 --- a/src/api-docs-entry.ts +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright 2020 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - LaunchOptions, - BrowserLaunchArgumentOptions, -} from './node/LaunchOptions.js'; -import {BrowserConnectOptions} from './common/BrowserConnector.js'; -import {Product} from './common/Product.js'; -import {Browser} from './common/Browser.js'; -import {ConnectOptions} from './common/Puppeteer.js'; -import {DevicesMap} from './common/DeviceDescriptors.js'; -import {PuppeteerErrors} from './common/Errors.js'; -import {PredefinedNetworkConditions} from './common/NetworkConditions.js'; -import {CustomQueryHandler} from './common/QueryHandler.js'; - -/* - * This file re-exports any APIs that we want to have documentation generated - * for. It is used by API Extractor to determine what parts of the system to - * document. - * - * The legacy DocLint system and the unit test coverage system use the list of - * modules defined in coverage-utils.js. src/api-docs-entry.ts is ONLY used by - * API Extractor. - * - * Once we have migrated to API Extractor and removed DocLint we can remove the - * duplication and use this file. - */ -export * from './common/Accessibility.js'; -export * from './common/Browser.js'; -export * from './common/BrowserConnector.js'; -export * from './common/Connection.js'; -export * from './common/ConsoleMessage.js'; -export * from './common/Coverage.js'; -export * from './common/Coverage.js'; -export * from './common/DeviceDescriptors.js'; -export * from './common/Dialog.js'; -export * from './common/DOMWorld.js'; -export * from './common/ElementHandle.js'; -export * from './common/Errors.js'; -export * from './common/EventEmitter.js'; -export * from './common/ExecutionContext.js'; -export * from './common/FileChooser.js'; -export * from './common/FrameManager.js'; -export * from './common/HTTPRequest.js'; -export * from './common/HTTPResponse.js'; -export * from './common/Input.js'; -export * from './common/JSHandle.js'; -export * from './common/LifecycleWatcher.js'; -export * from './common/NetworkConditions.js'; -export * from './common/NetworkManager.js'; -export * from './common/Page.js'; -export * from './common/PDFOptions.js'; -export * from './common/Product.js'; -export * from './common/Puppeteer.js'; -export * from './common/PuppeteerViewport.js'; -export * from './common/QueryHandler.js'; -export * from './common/SecurityDetails.js'; -export * from './common/Target.js'; -export * from './common/TimeoutSettings.js'; -export * from './common/Tracing.js'; -export * from './common/types.js'; -export * from './common/USKeyboardLayout.js'; -export * from './common/WebWorker.js'; -export * from './node/BrowserFetcher.js'; -export * from './node/LaunchOptions.js'; -export * from './node/ProductLauncher.js'; -export * from './node/Puppeteer.js'; -export * from 'devtools-protocol/types/protocol'; - -/* - * We maintain a namespace that emulates the API of the Puppeteer instance you - * get when you `import puppeteer from 'puppeteer'. - * - * We do this as a namespace because export = PuppeteerDefault where - * PuppeteerDefault is a namespace seems to make sure that the types work in - * both ESM and CJS contexts. - * - * This namespace must be kept in sync with the public API offered by the - * PuppeteerNode class. - */ - -/** - * @public - * {@inheritDoc PuppeteerNode.launch} - */ -export declare function launch( - options?: LaunchOptions & - BrowserLaunchArgumentOptions & - BrowserConnectOptions & { - product?: Product; - extraPrefsFirefox?: Record; - } -): Promise; - -/** - * @public - * {@inheritDoc PuppeteerNode.connect} - */ -export declare function connect(options: ConnectOptions): Promise; - -/** - * @public - * {@inheritDoc Puppeteer.devices} - */ -export let devices: DevicesMap; -/** - * @public - */ -export let errors: PuppeteerErrors; -/** - * @public - */ -export let networkConditions: PredefinedNetworkConditions; - -/** - * @public - * {@inheritDoc Puppeteer.registerCustomQueryHandler} - */ -export declare function registerCustomQueryHandler( - name: string, - queryHandler: CustomQueryHandler -): void; - -/** - * @public - * {@inheritDoc Puppeteer.unregisterCustomQueryHandler} - */ -export declare function unregisterCustomQueryHandler(name: string): void; -/** - * @public - * {@inheritDoc Puppeteer.customQueryHandlerNames} - */ -export declare function customQueryHandlerNames(): string[]; -/** - * @public - * {@inheritDoc Puppeteer.clearCustomQueryHandlers} - */ -export declare function clearCustomQueryHandlers(): void; diff --git a/src/common/BrowserWebSocketTransport.ts b/src/common/BrowserWebSocketTransport.ts index abfadec6..5fe32e65 100644 --- a/src/common/BrowserWebSocketTransport.ts +++ b/src/common/BrowserWebSocketTransport.ts @@ -15,6 +15,9 @@ */ import {ConnectionTransport} from './ConnectionTransport.js'; +/** + * @internal + */ export class BrowserWebSocketTransport implements ConnectionTransport { static create(url: string): Promise { return new Promise((resolve, reject) => { diff --git a/src/common/DOMWorld.ts b/src/common/DOMWorld.ts index 713ad16f..64c2b6ed 100644 --- a/src/common/DOMWorld.ts +++ b/src/common/DOMWorld.ts @@ -24,7 +24,7 @@ import {Frame, FrameManager} from './FrameManager.js'; import {MouseButton} from './Input.js'; import {JSHandle} from './JSHandle.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; -import {_getQueryHandlerAndSelector} from './QueryHandler.js'; +import {getQueryHandlerAndSelector} from './QueryHandler.js'; import {TimeoutSettings} from './TimeoutSettings.js'; import {EvaluateFunc, HandleFor} from './types.js'; import { @@ -653,7 +653,7 @@ export class DOMWorld { options: WaitForSelectorOptions ): Promise { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert(queryHandler.waitFor, 'Query handler does not support waiting'); return queryHandler.waitFor(this, updatedSelector, options); } diff --git a/src/common/Debug.ts b/src/common/Debug.ts index d281e1cc..3aaa9806 100644 --- a/src/common/Debug.ts +++ b/src/common/Debug.ts @@ -25,14 +25,10 @@ declare global { * A debug function that can be used in any environment. * * @remarks - * * If used in Node, it falls back to the * {@link https://www.npmjs.com/package/debug | debug module}. In the browser it * uses `console.log`. * - * @param prefix - this will be prefixed to each log. - * @returns a function that can be called to log to that debug channel. - * * In Node, use the `DEBUG` environment variable to control logging: * * ``` @@ -56,6 +52,11 @@ declare global { * log('new page created') * // logs "Page: new page created" * ``` + * + * @param prefix - this will be prefixed to each log. + * @returns a function that can be called to log to that debug channel. + * + * @internal */ export const debug = (prefix: string): ((...args: unknown[]) => void) => { if (isNode) { diff --git a/src/common/DeviceDescriptors.ts b/src/common/DeviceDescriptors.ts index fc2cfc20..934633c4 100644 --- a/src/common/DeviceDescriptors.ts +++ b/src/common/DeviceDescriptors.ts @@ -30,7 +30,7 @@ export interface Device { }; } -const devices: Device[] = [ +const deviceArray: Device[] = [ { name: 'Blackberry PlayBook', userAgent: @@ -1536,10 +1536,30 @@ export type DevicesMap = { }; /** - * @internal + * A list of devices to be used with `page.emulate(options)`. Actual list of devices can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts | src/common/DeviceDescriptors.ts}. + * + * @example + * + * ```js + * const puppeteer = require('puppeteer'); + * const iPhone = puppeteer.devices['iPhone 6']; + * + * (async () => { + * const browser = await puppeteer.launch(); + * const page = await browser.newPage(); + * await page.emulate(iPhone); + * await page.goto('https://www.google.com'); + * // other actions... + * await browser.close(); + * })(); + * ``` + * + * @public */ -export const _devicesMap: DevicesMap = {}; +const devices: DevicesMap = {}; -for (const device of devices) { - _devicesMap[device.name] = device; +for (const device of deviceArray) { + devices[device.name] = device; } + +export {devices}; diff --git a/src/common/ElementHandle.ts b/src/common/ElementHandle.ts index 9429b1d6..904b4922 100644 --- a/src/common/ElementHandle.ts +++ b/src/common/ElementHandle.ts @@ -8,14 +8,13 @@ import { BoundingBox, BoxModel, ClickOptions, - computeQuadArea, JSHandle, Offset, Point, PressOptions, } from './JSHandle.js'; import {Page, ScreenshotOptions} from './Page.js'; -import {_getQueryHandlerAndSelector} from './QueryHandler.js'; +import {getQueryHandlerAndSelector} from './QueryHandler.js'; import {EvaluateFunc} from './types.js'; import {KeyInput} from './USKeyboardLayout.js'; import {debugError, isString} from './util.js'; @@ -841,7 +840,7 @@ export class ElementHandle< async $(selector: string): Promise; async $(selector: string): Promise { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert( queryHandler.queryOne, 'Cannot handle queries for a single element with the given selector' @@ -866,7 +865,7 @@ export class ElementHandle< async $$(selector: string): Promise; async $$(selector: string): Promise { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert( queryHandler.queryAll, 'Cannot handle queries for a multiple element with the given selector' @@ -986,7 +985,7 @@ export class ElementHandle< ...args: Params ): Promise>> { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert(queryHandler.queryAllArray); const arrayHandle = await queryHandler.queryAllArray(this, updatedSelector); const result = await arrayHandle.evaluate(pageFunction, ...args); @@ -1046,3 +1045,16 @@ export class ElementHandle< }, threshold); } } + +function computeQuadArea(quad: Point[]): number { + /* Compute sum of all directed areas of adjacent triangles + https://en.wikipedia.org/wiki/Polygon#Simple_polygons + */ + let area = 0; + for (let i = 0; i < quad.length; ++i) { + const p1 = quad[i]!; + const p2 = quad[(i + 1) % quad.length]!; + area += (p1.x * p2.y - p2.x * p1.y) / 2; + } + return Math.abs(area); +} diff --git a/src/common/EmulationManager.ts b/src/common/EmulationManager.ts index 0c2af6b6..ba108d31 100644 --- a/src/common/EmulationManager.ts +++ b/src/common/EmulationManager.ts @@ -17,6 +17,9 @@ import {CDPSession} from './Connection.js'; import {Viewport} from './PuppeteerViewport.js'; import {Protocol} from 'devtools-protocol'; +/** + * @internal + */ export class EmulationManager { #client: CDPSession; #emulatingMobile = false; diff --git a/src/common/Errors.ts b/src/common/Errors.ts index fbd23c3a..e1537800 100644 --- a/src/common/Errors.ts +++ b/src/common/Errors.ts @@ -26,12 +26,12 @@ export class CustomError extends Error { } /** - * TimeoutError is emitted whenever certain operations are terminated due to timeout. + * TimeoutError is emitted whenever certain operations are terminated due to + * timeout. * * @remarks - * - * Example operations are {@link Page.waitForSelector | page.waitForSelector} - * or {@link PuppeteerNode.launch | puppeteer.launch}. + * Example operations are {@link Page.waitForSelector | page.waitForSelector} or + * {@link PuppeteerNode.launch | puppeteer.launch}. * * @public */ @@ -56,9 +56,28 @@ export interface PuppeteerErrors { } /** + * Puppeteer methods might throw errors if they are unable to fulfill a request. + * For example, `page.waitForSelector(selector[, options])` might fail if the + * selector doesn't match any nodes during the given timeframe. + * + * For certain types of errors Puppeteer uses specific error classes. These + * classes are available via `puppeteer.errors`. + * + * @example + * An example of handling a timeout error: + * ```js + * try { + * await page.waitForSelector('.foo'); + * } catch (e) { + * if (e instanceof puppeteer.errors.TimeoutError) { + * // Do something if this is a timeout. + * } + * } + * ``` + * * @public */ -export const puppeteerErrors: PuppeteerErrors = Object.freeze({ +export const errors: PuppeteerErrors = Object.freeze({ TimeoutError, ProtocolError, }); diff --git a/src/common/Events.ts b/src/common/Events.ts deleted file mode 100644 index 76bca067..00000000 --- a/src/common/Events.ts +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2019 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * IMPORTANT: we are mid-way through migrating away from this Events.ts file - * in favour of defining events next to the class that emits them. - * - * However we need to maintain this file for now because the legacy DocLint - * system relies on them. Be aware in the mean time if you make a change here - * you probably need to replicate it in the relevant class. For example if you - * add a new Page event, you should update the PageEmittedEvents enum in - * src/common/Page.ts. - * - * Chat to \@jackfranklin if you're unsure. - */ - -export const Events = { - Page: { - Close: 'close', - Console: 'console', - Dialog: 'dialog', - DOMContentLoaded: 'domcontentloaded', - Error: 'error', - // Can't use just 'error' due to node.js special treatment of error events. - // @see https://nodejs.org/api/events.html#events_error_events - PageError: 'pageerror', - Request: 'request', - Response: 'response', - RequestFailed: 'requestfailed', - RequestFinished: 'requestfinished', - FrameAttached: 'frameattached', - FrameDetached: 'framedetached', - FrameNavigated: 'framenavigated', - Load: 'load', - Metrics: 'metrics', - Popup: 'popup', - WorkerCreated: 'workercreated', - WorkerDestroyed: 'workerdestroyed', - }, - - Browser: { - TargetCreated: 'targetcreated', - TargetDestroyed: 'targetdestroyed', - TargetChanged: 'targetchanged', - Disconnected: 'disconnected', - }, - - BrowserContext: { - TargetCreated: 'targetcreated', - TargetDestroyed: 'targetdestroyed', - TargetChanged: 'targetchanged', - }, - - NetworkManager: { - Request: Symbol('Events.NetworkManager.Request'), - Response: Symbol('Events.NetworkManager.Response'), - RequestFailed: Symbol('Events.NetworkManager.RequestFailed'), - RequestFinished: Symbol('Events.NetworkManager.RequestFinished'), - }, - - FrameManager: { - FrameAttached: Symbol('Events.FrameManager.FrameAttached'), - FrameNavigated: Symbol('Events.FrameManager.FrameNavigated'), - FrameDetached: Symbol('Events.FrameManager.FrameDetached'), - LifecycleEvent: Symbol('Events.FrameManager.LifecycleEvent'), - FrameNavigatedWithinDocument: Symbol( - 'Events.FrameManager.FrameNavigatedWithinDocument' - ), - ExecutionContextCreated: Symbol( - 'Events.FrameManager.ExecutionContextCreated' - ), - ExecutionContextDestroyed: Symbol( - 'Events.FrameManager.ExecutionContextDestroyed' - ), - }, - - Connection: { - Disconnected: Symbol('Events.Connection.Disconnected'), - }, - - CDPSession: { - Disconnected: Symbol('Events.CDPSession.Disconnected'), - }, -} as const; diff --git a/src/common/ExecutionContext.ts b/src/common/ExecutionContext.ts index 3615b39c..52018be1 100644 --- a/src/common/ExecutionContext.ts +++ b/src/common/ExecutionContext.ts @@ -26,7 +26,7 @@ import { getExceptionMessage, isString, valueFromRemoteObject, - _createJSHandle, + createJSHandle, } from './util.js'; /** @@ -253,7 +253,7 @@ export class ExecutionContext { return returnByValue ? valueFromRemoteObject(remoteObject) - : _createJSHandle(this, remoteObject); + : createJSHandle(this, remoteObject); } if (typeof pageFunction !== 'function') { @@ -309,7 +309,7 @@ export class ExecutionContext { } return returnByValue ? valueFromRemoteObject(remoteObject) - : _createJSHandle(this, remoteObject); + : createJSHandle(this, remoteObject); function convertArgument( this: ExecutionContext, @@ -407,7 +407,7 @@ export class ExecutionContext { const response = await this._client.send('Runtime.queryObjects', { prototypeObjectId: prototypeHandle._remoteObject.objectId, }); - return _createJSHandle(this, response.objects) as HandleFor; + return createJSHandle(this, response.objects) as HandleFor; } /** @@ -420,7 +420,7 @@ export class ExecutionContext { backendNodeId: backendNodeId, executionContextId: this._contextId, }); - return _createJSHandle(this, object) as ElementHandle; + return createJSHandle(this, object) as ElementHandle; } /** diff --git a/src/common/JSHandle.ts b/src/common/JSHandle.ts index 4f540d86..f6eb085e 100644 --- a/src/common/JSHandle.ts +++ b/src/common/JSHandle.ts @@ -20,7 +20,7 @@ import {CDPSession} from './Connection.js'; import {EvaluateFunc, HandleFor, HandleOr} from './types.js'; import {ExecutionContext} from './ExecutionContext.js'; import {MouseButton} from './Input.js'; -import {releaseObject, valueFromRemoteObject, _createJSHandle} from './util.js'; +import {releaseObject, valueFromRemoteObject, createJSHandle} from './util.js'; import type {ElementHandle} from './ElementHandle.js'; /** @@ -222,7 +222,7 @@ export class JSHandle { if (!property.enumerable || !property.value) { continue; } - result.set(property.name, _createJSHandle(this.#context, property.value)); + result.set(property.name, createJSHandle(this.#context, property.value)); } return result; } @@ -345,16 +345,3 @@ export interface Point { x: number; y: number; } - -export function computeQuadArea(quad: Point[]): number { - /* Compute sum of all directed areas of adjacent triangles - https://en.wikipedia.org/wiki/Polygon#Simple_polygons - */ - let area = 0; - for (let i = 0; i < quad.length; ++i) { - const p1 = quad[i]!; - const p2 = quad[(i + 1) % quad.length]!; - area += (p1.x * p2.y - p2.x * p1.y) / 2; - } - return Math.abs(area); -} diff --git a/src/common/NetworkConditions.ts b/src/common/NetworkConditions.ts index b3bbc5d4..ca79da1e 100644 --- a/src/common/NetworkConditions.ts +++ b/src/common/NetworkConditions.ts @@ -17,14 +17,33 @@ import {NetworkConditions} from './NetworkManager.js'; /** + * A list of network conditions to be used with + * `page.emulateNetworkConditions(networkConditions)`. Actual list of predefined + * conditions can be found in + * {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts | src/common/NetworkConditions.ts}. + * + * @example + * + * ```js + * const puppeteer = require('puppeteer'); + * const slow3G = puppeteer.networkConditions['Slow 3G']; + * + * (async () => { + * const browser = await puppeteer.launch(); + * const page = await browser.newPage(); + * await page.emulateNetworkConditions(slow3G); + * await page.goto('https://www.google.com'); + * // other actions... + * await browser.close(); + * })(); + * ``` + * * @public */ -export type PredefinedNetworkConditions = {[name: string]: NetworkConditions}; - -/** - * @public - */ -export const networkConditions: PredefinedNetworkConditions = { +export const networkConditions: Readonly<{ + 'Slow 3G': NetworkConditions; + 'Fast 3G': NetworkConditions; +}> = Object.freeze({ 'Slow 3G': { download: ((500 * 1000) / 8) * 0.8, upload: ((500 * 1000) / 8) * 0.8, @@ -35,4 +54,4 @@ export const networkConditions: PredefinedNetworkConditions = { upload: ((750 * 1000) / 8) * 0.9, latency: 150 * 3.75, }, -}; +}); diff --git a/src/common/NetworkEventManager.ts b/src/common/NetworkEventManager.ts index 33ae4cce..9ea138cc 100644 --- a/src/common/NetworkEventManager.ts +++ b/src/common/NetworkEventManager.ts @@ -1,25 +1,38 @@ import {Protocol} from 'devtools-protocol'; import {HTTPRequest} from './HTTPRequest.js'; +/** + * @internal + */ export type QueuedEventGroup = { responseReceivedEvent: Protocol.Network.ResponseReceivedEvent; loadingFinishedEvent?: Protocol.Network.LoadingFinishedEvent; loadingFailedEvent?: Protocol.Network.LoadingFailedEvent; }; +/** + * @internal + */ export type FetchRequestId = string; -export type NetworkRequestId = string; - -type RedirectInfo = { - event: Protocol.Network.RequestWillBeSentEvent; - fetchRequestId?: FetchRequestId; -}; -export type RedirectInfoList = RedirectInfo[]; /** * @internal - * + */ +export type RedirectInfo = { + event: Protocol.Network.RequestWillBeSentEvent; + fetchRequestId?: FetchRequestId; +}; +type RedirectInfoList = RedirectInfo[]; + +/** + * @internal + */ +export type NetworkRequestId = string; + +/** * Helper class to track network events by request ID + * + * @internal */ export class NetworkEventManager { /* diff --git a/src/common/Page.ts b/src/common/Page.ts index 4a3e471f..2e5754e5 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -17,7 +17,7 @@ import {Protocol} from 'devtools-protocol'; import type {Readable} from 'stream'; import {Accessibility} from './Accessibility.js'; -import {assert, assertNever} from './assert.js'; +import {assert} from './assert.js'; import {Browser, BrowserContext} from './Browser.js'; import {CDPSession, CDPSessionEmittedEvents, Connection} from './Connection.js'; import {ConsoleMessage, ConsoleMessageType} from './ConsoleMessage.js'; @@ -51,6 +51,7 @@ import {TimeoutSettings} from './TimeoutSettings.js'; import {Tracing} from './Tracing.js'; import {EvaluateFunc, HandleFor} from './types.js'; import { + createJSHandle, debugError, evaluationString, getExceptionMessage, @@ -67,7 +68,6 @@ import { valueFromRemoteObject, waitForEvent, waitWithTimeout, - _createJSHandle, } from './util.js'; import {WebWorker} from './WebWorker.js'; @@ -1640,7 +1640,7 @@ export class Page extends EventEmitter { this.#client ); const values = event.args.map(arg => { - return _createJSHandle(context, arg); + return createJSHandle(context, arg); }); this.#addConsoleMessage(event.type, values, event.stackTrace); } @@ -2273,12 +2273,15 @@ export class Page extends EventEmitter { } /** - * Emulates given device metrics and user agent. This method is a shortcut for - * calling two methods: {@link Page.setUserAgent} and {@link Page.setViewport} - * To aid emulation, Puppeteer provides a list of device descriptors that can - * be obtained via the {@link Puppeteer.devices} `page.emulate` will resize - * the page. A lot of websites don't expect phones to change size, so you - * should emulate before navigating to the page. + * Emulates given device metrics and user agent. + * + * @remarks + * This method is a shortcut for calling two methods: + * {@link Page.setUserAgent} and {@link Page.setViewport} To aid emulation, + * Puppeteer provides a list of device descriptors that can be obtained via + * {@link devices}. `page.emulate` will resize the page. A lot of websites + * don't expect phones to change size, so you should emulate before navigating + * to the page. * @example * ```js * const puppeteer = require('puppeteer'); @@ -2783,10 +2786,6 @@ export class Page extends EventEmitter { // because it may be a 0-length file with no extension created beforehand // (i.e. as a temp file). if (options.type) { - const type = options.type; - if (type !== 'png' && type !== 'jpeg' && type !== 'webp') { - assertNever(type, 'Unknown options.type value: ' + type); - } screenshotType = options.type as Protocol.Page.CaptureScreenshotRequestFormat; } else if (options.path) { diff --git a/src/common/Puppeteer.ts b/src/common/Puppeteer.ts index 86b70738..085d5b8f 100644 --- a/src/common/Puppeteer.ts +++ b/src/common/Puppeteer.ts @@ -13,23 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {puppeteerErrors, PuppeteerErrors} from './Errors.js'; -import {ConnectionTransport} from './ConnectionTransport.js'; -import {_devicesMap, DevicesMap} from './DeviceDescriptors.js'; import {Browser} from './Browser.js'; -import { - _registerCustomQueryHandler, - _unregisterCustomQueryHandler, - _customQueryHandlerNames, - _clearCustomQueryHandlers, - CustomQueryHandler, -} from './QueryHandler.js'; +import {BrowserConnectOptions, _connectToBrowser} from './BrowserConnector.js'; +import {ConnectionTransport} from './ConnectionTransport.js'; +import {devices} from './DeviceDescriptors.js'; +import {errors} from './Errors.js'; +import {networkConditions} from './NetworkConditions.js'; import {Product} from './Product.js'; -import {_connectToBrowser, BrowserConnectOptions} from './BrowserConnector.js'; import { - PredefinedNetworkConditions, - networkConditions, -} from './NetworkConditions.js'; + clearCustomQueryHandlers, + CustomQueryHandler, + customQueryHandlerNames, + registerCustomQueryHandler, + unregisterCustomQueryHandler, +} from './QueryHandler.js'; /** * Settings that are common to the Puppeteer class, regardless of environment. @@ -69,12 +66,6 @@ export class Puppeteer { this._isPuppeteerCore = settings.isPuppeteerCore; this.connect = this.connect.bind(this); - this.registerCustomQueryHandler = - this.registerCustomQueryHandler.bind(this); - this.unregisterCustomQueryHandler = - this.unregisterCustomQueryHandler.bind(this); - this.customQueryHandlerNames = this.customQueryHandlerNames.bind(this); - this.clearCustomQueryHandlers = this.clearCustomQueryHandlers.bind(this); } /** @@ -90,120 +81,82 @@ export class Puppeteer { } /** - * @remarks - * A list of devices to be used with `page.emulate(options)`. Actual list of devices can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts | src/common/DeviceDescriptors.ts}. - * + * @deprecated Import directly puppeteer. * @example - * - * ```js - * const puppeteer = require('puppeteer'); - * const iPhone = puppeteer.devices['iPhone 6']; - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * await page.emulate(iPhone); - * await page.goto('https://www.google.com'); - * // other actions... - * await browser.close(); - * })(); + * ```ts + * import { devices } from 'puppeteer'; * ``` - * */ - get devices(): DevicesMap { - return _devicesMap; + get devices(): typeof devices { + return devices; } /** - * @remarks - * - * Puppeteer methods might throw errors if they are unable to fulfill a request. - * For example, `page.waitForSelector(selector[, options])` might fail if - * the selector doesn't match any nodes during the given timeframe. - * - * For certain types of errors Puppeteer uses specific error classes. - * These classes are available via `puppeteer.errors`. - * + * @deprecated Import directly puppeteer. * @example - * An example of handling a timeout error: - * ```js - * try { - * await page.waitForSelector('.foo'); - * } catch (e) { - * if (e instanceof puppeteer.errors.TimeoutError) { - * // Do something if this is a timeout. - * } - * } + * ```ts + * import { errors } from 'puppeteer'; * ``` */ - get errors(): PuppeteerErrors { - return puppeteerErrors; + get errors(): typeof errors { + return errors; } /** - * @remarks - * Returns a list of network conditions to be used with `page.emulateNetworkConditions(networkConditions)`. Actual list of predefined conditions can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts | src/common/NetworkConditions.ts}. - * + * @deprecated Import directly puppeteer. * @example - * - * ```js - * const puppeteer = require('puppeteer'); - * const slow3G = puppeteer.networkConditions['Slow 3G']; - * - * (async () => { - * const browser = await puppeteer.launch(); - * const page = await browser.newPage(); - * await page.emulateNetworkConditions(slow3G); - * await page.goto('https://www.google.com'); - * // other actions... - * await browser.close(); - * })(); + * ```ts + * import { networkConditions } from 'puppeteer'; * ``` - * */ - get networkConditions(): PredefinedNetworkConditions { + get networkConditions(): typeof networkConditions { return networkConditions; } /** - * Registers a {@link CustomQueryHandler | custom query handler}. After - * registration, the handler can be used everywhere where a selector is - * expected by prepending the selection string with `/`. The name is - * only allowed to consist of lower- and upper case latin letters. + * @deprecated Import directly puppeteer. * @example + * ```ts + * import { registerCustomQueryHandler } from 'puppeteer'; * ``` - * puppeteer.registerCustomQueryHandler('text', { … }); - * const aHandle = await page.$('text/…'); - * ``` - * @param name - The name that the custom query handler will be registered under. - * @param queryHandler - The {@link CustomQueryHandler | custom query handler} to - * register. */ registerCustomQueryHandler( name: string, queryHandler: CustomQueryHandler ): void { - _registerCustomQueryHandler(name, queryHandler); + return registerCustomQueryHandler(name, queryHandler); } /** - * @param name - The name of the query handler to unregistered. + * @deprecated Import directly puppeteer. + * @example + * ```ts + * import { unregisterCustomQueryHandler } from 'puppeteer'; + * ``` */ unregisterCustomQueryHandler(name: string): void { - _unregisterCustomQueryHandler(name); + return unregisterCustomQueryHandler(name); } /** - * @returns a list with the names of all registered custom query handlers. + * @deprecated Import directly puppeteer. + * @example + * ```ts + * import { customQueryHandlerNames } from 'puppeteer'; + * ``` */ customQueryHandlerNames(): string[] { - return _customQueryHandlerNames(); + return customQueryHandlerNames(); } /** - * Clears all registered handlers. + * @deprecated Import directly puppeteer. + * @example + * ```ts + * import { clearCustomQueryHandlers } from 'puppeteer'; + * ``` */ clearCustomQueryHandlers(): void { - _clearCustomQueryHandlers(); + return clearCustomQueryHandlers(); } } diff --git a/src/common/QueryHandler.ts b/src/common/QueryHandler.ts index b66385f4..80ada7a0 100644 --- a/src/common/QueryHandler.ts +++ b/src/common/QueryHandler.ts @@ -44,7 +44,7 @@ export interface InternalQueryHandler { /** * Contains two functions `queryOne` and `queryAll` that can - * be {@link Puppeteer.registerCustomQueryHandler | registered} + * be {@link registerCustomQueryHandler | registered} * as alternative querying strategies. The functions `queryOne` and `queryAll` * are executed in the page context. `queryOne` should take an `Element` and a * selector string as argument and return a single `Element` or `null` if no @@ -114,7 +114,7 @@ function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler { return internalHandler; } -const _defaultHandler = makeQueryHandler({ +const defaultHandler = makeQueryHandler({ queryOne: (element: Element | Document, selector: string) => { return element.querySelector(selector); }, @@ -180,9 +180,27 @@ const builtInHandlers = new Map([ const queryHandlers = new Map(builtInHandlers); /** - * @internal + * Registers a {@link CustomQueryHandler | custom query handler}. + * + * @remarks + * After registration, the handler can be used everywhere where a selector is + * expected by prepending the selection string with `/`. The name is only + * allowed to consist of lower- and upper case latin letters. + * + * @example + * ``` + * puppeteer.registerCustomQueryHandler('text', { … }); + * const aHandle = await page.$('text/…'); + * ``` + * + * @param name - The name that the custom query handler will be registered + * under. + * @param queryHandler - The {@link CustomQueryHandler | custom query handler} + * to register. + * + * @public */ -export function _registerCustomQueryHandler( +export function registerCustomQueryHandler( name: string, handler: CustomQueryHandler ): void { @@ -201,40 +219,46 @@ export function _registerCustomQueryHandler( } /** - * @internal + * @param name - The name of the query handler to unregistered. + * + * @public */ -export function _unregisterCustomQueryHandler(name: string): void { +export function unregisterCustomQueryHandler(name: string): void { if (queryHandlers.has(name) && !builtInHandlers.has(name)) { queryHandlers.delete(name); } } /** - * @internal + * @returns a list with the names of all registered custom query handlers. + * + * @public */ -export function _customQueryHandlerNames(): string[] { +export function customQueryHandlerNames(): string[] { return [...queryHandlers.keys()].filter(name => { return !builtInHandlers.has(name); }); } /** - * @internal + * Clears all registered handlers. + * + * @public */ -export function _clearCustomQueryHandlers(): void { - _customQueryHandlerNames().forEach(_unregisterCustomQueryHandler); +export function clearCustomQueryHandlers(): void { + customQueryHandlerNames().forEach(unregisterCustomQueryHandler); } /** * @internal */ -export function _getQueryHandlerAndSelector(selector: string): { +export function getQueryHandlerAndSelector(selector: string): { updatedSelector: string; queryHandler: InternalQueryHandler; } { const hasCustomQueryHandler = /^[a-zA-Z]+\//.test(selector); if (!hasCustomQueryHandler) { - return {updatedSelector: selector, queryHandler: _defaultHandler}; + return {updatedSelector: selector, queryHandler: defaultHandler}; } const index = selector.indexOf('/'); diff --git a/src/common/TaskQueue.ts b/src/common/TaskQueue.ts index 1403f2ee..97cfe7c7 100644 --- a/src/common/TaskQueue.ts +++ b/src/common/TaskQueue.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @internal + */ export class TaskQueue { #chain: Promise; diff --git a/src/common/assert.ts b/src/common/assert.ts index 232c84d5..bd8b10e7 100644 --- a/src/common/assert.ts +++ b/src/common/assert.ts @@ -18,6 +18,8 @@ * Asserts that the given value is truthy. * @param value - some conditional statement * @param message - the error message to throw if the value is not truthy. + * + * @internal */ export const assert: (value: unknown, message?: string) => asserts value = ( value, @@ -27,12 +29,3 @@ export const assert: (value: unknown, message?: string) => asserts value = ( throw new Error(message); } }; - -export const assertNever: ( - value: unknown, - message?: string -) => asserts value is never = (value, message) => { - if (value) { - throw new Error(message); - } -}; diff --git a/src/common/fetch.ts b/src/common/fetch.ts index 218c1789..5f13a352 100644 --- a/src/common/fetch.ts +++ b/src/common/fetch.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -/* Use the global version if we're in the browser, else load the node-fetch module. */ +/** + * Gets the global version if we're in the browser, else loads the node-fetch module. + * + * @internal + */ export const getFetch = async (): Promise => { return (globalThis as any).fetch || (await import('cross-fetch')).fetch; }; diff --git a/src/common/types.ts b/src/common/types.ts index 4bbe8ab2..a5142314 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -17,16 +17,34 @@ import {JSHandle} from './JSHandle.js'; import {ElementHandle} from './ElementHandle.js'; +/** + * @public + */ export type Awaitable = T | PromiseLike; +/** + * @public + */ export type HandleFor = T extends Element ? ElementHandle : JSHandle; +/** + * @public + */ export type HandleOr = HandleFor | JSHandle | T; -type FlattenHandle = T extends HandleOr ? U : never; +/** + * @public + */ +export type FlattenHandle = T extends HandleOr ? U : never; +/** + * @public + */ export type InnerParams = { [K in keyof T]: FlattenHandle; }; +/** + * @public + */ export type EvaluateFunc = ( ...params: InnerParams ) => Awaitable; diff --git a/src/common/util.ts b/src/common/util.ts index 0ca5715f..dc237b0e 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -26,8 +26,14 @@ import {CommonEventEmitter} from './EventEmitter.js'; import {ExecutionContext} from './ExecutionContext.js'; import {JSHandle} from './JSHandle.js'; +/** + * @internal + */ export const debugError = debug('puppeteer:error'); +/** + * @internal + */ export function getExceptionMessage( exceptionDetails: Protocol.Runtime.ExceptionDetails ): string { @@ -52,6 +58,9 @@ export function getExceptionMessage( return message; } +/** + * @internal + */ export function valueFromRemoteObject( remoteObject: Protocol.Runtime.RemoteObject ): any { @@ -79,6 +88,9 @@ export function valueFromRemoteObject( return remoteObject.value; } +/** + * @internal + */ export async function releaseObject( client: CDPSession, remoteObject: Protocol.Runtime.RemoteObject @@ -95,12 +107,18 @@ export async function releaseObject( }); } +/** + * @internal + */ export interface PuppeteerEventListener { emitter: CommonEventEmitter; eventName: string | symbol; handler: (...args: any[]) => void; } +/** + * @internal + */ export function addEventListener( emitter: CommonEventEmitter, eventName: string | symbol, @@ -110,6 +128,9 @@ export function addEventListener( return {emitter, eventName, handler}; } +/** + * @internal + */ export function removeEventListeners( listeners: Array<{ emitter: CommonEventEmitter; @@ -123,14 +144,23 @@ export function removeEventListeners( listeners.length = 0; } +/** + * @internal + */ export const isString = (obj: unknown): obj is string => { return typeof obj === 'string' || obj instanceof String; }; +/** + * @internal + */ export const isNumber = (obj: unknown): obj is number => { return typeof obj === 'number' || obj instanceof Number; }; +/** + * @internal + */ export async function waitForEvent( emitter: CommonEventEmitter, eventName: string | symbol, @@ -182,7 +212,7 @@ export async function waitForEvent( /** * @internal */ -export function _createJSHandle( +export function createJSHandle( context: ExecutionContext, remoteObject: Protocol.Runtime.RemoteObject ): JSHandle | ElementHandle { @@ -201,6 +231,9 @@ export function _createJSHandle( return new JSHandle(context, context._client, remoteObject); } +/** + * @internal + */ export function evaluationString( fun: Function | string, ...args: unknown[] @@ -220,6 +253,9 @@ export function evaluationString( return `(${fun})(${args.map(serializeArgument).join(',')})`; } +/** + * @internal + */ export function pageBindingInitString(type: string, name: string): string { function addPageBinding(type: string, bindingName: string): void { /* Cast window to any here as we're about to add properties to it @@ -247,6 +283,9 @@ export function pageBindingInitString(type: string, name: string): string { return evaluationString(addPageBinding, type, name); } +/** + * @internal + */ export function pageBindingDeliverResultString( name: string, seq: number, @@ -259,6 +298,9 @@ export function pageBindingDeliverResultString( return evaluationString(deliverResult, name, seq, result); } +/** + * @internal + */ export function pageBindingDeliverErrorString( name: string, seq: number, @@ -279,6 +321,9 @@ export function pageBindingDeliverErrorString( return evaluationString(deliverError, name, seq, message, stack); } +/** + * @internal + */ export function pageBindingDeliverErrorValueString( name: string, seq: number, @@ -291,6 +336,9 @@ export function pageBindingDeliverErrorValueString( return evaluationString(deliverErrorValue, name, seq, value); } +/** + * @internal + */ export function makePredicateString( predicate: Function, predicateQueryHandler?: Function @@ -334,6 +382,9 @@ export function makePredicateString( })() `; } +/** + * @internal + */ export async function waitWithTimeout( promise: Promise, taskName: string, @@ -361,6 +412,9 @@ export async function waitWithTimeout( } } +/** + * @internal + */ export async function getReadableAsBuffer( readable: Readable, path?: string @@ -396,6 +450,9 @@ export async function getReadableAsBuffer( } } +/** + * @internal + */ export async function getReadableFromProtocolStream( client: CDPSession, handle: string @@ -426,17 +483,26 @@ export async function getReadableFromProtocolStream( }); } -interface ErrorLike extends Error { +/** + * @internal + */ +export interface ErrorLike extends Error { name: string; message: string; } +/** + * @internal + */ export function isErrorLike(obj: unknown): obj is ErrorLike { return ( typeof obj === 'object' && obj !== null && 'name' in obj && 'message' in obj ); } +/** + * @internal + */ export function isErrnoException(obj: unknown): obj is NodeJS.ErrnoException { return ( isErrorLike(obj) && diff --git a/src/constants.ts b/src/constants.ts index dd9726d5..d8e562cc 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,7 @@ import {dirname} from 'path'; import {puppeteerDirname} from './compat.js'; +/** + * @internal + */ export const rootDirname = dirname(dirname(dirname(puppeteerDirname))); diff --git a/src/environment.ts b/src/environment.ts index f7d86977..5ceca84a 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -14,4 +14,7 @@ * limitations under the License. */ +/** + * @internal + */ export const isNode = !!(typeof process !== 'undefined' && process.version); diff --git a/src/generated/version.ts b/src/generated/version.ts index c2f6a185..86e1da0f 100644 --- a/src/generated/version.ts +++ b/src/generated/version.ts @@ -1 +1,4 @@ +/** + * @internal + */ export const packageVersion = '15.1.1'; diff --git a/src/initializePuppeteer.ts b/src/initializePuppeteer.ts index 0b733905..224e498e 100644 --- a/src/initializePuppeteer.ts +++ b/src/initializePuppeteer.ts @@ -20,6 +20,9 @@ import {rootDirname} from './constants.js'; import {PuppeteerNode} from './node/Puppeteer.js'; import {PUPPETEER_REVISIONS} from './revisions.js'; +/** + * @internal + */ export const initializePuppeteer = (packageName: string): PuppeteerNode => { const isPuppeteerCore = packageName === 'puppeteer-core'; const puppeteerRootDirectory = sync(rootDirname); diff --git a/src/node/BrowserFetcher.ts b/src/node/BrowserFetcher.ts index 1407483e..01865f6a 100644 --- a/src/node/BrowserFetcher.ts +++ b/src/node/BrowserFetcher.ts @@ -71,6 +71,7 @@ const browserConfig = { /** * Supported platforms. + * * @public */ export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64'; @@ -100,10 +101,7 @@ function archiveName( } } -/** - * @internal - */ -function _downloadURL( +function downloadURL( product: Product, platform: Platform, host: string, @@ -282,7 +280,7 @@ export class BrowserFetcher { * from the host. */ canDownload(revision: string): Promise { - const url = _downloadURL( + const url = downloadURL( this.#product, this.#platform, this.#downloadHost, @@ -318,7 +316,7 @@ export class BrowserFetcher { revision: string, progressCallback: (x: number, y: number) => void = (): void => {} ): Promise { - const url = _downloadURL( + const url = downloadURL( this.#product, this.#platform, this.#downloadHost, @@ -451,7 +449,7 @@ export class BrowserFetcher { } else { throw new Error('Unsupported product: ' + this.#product); } - const url = _downloadURL( + const url = downloadURL( this.#product, this.#platform, this.#downloadHost, diff --git a/src/node/BrowserRunner.ts b/src/node/BrowserRunner.ts index 34b10b00..bdcdda75 100644 --- a/src/node/BrowserRunner.ts +++ b/src/node/BrowserRunner.ts @@ -48,6 +48,9 @@ This means that, on future Puppeteer launches, Puppeteer might not be able to la Please check your open processes and ensure that the browser processes that Puppeteer launched have been killed. If you think this is a bug, please report it on the Puppeteer issue tracker.`; +/** + * @internal + */ export class BrowserRunner { #product: Product; #executablePath: string; diff --git a/src/node/NodeWebSocketTransport.ts b/src/node/NodeWebSocketTransport.ts index bf749202..5596d10b 100644 --- a/src/node/NodeWebSocketTransport.ts +++ b/src/node/NodeWebSocketTransport.ts @@ -18,6 +18,9 @@ import {ConnectionTransport} from '../common/ConnectionTransport.js'; import {packageVersion} from '../generated/version.js'; import {promises as dns} from 'dns'; +/** + * @internal + */ export class NodeWebSocketTransport implements ConnectionTransport { static async create(urlString: string): Promise { // TODO(jrandolf): Starting in Node 17, IPv6 is favoured over IPv4 due to a change diff --git a/src/node/PipeTransport.ts b/src/node/PipeTransport.ts index 511d7fb6..a622a9bb 100644 --- a/src/node/PipeTransport.ts +++ b/src/node/PipeTransport.ts @@ -22,6 +22,9 @@ import { removeEventListeners, } from '../common/util.js'; +/** + * @internal + */ export class PipeTransport implements ConnectionTransport { #pipeWrite: NodeJS.WritableStream; #eventListeners: PuppeteerEventListener[]; diff --git a/src/node/ProductLauncher.ts b/src/node/ProductLauncher.ts index 8d5c233d..a1d7c84f 100644 --- a/src/node/ProductLauncher.ts +++ b/src/node/ProductLauncher.ts @@ -40,6 +40,9 @@ export interface ProductLauncher { product: Product; } +/** + * @internal + */ export function executablePathForChannel( channel: ChromeReleaseChannel ): string { @@ -116,6 +119,9 @@ export function executablePathForChannel( return chromePath; } +/** + * @internal + */ export function resolveExecutablePath( launcher: ChromeLauncher | FirefoxLauncher ): { diff --git a/src/node/Puppeteer.ts b/src/node/Puppeteer.ts index fb9af91a..fa994f02 100644 --- a/src/node/Puppeteer.ts +++ b/src/node/Puppeteer.ts @@ -39,14 +39,13 @@ export interface PuppeteerLaunchOptions } /** - * Extends the main {@link Puppeteer} class with Node specific behaviour for fetching and - * downloading browsers. + * Extends the main {@link Puppeteer} class with Node specific behaviour for + * fetching and downloading browsers. * * If you're using Puppeteer in a Node environment, this is the class you'll get * when you run `require('puppeteer')` (or the equivalent ES `import`). * * @remarks - * * The most common method to use is {@link PuppeteerNode.launch | launch}, which * is used to launch and connect to a new browser instance. * @@ -107,8 +106,6 @@ export class PuppeteerNode extends Puppeteer { /** * This method attaches Puppeteer to an existing browser instance. * - * @remarks - * * @param options - Set of configurable options to set on the browser. * @returns Promise which resolves to browser instance. */ @@ -125,10 +122,6 @@ export class PuppeteerNode extends Puppeteer { get _productName(): Product | undefined { return this.#productName; } - - /** - * @internal - */ set _productName(name: Product | undefined) { if (this.#productName !== name) { this._changedProduct = true; @@ -137,10 +130,8 @@ export class PuppeteerNode extends Puppeteer { } /** - * Launches puppeteer and launches a browser instance with given arguments - * and options when specified. - * - * @remarks + * Launches puppeteer and launches a browser instance with given arguments and + * options when specified. * * @example * You can use `ignoreDefaultArgs` to filter out `--mute-audio` from default arguments: @@ -150,13 +141,20 @@ export class PuppeteerNode extends Puppeteer { * }); * ``` * - * **NOTE** Puppeteer can also be used to control the Chrome browser, - * but it works best with the version of Chromium it is bundled with. - * There is no guarantee it will work with any other version. - * Use `executablePath` option with extreme caution. - * If Google Chrome (rather than Chromium) is preferred, a {@link https://www.google.com/chrome/browser/canary.html | Chrome Canary} or {@link https://www.chromium.org/getting-involved/dev-channel | Dev Channel} build is suggested. - * In `puppeteer.launch([options])`, any mention of Chromium also applies to Chrome. - * See {@link https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/ | this article} for a description of the differences between Chromium and Chrome. {@link https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md | This article} describes some differences for Linux users. + * @remarks + * **NOTE** Puppeteer can also be used to control the Chrome browser, but it + * works best with the version of Chromium it is bundled with. There is no + * guarantee it will work with any other version. Use `executablePath` option + * with extreme caution. If Google Chrome (rather than Chromium) is preferred, + * a {@link https://www.google.com/chrome/browser/canary.html | Chrome Canary} + * or + * {@link https://www.chromium.org/getting-involved/dev-channel | Dev Channel} + * build is suggested. In `puppeteer.launch([options])`, any mention of + * Chromium also applies to Chrome. See + * {@link https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/ | this article} + * for a description of the differences between Chromium and Chrome. + * {@link https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md | This article} + * describes some differences for Linux users. * * @param options - Set of configurable options to set on the browser. * @returns Promise which resolves to browser instance. @@ -170,13 +168,13 @@ export class PuppeteerNode extends Puppeteer { /** * @remarks + * **NOTE** `puppeteer.executablePath()` is affected by the + * `PUPPETEER_EXECUTABLE_PATH` and `PUPPETEER_CHROMIUM_REVISION` environment + * variables. * - * **NOTE** `puppeteer.executablePath()` is affected by the `PUPPETEER_EXECUTABLE_PATH` - * and `PUPPETEER_CHROMIUM_REVISION` environment variables. - * - * @returns A path where Puppeteer expects to find the bundled browser. - * The browser binary might not be there if the download was skipped with - * the `PUPPETEER_SKIP_DOWNLOAD` environment variable. + * @returns A path where Puppeteer expects to find the bundled browser. The + * browser binary might not be there if the download was skipped with the + * `PUPPETEER_SKIP_DOWNLOAD` environment variable. */ executablePath(channel?: string): string { return this._launcher.executablePath(channel); @@ -211,11 +209,12 @@ export class PuppeteerNode extends Puppeteer { } /** - * The name of the browser that is under automation (`"chrome"` or `"firefox"`) + * The name of the browser that is under automation (`"chrome"` or + * `"firefox"`) * * @remarks - * The product is set by the `PUPPETEER_PRODUCT` environment variable or the `product` - * option in `puppeteer.launch([options])` and defaults to `chrome`. + * The product is set by the `PUPPETEER_PRODUCT` environment variable or the + * `product` option in `puppeteer.launch([options])` and defaults to `chrome`. * Firefox support is experimental. */ get product(): string { @@ -223,7 +222,6 @@ export class PuppeteerNode extends Puppeteer { } /** - * * @param options - Set of configurable options to set on the browser. * @returns The default flags that Chromium will be launched with. */ @@ -232,8 +230,8 @@ export class PuppeteerNode extends Puppeteer { } /** - * @param options - Set of configurable options to specify the settings - * of the BrowserFetcher. + * @param options - Set of configurable options to specify the settings of the + * BrowserFetcher. * @returns A new BrowserFetcher instance. */ createBrowserFetcher(options: BrowserFetcherOptions): BrowserFetcher { diff --git a/src/node/install.ts b/src/node/install.ts index 4c3e19ed..9480a334 100644 --- a/src/node/install.ts +++ b/src/node/install.ts @@ -23,11 +23,17 @@ import {PuppeteerNode} from './Puppeteer.js'; import createHttpsProxyAgent, {HttpsProxyAgentOptions} from 'https-proxy-agent'; import {getProxyForUrl} from 'proxy-from-env'; +/** + * @internal + */ const supportedProducts = { chrome: 'Chromium', firefox: 'Firefox Nightly', } as const; +/** + * @internal + */ function getProduct(input: string): 'chrome' | 'firefox' { if (input !== 'chrome' && input !== 'firefox') { throw new Error(`Unsupported product ${input}`); @@ -35,6 +41,9 @@ function getProduct(input: string): 'chrome' | 'firefox' { return input; } +/** + * @internal + */ export async function downloadBrowser(): Promise { const downloadHost = process.env['PUPPETEER_DOWNLOAD_HOST'] || @@ -209,6 +218,9 @@ export async function downloadBrowser(): Promise { } } +/** + * @internal + */ export function logPolitely(toBeLogged: unknown): void { const logLevel = process.env['npm_config_loglevel'] || ''; const logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1; diff --git a/src/puppeteer-core.ts b/src/puppeteer-core.ts index 201eb525..50da7183 100644 --- a/src/puppeteer-core.ts +++ b/src/puppeteer-core.ts @@ -16,21 +16,19 @@ import {initializePuppeteer} from './initializePuppeteer.js'; +export * from './common/NetworkConditions.js'; +export * from './common/QueryHandler.js'; +export * from './common/DeviceDescriptors.js'; +export * from './common/Errors.js'; + const puppeteer = initializePuppeteer('puppeteer-core'); export const { - clearCustomQueryHandlers, connect, createBrowserFetcher, - customQueryHandlerNames, defaultArgs, - devices, - errors, executablePath, launch, - networkConditions, - registerCustomQueryHandler, - unregisterCustomQueryHandler, } = puppeteer; export default puppeteer; diff --git a/src/puppeteer.ts b/src/puppeteer.ts index 7443709f..21a4a2ca 100644 --- a/src/puppeteer.ts +++ b/src/puppeteer.ts @@ -16,21 +16,22 @@ import {initializePuppeteer} from './initializePuppeteer.js'; +export * from './common/NetworkConditions.js'; +export * from './common/QueryHandler.js'; +export * from './common/DeviceDescriptors.js'; +export * from './common/Errors.js'; + +/** + * @public + */ const puppeteer = initializePuppeteer('puppeteer'); export const { - clearCustomQueryHandlers, connect, createBrowserFetcher, - customQueryHandlerNames, defaultArgs, - devices, - errors, executablePath, launch, - networkConditions, - registerCustomQueryHandler, - unregisterCustomQueryHandler, } = puppeteer; export default puppeteer; diff --git a/src/revisions.ts b/src/revisions.ts index 36eb902f..b3503987 100644 --- a/src/revisions.ts +++ b/src/revisions.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @internal + */ export const PUPPETEER_REVISIONS = Object.freeze({ chromium: '1011831', firefox: 'latest', diff --git a/src/templates/version.ts.tmpl b/src/templates/version.ts.tmpl index 18444ac3..73b984d2 100644 --- a/src/templates/version.ts.tmpl +++ b/src/templates/version.ts.tmpl @@ -1 +1,4 @@ +/** + * @internal + */ export const packageVersion = 'PACKAGE_VERSION'; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..fa4ddbec --- /dev/null +++ b/src/types.ts @@ -0,0 +1,71 @@ +// AUTOGENERATED - Use `utils/export_all.js` to regenerate. + +export * from './compat.d.js'; +export * from './constants.js'; +export * from './environment.js'; +export * from './initializePuppeteer.js'; +export * from './puppeteer.js'; +export * from './revisions.js'; + +// Exports from `common` +export * from './common/Accessibility.js'; +export * from './common/AriaQueryHandler.js'; +export * from './common/Browser.js'; +export * from './common/BrowserConnector.js'; +export * from './common/BrowserWebSocketTransport.js'; +export * from './common/Connection.js'; +export * from './common/ConnectionTransport.js'; +export * from './common/ConsoleMessage.js'; +export * from './common/Coverage.js'; +export * from './common/DOMWorld.js'; +export * from './common/Debug.js'; +export * from './common/DeviceDescriptors.js'; +export * from './common/Dialog.js'; +export * from './common/ElementHandle.js'; +export * from './common/EmulationManager.js'; +export * from './common/Errors.js'; +export * from './common/EventEmitter.js'; +export * from './common/ExecutionContext.js'; +export * from './common/FileChooser.js'; +export * from './common/FrameManager.js'; +export * from './common/HTTPRequest.js'; +export * from './common/HTTPResponse.js'; +export * from './common/Input.js'; +export * from './common/JSHandle.js'; +export * from './common/LifecycleWatcher.js'; +export * from './common/NetworkConditions.js'; +export * from './common/NetworkEventManager.js'; +export * from './common/NetworkManager.js'; +export * from './common/PDFOptions.js'; +export * from './common/Page.js'; +export * from './common/Product.js'; +export * from './common/Puppeteer.js'; +export * from './common/PuppeteerViewport.js'; +export * from './common/QueryHandler.js'; +export * from './common/SecurityDetails.js'; +export * from './common/Target.js'; +export * from './common/TaskQueue.js'; +export * from './common/TimeoutSettings.js'; +export * from './common/Tracing.js'; +export * from './common/USKeyboardLayout.js'; +export * from './common/WebWorker.js'; +export * from './common/assert.js'; +export * from './common/fetch.js'; +export * from './common/types.js'; +export * from './common/util.js'; + +// Exports from `node` +export * from './node/BrowserFetcher.js'; +export * from './node/BrowserRunner.js'; +export * from './node/ChromeLauncher.js'; +export * from './node/FirefoxLauncher.js'; +export * from './node/LaunchOptions.js'; +export * from './node/NodeWebSocketTransport.js'; +export * from './node/PipeTransport.js'; +export * from './node/ProductLauncher.js'; +export * from './node/Puppeteer.js'; +export * from './node/install.js'; +export * from './node/util.js'; + +// Exports from `generated` +export * from './generated/version.js'; diff --git a/test/src/oopif.spec.ts b/test/src/oopif.spec.ts index 0582375a..f747910d 100644 --- a/test/src/oopif.spec.ts +++ b/test/src/oopif.spec.ts @@ -24,8 +24,8 @@ import { import { Browser, BrowserContext, - Page, -} from '../../lib/cjs/puppeteer/api-docs-entry.js'; +} from '../../lib/cjs/puppeteer/common/Browser.js'; +import {Page} from '../../lib/cjs/puppeteer/common/Page.js'; describeChromeOnly('OOPIF', function () { /* We use a special browser for this test as we need the --site-per-process flag */ diff --git a/utils/export_all.js b/utils/export_all.js new file mode 100644 index 00000000..2cbef44f --- /dev/null +++ b/utils/export_all.js @@ -0,0 +1,30 @@ +const {readdirSync, writeFileSync} = require('fs'); +const {join, basename} = require('path'); + +const EXCLUDE_FILES = ['puppeteer-core.ts']; + +let typesTs = '// AUTOGENERATED - Use `utils/export_all.js` to regenerate.\n'; + +typesTs += `\n`; +for (const file of readdirSync(join(__dirname, `../src`)).filter(filename => { + return ( + filename.endsWith('ts') && + !filename.startsWith('types') && + !EXCLUDE_FILES.includes(filename) + ); +})) { + typesTs += `export * from './${basename(file, '.ts')}.js';\n`; +} + +for (const folder of ['common', 'node', 'generated']) { + typesTs += `\n// Exports from \`${folder}\`\n`; + for (const file of readdirSync(join(__dirname, `../src/${folder}`)).filter( + filename => { + return filename.endsWith('ts') && !EXCLUDE_FILES.includes(filename); + } + )) { + typesTs += `export * from './${folder}/${basename(file, '.ts')}.js';\n`; + } +} + +writeFileSync(join(__dirname, '../src/types.ts'), typesTs);