# Examples
## 1 ā Process execution with real-time monitoring
> Execute commands with live output streaming and error handling.
```ts
import { executeProcess, ProcessObserver } from '@push-based/utils';
// Create an observer to handle process events
const observer: ProcessObserver = {
onStdout: (data) => {
console.log(`š¤ ${data.trim()}`);
},
onStderr: (data) => {
console.error(`ā ${data.trim()}`);
},
onError: (error) => {
console.error(`Process failed with code ${error.code}`);
},
onComplete: () => {
console.log('ā
Process completed successfully');
},
};
// Execute a Node.js command
const result = await executeProcess({
command: 'node',
args: ['--version'],
observer,
});
console.log(`Exit code: ${result.code}`);
console.log(`Duration: ${result.duration}ms`);
console.log(`Output: ${result.stdout.trim()}`);
// Output:
// ā š¤ v18.17.0
// ā ā
Process completed successfully
// ā Exit code: 0
// ā Duration: 45ms
// ā Output: v18.17.0
```
---
## 2 ā File pattern searching and processing
> Search for files containing specific patterns and process the results.
```ts
import {
findFilesWithPattern,
findInFile,
resolveFileCached,
} from '@push-based/utils';
// Find all TypeScript files containing 'Component'
const componentFiles = await findFilesWithPattern('./src', 'Component');
console.log(`Found ${componentFiles.length} files with 'Component':`);
componentFiles.forEach((file) => console.log(` - ${file}`));
// Get detailed information about matches in a specific file
if (componentFiles.length > 0) {
const firstFile = componentFiles[0];
const matches = await findInFile(firstFile, 'Component');
console.log(`\nDetailed matches in ${firstFile}:`);
matches.forEach((match) => {
console.log(
` Line ${match.position.startLine}, Column ${match.position.startColumn}`
);
});
// Load and cache the file content
const content = await resolveFileCached(firstFile);
console.log(`File size: ${content.length} characters`);
// Subsequent calls will use cached version
const cachedContent = await resolveFileCached(firstFile); // ā” Fast cached access
}
// Output:
// ā Found 3 files with 'Component':
// ā - ./src/app/user.component.ts
// ā - ./src/app/admin.component.ts
// ā - ./src/shared/base.component.ts
// ā
// ā Detailed matches in ./src/app/user.component.ts:
// ā Line 5, Column 14
// ā Line 12, Column 25
// ā File size: 1247 characters
```
---
## 3 ā Command formatting and logging
> Format commands with colors and context for better development experience.
```ts
import { formatCommandLog, isVerbose, calcDuration } from '@push-based/utils';
// Set verbose mode for demonstration
process.env['NG_MCP_VERBOSE'] = 'true';
// Format commands with different contexts
const commands = [
{ cmd: 'npm', args: ['install'], cwd: undefined },
{ cmd: 'npx', args: ['eslint', '--fix', 'src/'], cwd: './packages/app' },
{ cmd: 'node', args: ['build.js', '--prod'], cwd: '../tools' },
{
cmd: 'git',
args: ['commit', '-m', 'feat: add new feature'],
cwd: process.cwd(),
},
];
console.log('Formatted commands:');
commands.forEach(({ cmd, args, cwd }) => {
const formatted = formatCommandLog(cmd, args, cwd);
console.log(formatted);
});
// Performance timing example
async function timedOperation() {
const start = performance.now();
// Simulate some work
await new Promise((resolve) => setTimeout(resolve, 150));
const duration = calcDuration(start);
console.log(`Operation completed in ${duration}ms`);
}
// Verbose logging check
if (isVerbose()) {
console.log('š Verbose logging is enabled');
await timedOperation();
} else {
console.log('š Verbose logging is disabled');
}
// Output (with ANSI colors in terminal):
// ā Formatted commands:
// ā $ npm install
// ā packages/app $ npx eslint --fix src/
// ā .. $ node build.js --prod
// ā $ git commit -m feat: add new feature
// ā š Verbose logging is enabled
// ā Operation completed in 152ms
```
---
## 4 ā CLI argument generation
> Convert objects to command-line arguments for process execution.
```ts
import { objectToCliArgs, executeProcess } from '@push-based/utils';
// Simple configuration object
const config = {
_: ['npx', 'eslint'], // Command and base args
fix: true, // Boolean flag
format: 'json', // String value
ext: ['.ts', '.js'], // Array values
'max-warnings': 0, // Numeric value
quiet: false, // Negative boolean
};
const args = objectToCliArgs(config);
console.log('Generated CLI args:');
args.forEach((arg) => console.log(` ${arg}`));
// Use the generated arguments in process execution
const result = await executeProcess({
command: args[0], // 'npx'
args: args.slice(1), // Everything after the command
});
// Output:
// ā Generated CLI args:
// ā npx
// ā eslint
// ā --fix
// ā --format="json"
// ā --ext=".ts"
// ā --ext=".js"
// ā --max-warnings=0
// ā --no-quiet
// Complex nested configuration
const complexConfig = {
_: ['node', 'build.js'],
output: {
path: './dist',
format: 'esm',
},
optimization: {
minify: true,
'tree-shake': true,
},
};
const complexArgs = objectToCliArgs(complexConfig);
console.log('\nComplex nested args:');
complexArgs.forEach((arg) => console.log(` ${arg}`));
// Output:
// ā Complex nested args:
// ā node
// ā build.js
// ā --output.path="./dist"
// ā --output.format="esm"
// ā --optimization.minify
// ā --optimization.tree-shake
```
---
## 5 ā Error handling and process management
> Handle process errors gracefully with comprehensive error information.
```ts
import { executeProcess, ProcessError } from '@push-based/utils';
async function robustProcessExecution() {
const commands = [
{ command: 'node', args: ['--version'] }, // ā
Should succeed
{ command: 'nonexistent-command', args: [] }, // ā Should fail
{ command: 'node', args: ['-e', 'process.exit(1)'] }, // ā Should fail with exit code 1
];
for (const config of commands) {
try {
console.log(
`\nš Executing: ${config.command} ${config.args?.join(' ') || ''}`
);
const result = await executeProcess({
...config,
observer: {
onStdout: (data) => console.log(` š¤ ${data.trim()}`),
onStderr: (data) => console.error(` ā ${data.trim()}`),
onComplete: () => console.log(' ā
Process completed'),
},
});
console.log(
` ā
Success! Exit code: ${result.code}, Duration: ${result.duration}ms`
);
} catch (error) {
if (error instanceof ProcessError) {
console.error(` ā Process failed:`);
console.error(` Exit code: ${error.code}`);
console.error(
` Error output: ${error.stderr.trim() || 'No stderr'}`
);
console.error(
` Standard output: ${error.stdout.trim() || 'No stdout'}`
);
} else {
console.error(` ā Unexpected error: ${error}`);
}
}
}
// Example with ignoreExitCode option
console.log('\nš Executing command with ignoreExitCode=true:');
try {
const result = await executeProcess({
command: 'node',
args: ['-e', 'console.log("Hello"); process.exit(1)'],
ignoreExitCode: true,
observer: {
onStdout: (data) => console.log(` š¤ ${data.trim()}`),
onComplete: () =>
console.log(' ā
Process completed (exit code ignored)'),
},
});
console.log(` ā
Completed with exit code ${result.code} (ignored)`);
console.log(` š Output: ${result.stdout.trim()}`);
} catch (error) {
console.error(` ā This shouldn't happen with ignoreExitCode=true`);
}
}
await robustProcessExecution();
// Output:
// ā š Executing: node --version
// ā š¤ v18.17.0
// ā ā
Process completed
// ā ā
Success! Exit code: 0, Duration: 42ms
// ā
// ā š Executing: nonexistent-command
// ā ā Process failed:
// ā Exit code: null
// ā Error output: spawn nonexistent-command ENOENT
// ā Standard output: No stdout
// ā
// ā š Executing: node -e process.exit(1)
// ā ā Process failed:
// ā Exit code: 1
// ā Error output: No stderr
// ā Standard output: No stdout
// ā
// ā š Executing command with ignoreExitCode=true:
// ā š¤ Hello
// ā ā
Process completed (exit code ignored)
// ā ā
Completed with exit code 1 (ignored)
// ā š Output: Hello
```
---
## 6 ā Advanced file operations with generators
> Use async generators for efficient file processing.
```ts
import {
findAllFiles,
accessContent,
getLineHits,
isExcludedDirectory,
} from '@push-based/utils';
// Custom file finder with filtering
async function findLargeTypeScriptFiles(
baseDir: string,
minSize: number = 1000
) {
const largeFiles: string[] = [];
// Use async generator to process files one by one
for await (const file of findAllFiles(baseDir, (path) =>
path.endsWith('.ts')
)) {
try {
const stats = await fs.stat(file);
if (stats.size > minSize) {
largeFiles.push(file);
console.log(`š Large file: ${file} (${stats.size} bytes)`);
}
} catch (error) {
console.warn(`ā ļø Could not stat file: ${file}`);
}
}
return largeFiles;
}
// Process file content line by line
async function analyzeFileContent(filePath: string, searchTerm: string) {
const content = await fs.readFile(filePath, 'utf-8');
const results = {
totalLines: 0,
matchingLines: 0,
matches: [] as Array<{ line: number; hits: number; content: string }>,
};
// Use generator to process content efficiently
let lineNumber = 0;
for (const line of accessContent(content)) {
lineNumber++;
results.totalLines++;
const hits = getLineHits(line, searchTerm);
if (hits.length > 0) {
results.matchingLines++;
results.matches.push({
line: lineNumber,
hits: hits.length,
content: line.trim(),
});
}
}
return results;
}
// Directory filtering
const directories = [
'src',
'.git',
'node_modules',
'dist',
'coverage',
'.vscode',
];
directories.forEach((dir) => {
const excluded = isExcludedDirectory(dir);
console.log(`${dir}: ${excluded ? 'ā excluded' : 'ā
included'}`);
});
// Usage example
const largeFiles = await findLargeTypeScriptFiles('./src', 2000);
if (largeFiles.length > 0) {
const analysis = await analyzeFileContent(largeFiles[0], 'export');
console.log(`\nAnalysis of ${largeFiles[0]}:`);
console.log(`Total lines: ${analysis.totalLines}`);
console.log(`Lines with 'export': ${analysis.matchingLines}`);
console.log(`First few matches:`);
analysis.matches.slice(0, 3).forEach((match) => {
console.log(` Line ${match.line} (${match.hits} hits): ${match.content}`);
});
}
// Output:
// ā src: ā
included
// ā .git: ā excluded
// ā node_modules: ā excluded
// ā dist: ā excluded
// ā coverage: ā excluded
// ā .vscode: ā
included
// ā š Large file: ./src/lib/utils.ts (2247 bytes)
// ā š Large file: ./src/lib/execute-process.ts (5043 bytes)
// ā
// ā Analysis of ./src/lib/utils.ts:
// ā Total lines: 88
// ā Lines with 'export': 5
// ā First few matches:
// ā Line 2 (1 hits): export function calcDuration(start: number, stop?: number): number {
// ā Line 6 (1 hits): export function isVerbose(): boolean {
// ā Line 14 (1 hits): export function formatCommandLog(command: string, args?: string[], cwd?: string): string {
```
---
## 7 ā ES Module loading and dynamic imports
> Load ES modules dynamically and extract default exports safely.
```ts
import { loadDefaultExport } from '@push-based/utils';
// Load configuration from ES module
const config = await loadDefaultExport('./config/app.config.mjs');
console.log(`API Port: ${config.port}`);
// Load with type safety
interface AppData {
version: string;
features: string[];
}
const appData = await loadDefaultExport<AppData>('./data/app.mjs');
console.log(`App version: ${appData.version}`);
console.log(`Features: ${appData.features.join(', ')}`);
// Handle loading errors gracefully
try {
const plugin = await loadDefaultExport('./plugins/optional.mjs');
console.log('ā
Plugin loaded');
} catch (error) {
if (error.message.includes('No default export found')) {
console.warn('ā ļø Module missing default export');
} else {
console.warn('ā ļø Plugin not found, continuing without it');
}
}
// Output:
// ā API Port: 3000
// ā App version: 1.2.0
// ā Features: auth, logging, metrics
// ā ā ļø Plugin not found, continuing without it
```
---
These examples demonstrate the comprehensive capabilities of the `@push-based/utils` library for process execution, file operations, string manipulation, and development tooling in Node.js applications.