Generic configuration validation tool that helps with warnings, errors and deprecation messages as well as showing users examples of correct configuration.
npx @tessl/cli install tessl/npm-jest-validate@30.1.00
# jest-validate
1
2
jest-validate is a generic configuration validation tool that helps with warnings, errors and deprecation messages as well as showing users examples of correct configuration. Originally developed for Jest, it provides a comprehensive validation framework for JavaScript/Node.js applications with extensive customization options.
3
4
## Package Information
5
6
- **Package Name**: jest-validate
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install jest-validate`
10
11
## Core Imports
12
13
```typescript
14
import { validate, validateCLIOptions, multipleValidOptions, ValidationError, format, formatPrettyObject, createDidYouMeanMessage, logValidationWarning } from "jest-validate";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { validate, validateCLIOptions, multipleValidOptions, ValidationError, format, formatPrettyObject, createDidYouMeanMessage, logValidationWarning } = require("jest-validate");
21
```
22
23
## Basic Usage
24
25
```typescript
26
import { validate, multipleValidOptions } from "jest-validate";
27
28
// Define example configuration (required)
29
const exampleConfig = {
30
transform: {},
31
testMatch: ["**/__tests__/**/*.(js|ts)"],
32
verbose: false,
33
timeout: 5000,
34
retries: multipleValidOptions(1, false) // allows number or boolean
35
};
36
37
// Validate user configuration
38
const result = validate(userConfig, { exampleConfig });
39
40
if (result.isValid) {
41
console.log("Configuration is valid!");
42
if (result.hasDeprecationWarnings) {
43
console.log("Note: Some deprecated options were found");
44
}
45
}
46
```
47
48
## Architecture
49
50
jest-validate is built around several key components:
51
52
- **Core Validation**: `validate()` function that compares configurations against example schemas
53
- **CLI Validation**: `validateCLIOptions()` for command-line argument validation with deprecation support
54
- **Type Checking**: Automatic type validation based on example configurations using JavaScript's native type system
55
- **Multiple Type Support**: `multipleValidOptions()` utility for options that accept different types
56
- **Error System**: Custom `ValidationError` class with formatted, colorized output
57
- **Deprecation Management**: Built-in handling for deprecated options with customizable warning messages
58
- **Extensible Handlers**: Pluggable error, warning, and unknown option handlers
59
60
## Capabilities
61
62
### Configuration Validation
63
64
Core validation functionality that compares user configurations against example schemas with comprehensive error reporting and type checking.
65
66
```typescript { .api }
67
/**
68
* Validates a configuration object against an example configuration schema
69
* @param config - The configuration object to validate
70
* @param options - Validation options including required exampleConfig
71
* @returns Validation result with deprecation warnings flag and validity status
72
*/
73
function validate(
74
config: Record<string, unknown>,
75
options: ValidationOptions
76
): { hasDeprecationWarnings: boolean; isValid: boolean };
77
78
interface ValidationOptions {
79
/** Additional comment text to display with error/warning messages */
80
comment?: string;
81
/** Custom validation condition function for comparing option values */
82
condition?: (option: unknown, validOption: unknown) => boolean;
83
/** Custom deprecation handler function */
84
deprecate?: (
85
config: Record<string, unknown>,
86
option: string,
87
deprecatedOptions: DeprecatedOptions,
88
options: ValidationOptions
89
) => boolean;
90
/** Object mapping deprecated option names to deprecation message functions */
91
deprecatedConfig?: DeprecatedOptions;
92
/** Custom error handler function */
93
error?: (
94
option: string,
95
received: unknown,
96
defaultValue: unknown,
97
options: ValidationOptions,
98
path?: Array<string>
99
) => void;
100
/** Required example configuration object that defines valid structure and types */
101
exampleConfig: Record<string, unknown>;
102
/** Whether to recursively validate nested objects (default: true) */
103
recursive?: boolean;
104
/** Array of key paths to exclude from recursive validation */
105
recursiveDenylist?: Array<string>;
106
/** Custom titles for error/warning messages */
107
title?: Title;
108
/** Custom handler for unknown/unrecognized options */
109
unknown?: (
110
config: Record<string, unknown>,
111
exampleConfig: Record<string, unknown>,
112
option: string,
113
options: ValidationOptions,
114
path?: Array<string>
115
) => void;
116
}
117
118
interface Title {
119
deprecation?: string;
120
error?: string;
121
warning?: string;
122
}
123
124
type DeprecatedOptions = Record<string, DeprecatedOptionFunc>;
125
type DeprecatedOptionFunc = (arg: Record<string, unknown>) => string;
126
```
127
128
**Usage Examples:**
129
130
```typescript
131
import { validate } from "jest-validate";
132
133
// Basic validation
134
const result = validate(userConfig, {
135
exampleConfig: {
136
verbose: true,
137
testTimeout: 5000,
138
setupFiles: []
139
}
140
});
141
142
// Custom validation with deprecation handling
143
const result = validate(userConfig, {
144
exampleConfig: { verbose: true },
145
deprecatedConfig: {
146
silent: () => 'Option "silent" has been replaced by "verbose"'
147
},
148
comment: 'See documentation at https://example.com/config'
149
});
150
151
// Recursive validation with denylist
152
const result = validate(userConfig, {
153
exampleConfig: { nested: { allowed: true, ignored: {} } },
154
recursive: true,
155
recursiveDenylist: ['nested.ignored'] // Skip validating nested.ignored
156
});
157
```
158
159
### CLI Options Validation
160
161
Validates command-line options against allowed option schemas with support for deprecated options, aliases, and automatic suggestion generation.
162
163
```typescript { .api }
164
/**
165
* Validates CLI options and arguments with deprecation support
166
* @param argv - Parsed command-line arguments object (typically from yargs)
167
* @param options - Object defining allowed options and their configuration
168
* @param rawArgv - Optional raw argument array for filtering
169
* @returns true if validation passes, throws ValidationError if not
170
*/
171
function validateCLIOptions(
172
argv: Config.Argv,
173
options: Record<string, Options> & { deprecationEntries?: DeprecatedOptions },
174
rawArgv?: Array<string>
175
): boolean;
176
177
interface Options {
178
/** Alias for the option (single string or array of strings) */
179
alias?: string | string[];
180
/** Additional option properties from yargs */
181
[key: string]: any;
182
}
183
184
type Config.Argv = Record<string, unknown>;
185
```
186
187
**Usage Examples:**
188
189
```typescript
190
import { validateCLIOptions } from "jest-validate";
191
192
// Define allowed CLI options
193
const allowedOptions = {
194
verbose: { alias: 'v' },
195
config: { alias: 'c' },
196
watch: { alias: 'w' },
197
help: { alias: 'h' }
198
};
199
200
// Validate CLI arguments
201
try {
202
validateCLIOptions(parsedArgs, allowedOptions);
203
console.log("CLI options are valid");
204
} catch (error) {
205
console.error(error.message);
206
}
207
208
// With deprecation entries
209
const optionsWithDeprecation = {
210
...allowedOptions,
211
deprecationEntries: {
212
runInBand: () => 'Option "runInBand" has been replaced by "maxWorkers=1"'
213
}
214
};
215
216
validateCLIOptions(parsedArgs, optionsWithDeprecation);
217
```
218
219
### Multiple Valid Options
220
221
Utility for creating configuration options that accept multiple types, enabling flexible API design while maintaining type safety.
222
223
```typescript { .api }
224
/**
225
* Creates a configuration that accepts multiple valid types for a single option
226
* Uses internal symbol marking to allow validation against multiple type examples
227
* @param args - Variable number of example values of different types
228
* @returns Array containing the examples, marked internally for multi-type validation
229
*/
230
function multipleValidOptions<T extends Array<unknown>>(...args: T): T[number];
231
```
232
233
**Usage Examples:**
234
235
```typescript
236
import { validate, multipleValidOptions } from "jest-validate";
237
238
// Allow string or number for maxWorkers
239
const exampleConfig = {
240
maxWorkers: multipleValidOptions("50%", 4),
241
verbose: multipleValidOptions(true, "full"), // boolean or specific string
242
timeout: multipleValidOptions(5000, "30s") // number or string
243
};
244
245
const result = validate({
246
maxWorkers: "75%", // Valid - matches string type
247
verbose: true, // Valid - matches boolean type
248
timeout: "45s" // Valid - matches string type
249
}, { exampleConfig });
250
```
251
252
### Error Handling
253
254
Custom error class for validation failures with formatted, colorized output designed for developer-friendly error messages.
255
256
```typescript { .api }
257
/**
258
* Custom error class for validation failures with formatted output
259
*/
260
class ValidationError extends Error {
261
override name: string;
262
override message: string;
263
264
/**
265
* Creates a new validation error with formatted message
266
* @param name - Error name/title to display
267
* @param message - Main error message content
268
* @param comment - Optional additional comment or documentation reference
269
*/
270
constructor(name: string, message: string, comment?: string | null);
271
}
272
```
273
274
### Utility Functions
275
276
Helper functions for formatting values and creating user-friendly error messages.
277
278
```typescript { .api }
279
/**
280
* Formats values for display in error messages
281
* @param value - Value to format (any type)
282
* @returns Formatted string representation
283
*/
284
function format(value: unknown): string;
285
286
/**
287
* Formats values as pretty-printed objects for display
288
* @param value - Value to format (any type)
289
* @returns Pretty-formatted string representation with indentation
290
*/
291
function formatPrettyObject(value: unknown): string;
292
293
/**
294
* Creates suggestion messages for similar option names using edit distance
295
* @param unrecognized - The unrecognized option name
296
* @param allowedOptions - Array of valid option names
297
* @returns Suggestion message or empty string if no close matches
298
*/
299
function createDidYouMeanMessage(
300
unrecognized: string,
301
allowedOptions: Array<string>
302
): string;
303
304
/**
305
* Logs validation warnings to console with formatted output
306
* @param name - Warning name/title
307
* @param message - Warning message content
308
* @param comment - Optional additional comment
309
*/
310
function logValidationWarning(
311
name: string,
312
message: string,
313
comment?: string | null
314
): void;
315
```
316
317
**Usage Examples:**
318
319
```typescript
320
import { ValidationError, format, createDidYouMeanMessage } from "jest-validate";
321
322
// Custom error handling
323
try {
324
// Some validation logic
325
throw new ValidationError(
326
"Custom Validation Error",
327
`Invalid value: ${format(userValue)}`,
328
"Check the documentation for valid options"
329
);
330
} catch (error) {
331
console.error(error.message); // Formatted, colorized output
332
}
333
334
// Generate suggestions
335
const suggestion = createDidYouMeanMessage("verbos", ["verbose", "version"]);
336
console.log(suggestion); // "Did you mean verbose?"
337
338
// Format various value types
339
console.log(format("hello")); // "hello"
340
console.log(format(42)); // 42
341
console.log(format([1, 2, 3])); // [1, 2, 3]
342
console.log(format(undefined)); // undefined
343
344
// Format with pretty printing for objects
345
console.log(formatPrettyObject({ name: "test", value: 42 }));
346
// Output:
347
// {
348
// "name": "test",
349
// "value": 42
350
// }
351
```
352
353
## Advanced Configuration
354
355
### Custom Validation Conditions
356
357
```typescript
358
import { validate } from "jest-validate";
359
360
const result = validate(userConfig, {
361
exampleConfig: { port: 3000 },
362
condition: (option, validOption) => {
363
// Custom logic for port validation
364
if (typeof option === 'number' && typeof validOption === 'number') {
365
return option > 0 && option < 65536;
366
}
367
return option === validOption;
368
}
369
});
370
```
371
372
### Custom Error Handlers
373
374
```typescript
375
import { validate, ValidationError } from "jest-validate";
376
377
const result = validate(userConfig, {
378
exampleConfig: { timeout: 5000 },
379
error: (option, received, defaultValue, options, path) => {
380
const fullPath = path ? `${path.join('.')}.${option}` : option;
381
throw new ValidationError(
382
"Configuration Error",
383
`Option "${fullPath}" expected ${typeof defaultValue} but got ${typeof received}`,
384
"Please check your configuration file"
385
);
386
}
387
});
388
```
389
390
### Handling Unknown Options
391
392
```typescript
393
import { validate } from "jest-validate";
394
395
const result = validate(userConfig, {
396
exampleConfig: { knownOption: true },
397
unknown: (config, exampleConfig, option, options, path) => {
398
const fullPath = path ? `${path.join('.')}.${option}` : option;
399
console.warn(`Unknown option "${fullPath}" will be ignored`);
400
// Could also delete the unknown option: delete config[option];
401
}
402
});
403
```