@jentic/arazzo-resolver 1.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +490 -0
- package/dist/jentic-arazzo-resolver.browser.js +84468 -0
- package/dist/jentic-arazzo-resolver.browser.min.js +1 -0
- package/package.json +73 -0
- package/src/dereference/arazzo.cjs +272 -0
- package/src/dereference/arazzo.mjs +264 -0
- package/src/dereference/openapi.cjs +259 -0
- package/src/dereference/openapi.mjs +251 -0
- package/src/errors/DereferenceError.cjs +15 -0
- package/src/errors/DereferenceError.mjs +12 -0
- package/src/index.cjs +15 -0
- package/src/index.mjs +3 -0
- package/types/arazzo-resolver.d.ts +217 -0
package/README.md
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
# @jentic/arazzo-resolver
|
|
2
|
+
|
|
3
|
+
`@jentic/arazzo-resolver` is a resolver for [Arazzo Specification](https://spec.openapis.org/arazzo/latest.html) and [OpenAPI Specification](https://spec.openapis.org/oas/latest.html) documents.
|
|
4
|
+
It produces [SpecLynx ApiDOM](https://github.com/speclynx/apidom) data models using the appropriate namespace ([Arazzo 1.x](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-arazzo-1#readme), [OpenAPI 2.0](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-2#readme), [OpenAPI 3.0.x](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-3-0#readme), [OpenAPI 3.1.x](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-3-1#readme)).
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
You can install this package via [npm](https://npmjs.org/) CLI by running the following command:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @jentic/arazzo-resolver
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Dereferencing
|
|
15
|
+
|
|
16
|
+
Dereferencing is the process of replacing references with the actual content they point to.
|
|
17
|
+
|
|
18
|
+
**In Arazzo Documents**, this includes:
|
|
19
|
+
|
|
20
|
+
- **JSON Schemas** - resolves references within schemas
|
|
21
|
+
- **Reusable Object references** (`$components.*`) - references to reusable components like parameters and actions
|
|
22
|
+
|
|
23
|
+
**In OpenAPI Documents**, this includes:
|
|
24
|
+
|
|
25
|
+
- **Reference Objects** (`$ref`) - resolves references to components, external files, and URLs
|
|
26
|
+
- **JSON Schemas** - resolves references within schemas
|
|
27
|
+
- **Path Item Object** - resolves references to path items
|
|
28
|
+
- and others
|
|
29
|
+
|
|
30
|
+
After dereferencing, all references are resolved inline, making the document self-contained and easier to process programmatically.
|
|
31
|
+
|
|
32
|
+
### Functions
|
|
33
|
+
|
|
34
|
+
**Arazzo:**
|
|
35
|
+
- **`dereferenceArazzo(uri)`** - Dereferences from a file system path or HTTP(S) URL
|
|
36
|
+
- **`dereferenceArazzoElement(element)`** - Dereferences a SpecLynx ApiDOM element
|
|
37
|
+
|
|
38
|
+
**OpenAPI:**
|
|
39
|
+
- **`dereferenceOpenAPI(uri)`** - Dereferences from a file system path or HTTP(S) URL
|
|
40
|
+
- **`dereferenceOpenAPIElement(element)`** - Dereferences a SpecLynx ApiDOM element
|
|
41
|
+
|
|
42
|
+
### Arazzo Documents
|
|
43
|
+
|
|
44
|
+
#### From file
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
48
|
+
|
|
49
|
+
const parseResult = await dereferenceArazzo('/path/to/arazzo.json');
|
|
50
|
+
// parseResult is ParseResultElement with all references resolved
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### From URL
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
57
|
+
|
|
58
|
+
const parseResult = await dereferenceArazzo('https://example.com/arazzo.yaml');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### From ApiDOM element
|
|
62
|
+
|
|
63
|
+
When you already have a parsed Arazzo Document (e.g., from `@jentic/arazzo-parser`), you can dereference the element directly:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
import { parseArazzo } from '@jentic/arazzo-parser';
|
|
67
|
+
import { dereferenceArazzoElement } from '@jentic/arazzo-resolver';
|
|
68
|
+
|
|
69
|
+
// Parse first, then dereference
|
|
70
|
+
const parseResult = await parseArazzo('/path/to/arazzo.json');
|
|
71
|
+
const dereferenced = await dereferenceArazzoElement(parseResult);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
##### Without retrievalURI
|
|
75
|
+
|
|
76
|
+
When dereferencing a ParseResultElement that was parsed from inline content (string or object), you must provide a `baseURI`:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { parseArazzo } from '@jentic/arazzo-parser';
|
|
80
|
+
import { dereferenceArazzoElement } from '@jentic/arazzo-resolver';
|
|
81
|
+
|
|
82
|
+
const parseResult = await parseArazzo({ arazzo: '1.0.1', ... });
|
|
83
|
+
const dereferenced = await dereferenceArazzoElement(parseResult, {
|
|
84
|
+
resolve: { baseURI: 'https://example.com/arazzo.json' },
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
##### Child elements
|
|
89
|
+
|
|
90
|
+
You can dereference individual child elements (e.g., a specific workflow) by providing the parent parseResult in options:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import { parseArazzo } from '@jentic/arazzo-parser';
|
|
94
|
+
import { dereferenceArazzoElement } from '@jentic/arazzo-resolver';
|
|
95
|
+
|
|
96
|
+
const parseResult = await parseArazzo('/path/to/arazzo.json');
|
|
97
|
+
const workflow = parseResult.api.workflows.get(0);
|
|
98
|
+
|
|
99
|
+
const dereferencedWorkflow = await dereferenceArazzoElement(workflow, {
|
|
100
|
+
dereference: { strategyOpts: { parseResult } },
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
##### Source descriptions
|
|
105
|
+
|
|
106
|
+
Source descriptions referenced in the Arazzo Document can optionally be dereferenced using strategy options.
|
|
107
|
+
|
|
108
|
+
The following options can be passed via `dereference.strategyOpts` (globally) or `dereference.strategyOpts['arazzo-1']` (strategy-specific).
|
|
109
|
+
Strategy-specific options take precedence over global options.
|
|
110
|
+
|
|
111
|
+
- **sourceDescriptions** - Controls which external source descriptions are dereferenced and included in the result.
|
|
112
|
+
- `true` - dereference all source descriptions
|
|
113
|
+
- `string[]` - dereference only source descriptions with matching names (e.g., `['petStore', 'paymentApi']`)
|
|
114
|
+
|
|
115
|
+
Each dereferenced source description is added with a `'source-description'` class and metadata (`name`, `type`, `retrievalURI`).
|
|
116
|
+
Only [OpenAPI 2.0](https://spec.openapis.org/oas/v2.0), [OpenAPI 3.0.x](https://spec.openapis.org/oas/v3.0.4), [OpenAPI 3.1.x](https://spec.openapis.org/oas/v3.1.2), and [Arazzo 1.x](https://spec.openapis.org/arazzo/v1.0.1) documents are accepted as source descriptions.
|
|
117
|
+
- **sourceDescriptionsMaxDepth** - Maximum recursion depth for dereferencing nested Arazzo source descriptions.
|
|
118
|
+
Defaults to `+Infinity`. Circular references are automatically detected and skipped.
|
|
119
|
+
|
|
120
|
+
###### Error handling
|
|
121
|
+
|
|
122
|
+
The source descriptions dereferencing uses annotations instead of throwing errors, allowing dereferencing to continue
|
|
123
|
+
even when individual source descriptions fail. Errors are reported as `AnnotationElement` instances
|
|
124
|
+
with an `'error'` class within the result:
|
|
125
|
+
|
|
126
|
+
- **Max depth exceeded** - When `sourceDescriptionsMaxDepth` is reached, an error annotation is returned
|
|
127
|
+
instead of the nested source descriptions
|
|
128
|
+
- **Dereference failures** - If a source description file cannot be dereferenced (e.g., file not found, invalid syntax),
|
|
129
|
+
an error annotation is returned for that specific source description while other source descriptions
|
|
130
|
+
continue to be processed
|
|
131
|
+
- **Validation warnings** - Warning annotations (with `'warning'` class) are returned when the dereferenced document
|
|
132
|
+
is not an OpenAPI or Arazzo specification
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
136
|
+
|
|
137
|
+
// Dereference all source descriptions
|
|
138
|
+
const result = await dereferenceArazzo('/path/to/arazzo.json', {
|
|
139
|
+
dereference: {
|
|
140
|
+
strategyOpts: {
|
|
141
|
+
sourceDescriptions: true,
|
|
142
|
+
sourceDescriptionsMaxDepth: 10,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Dereference only specific source descriptions by name
|
|
148
|
+
const resultFiltered = await dereferenceArazzo('/path/to/arazzo.json', {
|
|
149
|
+
dereference: {
|
|
150
|
+
strategyOpts: {
|
|
151
|
+
'arazzo-1': {
|
|
152
|
+
sourceDescriptions: ['petStore', 'paymentApi'],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### OpenAPI Documents
|
|
160
|
+
|
|
161
|
+
Supports [OpenAPI 2.0 (Swagger)](https://spec.openapis.org/oas/v2.0), [OpenAPI 3.0.x](https://spec.openapis.org/oas/v3.0.4), and [OpenAPI 3.1.x](https://spec.openapis.org/oas/v3.1.2).
|
|
162
|
+
|
|
163
|
+
#### From file
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
import { dereferenceOpenAPI } from '@jentic/arazzo-resolver';
|
|
167
|
+
|
|
168
|
+
const parseResult = await dereferenceOpenAPI('/path/to/openapi.json');
|
|
169
|
+
// parseResult is ParseResultElement with all references resolved
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### From URL
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
import { dereferenceOpenAPI } from '@jentic/arazzo-resolver';
|
|
176
|
+
|
|
177
|
+
const parseResult = await dereferenceOpenAPI('https://example.com/openapi.yaml');
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### From ApiDOM element
|
|
181
|
+
|
|
182
|
+
When you already have a parsed OpenAPI Document (e.g., from `@jentic/arazzo-parser`), you can dereference the element directly:
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
import { parseOpenAPI } from '@jentic/arazzo-parser';
|
|
186
|
+
import { dereferenceOpenAPIElement } from '@jentic/arazzo-resolver';
|
|
187
|
+
|
|
188
|
+
// Parse first, then dereference
|
|
189
|
+
const parseResult = await parseOpenAPI('/path/to/openapi.json');
|
|
190
|
+
const dereferenced = await dereferenceOpenAPIElement(parseResult);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
##### Without retrievalURI
|
|
194
|
+
|
|
195
|
+
When dereferencing a ParseResultElement that was parsed from inline content (string or object), you must provide a `baseURI`:
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
import { parseOpenAPI } from '@jentic/arazzo-parser';
|
|
199
|
+
import { dereferenceOpenAPIElement } from '@jentic/arazzo-resolver';
|
|
200
|
+
|
|
201
|
+
const parseResult = await parseOpenAPI({ openapi: '3.1.0', ... });
|
|
202
|
+
const dereferenced = await dereferenceOpenAPIElement(parseResult, {
|
|
203
|
+
resolve: { baseURI: 'https://example.com/openapi.json' },
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
##### Child elements
|
|
208
|
+
|
|
209
|
+
You can dereference individual child elements (e.g., a specific Operation Object) by providing the parent parseResult in options:
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
import { parseOpenAPI } from '@jentic/arazzo-parser';
|
|
213
|
+
import { dereferenceOpenAPIElement } from '@jentic/arazzo-resolver';
|
|
214
|
+
|
|
215
|
+
const parseResult = await parseOpenAPI('/path/to/openapi.json');
|
|
216
|
+
const operation = parseResult.api.paths.get('/users').get;
|
|
217
|
+
|
|
218
|
+
const dereferencedOperation = await dereferenceOpenAPIElement(operation, {
|
|
219
|
+
dereference: { strategyOpts: { parseResult } },
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Options
|
|
224
|
+
|
|
225
|
+
All dereference functions accept an optional options argument compatible with [SpecLynx ApiDOM Reference Options](https://github.com/speclynx/apidom/blob/main/packages/apidom-reference/src/options/index.ts):
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
229
|
+
|
|
230
|
+
const parseResult = await dereferenceArazzo('/path/to/arazzo.json', {
|
|
231
|
+
resolve: {
|
|
232
|
+
baseURI: 'https://example.com/', // Base URI for relative references
|
|
233
|
+
},
|
|
234
|
+
parse: {
|
|
235
|
+
parserOpts: {
|
|
236
|
+
sourceMap: true, // Include source maps in parsed documents
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Default options
|
|
243
|
+
|
|
244
|
+
You can import and inspect the default options:
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
import {
|
|
248
|
+
defaultDereferenceArazzoOptions,
|
|
249
|
+
defaultDereferenceOpenAPIOptions,
|
|
250
|
+
} from '@jentic/arazzo-resolver';
|
|
251
|
+
|
|
252
|
+
console.log(defaultDereferenceArazzoOptions);
|
|
253
|
+
// {
|
|
254
|
+
// resolve: {
|
|
255
|
+
// resolvers: [FileResolver, HTTPResolverAxios],
|
|
256
|
+
// },
|
|
257
|
+
// parse: {
|
|
258
|
+
// parsers: [
|
|
259
|
+
// ArazzoJSON1Parser, ArazzoYAML1Parser,
|
|
260
|
+
// OpenApiJSON2Parser, OpenApiYAML2Parser,
|
|
261
|
+
// OpenApiJSON3_0Parser, OpenApiYAML3_0Parser,
|
|
262
|
+
// OpenApiJSON3_1Parser, OpenApiYAML3_1Parser,
|
|
263
|
+
// JSONParser, YAMLParser, BinaryParser
|
|
264
|
+
// ],
|
|
265
|
+
// },
|
|
266
|
+
// dereference: {
|
|
267
|
+
// strategies: [
|
|
268
|
+
// Arazzo1DereferenceStrategy,
|
|
269
|
+
// OpenAPI2DereferenceStrategy, OpenAPI3_0DereferenceStrategy, OpenAPI3_1DereferenceStrategy
|
|
270
|
+
// ],
|
|
271
|
+
// strategyOpts: {
|
|
272
|
+
// sourceDescriptions: false,
|
|
273
|
+
// },
|
|
274
|
+
// },
|
|
275
|
+
// }
|
|
276
|
+
|
|
277
|
+
console.log(defaultDereferenceOpenAPIOptions);
|
|
278
|
+
// {
|
|
279
|
+
// resolve: {
|
|
280
|
+
// resolvers: [FileResolver, HTTPResolverAxios],
|
|
281
|
+
// },
|
|
282
|
+
// parse: {
|
|
283
|
+
// parsers: [
|
|
284
|
+
// OpenApiJSON2Parser, OpenApiYAML2Parser,
|
|
285
|
+
// OpenApiJSON3_0Parser, OpenApiYAML3_0Parser,
|
|
286
|
+
// OpenApiJSON3_1Parser, OpenApiYAML3_1Parser,
|
|
287
|
+
// JSONParser, YAMLParser, BinaryParser
|
|
288
|
+
// ],
|
|
289
|
+
// },
|
|
290
|
+
// dereference: {
|
|
291
|
+
// strategies: [OpenAPI2DereferenceStrategy, OpenAPI3_0DereferenceStrategy, OpenAPI3_1DereferenceStrategy],
|
|
292
|
+
// },
|
|
293
|
+
// }
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Error handling
|
|
297
|
+
|
|
298
|
+
When dereferencing fails, a `DereferenceError` is thrown. The original error is available via the `cause` property:
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
import { dereferenceArazzo, dereferenceOpenAPI, DereferenceError } from '@jentic/arazzo-resolver';
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
await dereferenceArazzo('/path/to/arazzo.json');
|
|
305
|
+
} catch (error) {
|
|
306
|
+
if (error instanceof DereferenceError) {
|
|
307
|
+
console.error(error.message); // 'Failed to dereference Arazzo Document at "/path/to/arazzo.json"'
|
|
308
|
+
console.error(error.cause); // Original error from underlying resolver
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
await dereferenceOpenAPI('/path/to/openapi.json');
|
|
314
|
+
} catch (error) {
|
|
315
|
+
if (error instanceof DereferenceError) {
|
|
316
|
+
console.error(error.message); // 'Failed to dereference OpenAPI Document at "/path/to/openapi.json"'
|
|
317
|
+
console.error(error.cause); // Original error from underlying resolver
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Working with the result
|
|
323
|
+
|
|
324
|
+
Both `dereferenceArazzo` and `dereferenceOpenAPI` functions return a [ParseResultElement](https://github.com/speclynx/apidom/blob/main/packages/apidom-datamodel/README.md#parseresultelement) with all references resolved inline.
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
328
|
+
|
|
329
|
+
const parseResult = await dereferenceArazzo('/path/to/arazzo.json');
|
|
330
|
+
|
|
331
|
+
// Access the main Arazzo specification element
|
|
332
|
+
const arazzoSpec = parseResult.api;
|
|
333
|
+
|
|
334
|
+
// Check if parsing produced any errors
|
|
335
|
+
const hasErrors = parseResult.errors.length > 0;
|
|
336
|
+
|
|
337
|
+
// Check if parseResult is empty
|
|
338
|
+
const isEmpty = parseResult.isEmpty;
|
|
339
|
+
|
|
340
|
+
// All references are now resolved inline
|
|
341
|
+
const firstWorkflow = arazzoSpec.workflows.get(0);
|
|
342
|
+
const firstStep = firstWorkflow.steps.get(0);
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Retrieval URI metadata
|
|
346
|
+
|
|
347
|
+
Both `dereferenceArazzo` and `dereferenceOpenAPI` functions automatically set `retrievalURI` metadata on the parse result:
|
|
348
|
+
|
|
349
|
+
```js
|
|
350
|
+
import { dereferenceArazzo, dereferenceOpenAPI } from '@jentic/arazzo-resolver';
|
|
351
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
352
|
+
|
|
353
|
+
const arazzoResult = await dereferenceArazzo('https://example.com/arazzo.yaml');
|
|
354
|
+
const arazzoUri = toValue(arazzoResult.meta.get('retrievalURI'));
|
|
355
|
+
// 'https://example.com/arazzo.yaml'
|
|
356
|
+
|
|
357
|
+
const openapiResult = await dereferenceOpenAPI('https://example.com/openapi.yaml');
|
|
358
|
+
const openapiUri = toValue(openapiResult.meta.get('retrievalURI'));
|
|
359
|
+
// 'https://example.com/openapi.yaml'
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Note: `dereferenceArazzoElement` and `dereferenceOpenAPIElement` do not set `retrievalURI` - they preserve whatever metadata was on the original element.
|
|
363
|
+
|
|
364
|
+
#### Source descriptions
|
|
365
|
+
|
|
366
|
+
When dereferencing with `sourceDescriptions` enabled, the result contains the entry Arazzo Document at index 0, followed by any dereferenced source descriptions.
|
|
367
|
+
Each source description is a `ParseResultElement` with `'source-description'` class and metadata.
|
|
368
|
+
|
|
369
|
+
```js
|
|
370
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
371
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
372
|
+
|
|
373
|
+
const result = await dereferenceArazzo('/path/to/arazzo.json', {
|
|
374
|
+
dereference: { strategyOpts: { sourceDescriptions: true } },
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// Access entry Arazzo Document
|
|
378
|
+
const entryArazzo = result.api; // ArazzoSpecification1Element
|
|
379
|
+
|
|
380
|
+
// Iterate over source descriptions (starting at index 1)
|
|
381
|
+
for (let i = 1; i < result.length; i++) {
|
|
382
|
+
const sdParseResult = result.get(i);
|
|
383
|
+
|
|
384
|
+
// Check if it's a source description
|
|
385
|
+
if (sdParseResult.classes.includes('source-description')) {
|
|
386
|
+
const name = toValue(sdParseResult.meta.get('name'));
|
|
387
|
+
const type = toValue(sdParseResult.meta.get('type')); // 'openapi' or 'arazzo'
|
|
388
|
+
const retrievalURI = toValue(sdParseResult.meta.get('retrievalURI'));
|
|
389
|
+
|
|
390
|
+
// Access the dereferenced API element
|
|
391
|
+
const api = sdParseResult.api; // OpenApi3_1Element, SwaggerElement, ArazzoSpecification1Element, etc.
|
|
392
|
+
console.log(`Source "${name}" (${type}) from ${retrievalURI}:`, api?.element);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
##### Accessing via SourceDescriptionElement
|
|
398
|
+
|
|
399
|
+
An alternative way to access dereferenced source descriptions is through the `SourceDescriptionElement` metadata.
|
|
400
|
+
When source descriptions are dereferenced, a `ParseResultElement` is attached to each `SourceDescriptionElement`'s metadata under the key `'parseResult'`.
|
|
401
|
+
|
|
402
|
+
```js
|
|
403
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
404
|
+
import { toValue } from '@speclynx/apidom-core';
|
|
405
|
+
|
|
406
|
+
const result = await dereferenceArazzo('/path/to/arazzo.json', {
|
|
407
|
+
dereference: { strategyOpts: { sourceDescriptions: true } },
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
const arazzoSpec = result.api;
|
|
411
|
+
|
|
412
|
+
// Access dereferenced document via SourceDescriptionElement
|
|
413
|
+
const sourceDesc = arazzoSpec.sourceDescriptions.get(0);
|
|
414
|
+
const sdParseResult = sourceDesc.meta.get('parseResult');
|
|
415
|
+
|
|
416
|
+
// Check for errors before using
|
|
417
|
+
if (sdParseResult.errors.length === 0) {
|
|
418
|
+
// Access the dereferenced API
|
|
419
|
+
const api = sdParseResult.api;
|
|
420
|
+
console.log(`API type: ${api.element}`); // e.g., 'openApi3_1'
|
|
421
|
+
|
|
422
|
+
// Get the retrieval URI
|
|
423
|
+
const retrievalURI = toValue(sdParseResult.meta.get('retrievalURI'));
|
|
424
|
+
console.log(`Loaded from: ${retrievalURI}`);
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
This approach is useful when you need to:
|
|
429
|
+
- Access a specific source description by its position in the `sourceDescriptions` array
|
|
430
|
+
- Get the `retrievalURI` metadata indicating where the document was fetched from
|
|
431
|
+
- Correlate dereferenced documents with their source description definitions
|
|
432
|
+
|
|
433
|
+
**Note:** When the `ParseResultElement` already contains parsed source descriptions (from parsing with `sourceDescriptions: true`), the dereferencer reuses them instead of re-fetching. This makes the parse-then-dereference workflow efficient.
|
|
434
|
+
|
|
435
|
+
## SpecLynx ApiDOM tooling
|
|
436
|
+
|
|
437
|
+
Since `@jentic/arazzo-resolver` produces a SpecLynx ApiDOM data model, you have access to the full suite of ApiDOM tools for manipulating, traversing, and transforming the dereferenced document.
|
|
438
|
+
|
|
439
|
+
### Core utilities
|
|
440
|
+
|
|
441
|
+
The [@speclynx/apidom-core](https://github.com/speclynx/apidom/tree/main/packages/apidom-core) package provides essential utilities for working with ApiDOM elements. Here are just a few examples:
|
|
442
|
+
|
|
443
|
+
```js
|
|
444
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
445
|
+
import { cloneDeep, cloneShallow } from '@speclynx/apidom-datamodel';
|
|
446
|
+
import { toValue, toJSON, toYAML, sexprs } from '@speclynx/apidom-core';
|
|
447
|
+
|
|
448
|
+
const parseResult = await dereferenceArazzo('/path/to/arazzo.json');
|
|
449
|
+
const arazzoSpec = parseResult.api;
|
|
450
|
+
|
|
451
|
+
// Convert to plain JavaScript object
|
|
452
|
+
const obj = toValue(arazzoSpec);
|
|
453
|
+
|
|
454
|
+
// Serialize to JSON string
|
|
455
|
+
const json = toJSON(arazzoSpec);
|
|
456
|
+
|
|
457
|
+
// Serialize to YAML string
|
|
458
|
+
const yaml = toYAML(arazzoSpec);
|
|
459
|
+
|
|
460
|
+
// Clone the element
|
|
461
|
+
const clonedShallow = cloneShallow(arazzoSpec);
|
|
462
|
+
const clonedDeep = cloneDeep(arazzoSpec);
|
|
463
|
+
|
|
464
|
+
// Get S-expression representation (useful for debugging)
|
|
465
|
+
const sexpr = sexprs(arazzoSpec);
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Traversal
|
|
469
|
+
|
|
470
|
+
The [@speclynx/apidom-traverse](https://github.com/speclynx/apidom/tree/main/packages/apidom-traverse) package provides powerful traversal capabilities. Here is a basic example:
|
|
471
|
+
|
|
472
|
+
```js
|
|
473
|
+
import { dereferenceArazzo } from '@jentic/arazzo-resolver';
|
|
474
|
+
import { traverse } from '@speclynx/apidom-traverse';
|
|
475
|
+
|
|
476
|
+
const parseResult = await dereferenceArazzo('/path/to/arazzo.json');
|
|
477
|
+
|
|
478
|
+
// Traverse and collect steps using semantic visitor hook
|
|
479
|
+
const steps = [];
|
|
480
|
+
traverse(parseResult.api, {
|
|
481
|
+
StepElement(path) {
|
|
482
|
+
steps.push(path.node);
|
|
483
|
+
if (steps.length >= 10) {
|
|
484
|
+
path.stop(); // Stop traversal after collecting 10 steps
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
For more information about available utilities, see the [SpecLynx ApiDOM documentation](https://github.com/speclynx/apidom).
|