UNPKG

@sfdx-falcon/generator

Version:

Extends Yeoman's Generator class, adding customized support for SFDX-Falcon specific tools and capabilities. Part of the SFDX-Falcon Library.

273 lines (272 loc) 15.5 kB
/** * @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/generator/src/project-generator.ts * @summary Exports `SfdxFalconProjectGenerator` for use with custom Yeoman generators that * focus on standing up local projects. * @description Exports an abstract class that extends the SFDX-Falcon Library's `SfdxFalconGenerator` * class, adding customized support for tools and capabilities that make it easier * to stand up a local git-based project. */ import * as Generator from 'yeoman-generator'; import { SfdxEnvironment } from '@sfdx-falcon/environment'; import { SfdxFalconInterview } from '@sfdx-falcon/interview'; import { SfdxFalconResult } from '@sfdx-falcon/status'; import { GeneratorStatus } from '@sfdx-falcon/status'; import { GeneratorOptions } from '@sfdx-falcon/command'; import { SfdxEnvironmentRequirements } from '@sfdx-falcon/environment'; import { SfdxFalconTableData } from '@sfdx-falcon/status'; import { JsonMap } from '@sfdx-falcon/types'; import { StyledMessage } from '@sfdx-falcon/types'; /** * Interface. Collection of objects that represent the Answers that will be leveraged by an * `SfdxFalconGenerator`. */ export interface Answers<T extends JsonMap> { /** Required. The set of default answers for the Interview of an `SfdxFalconGenerator`. */ default: T; /** Required. The set of answers provided by the user for the Interview of an `SfdxFalconGenerator`. */ user: T; /** Required. The set of final answers for the Interview of an `SfdxFalconGenerator`. In other words, the merging of User and Default answers in case the user did not supply some answers. */ final: T; /** Optional. Special set of answers. Provides a means to send meta values (usually template tags) to EJS templates. */ meta?: T; } /** * Interface. Collection of message strings that are displayed at various times during the execution * of an `SfdxFalconGenerator`. */ export interface GeneratorMessage { /** Required. Message shown to the user before exiting the initializing() run-loop function. */ confirmation: string; /** Required. Message that will be displayed by the yosay "Yeoman" ASCII art when the generator is loaded. */ opening: string; /** Required. Message that will be displayed by the `end()` run-loop function upon successful completion of the Generator. */ success: string; /** Required. Message that will be displayed by the `end()` run-loop function upon failure of the Generator. */ failure: string; /** Required. Message that will be displayed by the `end()` run-loop function upon partial success of the Generator. */ warning: string; } /** * Interface. Collection of requirements for the initialization process of an `SfdxFalconGenerator`. */ export interface GeneratorRequirements { gitEnvReqs: object; sfdxEnvReqs: SfdxEnvironmentRequirements; localEnvReqs: object; } /** * Interface. Collection of status `boolean` variables that reflect the status of various Yeoman * run-loop functions. */ export interface RunLoopStatus { /** Required. Indicates that the `initializing()` run-loop function has completed successfully. */ initializingComplete: boolean; /** Required. Indicates that the `prompting()` run-loop function has completed successfully. */ promptingComplete: boolean; /** Required. Indicates that the `configuring()` run-loop function has completed successfully. */ configuringComplete: boolean; /** Required. Indicates that the `writing()` run-loop function has completed successfully. */ writingComplete: boolean; /** Required. Indicates that the `install()` run-loop function has completed successfully. */ installComplete: boolean; /** Required. Indicates that the `end()` run-loop function completed successfully. */ endComplete: boolean; } /** * @class SfdxFalconGenerator * @extends Generator * @summary Abstract base class class for building Yeoman Generators for SFDX-Falcon commands. * @description Classes that extend `SfdxFalconGenerator` must provide a type parameter to * ensure that the "answers" family of member variables (`defaultAnswers`, * `userAnswers`, `metaAnswers`, and `finalAnswers`) has the appropriate interface * type which defines the answers that are relevant to a concrete child class. * @public @abstract */ export declare abstract class SfdxFalconGenerator<T extends JsonMap> extends Generator { /** Name of the CLI command that kicked off this Generator. */ protected readonly commandName: string; /** Version of the plugin that's running this Generator. Taken dynamically from `package.json`. */ protected readonly pluginVersion: string; /** Custom `falcon` options key from `package.json`. Can be used to read package-global settings that a plugin developer chooses to add to `package.json`. */ protected readonly falcon: JsonMap; /** Specifies the various messages used by this Generator. */ protected readonly generatorMessage: GeneratorMessage; /** Tracks the name (type) of Generator being run, eg. `clone-appx-package-project`. */ protected readonly generatorType: string; /** Tracks the path to the of the source file containing the Generator being run, eg `../../generators`. */ protected readonly generatorPath: string; /** Used to keep track of status and to return messages to the caller. */ protected readonly generatorStatus: GeneratorStatus; /** Used to keep track of status and to return messages to the caller. */ protected readonly generatorResult: SfdxFalconResult; /** Determines which initialization tasks are performed during the Default Initialization process. */ protected readonly generatorReqs: GeneratorRequirements; /** Tracks the status of various run-loop functions. */ protected readonly runLoopStatus: RunLoopStatus; /** Collection of objects that represent the Answers to questions that will be asked during the Interview. */ protected readonly answers: Answers<T>; /** Used to share data between the Generator, Inqurirer Prompts, and Listr Tasks. */ protected readonly sharedData: object; /** Holds the `SfdxFalconInterview` object that will be run during the `prompting()` run-loop function. */ protected userInterview: SfdxFalconInterview<T>; /** Represents the SFDX Environment. */ protected sfdxEnv: SfdxEnvironment; /** * @constructs SfdxFalconGenerator * @param {string|string[]} args Required. Array of arguments that are * passed to this generator by Yeoman if the generator is being * invoked from the command line. Passed directly through to * the superclass constructor without modification. * @param {GeneratorOptions} opts Required. Object containing options * that help specify how a specific generator is run. These * options are set when external code uses a Yeoman Environment * to `run()` a Generator that's derived from this class. * @description Constructs an `SfdxFalconGenerator` object. * @public */ constructor(args: string | string[], opts: GeneratorOptions, reqs: GeneratorRequirements); /** * @method initializing * @returns {Promise<void>} * @description STEP ONE in the Yeoman run-loop. Uses Yeoman's "initializing" * run-loop priority. This is a "default" implementation and * should work for most SFDX-Falcon use cases. It must be called * from inside the initializing() method of the child class. * @public @async */ /** * @method prompting * @param {StyledMessage} [preInterviewMessage] Optional. Message to * display to the user before the Interview starts. * @param {StyledMessage} [postInterviewMessage] Optional. Message to * display to the user after the Interview ends. * @returns {Promise<void>} * @description STEP TWO in the Yeoman run-loop. Interviews the User to get * information needed by the "writing" and "installing" phases. * This is a "default" implementation and should work for most * SFDX-Falcon use cases. It must be called from inside the * prompting() method of the child class. * @public @async */ prompting(preInterviewMessage?: StyledMessage, postInterviewMessage?: StyledMessage): Promise<void>; /** * @method configuring * @returns {void} * @description STEP THREE in the Yeoman run-loop. Perform any pre-install * configuration steps based on the answers provided by the User. * This is a "default" implementation and should work for most * SFDX-Falcon use cases. It must be called from inside the * configuring() method of the child class. * @protected */ configuring(): Promise<void>; /** * @method writing * @returns {Promise<void>} * @description STEP FOUR in the Yeoman run-loop. Typically, this is where * you perform filesystem writes, git clone operations, etc. * This is a "default" implementation and should work for most * SFDX-Falcon use cases. It must be called from inside the * writing() method of the child class. * @public @async */ writing(): Promise<void>; /** * @method install * @returns {Promise<void>} * @description STEP FIVE in the Yeoman run-loop. Typically, this is where * you perform operations that must happen AFTER files are * written to disk. For example, if the "writing" step downloaded * an app to install, the "install" step would run the * installation. This is a "default" implementation and should * work for most SFDX-Falcon use cases. It must be called from * inside the install() method of the child class. * @public @async */ install(): Promise<void>; /** * @method end * @returns {Promise<void>} * @description STEP SIX in the Yeoman run-loop. This is the FINAL step that * Yeoman runs and it gives us a chance to do any post-Yeoman * updates and/or cleanup. This is a "default" implementation * and should work for most SFDX-Falcon use cases. It must be * called from inside the end() method of the child class. * @public @async */ end(): Promise<void>; /** Builds a complete `SfdxFalconInterview` object, which may include zero or more confirmation groupings. */ protected abstract _buildInterview(): SfdxFalconInterview<T>; /** Creates Interview Answers table data. Can be used to render an `SfdxFalconTable` object. */ protected abstract _buildInterviewAnswersTableData(userAnswers: T): Promise<SfdxFalconTableData>; /** STEP ONE in the Yeoman run-loop. Uses Yeoman's "initializing" run-loop priority. */ protected abstract _initializing(): Promise<void>; /** STEP TWO in the Yeoman run-loop. Interviews the User to get information needed by the `_writing()` and `_install()` functions. */ protected abstract _prompting(): Promise<void>; /** STEP THREE in the Yeoman run-loop. Perform any pre-install configuration steps based on the answers provided by the User. */ protected abstract _configuring(): Promise<void>; /** STEP FOUR in the Yeoman run-loop. Typically, this is where you perform filesystem writes, git clone operations, etc. */ protected abstract _writing(): Promise<void>; /** STEP FIVE in the Yeoman run-loop. Typically, this is where you perform operations that must happen AFTER files are written to disk. For example, if the `_writing()` step downloaded an app to install, the `_install()` step would run the installation. */ protected abstract _install(): Promise<void>; /** STEP SIX in the Yeoman run-loop. This is the FINAL step that Yeoman runs and it gives us a chance to do any post-Yeoman updates and/or cleanup. */ protected abstract _end(): Promise<void>; /** * @method _cloneRepository * @returns {Promise<string>} Local path into which the Git Repository * was cloned. If the clone operation is unsuccessful, this * will return an empty string. * @description Clones a remote Git Repository per information specified * during by the command and/or during their interview. Returns * the local path to which the Git Repository was cloned, or * an empty string otherwise. * @protected @async */ /** * @method _executeInitializationTasks * @returns {Promise<void>} * @description Runs a series of initialization tasks using the Listr UX/Task * Runner module. Listr provides a framework for executing tasks * while also providing an attractive, realtime display of task * status (running, successful, failed, etc.). * @protected @async */ /** * @method _finalizeGitActions * @param {string} destinationRoot Required. * @param {boolean} isInitializingGit Required. * @param {string} gitRemoteUri Required. * @param {string} projectAlias Required. * @returns {Promise<void>} * @description Intended to run after _finalizeProjectCreation() during the * Yeoman "writing" phase. Initializes local Git repo, and will * even try to attach a Git remote if specified by the user. * @protected @async */ /** * @method _finalizeProjectCloning * @returns {boolean} Returns FALSE if the project was aborted. * @description Intended to run after the Yeoman "writing" phase. Has logic * that ensures the Generator wasn't aborted, and then carries * out finalization tasks that are generic to "cloning" * Generators. Returns a boolean so the calling class can decide * whether or not to perform additional actions. * @protected */ protected _finalizeProjectCloning(): boolean; /** * @method _finalizeProjectCreation * @returns {boolean} Returns FALSE if the project was aborted. * @description Intended to run after the Yeoman "writing" phase. Has logic * that ensures the Generator wasn't aborted, and then carries * out finalization tasks that are generic to "creation" * Generators. Returns a boolean so the calling class can decide * whether or not to perform additional actions. * @protected */ protected _finalizeProjectCreation(): boolean; }