@storm-stack/core
Version:
A build toolkit and runtime used by Storm Software in TypeScript applications
153 lines (151 loc) • 5.08 kB
JavaScript
import { extendLog, createLog } from './chunk-RDCOIWVB.js';
import { __name } from './chunk-43IZMM3W.js';
import { LogLevelLabel } from '@storm-software/config-tools/types';
import { camelCase } from '@stryke/string-format/camel-case';
import { kebabCase } from '@stryke/string-format/kebab-case';
import { titleCase } from '@stryke/string-format/title-case';
import defu from 'defu';
var Plugin = class {
static {
__name(this, "Plugin");
}
#log;
#primaryKeyFields = [];
/**
* A list of plugin modules required as dependencies by the current Plugin.
*
* @remarks
* These plugins will be called prior to the current Plugin.
*/
dependencies = [];
/**
* The configuration options for the plugin
*
* @remarks
* This is used to store the configuration options for the plugin, which can be accessed by the plugin's methods.
*/
options;
/**
* A list of dependencies that are required for the plugin to work. These dependencies will be installed when Storm Stack CLI is run.
*/
packageDeps = {};
/**
* A property to override the plugin's {@link name} field.
*
* @remarks
* This is useful for plugins that need to have a different name than the default one derived from the class name.
*/
get overrideName() {
return void 0;
}
/**
* The name of the plugin
*
* @remarks
* This is used to identify the plugin's name used in {@link Context.options}, logs, and other output.
*/
get name() {
let name = kebabCase(this.overrideName || this.constructor.name);
if (name.startsWith("plugin-")) {
name = name.replace(/^plugin-/g, "").trim();
}
if (name.endsWith("-plugin")) {
name = name.replace(/-plugin$/g, "").trim();
}
return name;
}
/**
* The primary keys for the plugin's options.
*
* @remarks
* This is used to identify when a two instances of the plugin are the same and can be de-duplicated.
*/
get primaryKeys() {
return this.primaryKeyFields.map((primaryKeyField) => this.options[primaryKeyField]);
}
/**
* Returns true if the plugin is a singleton. Singleton plugins can only be instantiated once (so whenever other plugins specify them as dependencies, they will be de-duplicated).
*
* @remarks
* A plugin is considered a singleton if it has zero primary key option fields defined.
*/
get isSingleton() {
return this.primaryKeyFields.length === 0;
}
/**
* A list of primary keys for the plugin's options.
*
* @remarks
* This is used to identify when a two instances of the plugin are the same and can be de-duplicated.
*/
get primaryKeyFields() {
return this.#primaryKeyFields ?? [];
}
/**
* The identifier for the plugin used in the {@link isSame} method
*
* @remarks
* Child plugins can override this to provide a more or less specific identifier. This is used to identify the plugin's options in {@link Context.options}.
*/
get identifier() {
return camelCase(`${this.name}${this.isSingleton ? "" : `-${this.primaryKeys.join("-")}`}`);
}
/**
* The logger function to use
*/
get log() {
if (!this.#log) {
this.#log = this.options.log ? extendLog(this.options.log, `${titleCase(this.name)} Plugin`) : createLog(`${titleCase(this.name)} Plugin`);
}
return this.#log;
}
/**
* The constructor for the plugin
*
* @param options - The configuration options for the plugin
*/
constructor(options) {
this.options = options;
}
/**
* Checks if the current plugin is the same as another plugin based on primary key fields.
*
* @param plugin - The plugin to compare with.
* @returns `true` if the plugins are the same, `false` otherwise.
*/
isSame(plugin) {
return this.identifier === plugin.identifier || this.name === plugin.name && this.isSingleton && plugin.isSingleton;
}
/**
* Adds hooks to the engine's hook system.
*
* @param hooks - The hooks to add to the engine.
*/
addHooks(hooks) {
hooks.addHooks({
"init:begin": this.#initBegin.bind(this)
});
}
/**
* Initializes the plugin's context with required installations.
*
* @param context - The context to initialize.
*/
async #initBegin(context) {
this.log(LogLevelLabel.TRACE, `Adding required installations for the project.`);
this.options = defu(this.options, context.options.plugins[this.identifier] ?? {});
if (Object.keys(this.packageDeps).length > 0) {
Object.keys(this.packageDeps).forEach((dependency) => {
if (this.packageDeps[dependency] && (this.packageDeps[dependency] === "devDependency" || context.options.projectType === "application")) {
if (dependency.lastIndexOf("@") > 0 && dependency.substring(0, dependency.lastIndexOf("@")) in context.packageDeps) {
delete context.packageDeps[dependency.substring(0, dependency.lastIndexOf("@"))];
}
context.packageDeps[dependency] = this.packageDeps[dependency];
}
});
}
}
};
export { Plugin };
//# sourceMappingURL=chunk-CM2TQ3NN.js.map
//# sourceMappingURL=chunk-CM2TQ3NN.js.map