constructor()

in components/base/packages/serverless-solution-commands/lib/serverless-solution-commands-plugin.js [37:191]


  constructor(serverless, options) {
    this.serverless = serverless;
    this.options = options;

    // set the cwd to the directory from where the sls command was invoked
    this.cwd = path.normalize(path.resolve('.'));

    this.serverlessSolutionCommands = new ServerlessSolutionCommands(this);
    this.cli = getCommandLogger(this.serverless);

    // An object containing default solution level commands that this serverless plugin adds
    // other plugins registered via extension point "commands" can contribute their own commands
    const defaultCommandsMap = {
      // -- COMMANDS to assemble the solution by integrating components
      'solution-assemble': {
        usage:
          "First, uses the assembly process to create the solution's deployable units. Then installs all package dependencies in the workspace based on the package lock. Finally, builds all packages.",
        lifecycleEvents: ['assemble'],
        options: {
          'no-install': {
            usage: 'Skips installing dependencies after performing assembly tasks.',
            required: false,
          },
          'update-package-lock': {
            usage:
              'Unlike the default behavior without this flag, when installing dependencies the script will NOT fail if the lockfile is out of sync with the manifest, an update is needed, or not present. And it WILL generate a new lockfile if one does not exist, or update an existing lockfile if one already exists.',
            required: false,
          },
        },
      },

      // -- COMMANDS that run against pnpm workspace packages
      'solution-build': {
        usage: 'Builds all packages of the solution',
        lifecycleEvents: ['build'],
        options: {},
      },
      'solution-build-watch': {
        usage: 'Starts build watch across all packages of the solution',
        lifecycleEvents: ['buildWatch'],
        options: {},
      },
      'solution-unit-test': {
        usage: 'Runs unit tests for all packages of the solution',
        lifecycleEvents: ['unitTest'],
        options: {},
      },
      'solution-integration-test': {
        usage: 'Runs integration tests for all packages of the solution',
        lifecycleEvents: ['integrationTest'],
        options: {},
      },
      'solution-lint': {
        usage: 'Runs static code analysis i.e., lint npm script for all packages of the solution',
        lifecycleEvents: ['lint'],
        options: {},
      },

      // Commands that run against deployable units. Each deployable unit is a separate Serverless Framework Project.
      'solution-package': {
        usage: 'Packages all deployable units of the solution',
        lifecycleEvents: ['package'],
        options: {},
      },
      'solution-deploy': {
        usage: 'Deploys all deployable units of the solution',
        lifecycleEvents: ['deploy'],
        options: {
          cfnLintWarnOnly: {
            usage: 'When cfn-lint runs, do not break the deployment on errors',
            required: false,
          },
        },
      },
      'solution-info': {
        usage: 'Prints important information collected from all deployable units of the solution',
        lifecycleEvents: ['info'],
        options: {},
      },
      'solution-remove': {
        usage: 'Un-deploys all deployable units of the solution',
        lifecycleEvents: ['remove'],
        options: {},
      },
    };

    const commandsInfo = getCommandsInfo(this);
    const pluginRegistry = commandsInfo.getPluginRegistry();
    const pluginRegistryUtil = new PluginRegistryUtil(pluginRegistry);

    this.commands = pluginRegistryUtil.visitPlugins(
      'commands',
      'getCommands',
      { payload: defaultCommandsMap },
      this,
      pluginRegistry,
    );

    /**
     * An object containing default map of command lifecycle events and their hooks (handlers)
     * Serverless Plugin expects the "hooks" object to contain lifecycle events mapped to one and
     * only one hook function.
     * We want to give all plugins registered to the extension point "commands" give a chance to
     * provide their own hooks to each command lifecycle so we have each lifecycle event mapped
     * to an array of hook functions instead of just one function.
     */
    const defaultHooks = {
      'solution-assemble:assemble': [this.assemble.bind(this)],

      'solution-build:build': [this.build.bind(this)],
      'solution-build-watch:buildWatch': [this.buildWatch.bind(this)],
      'solution-unit-test:unitTest': [this.unitTest.bind(this)],
      'solution-integration-test:integrationTest': [this.integrationTest.bind(this)],
      'solution-lint:lint': [this.lint.bind(this)],

      'solution-package:package': [this.package.bind(this)],
      'solution-deploy:deploy': [this.deploy.bind(this)],
      'solution-info:info': [this.info.bind(this)],
      'solution-remove:remove': [this.remove.bind(this)],
    };
    const hooksFromAllPlugins = pluginRegistryUtil.visitPlugins(
      'commands',
      'getHooks',
      { payload: defaultHooks },
      this,
      pluginRegistry,
    );
    this.hooks = _.transform(
      hooksFromAllPlugins,
      (result, value, key) => {
        const hookFns = value;
        if (_.isArray(hookFns)) {
          // the hooks may be an array of hook functions but Serverless Framework expects
          // only one hook function so create a wrapper function that will call each hook
          // function in sequence and pass the Serverless Framework plugin instance
          // (i.e., "this") as an argument to the hook function
          result[key] = async () => {
            // call each hook function in strict order
            for (let i = 0; i < hookFns.length; i += 1) {
              const hookFn = hookFns[i];
              // We need to await the hook method call in strict sequence
              // so awaiting in loop
              // eslint-disable-next-line no-await-in-loop
              await hookFn(this);
            }
          };
        } else {
          // if the hook function (value) is not an array of functions then set it to the hook object (result) "as is"
          result[key] = value;
        }
        return result;
      },
      {},
    );
  }