Various utilities for electron-builder ecosystem including process execution, file operations, architecture handling, and cross-platform building support.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Concurrent task execution with cancellation support, promise utilities, and error aggregation for managing complex asynchronous workflows. Provides utilities for task coordination, error handling, and promise-based operations.
Manages concurrent execution of multiple asynchronous tasks with cancellation support.
/**
* Manages concurrent asynchronous tasks with cancellation support
*/
class AsyncTaskManager {
/** Array of managed task promises */
readonly tasks: Array<Promise<any>>;
/** Array of accumulated errors from failed tasks */
private readonly errors: Array<Error>;
/**
* Create task manager with cancellation token
* @param cancellationToken - Token for task cancellation
*/
constructor(cancellationToken: CancellationToken);
/**
* Add a task function to be executed
* @param task - Function returning a promise
*/
add(task: () => Promise<any>): void;
/**
* Add an already-created promise to be managed
* @param promise - Promise to manage
*/
addTask(promise: Promise<any>): void;
/**
* Cancel all managed tasks
*/
cancelTasks(): void;
/**
* Wait for all tasks to complete and return results
* @returns Promise resolving to array of task results
* @throws NestedError if any tasks failed
*/
awaitTasks(): Promise<Array<any>>;
}Usage Examples:
import { AsyncTaskManager } from "builder-util";
// Create task manager
const cancellationToken = new CancellationToken();
const taskManager = new AsyncTaskManager(cancellationToken);
// Add task functions
taskManager.add(async () => {
return await compileTypeScript();
});
taskManager.add(async () => {
return await bundleAssets();
});
taskManager.add(async () => {
return await optimizeImages();
});
// Add existing promises
const existingTask = processData();
taskManager.addTask(existingTask);
try {
// Wait for all tasks to complete
const results = await taskManager.awaitTasks();
console.log("All tasks completed:", results);
} catch (error) {
console.error("Some tasks failed:", error);
// Cancel remaining tasks if needed
taskManager.cancelTasks();
}Utility functions for enhanced promise handling and error management.
/**
* Execute a promise with a guaranteed finally block
* @param promise - Promise to execute
* @param task - Function to run in finally block, receives error status
* @returns Promise resolving to the original promise result
*/
function executeFinally<T>(
promise: Promise<T>,
task: (isErrorOccurred: boolean) => Promise<any>
): Promise<T>;
/**
* Return null if promise fails due to file not existing
* @param promise - Promise that might fail with ENOENT
* @returns Promise resolving to result or null if file doesn't exist
*/
function orNullIfFileNotExist<T>(promise: Promise<T>): Promise<T | null>;
/**
* Return fallback value if promise fails due to file not existing
* @param promise - Promise that might fail with ENOENT
* @param fallbackValue - Value to return if file doesn't exist
* @returns Promise resolving to result or fallback value
*/
function orIfFileNotExist<T>(promise: Promise<T>, fallbackValue: T): Promise<T>;Usage Examples:
import { executeFinally, orNullIfFileNotExist, orIfFileNotExist } from "builder-util";
// Execute with guaranteed cleanup
const result = await executeFinally(
processLargeFile("/path/to/file.dat"),
async (isErrorOccurred) => {
// Cleanup always runs, regardless of success/failure
await cleanupTempFiles();
if (isErrorOccurred) {
console.log("Processing failed, cleanup completed");
} else {
console.log("Processing succeeded, cleanup completed");
}
}
);
// Handle optional file operations
const config = await orNullIfFileNotExist(
readFile("/optional/config.json")
);
if (config) {
console.log("Config loaded:", config);
} else {
console.log("No config file found, using defaults");
}
// Handle with fallback value
const settings = await orIfFileNotExist(
readSettingsFile("/user/settings.json"),
getDefaultSettings()
);Specialized error class for handling multiple related errors.
/**
* Error class that aggregates multiple errors into a single error
*/
class NestedError extends Error {
/**
* Create error from array of errors
* @param errors - Array of errors to aggregate
* @param message - Optional custom message prefix
*/
constructor(errors: Array<Error>, message?: string);
}Usage Examples:
import { NestedError } from "builder-util";
// Collect errors from multiple operations
const errors: Array<Error> = [];
try {
await operation1();
} catch (error) {
errors.push(error);
}
try {
await operation2();
} catch (error) {
errors.push(error);
}
try {
await operation3();
} catch (error) {
errors.push(error);
}
// Throw aggregated error if any failed
if (errors.length > 0) {
throw new NestedError(errors, "Multiple operations failed:");
}Utility for handling fatal errors and process termination.
/**
* Print error and exit process with code 1
* @param error - Error to print before exiting
*/
function printErrorAndExit(error: Error): void;Usage Examples:
import { printErrorAndExit } from "builder-util";
// Handle fatal errors
process.on("unhandledRejection", (error: Error) => {
console.error("Unhandled promise rejection:");
printErrorAndExit(error);
});
// Use in CLI applications
try {
await runBuildProcess();
} catch (error) {
printErrorAndExit(error);
}import { AsyncTaskManager } from "builder-util";
class BuildPipeline {
async build(targets: Array<BuildTarget>) {
const cancellationToken = new CancellationToken();
const taskManager = new AsyncTaskManager(cancellationToken);
// Add build tasks for each target
for (const target of targets) {
taskManager.add(async () => {
console.log(`Building for ${target.platform}-${target.arch}`);
return await this.buildForTarget(target);
});
}
// Add asset processing in parallel
taskManager.add(async () => {
return await this.processAssets();
});
taskManager.add(async () => {
return await this.generateManifests();
});
try {
const results = await taskManager.awaitTasks();
console.log("All build tasks completed");
return results;
} catch (error) {
console.error("Build failed:", error);
taskManager.cancelTasks();
throw error;
}
}
}import { executeFinally } from "builder-util";
class ResourceManager {
async processWithResources<T>(operation: () => Promise<T>): Promise<T> {
const resources = await this.acquireResources();
return executeFinally(
operation(),
async (isErrorOccurred) => {
await this.releaseResources(resources);
if (isErrorOccurred) {
await this.cleanupFailedOperation();
}
}
);
}
private async acquireResources() {
// Acquire database connections, file handles, etc.
return {
dbConnection: await connectToDatabase(),
tempDir: await createTempDirectory()
};
}
private async releaseResources(resources: any) {
// Always cleanup resources
await resources.dbConnection?.close();
await removeTempDirectory(resources.tempDir);
}
}import { orNullIfFileNotExist, orIfFileNotExist } from "builder-util";
class ConfigManager {
async loadConfiguration(): Promise<AppConfig> {
// Try loading user config, fall back to defaults
const userConfig = await orNullIfFileNotExist(
this.loadUserConfig()
);
const projectConfig = await orIfFileNotExist(
this.loadProjectConfig(),
this.getDefaultProjectConfig()
);
// Merge configurations
return {
...this.getDefaultConfig(),
...projectConfig,
...userConfig
};
}
private async loadUserConfig() {
const configPath = path.join(os.homedir(), ".myapp", "config.json");
return JSON.parse(await fs.readFile(configPath, "utf8"));
}
private async loadProjectConfig() {
return JSON.parse(await fs.readFile("./myapp.config.json", "utf8"));
}
}import { NestedError } from "builder-util";
class ValidationEngine {
async validateProject(projectPath: string): Promise<ValidationResult> {
const errors: Array<Error> = [];
const warnings: Array<string> = [];
// Collect all validation errors
try {
await this.validatePackageJson(projectPath);
} catch (error) {
errors.push(error);
}
try {
await this.validateTypeScript(projectPath);
} catch (error) {
errors.push(error);
}
try {
await this.validateAssets(projectPath);
} catch (error) {
errors.push(error);
}
// Return results or throw aggregated error
if (errors.length > 0) {
throw new NestedError(errors, "Project validation failed:");
}
return {
isValid: true,
warnings
};
}
}Install with Tessl CLI
npx tessl i tessl/npm-builder-util