Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
vanvianen committed Dec 22, 2024
1 parent 4279bfe commit 03cdd0c
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 88 deletions.
10 changes: 5 additions & 5 deletions src/ts/core/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// Import
// ============================================================================

import { ActionInterface } from '../interface/ActionInterface';
import { ActionOptionsType } from '../types/ActionOptionsType';
import { ActionInterface } from "../interface/ActionInterface";
import { ActionOptionsType } from "../types/ActionOptionsType";


// ============================================================================
Expand All @@ -27,7 +27,7 @@ export abstract class Action implements ActionInterface {
* validation logic.
*
* @param options - The options to validate, ensuring they meet the
* action's specific requirements.
* action"s specific requirements.
* @returns A boolean indicating whether the options are valid. Default
* implementation always returns true.
*/
Expand All @@ -39,7 +39,7 @@ export abstract class Action implements ActionInterface {

/**
* Abstract method that must be implemented by derived classes to perform
* the action's main logic.
* the action"s main logic.
* This method is invoked during the step execution process.
*
* @param options - A structured set of options specific to the action's
Expand All @@ -57,7 +57,7 @@ export abstract class Action implements ActionInterface {
* @returns A string description of the action.
*/
describe(): string {
return 'Base action for executing steps in the pipeline.';
return "Base action for executing steps in the pipeline.";
}

/**
Expand Down
28 changes: 14 additions & 14 deletions src/ts/core/ActionRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
// Import
// ============================================================================

import { DirectoryCleanAction } from '../actions/DirectoryCleanAction/DirectoryCleanAction';
import { DirectoryCopyAction } from '../actions/DirectoryCopyAction/DirectoryCopyAction';
import { FileCopyAction } from '../actions/FileCopyAction/FileCopyAction';
import { PackageManagerAction } from '../actions/PackageManagerAction/PackageManagerAction';
import { StyleProcessingAction } from '../actions/StyleProcessingAction/StyleProcessingAction';
import { VersionWriteAction } from '../actions/VersionWriterAction/VersionWriterAction';
import { ActionInterface } from '../interface/ActionInterface';
import { DirectoryCleanAction } from "../actions/DirectoryCleanAction/DirectoryCleanAction";
import { DirectoryCopyAction } from "../actions/DirectoryCopyAction/DirectoryCopyAction";
import { FileCopyAction } from "../actions/FileCopyAction/FileCopyAction";
import { PackageManagerAction } from "../actions/PackageManagerAction/PackageManagerAction";
import { StyleProcessingAction } from "../actions/StyleProcessingAction/StyleProcessingAction";
import { VersionWriteAction } from "../actions/VersionWriterAction/VersionWriterAction";
import { ActionInterface } from "../interface/ActionInterface";


// ============================================================================
Expand All @@ -33,7 +33,7 @@ const actionRegistry: Map<string, new () => ActionInterface> = new Map();
* @param name - The unique name of the action. This name is used to reference
* the action in pipeline configurations.
* @param actionClass - The class that implements the ActionInterface
* interface. This class defines the action's behavior.
* interface. This class defines the action"s behavior.
* @throws Error if the action name is already registered, ensuring uniqueness
* of action names.
*/
Expand Down Expand Up @@ -74,9 +74,9 @@ export function listRegisteredActions(): string[] {
}

// Pre-register core actions
registerAction('DirectoryCleanAction', DirectoryCleanAction);
registerAction('DirectoryCopyAction', DirectoryCopyAction);
registerAction('FileCopyAction', FileCopyAction);
registerAction('PackageManagerAction', PackageManagerAction);
registerAction('StyleProcessingAction', StyleProcessingAction);
registerAction('VersionWriteAction', VersionWriteAction);
registerAction("DirectoryCleanAction", DirectoryCleanAction);
registerAction("DirectoryCopyAction", DirectoryCopyAction);
registerAction("FileCopyAction", FileCopyAction);
registerAction("PackageManagerAction", PackageManagerAction);
registerAction("StyleProcessingAction", StyleProcessingAction);
registerAction("VersionWriteAction", VersionWriteAction);
59 changes: 39 additions & 20 deletions src/ts/core/ConfigLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* and converts it into a usable format for the pipeline.
*/

import path from 'path';
import fs from 'fs';
import yaml from 'js-yaml';
import { ConfigInterface } from '../interface/ConfigInterface';
import path from "path";
import fs from "fs";
import yaml from "js-yaml";
import { ConfigInterface } from "../interface/ConfigInterface";

export class ConfigLoader {
private configPath: string;
Expand All @@ -16,39 +16,46 @@ export class ConfigLoader {
* Constructs a ConfigLoader instance, setting up the path to the
* configuration file.
*/
constructor(configFileName: string = 'pack.yaml') {
constructor(configFileName: string = "pack.yaml") {
this.configPath = path.resolve(process.cwd(), configFileName);
}

/**
* Loads the configuration from the YAML file.
* @returns ConfigInterface - The parsed configuration object containing the pipeline stages, steps, and global options.
* @throws Error if the configuration file cannot be read, parsed, or validated.
* @returns ConfigInterface - The parsed configuration object containing
* the pipeline stages, steps, and global options.
* @throws Error if the configuration file cannot be read, parsed,
* or validated.
*/
public loadConfig(): ConfigInterface {
try {
// Read and parse the YAML configuration file
const fileContents = fs.readFileSync(this.configPath, 'utf8');
const fileContents = fs.readFileSync(this.configPath, "utf8");
const config = yaml.load(fileContents) as ConfigInterface;

// Validate the configuration structure
this.validateConfig(config);

return config;
} catch (error) {
throw new Error(`Failed to load config from ${this.configPath}: ${(error as Error).message}`);
throw new Error(
`Failed to load config from ${this.configPath}: ${(error as Error).message}`
);
}
}

/**
* Validates the structure and content of the configuration object.
* Ensures that stages have unique names, valid dependencies, and that the configuration adheres to expected formats.
* Ensures that stages have unique names, valid dependencies, and that
* the configuration adheres to expected formats.
* @param config - The configuration object to validate.
* @throws Error if the configuration is invalid.
*/
private validateConfig(config: ConfigInterface): void {
if (!config || !Array.isArray(config.stages)) {
throw new Error('Invalid configuration format: "stages" must be an array.');
throw new Error(
"Invalid configuration format: 'stages' must be an array."
);
}

const stageNames = new Set<string>();
Expand All @@ -64,7 +71,9 @@ export class ConfigLoader {
if (stage.dependsOn) {
for (const dependency of stage.dependsOn) {
if (!stageNames.has(dependency)) {
throw new Error(`Stage "${stage.name}" has an undefined dependency: "${dependency}".`);
throw new Error(
`Stage "${stage.name}" has an undefined dependency: "${dependency}".`
);
}
}
}
Expand All @@ -75,31 +84,41 @@ export class ConfigLoader {
}

/**
* Validates the steps within a stage, ensuring each step has the necessary properties.
* Validates the steps within a stage, ensuring each step has the
* necessary properties.
* @param steps - The steps array to validate.
* @param stageName - The name of the stage containing the steps.
* @throws Error if any step is invalid.
*/
private validateSteps(steps: any[], stageName: string): void {
if (!Array.isArray(steps) || steps.length === 0) {
throw new Error(`Stage "${stageName}" must contain at least one step.`);
throw new Error(
`Stage "${stageName}" must contain at least one step.`
);
}

const stepNames = new Set<string>();

for (const step of steps) {
if (!step.name || typeof step.name !== 'string') {
throw new Error(`Each step in stage "${stageName}" must have a valid "name" property.`);
if (!step.name || typeof step.name !== "string") {
throw new Error(
`Each step in stage "${stageName}" must have a valid "name" property.`
);
}

if (stepNames.has(step.name)) {
throw new Error(`Duplicate step name found in stage "${stageName}": "${step.name}".`);
throw new Error(
`Duplicate step name found in stage "${stageName}": "${step.name}".`
);
}
stepNames.add(step.name);

// Further validation for step actions and options could be added here as needed
if (!step.action || typeof step.action !== 'string') {
throw new Error(`Step "${step.name}" in stage "${stageName}" must have a valid "action" property.`);
// Further validation for step actions and options could be added
// here as needed
if (!step.action || typeof step.action !== "string") {
throw new Error(
`Step "${step.name}" in stage "${stageName}" must have a valid "action" property.`
);
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/ts/core/FileWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Import
// ============================================================================

import chokidar, { FSWatcher } from 'chokidar';
import chokidar, { FSWatcher } from "chokidar";


// ============================================================================
Expand All @@ -30,7 +30,7 @@ export class FileWatcher {
this.watcher = chokidar.watch(this.pathsToWatch, {
ignored: this.ignoredPaths,
persistent: true,
ignoreInitial: true, // Prevents initial 'add' events on startup
ignoreInitial: true, // Prevents initial "add" events on startup
awaitWriteFinish: {
stabilityThreshold: 100, // Waits for file to finish writing
pollInterval: 100, // Polling interval to check for file stability
Expand All @@ -46,19 +46,19 @@ export class FileWatcher {
*/
private setupWatchers() {
this.watcher
.on('ready', () => {
console.log('File watching is active. Waiting for changes...');
.on("ready", () => {
console.log("File watching is active. Waiting for changes...");
})
.on('change', (filePath) => {
.on("change", (filePath) => {
console.log(`File changed: ${filePath}`);
try {
this.onChange(filePath);
} catch (error) {
console.error(`Error handling file change for ${filePath}:`, error);
}
})
.on('error', (error) => {
console.error('Watcher encountered an error:', error);
.on("error", (error) => {
console.error("Watcher encountered an error:", error);
});
}

Expand All @@ -73,7 +73,7 @@ export class FileWatcher {
ignoreInitial: true,
});
this.setupWatchers();
console.log('File watching started.');
console.log("File watching started.");
}
}

Expand All @@ -83,9 +83,9 @@ export class FileWatcher {
public stopWatching(): void {
if (this.watcher) {
this.watcher.close().then(() => {
console.log('File watching stopped.');
console.log("File watching stopped.");
}).catch(error => {
console.error('Error stopping file watcher:', error);
console.error("Error stopping file watcher:", error);
});
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/ts/core/Pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// Import
// ============================================================================

import { ConfigInterface } from '../interface/ConfigInterface';
import { Stage } from './Stage';
import { ConfigInterface } from "../interface/ConfigInterface";
import { Stage } from "./Stage";


// ============================================================================
Expand All @@ -27,7 +27,7 @@ export class Pipeline {
/**
* Global options that apply across the entire pipeline.
*/
private globalOptions?: ConfigInterface['globalOptions'];
private globalOptions?: ConfigInterface["globalOptions"];

/**
* Constructs a new Pipeline instance with the given configuration.
Expand All @@ -47,7 +47,7 @@ export class Pipeline {
* handling, and execution control.
*/
async run(): Promise<void> {
console.log('Starting pipeline execution...');
console.log("Starting pipeline execution...");

// Track stages that have been completed
const completedStages = new Set<string>();
Expand All @@ -59,16 +59,16 @@ export class Pipeline {
);
await this.runWithConcurrencyControl(stagePromises);
} catch (error) {
console.error('Pipeline execution failed:', error);
console.error("Pipeline execution failed:", error);
if (this.globalOptions?.haltOnFailure !== false) {
console.error('Halting pipeline due to failure.');
console.error("Halting pipeline due to failure.");
// Optionally halt the process if the pipeline is set to
// halt on failure
process.exit(1);
}
}

console.log('Pipeline execution completed successfully.');
console.log("Pipeline execution completed successfully.");
}

/**
Expand Down
Loading

0 comments on commit 03cdd0c

Please sign in to comment.