0
# Reference Resolution
1
2
Advanced reference resolution capabilities for bundling external $ref pointers and dereferencing all references inline, providing complete control over how API definitions handle references.
3
4
## Capabilities
5
6
### Bundle Method
7
8
Bundle external $ref pointers into the main document, resolving references to external files while preserving internal references.
9
10
```typescript { .api }
11
/**
12
* Bundle up the given API definition, resolving any external $ref pointers in the process
13
* Internal references are preserved, external files are loaded and embedded
14
* @returns Promise resolving to bundled OpenAPI document
15
*/
16
async bundle(): Promise<OpenAPI.Document>;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import OASNormalize from "oas-normalize";
23
24
// API definition with external references
25
const apiWithExternalRefs = {
26
openapi: "3.0.0",
27
info: { title: "Pet Store", version: "1.0.0" },
28
paths: {
29
"/pets": {
30
get: {
31
responses: {
32
"200": {
33
description: "Successful response",
34
content: {
35
"application/json": {
36
schema: { $ref: "./schemas/pet.json" } // External reference
37
}
38
}
39
}
40
}
41
}
42
}
43
},
44
components: {
45
schemas: {
46
Error: { // Internal schema preserved
47
type: "object",
48
properties: {
49
code: { type: "integer" },
50
message: { type: "string" }
51
}
52
}
53
}
54
}
55
};
56
57
const oas = new OASNormalize(apiWithExternalRefs, { enablePaths: true });
58
const bundled = await oas.bundle();
59
60
// External ./schemas/pet.json is now embedded in the bundled document
61
// Internal references like #/components/schemas/Error remain as-is
62
console.log(bundled.components.schemas.Pet); // Now contains the content from pet.json
63
```
64
65
### Dereference Method
66
67
Dereference all $ref pointers, both internal and external, creating a fully expanded document with no references.
68
69
```typescript { .api }
70
/**
71
* Dereference the given API definition, resolving all $ref pointers inline
72
* Creates a fully expanded document with no remaining references
73
* @returns Promise resolving to dereferenced OpenAPI document
74
*/
75
async dereference(): Promise<OpenAPI.Document>;
76
```
77
78
**Usage Examples:**
79
80
```typescript
81
// API definition with internal references
82
const apiWithRefs = {
83
openapi: "3.0.0",
84
info: { title: "Pet Store", version: "1.0.0" },
85
paths: {
86
"/pets": {
87
post: {
88
requestBody: {
89
$ref: "#/components/requestBodies/Pet" // Internal reference
90
},
91
responses: {
92
"200": {
93
description: "Success",
94
content: {
95
"application/json": {
96
schema: { $ref: "#/components/schemas/Pet" } // Internal reference
97
}
98
}
99
}
100
}
101
}
102
}
103
},
104
components: {
105
schemas: {
106
Pet: {
107
type: "object",
108
properties: {
109
name: { type: "string" },
110
category: { $ref: "#/components/schemas/Category" } // Nested reference
111
}
112
},
113
Category: {
114
type: "object",
115
properties: {
116
id: { type: "integer" },
117
name: { type: "string" }
118
}
119
}
120
},
121
requestBodies: {
122
Pet: {
123
description: "Pet object that needs to be added",
124
required: true,
125
content: {
126
"application/json": {
127
schema: { $ref: "#/components/schemas/Pet" }
128
}
129
}
130
}
131
}
132
}
133
};
134
135
const oas = new OASNormalize(apiWithRefs);
136
const dereferenced = await oas.dereference();
137
138
// All $ref pointers are now resolved inline
139
console.log(dereferenced.paths['/pets'].post.requestBody);
140
// Contains the full requestBody object instead of { $ref: "..." }
141
142
console.log(dereferenced.paths['/pets'].post.requestBody.content['application/json'].schema);
143
// Contains the full Pet schema with Category schema inlined
144
```
145
146
### Deref Method (Deprecated)
147
148
Legacy alias for the dereference method, maintained for backward compatibility.
149
150
```typescript { .api }
151
/**
152
* Dereference the given API definition
153
* @deprecated Use dereference() instead. Will be removed in a future release.
154
* @returns Promise resolving to dereferenced OpenAPI document
155
*/
156
async deref(): Promise<OpenAPI.Document>;
157
```
158
159
**Usage Examples:**
160
161
```typescript
162
// Deprecated usage - still works but not recommended
163
const oas = new OASNormalize(apiSpec);
164
const dereferenced = await oas.deref();
165
166
// Preferred usage
167
const preferred = await oas.dereference();
168
```
169
170
## Bundle vs Dereference
171
172
### Bundle: External References Only
173
174
Bundling resolves only external file references, keeping internal references intact:
175
176
```typescript
177
// Before bundling
178
const spec = {
179
paths: {
180
"/pets": {
181
get: {
182
responses: {
183
"200": {
184
schema: { $ref: "./external-schema.json" } // External - will be resolved
185
},
186
"400": {
187
schema: { $ref: "#/components/schemas/Error" } // Internal - preserved
188
}
189
}
190
}
191
}
192
}
193
};
194
195
const bundled = await new OASNormalize(spec, { enablePaths: true }).bundle();
196
197
// After bundling:
198
// - ./external-schema.json content is embedded
199
// - #/components/schemas/Error reference remains as $ref
200
```
201
202
### Dereference: All References
203
204
Dereferencing resolves all references, creating a fully expanded document:
205
206
```typescript
207
// Before dereferencing
208
const spec = {
209
paths: {
210
"/pets": {
211
get: {
212
responses: {
213
"200": { schema: { $ref: "#/components/schemas/Pet" } }
214
}
215
}
216
}
217
},
218
components: {
219
schemas: {
220
Pet: {
221
properties: {
222
category: { $ref: "#/components/schemas/Category" }
223
}
224
},
225
Category: { type: "object", properties: { name: { type: "string" } } }
226
}
227
}
228
};
229
230
const dereferenced = await new OASNormalize(spec).dereference();
231
232
// After dereferencing:
233
// - All $ref pointers are replaced with actual content
234
// - Category schema is inlined within Pet schema
235
// - No references remain in the document
236
```
237
238
## Postman Collection Handling
239
240
Both bundling and dereferencing automatically handle Postman collection conversion:
241
242
```typescript
243
const postmanCollection = {
244
info: { name: "API Collection" },
245
item: [/* collection items */]
246
};
247
248
// Postman collections are automatically converted to OpenAPI first
249
const bundled = await new OASNormalize(postmanCollection).bundle();
250
const dereferenced = await new OASNormalize(postmanCollection).dereference();
251
252
// Both results are OpenAPI documents, not Postman collections
253
console.log(bundled.openapi); // "3.0.0"
254
console.log(dereferenced.openapi); // "3.0.0"
255
```
256
257
## Performance and Caching
258
259
Both operations are cached to improve performance:
260
261
```typescript
262
const oas = new OASNormalize(complexSpec);
263
264
// First call performs the operation
265
const bundled1 = await oas.bundle();
266
267
// Second call returns cached result
268
const bundled2 = await oas.bundle();
269
270
console.log(bundled1 === bundled2); // true
271
272
// Same applies to dereference
273
const deref1 = await oas.dereference();
274
const deref2 = await oas.dereference();
275
console.log(deref1 === deref2); // true
276
```
277
278
## Error Handling
279
280
### External Reference Resolution Errors
281
282
```typescript
283
const specWithBadRef = {
284
openapi: "3.0.0",
285
paths: {
286
"/pets": {
287
get: {
288
responses: {
289
"200": {
290
schema: { $ref: "./nonexistent-file.json" }
291
}
292
}
293
}
294
}
295
}
296
};
297
298
try {
299
await new OASNormalize(specWithBadRef, { enablePaths: true }).bundle();
300
} catch (error) {
301
console.error("Failed to resolve external reference:", error.message);
302
}
303
```
304
305
### Security Restrictions
306
307
```typescript
308
const specWithFileRef = {
309
openapi: "3.0.0",
310
paths: {
311
"/pets": {
312
get: {
313
parameters: [{
314
schema: { $ref: "/etc/passwd" } // Attempting to read system file
315
}]
316
}
317
}
318
}
319
};
320
321
// Without enablePaths, this will fail
322
try {
323
await new OASNormalize(specWithFileRef).bundle();
324
} catch (error) {
325
console.error(error.message); // "Unable to resolve $ref pointer..."
326
}
327
```
328
329
## Integration with Validation
330
331
Reference resolution works seamlessly with validation:
332
333
```typescript
334
const specWithRefs = {
335
// API spec with various $ref pointers
336
};
337
338
const oas = new OASNormalize(specWithRefs);
339
340
// Validate the bundled version
341
const bundled = await oas.bundle();
342
await new OASNormalize(bundled).validate();
343
344
// Or validate the dereferenced version
345
const dereferenced = await oas.dereference();
346
await new OASNormalize(dereferenced).validate();
347
348
// Direct validation also works (resolves references internally)
349
await oas.validate();
350
```