import {stdin as input, stdout as output} from 'node:process'; import * as readline from 'node:readline';
import type * as Yargs from 'yargs';
import {
Browser,
resolveBuildId,
BrowserPlatform,
type ChromeReleaseChannel,
} from './browser-data/browser-data.js'; import {Cache} from './Cache.js'; import {detectBrowserPlatform} from './detectPlatform.js'; import {install} from './install.js'; import {
computeExecutablePath,
computeSystemExecutablePath,
launch,
} from './launch.js';
function isValidBrowser(browser: unknown): browser is Browser { return Object.values(Browser).includes(browser as Browser);
}
function isValidPlatform(platform: unknown): platform is BrowserPlatform { return Object.values(BrowserPlatform).includes(platform as BrowserPlatform);
}
// If moved update release-please config // x-release-please-start-version const packageVersion = '2.11.1'; // x-release-please-end
#definePathParameter<T>(yargs: Yargs.Argv<T>, required = false) { if (!this.#allowCachePathOverride) { return yargs as Yargs.Argv<T & {path: undefined}>;
}
return yargs.option('path', {
type: 'string',
desc: 'Path to the root folder for the browser downloads and installation. If a relative path is provided, it will be resolved relative to the current working directory. The installation folder structure is compatible with the cache structure used by Puppeteer.',
defaultDescription: 'Current working directory',
...(required ? {} : {default: process.cwd()}),
demandOption: required,
});
}
#build(yargs: Yargs.Argv<unknown>) { const latestOrPinned = this.#pinnedBrowsers ? 'pinned' : 'latest'; // If there are pinned browsers allow the positional arg to be optional const browserArgType = this.#pinnedBrowsers ? '[browser]' : '<browser>'; return yargs
.command(
`install ${browserArgType}`, 'Download and install the specified browser. If successful, the command outputs the actual browser buildId that was installed and the absolute path to the browser executable (format: <browser>@<buildID> <path>).',
yargs => { if (this.#pinnedBrowsers) {
yargs.example('$0 install', 'Install all pinned browsers');
}
yargs
.example( '$0 install chrome',
`Install the ${latestOrPinned} available build of the Chrome browser.`,
)
.example( '$0 install chrome@latest', 'Install the latest available build for the Chrome browser.',
)
.example( '$0 install chrome@stable', 'Install the latest available build for the Chrome browser from the stable channel.',
)
.example( '$0 install chrome@beta', 'Install the latest available build for the Chrome browser from the beta channel.',
)
.example( '$0 install chrome@dev', 'Install the latest available build for the Chrome browser from the dev channel.',
)
.example( '$0 install chrome@canary', 'Install the latest available build for the Chrome Canary browser.',
)
.example( '$0 install chrome@115', 'Install the latest available build for Chrome 115.',
)
.example( '$0 install chromedriver@canary', 'Install the latest available build for ChromeDriver Canary.',
)
.example( '$0 install chromedriver@115', 'Install the latest available build for ChromeDriver 115.',
)
.example( '$0 install chromedriver@115.0.5790', 'Install the latest available patch (115.0.5790.X) build for ChromeDriver.',
)
.example( '$0 install chrome-headless-shell', 'Install the latest available chrome-headless-shell build.',
)
.example( '$0 install chrome-headless-shell@beta', 'Install the latest available chrome-headless-shell build corresponding to the Beta channel.',
)
.example( '$0 install chrome-headless-shell@118', 'Install the latest available chrome-headless-shell 118 build.',
)
.example( '$0 install chromium@1083080', 'Install the revision 1083080 of the Chromium browser.',
)
.example( '$0 install firefox', 'Install the latest nightly available build of the Firefox browser.',
)
.example( '$0 install firefox@stable', 'Install the latest stable build of the Firefox browser.',
)
.example( '$0 install firefox@beta', 'Install the latest beta build of the Firefox browser.',
)
.example( '$0 install firefox@devedition', 'Install the latest devedition build of the Firefox browser.',
)
.example( '$0 install firefox@esr', 'Install the latest ESR build of the Firefox browser.',
)
.example( '$0 install firefox@nightly', 'Install the latest nightly build of the Firefox browser.',
)
.example( '$0 install firefox@stable_111.0.1', 'Install a specific version of the Firefox browser.',
)
.example( '$0 install firefox --platform mac', 'Install the latest Mac (Intel) build of the Firefox browser.',
); if (this.#allowCachePathOverride) {
yargs.example( '$0 install firefox --path /tmp/my-browser-cache', 'Install to the specified cache directory.',
);
}
const yargsWithBrowserParam = this.#defineBrowserParameter(
yargs,
!Boolean(this.#pinnedBrowsers),
); const yargsWithPlatformParam = this.#definePlatformParameter(
yargsWithBrowserParam,
); returnthis.#definePathParameter(yargsWithPlatformParam, false)
.option('base-url', {
type: 'string',
desc: 'Base URL to download from',
})
.option('install-deps', {
type: 'boolean',
desc: 'Whether to attempt installing system dependencies (only supported on Linux, requires root privileges).', default: false,
});
},
async args => { if (this.#pinnedBrowsers && !args.browser) { // Use allSettled to avoid scenarios that // a browser may fail early and leave the other // installation in a faulty state const result = await Promise.allSettled(
Object.entries(this.#pinnedBrowsers).map(
async ([browser, options]) => { if (options.skipDownload) { return;
}
await this.#install({
...args,
browser: {
name: browser as Browser,
buildId: options.buildId,
},
});
},
),
);
for (const install of result) { if (install.status === 'rejected') { throw install.reason;
}
}
} else {
await this.#install(args);
}
},
)
.command( 'launch <browser>', 'Launch the specified browser',
yargs => {
yargs
.example( '$0 launch chrome@115.0.5790.170', 'Launch Chrome 115.0.5790.170',
)
.example( '$0 launch firefox@112.0a1', 'Launch the Firefox browser identified by the milestone 112.0a1.',
)
.example( '$0 launch chrome@115.0.5790.170 --detached', 'Launch the browser but detach the sub-processes.',
)
.example( '$0 launch chrome@canary --system', 'Try to locate the Canary build of Chrome installed on the system and launch it.',
)
.example( '$0 launch chrome@115.0.5790.170 -- --version', 'Launch Chrome 115.0.5790.170 and pass custom argument to the binary.',
);
const yargsWithExtraAgs = yargs.parserConfiguration({ 'populate--': true, // Yargs does not have the correct overload for this.
}) as Yargs.Argv<{'--'?: Array<string | number>}>; const yargsWithBrowserParam = this.#defineBrowserParameter(
yargsWithExtraAgs, true,
); const yargsWithPlatformParam = this.#definePlatformParameter(
yargsWithBrowserParam,
); returnthis.#definePathParameter(yargsWithPlatformParam)
.option('detached', {
type: 'boolean',
desc: 'Detach the child process.', default: false,
})
.option('system', {
type: 'boolean',
desc: 'Search for a browser installed on the system instead of the cache folder.', default: false,
})
.option('dumpio', {
type: 'boolean',
desc: "Forwards the browser's process stdout and stderr", default: false,
});
},
async args => { const extraArgs = args['--']?.filter(arg => { returntypeof arg === 'string';
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.