0
# Spec Resolution and Processing
1
2
Resolve OpenAPI specifications with reference handling, validation, and normalization across different spec versions.
3
4
## Capabilities
5
6
### Resolve Function
7
8
Resolve OpenAPI specifications with automatic reference resolution and validation.
9
10
```javascript { .api }
11
/**
12
* Resolve an OpenAPI specification
13
* @param options - Resolution configuration options
14
* @returns Promise resolving to resolution result
15
*/
16
function resolve(options: ResolveOptions): Promise<ResolutionResult>;
17
18
interface ResolveOptions {
19
/** OpenAPI specification object to resolve */
20
spec?: object;
21
/** URL to fetch specification from */
22
url?: string;
23
/** Custom HTTP client for fetching external references */
24
http?: HttpClient;
25
/** Legacy fetch function (use userFetch instead) */
26
fetch?: FetchFunction;
27
/** Custom fetch implementation */
28
userFetch?: FetchFunction;
29
/** Allow patching of meta patches during resolution */
30
allowMetaPatches?: boolean;
31
/** Use circular structures in resolved spec */
32
useCircularStructures?: boolean;
33
/** Function to intercept and modify requests */
34
requestInterceptor?: RequestInterceptor;
35
/** Function to intercept and modify responses */
36
responseInterceptor?: ResponseInterceptor;
37
/** Skip normalization of the resolved specification */
38
skipNormalization?: boolean;
39
/** Array of path segments to discriminate during resolution */
40
pathDiscriminator?: string[];
41
/** Resolution strategies to use */
42
strategies?: ResolveStrategy[];
43
}
44
45
interface ResolutionResult {
46
/** Resolved OpenAPI specification */
47
spec: object;
48
/** Errors encountered during resolution */
49
errors: ResolutionError[];
50
}
51
52
interface ResolutionError {
53
/** Error message */
54
message: string;
55
/** Full path where error occurred */
56
fullPath: string[];
57
}
58
```
59
60
**Usage Examples:**
61
62
```javascript
63
import { resolve } from "swagger-client";
64
65
// Resolve from URL
66
const result = await resolve({
67
url: "https://petstore.swagger.io/v2/swagger.json"
68
});
69
70
console.log("Resolved spec:", result.spec);
71
console.log("Resolution errors:", result.errors);
72
73
// Resolve spec object with external references
74
const result = await resolve({
75
spec: {
76
openapi: "3.0.0",
77
info: { title: "API", version: "1.0.0" },
78
paths: {
79
"/users": {
80
"$ref": "https://api.example.com/paths/users.json"
81
}
82
}
83
}
84
});
85
86
// Resolve with custom HTTP client
87
const result = await resolve({
88
url: "https://api.example.com/openapi.json",
89
http: customHttpClient
90
});
91
92
// Resolve with request interceptor for authentication
93
const result = await resolve({
94
url: "https://api.example.com/openapi.json",
95
requestInterceptor: (req) => {
96
req.headers.Authorization = "Bearer token";
97
return req;
98
}
99
});
100
101
// Resolve with circular structure support
102
const result = await resolve({
103
spec: specWithCircularRefs,
104
useCircularStructures: true
105
});
106
```
107
108
### Custom Resolver Creation
109
110
Create custom resolvers with specific strategies and default options.
111
112
```javascript { .api }
113
/**
114
* Create a custom resolver function with default options
115
* @param defaultOptions - Default options for resolution
116
* @returns Custom resolver function
117
*/
118
function makeResolve(defaultOptions: ResolveOptions): (options: ResolveOptions) => Promise<ResolutionResult>;
119
```
120
121
**makeResolve Examples:**
122
123
```javascript
124
import { makeResolve } from "swagger-client";
125
126
// Create resolver with authentication defaults
127
const authenticatedResolve = makeResolve({
128
requestInterceptor: (req) => {
129
req.headers.Authorization = "Bearer " + getToken();
130
return req;
131
}
132
});
133
134
// Use the custom resolver
135
const result = await authenticatedResolve({
136
url: "https://api.example.com/openapi.json"
137
});
138
139
// Create resolver with custom strategies
140
const customResolve = makeResolve({
141
strategies: [
142
strategies["openapi-3-1-apidom"],
143
strategies["openapi-3-0"]
144
],
145
allowMetaPatches: true
146
});
147
```
148
149
### Resolution Strategies
150
151
Different strategies for resolving different OpenAPI specification versions.
152
153
```javascript { .api }
154
interface ResolveStrategy {
155
/** Check if this strategy can handle the given spec */
156
match(spec: object): boolean;
157
/** Normalize the specification */
158
normalize(spec: object): object;
159
/** Resolve the specification */
160
resolve(options: ResolveOptions): Promise<ResolutionResult>;
161
}
162
163
// Available strategies
164
const strategies = {
165
"openapi-3-1-apidom": OpenApi31ApiDOMStrategy,
166
"openapi-3-0": OpenApi30Strategy,
167
"openapi-2-0": OpenApi2Strategy,
168
"generic": GenericStrategy
169
};
170
```
171
172
**Strategy Examples:**
173
174
```javascript
175
import { makeResolve } from "swagger-client";
176
177
// Create resolver with custom strategies
178
const customResolve = makeResolve({
179
strategies: [
180
strategies["openapi-3-1-apidom"],
181
strategies["openapi-3-0"],
182
strategies["generic"]
183
]
184
});
185
186
const result = await customResolve({
187
url: "https://api.example.com/openapi.json"
188
});
189
```
190
191
### Subtree Resolution
192
193
Resolve specific parts of a specification for performance optimization.
194
195
```javascript { .api }
196
/**
197
* Resolve a subtree of an OpenAPI specification
198
* @param obj - OpenAPI specification object
199
* @param path - Array path to the subtree to resolve
200
* @param options - Resolution options
201
* @returns Promise resolving to resolution result
202
*/
203
function resolveSubtree(obj: object, path: string[], options?: SubtreeOptions): Promise<ResolutionResult>;
204
205
/**
206
* Create a custom subtree resolver with default options
207
* @param defaultOptions - Default options for subtree resolution
208
* @returns Custom subtree resolver function
209
*/
210
function makeResolveSubtree(defaultOptions: SubtreeOptions): (obj: object, path: string[], options?: SubtreeOptions) => Promise<ResolutionResult>;
211
212
interface SubtreeOptions {
213
/** Return entire tree instead of just the subtree */
214
returnEntireTree?: boolean;
215
/** Base document for resolution context */
216
baseDoc?: object;
217
/** Function to intercept requests */
218
requestInterceptor?: RequestInterceptor;
219
/** Function to intercept responses */
220
responseInterceptor?: ResponseInterceptor;
221
/** Parameter macro function */
222
parameterMacro?: Function;
223
/** Model property macro function */
224
modelPropertyMacro?: Function;
225
/** Use circular structures in resolution */
226
useCircularStructures?: boolean;
227
/** Resolution strategies to use */
228
strategies?: ResolveStrategy[];
229
}
230
```
231
232
**Subtree Examples:**
233
234
```javascript
235
import { resolveSubtree, makeResolveSubtree } from "swagger-client";
236
237
// Resolve only specific paths
238
const result = await resolveSubtree(
239
openApiSpec,
240
["paths", "/users", "get"]
241
);
242
243
// Resolve only components section
244
const result = await resolveSubtree(
245
openApiSpec,
246
["components", "schemas"]
247
);
248
249
// Return entire tree with specific subtree resolved
250
const result = await resolveSubtree(
251
openApiSpec,
252
["paths", "/users"],
253
{ returnEntireTree: true }
254
);
255
256
// Create custom subtree resolver
257
const customSubtreeResolve = makeResolveSubtree({
258
useCircularStructures: true,
259
requestInterceptor: (req) => {
260
req.headers.Authorization = "Bearer " + getToken();
261
return req;
262
}
263
});
264
265
const result = await customSubtreeResolve(
266
openApiSpec,
267
["components", "schemas", "User"]
268
);
269
```
270
271
### Reference Resolution
272
273
Handle JSON Schema references ($ref) in OpenAPI specifications.
274
275
```javascript { .api }
276
// External reference resolution
277
const spec = {
278
openapi: "3.0.0",
279
info: { title: "API", version: "1.0.0" },
280
components: {
281
schemas: {
282
User: {
283
"$ref": "https://api.example.com/schemas/user.json"
284
}
285
}
286
}
287
};
288
289
const result = await resolve({ spec });
290
291
// Internal reference resolution
292
const spec = {
293
openapi: "3.0.0",
294
info: { title: "API", version: "1.0.0" },
295
paths: {
296
"/users": {
297
get: {
298
responses: {
299
"200": {
300
content: {
301
"application/json": {
302
schema: { "$ref": "#/components/schemas/User" }
303
}
304
}
305
}
306
}
307
}
308
}
309
},
310
components: {
311
schemas: {
312
User: {
313
type: "object",
314
properties: {
315
id: { type: "integer" },
316
name: { type: "string" }
317
}
318
}
319
}
320
}
321
};
322
323
const result = await resolve({ spec });
324
```
325
326
### Path Discrimination
327
328
Filter resolution to specific paths for performance and security.
329
330
```javascript { .api }
331
// Resolve only specific operation paths
332
const result = await resolve({
333
spec: openApiSpec,
334
pathDiscriminator: ["paths", "/users", "get"]
335
});
336
337
// Multiple path discrimination
338
const result = await resolve({
339
spec: openApiSpec,
340
pathDiscriminator: [
341
"paths./users.get",
342
"paths./users.post",
343
"components.schemas.User"
344
]
345
});
346
```
347
348
### Normalization Control
349
350
Control specification normalization during resolution.
351
352
```javascript { .api }
353
// Skip normalization for raw spec access
354
const result = await resolve({
355
spec: openApiSpec,
356
skipNormalization: true
357
});
358
359
// Allow meta patches for spec correction
360
const result = await resolve({
361
spec: openApiSpec,
362
allowMetaPatches: true
363
});
364
```
365
366
### Resolution Errors
367
368
Handle and process resolution errors.
369
370
```javascript { .api }
371
interface ResolutionError {
372
/** Human-readable error message */
373
message: string;
374
/** Array representing the JSON path where error occurred */
375
fullPath: string[];
376
}
377
378
// Example error handling
379
const result = await resolve({
380
url: "https://api.example.com/broken-spec.json"
381
});
382
383
if (result.errors.length > 0) {
384
result.errors.forEach(error => {
385
console.error(`Error at ${error.fullPath.join('.')}: ${error.message}`);
386
});
387
}
388
389
// Common error types:
390
// - Reference resolution failures
391
// - Invalid JSON/YAML syntax
392
// - Network errors when fetching external refs
393
// - Circular reference detection
394
// - Schema validation errors
395
```
396
397
### Cache Management
398
399
Manage resolution caches for performance optimization.
400
401
```javascript { .api }
402
/**
403
* Clear all resolution caches
404
*/
405
function clearCache(): void;
406
407
// Usage
408
import { clearCache } from "swagger-client";
409
410
// Clear caches to free memory or force re-resolution
411
clearCache();
412
```
413
414
### Advanced Resolution Options
415
416
Advanced configuration for complex resolution scenarios.
417
418
```javascript { .api }
419
// Custom HTTP configuration
420
const result = await resolve({
421
url: "https://api.example.com/openapi.json",
422
http: {
423
withCredentials: true,
424
timeout: 30000
425
}
426
});
427
428
// Response interceptor for custom processing
429
const result = await resolve({
430
url: "https://api.example.com/openapi.json",
431
responseInterceptor: (response) => {
432
if (response.headers["content-type"].includes("text/plain")) {
433
// Convert plain text to JSON
434
response.body = JSON.parse(response.text);
435
}
436
return response;
437
}
438
});
439
440
// Circular structure handling
441
const result = await resolve({
442
spec: {
443
openapi: "3.0.0",
444
info: { title: "API", version: "1.0.0" },
445
components: {
446
schemas: {
447
Node: {
448
type: "object",
449
properties: {
450
value: { type: "string" },
451
children: {
452
type: "array",
453
items: { "$ref": "#/components/schemas/Node" }
454
}
455
}
456
}
457
}
458
}
459
},
460
useCircularStructures: true
461
});
462
```
463
464
## Common Types
465
466
```javascript { .api }
467
interface HttpClient {
468
(url: string, options?: HttpOptions): Promise<ResponseObject>;
469
withCredentials?: boolean;
470
timeout?: number;
471
}
472
473
interface FetchFunction {
474
(url: string, options?: RequestInit): Promise<Response>;
475
}
476
477
interface RequestInterceptor {
478
(request: RequestObject): RequestObject | Promise<RequestObject>;
479
}
480
481
interface ResponseInterceptor {
482
(response: ResponseObject): ResponseObject | Promise<ResponseObject>;
483
}
484
485
interface ResponseObject {
486
url: string;
487
status: number;
488
statusText: string;
489
headers: Record<string, string>;
490
text: string;
491
body: any;
492
ok: boolean;
493
}
494
495
interface RequestObject {
496
url: string;
497
method: string;
498
headers: Record<string, string>;
499
body?: any;
500
}
501
```