kist 0.0.0 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +298 -3
- package/js/actions/CoreActions.d.ts +6 -0
- package/js/actions/CoreActions.js +47 -0
- package/js/actions/DirectoryCleanAction/DirectoryCleanAction.d.ts +36 -0
- package/js/actions/DirectoryCleanAction/DirectoryCleanAction.js +123 -0
- package/js/actions/DirectoryCleanAction/index.d.ts +2 -0
- package/js/actions/DirectoryCleanAction/index.js +8 -0
- package/js/actions/DirectoryCopyAction/DirectoryCopyAction.d.ts +42 -0
- package/js/actions/DirectoryCopyAction/DirectoryCopyAction.js +118 -0
- package/js/actions/DirectoryCopyAction/index.d.ts +2 -0
- package/js/actions/DirectoryCopyAction/index.js +8 -0
- package/js/actions/DirectoryCreateAction/DirectoryCreateAction.d.ts +30 -0
- package/js/actions/DirectoryCreateAction/DirectoryCreateAction.js +85 -0
- package/js/actions/DirectoryCreateAction/index.d.ts +2 -0
- package/js/actions/DirectoryCreateAction/index.js +8 -0
- package/js/actions/DocumentationAction/DocumentationAction.d.ts +23 -0
- package/js/actions/DocumentationAction/DocumentationAction.js +88 -0
- package/js/actions/DocumentationAction/index.d.ts +2 -0
- package/js/actions/DocumentationAction/index.js +8 -0
- package/js/actions/FileCopyAction/FileCopyAction.d.ts +42 -0
- package/js/actions/FileCopyAction/FileCopyAction.js +127 -0
- package/js/actions/FileCopyAction/index.d.ts +2 -0
- package/js/actions/FileCopyAction/index.js +8 -0
- package/js/actions/FileRenameAction/FileRenameAction.d.ts +30 -0
- package/js/actions/FileRenameAction/FileRenameAction.js +84 -0
- package/js/actions/FileRenameAction/index.d.ts +2 -0
- package/js/actions/FileRenameAction/index.js +8 -0
- package/js/actions/JavaScriptMinifyAction/JavaScriptMinifyAction.d.ts +31 -0
- package/js/actions/JavaScriptMinifyAction/JavaScriptMinifyAction.js +98 -0
- package/js/actions/JavaScriptMinifyAction/index.d.ts +2 -0
- package/js/actions/JavaScriptMinifyAction/index.js +8 -0
- package/js/actions/JavaScriptMinifyAction/terser.config.d.ts +27 -0
- package/js/actions/JavaScriptMinifyAction/terser.config.js +119 -0
- package/js/actions/LintAction/LintAction.d.ts +17 -0
- package/js/actions/LintAction/LintAction.js +63 -0
- package/js/actions/LintAction/index.d.ts +2 -0
- package/js/actions/LintAction/index.js +8 -0
- package/js/actions/PackageManagerAction/PackageManagerAction.d.ts +57 -0
- package/js/actions/PackageManagerAction/PackageManagerAction.js +161 -0
- package/js/actions/PackageManagerAction/index.d.ts +2 -0
- package/js/actions/PackageManagerAction/index.js +8 -0
- package/js/actions/PackageManagerAction/package.config.d.ts +16 -0
- package/js/actions/PackageManagerAction/package.config.js +91 -0
- package/js/actions/StyleProcessingAction/StyleProcessingAction.d.ts +34 -0
- package/js/actions/StyleProcessingAction/StyleProcessingAction.js +164 -0
- package/js/actions/StyleProcessingAction/index.d.ts +2 -0
- package/js/actions/StyleProcessingAction/index.js +8 -0
- package/js/actions/StyleProcessingAction/postcss.config.compressed.d.ts +10 -0
- package/js/actions/StyleProcessingAction/postcss.config.compressed.js +31 -0
- package/js/actions/StyleProcessingAction/postcss.config.expanded.d.ts +16 -0
- package/js/actions/StyleProcessingAction/postcss.config.expanded.js +45 -0
- package/js/actions/SvgPackagerAction/SvgPackagerAction.d.ts +68 -0
- package/js/actions/SvgPackagerAction/SvgPackagerAction.js +186 -0
- package/js/actions/SvgPackagerAction/index.d.ts +2 -0
- package/js/actions/SvgPackagerAction/index.js +8 -0
- package/js/actions/SvgReaderAction/SvgReaderAction.d.ts +32 -0
- package/js/actions/SvgReaderAction/SvgReaderAction.js +87 -0
- package/js/actions/SvgReaderAction/index.d.ts +2 -0
- package/js/actions/SvgReaderAction/index.js +8 -0
- package/js/actions/SvgSpriteAction/SvgSpriteAction.d.ts +37 -0
- package/js/actions/SvgSpriteAction/SvgSpriteAction.js +114 -0
- package/js/actions/SvgSpriteAction/index.d.ts +2 -0
- package/js/actions/SvgSpriteAction/index.js +8 -0
- package/js/actions/SvgSpriteAction/svgsprite.config.d.ts +3 -0
- package/js/actions/SvgSpriteAction/svgsprite.config.js +117 -0
- package/js/actions/SvgToPngAction/SvgToPngAction.d.ts +28 -0
- package/js/actions/SvgToPngAction/SvgToPngAction.js +108 -0
- package/js/actions/SvgToPngAction/index.d.ts +2 -0
- package/js/actions/SvgToPngAction/index.js +8 -0
- package/js/actions/TypeScriptCompilerAction/TypeScriptCompilerAction.d.ts +28 -0
- package/js/actions/TypeScriptCompilerAction/TypeScriptCompilerAction.js +96 -0
- package/js/actions/TypeScriptCompilerAction/index.d.ts +2 -0
- package/js/actions/TypeScriptCompilerAction/index.js +8 -0
- package/js/actions/VersionWriteAction/VersionWriteAction.d.ts +45 -0
- package/js/actions/VersionWriteAction/VersionWriteAction.js +147 -0
- package/js/actions/VersionWriteAction/index.d.ts +2 -0
- package/js/actions/VersionWriteAction/index.js +8 -0
- package/js/cli/ArgumentParser.d.ts +62 -0
- package/js/cli/ArgumentParser.js +118 -0
- package/js/cli.d.ts +6 -0
- package/js/cli.js +58 -0
- package/js/core/abstract/AbstractProcess.d.ts +62 -0
- package/js/core/abstract/AbstractProcess.js +96 -0
- package/js/core/abstract/AbstractValidator.d.ts +72 -0
- package/js/core/abstract/AbstractValidator.js +128 -0
- package/js/core/config/ConfigLoader.d.ts +47 -0
- package/js/core/config/ConfigLoader.js +130 -0
- package/js/core/config/ConfigStore.d.ts +69 -0
- package/js/core/config/ConfigStore.js +168 -0
- package/js/core/config/defaultConfig.d.ts +5 -0
- package/js/core/config/defaultConfig.js +131 -0
- package/js/core/pipeline/Action.d.ts +60 -0
- package/js/core/pipeline/Action.js +77 -0
- package/js/core/pipeline/ActionRegistry.d.ts +80 -0
- package/js/core/pipeline/ActionRegistry.js +180 -0
- package/js/core/pipeline/Pipeline.d.ts +42 -0
- package/js/core/pipeline/Pipeline.js +107 -0
- package/js/core/pipeline/PipelineManager.d.ts +55 -0
- package/js/core/pipeline/PipelineManager.js +164 -0
- package/js/core/pipeline/Stage.d.ts +45 -0
- package/js/core/pipeline/Stage.js +110 -0
- package/js/core/pipeline/Step.d.ts +26 -0
- package/js/core/pipeline/Step.js +85 -0
- package/js/core/validation/OptionsValidator.d.ts +43 -0
- package/js/core/validation/OptionsValidator.js +123 -0
- package/js/index.d.ts +3 -0
- package/js/index.js +36 -0
- package/js/interface/ActionInterface.d.ts +57 -0
- package/js/interface/ActionInterface.js +5 -0
- package/js/interface/ActionPlugin.d.ts +4 -0
- package/js/interface/ActionPlugin.js +5 -0
- package/js/interface/ConfigInterface.d.ts +43 -0
- package/js/interface/ConfigInterface.js +5 -0
- package/js/interface/LiveOptionsInterface.d.ts +42 -0
- package/js/interface/LiveOptionsInterface.js +2 -0
- package/js/interface/MetadataInterface.d.ts +95 -0
- package/js/interface/MetadataInterface.js +2 -0
- package/js/interface/OptionsInterface.d.ts +45 -0
- package/js/interface/OptionsInterface.js +5 -0
- package/js/interface/PipelineOptionsInterface.d.ts +66 -0
- package/js/interface/PipelineOptionsInterface.js +5 -0
- package/js/interface/StageInterface.d.ts +79 -0
- package/js/interface/StageInterface.js +5 -0
- package/js/interface/StepInterface.d.ts +66 -0
- package/js/interface/StepInterface.js +5 -0
- package/js/interface/StepOptionsInterface.d.ts +38 -0
- package/js/interface/StepOptionsInterface.js +21 -0
- package/js/interface/index.d.ts +7 -0
- package/js/interface/index.js +3 -0
- package/js/kist.d.ts +58 -0
- package/js/kist.js +145 -0
- package/js/live/LiveServer.d.ts +95 -0
- package/js/live/LiveServer.js +233 -0
- package/js/live/LiveWatcher.d.ts +45 -0
- package/js/live/LiveWatcher.js +140 -0
- package/js/logger/Logger.d.ts +94 -0
- package/js/logger/Logger.js +151 -0
- package/js/logger/LoggerStyles.d.ts +23 -0
- package/js/logger/LoggerStyles.js +30 -0
- package/js/types/ActionOptionsType.d.ts +8 -0
- package/js/types/ActionOptionsType.js +2 -0
- package/js/types/index.d.ts +1 -0
- package/js/types/index.js +3 -0
- package/package.json +93 -7
- package/ts/actions/CoreActions.ts +64 -0
- package/ts/actions/DirectoryCleanAction/DirectoryCleanAction.ts +121 -0
- package/ts/actions/DirectoryCleanAction/index.ts +11 -0
- package/ts/actions/DirectoryCopyAction/DirectoryCopyAction.ts +118 -0
- package/ts/actions/DirectoryCopyAction/index.ts +11 -0
- package/ts/actions/DirectoryCreateAction/DirectoryCreateAction.ts +81 -0
- package/ts/actions/DirectoryCreateAction/index.ts +11 -0
- package/ts/actions/DocumentationAction/DocumentationAction.ts +100 -0
- package/ts/actions/DocumentationAction/index.ts +11 -0
- package/ts/actions/FileCopyAction/FileCopyAction.ts +125 -0
- package/ts/actions/FileCopyAction/index.ts +11 -0
- package/ts/actions/FileRenameAction/FileRenameAction.ts +82 -0
- package/ts/actions/FileRenameAction/index.ts +11 -0
- package/ts/actions/JavaScriptMinifyAction/JavaScriptMinifyAction.ts +109 -0
- package/ts/actions/JavaScriptMinifyAction/index.ts +11 -0
- package/ts/actions/JavaScriptMinifyAction/terser.config.ts +177 -0
- package/ts/actions/LintAction/LintAction.ts +67 -0
- package/ts/actions/LintAction/index.ts +11 -0
- package/ts/actions/PackageManagerAction/PackageManagerAction.ts +176 -0
- package/ts/actions/PackageManagerAction/index.ts +11 -0
- package/ts/actions/PackageManagerAction/package.config.ts +94 -0
- package/ts/actions/SassDocAction/SassDocAction.ts +66 -0
- package/ts/actions/SassDocAction/index.ts +11 -0
- package/ts/actions/StyleProcessingAction/StyleProcessingAction.ts +142 -0
- package/ts/actions/StyleProcessingAction/index.ts +11 -0
- package/ts/actions/StyleProcessingAction/postcss.config.compressed.ts +31 -0
- package/ts/actions/StyleProcessingAction/postcss.config.expanded.ts +47 -0
- package/ts/actions/SvgPackagerAction/SvgPackagerAction.ts +187 -0
- package/ts/actions/SvgPackagerAction/index.ts +11 -0
- package/ts/actions/SvgReaderAction/SvgReaderAction.ts +77 -0
- package/ts/actions/SvgReaderAction/index.ts +11 -0
- package/ts/actions/SvgSpriteAction/SvgSpriteAction.ts +127 -0
- package/ts/actions/SvgSpriteAction/index.ts +11 -0
- package/ts/actions/SvgSpriteAction/svgsprite.config.ts +123 -0
- package/ts/actions/SvgToPngAction/SvgToPngAction.ts +113 -0
- package/ts/actions/SvgToPngAction/index.ts +11 -0
- package/ts/actions/TypeScriptCompilerAction/TypeScriptCompilerAction.ts +117 -0
- package/ts/actions/TypeScriptCompilerAction/index.ts +11 -0
- package/ts/actions/VersionWriteAction/VersionWriteAction.ts +174 -0
- package/ts/actions/VersionWriteAction/index.ts +11 -0
- package/ts/actions/index.ts +0 -0
- package/ts/cli/ArgumentParser.ts +150 -0
- package/ts/cli/index.ts +1 -0
- package/ts/cli.ts +56 -0
- package/ts/core/abstract/AbstractProcess.ts +109 -0
- package/ts/core/abstract/AbstractSingleton.ts +46 -0
- package/ts/core/abstract/AbstractValidator.ts +167 -0
- package/ts/core/abstract/index.ts +0 -0
- package/ts/core/config/ConfigLoader.ts +141 -0
- package/ts/core/config/ConfigStore.ts +201 -0
- package/ts/core/config/defaultConfig.ts +154 -0
- package/ts/core/config/index.ts +0 -0
- package/ts/core/index.ts +34 -0
- package/ts/core/pipeline/Action.ts +101 -0
- package/ts/core/pipeline/ActionRegistry.ts +216 -0
- package/ts/core/pipeline/Pipeline.ts +121 -0
- package/ts/core/pipeline/PipelineManager.ts +170 -0
- package/ts/core/pipeline/Stage.ts +131 -0
- package/ts/core/pipeline/Step.ts +96 -0
- package/ts/core/pipeline/index.ts +0 -0
- package/ts/core/validation/ActionValidator.ts +97 -0
- package/ts/core/validation/ConfigValidator.ts +103 -0
- package/ts/core/validation/OptionsValidator.ts +179 -0
- package/ts/core/validation/StageValidator.ts +175 -0
- package/ts/core/validation/StepValidator.ts +203 -0
- package/ts/core/validation/index.ts +0 -0
- package/ts/index.ts +26 -0
- package/ts/interface/ActionInterface.ts +70 -0
- package/ts/interface/ActionPlugin.ts +14 -0
- package/ts/interface/ConfigInterface.ts +55 -0
- package/ts/interface/File.ts +24 -0
- package/ts/interface/LiveOptionsInterface.ts +46 -0
- package/ts/interface/MetadataInterface.ts +105 -0
- package/ts/interface/OptionsInterface.ts +58 -0
- package/ts/interface/PackageJson.ts +171 -0
- package/ts/interface/PipelineOptionsInterface.ts +74 -0
- package/ts/interface/SVG.ts +84 -0
- package/ts/interface/StageInterface.ts +96 -0
- package/ts/interface/StepInterface.ts +83 -0
- package/ts/interface/StepOptionsInterface.ts +57 -0
- package/ts/interface/index.ts +9 -0
- package/ts/kist.ts +161 -0
- package/ts/live/LiveServer.ts +311 -0
- package/ts/live/LiveWatcher.ts +150 -0
- package/ts/live/index.ts +11 -0
- package/ts/logger/Logger.ts +187 -0
- package/ts/logger/LoggerStyles.ts +28 -0
- package/ts/logger/index.ts +0 -0
- package/ts/types/ActionOptionsType.ts +10 -0
- package/ts/types/index.ts +3 -0
- package/index.js +0 -3
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { readdirSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { coreActions } from "../../actions/CoreActions";
|
|
8
|
+
import { ActionInterface } from "../../interface/ActionInterface";
|
|
9
|
+
import { ActionPlugin } from "../../interface/ActionPlugin";
|
|
10
|
+
import { AbstractProcess } from "../abstract/AbstractProcess";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Class
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* ActionRegistry is a singleton registry for step actions, mapping action
|
|
18
|
+
* names to their corresponding classes. This registry allows dynamic
|
|
19
|
+
* resolution of step actions within the pipeline and supports custom
|
|
20
|
+
* developer integrations.
|
|
21
|
+
*/
|
|
22
|
+
export class ActionRegistry extends AbstractProcess {
|
|
23
|
+
// Parameters
|
|
24
|
+
// ========================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Singleton instance
|
|
28
|
+
*/
|
|
29
|
+
private static instance: ActionRegistry | null = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Map to store registered actions
|
|
33
|
+
*/
|
|
34
|
+
private registry: Map<string, new () => ActionInterface>;
|
|
35
|
+
|
|
36
|
+
// Constructor
|
|
37
|
+
// ========================================================================
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Constructs an ActionRegistry instance and automatically registers core
|
|
41
|
+
* actions. The constructor is private to enforce the singleton pattern.
|
|
42
|
+
*/
|
|
43
|
+
constructor() {
|
|
44
|
+
// Initialize logging through AbstractProcess
|
|
45
|
+
super();
|
|
46
|
+
this.registry = new Map();
|
|
47
|
+
// Automatically register core actions
|
|
48
|
+
this.registerCoreActions();
|
|
49
|
+
this.discoverPlugins();
|
|
50
|
+
this.logInfo("ActionRegistry initialized.");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Singleton Methods
|
|
54
|
+
// ========================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initializes the singleton instance of ActionRegistry.
|
|
58
|
+
* Should only be called once during application startup.
|
|
59
|
+
*
|
|
60
|
+
* @throws Error if the registry has already been initialized.
|
|
61
|
+
*/
|
|
62
|
+
public static initialize(): void {
|
|
63
|
+
if (ActionRegistry.instance) {
|
|
64
|
+
throw new Error("ActionRegistry has already been initialized.");
|
|
65
|
+
}
|
|
66
|
+
ActionRegistry.instance = new ActionRegistry();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Retrieves the singleton instance of ActionRegistry, initializing it if
|
|
71
|
+
* necessary.
|
|
72
|
+
*
|
|
73
|
+
* @returns The ActionRegistry instance.
|
|
74
|
+
*/
|
|
75
|
+
public static getInstance(): ActionRegistry {
|
|
76
|
+
if (!ActionRegistry.instance) {
|
|
77
|
+
ActionRegistry.instance = new ActionRegistry();
|
|
78
|
+
}
|
|
79
|
+
return ActionRegistry.instance;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resets the singleton instance of ActionRegistry.
|
|
84
|
+
* This is useful for testing or resetting the registry state during
|
|
85
|
+
* runtime.
|
|
86
|
+
*/
|
|
87
|
+
public static resetInstance(): void {
|
|
88
|
+
ActionRegistry.instance = null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Instance Methods
|
|
92
|
+
// ========================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Registers a new action in the registry.
|
|
96
|
+
*
|
|
97
|
+
* @param actionClass - The class implementing `ActionInterface`.
|
|
98
|
+
* @throws Error if the action name is already registered or missing.
|
|
99
|
+
*/
|
|
100
|
+
public registerAction(actionClass: new () => ActionInterface): void {
|
|
101
|
+
const actionInstance = new actionClass();
|
|
102
|
+
const name = actionInstance.name;
|
|
103
|
+
|
|
104
|
+
if (!name || typeof name !== "string") {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`[ActionRegistry] Action class must have a valid 'name' property.`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
if (this.registry.has(name)) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`[ActionRegistry] Action "${name}" is already registered.`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.registry.set(name, actionClass);
|
|
116
|
+
this.logInfo(`Action "${name}" registered successfully.`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Retrieves a step action class from the registry.
|
|
121
|
+
* This method looks up an action by name and returns the corresponding
|
|
122
|
+
* class that implements the ActionInterface.
|
|
123
|
+
*
|
|
124
|
+
* @param name - The name of the action to retrieve.
|
|
125
|
+
* @returns The action class constructor if found, or undefined if no such
|
|
126
|
+
* action is registered.
|
|
127
|
+
*/
|
|
128
|
+
public getAction(name: string): (new () => ActionInterface) | undefined {
|
|
129
|
+
// Validate the input name
|
|
130
|
+
if (!name || typeof name !== "string") {
|
|
131
|
+
this.logWarn(`Invalid action name requested: "${name}".`);
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Retrieve the action from the registry
|
|
136
|
+
const action = this.registry.get(name);
|
|
137
|
+
|
|
138
|
+
// Log a warning if the action is not found
|
|
139
|
+
if (!action) {
|
|
140
|
+
this.logWarn(`Action "${name}" not found in the registry.`);
|
|
141
|
+
} else {
|
|
142
|
+
this.logDebug(`Retrieved action "${name}" from the registry.`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return action;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Lists all registered step actions.
|
|
150
|
+
* Provides a utility to view currently registered actions, useful for
|
|
151
|
+
* debugging and validation.
|
|
152
|
+
*
|
|
153
|
+
* @returns An array of registered action names.
|
|
154
|
+
*/
|
|
155
|
+
public listRegisteredActions(): string[] {
|
|
156
|
+
this.logDebug("Listing all registered actions.");
|
|
157
|
+
return Array.from(this.registry.keys());
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Pre-registers core actions that are included with the pipeline by
|
|
162
|
+
* default. Developers can extend this by registering additional custom
|
|
163
|
+
* actions as needed.
|
|
164
|
+
*/
|
|
165
|
+
private registerCoreActions(): void {
|
|
166
|
+
Object.values(coreActions).forEach((actionClass) => {
|
|
167
|
+
this.registerAction(actionClass);
|
|
168
|
+
});
|
|
169
|
+
this.logInfo("Core actions registered successfully.");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private discoverPlugins(): void {
|
|
173
|
+
this.logInfo("Discovering external plugins...");
|
|
174
|
+
|
|
175
|
+
const nodeModulesPath = join(process.cwd(), "node_modules");
|
|
176
|
+
const pluginPrefix = "@kist/plugin-";
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
const directories = readdirSync(nodeModulesPath, {
|
|
180
|
+
withFileTypes: true,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
for (const dir of directories) {
|
|
184
|
+
if (dir.isDirectory() && dir.name.startsWith(pluginPrefix)) {
|
|
185
|
+
const pluginPath = join(nodeModulesPath, dir.name);
|
|
186
|
+
const plugin: ActionPlugin = require(pluginPath).default;
|
|
187
|
+
|
|
188
|
+
if (
|
|
189
|
+
plugin &&
|
|
190
|
+
typeof plugin.registerActions === "function"
|
|
191
|
+
) {
|
|
192
|
+
const actions = plugin.registerActions();
|
|
193
|
+
for (const [name, actionClass] of Object.entries(
|
|
194
|
+
actions,
|
|
195
|
+
)) {
|
|
196
|
+
this.registerAction(actionClass);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
this.logInfo("Plugins loaded successfully.");
|
|
203
|
+
} catch (error) {
|
|
204
|
+
this.logError("Failed to discover plugins.", error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Clears all registered actions in the registry.
|
|
210
|
+
* Useful for testing or resetting the pipeline.
|
|
211
|
+
*/
|
|
212
|
+
public clearRegistry(): void {
|
|
213
|
+
this.registry.clear();
|
|
214
|
+
this.logInfo("Registry cleared.");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { ConfigInterface } from "../../interface/ConfigInterface";
|
|
6
|
+
import { AbstractProcess } from "../abstract/AbstractProcess";
|
|
7
|
+
import { Stage } from "./Stage";
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Class
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents the pipeline of stages to be executed.
|
|
15
|
+
* This class manages the execution flow of stages, including parallel
|
|
16
|
+
* execution, dependency handling, and applying global options for consistent
|
|
17
|
+
* pipeline behavior.
|
|
18
|
+
*/
|
|
19
|
+
export class Pipeline extends AbstractProcess {
|
|
20
|
+
// Parameters
|
|
21
|
+
// ========================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* List of stages to be executed in the pipeline.
|
|
25
|
+
*/
|
|
26
|
+
private stages: Stage[];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Global options that apply across the entire pipeline.
|
|
30
|
+
*/
|
|
31
|
+
private options?: ConfigInterface["options"];
|
|
32
|
+
|
|
33
|
+
// Constructor
|
|
34
|
+
// ========================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Constructs a new Pipeline instance with the given configuration.
|
|
38
|
+
* Initializes stages and applies global options for execution control.
|
|
39
|
+
*
|
|
40
|
+
* @param config - The configuration object defining the stages, steps,
|
|
41
|
+
* and global options for the pipeline.
|
|
42
|
+
*/
|
|
43
|
+
constructor(private config: ConfigInterface) {
|
|
44
|
+
super();
|
|
45
|
+
this.stages = config.stages.map((stage) => new Stage(stage));
|
|
46
|
+
this.options = config.options;
|
|
47
|
+
this.logInfo("Pipeline instance created.");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Methods
|
|
51
|
+
// ========================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Runs the pipeline, executing stages based on their dependencies.
|
|
55
|
+
* Stages are run in parallel by default, but their execution respects
|
|
56
|
+
* defined dependencies. Applies global options for logging, error
|
|
57
|
+
* handling, and execution control.
|
|
58
|
+
*/
|
|
59
|
+
async run(): Promise<void> {
|
|
60
|
+
this.logInfo("Starting pipeline execution...");
|
|
61
|
+
|
|
62
|
+
// Track stages that have been completed
|
|
63
|
+
const completedStages = new Set<string>();
|
|
64
|
+
|
|
65
|
+
// Run stages with dependency management and parallel execution control
|
|
66
|
+
try {
|
|
67
|
+
this.logDebug("Pipeline execution started with debug logging.");
|
|
68
|
+
|
|
69
|
+
// Execute all stages with concurrency control
|
|
70
|
+
const stagePromises = this.stages.map((stage) =>
|
|
71
|
+
stage.execute(completedStages),
|
|
72
|
+
);
|
|
73
|
+
await this.runWithConcurrencyControl(stagePromises);
|
|
74
|
+
|
|
75
|
+
this.logInfo("Pipeline execution completed successfully.");
|
|
76
|
+
} catch (error) {
|
|
77
|
+
this.logError("Pipeline execution failed:", error);
|
|
78
|
+
|
|
79
|
+
// Halt pipeline if configured to do so on failure
|
|
80
|
+
if (this.options?.haltOnFailure !== false) {
|
|
81
|
+
this.logError("Halting pipeline due to failure.");
|
|
82
|
+
process.exit(1);
|
|
83
|
+
} else {
|
|
84
|
+
this.logWarn("Continuing pipeline execution despite errors.");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Runs the stage promises with concurrency control based on global
|
|
91
|
+
* options. Limits the number of parallel running stages if
|
|
92
|
+
* maxConcurrentStages is set in global options.
|
|
93
|
+
* @param stagePromises - An array of promises representing stage
|
|
94
|
+
* executions.
|
|
95
|
+
*/
|
|
96
|
+
private async runWithConcurrencyControl(
|
|
97
|
+
stagePromises: Promise<void>[],
|
|
98
|
+
): Promise<void> {
|
|
99
|
+
const maxConcurrentStages =
|
|
100
|
+
this.options?.maxConcurrentStages || stagePromises.length;
|
|
101
|
+
|
|
102
|
+
// Process stages with a concurrency limit
|
|
103
|
+
const executingStages = new Set<Promise<void>>();
|
|
104
|
+
|
|
105
|
+
for (const stagePromise of stagePromises) {
|
|
106
|
+
executingStages.add(stagePromise);
|
|
107
|
+
|
|
108
|
+
// Ensure stages are removed from the set once complete
|
|
109
|
+
stagePromise.finally(() => executingStages.delete(stagePromise));
|
|
110
|
+
|
|
111
|
+
// Enforce concurrency limit
|
|
112
|
+
if (executingStages.size >= (maxConcurrentStages as number)) {
|
|
113
|
+
// Wait until at least one stage completes
|
|
114
|
+
await Promise.race(executingStages);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Wait for all remaining stages to complete
|
|
119
|
+
await Promise.all(executingStages);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { ChildProcess, spawn } from "child_process";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { LiveServer } from "../../live/LiveServer";
|
|
8
|
+
import { AbstractProcess } from "../abstract/AbstractProcess";
|
|
9
|
+
import { ConfigStore } from "../config/ConfigStore";
|
|
10
|
+
import { Pipeline } from "./Pipeline";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Class
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Manages the lifecycle of the pipeline process and integrates with the
|
|
18
|
+
* LiveServer for client notifications upon pipeline events.
|
|
19
|
+
*/
|
|
20
|
+
export class PipelineManager extends AbstractProcess {
|
|
21
|
+
// Parameters
|
|
22
|
+
// ========================================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The current instance of the pipeline process.
|
|
26
|
+
*/
|
|
27
|
+
private pipelineProcess: ChildProcess | null = null;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Flag to prevent overlapping restarts.
|
|
31
|
+
*/
|
|
32
|
+
private isRestarting: boolean = false;
|
|
33
|
+
|
|
34
|
+
// Constructor
|
|
35
|
+
// ========================================================================
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initializes the PipelineManager with a LiveServer instance.
|
|
39
|
+
*
|
|
40
|
+
* @param liveServer - The LiveServer instance to notify when the
|
|
41
|
+
* pipeline restarts.
|
|
42
|
+
*/
|
|
43
|
+
constructor(private liveServer?: LiveServer) {
|
|
44
|
+
super();
|
|
45
|
+
this.logInfo("PipelineManager initialized.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Methods
|
|
49
|
+
// ========================================================================
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Runs the pipeline using the configuration from the `ConfigStore`.
|
|
53
|
+
* This method executes the pipeline stages directly, bypassing the CLI.
|
|
54
|
+
*/
|
|
55
|
+
public async runPipeline(): Promise<void> {
|
|
56
|
+
const config = ConfigStore.getInstance().getConfig();
|
|
57
|
+
|
|
58
|
+
if (!config.stages || !Array.isArray(config.stages)) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"Invalid configuration: 'stages' must be an array.",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.logInfo("Initializing pipeline...");
|
|
65
|
+
const pipeline = new Pipeline(config);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
await pipeline.run();
|
|
69
|
+
|
|
70
|
+
this.logInfo("Pipeline execution finished successfully.");
|
|
71
|
+
this.liveServer?.reloadClients();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
this.logError("Error during pipeline execution.", error);
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Restarts the pipeline process, stopping any currently running process.
|
|
80
|
+
* Notifies connected clients via the LiveServer after restarting.
|
|
81
|
+
*/
|
|
82
|
+
public restartPipeline(): void {
|
|
83
|
+
if (this.isRestarting) {
|
|
84
|
+
this.logWarn("Pipeline restart already in progress. Skipping...");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.isRestarting = true;
|
|
89
|
+
|
|
90
|
+
if (this.pipelineProcess) {
|
|
91
|
+
this.logInfo("Stopping current pipeline process...");
|
|
92
|
+
this.stopPipeline();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.logInfo("Starting pipeline...");
|
|
96
|
+
const scriptPath = path.resolve(process.cwd(), "dist/js/cli.js");
|
|
97
|
+
|
|
98
|
+
this.pipelineProcess = spawn("node", [scriptPath], {
|
|
99
|
+
stdio: "inherit",
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
this.attachProcessListeners();
|
|
103
|
+
|
|
104
|
+
this.isRestarting = false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Attaches event listeners to the pipeline process for logging and
|
|
109
|
+
* notification purposes.
|
|
110
|
+
*/
|
|
111
|
+
private attachProcessListeners(): void {
|
|
112
|
+
if (!this.pipelineProcess) return;
|
|
113
|
+
|
|
114
|
+
this.pipelineProcess.on("close", (code) => {
|
|
115
|
+
if (code !== 0) {
|
|
116
|
+
this.logError(`Pipeline process exited with code ${code}`);
|
|
117
|
+
} else {
|
|
118
|
+
this.logInfo("Pipeline process exited successfully.");
|
|
119
|
+
}
|
|
120
|
+
this.liveServer?.reloadClients();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
this.pipelineProcess.on("error", (error) => {
|
|
124
|
+
this.logError("Error starting pipeline process.", error);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
this.pipelineProcess.on("exit", (code, signal) => {
|
|
128
|
+
if (signal) {
|
|
129
|
+
this.logWarn(
|
|
130
|
+
`Pipeline process was terminated with signal: ${signal}`,
|
|
131
|
+
);
|
|
132
|
+
} else {
|
|
133
|
+
this.logInfo(`Pipeline process exited with code: ${code}`);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Stops the currently running pipeline process, if any.
|
|
140
|
+
* Gracefully kills the process and handles cleanup.
|
|
141
|
+
*/
|
|
142
|
+
public stopPipeline(): void {
|
|
143
|
+
if (this.pipelineProcess) {
|
|
144
|
+
this.logInfo("Stopping pipeline process...");
|
|
145
|
+
this.pipelineProcess.kill("SIGTERM");
|
|
146
|
+
this.pipelineProcess = null;
|
|
147
|
+
this.logInfo("Pipeline process stopped.");
|
|
148
|
+
} else {
|
|
149
|
+
this.logWarn("No pipeline process is currently running.");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Checks if the pipeline process is currently running.
|
|
155
|
+
* @returns True if the pipeline process is running, false otherwise.
|
|
156
|
+
*/
|
|
157
|
+
public isPipelineRunning(): boolean {
|
|
158
|
+
return this.pipelineProcess !== null && !this.pipelineProcess.killed;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Restarts the pipeline with a delay, useful for throttling restarts when
|
|
163
|
+
* changes occur rapidly.
|
|
164
|
+
* @param delay - The delay in milliseconds before restarting the pipeline.
|
|
165
|
+
*/
|
|
166
|
+
public restartPipelineWithDelay(delay: number = 1000): void {
|
|
167
|
+
this.logInfo(`Delaying pipeline restart by ${delay} milliseconds...`);
|
|
168
|
+
setTimeout(() => this.restartPipeline(), delay);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { StageInterface } from "../../interface/StageInterface";
|
|
6
|
+
import { AbstractProcess } from "../abstract/AbstractProcess";
|
|
7
|
+
import { Step } from "./Step";
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Class
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents a stage in the pipeline, encapsulating its execution logic and
|
|
15
|
+
* dependencies. Each stage consists of multiple steps that are executed
|
|
16
|
+
* consecutively, and stages can have dependencies on other stages which are
|
|
17
|
+
* managed before execution.
|
|
18
|
+
*/
|
|
19
|
+
export class Stage extends AbstractProcess {
|
|
20
|
+
// Parameters
|
|
21
|
+
// ========================================================================
|
|
22
|
+
|
|
23
|
+
private name: string;
|
|
24
|
+
private steps: Step[];
|
|
25
|
+
private dependsOn?: string[];
|
|
26
|
+
|
|
27
|
+
// Constructor
|
|
28
|
+
// ========================================================================
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Constructs a Stage instance with the given stage definition.
|
|
32
|
+
* @param stage - The stage definition containing name, steps, and
|
|
33
|
+
* dependencies.
|
|
34
|
+
*/
|
|
35
|
+
constructor(stage: StageInterface) {
|
|
36
|
+
super(); // Initialize logging
|
|
37
|
+
this.name = stage.name;
|
|
38
|
+
this.steps = stage.steps.map((step) => new Step(step));
|
|
39
|
+
this.dependsOn = stage.dependsOn;
|
|
40
|
+
|
|
41
|
+
this.logInfo(
|
|
42
|
+
`Stage "${this.name}" initialized with ${this.steps.length} steps.`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Methods
|
|
47
|
+
// ========================================================================
|
|
48
|
+
|
|
49
|
+
// Methods
|
|
50
|
+
// ========================================================================
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Executes the stage by running its steps consecutively.
|
|
54
|
+
* Manages dependencies by waiting for dependent stages to complete
|
|
55
|
+
* before execution.
|
|
56
|
+
* @param completedStages - A set of completed stage names used for
|
|
57
|
+
* dependency tracking.
|
|
58
|
+
* @throws Error if any step within the stage fails.
|
|
59
|
+
*/
|
|
60
|
+
async execute(completedStages: Set<string>): Promise<void> {
|
|
61
|
+
// Handle dependencies before executing the stage
|
|
62
|
+
if (this.dependsOn) {
|
|
63
|
+
await this.resolveDependencies(completedStages);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.logInfo(`Executing stage: ${this.name}`);
|
|
67
|
+
|
|
68
|
+
// Execute all steps within the stage consecutively
|
|
69
|
+
try {
|
|
70
|
+
for (const step of this.steps) {
|
|
71
|
+
await step.execute();
|
|
72
|
+
}
|
|
73
|
+
this.logInfo(`Stage "${this.name}" completed successfully.`);
|
|
74
|
+
completedStages.add(this.name);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
this.logError(
|
|
77
|
+
`Error executing stage "${this.name}": ${error}`,
|
|
78
|
+
error,
|
|
79
|
+
);
|
|
80
|
+
// Propagate the error to halt pipeline or manage based on
|
|
81
|
+
// global settings
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resolves dependencies by ensuring all required stages have completed.
|
|
88
|
+
* @param completedStages - A set of completed stage names used for
|
|
89
|
+
* dependency tracking.
|
|
90
|
+
* @returns A promise that resolves once all dependencies are met.
|
|
91
|
+
*/
|
|
92
|
+
private async resolveDependencies(
|
|
93
|
+
completedStages: Set<string>,
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
if (!this.dependsOn) return;
|
|
96
|
+
|
|
97
|
+
this.logInfo(
|
|
98
|
+
`Stage "${this.name}" is waiting for
|
|
99
|
+
dependencies:${this.dependsOn.join(", ")}`,
|
|
100
|
+
);
|
|
101
|
+
await Promise.all(
|
|
102
|
+
this.dependsOn.map((dep) =>
|
|
103
|
+
this.waitForStageCompletion(dep, completedStages),
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
this.logInfo(`All dependencies resolved for stage: "${this.name}"`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Waits for a specified stage to complete by monitoring the completed
|
|
111
|
+
* stages set.
|
|
112
|
+
* @param stageName - The name of the stage to wait for.
|
|
113
|
+
* @param completedStages - A set of completed stage names used for
|
|
114
|
+
* dependency tracking.
|
|
115
|
+
* @returns A promise that resolves when the specified stage is marked
|
|
116
|
+
* as completed.
|
|
117
|
+
*/
|
|
118
|
+
private async waitForStageCompletion(
|
|
119
|
+
stageName: string,
|
|
120
|
+
completedStages: Set<string>,
|
|
121
|
+
): Promise<void> {
|
|
122
|
+
while (!completedStages.has(stageName)) {
|
|
123
|
+
await new Promise((resolve) =>
|
|
124
|
+
setTimeout(
|
|
125
|
+
resolve,
|
|
126
|
+
100, // Polling interval to check completion status
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|