0
# Utility Functions
1
2
General-purpose utilities for common scripting tasks including retry logic, error handling, string processing, and vendor library access.
3
4
## Capabilities
5
6
### Retry and Resilience
7
8
Implement retry logic with various backoff strategies for handling transient failures.
9
10
```typescript { .api }
11
/**
12
* Retry a function with exponential backoff
13
* @param count - Number of retry attempts
14
* @param callback - Function to retry
15
* @returns Promise resolving to callback result
16
*/
17
function retry<T>(count: number, callback: () => T): Promise<T>;
18
19
/**
20
* Retry a function with custom backoff strategy
21
* @param count - Number of retry attempts
22
* @param duration - Fixed delay or generator for dynamic delays
23
* @param callback - Function to retry
24
* @returns Promise resolving to callback result
25
*/
26
function retry<T>(
27
count: number,
28
duration: Duration | Generator<number>,
29
callback: () => T
30
): Promise<T>;
31
32
/**
33
* Generate exponential backoff delays
34
* @param max - Maximum delay (default: '60s')
35
* @param delay - Initial delay (default: '100ms')
36
* @returns Generator yielding delay values in milliseconds
37
*/
38
function expBackoff(
39
max?: Duration,
40
delay?: Duration
41
): Generator<number, void, unknown>;
42
```
43
44
**Usage Examples:**
45
46
```typescript
47
import { retry, expBackoff, $, echo, fetch } from "zx";
48
49
// Simple retry
50
const result = await retry(3, async () => {
51
const response = await fetch('https://unreliable-api.example.com/data');
52
if (!response.ok) throw new Error(`HTTP ${response.status}`);
53
return response.json();
54
});
55
56
// Retry with fixed delay
57
const fileContent = await retry(5, '2s', async () => {
58
return await $`cat /proc/meminfo`;
59
});
60
61
// Retry with exponential backoff
62
const backoffGen = expBackoff('30s', '500ms');
63
const stableResult = await retry(10, backoffGen, async () => {
64
const healthCheck = await $`curl -f https://service.example.com/health`;
65
return healthCheck.stdout;
66
});
67
68
// Custom retry with logging
69
const deployment = await retry(3, '5s', async () => {
70
try {
71
echo('Attempting deployment...');
72
await $`kubectl apply -f deployment.yaml`;
73
await $`kubectl rollout status deployment/myapp`;
74
echo('Deployment successful');
75
return 'success';
76
} catch (error) {
77
echo`Deployment failed: ${error.message}`;
78
throw error;
79
}
80
});
81
82
// Complex backoff strategy
83
function* customBackoff() {
84
const delays = [1000, 2000, 5000, 10000, 30000]; // Custom delays
85
for (const delay of delays) {
86
yield delay;
87
}
88
while (true) {
89
yield 30000; // Max delay for remaining attempts
90
}
91
}
92
93
const criticalOperation = await retry(20, customBackoff(), async () => {
94
return await $`important-operation`;
95
});
96
```
97
98
### String Processing
99
100
Utilities for processing and formatting strings in shell contexts.
101
102
```typescript { .api }
103
/**
104
* Quote shell arguments to prevent injection
105
* @param arg - String to quote for shell safety
106
* @returns Properly quoted string
107
*/
108
function quote(arg: string): string;
109
110
/**
111
* Quote arguments for PowerShell
112
* @param arg - String to quote for PowerShell safety
113
* @returns Properly quoted string for PowerShell
114
*/
115
function quotePowerShell(arg: string): string;
116
```
117
118
**Usage Examples:**
119
120
```typescript
121
import { quote, quotePowerShell, $, echo } from "zx";
122
123
// Safe shell argument quoting
124
const userInput = "file with spaces & special chars";
125
const quoted = quote(userInput);
126
echo`Quoted: ${quoted}`;
127
128
// Use in commands
129
const filename = "my file.txt";
130
await $`cat ${quote(filename)}`; // Safer than direct interpolation
131
132
// PowerShell quoting
133
const psArg = "C:\\Program Files\\My App\\data.txt";
134
const psQuoted = quotePowerShell(psArg);
135
echo`PowerShell quoted: ${psQuoted}`;
136
137
// Platform-specific quoting
138
const path = "/path/with spaces/file.txt";
139
const safePath = process.platform === 'win32'
140
? quotePowerShell(path)
141
: quote(path);
142
143
await $`ls ${safePath}`;
144
```
145
146
### Error Handling
147
148
Error classes and utilities for better error reporting.
149
150
```typescript { .api }
151
/**
152
* Enhanced error class for command failures
153
*/
154
class Fail extends Error {
155
constructor(message?: string);
156
157
/** Format exit error message */
158
static formatExitMessage(code: number, signal: string, stderr: string): string;
159
160
/** Format general error message */
161
static formatErrorMessage(error: Error): string;
162
163
/** Format detailed error information */
164
static formatErrorDetails(error: Error): string;
165
166
/** Get exit code information */
167
static getExitCodeInfo(code: number): string;
168
}
169
```
170
171
**Usage Examples:**
172
173
```typescript
174
import { Fail, $, echo } from "zx";
175
176
// Custom error handling
177
function validateInput(input) {
178
if (!input || input.trim().length === 0) {
179
throw new Fail('Input cannot be empty');
180
}
181
return input.trim();
182
}
183
184
try {
185
const userInput = validateInput('');
186
} catch (error) {
187
if (error instanceof Fail) {
188
echo`Validation error: ${error.message}`;
189
}
190
}
191
192
// Process error formatting
193
try {
194
await $`exit 1`;
195
} catch (error) {
196
echo('Exit message:', Fail.formatExitMessage(1, null, 'Command failed'));
197
echo('Error details:', Fail.formatErrorDetails(error));
198
}
199
```
200
201
### Logging System
202
203
Structured logging with different output modes and filtering.
204
205
```typescript { .api }
206
/**
207
* Logging function with structured output
208
* @param entry - Log entry object or message
209
*/
210
function log(entry: LogEntry | any): void;
211
212
interface LogEntry {
213
/** Log entry type/category */
214
kind: string;
215
/** Whether to show verbose output */
216
verbose?: boolean;
217
/** Error message */
218
error?: string;
219
/** Additional metadata */
220
[key: string]: any;
221
}
222
```
223
224
**Usage Examples:**
225
226
```typescript
227
import { log, $ } from "zx";
228
229
// Structured logging
230
log({
231
kind: 'deployment',
232
status: 'started',
233
environment: 'production',
234
verbose: true
235
});
236
237
// Error logging
238
log({
239
kind: 'error',
240
message: 'Database connection failed',
241
error: 'Connection timeout',
242
retries: 3
243
});
244
245
// Simple message logging
246
log('Starting backup process...');
247
248
// Conditional verbose logging
249
log({
250
kind: 'debug',
251
message: 'Processing file batch',
252
count: 150,
253
verbose: $.verbose
254
});
255
```
256
257
### Vendor Library Access
258
259
Access to commonly used libraries bundled with zx.
260
261
```typescript { .api }
262
/**
263
* Command line argument parser
264
*/
265
declare const minimist: typeof import('minimist') & {
266
(args: string[], opts?: minimist.Opts): minimist.ParsedArgs;
267
};
268
269
/**
270
* Environment variable loader with dotenv config functionality
271
*/
272
declare const dotenv: {
273
config(options?: { path?: string }): { parsed?: Record<string, string> };
274
};
275
276
/**
277
* Enhanced file system operations (fs-extra)
278
*/
279
declare const fs: typeof import('fs-extra');
280
281
/**
282
* YAML parser and serializer
283
*/
284
declare const YAML: {
285
parse(text: string): any;
286
stringify(object: any): string;
287
};
288
289
/**
290
* File globbing and pattern matching (globby)
291
*/
292
declare const glob: {
293
(patterns: string | readonly string[], options?: GlobbyOptions): Promise<string[]>;
294
sync: (patterns: string | readonly string[], options?: GlobbyOptions) => string[];
295
globby: typeof glob;
296
convertPathToPattern: (path: string) => string;
297
isDynamicPattern: (pattern: string) => boolean;
298
};
299
300
/**
301
* Terminal string styling (chalk)
302
*/
303
declare const chalk: ChalkInstance;
304
305
/**
306
* Find executable in PATH
307
*/
308
declare const which: {
309
(cmd: string): Promise<string>;
310
sync: (cmd: string) => string;
311
};
312
313
/**
314
* Process information utilities
315
*/
316
declare const ps: {
317
findAll(): Promise<Array<{ pid: number; name: string; cmd: string }>>;
318
};
319
```
320
321
**Usage Examples:**
322
323
```typescript
324
import {
325
minimist, dotenv, fs, YAML, glob, chalk, which, ps, echo
326
} from "zx";
327
328
// Command line parsing
329
const args = minimist(process.argv.slice(2), {
330
boolean: ['verbose', 'dry-run'],
331
string: ['env', 'config'],
332
default: { env: 'development' }
333
});
334
echo`Environment: ${args.env}`;
335
336
// Environment variables
337
dotenv.config({ path: '.env.local' });
338
echo`Database URL: ${process.env.DATABASE_URL}`;
339
340
// File system operations
341
await fs.ensureDir('build/assets');
342
const packageInfo = await fs.readJson('package.json');
343
echo`Project: ${packageInfo.name}`;
344
345
// YAML processing
346
const config = YAML.parse(await fs.readFile('config.yaml', 'utf8'));
347
echo`Config loaded: ${config.app.name}`;
348
349
// File globbing
350
const jsFiles = await glob('src/**/*.js');
351
echo`Found ${jsFiles.length} JavaScript files`;
352
353
// Terminal styling
354
echo(chalk.green('✓ Success'), chalk.blue('Deployment completed'));
355
echo(chalk.red.bold('Error:'), chalk.yellow('Configuration missing'));
356
357
// Executable discovery
358
const dockerPath = await which('docker');
359
if (dockerPath) {
360
echo`Docker found at: ${dockerPath}`;
361
} else {
362
echo(chalk.red('Docker not found in PATH'));
363
}
364
365
// Process information
366
const processes = await ps.findAll();
367
const nodeProcesses = processes.filter(p => p.name.includes('node'));
368
echo`Found ${nodeProcesses.length} Node.js processes`;
369
```
370
371
### Version Information
372
373
Access package version information and dependency versions.
374
375
```typescript { .api }
376
/**
377
* ZX package version string
378
*/
379
declare const VERSION: string;
380
381
/**
382
* Alias for VERSION
383
*/
384
declare const version: string;
385
386
/**
387
* Version information for zx and bundled dependencies
388
*/
389
declare const versions: Record<string, string>;
390
```
391
392
**Usage Examples:**
393
394
```typescript
395
import { VERSION, version, versions, echo } from "zx";
396
397
echo`Running ZX version: ${VERSION}`;
398
echo`Version (alias): ${version}`;
399
400
// Version comparison
401
const [major, minor, patch] = VERSION.split('.').map(n => parseInt(n));
402
if (major >= 8) {
403
echo('Using modern ZX features');
404
}
405
406
// Dependency versions
407
echo`Bundled dependencies:`;
408
for (const [dep, ver] of Object.entries(versions)) {
409
echo` ${dep}: ${ver}`;
410
}
411
412
// Check specific dependency version
413
echo`Using chalk version: ${versions.chalk}`;
414
echo`Using minimist version: ${versions.minimist}`;
415
```
416
417
### Argument Parsing Utilities
418
419
Enhanced argument parsing with additional processing options.
420
421
```typescript { .api }
422
/**
423
* Global parsed arguments (automatically populated)
424
*/
425
declare const argv: minimist.ParsedArgs;
426
427
/**
428
* Update global argv with new arguments
429
* @param args - Arguments to parse
430
* @param opts - Parsing options
431
*/
432
function updateArgv(args?: string[], opts?: ArgvOpts): void;
433
434
interface ArgvOpts extends minimist.Opts {
435
/** Convert kebab-case to camelCase */
436
camelCase?: boolean;
437
/** Parse 'true'/'false' strings to booleans */
438
parseBoolean?: boolean;
439
}
440
```
441
442
**Usage Examples:**
443
444
```typescript
445
import { argv, updateArgv, echo } from "zx";
446
447
// Access global arguments
448
echo`Script arguments:`, argv;
449
450
if (argv.help || argv.h) {
451
echo('Usage: script.mjs [options]');
452
echo('Options:');
453
echo(' --env, -e Environment (default: development)');
454
echo(' --verbose, -v Enable verbose logging');
455
echo(' --help, -h Show this help');
456
process.exit(0);
457
}
458
459
// Update arguments dynamically
460
updateArgv(['--database-url', 'postgres://localhost/mydb'], {
461
camelCase: true
462
});
463
464
echo`Database URL: ${argv.databaseUrl}`;
465
466
// Boolean parsing
467
updateArgv(['--enable-cache', 'true', '--debug', 'false'], {
468
parseBoolean: true
469
});
470
471
echo`Cache enabled: ${argv.enableCache}`; // true (boolean)
472
echo`Debug mode: ${argv.debug}`; // false (boolean)
473
```
474
475
## Types
476
477
```typescript { .api }
478
/**
479
* Duration specification as string or number
480
*/
481
type Duration = string | number;
482
483
/**
484
* Log entry structure
485
*/
486
interface LogEntry {
487
kind: string;
488
verbose?: boolean;
489
error?: string;
490
[key: string]: any;
491
}
492
493
/**
494
* Parsed command line arguments
495
*/
496
interface ParsedArgs {
497
_: string[];
498
[key: string]: any;
499
}
500
501
/**
502
* Argument parsing options
503
*/
504
interface ArgvOpts extends minimist.Opts {
505
camelCase?: boolean;
506
parseBoolean?: boolean;
507
}
508
```