@jentic/arazzo-parser 1.0.0-alpha.1 → 1.0.0-alpha.11

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 CHANGED
@@ -3,6 +3,62 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.0.0-alpha.11](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.10...v1.0.0-alpha.11) (2026-02-10)
7
+
8
+ ### Features
9
+
10
+ - add initial validator implementation ([#60](https://github.com/jentic/jentic-arazzo-tools/issues/60)) ([4e9a73d](https://github.com/jentic/jentic-arazzo-tools/commit/4e9a73dd5ca2b2b48ebc32de6b02c93524fabccf))
11
+
12
+ # [1.0.0-alpha.10](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.9...v1.0.0-alpha.10) (2026-02-08)
13
+
14
+ ### Bug Fixes
15
+
16
+ - **parser:** add doc for accessing parse result via SourceDescription ([c23699b](https://github.com/jentic/jentic-arazzo-tools/commit/c23699bc6cf77cafbd77a9df5dd5fb355f771696))
17
+
18
+ # [1.0.0-alpha.9](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.8...v1.0.0-alpha.9) (2026-02-05)
19
+
20
+ ### Features
21
+
22
+ - **resolver:** add dereferencing support for Arazzo Source Descriptions ([#43](https://github.com/jentic/jentic-arazzo-tools/issues/43)) ([091610b](https://github.com/jentic/jentic-arazzo-tools/commit/091610be81b32540845c7f1cb60dd68348ee282b))
23
+
24
+ # [1.0.0-alpha.8](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.7...v1.0.0-alpha.8) (2026-02-05)
25
+
26
+ **Note:** Version bump only for package @jentic/arazzo-parser
27
+
28
+ # [1.0.0-alpha.7](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) (2026-02-04)
29
+
30
+ ### Features
31
+
32
+ - **parser:** add support for parsing OpenAPI Documents ([#35](https://github.com/jentic/jentic-arazzo-tools/issues/35)) ([4c2615e](https://github.com/jentic/jentic-arazzo-tools/commit/4c2615e07c3b74ea7fe74b91b977c8c7123a2188))
33
+
34
+ # [1.0.0-alpha.6](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) (2026-02-04)
35
+
36
+ ### Features
37
+
38
+ - **parser:** add support for parsing entire Arazzo Description ([#34](https://github.com/jentic/jentic-arazzo-tools/issues/34)) ([44b2bda](https://github.com/jentic/jentic-arazzo-tools/commit/44b2bda1c7449e1db8145af1dea457f2e09a465b))
39
+
40
+ # [1.0.0-alpha.5](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) (2026-01-31)
41
+
42
+ **Note:** Version bump only for package @jentic/arazzo-parser
43
+
44
+ # [1.0.0-alpha.4](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2026-01-31)
45
+
46
+ ### Features
47
+
48
+ - **parser:** add unified options interface & retrievalURI meta ([#16](https://github.com/jentic/jentic-arazzo-tools/issues/16)) ([2d6c3b3](https://github.com/jentic/jentic-arazzo-tools/commit/2d6c3b37f3246bc5ad775c30b508607119c9eb50))
49
+ - **resolver:** add dereferencing support for Arazzo Document fragments ([#21](https://github.com/jentic/jentic-arazzo-tools/issues/21)) ([868dc43](https://github.com/jentic/jentic-arazzo-tools/commit/868dc434b51f6247ca102fae7422a85a0e545d09))
50
+ - **resolver:** add dereferencing support for entry Arazzo Document ([#15](https://github.com/jentic/jentic-arazzo-tools/issues/15)) ([cf016ed](https://github.com/jentic/jentic-arazzo-tools/commit/cf016ed9130f08aac87bbb94b0e45e80c27f8fc3))
51
+
52
+ # [1.0.0-alpha.3](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) (2026-01-29)
53
+
54
+ ### Features
55
+
56
+ - **parser:** add package keywords ([#10](https://github.com/jentic/jentic-arazzo-tools/issues/10)) ([0e71b1b](https://github.com/jentic/jentic-arazzo-tools/commit/0e71b1b77a1222a427214f7f9c281cbc1da13278))
57
+
58
+ # [1.0.0-alpha.2](https://github.com/jentic/jentic-arazzo-tools/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2026-01-28)
59
+
60
+ **Note:** Version bump only for package @jentic/arazzo-parser
61
+
6
62
  # 1.0.0-alpha.1 (2026-01-28)
7
63
 
8
64
  ### Bug Fixes
package/README.md CHANGED
@@ -3,6 +3,15 @@
3
3
  `@jentic/arazzo-parser` is a parser for [Arazzo Specification](https://spec.openapis.org/arazzo/latest.html) documents.
4
4
  It produces [SpecLynx ApiDOM](https://github.com/speclynx/apidom) data model using the [Arazzo 1.x namespace](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-arazzo-1#readme).
5
5
 
6
+ **Supported Arazzo versions:**
7
+ - [Arazzo 1.0.0](https://spec.openapis.org/arazzo/v1.0.0)
8
+ - [Arazzo 1.0.1](https://spec.openapis.org/arazzo/v1.0.1)
9
+
10
+ **Supported OpenAPI versions (for source descriptions):**
11
+ - [OpenAPI 2.0](https://spec.openapis.org/oas/v2.0)
12
+ - [OpenAPI 3.0.x](https://spec.openapis.org/oas/v3.0.4)
13
+ - [OpenAPI 3.1.x](https://spec.openapis.org/oas/v3.1.2)
14
+
6
15
  ## Installation
7
16
 
8
17
  You can install this package via [npm](https://npmjs.org/) CLI by running the following command:
@@ -13,17 +22,21 @@ npm install @jentic/arazzo-parser
13
22
 
14
23
  ## Usage
15
24
 
16
- `@jentic/arazzo-parser` provides a unified `parse` function that accepts multiple input types:
25
+ `@jentic/arazzo-parser` provides a `parseArazzo` function for parsing Arazzo documents.
26
+
27
+ ## Parsing Arazzo Documents
17
28
 
18
- 1. **Plain JavaScript object** - directly refracts into ApiDOM
19
- 2. **String content** - parses inline JSON or YAML Arazzo Documents
29
+ The `parseArazzo` function accepts multiple input types:
30
+
31
+ 1. **Plain JavaScript object** - converts to JSON and parses (source maps supported with `strict: false`)
32
+ 2. **String content** - detects Arazzo content and parses inline JSON or YAML
20
33
  3. **File system path** - resolves and parses local Arazzo Documents
21
34
  4. **HTTP(S) URL** - fetches and parses remote Arazzo Documents
22
35
 
23
- ### Parsing from object
36
+ ### From object
24
37
 
25
38
  ```js
26
- import { parse } from '@jentic/arazzo-parser';
39
+ import { parseArazzo } from '@jentic/arazzo-parser';
27
40
 
28
41
  const arazzoDocument = {
29
42
  arazzo: '1.0.1',
@@ -41,20 +54,20 @@ const arazzoDocument = {
41
54
  workflows: [],
42
55
  };
43
56
 
44
- const parseResult = await parse(arazzoDocument);
57
+ const parseResult = await parseArazzo(arazzoDocument);
45
58
  // parseResult is ParseResultElement containing ArazzoSpecification1Element
46
59
  ```
47
60
 
48
- ### Parsing from string
61
+ ### From string
49
62
 
50
63
  ```js
51
- import { parse } from '@jentic/arazzo-parser';
64
+ import { parseArazzo } from '@jentic/arazzo-parser';
52
65
 
53
66
  // JSON string
54
- const parseResult = await parse('{"arazzo": "1.0.1", "info": {...}}');
67
+ const parseResult = await parseArazzo('{"arazzo": "1.0.1", "info": {...}}');
55
68
 
56
69
  // YAML string
57
- const parseResult = await parse(`
70
+ const parseResult = await parseArazzo(`
58
71
  arazzo: '1.0.1'
59
72
  info:
60
73
  title: My API Workflow
@@ -62,55 +75,62 @@ info:
62
75
  `);
63
76
  ```
64
77
 
65
- ### Parsing from file
78
+ ### From file
66
79
 
67
80
  ```js
68
- import { parse } from '@jentic/arazzo-parser';
81
+ import { parseArazzo } from '@jentic/arazzo-parser';
69
82
 
70
- const parseResult = await parse('/path/to/arazzo.json');
83
+ const parseResult = await parseArazzo('/path/to/arazzo.json');
71
84
  ```
72
85
 
73
- ### Parsing from URL
86
+ ### From URL
74
87
 
75
88
  ```js
76
- import { parse } from '@jentic/arazzo-parser';
89
+ import { parseArazzo } from '@jentic/arazzo-parser';
77
90
 
78
- const parseResult = await parse('https://example.com/arazzo.yaml');
91
+ const parseResult = await parseArazzo('https://example.com/arazzo.yaml');
79
92
  ```
80
93
 
81
94
  ## Parse options
82
95
 
83
- The `parse` function accepts an optional second argument with parsing options:
96
+ The `parseArazzo` function accepts an optional second argument with reference options compatible with [SpecLynx ApiDOM Reference Options](https://github.com/speclynx/apidom/blob/main/packages/apidom-reference/src/options/index.ts):
84
97
 
85
98
  ```js
86
- import { parse } from '@jentic/arazzo-parser';
99
+ import { parseArazzo } from '@jentic/arazzo-parser';
87
100
 
88
- const parseResult = await parse(source, {
89
- strict: true, // Use strict parsing mode (default: true)
90
- sourceMap: false, // Include source maps (default: false)
91
- parserOpts: {}, // Additional parser options (default: {})
92
- resolverOpts: {}, // Additional resolver options (default: {})
101
+ const parseResult = await parseArazzo(source, {
102
+ parse: {
103
+ parserOpts: {
104
+ strict: true, // Use strict parsing mode (default: true)
105
+ sourceMap: false, // Include source maps (default: false)
106
+ },
107
+ },
93
108
  });
94
109
  ```
95
110
 
96
- ### Options
97
-
98
- | Option | Type | Default | Description |
99
- |--------|------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------|
100
- | `strict` | `boolean` | `true` | Whether to enforce strict parsing mode. Strict mode uses native JSON and YAML parsers without error recovery. |
101
- | `sourceMap` | `boolean` | `false` | Whether to include [source maps](https://github.com/speclynx/apidom/blob/main/packages/apidom-datamodel/README.md#source-maps) in the parsed result. |
102
- | `parserOpts` | `Record<string, unknown>` | `{}` | Additional options passed to the underlying parsers. |
103
- | `resolverOpts` | `Record<string, unknown>` | `{}` | Additional options passed to the underlying resolvers. |
104
-
105
111
  ### Default options
106
112
 
107
113
  You can import the default options:
108
114
 
109
115
  ```js
110
- import { defaultParseOptions } from '@jentic/arazzo-parser';
111
-
112
- console.log(defaultParseOptions);
113
- // { strict: true, sourceMap: false, parserOpts: {}, resolverOpts: {} }
116
+ import { defaultOptions } from '@jentic/arazzo-parser';
117
+
118
+ console.log(defaultOptions);
119
+ // {
120
+ // parse: {
121
+ // parsers: [
122
+ // ArazzoJSON1Parser, ArazzoYAML1Parser,
123
+ // OpenApiJSON2Parser, OpenApiYAML2Parser,
124
+ // OpenApiJSON3_0Parser, OpenApiYAML3_0Parser,
125
+ // OpenApiJSON3_1Parser, OpenApiYAML3_1Parser,
126
+ // ],
127
+ // parserOpts: { sourceMap: false, strict: true, sourceDescriptions: false },
128
+ // },
129
+ // resolve: {
130
+ // resolvers: [MemoryResolver, FileResolver, HTTPResolverAxios],
131
+ // resolverOpts: {},
132
+ // },
133
+ // }
114
134
  ```
115
135
 
116
136
  ## Error handling
@@ -118,10 +138,10 @@ console.log(defaultParseOptions);
118
138
  When parsing fails, a `ParseError` is thrown. The original error is available via the `cause` property:
119
139
 
120
140
  ```js
121
- import { parse } from '@jentic/arazzo-parser';
141
+ import { parseArazzo } from '@jentic/arazzo-parser';
122
142
 
123
143
  try {
124
- await parse('invalid content');
144
+ await parseArazzo('invalid content');
125
145
  } catch (error) {
126
146
  console.error(error.message); // 'Failed to parse Arazzo Document'
127
147
  console.error(error.cause); // Original error from underlying parser
@@ -130,12 +150,12 @@ try {
130
150
 
131
151
  ## Working with the result
132
152
 
133
- The `parse` function returns a [ParseResultElement](https://github.com/speclynx/apidom/blob/main/packages/apidom-datamodel/README.md#parseresultelement) representing the result of the parsing operation.
153
+ The `parseArazzo` function returns a [ParseResultElement](https://github.com/speclynx/apidom/blob/main/packages/apidom-datamodel/README.md#parseresultelement) representing the result of the parsing operation.
134
154
 
135
155
  ```js
136
- import { parse } from '@jentic/arazzo-parser';
156
+ import { parseArazzo } from '@jentic/arazzo-parser';
137
157
 
138
- const parseResult = await parse(source);
158
+ const parseResult = await parseArazzo(source);
139
159
 
140
160
  // Access the main Arazzo specification element
141
161
  const arazzoSpec = parseResult.api;
@@ -147,6 +167,340 @@ const hasErrors = parseResult.errors.length > 0;
147
167
  const isEmpty = parseResult.isEmpty;
148
168
  ```
149
169
 
170
+ ### Retrieval URI metadata
171
+
172
+ When parsing from a file system path or HTTP(S) URL, the `retrievalURI` metadata is set on the parse result:
173
+
174
+ ```js
175
+ import { parseArazzo } from '@jentic/arazzo-parser';
176
+ import { toValue } from '@speclynx/apidom-core';
177
+
178
+ const parseResult = await parseArazzo('/path/to/arazzo.json');
179
+
180
+ // Get the URI from which the document was retrieved
181
+ const uri = toValue(parseResult.meta.get('retrievalURI'));
182
+ // '/path/to/arazzo.json'
183
+ ```
184
+
185
+ Note: `retrievalURI` is not set when parsing from inline content (string) or plain objects.
186
+
187
+ ### Source maps
188
+
189
+ Source maps allow you to track the original position (line, column) of each element in the parsed document. This is useful for error reporting, IDE integrations, linting, and any tooling that needs to show precise locations in the original source.
190
+
191
+
192
+ To enable source maps, set `sourceMap: true` and `strict: false` in the parser options:
193
+
194
+ ```js
195
+ import { parseArazzo } from '@jentic/arazzo-parser';
196
+
197
+ const parseResult = await parseArazzo('/path/to/arazzo.yaml', {
198
+ parse: {
199
+ parserOpts: {
200
+ sourceMap: true,
201
+ strict: false,
202
+ },
203
+ },
204
+ });
205
+ ```
206
+
207
+ When source maps are enabled, each element in the parsed result contains positional properties stored directly on the element. Position values use UTF-16 code units for compatibility with Language Server Protocol (LSP) and JavaScript string indexing:
208
+
209
+ ```js
210
+ import { parseArazzo } from '@jentic/arazzo-parser';
211
+
212
+ const parseResult = await parseArazzo('/path/to/arazzo.yaml', {
213
+ parse: { parserOpts: { sourceMap: true, strict: false } },
214
+ });
215
+
216
+ const arazzoSpec = parseResult.api;
217
+
218
+ // Access source map properties directly on the element
219
+ arazzoSpec.startLine; // 0-based line number where element begins
220
+ arazzoSpec.startCharacter; // 0-based column number where element begins
221
+ arazzoSpec.startOffset; // 0-based character offset from document start
222
+ arazzoSpec.endLine; // 0-based line number where element ends
223
+ arazzoSpec.endCharacter; // 0-based column number where element ends
224
+ arazzoSpec.endOffset; // 0-based character offset where element ends
225
+
226
+ // Access source map on nested elements
227
+ const workflow = arazzoSpec.workflows.get(0);
228
+ console.log(`Workflow starts at line ${workflow.startLine}, column ${workflow.startCharacter}`);
229
+ ```
230
+
231
+ For more details about source maps, see the [SpecLynx ApiDOM Data Model documentation](https://github.com/speclynx/apidom/tree/main/packages/apidom-datamodel#source-maps).
232
+
233
+ **Note:** Source maps require `strict: false` to be set. When parsing from objects, they are converted to pretty-printed JSON strings internally (2-space indentation), so source map positions refer to this generated JSON representation, not the original object structure:
234
+
235
+ ```js
236
+ // Source maps with objects (requires strict: false)
237
+ // Positions will reference the internally generated JSON string
238
+ await parseArazzo({ arazzo: '1.0.1', ... }, {
239
+ parse: { parserOpts: { sourceMap: true, strict: false } },
240
+ });
241
+ ```
242
+
243
+ ## Parsing source descriptions
244
+
245
+ Arazzo documents can reference external API specifications (OpenAPI, Arazzo) through [Source Descriptions](https://spec.openapis.org/arazzo/latest.html#source-description-object). The parser can automatically fetch and parse these referenced documents.
246
+
247
+ **Note:** Source descriptions parsing is disabled by default for performance reasons. Enable it explicitly when you need to resolve and parse referenced API specifications.
248
+
249
+ ### Enabling source descriptions parsing
250
+
251
+ To parse source descriptions, enable the `sourceDescriptions` option in `parserOpts`:
252
+
253
+ ```js
254
+ import { parseArazzo } from '@jentic/arazzo-parser';
255
+
256
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
257
+ parse: {
258
+ parserOpts: {
259
+ sourceDescriptions: true,
260
+ },
261
+ },
262
+ });
263
+ ```
264
+
265
+ Alternatively, you can configure it per parser for more granular control:
266
+
267
+ ```js
268
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
269
+ parse: {
270
+ parserOpts: {
271
+ 'arazzo-json-1': { sourceDescriptions: true },
272
+ 'arazzo-yaml-1': { sourceDescriptions: true },
273
+ },
274
+ },
275
+ });
276
+ ```
277
+
278
+ ### Selective parsing
279
+
280
+ You can selectively parse only specific source descriptions by providing an array of names:
281
+
282
+ ```js
283
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
284
+ parse: {
285
+ parserOpts: {
286
+ sourceDescriptions: ['petStoreApi', 'paymentApi'],
287
+ },
288
+ },
289
+ });
290
+ ```
291
+
292
+ ### Result structure
293
+
294
+ When source descriptions are parsed, each parsed document that is a *direct* source description of the main Arazzo document is added to the main `ParseResultElement` as an additional top-level element. The first element is always the main Arazzo document, and subsequent top-level elements are these directly parsed source descriptions. When recursive parsing discovers further source descriptions from within an already parsed source description, those recursively parsed documents are attached as nested `ParseResultElement` instances beneath the source-description element that referenced them (they are not duplicated at the top level). Consumers that need to see all documents should traverse both the top-level elements and any nested `ParseResultElement`s reachable from source-description elements.
295
+
296
+ Source descriptions are parsed into their appropriate SpecLynx ApiDOM namespace data models based on document type:
297
+
298
+ - [Arazzo 1.x](https://spec.openapis.org/arazzo/latest.html) → [@speclynx/apidom-ns-arazzo-1](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-arazzo-1)
299
+ - [OpenAPI 2.0 (Swagger)](https://spec.openapis.org/oas/v2.0) → [@speclynx/apidom-ns-openapi-2](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-2)
300
+ - [OpenAPI 3.0.x](https://spec.openapis.org/oas/v3.0.4) → [@speclynx/apidom-ns-openapi-3-0](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-3-0)
301
+ - [OpenAPI 3.1.x](https://spec.openapis.org/oas/v3.1.2) → [@speclynx/apidom-ns-openapi-3-1](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-3-1)
302
+
303
+ ```
304
+ ParseResultElement
305
+ ├── .api: ArazzoSpecification1Element
306
+
307
+ ├── ParseResultElement (petStoreApi) ─┐
308
+ │ └── .api: OpenApi3_1Element │ source
309
+ │ │ descriptions
310
+ └── ParseResultElement (legacyApi) ─┘
311
+ ├── .errors
312
+ └── .warnings
313
+ ```
314
+
315
+ ```js
316
+ import { parseArazzo } from '@jentic/arazzo-parser';
317
+
318
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
319
+ parse: {
320
+ parserOpts: {
321
+ sourceDescriptions: true,
322
+ },
323
+ },
324
+ });
325
+
326
+ // Main Arazzo document
327
+ const arazzoSpec = parseResult.api;
328
+
329
+ // Number of elements (1 main + N source descriptions)
330
+ console.log(parseResult.length);
331
+
332
+ // Access parsed source descriptions (filter by 'source-description' class)
333
+ for (let i = 0; i < parseResult.length; i++) {
334
+ const element = parseResult.get(i);
335
+
336
+ if (element.classes.includes('source-description')) {
337
+ // Source description metadata
338
+ const name = element.meta.get('name')?.toValue();
339
+ const type = element.meta.get('type')?.toValue();
340
+
341
+ console.log(`Source description "${name}" (${type})`);
342
+
343
+ // The parsed API document
344
+ const api = element.api;
345
+ }
346
+ }
347
+ ```
348
+
349
+ ### Accessing via SourceDescriptionElement
350
+
351
+ An alternative way to access parsed source descriptions is through the `SourceDescriptionElement` metadata.
352
+ When source descriptions are parsed, a `ParseResultElement` is attached to each `SourceDescriptionElement`'s metadata under the key `'parseResult'`.
353
+
354
+ ```js
355
+ import { parseArazzo } from '@jentic/arazzo-parser';
356
+ import { toValue } from '@speclynx/apidom-core';
357
+
358
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
359
+ parse: {
360
+ parserOpts: {
361
+ sourceDescriptions: true,
362
+ },
363
+ },
364
+ });
365
+
366
+ const arazzoSpec = parseResult.api;
367
+
368
+ // Access parsed document via SourceDescriptionElement
369
+ const sourceDesc = arazzoSpec.sourceDescriptions.get(0);
370
+ const sdParseResult = sourceDesc.meta.get('parseResult');
371
+
372
+ // Check for errors before using
373
+ if (sdParseResult.errors.length === 0) {
374
+ // Access the parsed API
375
+ const api = sdParseResult.api;
376
+ console.log(`API type: ${api.element}`); // e.g., 'openApi3_1'
377
+
378
+ // Get the retrieval URI
379
+ const retrievalURI = toValue(sdParseResult.meta.get('retrievalURI'));
380
+ console.log(`Loaded from: ${retrievalURI}`);
381
+ }
382
+ ```
383
+
384
+ This approach is useful when you need to:
385
+ - Access a specific source description by its position in the `sourceDescriptions` array
386
+ - Get the `retrievalURI` metadata indicating where the document was fetched from
387
+ - Correlate parsed documents with their source description definitions
388
+
389
+ ### Recursive parsing
390
+
391
+ When a source description is of type `arazzo`, the parser recursively parses that document's source descriptions as well. This allows you to parse entire dependency trees of Arazzo documents.
392
+
393
+ ### Limiting recursion depth
394
+
395
+ To prevent excessive recursion or handle deeply nested documents, use the `sourceDescriptionsMaxDepth` option:
396
+
397
+ ```js
398
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
399
+ parse: {
400
+ parserOpts: {
401
+ sourceDescriptions: true,
402
+ sourceDescriptionsMaxDepth: 2, // Only parse 2 levels deep
403
+ },
404
+ },
405
+ });
406
+ ```
407
+
408
+ The default value is `+Infinity` (no limit). Setting it to `0` will create error annotations instead of parsing any source descriptions.
409
+
410
+ ### Cycle detection
411
+
412
+ The parser automatically detects circular references between Arazzo documents. When a cycle is detected, a warning annotation is added instead of causing infinite recursion:
413
+
414
+ ```js
415
+ // arazzo-a.json references arazzo-b.json
416
+ // arazzo-b.json references arazzo-a.json (cycle!)
417
+
418
+ const parseResult = await parseArazzo('/path/to/arazzo-a.json', {
419
+ parse: {
420
+ parserOpts: {
421
+ sourceDescriptions: true,
422
+ },
423
+ },
424
+ });
425
+
426
+ // The cycle is handled gracefully - check for warning annotations
427
+ ```
428
+
429
+ ### Error and warning handling
430
+
431
+ When issues occur during source description parsing, the parser does not throw errors. Instead, it adds annotation elements to the source description's parse result:
432
+
433
+ - **`error`** class - Parsing failed (e.g., file not found, invalid document, max depth exceeded)
434
+ - **`warning`** class - Non-fatal issues (e.g., cycle detected, type mismatch between declared and actual)
435
+
436
+ This allows partial parsing to succeed even if some source descriptions have issues:
437
+
438
+ ```js
439
+ const parseResult = await parseArazzo('/path/to/arazzo.json', {
440
+ parse: {
441
+ parserOpts: {
442
+ sourceDescriptions: true,
443
+ },
444
+ },
445
+ });
446
+
447
+ // Check each source description for errors and warnings
448
+ for (let i = 0; i < parseResult.length; i++) {
449
+ const element = parseResult.get(i);
450
+
451
+ if (element.classes.includes('source-description')) {
452
+ const name = element.meta.get('name')?.toValue();
453
+
454
+ // Use built-in accessors for errors and warnings
455
+ element.errors.forEach((error) => {
456
+ console.error(`Error in "${name}": ${error.toValue()}`);
457
+ });
458
+
459
+ element.warnings.forEach((warning) => {
460
+ console.warn(`Warning in "${name}": ${warning.toValue()}`);
461
+ });
462
+ }
463
+ }
464
+ ```
465
+
466
+ ## Parsing OpenAPI Documents
467
+
468
+ The `parseOpenAPI` function provides complete control for parsing OpenAPI documents manually.
469
+ This is useful when you need to parse source descriptions independently or implement custom source description resolution logic.
470
+
471
+ The function accepts the same input types as `parseArazzo`:
472
+
473
+ 1. **Plain JavaScript object** - converts to JSON and parses
474
+ 2. **String content** - detects OpenAPI content and parses inline JSON or YAML
475
+ 3. **File system path** - resolves and parses local OpenAPI Documents
476
+ 4. **HTTP(S) URL** - fetches and parses remote OpenAPI Documents
477
+
478
+ Documents are parsed into their appropriate SpecLynx ApiDOM namespace data models:
479
+
480
+ - [OpenAPI 2.0 (Swagger)](https://spec.openapis.org/oas/v2.0) → [@speclynx/apidom-ns-openapi-2](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-2)
481
+ - [OpenAPI 3.0.x](https://spec.openapis.org/oas/v3.0.4) → [@speclynx/apidom-ns-openapi-3-0](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-3-0)
482
+ - [OpenAPI 3.1.x](https://spec.openapis.org/oas/v3.1.2) → [@speclynx/apidom-ns-openapi-3-1](https://github.com/speclynx/apidom/tree/main/packages/apidom-ns-openapi-3-1)
483
+
484
+ ```js
485
+ import { parseOpenAPI } from '@jentic/arazzo-parser';
486
+
487
+ // From object
488
+ const parseResult = await parseOpenAPI({
489
+ openapi: '3.1.0',
490
+ info: { title: 'My API', version: '1.0.0' },
491
+ paths: {},
492
+ });
493
+
494
+ // From string
495
+ const parseResult = await parseOpenAPI('{"openapi": "3.1.0", ...}');
496
+
497
+ // From file
498
+ const parseResult = await parseOpenAPI('/path/to/openapi.json');
499
+
500
+ // From URL
501
+ const parseResult = await parseOpenAPI('https://example.com/openapi.yaml');
502
+ ```
503
+
150
504
  ## SpecLynx ApiDOM tooling
151
505
 
152
506
  Since `@jentic/arazzo-parser` produces a SpecLynx ApiDOM data model, you have access to the full suite of ApiDOM tools for manipulating, traversing, and transforming the parsed document.
@@ -156,10 +510,11 @@ Since `@jentic/arazzo-parser` produces a SpecLynx ApiDOM data model, you have ac
156
510
  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:
157
511
 
158
512
  ```js
159
- import { parse } from '@jentic/arazzo-parser';
160
- import { toValue, toJSON, toYAML, clone, sexprs } from '@speclynx/apidom-core';
513
+ import { parseArazzo } from '@jentic/arazzo-parser';
514
+ import { cloneDeep, cloneShallow } from '@speclynx/apidom-datamodel';
515
+ import { toValue, toJSON, toYAML, sexprs } from '@speclynx/apidom-core';
161
516
 
162
- const parseResult = await parse(source);
517
+ const parseResult = await parseArazzo(source);
163
518
  const arazzoSpec = parseResult.api;
164
519
 
165
520
  // Convert to plain JavaScript object
@@ -171,8 +526,9 @@ const json = toJSON(arazzoSpec);
171
526
  // Serialize to YAML string
172
527
  const yaml = toYAML(arazzoSpec);
173
528
 
174
- // Deep clone the element
175
- const cloned = clone(arazzoSpec);
529
+ // Clone the element
530
+ const clonedShallow = cloneShallow(arazzoSpec);
531
+ const clonedDeep = cloneDeep(arazzoSpec);
176
532
 
177
533
  // Get S-expression representation (useful for debugging)
178
534
  const sexpr = sexprs(arazzoSpec);
@@ -183,10 +539,10 @@ const sexpr = sexprs(arazzoSpec);
183
539
  The [@speclynx/apidom-traverse](https://github.com/speclynx/apidom/tree/main/packages/apidom-traverse) package provides powerful traversal capabilities. Here is a basic example:
184
540
 
185
541
  ```js
186
- import { parse } from '@jentic/arazzo-parser';
542
+ import { parseArazzo } from '@jentic/arazzo-parser';
187
543
  import { traverse } from '@speclynx/apidom-traverse';
188
544
 
189
- const parseResult = await parse(source);
545
+ const parseResult = await parseArazzo(source);
190
546
 
191
547
  // Traverse and collect steps using semantic visitor hook
192
548
  const steps = [];