| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  | #!/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'); | 
					
						
							| 
									
										
										
										
											2020-07-30 17:15:46 -07:00
										 |  |  | const os = require('os'); | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  | 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, '..'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 13:46:40 -07:00
										 |  |  | const PLAYWRIGHT_CORE_FILES = ['bin', 'lib', 'types', 'NOTICE', 'LICENSE']; | 
					
						
							| 
									
										
										
										
											2020-09-09 09:51:28 -07:00
										 |  |  | const FFMPEG_FILES = ['third_party/ffmpeg']; | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | const PACKAGES = { | 
					
						
							|  |  |  |   'playwright': { | 
					
						
							|  |  |  |     description: 'A high-level API to automate web browsers', | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     browsers: ['chromium', 'firefox', 'webkit'], | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |     // We copy README.md additionally for Playwright so that it looks nice on NPM.
 | 
					
						
							| 
									
										
										
										
											2020-09-09 09:51:28 -07:00
										 |  |  |     files: [...PLAYWRIGHT_CORE_FILES, ...FFMPEG_FILES, 'README.md'], | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   'playwright-core': { | 
					
						
							|  |  |  |     description: 'A high-level API to automate web browsers', | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     browsers: [], | 
					
						
							|  |  |  |     files: PLAYWRIGHT_CORE_FILES, | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   'playwright-webkit': { | 
					
						
							|  |  |  |     description: 'A high-level API to automate WebKit', | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     browsers: ['webkit'], | 
					
						
							|  |  |  |     files: PLAYWRIGHT_CORE_FILES, | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   'playwright-firefox': { | 
					
						
							|  |  |  |     description: 'A high-level API to automate Firefox', | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     browsers: ['firefox'], | 
					
						
							|  |  |  |     files: PLAYWRIGHT_CORE_FILES, | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   'playwright-chromium': { | 
					
						
							|  |  |  |     description: 'A high-level API to automate Chromium', | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     browsers: ['chromium'], | 
					
						
							| 
									
										
										
										
											2020-09-09 09:51:28 -07:00
										 |  |  |     files: [...PLAYWRIGHT_CORE_FILES, ...FFMPEG_FILES], | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   'playwright-electron': { | 
					
						
							|  |  |  |     version: '0.4.0', // Manually manage playwright-electron version.
 | 
					
						
							|  |  |  |     description: 'A high-level API to automate Electron', | 
					
						
							|  |  |  |     browsers: [], | 
					
						
							| 
									
										
										
										
											2020-09-09 09:51:28 -07:00
										 |  |  |     files: [...PLAYWRIGHT_CORE_FILES, ...FFMPEG_FILES, 'electron-types.d.ts'], | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 16:36:00 -07:00
										 |  |  | const packageName = args[0]; | 
					
						
							|  |  |  | const outputPath = path.resolve(args[1]); | 
					
						
							|  |  |  | const packagePath = path.join(__dirname, 'output', packageName); | 
					
						
							|  |  |  | const package = PACKAGES[packageName]; | 
					
						
							|  |  |  | if (!package) { | 
					
						
							|  |  |  |   console.log(`ERROR: unknown package ${packageName}`); | 
					
						
							|  |  |  |   process.exit(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  | // 2. Setup cleanup if needed
 | 
					
						
							|  |  |  | if (!args.some(arg => arg === '--no-cleanup')) { | 
					
						
							| 
									
										
										
										
											2020-07-23 15:14:36 -07:00
										 |  |  |   process.on('exit', () => { | 
					
						
							| 
									
										
										
										
											2020-07-24 16:36:00 -07:00
										 |  |  |     rmSync(packagePath, {}); | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  |   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); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | (async () => { | 
					
						
							|  |  |  |   // 3. Copy package files.
 | 
					
						
							| 
									
										
										
										
											2020-07-24 16:36:00 -07:00
										 |  |  |   rmSync(packagePath, {}); | 
					
						
							|  |  |  |   fs.mkdirSync(packagePath, { recursive: true }); | 
					
						
							|  |  |  |   await copyToPackage(path.join(__dirname, 'common') + path.sep, packagePath + path.sep); | 
					
						
							|  |  |  |   if (fs.existsSync(path.join(__dirname, packageName))) { | 
					
						
							|  |  |  |     // Copy package-specific files, these can overwrite common ones.
 | 
					
						
							|  |  |  |     await copyToPackage(path.join(__dirname, packageName) + path.sep, packagePath + path.sep); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   for (const file of package.files) | 
					
						
							| 
									
										
										
										
											2020-07-24 16:36:00 -07:00
										 |  |  |     await copyToPackage(path.join(ROOT_PATH, file), path.join(packagePath, file)); | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-01 21:47:16 +02:00
										 |  |  |   await copyToPackage(path.join(ROOT_PATH, 'docs/api.json'), path.join(packagePath, 'api.json')); | 
					
						
							| 
									
										
										
										
											2020-08-21 18:46:11 -07:00
										 |  |  |   await copyToPackage(path.join(ROOT_PATH, 'src/protocol/protocol.yml'), path.join(packagePath, 'protocol.yml')); | 
					
						
							| 
									
										
										
										
											2020-07-28 22:30:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   // 4. Generate package.json
 | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |   const pwInternalJSON = require(path.join(ROOT_PATH, 'package.json')); | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   await writeToPackage('package.json', JSON.stringify({ | 
					
						
							|  |  |  |     name: packageName, | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     version: package.version || pwInternalJSON.version, | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |     description: package.description, | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     repository: pwInternalJSON.repository, | 
					
						
							|  |  |  |     engines: pwInternalJSON.engines, | 
					
						
							|  |  |  |     homepage: pwInternalJSON.homepage, | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |     main: 'index.js', | 
					
						
							| 
									
										
										
										
											2020-07-23 15:14:36 -07:00
										 |  |  |     exports: { | 
					
						
							| 
									
										
										
										
											2020-07-24 14:21:25 -07:00
										 |  |  |       // 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.
 | 
					
						
							|  |  |  |       './': './', | 
					
						
							| 
									
										
										
										
											2020-07-23 15:14:36 -07:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |     scripts: { | 
					
						
							|  |  |  |       install: 'node install.js', | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2020-06-18 17:11:10 -07:00
										 |  |  |     author: pwInternalJSON.author, | 
					
						
							|  |  |  |     license: pwInternalJSON.license, | 
					
						
							|  |  |  |     dependencies: pwInternalJSON.dependencies | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   }, null, 2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 5. Generate browsers.json
 | 
					
						
							|  |  |  |   const browsersJSON = require(path.join(ROOT_PATH, 'browsers.json')); | 
					
						
							| 
									
										
										
										
											2020-07-24 16:36:00 -07:00
										 |  |  |   for (const browser of browsersJSON.browsers) | 
					
						
							|  |  |  |     browser.download = package.browsers.includes(browser.name); | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   await writeToPackage('browsers.json', JSON.stringify(browsersJSON, null, 2)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-03 10:29:43 -07:00
										 |  |  |   // 6. Bake commit SHA into the package
 | 
					
						
							|  |  |  |   const commitSHA = spawnSync('git', ['rev-parse', 'HEAD'], {cwd: __dirname, encoding: 'utf8'}); | 
					
						
							|  |  |  |   await writeToPackage('commitinfo', commitSHA.stdout.trim()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 7. Run npm pack
 | 
					
						
							| 
									
										
										
										
											2020-07-30 17:15:46 -07:00
										 |  |  |   const shell = os.platform() === 'win32'; | 
					
						
							|  |  |  |   const {stdout, stderr, status} = spawnSync('npm', ['pack'], {cwd: packagePath, encoding: 'utf8', shell}); | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   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); | 
					
						
							|  |  |  |   console.error(`- generating: //${path.relative(ROOT_PATH, toPath)}`); | 
					
						
							|  |  |  |   await writeFileAsync(toPath, content); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 16:36:00 -07:00
										 |  |  | async function copyToPackage(fromPath, toPath) { | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   console.error(`- copying: //${path.relative(ROOT_PATH, fromPath)} -> //${path.relative(ROOT_PATH, toPath)}`); | 
					
						
							| 
									
										
										
										
											2020-09-09 09:51:28 -07:00
										 |  |  |   try { | 
					
						
							|  |  |  |     fs.mkdirSync(path.dirname(toPath), { recursive: true }); | 
					
						
							|  |  |  |   } catch (e) { | 
					
						
							|  |  |  |     // the folder might exist already
 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-05-21 13:18:15 -07:00
										 |  |  |   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 | 
					
						
							|  |  |  | `;
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |