Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: bundle externalValue with relative reference in examples object #1747

Merged
merged 9 commits into from
Oct 3, 2024
Merged
6 changes: 6 additions & 0 deletions .changeset/little-pears-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@redocly/openapi-core": patch
"@redocly/cli": patch
---

Fixed an issue where the bundle command did not resolve links in `externalValue`.
4 changes: 4 additions & 0 deletions __tests__/bundle/bundle-external-value/external-value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"foo": "bar",
"key": "value"
}
8 changes: 8 additions & 0 deletions __tests__/bundle/bundle-external-value/redocly.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apis:
first:
root: ./test-success.yaml
second:
root: ./test-wrong-examples.yaml

extends:
- recommended
59 changes: 59 additions & 0 deletions __tests__/bundle/bundle-external-value/snapshot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`E2E bundle bundle-external-value 1`] = `
openapi: 3.1.0
info:
version: 1.0.0
title: Example.com
termsOfService: https://example.com/terms/
contact:
email: [email protected]
url: http://example.com/contact
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
description: OpenAPI description with external example
security: []
paths:
/:
post:
summary: Test request externalValue with relative reference in examples
requestBody:
content:
application/xml:
schema:
type: object
examples:
test-resolved:
summary: Example should resolved to value
value:
foo: bar
key: value
test-no-resolved:
summary: Example shouldn't be resolved to value
value:
type: object
externalValue: ./external-value.json
components: {}

bundling ./test-success.yaml...
📦 Created a bundle for ./test-success.yaml at stdout <test>ms.
bundling ./test-wrong-examples.yaml...
[1] test-wrong-examples.yaml:27:17 at #/paths/~1/post/requestBody/content/application~1xml/examples/test-wrong-ref

Can't resolve $ref: ENOENT: no such file or directory './__tests__/bundle/bundle-external-value/external-value-bad-path.json'

25 | examples:
26 | test-wrong-ref:
27 | summary: Example shouldn't resolved to value
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28 | externalValue: './external-value-bad-path.json'
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29 |

Error was generated by the bundler rule.


❌ Errors encountered while bundling ./test-wrong-examples.yaml: bundle not created (use --force to ignore errors).

`;
33 changes: 33 additions & 0 deletions __tests__/bundle/bundle-external-value/test-success.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
openapi: 3.1.0
security: []
info:
version: 1.0.0
title: Example.com
termsOfService: https://example.com/terms/
contact:
email: [email protected]
url: http://example.com/contact
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
description: OpenAPI description with external example
components: {}

paths:
/:
post:
summary: Test request externalValue with relative reference in examples
requestBody:
content:
application/xml:
schema:
type: object
examples:
test-resolved:
summary: Example should resolved to value
externalValue: './external-value.json'
test-no-resolved:
summary: Example shouldn't be resolved to value
value:
type: object
externalValue: './external-value.json'
28 changes: 28 additions & 0 deletions __tests__/bundle/bundle-external-value/test-wrong-examples.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
openapi: 3.1.0
security: []
info:
version: 1.0.0
title: Example.com
termsOfService: https://example.com/terms/
contact:
email: [email protected]
url: http://example.com/contact
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
description: OpenAPI description with external example
components: {}

paths:
/:
post:
summary: Test request externalValue with relative reference in examples
requestBody:
content:
application/xml:
schema:
type: object
examples:
test-wrong-ref:
summary: Example shouldn't resolved to value
externalValue: './external-value-bad-path.json'
19 changes: 19 additions & 0 deletions packages/core/src/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,25 @@ function makeBundleVisitor(
}
},
},
Example: {
leave(node: any, ctx: UserContext) {
if (node.externalValue && node.value === undefined) {
const resolved = ctx.resolve({ $ref: node.externalValue });

if (!resolved.location || resolved.node === undefined) {
reportUnresolvedRef(resolved, ctx.report, ctx.location);
return;
}

if (keepUrlRefs && isAbsoluteUrl(node.externalValue)) {
return;
}

node.value = ctx.resolve({ $ref: node.externalValue }).node;
delete node.externalValue;
}
},
},
Root: {
enter(root: any, ctx: any) {
rootLocation = ctx.location;
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,28 @@ export async function resolveDocument(opts: {
});
resolvePromises.push(promise);
}

// handle externalValue with relative reference in examples object
AlexVarchuk marked this conversation as resolved.
Show resolved Hide resolved
if (node.externalValue) {
const promise = followRef(
rootNodeDocument,
{ $ref: node.externalValue },
{
prev: null,
node,
}
).then((resolvedRef) => {
if (resolvedRef.resolved) {
resolveRefsInParallel(
resolvedRef.node,
resolvedRef.document,
resolvedRef.nodePointer!,
type
);
}
});
resolvePromises.push(promise);
}
}

async function followRef(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
a: foo
b: 100
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ describe('no-invalid-media-type-examples', () => {
type: number
examples:
first:
externalValue: "https://example.com/example.json"
externalValue: ./fixtures/external-value.yaml
`,
'foobar.yaml'
);
Expand Down
Loading