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,150 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { AbstractProcess } from "../core/abstract/AbstractProcess";
|
|
6
|
+
import { OptionsValidator } from "../core/validation/OptionsValidator";
|
|
7
|
+
import { OptionsInterface } from "../interface/OptionsInterface";
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Class
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* ArgumentParser handles parsing and validating command-line arguments
|
|
15
|
+
* against the structure defined in OptionsInterface.
|
|
16
|
+
* Extends AbstractProcess for consistent logging.
|
|
17
|
+
*/
|
|
18
|
+
export class ArgumentParser extends AbstractProcess {
|
|
19
|
+
// Parameters
|
|
20
|
+
// ========================================================================
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Command-line arguments to parse, excluding the Node.js and script path.
|
|
24
|
+
*/
|
|
25
|
+
private args: string[];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Instance of OptionsValidator for validating parsed arguments.
|
|
29
|
+
*/
|
|
30
|
+
private validator: OptionsValidator;
|
|
31
|
+
|
|
32
|
+
// Constructor
|
|
33
|
+
// ========================================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Initializes the ArgumentParser with command-line arguments and an
|
|
37
|
+
* instance of OptionsValidator for validation.
|
|
38
|
+
*
|
|
39
|
+
* @param args - Command-line arguments. Defaults to `process.argv.slice(2)`.
|
|
40
|
+
*/
|
|
41
|
+
constructor() { // args: string[] = process.argv.slice(2)
|
|
42
|
+
super();
|
|
43
|
+
// Skip Node.js and script path
|
|
44
|
+
this.args = process.argv.slice(2);
|
|
45
|
+
|
|
46
|
+
// console.log(process.argv.slice(2))
|
|
47
|
+
|
|
48
|
+
// this.args = args;
|
|
49
|
+
this.validator = new OptionsValidator();
|
|
50
|
+
this.logDebug("ArgumentParser initialized with arguments.");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Methods
|
|
54
|
+
// ========================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Retrieves the value of a specific option from the CLI arguments, with
|
|
58
|
+
* validation.
|
|
59
|
+
*
|
|
60
|
+
* @param key - The name of the option (matches keys in OptionsInterface).
|
|
61
|
+
* @param options - Additional options:
|
|
62
|
+
* - `default`: The default value to return if the option is not found.
|
|
63
|
+
* @returns The value of the option or the default value if not found.
|
|
64
|
+
* @throws Error if the value is invalid based on the validation rules.
|
|
65
|
+
*/
|
|
66
|
+
public getOption<K extends keyof OptionsInterface>(
|
|
67
|
+
key: K,
|
|
68
|
+
options?: { default?: OptionsInterface[K] },
|
|
69
|
+
): OptionsInterface[K] | undefined {
|
|
70
|
+
const flag = `--${key}`;
|
|
71
|
+
const flagIndex = this.args.findIndex((arg) => arg === flag);
|
|
72
|
+
const value =
|
|
73
|
+
flagIndex !== -1 && this.args[flagIndex + 1]
|
|
74
|
+
? this.args[flagIndex + 1]
|
|
75
|
+
: options?.default;
|
|
76
|
+
|
|
77
|
+
if (value !== undefined) {
|
|
78
|
+
// Create a partial object to validate the specific key-value pair
|
|
79
|
+
const partialOption = {
|
|
80
|
+
[key]: value,
|
|
81
|
+
} as Partial<OptionsInterface>;
|
|
82
|
+
// Validate the key-value pair
|
|
83
|
+
this.validator.validate(partialOption);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.logInfo(`Retrieved option "${key}" with value: ${value}`);
|
|
87
|
+
return value as OptionsInterface[K];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Checks if a specific flag exists in the CLI arguments.
|
|
92
|
+
*
|
|
93
|
+
* @param key - The name of the flag to check (e.g., "dryRun").
|
|
94
|
+
* @returns `true` if the flag is present, otherwise `false`.
|
|
95
|
+
*/
|
|
96
|
+
public hasFlag(key: keyof OptionsInterface): boolean {
|
|
97
|
+
const flag = `--${key}`;
|
|
98
|
+
const exists = this.args.includes(flag);
|
|
99
|
+
this.logInfo(
|
|
100
|
+
`Flag "${flag}" is ${exists ? "present" : "not present"}.`,
|
|
101
|
+
);
|
|
102
|
+
return exists;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Parses all CLI arguments into a key-value object.
|
|
107
|
+
* Flags are treated as boolean if not followed by a value.
|
|
108
|
+
*
|
|
109
|
+
* Example:
|
|
110
|
+
* --live --mode development => { live: true, mode: "development" }
|
|
111
|
+
*
|
|
112
|
+
* @returns A key-value object of all parsed CLI arguments.
|
|
113
|
+
*/
|
|
114
|
+
public getAllFlags(): Record<string, string | boolean> {
|
|
115
|
+
const flags: Record<string, string | boolean> = {};
|
|
116
|
+
|
|
117
|
+
for (let i = 0; i < this.args.length; i++) {
|
|
118
|
+
const arg = this.args[i];
|
|
119
|
+
if (arg.startsWith("--")) {
|
|
120
|
+
const key = arg.slice(2);
|
|
121
|
+
const nextArg = this.args[i + 1];
|
|
122
|
+
if (nextArg && !nextArg.startsWith("--")) {
|
|
123
|
+
flags[key] = nextArg;
|
|
124
|
+
// Skip the next argument since it's a value
|
|
125
|
+
i++;
|
|
126
|
+
} else {
|
|
127
|
+
// Flag with no value is treated as boolean true
|
|
128
|
+
flags[key] = true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return flags;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Retrieves a specific flag value.
|
|
138
|
+
*
|
|
139
|
+
* @param key - The flag name to retrieve.
|
|
140
|
+
* @param defaultValue - The default value if the flag is not present.
|
|
141
|
+
* @returns The value of the flag or the default value.
|
|
142
|
+
*/
|
|
143
|
+
public getFlag(
|
|
144
|
+
key: string,
|
|
145
|
+
defaultValue: string | boolean = false,
|
|
146
|
+
): string | boolean {
|
|
147
|
+
const flags = this.getAllFlags();
|
|
148
|
+
return flags[key] ?? defaultValue;
|
|
149
|
+
}
|
|
150
|
+
}
|
package/ts/cli/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// export { getMode } from "./getMode";
|
package/ts/cli.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Imports
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
import { ArgumentParser } from "./cli/ArgumentParser";
|
|
8
|
+
import { ConfigLoader } from "./core/config/ConfigLoader";
|
|
9
|
+
import { ConfigStore } from "./core/config/ConfigStore";
|
|
10
|
+
import { Kist } from "./kist";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Main Entry Point
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The entry point for the Kist CLI application. Sets up the runtime
|
|
18
|
+
* environment, loads configuration, and invokes the Kist class.
|
|
19
|
+
*/
|
|
20
|
+
(async () => {
|
|
21
|
+
try {
|
|
22
|
+
// console.log("Raw arguments:", process.argv);
|
|
23
|
+
|
|
24
|
+
// Initialize CLI argument parser
|
|
25
|
+
const parser = new ArgumentParser();
|
|
26
|
+
const cliOptions = parser.getAllFlags();
|
|
27
|
+
// console.log(cliOptions)
|
|
28
|
+
|
|
29
|
+
// Initialize ConfigStore
|
|
30
|
+
const configStore = ConfigStore.getInstance();
|
|
31
|
+
|
|
32
|
+
// Initialize ConfigStore and load configuration
|
|
33
|
+
const configLoader = new ConfigLoader();
|
|
34
|
+
await configLoader.initialize();
|
|
35
|
+
const fileConfig = await configLoader.loadConfig();
|
|
36
|
+
|
|
37
|
+
// Merge Configs
|
|
38
|
+
// configStore.print()
|
|
39
|
+
configStore.merge(fileConfig); // Merge file-based config
|
|
40
|
+
// configStore.print()
|
|
41
|
+
configStore.merge({ options: cliOptions }); // Merge CLI options
|
|
42
|
+
// configStore.print()
|
|
43
|
+
|
|
44
|
+
// Create a Kist instance and execute the workflow
|
|
45
|
+
const kist = new Kist();
|
|
46
|
+
await kist.run();
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error(`[CLI] An unexpected error occurred:`, error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Note: The `#!/usr/bin/env node` shebang ensures that the script can be executed
|
|
55
|
+
* directly as a Node.js script on compatible systems.
|
|
56
|
+
*/
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { Logger } from "../../logger/Logger";
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Class
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* AbstractProcess provides consistent logging functionality to its subclasses.
|
|
13
|
+
* It leverages a centralized logger to manage different log levels and
|
|
14
|
+
* ensures logging consistency across the application.
|
|
15
|
+
*/
|
|
16
|
+
export abstract class AbstractProcess {
|
|
17
|
+
// Parameters
|
|
18
|
+
// ========================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Logger instance for handling log messages.
|
|
22
|
+
*/
|
|
23
|
+
protected readonly logger: Logger;
|
|
24
|
+
|
|
25
|
+
// Constructor
|
|
26
|
+
// ========================================================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Constructs an AbstractProcess instance.
|
|
30
|
+
* Initializes the logger to ensure logging capabilities are available to
|
|
31
|
+
* subclasses.
|
|
32
|
+
*/
|
|
33
|
+
constructor() {
|
|
34
|
+
this.logger = Logger.getInstance();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Logging Methods
|
|
38
|
+
// ========================================================================
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Logs an informational message with the originating class name as context.
|
|
42
|
+
* Use this for standard informational messages.
|
|
43
|
+
* @param message - The message to log.
|
|
44
|
+
*/
|
|
45
|
+
protected logInfo(message: string): void {
|
|
46
|
+
this.logger.logInfo(this.constructor.name, message);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Logs a debug message with the originating class name as context.
|
|
51
|
+
* @param message - The debug message to log.
|
|
52
|
+
*/
|
|
53
|
+
protected logDebug(message: string): void {
|
|
54
|
+
this.logger.logDebug(this.constructor.name, message);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Logs a warning message with the originating class name as context.
|
|
59
|
+
* Use this to highlight potential issues that are non-critical.
|
|
60
|
+
* @param message - The warning message to log.
|
|
61
|
+
*/
|
|
62
|
+
protected logWarn(message: string): void {
|
|
63
|
+
this.logger.logWarn(this.constructor.name, message);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Logs an error message with the originating class name as context.
|
|
68
|
+
* Handles any type of error and ensures consistent error reporting.
|
|
69
|
+
* Use this for logging critical issues or exceptions.
|
|
70
|
+
*
|
|
71
|
+
* @param message - A custom message providing additional context for
|
|
72
|
+
* the error.
|
|
73
|
+
* @param error - (Optional) The error to log. Can be a string, an Error
|
|
74
|
+
* object, or other types.
|
|
75
|
+
*/
|
|
76
|
+
protected logError(message: string, error?: unknown): void {
|
|
77
|
+
const errorMessage = this.formatError(message, error);
|
|
78
|
+
this.logger.logError(this.constructor.name, errorMessage);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Formats an error message for logging.
|
|
83
|
+
* Combines a custom message with additional error details if available.
|
|
84
|
+
*
|
|
85
|
+
* @param message - The base error message.
|
|
86
|
+
* @param error - Additional error information, such as an Error object.
|
|
87
|
+
* @returns A formatted string combining the message and error details.
|
|
88
|
+
*/
|
|
89
|
+
private formatError(message: string, error?: unknown): string {
|
|
90
|
+
if (error instanceof Error) {
|
|
91
|
+
return `${message}: ${error.message}`;
|
|
92
|
+
} else if (typeof error === "string") {
|
|
93
|
+
return `${message}: ${error}`;
|
|
94
|
+
} else if (error) {
|
|
95
|
+
return `${message}: ${JSON.stringify(error)}`;
|
|
96
|
+
}
|
|
97
|
+
return message;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Logs a success message with the originating class name as context.
|
|
102
|
+
* Use this to indicate successful completion of a process or step.
|
|
103
|
+
*
|
|
104
|
+
* @param message - The success message to log.
|
|
105
|
+
*/
|
|
106
|
+
protected logSuccess(message: string): void {
|
|
107
|
+
this.logger.logInfo(this.constructor.name, message);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Abstract Singleton
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* AbstractSingleton provides a base class for implementing singletons.
|
|
7
|
+
* It ensures that only one instance of the derived class can exist.
|
|
8
|
+
*/
|
|
9
|
+
export abstract class AbstractSingleton<T extends AbstractSingleton<T>> {
|
|
10
|
+
private static _instances = new Map<string, AbstractSingleton<any>>();
|
|
11
|
+
|
|
12
|
+
protected constructor() {
|
|
13
|
+
const className = this.constructor.name;
|
|
14
|
+
if (AbstractSingleton._instances.has(className)) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`${className} is a singleton and has already been instantiated.`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
AbstractSingleton._instances.set(className, this);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves the singleton instance of the derived class.
|
|
24
|
+
* If no instance exists, it initializes one.
|
|
25
|
+
*
|
|
26
|
+
* @returns The singleton instance.
|
|
27
|
+
*/
|
|
28
|
+
public static getInstance<T extends AbstractSingleton<T>>(
|
|
29
|
+
this: new () => T,
|
|
30
|
+
): T {
|
|
31
|
+
const className = this.name;
|
|
32
|
+
if (!AbstractSingleton._instances.has(className)) {
|
|
33
|
+
AbstractSingleton._instances.set(className, new this());
|
|
34
|
+
}
|
|
35
|
+
return AbstractSingleton._instances.get(className) as T;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Clears the singleton instance, useful for testing or resetting state.
|
|
40
|
+
*/
|
|
41
|
+
public static clearInstance<T extends AbstractSingleton<T>>(
|
|
42
|
+
this: new () => T,
|
|
43
|
+
): void {
|
|
44
|
+
AbstractSingleton._instances.delete(this.name);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { AbstractProcess } from "../abstract/AbstractProcess";
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Class
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* AbstractValidator provides a base class for validation.
|
|
13
|
+
* Extends AbstractProcess for consistent logging and validation utility
|
|
14
|
+
* methods.
|
|
15
|
+
* Subclasses should implement the specific `validateProperty` method for
|
|
16
|
+
* custom validation logic.
|
|
17
|
+
*/
|
|
18
|
+
export abstract class AbstractValidator<T> extends AbstractProcess {
|
|
19
|
+
// Parameters
|
|
20
|
+
// ========================================================================
|
|
21
|
+
|
|
22
|
+
// Constructor
|
|
23
|
+
// ========================================================================
|
|
24
|
+
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Abstract Methods
|
|
30
|
+
// ========================================================================
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Validates an entire object.
|
|
34
|
+
* @param target - The object to validate.
|
|
35
|
+
* @throws Error if validation fails for any property.
|
|
36
|
+
*/
|
|
37
|
+
public validate(target: T): void {
|
|
38
|
+
if (!target || typeof target !== "object") {
|
|
39
|
+
throw new Error("Target must be a valid object.");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const key in target) {
|
|
43
|
+
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|
44
|
+
this.validateProperty(key as keyof T, target[key as keyof T]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.logInfo("Validation completed successfully.");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Validates a specific property of the object.
|
|
53
|
+
* Subclasses must implement this method to provide specific validation logic.
|
|
54
|
+
*
|
|
55
|
+
* @param key - The key of the property being validated.
|
|
56
|
+
* @param value - The value of the property being validated.
|
|
57
|
+
*/
|
|
58
|
+
protected abstract validateProperty<K extends keyof T>(
|
|
59
|
+
key: K,
|
|
60
|
+
value: T[K],
|
|
61
|
+
): void;
|
|
62
|
+
|
|
63
|
+
// Validation Methods
|
|
64
|
+
// ========================================================================
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Validates a numeric value.
|
|
68
|
+
*
|
|
69
|
+
* @param key - The key being validated.
|
|
70
|
+
* @param value - The numeric value to validate.
|
|
71
|
+
* @throws Error if the value is not a non-negative number.
|
|
72
|
+
*/
|
|
73
|
+
protected validateNumber<K extends keyof T>(key: K, value: T[K]): void {
|
|
74
|
+
if (typeof value !== "number" || value < 0) {
|
|
75
|
+
this.throwValidationError(
|
|
76
|
+
key,
|
|
77
|
+
value,
|
|
78
|
+
"Must be a non-negative number.",
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Validates a boolean value.
|
|
85
|
+
*
|
|
86
|
+
* @param key - The key being validated.
|
|
87
|
+
* @param value - The boolean value to validate.
|
|
88
|
+
* @throws Error if the value is not a boolean.
|
|
89
|
+
*/
|
|
90
|
+
protected validateBoolean<K extends keyof T>(key: K, value: T[K]): void {
|
|
91
|
+
if (typeof value !== "boolean") {
|
|
92
|
+
this.throwValidationError(key, value, "Must be a boolean.");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Validates a string value.
|
|
98
|
+
*
|
|
99
|
+
* @param key - The key being validated.
|
|
100
|
+
* @param value - The string value to validate.
|
|
101
|
+
* @throws Error if the value is not a non-empty string.
|
|
102
|
+
*/
|
|
103
|
+
protected validateString<K extends keyof T>(key: K, value: T[K]): void {
|
|
104
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
105
|
+
this.throwValidationError(
|
|
106
|
+
key,
|
|
107
|
+
value,
|
|
108
|
+
"Must be a non-empty string.",
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Validates an object value.
|
|
115
|
+
*
|
|
116
|
+
* @param key - The key being validated.
|
|
117
|
+
* @param value - The object value to validate.
|
|
118
|
+
* @throws Error if the value is not a valid object.
|
|
119
|
+
*/
|
|
120
|
+
protected validateObject<K extends keyof T>(key: K, value: T[K]): void {
|
|
121
|
+
if (
|
|
122
|
+
typeof value !== "object" ||
|
|
123
|
+
value === null ||
|
|
124
|
+
Array.isArray(value)
|
|
125
|
+
) {
|
|
126
|
+
this.throwValidationError(key, value, "Must be a valid object.");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Utility Methods
|
|
131
|
+
// ========================================================================
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Logs validation success for a property.
|
|
135
|
+
* @param key - The property key.
|
|
136
|
+
* @param value - The value of the property.
|
|
137
|
+
*/
|
|
138
|
+
protected logValidationSuccess(key: keyof T, value: T[keyof T]): void {
|
|
139
|
+
const message = `
|
|
140
|
+
Validation successful for property "${String(key)}"
|
|
141
|
+
with value: ${JSON.stringify(value)}
|
|
142
|
+
`;
|
|
143
|
+
this.logSuccess(message);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Throws a standardized validation error.
|
|
148
|
+
*
|
|
149
|
+
* @param key - The key being validated.
|
|
150
|
+
* @param value - The invalid value.
|
|
151
|
+
* @param message - Additional error message.
|
|
152
|
+
* @throws Error with a formatted message.
|
|
153
|
+
*/
|
|
154
|
+
protected throwValidationError<K extends keyof T>(
|
|
155
|
+
key: K,
|
|
156
|
+
value: T[K],
|
|
157
|
+
message: string,
|
|
158
|
+
): void {
|
|
159
|
+
const errorMessage = `
|
|
160
|
+
Validation failed for "${String(key)}"
|
|
161
|
+
with value "${JSON.stringify(value)}".
|
|
162
|
+
${message}
|
|
163
|
+
`;
|
|
164
|
+
this.logError(errorMessage);
|
|
165
|
+
throw new Error(errorMessage);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Import
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import yaml from "js-yaml";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { ConfigInterface } from "../../interface/ConfigInterface";
|
|
9
|
+
import { AbstractProcess } from "../abstract/AbstractProcess";
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Class
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ConfigLoader is responsible for loading and parsing configuration files
|
|
17
|
+
* (`kist.yaml` or `kist.yml` by default). It validates the configuration
|
|
18
|
+
* structure and provides it in a usable format for the pipeline.
|
|
19
|
+
* Extends `AbstractProcess` for consistent logging.
|
|
20
|
+
*/
|
|
21
|
+
export class ConfigLoader extends AbstractProcess {
|
|
22
|
+
// Parameters
|
|
23
|
+
// ========================================================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Resolved path to the configuration file, if found.
|
|
27
|
+
*/
|
|
28
|
+
private configPath: string | null = null;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Default filenames to search for configuration files.
|
|
32
|
+
*/
|
|
33
|
+
private readonly defaultFilenames = ["kist.yaml", "kist.yml"];
|
|
34
|
+
|
|
35
|
+
// Constructor
|
|
36
|
+
// ========================================================================
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Constructs a ConfigLoader instance.
|
|
40
|
+
* Searches for `kist.yaml` or `kist.yml` in the working directory
|
|
41
|
+
* unless a custom path is provided.
|
|
42
|
+
*
|
|
43
|
+
* @param configPath - Optional custom configuration file path.
|
|
44
|
+
*/
|
|
45
|
+
constructor(configPath?: string) {
|
|
46
|
+
super();
|
|
47
|
+
if (configPath) {
|
|
48
|
+
this.configPath = path.resolve(process.cwd(), configPath);
|
|
49
|
+
this.logDebug(`Custom configuration path set: ${this.configPath}`);
|
|
50
|
+
} else {
|
|
51
|
+
this.logDebug("ConfigLoader initialized without custom path.");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Methods
|
|
56
|
+
// ========================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Initializes the loader by locating the configuration file.
|
|
60
|
+
* Searches for `kist.yaml` or `kist.yml` by default.
|
|
61
|
+
*
|
|
62
|
+
* @param configPath - Optional custom configuration file path.
|
|
63
|
+
*/
|
|
64
|
+
public async initialize(configPath?: string): Promise<void> {
|
|
65
|
+
const searchPaths = configPath ? [configPath] : this.defaultFilenames;
|
|
66
|
+
|
|
67
|
+
this.logDebug(`Current working directory: ${process.cwd()}`);
|
|
68
|
+
this.logDebug("Searching for configuration files...");
|
|
69
|
+
|
|
70
|
+
for (const fileName of searchPaths) {
|
|
71
|
+
const resolvedPath = path.resolve(process.cwd(), fileName);
|
|
72
|
+
this.logDebug(`Checking: ${resolvedPath}`);
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await fs.promises.access(
|
|
76
|
+
resolvedPath,
|
|
77
|
+
fs.constants.F_OK | fs.constants.R_OK,
|
|
78
|
+
);
|
|
79
|
+
this.configPath = resolvedPath;
|
|
80
|
+
this.logDebug(`Configuration file found: ${resolvedPath}`);
|
|
81
|
+
return;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
this.logDebug(`File not accessible: ${resolvedPath}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.logWarn(
|
|
88
|
+
"No configuration file found. Proceeding with default settings.",
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Loads and validates the configuration file.
|
|
94
|
+
*
|
|
95
|
+
* @returns Parsed and validated configuration object.
|
|
96
|
+
* @throws Error if the configuration file cannot be read or validated.
|
|
97
|
+
*/
|
|
98
|
+
public async loadConfig(): Promise<ConfigInterface> {
|
|
99
|
+
if (!this.configPath) {
|
|
100
|
+
this.logWarn(
|
|
101
|
+
"No configuration file found. Using default configuration.",
|
|
102
|
+
);
|
|
103
|
+
return { stages: [] };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
this.logDebug(`Loading configuration from: ${this.configPath}`);
|
|
108
|
+
const fileContents = await fs.promises.readFile(
|
|
109
|
+
this.configPath,
|
|
110
|
+
"utf8",
|
|
111
|
+
);
|
|
112
|
+
const config = yaml.load(fileContents) as ConfigInterface;
|
|
113
|
+
|
|
114
|
+
this.validateConfig(config);
|
|
115
|
+
this.logDebug(
|
|
116
|
+
`Successfully loaded configuration from: ${this.configPath}`,
|
|
117
|
+
);
|
|
118
|
+
return config;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
this.logError("Failed to load configuration.", error);
|
|
121
|
+
throw new Error(
|
|
122
|
+
`Failed to load configuration: ${(error as Error).message}`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Validates the structure of the configuration.
|
|
129
|
+
*
|
|
130
|
+
* @param config - The configuration object to validate.
|
|
131
|
+
* @throws Error if validation fails.
|
|
132
|
+
*/
|
|
133
|
+
private validateConfig(config: ConfigInterface): void {
|
|
134
|
+
if (!Array.isArray(config.stages)) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
"Invalid configuration: 'stages' must be an array.",
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
this.logDebug("Configuration structure validated successfully.");
|
|
140
|
+
}
|
|
141
|
+
}
|