UNPKG

@sfdx-falcon/command

Version:

Contains SFDX-Falcon flavored extensions to @sfdx/command. Part of the SFDX-Falcon Library.

153 lines 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); //─────────────────────────────────────────────────────────────────────────────────────────────────┐ /** * @author Vivek M. Chawla <@VivekMChawla> * @copyright 2019, Vivek M. Chawla / Salesforce. All rights reserved. * @license BSD-3-Clause For full license text, see the LICENSE file in the repo root or * `https://opensource.org/licenses/BSD-3-Clause` * @file packages/command/src/sfdx-falcon-generator-command.ts * @summary Exports an abstract class that adds support for running a Yeoman Generator inside * of an SFDX-Falcon flavored Salesforce CLI command. * @description Exports an abstract class that adds support for running a Yeoman Generators inside * of an SFDX-Falcon flavored Salesforce CLI command. Generators are specialized * classes that define user interaction and task execution in a standardized mannner. * * Generator classes must be present in your package's source tree and must be * included when publishing your CLI plugin. The Generator's file name must match * string passed to the `generatorType` option. For example, if * `generatorType==='my-generator'`, there MUST be a corresponding source file * somewhere in your project named `my-generator.ts`. */ //─────────────────────────────────────────────────────────────────────────────────────────────────┘ // Import External Libraries, Modules, and Types const path = require("path"); // Node.js native path library. const yeoman = require("yeoman-environment"); // Facilitates the discovery and execution of a Yeoman Generator. // Import SFDX-Falcon Libraries const validator_1 = require("@sfdx-falcon/validator"); // Library of Type Validation helper functions. // Import SFDX-Falcon Classes & Functions const debug_1 = require("@sfdx-falcon/debug"); // Class. Provides custom "debugging" services (ie. debug-style info to console.log()). const error_1 = require("@sfdx-falcon/error"); // Class. Extends SfdxError to provide specialized error structures for SFDX-Falcon modules. const status_1 = require("@sfdx-falcon/status"); // Class. Provides a mechanism for sharing data among SFDX-Falcon code structures. // Import Internal Modules const sfdx_falcon_command_1 = require("./sfdx-falcon-command"); // Abstract Class. Custom SFDX-Falcon base class for SFDX Commands. // Import Internal Types const sfdx_falcon_command_2 = require("./sfdx-falcon-command"); // Enum. Represents the types of SFDX-Falcon Commands. // Set the File Local Debug Namespace const dbgNs = '@sfdx-falcon:command:generator'; debug_1.SfdxFalconDebug.msg(`${dbgNs}:`, `Debugging initialized for ${dbgNs}`); //─────────────────────────────────────────────────────────────────────────────────────────────────┐ /** * @class SfdxFalconGeneratorCommand * @extends SfdxFalconCommand * @summary Abstract base class class for building Salesforce CLI commands that use Yeoman. * @description Classes that extend `SfdxFalconGeneratorCommand` will be able to run any Generator * defined in the `src/generators` directory. The file name in `src/generators` should * match the `generatorType` string passed into `runYeomanGenerator()`. For example, * if `generatorType==='my-generator'`, then there MUST be a `.TS` script file located * at `src/generators/my-generator.ts`. * @public @abstract */ //─────────────────────────────────────────────────────────────────────────────────────────────────┘ class SfdxFalconGeneratorCommand extends sfdx_falcon_command_1.SfdxFalconCommand { //───────────────────────────────────────────────────────────────────────────┐ /** * @constructs SfdxFalconGeneratorCommand * @param {any} argv Required. Part of the `oclif` command run process. * Must be passed **unmodified** to the superclass. * @param {any} config Required. Part of the `oclif` command run process. * Must be passed **unmodified** to the superclass. * @description Constructs an `SfdxFalconGeneratorCommand` object. * @private */ //───────────────────────────────────────────────────────────────────────────┘ constructor(argv, config) { // Call the parent constructor. Make sure it knows this is a GENERATOR type command. // DO NOT MODIFY `argv` or `config` variables! super(argv, config, sfdx_falcon_command_2.SfdxFalconCommandType.GENERATOR); } //───────────────────────────────────────────────────────────────────────────┐ /** * @function runGenerator * @param {GeneratorOptions} opts Required. Options object that * specifies which Generator to run and any additional custom * options that should be passed to the Generator, eg. user * supplied arguments and flags. * @returns {Promise<SfdxFalconResult>} Returns a promise that resolves * and rejects with an SFDX-Falcon Result. The output of this * function is intended to be consumed by the `onSuccess()` and * `onError()` methods. * @description Runs the `SfdxFalconGenerator` specified by the `generatorPath` * and `generatorType` values supplied by the caller in the * `GeneratorOptions` object. Will pass custom options to the * Generator, if provided. * @protected @async */ //───────────────────────────────────────────────────────────────────────────┘ async runGenerator(opts) { // Define the function-local debug namespace and reflect arguments. const funcName = `runGenerator`; const dbgNsLocal = `${dbgNs}:${funcName}`; debug_1.SfdxFalconDebug.obj(`${dbgNsLocal}:arguments:`, arguments); // Validate the REQUIRED options. validator_1.TypeValidator.throwOnEmptyNullInvalidObject(opts, `${dbgNsLocal}`, `GeneratorOptions`); validator_1.TypeValidator.throwOnEmptyNullInvalidString(opts.commandName, `${dbgNsLocal}`, `GeneratorOptions.commandName`); validator_1.TypeValidator.throwOnEmptyNullInvalidString(opts.generatorPath, `${dbgNsLocal}`, `GeneratorOptions.generatorPath`); validator_1.TypeValidator.throwOnEmptyNullInvalidString(opts.generatorType, `${dbgNsLocal}`, `GeneratorOptions.generatorType`); // Validate the OPTIONAL options. if (opts.generatorResult) validator_1.TypeValidator.throwOnNullInvalidInstance(opts.generatorResult, status_1.SfdxFalconResult, `${dbgNsLocal}`, `GeneratorOptions.generatorResult`); if (opts.customOpts) validator_1.TypeValidator.throwOnEmptyNullInvalidObject(opts.customOpts, `${dbgNsLocal}`, `GeneratorOptions.customOpts`); // If one wasn't provided, initialize a GENERATOR Result. Pass it to the Generator so we can figure out how things went. if (typeof opts.generatorResult === 'undefined') { opts.generatorResult = new status_1.SfdxFalconResult(opts.generatorType, "GENERATOR" /* GENERATOR */, { startNow: true, bubbleError: false, bubbleFailure: false }); // Do not bubble failures. } debug_1.SfdxFalconDebug.obj(`${dbgNsLocal}:opts:`, opts); // Create a Yeoman environment. const yeomanEnv = yeoman.createEnv(); // Register a generator with the Yeoman environment, based on generatorType. yeomanEnv.register(require.resolve(path.join(opts.generatorPath, opts.generatorType)), `sfdx-falcon:${opts.generatorType}`); // Run the Yeoman Generator. return new Promise((resolve, reject) => { yeomanEnv.run(`sfdx-falcon:${opts.generatorType}`, opts, (generatorError) => { if (generatorError) { // If the Generator Error is the same SfdxFalconResult that we passed into the Generator, just reject it. if (generatorError === opts.generatorResult) { return reject(generatorError); } // Declare an SFDX-Falcon Error that will be defined differently based on what we got back from the Generator. let sfdxFalconError = null; // If the Generator Error is an Error, mark the Generator Result as an Error and reject it. if (generatorError instanceof Error) { sfdxFalconError = new error_1.SfdxFalconError(`Generator '${opts.generatorType}' failed. ${generatorError.message}`, `GeneratorError`, `${dbgNsLocal}`, generatorError); opts.generatorResult.error(sfdxFalconError); return reject(opts.generatorResult); } // If the Generator Error is an SfdxFalconResult, craft an SfdxFalconError, mark the Generator Result as Error, then reject it. if (generatorError instanceof status_1.SfdxFalconResult) { sfdxFalconError = new error_1.SfdxFalconError(`Generator '${opts.generatorType}' failed` + (generatorError.errObj ? `. ${generatorError.errObj.message}` : ` with an unknown error.`), `GeneratorResultError`, `${dbgNsLocal}`, generatorError.errObj); opts.generatorResult.addChild(generatorError); opts.generatorResult.error(sfdxFalconError); return reject(opts.generatorResult); } // If we get here, it means a completely unexpected result came back from the Generator. sfdxFalconError = new error_1.SfdxFalconError(`Generator '${opts.generatorType}' failed with an unexpected result. See error.details for more information.`, `UnexpectedGeneratorFailure`, `${dbgNsLocal}`, null, generatorError); opts.generatorResult.error(sfdxFalconError); return reject(opts.generatorResult); } else { // No Generator Error means that the Generator was successful. opts.generatorResult.success(); return resolve(opts.generatorResult); } }); }); } } exports.SfdxFalconGeneratorCommand = SfdxFalconGeneratorCommand; //# sourceMappingURL=sfdx-falcon-generator-command.js.map