/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import {Command, flags} from '@oclif/command'; import {args} from '@oclif/parser'; import {promises as fs} from 'fs'; import {mkdirp, pathExists, readJSON} from 'fs-extra'; import * as inquirer from 'inquirer'; import * as path from 'path'; import * as yarn from '../utils/yarn'; import cli from 'cli-ux'; import {runBuild} from 'flipper-pkg-lib'; async function deriveOutputFileName(inputDirectory: string): Promise { const packageJson = await readJSON(path.join(inputDirectory, 'package.json')); return `${packageJson.name || ''}-${packageJson.version}.tgz`; } export default class Pack extends Command { public static description = 'packs a plugin folder into a distributable archive'; public static examples = [`$ flipper-pkg pack path/to/plugin`]; public static flags = { output: flags.string({ char: 'o', default: '.', description: 'Where to output the package, file or directory. Defaults to the current working directory.', }), production: flags.boolean({ description: 'Force env.NODE_ENV=production, enable minification and disable producing source maps.', default: false, }), }; public static args: args.IArg[] = [ { name: 'directory', required: false, default: '.', description: 'Path to plugin package directory to pack. Defaults to the current working directory.', }, ]; public async run() { const {args, flags: parsedFlags} = this.parse(Pack); const stat = await fs.lstat(args.directory); if (!stat.isDirectory()) { this.error(`Plugin source ${args.directory} is not a directory.`); } let output; if (await pathExists(parsedFlags.output)) { const outputStat = await fs.lstat(parsedFlags.output); if (outputStat.isDirectory()) { output = path.resolve( path.join( parsedFlags.output, await deriveOutputFileName(args.directory), ), ); } else { output = parsedFlags.output; } } else { let dir; let file = null; // Treat this as a if (parsedFlags.output.slice(-1) === '/') { dir = parsedFlags.output; } else { dir = path.dirname(parsedFlags.output); file = path.basename(parsedFlags.output); } if (!(await pathExists(dir))) { const answer: {confirm: boolean} = await inquirer.prompt({ default: true, message: `Output directory '${dir}' doesn't exist. Create it?`, name: 'confirm', type: 'confirm', }); if (answer.confirm) { mkdirp(dir); } else { this.error(`Output directory ${dir} not found.`); } } if (file === null) { file = await deriveOutputFileName(args.directory); } output = path.join(dir, file); } const inputDirectory = path.resolve(args.directory); const outputFile = path.resolve(output); this.log(`⚙️ Packing ${inputDirectory} to ${outputFile}...`); cli.action.start('Installing dependencies'); await yarn.install(inputDirectory); cli.action.stop(); cli.action.start(`Compiling`); await runBuild(inputDirectory, parsedFlags.production); cli.action.stop(); cli.action.start(`Packing to ${outputFile}`); await yarn.pack(inputDirectory, outputFile); cli.action.stop(); this.log(`✅ Packed ${inputDirectory} to ${outputFile}`); } }