or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-commands.mdcore-build-system.mddev-file-management.mdindex.mdplatform-toolchain.mdutilities.md

utilities.mddocs/

0

# Utility Functions

1

2

Utility functions provide core infrastructure for file operations, network requests, system registry access, and cross-platform process execution used throughout node-gyp.

3

4

## Capabilities

5

6

### HTTP Download Utilities

7

8

Handles HTTP/HTTPS downloads with proper headers, proxy support, and CA certificate handling.

9

10

```javascript { .api }

11

/**

12

* Downloads files with proxy support and proper headers

13

* @param {Gyp} gyp - The gyp instance for configuration

14

* @param {string} url - URL to download from

15

* @returns {Promise<Response>} Fetch response object

16

*/

17

async function download(gyp: Gyp, url: string): Promise<Response>;

18

19

/**

20

* Reads CA certificate file for HTTPS downloads

21

* @param {string} filename - Path to CA certificate file

22

* @returns {Promise<string>} CA certificate content

23

*/

24

async function readCAFile(filename: string): Promise<string>;

25

```

26

27

**Usage Examples:**

28

29

```javascript

30

const { download, readCAFile } = require('node-gyp/lib/download');

31

const gyp = require('node-gyp');

32

33

// Download with gyp configuration

34

const gypInstance = gyp();

35

gypInstance.opts.proxy = 'http://proxy.company.com:8080';

36

37

try {

38

const response = await download(gypInstance, 'https://nodejs.org/dist/v16.14.0/node-v16.14.0-headers.tar.gz');

39

const buffer = await response.buffer();

40

console.log('Downloaded', buffer.length, 'bytes');

41

} catch (error) {

42

console.error('Download failed:', error.message);

43

}

44

45

// Use custom CA certificate

46

try {

47

const caCert = await readCAFile('/path/to/ca-certificates.crt');

48

console.log('Loaded CA certificate');

49

} catch (error) {

50

console.error('Failed to read CA file:', error.message);

51

}

52

```

53

54

**Download Features:**

55

- **Proxy Support**: Honors proxy and noproxy configuration

56

- **Custom CA**: Supports custom CA certificate files

57

- **User Agent**: Sets appropriate User-Agent headers

58

- **Timeout Handling**: Configurable request timeouts

59

- **Error Handling**: Detailed error reporting for network issues

60

61

### Process Execution Utilities

62

63

Cross-platform utilities for executing external processes with proper error handling.

64

65

```javascript { .api }

66

/**

67

* Promise wrapper for child_process.execFile with proper error handling

68

* @param {...any} args - Arguments passed to execFile (command, args, options, callback)

69

* @returns {Promise<[Error?, string?, string?]>} Tuple of [error, stdout, stderr]

70

*/

71

async function execFile(...args: any[]): Promise<[Error?, string?, string?]>;

72

```

73

74

**Usage Examples:**

75

76

```javascript

77

const { execFile } = require('node-gyp/lib/util');

78

79

// Execute command and handle results

80

const [error, stdout, stderr] = await execFile('python', ['--version']);

81

82

if (error) {

83

console.error('Command failed:', error.message);

84

} else {

85

console.log('Python version:', stdout.trim());

86

}

87

88

// Execute with options

89

const [error, stdout, stderr] = await execFile('make', ['-j4'], {

90

cwd: './build',

91

encoding: 'utf8',

92

timeout: 30000

93

});

94

95

if (!error) {

96

console.log('Build completed successfully');

97

}

98

```

99

100

### Windows Registry Utilities

101

102

Windows-specific utilities for reading registry values, used for toolchain discovery.

103

104

```javascript { .api }

105

/**

106

* Gets a value from the Windows registry

107

* @param {string} key - Registry key path

108

* @param {string} value - Value name to read

109

* @param {string[]} [addOpts] - Additional reg.exe options

110

* @returns {Promise<string>} Registry value content

111

*/

112

async function regGetValue(key: string, value: string, addOpts?: string[]): Promise<string>;

113

114

/**

115

* Searches multiple registry keys for a value, returning the first match

116

* @param {string[]} keys - Array of registry key paths to search

117

* @param {string} value - Value name to find

118

* @param {string[]} [addOpts] - Additional reg.exe options

119

* @returns {Promise<string>} First matching registry value

120

*/

121

async function regSearchKeys(keys: string[], value: string, addOpts?: string[]): Promise<string>;

122

```

123

124

**Usage Examples:**

125

126

```javascript

127

const { regGetValue, regSearchKeys } = require('node-gyp/lib/util');

128

129

// Windows only - get specific registry value

130

if (process.platform === 'win32') {

131

try {

132

const vsPath = await regGetValue(

133

'HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\VS',

134

'ProductDir'

135

);

136

console.log('Visual Studio 2015 path:', vsPath);

137

} catch (error) {

138

console.log('Visual Studio 2015 not found');

139

}

140

141

// Search multiple keys for Visual Studio installations

142

const vsKeys = [

143

'HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\16.0\\Setup\\VS',

144

'HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\15.0\\Setup\\VS',

145

'HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\VS'

146

];

147

148

try {

149

const vsPath = await regSearchKeys(vsKeys, 'ProductDir');

150

console.log('Found Visual Studio at:', vsPath);

151

} catch (error) {

152

console.log('No Visual Studio installations found');

153

}

154

}

155

```

156

157

### File Access Utilities

158

159

Cross-platform file access validation utilities.

160

161

```javascript { .api }

162

/**

163

* Returns the first file or directory from candidates that is readable by current user

164

* @param {string} logprefix - Prefix for log messages

165

* @param {string} dir - Base directory to search in

166

* @param {string[]} candidates - Array of candidate file/directory names

167

* @returns {string | undefined} Path to first accessible candidate or undefined

168

*/

169

function findAccessibleSync(logprefix: string, dir: string, candidates: string[]): string | undefined;

170

```

171

172

**Usage Examples:**

173

174

```javascript

175

const { findAccessibleSync } = require('node-gyp/lib/util');

176

177

// Find first accessible Python executable

178

const pythonDir = '/usr/bin';

179

const pythonCandidates = ['python3.9', 'python3.8', 'python3', 'python'];

180

181

const pythonPath = findAccessibleSync('python', pythonDir, pythonCandidates);

182

if (pythonPath) {

183

console.log('Found Python at:', pythonPath);

184

} else {

185

console.log('No accessible Python found');

186

}

187

188

// Find Node.js headers

189

const nodeDir = '/usr/local/include';

190

const headerCandidates = ['node/node.h', 'nodejs/node.h'];

191

192

const headerPath = findAccessibleSync('headers', nodeDir, headerCandidates);

193

if (headerPath) {

194

console.log('Found Node.js headers at:', headerPath);

195

}

196

```

197

198

## Logging Integration

199

200

All utilities integrate with the node-gyp logging system:

201

202

```javascript

203

const log = require('node-gyp/lib/log');

204

const { withPrefix } = log;

205

206

// Create prefixed logger for utility functions

207

const utilLog = withPrefix('util');

208

209

utilLog.verbose('Executing command:', 'python --version');

210

utilLog.silly('Registry query:', 'HKLM\\SOFTWARE\\...');

211

```

212

213

## Error Handling Patterns

214

215

### Network Error Handling

216

217

```javascript

218

const { download } = require('node-gyp/lib/download');

219

220

try {

221

const response = await download(gypInstance, url);

222

if (!response.ok) {

223

throw new Error(`HTTP ${response.status}: ${response.statusText}`);

224

}

225

} catch (error) {

226

if (error.code === 'ENOTFOUND') {

227

console.error('DNS resolution failed for:', url);

228

} else if (error.code === 'ECONNREFUSED') {

229

console.error('Connection refused, check proxy settings');

230

} else if (error.code === 'CERT_UNTRUSTED') {

231

console.error('SSL certificate error, check CA configuration');

232

} else {

233

console.error('Download failed:', error.message);

234

}

235

}

236

```

237

238

### Process Execution Error Handling

239

240

```javascript

241

const { execFile } = require('node-gyp/lib/util');

242

243

const [error, stdout, stderr] = await execFile('python', ['--version']);

244

245

if (error) {

246

if (error.code === 'ENOENT') {

247

console.error('Python executable not found in PATH');

248

} else if (error.code === 'EACCES') {

249

console.error('Permission denied executing Python');

250

} else if (error.signal) {

251

console.error('Python process killed by signal:', error.signal);

252

} else {

253

console.error('Python execution failed:', error.message);

254

}

255

}

256

```

257

258

### Registry Access Error Handling

259

260

```javascript

261

const { regGetValue } = require('node-gyp/lib/util');

262

263

if (process.platform === 'win32') {

264

try {

265

const value = await regGetValue(key, valueName);

266

} catch (error) {

267

if (error.message.includes('cannot find')) {

268

console.log('Registry key not found');

269

} else if (error.message.includes('Access is denied')) {

270

console.error('Registry access denied - run as administrator?');

271

} else {

272

console.error('Registry error:', error.message);

273

}

274

}

275

}

276

```

277

278

## Integration Examples

279

280

### Custom Download with Progress

281

282

```javascript

283

const { download } = require('node-gyp/lib/download');

284

const fs = require('fs');

285

286

async function downloadWithProgress(gyp, url, outputPath) {

287

const response = await download(gyp, url);

288

const total = parseInt(response.headers.get('content-length') || '0');

289

let downloaded = 0;

290

291

const fileStream = fs.createWriteStream(outputPath);

292

293

response.body.on('data', (chunk) => {

294

downloaded += chunk.length;

295

const percent = total ? (downloaded / total * 100).toFixed(1) : '?';

296

process.stdout.write(`\rDownloading: ${percent}%`);

297

});

298

299

await new Promise((resolve, reject) => {

300

response.body.pipe(fileStream);

301

response.body.on('end', resolve);

302

response.body.on('error', reject);

303

});

304

305

console.log('\nDownload completed');

306

}

307

```

308

309

### Toolchain Validation Utility

310

311

```javascript

312

const { execFile, findAccessibleSync } = require('node-gyp/lib/util');

313

314

async function validateBuildTools() {

315

const results = {

316

python: false,

317

make: false,

318

compiler: false

319

};

320

321

// Check Python

322

const [pythonError] = await execFile('python', ['--version']);

323

results.python = !pythonError;

324

325

// Check Make

326

const [makeError] = await execFile('make', ['--version']);

327

results.make = !makeError;

328

329

// Check compiler

330

const compilerCandidates = ['gcc', 'clang', 'cl.exe'];

331

for (const compiler of compilerCandidates) {

332

const [compilerError] = await execFile(compiler, ['--version']);

333

if (!compilerError) {

334

results.compiler = compiler;

335

break;

336

}

337

}

338

339

return results;

340

}

341

342

// Usage

343

const toolchainStatus = await validateBuildTools();

344

console.log('Toolchain status:', toolchainStatus);

345

```

346

347

### Cross-Platform Path Resolution

348

349

```javascript

350

const { findAccessibleSync } = require('node-gyp/lib/util');

351

const path = require('path');

352

353

function findExecutable(name, searchPaths = []) {

354

const defaultPaths = process.env.PATH.split(path.delimiter);

355

const allPaths = [...searchPaths, ...defaultPaths];

356

357

const extensions = process.platform === 'win32' ? ['.exe', '.cmd', '.bat'] : [''];

358

359

for (const searchPath of allPaths) {

360

const candidates = extensions.map(ext => name + ext);

361

const found = findAccessibleSync('executable', searchPath, candidates);

362

if (found) {

363

return found;

364

}

365

}

366

367

return null;

368

}

369

370

// Usage

371

const pythonPath = findExecutable('python3', ['/usr/local/bin', '/opt/python/bin']);

372

console.log('Python found at:', pythonPath);

373

```

374

375

## Logging Utilities

376

377

Advanced logging functions for creating custom loggers and direct output control.

378

379

```javascript { .api }

380

/**

381

* Creates log functions with predefined prefix

382

* @param {string} prefix - Prefix for log messages

383

* @returns {object} Object with logging functions for each level

384

*/

385

function withPrefix(prefix: string): object;

386

387

/**

388

* Direct stdout output function (can be nullified in tests)

389

* @param {...any} args - Arguments to output

390

*/

391

function stdout(...args: any[]): void;

392

393

/**

394

* Direct access to the logger instance

395

* @type {Logger}

396

*/

397

const logger: Logger;

398

```

399

400

**Usage Examples:**

401

402

```javascript

403

const { withPrefix, stdout, logger } = require('node-gyp/lib/log');

404

405

// Create prefixed logger

406

const myLog = withPrefix('custom');

407

myLog.info('This is a custom prefixed message');

408

myLog.verbose('Detailed information');

409

myLog.error('Error with custom prefix');

410

411

// Direct stdout access

412

stdout('Direct console output without logging formatting');

413

414

// Direct logger access

415

logger.level = 'verbose';

416

console.log('Current log level:', logger.level.id);

417

```

418

419

## Process Release Utilities

420

421

Functions for processing Node.js release information and generating download URLs.

422

423

```javascript { .api }

424

/**

425

* Processes Node.js release information for downloads and configuration

426

* @param {string[]} argv - Command arguments

427

* @param {Gyp} gyp - Gyp instance for configuration

428

* @param {string} defaultVersion - Default Node.js version

429

* @param {object} defaultRelease - Default release object

430

* @returns {object} Release information with URLs and paths

431

*/

432

function processRelease(

433

argv: string[],

434

gyp: Gyp,

435

defaultVersion: string,

436

defaultRelease: object

437

): object;

438

```

439

440

**Usage Example:**

441

442

```javascript

443

const processRelease = require('node-gyp/lib/process-release');

444

const gyp = require('node-gyp');

445

446

const gypInstance = gyp();

447

const releaseInfo = processRelease(

448

['16.14.0'],

449

gypInstance,

450

process.version,

451

process.release

452

);

453

454

console.log('Download URLs:', {

455

tarball: releaseInfo.tarballUrl,

456

headers: releaseInfo.headersUrl,

457

lib32: releaseInfo.libUrl32,

458

lib64: releaseInfo.libUrl64

459

});

460

```

461

462

## Command Usage Information

463

464

Each command module exports a usage string for help text generation.

465

466

```javascript { .api }

467

// All command modules export both function and usage

468

const buildCommand = require('node-gyp/lib/build');

469

const cleanCommand = require('node-gyp/lib/clean');

470

// etc.

471

472

/**

473

* Usage description for each command

474

* @type {string}

475

*/

476

buildCommand.usage: string;

477

cleanCommand.usage: string;

478

configureCommand.usage: string;

479

installCommand.usage: string;

480

listCommand.usage: string;

481

rebuildCommand.usage: string;

482

removeCommand.usage: string;

483

```

484

485

**Usage Example:**

486

487

```javascript

488

const buildCommand = require('node-gyp/lib/build');

489

const cleanCommand = require('node-gyp/lib/clean');

490

491

console.log('Build command:', buildCommand.usage);

492

// "Invokes `msbuild` (on Windows) or `make` (on other platforms) and builds the module"

493

494

console.log('Clean command:', cleanCommand.usage);

495

// "Removes any generated build files and the \"out\" dir"

496

497

// Generate help for all commands

498

const commands = ['build', 'clean', 'configure', 'install', 'list', 'rebuild', 'remove'];

499

commands.forEach(cmd => {

500

const cmdModule = require(`node-gyp/lib/${cmd}`);

501

console.log(`${cmd}: ${cmdModule.usage}`);

502

});

503

```