or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argv-env.mdconfiguration.mdfiles.mdindex.mdstores.mdutilities.md

utilities.mddocs/

0

# Utilities and Validation

1

2

Utility functions for key manipulation, file loading, object merging, and configuration validation with required key checking. These utilities support nconf's hierarchical configuration system.

3

4

## Capabilities

5

6

### Required Key Validation

7

8

Validate that essential configuration keys are present and throw descriptive errors for missing keys.

9

10

```javascript { .api }

11

/**

12

* Validate that required configuration keys are present

13

* @param {string[]} keys - Array of required key names (supports nested keys)

14

* @throws {Error} Throws error with missing key names if validation fails

15

* @returns {boolean} Returns true if all keys are present

16

*/

17

required(keys);

18

```

19

20

**Usage Examples:**

21

22

```javascript

23

const nconf = require('nconf');

24

25

// Basic required key validation

26

try {

27

nconf.required(['database:host', 'database:port', 'jwt:secret']);

28

console.log('All required configuration is present');

29

} catch (err) {

30

console.error('Configuration error:', err.message);

31

// Error: Missing required keys: jwt:secret

32

process.exit(1);

33

}

34

35

// Application startup validation

36

const requiredKeys = [

37

'NODE_ENV', // Environment name

38

'PORT', // Server port

39

'database:host', // Database connection

40

'database:port',

41

'database:name',

42

'redis:url', // Cache connection

43

'jwt:secret', // Authentication secret

44

'api:key' // External API key

45

];

46

47

function validateConfiguration() {

48

try {

49

return nconf.required(requiredKeys);

50

} catch (err) {

51

console.error('\n❌ Configuration Validation Failed');

52

console.error('Missing required keys:', err.message.replace('Missing required keys: ', ''));

53

console.error('\nPlease check your environment variables and configuration files.\n');

54

process.exit(1);

55

}

56

}

57

58

// Service-specific validation

59

const databaseKeys = ['database:host', 'database:port', 'database:name'];

60

const redisKeys = ['redis:host', 'redis:port'];

61

62

if (nconf.get('features:database')) {

63

nconf.required(databaseKeys);

64

}

65

66

if (nconf.get('features:caching')) {

67

nconf.required(redisKeys);

68

}

69

```

70

71

### Any Value Lookup

72

73

Get the first truthy value from a list of configuration keys, providing fallback behavior for configuration resolution.

74

75

```javascript { .api }

76

/**

77

* Get first truthy value from a list of keys

78

* @param {string[]|...string} keys - Array of keys or variable arguments

79

* @param {function} [callback] - Optional callback for async operation

80

* @returns {*} First truthy value found or null if none found

81

*/

82

any(keys, callback);

83

```

84

85

**Usage Examples:**

86

87

```javascript

88

// Array form with fallback keys

89

const dbHost = nconf.any(['DATABASE_HOST', 'DB_HOST', 'database:host']);

90

const apiKey = nconf.any(['API_KEY', 'EXTERNAL_API_KEY', 'api:key']);

91

92

// Variable arguments form

93

const port = nconf.any('PORT', 'HTTP_PORT', 'server:port', 'app:port');

94

95

// With default values

96

const timeout = nconf.any(['REQUEST_TIMEOUT', 'api:timeout']) || 5000;

97

const maxRetries = nconf.any(['MAX_RETRIES', 'retries:max']) || 3;

98

99

// Environment-specific configuration

100

const configFile = nconf.any([

101

`config/${process.env.NODE_ENV}.json`,

102

'config/default.json',

103

'./config.json'

104

]);

105

106

// Asynchronous form

107

nconf.any(['REDIS_URL', 'CACHE_URL', 'redis:url'], (err, value) => {

108

if (err) {

109

console.error('Error finding Redis URL:', err);

110

return;

111

}

112

113

if (value) {

114

console.log('Redis URL found:', value);

115

connectToRedis(value);

116

} else {

117

console.log('No Redis URL configured, skipping cache setup');

118

}

119

});

120

121

// Complex fallback logic

122

function getDatabaseConfig() {

123

// Try full connection string first

124

let dbUrl = nconf.any(['DATABASE_URL', 'DB_URL']);

125

if (dbUrl) {

126

return parseConnectionString(dbUrl);

127

}

128

129

// Fall back to individual components

130

return {

131

host: nconf.any(['DB_HOST', 'DATABASE_HOST']) || 'localhost',

132

port: nconf.any(['DB_PORT', 'DATABASE_PORT']) || 5432,

133

database: nconf.any(['DB_NAME', 'DATABASE_NAME']) || 'myapp',

134

username: nconf.any(['DB_USER', 'DATABASE_USER']) || 'postgres'

135

};

136

}

137

```

138

139

### Reset Configuration

140

141

Clear all configuration data from all writable stores, useful for testing and reinitialization.

142

143

```javascript { .api }

144

/**

145

* Clear all configuration data from writable stores

146

* @param {function} [callback] - Optional callback for async operation

147

* @returns {Provider} Provider instance for chaining

148

*/

149

reset(callback);

150

```

151

152

**Usage Examples:**

153

154

```javascript

155

// Synchronous reset

156

nconf.reset();

157

console.log('Configuration cleared');

158

159

// Asynchronous reset

160

nconf.reset((err) => {

161

if (err) {

162

console.error('Error clearing configuration:', err);

163

return;

164

}

165

console.log('Configuration reset successfully');

166

167

// Reload with fresh data

168

nconf.load((loadErr) => {

169

if (loadErr) console.error('Reload failed:', loadErr);

170

else console.log('Configuration reloaded');

171

});

172

});

173

174

// Reset and reconfigure pattern

175

function reconfigureApplication(newConfigPath) {

176

nconf

177

.reset()

178

.file({ file: newConfigPath })

179

.env()

180

.argv();

181

182

// Validate new configuration

183

try {

184

nconf.required(['database:host', 'app:port']);

185

console.log('Application reconfigured successfully');

186

return true;

187

} catch (err) {

188

console.error('Reconfiguration failed:', err.message);

189

return false;

190

}

191

}

192

193

// Testing utility

194

function cleanConfigForTest() {

195

nconf.reset();

196

nconf.defaults({

197

env: 'test',

198

database: {

199

host: 'localhost',

200

port: 5432,

201

name: 'test_db'

202

},

203

logging: {

204

level: 'error',

205

silent: true

206

}

207

});

208

}

209

```

210

211

## Static Utility Functions

212

213

### Key Manipulation

214

215

Utilities for working with nconf's colon-delimited key system.

216

217

```javascript { .api }

218

/**

219

* Join arguments into colon-delimited key

220

* @param {...string} args - Key segments to join

221

* @returns {string} Joined key with ':' delimiter

222

*/

223

nconf.key(...args);

224

225

/**

226

* Split key into array using delimiter

227

* @param {string} key - Key to split

228

* @param {string} [separator=':'] - Delimiter to split on

229

* @returns {string[]} Array of key segments

230

*/

231

nconf.path(key, separator);

232

233

/**

234

* Join arguments with custom delimiter

235

* @param {string} separator - Custom delimiter

236

* @param {...string} args - Key segments to join

237

* @returns {string} Joined key with custom delimiter

238

*/

239

nconf.keyed(separator, ...args);

240

```

241

242

**Usage Examples:**

243

244

```javascript

245

// Key building

246

const dbKey = nconf.key('database', 'connections', 'primary');

247

// Result: 'database:connections:primary'

248

249

const cacheKey = nconf.key('cache', 'redis', 'cluster', '1');

250

// Result: 'cache:redis:cluster:1'

251

252

// Key parsing

253

const segments = nconf.path('database:host:primary');

254

// Result: ['database', 'host', 'primary']

255

256

const customSegments = nconf.path('app.server.port', '.');

257

// Result: ['app', 'server', 'port']

258

259

// Custom delimiter joining

260

const envKey = nconf.keyed('__', 'APP', 'DATABASE', 'HOST');

261

// Result: 'APP__DATABASE__HOST'

262

263

const dotKey = nconf.keyed('.', 'config', 'server', 'timeout');

264

// Result: 'config.server.timeout'

265

266

// Dynamic key construction

267

function buildConfigKey(service, environment, setting) {

268

return nconf.key('services', service, environment, setting);

269

}

270

271

const redisHost = buildConfigKey('redis', 'production', 'host');

272

// Uses key: 'services:redis:production:host'

273

```

274

275

### File Loading Utilities

276

277

Utility functions for loading and merging multiple configuration files.

278

279

```javascript { .api }

280

/**

281

* Load multiple files asynchronously and merge results

282

* @param {string[]|Object} files - Array of file paths or options object

283

* @param {function} callback - Callback with (err, mergedData)

284

*/

285

nconf.loadFiles(files, callback);

286

287

/**

288

* Load multiple files synchronously and merge results

289

* @param {string[]|Object} files - Array of file paths or options object

290

* @returns {Object} Merged configuration data

291

*/

292

nconf.loadFilesSync(files);

293

```

294

295

**Usage Examples:**

296

297

```javascript

298

// Load multiple files asynchronously

299

const configFiles = [

300

'./config/default.json',

301

'./config/development.json',

302

'./config/local.json'

303

];

304

305

nconf.loadFiles(configFiles, (err, merged) => {

306

if (err) {

307

console.error('Failed to load config files:', err);

308

return;

309

}

310

311

console.log('Merged configuration:', merged);

312

// Files are merged in order, later files override earlier ones

313

});

314

315

// Load with custom format

316

nconf.loadFiles({

317

files: ['./config.ini', './local.ini'],

318

format: nconf.formats.ini

319

}, (err, data) => {

320

if (err) throw err;

321

console.log('INI config loaded:', data);

322

});

323

324

// Synchronous loading

325

try {

326

const config = nconf.loadFilesSync([

327

'./config/base.json',

328

`./config/${process.env.NODE_ENV}.json`

329

]);

330

331

console.log('Configuration loaded:', config);

332

} catch (err) {

333

console.error('Config load failed:', err.message);

334

process.exit(1);

335

}

336

337

// Environment-specific loading

338

const env = process.env.NODE_ENV || 'development';

339

const configFiles = [

340

'./config/default.json',

341

`./config/${env}.json`

342

];

343

344

// Add local override if it exists

345

const localConfig = './config/local.json';

346

if (require('fs').existsSync(localConfig)) {

347

configFiles.push(localConfig);

348

}

349

350

const mergedConfig = nconf.loadFilesSync(configFiles);

351

```

352

353

### Object Merging

354

355

Deep object merging utility used internally by nconf for combining configuration from multiple sources.

356

357

```javascript { .api }

358

/**

359

* Merge array of objects using Memory store

360

* @param {Object[]} objs - Array of objects to merge

361

* @returns {Object} Merged object with deep merging behavior

362

*/

363

nconf.merge(objs);

364

```

365

366

**Usage Examples:**

367

368

```javascript

369

// Merge configuration objects

370

const baseConfig = {

371

app: { name: 'MyApp', port: 3000 },

372

database: { host: 'localhost' }

373

};

374

375

const envConfig = {

376

app: { port: 8080, debug: true },

377

database: { port: 5432 }

378

};

379

380

const localConfig = {

381

database: { password: 'secret' }

382

};

383

384

const merged = nconf.merge([baseConfig, envConfig, localConfig]);

385

// Result: {

386

// app: { name: 'MyApp', port: 8080, debug: true },

387

// database: { host: 'localhost', port: 5432, password: 'secret' }

388

// }

389

390

// Merge with arrays (arrays are replaced, not merged)

391

const config1 = { features: ['auth', 'logging'] };

392

const config2 = { features: ['metrics', 'monitoring'] };

393

const result = nconf.merge([config1, config2]);

394

// Result: { features: ['metrics', 'monitoring'] }

395

396

// Custom merging in application code

397

function mergeEnvironmentConfigs() {

398

const configs = [];

399

400

// Base configuration

401

configs.push(require('./config/default.json'));

402

403

// Environment-specific

404

const env = process.env.NODE_ENV;

405

if (env && env !== 'development') {

406

configs.push(require(`./config/${env}.json`));

407

}

408

409

// Local overrides

410

try {

411

configs.push(require('./config/local.json'));

412

} catch (err) {

413

// Local config is optional

414

}

415

416

return nconf.merge(configs);

417

}

418

```

419

420

### Value Parsing

421

422

Parse string values to native JavaScript types, useful for processing environment variables and command-line arguments.

423

424

```javascript { .api }

425

/**

426

* Parse string value to native type

427

* @param {string} value - String value to parse

428

* @returns {*} Parsed value (boolean, number, object, array, undefined, or original string)

429

*/

430

nconf.parseValues(value);

431

```

432

433

**Usage Examples:**

434

435

```javascript

436

// Basic value parsing

437

console.log(nconf.parseValues('true')); // boolean: true

438

console.log(nconf.parseValues('false')); // boolean: false

439

console.log(nconf.parseValues('123')); // number: 123

440

console.log(nconf.parseValues('3.14')); // number: 3.14

441

console.log(nconf.parseValues('undefined')); // undefined

442

console.log(nconf.parseValues('null')); // null

443

console.log(nconf.parseValues('hello')); // string: 'hello'

444

445

// JSON parsing

446

const jsonStr = '{"host":"localhost","port":5432}';

447

console.log(nconf.parseValues(jsonStr));

448

// Result: { host: 'localhost', port: 5432 }

449

450

const arrayStr = '["auth","logging","metrics"]';

451

console.log(nconf.parseValues(arrayStr));

452

// Result: ['auth', 'logging', 'metrics']

453

454

// Custom parsing utility

455

function parseEnvironmentValues(env) {

456

const parsed = {};

457

Object.keys(env).forEach(key => {

458

parsed[key] = nconf.parseValues(env[key]);

459

});

460

return parsed;

461

}

462

463

// Usage with environment variables

464

const processEnv = parseEnvironmentValues(process.env);

465

console.log(processEnv.NODE_ENV); // string

466

console.log(processEnv.PORT); // number (if PORT=3000)

467

console.log(processEnv.DEBUG); // boolean (if DEBUG=true)

468

```

469

470

## Transform Utilities

471

472

Helper for transforming key-value pairs during store loading.

473

474

```javascript { .api }

475

/**

476

* Transform object using transformation function

477

* @param {Object} map - Object with key-value pairs

478

* @param {function} fn - Transformation function

479

* @returns {Object} Transformed object

480

*/

481

nconf.transform(map, fn);

482

```

483

484

**Usage Examples:**

485

486

```javascript

487

// Transform environment variables

488

const env = {

489

'MYAPP_DATABASE_HOST': 'localhost',

490

'MYAPP_DATABASE_PORT': '5432',

491

'OTHER_VAR': 'ignored'

492

};

493

494

const transformed = nconf.transform(env, function(obj) {

495

// Only process MYAPP_ prefixed variables

496

if (!obj.key.startsWith('MYAPP_')) {

497

return null; // Skip this key-value pair

498

}

499

500

return {

501

key: obj.key.replace('MYAPP_', '').toLowerCase().replace(/_/g, ':'),

502

value: nconf.parseValues(obj.value)

503

};

504

});

505

506

// Result: { 'database:host': 'localhost', 'database:port': 5432 }

507

508

// Transform configuration keys

509

const config = {

510

'server-host': 'localhost',

511

'server-port': '8080',

512

'database-url': 'postgres://...'

513

};

514

515

const normalized = nconf.transform(config, function(obj) {

516

return {

517

key: obj.key.replace(/-/g, ':'), // Convert kebab-case to colon notation

518

value: obj.value

519

};

520

});

521

522

// Result: { 'server:host': 'localhost', 'server:port': '8080', 'database:url': '...' }

523

```

524

525

### Key Construction

526

527

Utility functions for constructing configuration keys with custom separators.

528

529

```javascript { .api }

530

/**

531

* Join arguments with custom separator

532

* @param {string} separator - Separator to use between arguments

533

* @param {...string} args - Arguments to join

534

* @returns {string} Joined string with custom separator

535

*/

536

nconf.keyed(separator, ...args);

537

```

538

539

**Usage Examples:**

540

541

```javascript

542

// Custom separator key construction

543

const key1 = nconf.keyed('__', 'database', 'connection', 'host');

544

// Result: 'database__connection__host'

545

546

const key2 = nconf.keyed('.', 'app', 'server', 'port');

547

// Result: 'app.server.port'

548

549

const key3 = nconf.keyed('/', 'config', 'environment', 'production');

550

// Result: 'config/environment/production'

551

552

// Dynamic key construction

553

function buildKey(separator, ...parts) {

554

return nconf.keyed(separator, ...parts.filter(Boolean));

555

}

556

557

const dbKey = buildKey(':', 'database', process.env.NODE_ENV, 'host');

558

// Result: 'database:production:host' (if NODE_ENV=production)

559

560

// Build environment variable names

561

const envVar = nconf.keyed('_', 'MYAPP', 'DATABASE', 'HOST').toUpperCase();

562

// Result: 'MYAPP_DATABASE_HOST'

563

```