mirror of
https://github.com/microsoft/playwright-cli.git
synced 2026-09-14 19:59:39 +08:00
60cb176373
`registry.defaultRegistryDirectory` became a function upstream in microsoft/playwright#41942 and arrived here with the roll to 1.63.0-alpha-2026-08-05. `cacheFile()` still used it as a string, so `path.join()` threw, `readCache()`/`writeCache()` swallowed the TypeError, and the update check was never cached: every single CLI invocation fetched the npm registry and re-ran the installed-skill check. Locally that is ~480ms per command instead of ~125ms. Tests always set PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST, so the default branch was never exercised. Add a regression test that points HOME at a temp directory and asserts the cache file is written. Also hoist `cacheFile()` out of the try blocks so only I/O and parse failures are swallowed there, instead of masking a path-computation bug as "no cache".
116 lines
3.2 KiB
JavaScript
Executable File
116 lines
3.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* Copyright (c) Microsoft Corporation.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
// @ts-check
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const { program } = require('playwright-core/lib/tools/cli-client/program');
|
|
const coreBundle = require('playwright-core/lib/coreBundle');
|
|
const { tools, registry } = coreBundle;
|
|
const { checkInstalledSkills, frame } = require('./skillCheck');
|
|
|
|
const packageJson = require('./package.json');
|
|
|
|
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
|
|
main();
|
|
|
|
async function main() {
|
|
await checkForUpdates().catch(() => {});
|
|
program({ embedderVersion: packageJson.version });
|
|
}
|
|
|
|
async function checkForUpdates() {
|
|
if (process.env.NO_UPDATE_NOTIFIER || process.env.CI)
|
|
return;
|
|
|
|
const cache = readCache();
|
|
const stale = !cache || (Date.now() - cache.lastCheck) > ONE_DAY_MS;
|
|
if (!stale)
|
|
return;
|
|
writeCache({ lastCheck: Date.now() });
|
|
|
|
const command = process.argv.slice(2).find(arg => !arg.startsWith('-'));
|
|
if (command !== 'install')
|
|
checkInstalledSkills();
|
|
|
|
const latest = await fetchLatestVersion();
|
|
if (latest && tools.compareSemver(latest, packageJson.version) > 0)
|
|
printNotice(packageJson.version, latest);
|
|
}
|
|
|
|
async function fetchLatestVersion() {
|
|
try {
|
|
const controller = new AbortController();
|
|
const timeout = setTimeout(() => controller.abort(), 1500);
|
|
try {
|
|
const res = await fetch(`https://registry.npmjs.org/${packageJson.name}/latest`, { signal: controller.signal });
|
|
if (!res.ok)
|
|
return undefined;
|
|
const json = await res.json();
|
|
return typeof json.version === 'string' ? json.version : undefined;
|
|
} finally {
|
|
clearTimeout(timeout);
|
|
}
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} current
|
|
* @param {string} latest
|
|
*/
|
|
function printNotice(current, latest) {
|
|
process.stderr.write('\n' + frame([
|
|
`Update available for ${packageJson.name}: ${current} → ${latest}`,
|
|
`Run \`npm install -g ${packageJson.name}@latest\` (global) or`,
|
|
`\`npm install --save-dev ${packageJson.name}@latest\` (local) to update.`,
|
|
]) + '\n');
|
|
}
|
|
|
|
function cacheFile() {
|
|
const dir = process.env.PLAYWRIGHT_CLI_INSTALLATION_FOR_TEST || registry.defaultRegistryDirectory();
|
|
return path.join(dir, 'cli-update-check.json');
|
|
}
|
|
|
|
function readCache() {
|
|
const file = cacheFile();
|
|
try {
|
|
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
if (typeof data.lastCheck === 'number')
|
|
return data;
|
|
} catch {
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* @param {*} data
|
|
*/
|
|
function writeCache(data) {
|
|
const file = cacheFile();
|
|
try {
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
fs.writeFileSync(file, JSON.stringify(data));
|
|
} catch {
|
|
}
|
|
}
|