0
# Validation
1
2
Comprehensive validation system with detailed error reporting, contextual messages, and customizable validation rules for OpenAPI, Swagger, and Postman API definitions.
3
4
## Capabilities
5
6
### Validate Method
7
8
Validate API definitions with comprehensive error reporting and contextual information pointing to specific line numbers and issues.
9
10
```typescript { .api }
11
/**
12
* Validate a given API definition with detailed error reporting
13
* Supports OpenAPI 3.x, Swagger 2.0, and Postman collections
14
* @param opts - Optional validation configuration
15
* @returns Promise resolving to validation result if valid, throws ValidationError if invalid
16
*/
17
async validate(opts?: {
18
parser?: ParserOptions;
19
}): Promise<ValidationResult>;
20
21
interface ValidationResult {
22
valid: boolean;
23
warnings: WarningDetails[];
24
errors: ErrorDetails[];
25
}
26
27
interface ErrorDetails {
28
message: string;
29
path: string;
30
location?: {
31
line: number;
32
column: number;
33
};
34
}
35
36
interface WarningDetails {
37
message: string;
38
path: string;
39
rule: string;
40
}
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import OASNormalize from "oas-normalize";
47
48
// Basic validation
49
const oas = new OASNormalize(apiSpec);
50
51
try {
52
const result = await oas.validate();
53
console.log('✅ API definition is valid!');
54
if (result.warnings.length > 0) {
55
console.warn('⚠️ Warnings found:', result.warnings);
56
}
57
} catch (error) {
58
console.error('❌ Validation failed:');
59
console.error(error.message);
60
}
61
```
62
63
```typescript
64
// Validation with custom rules
65
const oas = new OASNormalize(apiSpec);
66
67
try {
68
const result = await oas.validate({
69
parser: {
70
validate: {
71
rules: {
72
openapi: {
73
'path-parameters-not-in-path': 'warning', // Treat as warning instead of error
74
'unused-components': 'off', // Disable this rule
75
'missing-example': 'error' // Enforce examples
76
}
77
}
78
}
79
}
80
});
81
82
if (result.warnings.length) {
83
console.warn('🚸 The API is valid but has some warnings:');
84
result.warnings.forEach(warning => {
85
console.warn(` - ${warning.message} (${warning.rule})`);
86
});
87
} else {
88
console.log('🍭 The API is valid with no warnings!');
89
}
90
} catch (error) {
91
console.error('❌ Validation failed:', error.message);
92
}
93
```
94
95
## Validation Features
96
97
### Multi-Format Support
98
99
Validates different API definition formats with automatic conversion as needed:
100
101
```typescript
102
// OpenAPI 3.x validation
103
const openapi = {
104
openapi: "3.0.0",
105
info: { title: "Pet Store", version: "1.0.0" },
106
paths: {}
107
};
108
await new OASNormalize(openapi).validate();
109
110
// Swagger 2.0 validation
111
const swagger = {
112
swagger: "2.0",
113
info: { title: "Pet Store", version: "1.0.0" },
114
paths: {}
115
};
116
await new OASNormalize(swagger).validate();
117
118
// Postman collection validation (converts to OpenAPI first)
119
const postman = {
120
info: { name: "Collection" },
121
item: []
122
};
123
await new OASNormalize(postman).validate();
124
```
125
126
### Detailed Error Messages
127
128
Validation errors include contextual information with line numbers and specific issue locations:
129
130
```typescript
131
const invalidSpec = {
132
openapi: "3.0.0",
133
info: { title: "API" }, // Missing required version field
134
servers: [
135
{ urll: "http://petstore.swagger.io/v2" } // Typo: should be "url"
136
],
137
paths: {}
138
};
139
140
try {
141
await new OASNormalize(invalidSpec).validate();
142
} catch (error) {
143
console.error(error.message);
144
// Output includes:
145
// OpenAPI schema validation failed.
146
//
147
// REQUIRED must have required property 'version'
148
//
149
// 2 | "info": {
150
// > 3 | "title": "API"
151
// | ^ ☹️ version is missing here!
152
// 4 | },
153
//
154
// REQUIRED must have required property 'url'
155
//
156
// 6 | "servers": [
157
// > 7 | {
158
// | ^ ☹️ url is missing here!
159
// 8 | "urll": "http://petstore.swagger.io/v2"
160
// 9 | }
161
}
162
```
163
164
### Colorized Error Output
165
166
Enable colorized error messages for better readability in terminal environments:
167
168
```typescript
169
const oas = new OASNormalize(invalidSpec, {
170
colorizeErrors: true
171
});
172
173
try {
174
await oas.validate();
175
} catch (error) {
176
// Error message will include ANSI color codes for:
177
// - Red highlighting for error locations
178
// - Yellow for warning text
179
// - Green for line numbers
180
// - Bold formatting for key information
181
console.error(error.message);
182
}
183
```
184
185
## Custom Validation Rules
186
187
### Rule Configuration
188
189
Configure validation behavior with custom rulesets:
190
191
```typescript
192
const validationOptions = {
193
parser: {
194
validate: {
195
rules: {
196
openapi: {
197
// Path parameter rules
198
'path-parameters-not-in-path': 'warning',
199
'path-parameters-defined-but-not-used': 'error',
200
201
// Schema rules
202
'unused-components': 'warning',
203
'missing-example': 'off',
204
'schema-names-camel-case': 'error',
205
206
// Security rules
207
'security-schemes-defined': 'error',
208
'security-requirements-defined': 'warning',
209
210
// Documentation rules
211
'operation-description': 'warning',
212
'parameter-description': 'off'
213
}
214
}
215
}
216
}
217
};
218
219
const result = await oas.validate(validationOptions);
220
```
221
222
### Rule Severity Levels
223
224
- **`error`**: Validation fails, throws ValidationError
225
- **`warning`**: Validation succeeds but includes warnings in result
226
- **`off`**: Rule is disabled completely
227
228
### Available Rules (Examples)
229
230
Common OpenAPI validation rules that can be configured:
231
232
```typescript
233
const commonRules = {
234
// Path and parameter validation
235
'path-parameters-not-in-path': 'error',
236
'path-parameters-defined-but-not-used': 'warning',
237
'duplicate-path-parameters': 'error',
238
239
// Schema validation
240
'unused-components': 'warning',
241
'missing-example': 'warning',
242
'schema-names-camel-case': 'off',
243
'required-properties-schema': 'error',
244
245
// Operation validation
246
'operation-id-unique': 'error',
247
'operation-id-case-convention': 'warning',
248
'operation-description': 'warning',
249
'operation-summary': 'off',
250
251
// Response validation
252
'response-schema-defined': 'error',
253
'success-response-defined': 'error',
254
255
// Security validation
256
'security-schemes-defined': 'error',
257
'security-requirements-defined': 'warning'
258
};
259
```
260
261
## Error Handling
262
263
### ValidationError Class
264
265
All validation failures throw `ValidationError` instances:
266
267
```typescript
268
import { ValidationError } from "oas-normalize/lib/errors";
269
270
try {
271
await oas.validate();
272
} catch (error) {
273
if (error instanceof ValidationError) {
274
console.error('Validation Error:', error.message);
275
console.error('Error Name:', error.name); // "ValidationError"
276
} else {
277
console.error('Unexpected Error:', error);
278
}
279
}
280
```
281
282
### Unsupported Format Handling
283
284
```typescript
285
const unsupportedSpec = {
286
// Missing format indicators
287
info: { title: "Unknown" }
288
};
289
290
try {
291
await new OASNormalize(unsupportedSpec).validate();
292
} catch (error) {
293
console.error(error.message); // "The supplied API definition is unsupported."
294
console.log(error instanceof ValidationError); // true
295
}
296
```
297
298
### Legacy Format Rejection
299
300
```typescript
301
const swagger12 = {
302
swagger: "1.2", // Unsupported version
303
info: { title: "Old API" }
304
};
305
306
try {
307
await new OASNormalize(swagger12).validate();
308
} catch (error) {
309
console.error(error.message); // "Swagger v1.2 is unsupported."
310
}
311
```
312
313
## Integration with Other Methods
314
315
Validation works seamlessly with other OAS Normalize operations:
316
317
```typescript
318
const oas = new OASNormalize(apiSpec);
319
320
// Validate after conversion
321
const converted = await oas.convert();
322
await new OASNormalize(converted).validate();
323
324
// Validate after bundling
325
const bundled = await oas.bundle();
326
await new OASNormalize(bundled).validate();
327
328
// Validate after dereferencing
329
const dereferenced = await oas.dereference();
330
await new OASNormalize(dereferenced).validate();
331
332
// Direct validation (handles conversion internally)
333
await oas.validate();
334
```
335
336
## Advanced Validation Scenarios
337
338
### Circular Reference Handling
339
340
```typescript
341
const specWithCircularRef = {
342
openapi: "3.0.0",
343
info: { title: "API", version: "1.0.0" },
344
components: {
345
schemas: {
346
Node: {
347
type: "object",
348
properties: {
349
value: { type: "string" },
350
child: { $ref: "#/components/schemas/Node" } // Circular reference
351
}
352
}
353
}
354
},
355
paths: {}
356
};
357
358
// Circular references are handled gracefully
359
const result = await new OASNormalize(specWithCircularRef).validate();
360
console.log('✅ Circular references validated successfully');
361
```
362
363
### External Reference Validation
364
365
```typescript
366
const specWithExternalRefs = {
367
openapi: "3.0.0",
368
info: { title: "API", version: "1.0.0" },
369
paths: {
370
"/pets": {
371
get: {
372
responses: {
373
"200": {
374
content: {
375
"application/json": {
376
schema: { $ref: "./pet-schema.json" }
377
}
378
}
379
}
380
}
381
}
382
}
383
}
384
};
385
386
// Validate with external reference resolution
387
const oas = new OASNormalize(specWithExternalRefs, { enablePaths: true });
388
await oas.validate(); // Resolves and validates external references
389
```
390
391
### Batch Validation
392
393
```typescript
394
const specs = [spec1, spec2, spec3];
395
396
const validationResults = await Promise.allSettled(
397
specs.map(spec => new OASNormalize(spec).validate())
398
);
399
400
validationResults.forEach((result, index) => {
401
if (result.status === 'fulfilled') {
402
console.log(`✅ Spec ${index + 1} is valid`);
403
} else {
404
console.error(`❌ Spec ${index + 1} failed:`, result.reason.message);
405
}
406
});
407
```