kist
Version:
Package Pipeline Processor
181 lines (180 loc) • 6.87 kB
JavaScript
;
// ============================================================================
// Import
// ============================================================================
Object.defineProperty(exports, "__esModule", { value: true });
exports.ActionRegistry = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const CoreActions_1 = require("../../actions/CoreActions");
const AbstractProcess_1 = require("../abstract/AbstractProcess");
// ============================================================================
// Class
// ============================================================================
/**
* ActionRegistry is a singleton registry for step actions, mapping action
* names to their corresponding classes. This registry allows dynamic
* resolution of step actions within the pipeline and supports custom
* developer integrations.
*/
class ActionRegistry extends AbstractProcess_1.AbstractProcess {
// Constructor
// ========================================================================
/**
* Constructs an ActionRegistry instance and automatically registers core
* actions. The constructor is private to enforce the singleton pattern.
*/
constructor() {
// Initialize logging through AbstractProcess
super();
this.registry = new Map();
// Automatically register core actions
this.registerCoreActions();
this.discoverPlugins();
this.logInfo("ActionRegistry initialized.");
}
// Singleton Methods
// ========================================================================
/**
* Initializes the singleton instance of ActionRegistry.
* Should only be called once during application startup.
*
* @throws Error if the registry has already been initialized.
*/
static initialize() {
if (ActionRegistry.instance) {
throw new Error("ActionRegistry has already been initialized.");
}
ActionRegistry.instance = new ActionRegistry();
}
/**
* Retrieves the singleton instance of ActionRegistry, initializing it if
* necessary.
*
* @returns The ActionRegistry instance.
*/
static getInstance() {
if (!ActionRegistry.instance) {
ActionRegistry.instance = new ActionRegistry();
}
return ActionRegistry.instance;
}
/**
* Resets the singleton instance of ActionRegistry.
* This is useful for testing or resetting the registry state during
* runtime.
*/
static resetInstance() {
ActionRegistry.instance = null;
}
// Instance Methods
// ========================================================================
/**
* Registers a new action in the registry.
*
* @param actionClass - The class implementing `ActionInterface`.
* @throws Error if the action name is already registered or missing.
*/
registerAction(actionClass) {
const actionInstance = new actionClass();
const name = actionInstance.name;
if (!name || typeof name !== "string") {
throw new Error(`[ActionRegistry] Action class must have a valid 'name' property.`);
}
if (this.registry.has(name)) {
throw new Error(`[ActionRegistry] Action "${name}" is already registered.`);
}
this.registry.set(name, actionClass);
this.logInfo(`Action "${name}" registered successfully.`);
}
/**
* Retrieves a step action class from the registry.
* This method looks up an action by name and returns the corresponding
* class that implements the ActionInterface.
*
* @param name - The name of the action to retrieve.
* @returns The action class constructor if found, or undefined if no such
* action is registered.
*/
getAction(name) {
// Validate the input name
if (!name || typeof name !== "string") {
this.logWarn(`Invalid action name requested: "${name}".`);
return undefined;
}
// Retrieve the action from the registry
const action = this.registry.get(name);
// Log a warning if the action is not found
if (!action) {
this.logWarn(`Action "${name}" not found in the registry.`);
}
else {
this.logDebug(`Retrieved action "${name}" from the registry.`);
}
return action;
}
/**
* Lists all registered step actions.
* Provides a utility to view currently registered actions, useful for
* debugging and validation.
*
* @returns An array of registered action names.
*/
listRegisteredActions() {
this.logDebug("Listing all registered actions.");
return Array.from(this.registry.keys());
}
/**
* Pre-registers core actions that are included with the pipeline by
* default. Developers can extend this by registering additional custom
* actions as needed.
*/
registerCoreActions() {
Object.values(CoreActions_1.coreActions).forEach((actionClass) => {
this.registerAction(actionClass);
});
this.logInfo("Core actions registered successfully.");
}
discoverPlugins() {
this.logInfo("Discovering external plugins...");
const nodeModulesPath = (0, path_1.join)(process.cwd(), "node_modules");
const pluginPrefix = "@kist/plugin-";
try {
const directories = (0, fs_1.readdirSync)(nodeModulesPath, {
withFileTypes: true,
});
for (const dir of directories) {
if (dir.isDirectory() && dir.name.startsWith(pluginPrefix)) {
const pluginPath = (0, path_1.join)(nodeModulesPath, dir.name);
const plugin = require(pluginPath).default;
if (plugin &&
typeof plugin.registerActions === "function") {
const actions = plugin.registerActions();
for (const [name, actionClass] of Object.entries(actions)) {
this.registerAction(actionClass);
}
}
}
}
this.logInfo("Plugins loaded successfully.");
}
catch (error) {
this.logError("Failed to discover plugins.", error);
}
}
/**
* Clears all registered actions in the registry.
* Useful for testing or resetting the pipeline.
*/
clearRegistry() {
this.registry.clear();
this.logInfo("Registry cleared.");
}
}
exports.ActionRegistry = ActionRegistry;
// Parameters
// ========================================================================
/**
* Singleton instance
*/
ActionRegistry.instance = null;