192 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			6.0 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.
 | 
						|
 */
 | 
						|
const fs = require('fs');
 | 
						|
const path = require('path');
 | 
						|
const rmSync = require('rimraf').sync;
 | 
						|
const ncp = require('ncp');
 | 
						|
const {spawnSync} = require('child_process');
 | 
						|
const util = require('util');
 | 
						|
 | 
						|
const writeFileAsync = util.promisify(fs.writeFile.bind(fs));
 | 
						|
const cpAsync = util.promisify(ncp);
 | 
						|
 | 
						|
const SCRIPT_NAME = path.basename(__filename);
 | 
						|
const ROOT_PATH = path.join(__dirname, '..');
 | 
						|
 | 
						|
const PLAYWRIGHT_CORE_FILES = ['lib', 'types', 'NOTICE', 'LICENSE', '.npmignore'];
 | 
						|
 | 
						|
const PACKAGES = {
 | 
						|
  'playwright': {
 | 
						|
    description: 'A high-level API to automate web browsers',
 | 
						|
    browsers: ['chromium', 'firefox', 'webkit'],
 | 
						|
    // We copy README.md additionally for Playwright so that it looks nice on NPM.
 | 
						|
    files: [...PLAYWRIGHT_CORE_FILES, 'README.md'],
 | 
						|
  },
 | 
						|
  'playwright-core': {
 | 
						|
    description: 'A high-level API to automate web browsers',
 | 
						|
    browsers: [],
 | 
						|
    files: PLAYWRIGHT_CORE_FILES,
 | 
						|
  },
 | 
						|
  'playwright-webkit': {
 | 
						|
    description: 'A high-level API to automate WebKit',
 | 
						|
    browsers: ['webkit'],
 | 
						|
    files: PLAYWRIGHT_CORE_FILES,
 | 
						|
  },
 | 
						|
  'playwright-firefox': {
 | 
						|
    description: 'A high-level API to automate Firefox',
 | 
						|
    browsers: ['firefox'],
 | 
						|
    files: PLAYWRIGHT_CORE_FILES,
 | 
						|
  },
 | 
						|
  'playwright-chromium': {
 | 
						|
    description: 'A high-level API to automate Chromium',
 | 
						|
    browsers: ['chromium'],
 | 
						|
    files: PLAYWRIGHT_CORE_FILES,
 | 
						|
  },
 | 
						|
  'playwright-electron': {
 | 
						|
    version: '0.4.0', // Manually manage playwright-electron version.
 | 
						|
    description: 'A high-level API to automate Electron',
 | 
						|
    browsers: [],
 | 
						|
    files: PLAYWRIGHT_CORE_FILES,
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
const cleanupPaths = [];
 | 
						|
 | 
						|
// 1. Parse CLI arguments
 | 
						|
const args = process.argv.slice(2);
 | 
						|
if (args.some(arg => arg === '--help')) {
 | 
						|
  console.log(usage());
 | 
						|
  process.exit(1);
 | 
						|
} else if (args.length < 1) {
 | 
						|
  console.log(`Please specify package name, e.g. 'playwright' or 'playwright-chromium'.`);
 | 
						|
  console.log(`Try running ${SCRIPT_NAME} --help`);
 | 
						|
  process.exit(1);
 | 
						|
} else if (args.length < 2) {
 | 
						|
  console.log(`Please specify output path`);
 | 
						|
  console.log(`Try running ${SCRIPT_NAME} --help`);
 | 
						|
  process.exit(1);
 | 
						|
}
 | 
						|
 | 
						|
// 2. Setup cleanup if needed
 | 
						|
if (!args.some(arg => arg === '--no-cleanup')) {
 | 
						|
  process.on('exit', () => {
 | 
						|
    cleanupPaths.forEach(cleanupPath => rmSync(cleanupPath, {}));
 | 
						|
  });
 | 
						|
  process.on('SIGINT', () => process.exit(2));
 | 
						|
  process.on('SIGHUP', () => process.exit(3));
 | 
						|
  process.on('SIGTERM', () => process.exit(4));
 | 
						|
  process.on('uncaughtException', error => {
 | 
						|
    console.error(error);
 | 
						|
    process.exit(5);
 | 
						|
  });
 | 
						|
  process.on('unhandledRejection', error => {
 | 
						|
    console.error(error);
 | 
						|
    process.exit(6);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
const packageName = args[0];
 | 
						|
const outputPath = path.resolve(args[1]);
 | 
						|
const packagePath = path.join(__dirname, packageName);
 | 
						|
const package = PACKAGES[packageName];
 | 
						|
if (!package) {
 | 
						|
  console.log(`ERROR: unknown package ${packageName}`);
 | 
						|
  process.exit(1);
 | 
						|
}
 | 
						|
 | 
						|
(async () => {
 | 
						|
  // 3. Copy package files.
 | 
						|
  for (const file of package.files)
 | 
						|
    await copyToPackage(file);
 | 
						|
 | 
						|
  // 4. Generate package.json
 | 
						|
  const pwInternalJSON = require(path.join(ROOT_PATH, 'package.json'));
 | 
						|
  await writeToPackage('package.json', JSON.stringify({
 | 
						|
    name: packageName,
 | 
						|
    version: package.version || pwInternalJSON.version,
 | 
						|
    description: package.description,
 | 
						|
    repository: pwInternalJSON.repository,
 | 
						|
    engines: pwInternalJSON.engines,
 | 
						|
    homepage: pwInternalJSON.homepage,
 | 
						|
    main: 'index.js',
 | 
						|
    exports: {
 | 
						|
      // Root import: we have a wrapper ES Module to support the following syntax.
 | 
						|
      // const { chromium } = require('playwright');
 | 
						|
      // import { chromium } from 'playwright';
 | 
						|
      '.': {
 | 
						|
        import: './index.mjs',
 | 
						|
        require: './index.js',
 | 
						|
      },
 | 
						|
      // Anything else can be required/imported by providing a relative path.
 | 
						|
      './': './',
 | 
						|
    },
 | 
						|
    scripts: {
 | 
						|
      install: 'node install.js',
 | 
						|
    },
 | 
						|
    author: pwInternalJSON.author,
 | 
						|
    license: pwInternalJSON.license,
 | 
						|
    dependencies: pwInternalJSON.dependencies
 | 
						|
  }, null, 2));
 | 
						|
 | 
						|
  // 5. Generate browsers.json
 | 
						|
  const browsersJSON = require(path.join(ROOT_PATH, 'browsers.json'));
 | 
						|
  browsersJSON.browsers = browsersJSON.browsers.filter(browser => package.browsers.includes(browser.name));
 | 
						|
  await writeToPackage('browsers.json', JSON.stringify(browsersJSON, null, 2));
 | 
						|
 | 
						|
  // 6. Run npm pack
 | 
						|
  const {stdout, stderr, status} = spawnSync('npm', ['pack'], {cwd: packagePath, encoding: 'utf8'});
 | 
						|
  if (status !== 0) {
 | 
						|
    console.log(`ERROR: "npm pack" failed`);
 | 
						|
    console.log(stderr);
 | 
						|
    process.exit(1);
 | 
						|
  }
 | 
						|
  const tgzName = stdout.trim();
 | 
						|
 | 
						|
  // 7. Move result to the outputPath
 | 
						|
  fs.renameSync(path.join(packagePath, tgzName), outputPath);
 | 
						|
  console.log(outputPath);
 | 
						|
})();
 | 
						|
 | 
						|
async function writeToPackage(fileName, content) {
 | 
						|
  const toPath = path.join(packagePath, fileName);
 | 
						|
  cleanupPaths.push(toPath);
 | 
						|
  console.error(`- generating: //${path.relative(ROOT_PATH, toPath)}`);
 | 
						|
  await writeFileAsync(toPath, content);
 | 
						|
}
 | 
						|
 | 
						|
async function copyToPackage(fileOrDirectoryName) {
 | 
						|
  const fromPath = path.join(ROOT_PATH, fileOrDirectoryName);
 | 
						|
  const toPath = path.join(packagePath, fileOrDirectoryName);
 | 
						|
  cleanupPaths.push(toPath);
 | 
						|
  console.error(`- copying: //${path.relative(ROOT_PATH, fromPath)} -> //${path.relative(ROOT_PATH, toPath)}`);
 | 
						|
  await cpAsync(fromPath, toPath);
 | 
						|
}
 | 
						|
 | 
						|
function usage() {
 | 
						|
  return `
 | 
						|
usage: ${SCRIPT_NAME} <package-name> <output-path> [--no-cleanup]
 | 
						|
 | 
						|
Creates a .tgz of the package and saves it at the given output path
 | 
						|
 | 
						|
  --no-cleanup    skip cleaning up generated files from package directory
 | 
						|
 | 
						|
Example:
 | 
						|
  ${SCRIPT_NAME} playwright ./playwright.tgz
 | 
						|
`;
 | 
						|
}
 | 
						|
 |