@rushstack/heft
Version:
Build all your JavaScript projects the same way: A way that works.
150 lines • 7.98 kB
JavaScript
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
import { JsonFile, JsonSchema } from '@rushstack/node-core-library';
import { HeftLifecyclePluginDefinition, HeftTaskPluginDefinition } from './HeftPluginDefinition';
import heftPluginSchema from '../schemas/heft-plugin.schema.json';
const HEFT_PLUGIN_CONFIGURATION_FILENAME = 'heft-plugin.json';
/**
* Loads and validates the heft-plugin.json file.
*/
export class HeftPluginConfiguration {
constructor(heftPluginConfigurationJson, packageRoot, packageName) {
this._heftPluginConfigurationJson = heftPluginConfigurationJson;
this.packageRoot = packageRoot;
this.packageName = packageName;
this._validate(heftPluginConfigurationJson, packageName);
}
/**
* Load the heft-plugin.json file from the specified package.
*/
static async loadFromPackageAsync(packageRoot, packageName) {
const resolvedHeftPluginConfigurationJsonFilename = `${packageRoot}/${HEFT_PLUGIN_CONFIGURATION_FILENAME}`;
let heftPluginConfigurationPromise = HeftPluginConfiguration._pluginConfigurationPromises.get(packageRoot);
if (!heftPluginConfigurationPromise) {
heftPluginConfigurationPromise = (async () => {
const heftPluginConfigurationJson = await JsonFile.loadAndValidateAsync(resolvedHeftPluginConfigurationJsonFilename, HeftPluginConfiguration._jsonSchema);
return new HeftPluginConfiguration(heftPluginConfigurationJson, packageRoot, packageName);
})();
HeftPluginConfiguration._pluginConfigurationPromises.set(packageRoot, heftPluginConfigurationPromise);
}
return await heftPluginConfigurationPromise;
}
/**
* Returns a loaded plugin definition for the provided specifier. Specifiers are normally obtained from the
* heft.json file.
*/
getPluginDefinitionBySpecifier(pluginSpecifier) {
if (!pluginSpecifier.pluginName) {
const pluginDefinitions = [].concat(Array.from(this._getLifecyclePluginDefinitions()), Array.from(this._getTaskPluginDefinitions()));
// Make an attempt at resolving the plugin without the name by looking for the first plugin
if (pluginDefinitions.length > 1) {
throw new Error(`The specified plugin package ${JSON.stringify(pluginSpecifier.pluginPackage)} contains ` +
'multiple plugins. You must specify a plugin name.');
}
return pluginDefinitions[0];
}
else {
// Try resolving to a lifecycle plugin first
const pluginDefinition = this.tryGetLifecyclePluginDefinitionByName(pluginSpecifier.pluginName) ||
this.tryGetTaskPluginDefinitionByName(pluginSpecifier.pluginName);
if (!pluginDefinition) {
throw new Error(`The specified plugin package ${JSON.stringify(pluginSpecifier.pluginPackage)} does not contain ` +
`a plugin named ${JSON.stringify(pluginSpecifier.pluginName)}.`);
}
return pluginDefinition;
}
}
/**
* Returns if the provided plugin definition is a lifecycle plugin definition.
*/
isLifecyclePluginDefinition(pluginDefinition) {
return this._getLifecyclePluginDefinitions().has(pluginDefinition);
}
/**
* Returns if the provided plugin definition is a task plugin definition.
*/
isTaskPluginDefinition(pluginDefinition) {
return this._getTaskPluginDefinitions().has(pluginDefinition);
}
/**
* Returns a loaded lifecycle plugin definition for the provided plugin name. If one can't be found,
* returns undefined.
*/
tryGetLifecyclePluginDefinitionByName(lifecyclePluginName) {
if (!this._lifecyclePluginDefinitionsMap) {
this._lifecyclePluginDefinitionsMap = new Map(Array.from(this._getLifecyclePluginDefinitions()).map((d) => [
d.pluginName,
d
]));
}
return this._lifecyclePluginDefinitionsMap.get(lifecyclePluginName);
}
/**
* Returns a loaded task plugin definition for the provided plugin name. If one can't be found,
* returns undefined.
*/
tryGetTaskPluginDefinitionByName(taskPluginName) {
if (!this._taskPluginDefinitionsMap) {
this._taskPluginDefinitionsMap = new Map(Array.from(this._getTaskPluginDefinitions()).map((d) => [d.pluginName, d]));
}
return this._taskPluginDefinitionsMap.get(taskPluginName);
}
_getLifecyclePluginDefinitions() {
if (!this._lifecyclePluginDefinitions) {
this._lifecyclePluginDefinitions = new Set();
for (const lifecyclePluginDefinitionJson of this._heftPluginConfigurationJson.lifecyclePlugins || []) {
this._lifecyclePluginDefinitions.add(HeftLifecyclePluginDefinition.loadFromObject({
heftPluginDefinitionJson: lifecyclePluginDefinitionJson,
packageRoot: this.packageRoot,
packageName: this.packageName
}));
}
}
return this._lifecyclePluginDefinitions;
}
/**
* Task plugin definitions sourced from the heft-plugin.json file.
*/
_getTaskPluginDefinitions() {
if (!this._taskPluginDefinitions) {
this._taskPluginDefinitions = new Set();
for (const taskPluginDefinitionJson of this._heftPluginConfigurationJson.taskPlugins || []) {
this._taskPluginDefinitions.add(HeftTaskPluginDefinition.loadFromObject({
heftPluginDefinitionJson: taskPluginDefinitionJson,
packageRoot: this.packageRoot,
packageName: this.packageName
}));
}
}
return this._taskPluginDefinitions;
}
_validate(heftPluginConfigurationJson, packageName) {
var _a, _b;
if (!((_a = heftPluginConfigurationJson.lifecyclePlugins) === null || _a === void 0 ? void 0 : _a.length) &&
!((_b = heftPluginConfigurationJson.taskPlugins) === null || _b === void 0 ? void 0 : _b.length)) {
throw new Error(`The specified plugin package ${JSON.stringify(packageName)} does not contain any plugins.`);
}
// Prevent duplicate plugin names. This is done because parameter scopes default to the plugin name
// when none are provided, and we want to avoid conflicting parameter scopes. Additionally, scoped loggers
// on lifecycle plugins are mapped to "[lifecycle:<pluginName>]", and scoped loggers must be unique.
const lifecyclePluginNames = new Set();
for (const lifecyclePluginDefinitionJson of heftPluginConfigurationJson.lifecyclePlugins || []) {
if (lifecyclePluginNames.has(lifecyclePluginDefinitionJson.pluginName)) {
throw new Error(`Duplicate plugin name: ${lifecyclePluginDefinitionJson.pluginName}`);
}
lifecyclePluginNames.add(lifecyclePluginDefinitionJson.pluginName);
}
const taskPluginNames = new Set();
for (const taskPluginDefinitionJson of heftPluginConfigurationJson.taskPlugins || []) {
// Also check that the name doesn't conflict with the lifecycle plugins
if (taskPluginNames.has(taskPluginDefinitionJson.pluginName) ||
lifecyclePluginNames.has(taskPluginDefinitionJson.pluginName)) {
throw new Error(`Duplicate plugin name: ${taskPluginDefinitionJson.pluginName}`);
}
taskPluginNames.add(taskPluginDefinitionJson.pluginName);
}
}
}
HeftPluginConfiguration._jsonSchema = JsonSchema.fromLoadedObject(heftPluginSchema);
HeftPluginConfiguration._pluginConfigurationPromises = new Map();
//# sourceMappingURL=HeftPluginConfiguration.js.map