Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions packages/apidom-reference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Parser-specific options take precedence over global options.
- `true` - parse all source descriptions
- `string[]` - parse only source descriptions with matching names (e.g., `['petStore', 'paymentApi']`)

Each parsed source description is added with a `'source-description'` class and metadata (`name`, `type`).
Each parsed source description is added with a `'source-description'` class and metadata (`name`, `type`, `retrievalURI`).
Only OpenAPI 2.0, OpenAPI 3.0.x, OpenAPI 3.1.x, and Arazzo 1.x documents are accepted as source descriptions.
- **sourceDescriptionsMaxDepth** - Maximum recursion depth for parsing nested Arazzo source descriptions.
Defaults to `+Infinity`. Circular references are automatically detected and skipped.
Expand All @@ -321,6 +321,7 @@ with an `'error'` class within the parse result:
for parsing are not met (e.g., API is not an Arazzo specification)

```js
import { toValue } from '@speclynx/apidom-core';
import { parse } from '@speclynx/apidom-reference';

// Parse all source descriptions
Expand All @@ -345,8 +346,9 @@ const parseResultFiltered = await parse('/path/to/arazzo.json', {
// Access parsed source descriptions
for (const element of parseResult) {
if (element.classes.includes('source-description')) {
console.log(element.meta.get('name').toValue()); // e.g., 'petStore'
console.log(element.meta.get('type').toValue()); // e.g., 'openapi'
console.log(toValue(element.meta.get('name'))); // e.g., 'petStore'
console.log(toValue(element.meta.get('type'))); // e.g., 'openapi'
console.log(toValue(element.meta.get('retrievalURI'))); // e.g., '/path/to/petstore.json'
}
}
```
Expand All @@ -361,6 +363,7 @@ regardless of success or failure:
- **On failure**: The parseResult contains error/warning annotations explaining what went wrong

```js
import { toValue } from '@speclynx/apidom-core';
import { parse } from '@speclynx/apidom-reference';

const parseResult = await parse('/path/to/arazzo.json', {
Expand All @@ -377,6 +380,7 @@ if (parsedDoc.errors.length > 0) {
console.log('Parsing failed:', parsedDoc.errors);
} else {
console.log(parsedDoc.api.element); // e.g., 'openApi3_1'
console.log(toValue(parsedDoc.meta.get('retrievalURI'))); // URI where it was fetched from
}
```

Expand Down Expand Up @@ -450,7 +454,7 @@ Parser-specific options take precedence over global options. See [arazzo-json-1]
- `true` - parse all source descriptions
- `string[]` - parse only source descriptions with matching names (e.g., `['petStore', 'paymentApi']`)

Each parsed source description is added with a `'source-description'` class and metadata (`name`, `type`).
Each parsed source description is added with a `'source-description'` class and metadata (`name`, `type`, `retrievalURI`).
Only OpenAPI 2.0, OpenAPI 3.0.x, OpenAPI 3.1.x, and Arazzo 1.x documents are accepted as source descriptions.
- **sourceDescriptionsMaxDepth** - Maximum recursion depth for parsing nested Arazzo source descriptions.
Defaults to `+Infinity`. Circular references are automatically detected and skipped.
Expand Down Expand Up @@ -1756,7 +1760,7 @@ Strategy-specific options take precedence over global options.
- `true` - dereference all source descriptions
- `string[]` - dereference only source descriptions with matching names (e.g., `['petStore', 'paymentApi']`)

Each dereferenced source description is added with a `'source-description'` class and metadata (`name`, `type`).
Each dereferenced source description is added with a `'source-description'` class and metadata (`name`, `type`, `retrievalURI`).
Only OpenAPI 2.0, OpenAPI 3.0.x, OpenAPI 3.1.x, and Arazzo 1.x documents are accepted as source descriptions.
- **sourceDescriptionsMaxDepth** - Maximum recursion depth for dereferencing nested Arazzo source descriptions.
Defaults to `+Infinity`. Circular references are automatically detected and skipped.
Expand Down Expand Up @@ -1810,6 +1814,7 @@ regardless of success or failure:
- **On failure**: The parseResult contains error/warning annotations explaining what went wrong

```js
import { toValue } from '@speclynx/apidom-core';
import { dereference } from '@speclynx/apidom-reference';

const parseResult = await dereference('/path/to/arazzo.json', {
Expand All @@ -1826,6 +1831,7 @@ if (dereferencedDoc.errors.length > 0) {
console.log('Dereferencing failed:', dereferencedDoc.errors);
} else {
console.log(dereferencedDoc.api.element); // e.g., 'openApi3_1'
console.log(toValue(dereferencedDoc.meta.get('retrievalURI'))); // URI where it was fetched from
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ async function dereferenceSourceDescription(

// normalize URI for consistent cycle detection and refSet cache key matching
const retrievalURI = url.sanitize(url.stripHash(url.resolve(ctx.baseURI, sourceDescriptionURI)));
parseResult.setMetaProperty('retrievalURI', retrievalURI);

// skip if already visited (cycle detection)
if (ctx.visitedUrls.has(retrievalURI)) {
Expand Down Expand Up @@ -199,7 +200,7 @@ async function dereferenceSourceDescription(
* in `dereference.strategyOpts` to filter which source descriptions to process.
* @param strategyName - Strategy name for options lookup (defaults to 'arazzo-1')
* @returns Array of ParseResultElements. Returns one ParseResultElement per source description
* (each with class 'source-description' and name/type metadata).
* (each with class 'source-description' and metadata: name, type, retrievalURI).
* May return early with a single-element array containing a warning annotation when:
* - The API is not an Arazzo specification
* - The sourceDescriptions field is missing or not an array
Expand All @@ -219,6 +220,7 @@ async function dereferenceSourceDescription(
* // Access dereferenced document from source description element
* const sourceDesc = parseResult.api.sourceDescriptions.get(0);
* const dereferencedDoc = sourceDesc.meta.get('parseResult');
* const uri = toValue(dereferencedDoc.meta.get('retrievalURI'));
* ```
*
* @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ async function parseSourceDescription(

// normalize URI for consistent cycle detection and cache key matching
const retrievalURI = url.sanitize(url.stripHash(url.resolve(ctx.baseURI, sourceDescriptionURI)));
parseResult.setMetaProperty('retrievalURI', retrievalURI);

// skip if already visited (cycle detection)
if (ctx.visitedUrls.has(retrievalURI)) {
Expand Down Expand Up @@ -166,7 +167,7 @@ async function parseSourceDescription(
* in `parse.parserOpts` to filter which source descriptions to process.
* @param parserName - Parser name for options lookup (defaults to 'arazzo-json-1')
* @returns Array of ParseResultElements. Returns one ParseResultElement per source description
* (each with class 'source-description' and name/type metadata).
* (each with class 'source-description' and metadata: name, type, retrievalURI).
* May return early with a single-element array containing a warning annotation when:
* - The API is not an Arazzo specification
* - The sourceDescriptions field is missing or not an array
Expand All @@ -189,6 +190,7 @@ async function parseSourceDescription(
* // Access parsed document from source description element
* const sourceDesc = parseResult.api.sourceDescriptions.get(0);
* const parsedDoc = sourceDesc.meta.get('parseResult');
* const uri = toValue(parsedDoc.meta.get('retrievalURI'));
* ```
*
* @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,27 @@ describe('dereference', function () {
assert.strictEqual(sdResult.meta.get('name')!.toValue(), 'petStore');
assert.strictEqual(sdResult.meta.get('type')!.toValue(), 'openapi');
});

specify(
'should set retrievalURI metadata on source description result',
async function () {
const uri = path.join(rootFixturePath, 'root.json');
const dereferenceResult = await dereference(uri, {
parse: { mediaType: mediaTypes.latest('json') },
dereference: {
strategyOpts: {
'arazzo-1': { sourceDescriptions: true },
},
},
});

const sdResult = dereferenceResult.get(1)!;
const retrievalURI = sdResult.meta.get('retrievalURI')?.toValue();

assert.isString(retrievalURI);
assert.include(retrievalURI, 'openapi.json');
},
);
});

context('given sourceDescriptions disabled', function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,26 @@ describe('parsers', function () {
assert.strictEqual(sdParseResult.meta.get('name')!.toValue(), 'petStore');
assert.strictEqual(sdParseResult.meta.get('type')!.toValue(), 'openapi');
});

specify(
'should set retrievalURI metadata on source description result',
async function () {
const uri = path.join(__dirname, 'fixtures', 'source-descriptions', 'root.json');
const parseResult = await parse(uri, {
parse: {
parserOpts: {
'arazzo-json-1': { sourceDescriptions: true },
},
},
});

const sdParseResult = parseResult.get(1)!;
const retrievalURI = sdParseResult.meta.get('retrievalURI')?.toValue();

assert.isString(retrievalURI);
assert.include(retrievalURI, 'openapi.json');
},
);
});

context('given sourceDescriptions disabled', function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,20 @@ describe('parsers', function () {
assert.isTrue(isParseResultElement(attachedParseResult));
assert.strictEqual(attachedParseResult.api?.element, 'openApi3_1');
});

specify('should set retrievalURI metadata on source description result', async function () {
const uri = path.join(__dirname, 'fixtures', 'source-descriptions', 'root.json');
const data = fs.readFileSync(uri).toString();
const parseResult = await parse(data);

const sourceDescriptions = await parseSourceDescriptions(parseResult, uri, options);

const sdParseResult = sourceDescriptions[0]!;
const retrievalURI = sdParseResult.meta.get('retrievalURI')?.toValue();

assert.isString(retrievalURI);
assert.include(retrievalURI, 'openapi.json');
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,26 @@ describe('parsers', function () {
assert.strictEqual(sdParseResult.meta.get('name')!.toValue(), 'petStore');
assert.strictEqual(sdParseResult.meta.get('type')!.toValue(), 'openapi');
});

specify(
'should set retrievalURI metadata on source description result',
async function () {
const uri = path.join(__dirname, 'fixtures', 'source-descriptions', 'root.yaml');
const parseResult = await parse(uri, {
parse: {
parserOpts: {
'arazzo-yaml-1': { sourceDescriptions: true },
},
},
});

const sdParseResult = parseResult.get(1)!;
const retrievalURI = sdParseResult.meta.get('retrievalURI')?.toValue();

assert.isString(retrievalURI);
assert.include(retrievalURI, 'openapi.yaml');
},
);
});

context('given sourceDescriptions disabled', function () {
Expand Down
Loading