UNPKG

@rushstack/heft

Version:

Build all your JavaScript projects the same way: A way that works.

138 lines 5.65 kB
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. import * as path from 'node:path'; import { InternalError, JsonSchema } from '@rushstack/node-core-library'; export class HeftPluginDefinitionBase { constructor(options) { this._heftPluginDefinitionJson = options.heftPluginDefinitionJson; this._pluginPackageName = options.packageName; this._resolvedEntryPoint = path.resolve(options.packageRoot, this._heftPluginDefinitionJson.entryPoint); // Ensure that the plugin parameters are unique const seenParameters = new Set(); for (const parameter of this.pluginParameters) { if (seenParameters.has(parameter.longName)) { throw new Error(`Parameter ${JSON.stringify(parameter.longName)} is defined multiple times by the providing ` + `plugin ${JSON.stringify(this.pluginName)} in package ` + `${JSON.stringify(this.pluginPackageName)}.`); } seenParameters.add(parameter.longName); } // Unfortunately loading the schema is a synchronous process. if (options.heftPluginDefinitionJson.optionsSchema) { const resolvedSchemaPath = path.resolve(options.packageRoot, options.heftPluginDefinitionJson.optionsSchema); this._optionsSchema = JsonSchema.fromFile(resolvedSchemaPath); } } /** * The package name containing the target plugin. */ get pluginPackageName() { return this._pluginPackageName; } /** * The name of the target plugin. */ get pluginName() { return this._heftPluginDefinitionJson.pluginName; } /** * The resolved entry point to the plugin. */ get entryPoint() { return this._resolvedEntryPoint; } /** * The scope for all parameters defined by this plugin. */ get pluginParameterScope() { // Default to the plugin name for the parameter scope. Plugin names should be unique within any run // of Heft. Additionally, plugin names have the same naming restrictions as parameter scopes so can // be used without modification. return this._heftPluginDefinitionJson.parameterScope || this.pluginName; } /** * The parameters that are defined for this plugin. */ get pluginParameters() { return this._heftPluginDefinitionJson.parameters || []; } /** * Load the plugin associated with the definition. */ async loadPluginAsync(logger) { // Do not memoize the plugin here, since we want a new instance of the plugin each time it is loaded // from the definition let heftPlugin; const entryPointPath = this.entryPoint; try { const loadedPluginModule = await import(entryPointPath); const heftPluginConstructor = loadedPluginModule.default || loadedPluginModule; heftPlugin = new heftPluginConstructor(); } catch (e) { const error = e; if (error.message === 'heftPluginConstructor is not a constructor') { // Common error scenario, give a more helpful error message throw new Error(`Could not load plugin from "${entryPointPath}": The target module does not ` + 'export a plugin class with a parameterless constructor.'); } else { throw new InternalError(`Could not load plugin from "${entryPointPath}": ${error}`); } } if (!heftPlugin) { throw new InternalError(`Plugin ${JSON.stringify(this.pluginName)} loaded from "${entryPointPath}" is null or undefined.`); } logger.terminal.writeVerboseLine(`Loaded plugin from "${entryPointPath}"`); if (typeof heftPlugin.apply !== 'function') { throw new InternalError(`The plugin ${JSON.stringify(this.pluginName)} loaded from "${entryPointPath}" ` + 'doesn\'t define an "apply" function.'); } return heftPlugin; } /** * Validate the provided plugin options against the plugin's options schema, if one is provided. */ validateOptions(options) { if (this._optionsSchema) { try { this._optionsSchema.validateObject(options || {}, ''); } catch (error) { throw new Error(`Provided options for plugin ${JSON.stringify(this.pluginName)} did not match the provided ` + `plugin schema.\n${error}`); } } } } export class HeftLifecyclePluginDefinition extends HeftPluginDefinitionBase { /** * Load a lifecycle plugin definition given the provided plugin definition options. */ static loadFromObject(options) { return new HeftLifecyclePluginDefinition(options); } /** * {@inheritDoc HeftPluginDefinitionBase.loadPluginAsync} * @override */ loadPluginAsync(logger) { return super.loadPluginAsync(logger); } } export class HeftTaskPluginDefinition extends HeftPluginDefinitionBase { /** * Load a task plugin definition given the provided plugin definition options. */ static loadFromObject(options) { return new HeftTaskPluginDefinition(options); } /** * {@inheritDoc HeftPluginDefinitionBase.loadPluginAsync} * @override */ loadPluginAsync(logger) { return super.loadPluginAsync(logger); } } //# sourceMappingURL=HeftPluginDefinition.js.map