From ac5c0cbf5e700cfe1b0bfe8523626b199b4047b5 Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:06:24 +0200 Subject: [PATCH 1/8] fix: do not resolve $ref in examples.value --- .changeset/loud-mails-hang.md | 5 + .../example.json | 4 + .../openapi.yaml | 92 ++++++ .../redocly.yaml | 3 + .../snapshot.txt | 92 ++++++ docs/@v2/configuration/reference/resolve.md | 2 +- docs/@v2/configuration/resolve.yaml | 3 +- .../bundle-examples-ref-resolution.test.ts | 289 ++++++++++++++++++ .../src/__tests__/fixtures/example-data.json | 4 + packages/core/src/types/index.ts | 1 + packages/core/src/types/oas2.ts | 2 +- packages/core/src/types/oas3.ts | 2 +- packages/core/src/types/oas3_2.ts | 2 +- 13 files changed, 496 insertions(+), 5 deletions(-) create mode 100644 .changeset/loud-mails-hang.md create mode 100644 __tests__/bundle/bundle-example-value-with-ref/example.json create mode 100644 __tests__/bundle/bundle-example-value-with-ref/openapi.yaml create mode 100644 __tests__/bundle/bundle-example-value-with-ref/redocly.yaml create mode 100644 __tests__/bundle/bundle-example-value-with-ref/snapshot.txt create mode 100644 packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts create mode 100644 packages/core/src/__tests__/fixtures/example-data.json diff --git a/.changeset/loud-mails-hang.md b/.changeset/loud-mails-hang.md new file mode 100644 index 0000000000..d2f2f4db59 --- /dev/null +++ b/.changeset/loud-mails-hang.md @@ -0,0 +1,5 @@ +--- +"@redocly/openapi-core": patch +--- + +Do not resolve `$ref` inside `Examples.value` during bundling and linting diff --git a/__tests__/bundle/bundle-example-value-with-ref/example.json b/__tests__/bundle/bundle-example-value-with-ref/example.json new file mode 100644 index 0000000000..a14f51e285 --- /dev/null +++ b/__tests__/bundle/bundle-example-value-with-ref/example.json @@ -0,0 +1,4 @@ +{ + "id": 123, + "name": "Test User" +} diff --git a/__tests__/bundle/bundle-example-value-with-ref/openapi.yaml b/__tests__/bundle/bundle-example-value-with-ref/openapi.yaml new file mode 100644 index 0000000000..cda6733edf --- /dev/null +++ b/__tests__/bundle/bundle-example-value-with-ref/openapi.yaml @@ -0,0 +1,92 @@ +openapi: 3.2.0 +info: + title: Test API + version: 1.0.0 +paths: + /test: + get: + summary: Test endpoint + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + active: + type: boolean + example: + $ref: example.json + examples: + Test: + summary: Example with $ref in value (should NOT resolve) + value: + $ref: example.json + + TestNested: + summary: Example with nested $ref in value (should NOT resolve) + value: + user: + $ref: example.json + status: active + + TestExternal: + summary: Example with externalValue (should resolve) + externalValue: example.json + + TestDataValue: + summary: Example with $ref in dataValue (should NOT resolve) + dataValue: + $ref: example.json + + TestSerialized: + summary: Example with serializedValue + serializedValue: '{"id": 123, "name": "Test"}' + + TestEmpty: + summary: Example with empty value + value: {} + + TestPrimitive: + summary: Example with primitive values + value: + string: 'hello' + number: 42 + boolean: true + null: null + array: [1, 2, 3] + object: + nested: true + + TestMultipleRefs: + summary: Example with multiple $ref in value + value: + $ref: example.json + fallback: + $ref: example.json + static: 'constant' + +components: + examples: + UserExample: + summary: User example with $ref in value + value: + $ref: example.json + + UserExternal: + summary: User example with externalValue + externalValue: example.json + + UserDataValue: + summary: User example with dataValue + dataValue: + $ref: example.json + + UserSerialized: + summary: User example with serializedValue + serializedValue: '{"id": 456, "name": "User"}' diff --git a/__tests__/bundle/bundle-example-value-with-ref/redocly.yaml b/__tests__/bundle/bundle-example-value-with-ref/redocly.yaml new file mode 100644 index 0000000000..e428bb9945 --- /dev/null +++ b/__tests__/bundle/bundle-example-value-with-ref/redocly.yaml @@ -0,0 +1,3 @@ +apis: + main: + root: openapi.yaml diff --git a/__tests__/bundle/bundle-example-value-with-ref/snapshot.txt b/__tests__/bundle/bundle-example-value-with-ref/snapshot.txt new file mode 100644 index 0000000000..fcc997fb04 --- /dev/null +++ b/__tests__/bundle/bundle-example-value-with-ref/snapshot.txt @@ -0,0 +1,92 @@ +openapi: 3.2.0 +info: + title: Test API + version: 1.0.0 +paths: + /test: + get: + summary: Test endpoint + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + active: + type: boolean + example: + id: 123 + name: Test User + examples: + Test: + summary: Example with $ref in value (should NOT resolve) + value: + $ref: example.json + TestNested: + summary: Example with nested $ref in value (should NOT resolve) + value: + user: + $ref: example.json + status: active + TestExternal: + summary: Example with externalValue (should resolve) + value: + id: 123 + name: Test User + TestDataValue: + summary: Example with $ref in dataValue (should NOT resolve) + dataValue: + $ref: example.json + TestSerialized: + summary: Example with serializedValue + serializedValue: '{"id": 123, "name": "Test"}' + TestEmpty: + summary: Example with empty value + value: {} + TestPrimitive: + summary: Example with primitive values + value: + string: hello + number: 42 + boolean: true + 'null': null + array: + - 1 + - 2 + - 3 + object: + nested: true + TestMultipleRefs: + summary: Example with multiple $ref in value + value: + $ref: example.json + fallback: + $ref: example.json + static: constant +components: + examples: + UserExample: + summary: User example with $ref in value + value: + $ref: example.json + UserExternal: + summary: User example with externalValue + value: + id: 123 + name: Test User + UserDataValue: + summary: User example with dataValue + dataValue: + $ref: example.json + UserSerialized: + summary: User example with serializedValue + serializedValue: '{"id": 456, "name": "User"}' + +bundling openapi.yaml using configuration for api 'main'... +📦 Created a bundle for openapi.yaml at stdout ms. diff --git a/docs/@v2/configuration/reference/resolve.md b/docs/@v2/configuration/reference/resolve.md index ca8971a057..e119bcc344 100644 --- a/docs/@v2/configuration/reference/resolve.md +++ b/docs/@v2/configuration/reference/resolve.md @@ -21,7 +21,7 @@ One HTTP header is supported for each URL resolved. - doNotResolveExamples - boolean -- When running `lint`, set this option to `true` to avoid resolving `$ref` fields in examples. Resolving `$ref`s in other parts of the API is unaffected. +- Set this option to `true` to prevent resolving `$ref` fields in `Example`. This affects both `lint` and `bundle` commands. Resolving `$ref`s in other parts of the API description is unaffected. --- diff --git a/docs/@v2/configuration/resolve.yaml b/docs/@v2/configuration/resolve.yaml index c0d41aeb57..4f81728a99 100644 --- a/docs/@v2/configuration/resolve.yaml +++ b/docs/@v2/configuration/resolve.yaml @@ -12,7 +12,8 @@ properties: doNotResolveExamples: type: boolean description: >- - You can stop `lint` from resolving `$refs` in examples by setting this configuration option to `true`. + Set this option to `true` to prevent resolving `$ref` fields in `Example`. + This affects both `lint` and `bundle` commands. This does not affect `$ref` resolution in other parts of the API description. default: false http: diff --git a/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts b/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts new file mode 100644 index 0000000000..a30eec6fbe --- /dev/null +++ b/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts @@ -0,0 +1,289 @@ +import outdent from 'outdent'; +import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { bundleDocument } from '../bundle/bundle-document.js'; +import { parseYamlToDocument, yamlSerializer } from '../../__tests__/utils.js'; +import { createConfig } from '../config/index.js'; +import { BaseResolver } from '../resolve.js'; +import { AsyncApi3Types, Oas3Types } from '../index.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +describe('Bundle Examples $ref Resolution', () => { + expect.addSnapshotSerializer(yamlSerializer); + + describe('OpenAPI 3.0/3.1 Examples', () => { + it('should resolve $ref in Example field', async () => { + const testDocument = parseYamlToDocument( + outdent` + openapi: 3.0.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + example: + $ref: ${path.join(__dirname, 'fixtures/example-data.json')} + `, + '' + ); + + const { bundle: result, problems } = await bundleDocument({ + document: testDocument, + externalRefResolver: new BaseResolver(), + config: await createConfig({}), + types: Oas3Types, + }); + + console.log(problems); + + expect(problems).toHaveLength(0); + expect(result.parsed).toMatchInlineSnapshot(` + openapi: 3.0.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + example: + id: 123 + name: Test User + components: {} + `); + }); + + it('should NOT resolve $ref in Example.value field', async () => { + const testDocument = parseYamlToDocument( + outdent` + openapi: 3.1.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + examples: + test-example: + value: + $ref: ./example-data.json + `, + '' + ); + + const { bundle: result, problems } = await bundleDocument({ + document: testDocument, + externalRefResolver: new BaseResolver(), + config: await createConfig({}), + types: Oas3Types, + }); + + expect(problems).toHaveLength(0); + expect(result.parsed).toMatchInlineSnapshot(` + openapi: 3.1.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + examples: + test-example: + value: + $ref: ./example-data.json + components: {} + `); + }); + }); + + describe('OpenAPI 3.2 Examples', () => { + it('should NOT resolve $ref in Example.dataValue field', async () => { + const testDocument = parseYamlToDocument( + outdent` + openapi: 3.2.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + examples: + test-example: + dataValue: + $ref: ./example-data.json + `, + '' + ); + + const { bundle: result, problems } = await bundleDocument({ + document: testDocument, + externalRefResolver: new BaseResolver(), + config: await createConfig({}), + types: Oas3Types, + }); + + expect(problems).toHaveLength(0); + expect(result.parsed).toMatchInlineSnapshot(` + openapi: 3.2.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + examples: + test-example: + dataValue: + $ref: ./example-data.json + components: {} + `); + }); + }); + + describe('AsyncAPI 3.0 Examples', () => { + it('should NOT resolve $ref in Example.value field', async () => { + const testDocument = parseYamlToDocument( + outdent` + asyncapi: 3.0.0 + info: + title: Test AsyncAPI + version: 1.0.0 + operations: + sendUserSignedup: + action: send + messages: + - payload: + type: object + examples: + test-example: + value: + $ref: ./example-data.json + `, + '' + ); + + const { bundle: result, problems } = await bundleDocument({ + document: testDocument, + externalRefResolver: new BaseResolver(), + config: await createConfig({}), + types: AsyncApi3Types, + }); + + expect(problems).toHaveLength(0); + expect(result.parsed).toMatchInlineSnapshot(` + asyncapi: 3.0.0 + info: + title: Test AsyncAPI + version: 1.0.0 + operations: + sendUserSignedup: + action: send + messages: + - payload: + type: object + examples: + test-example: + value: + $ref: ./example-data.json + components: {} + `); + }); + }); + + describe('Edge cases and configuration', () => { + it('should work with doNotResolveExamples: true config', async () => { + const testDocument = parseYamlToDocument( + outdent` + openapi: 3.1.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + examples: + test-example: + value: + $ref: ./example-data.json + `, + '' + ); + + const config = await createConfig({ + resolve: { + doNotResolveExamples: true, + }, + }); + + const { bundle: result, problems } = await bundleDocument({ + document: testDocument, + externalRefResolver: new BaseResolver(), + config, + types: Oas3Types, + }); + + expect(problems).toHaveLength(0); + expect(result.parsed).toMatchInlineSnapshot(` + openapi: 3.1.0 + info: + title: Test API + version: 1.0.0 + paths: + /test: + get: + responses: + '200': + content: + application/json: + examples: + test-example: + value: + $ref: ./example-data.json + components: {} + `); + }); + }); +}); diff --git a/packages/core/src/__tests__/fixtures/example-data.json b/packages/core/src/__tests__/fixtures/example-data.json new file mode 100644 index 0000000000..a14f51e285 --- /dev/null +++ b/packages/core/src/__tests__/fixtures/example-data.json @@ -0,0 +1,4 @@ +{ + "id": 123, + "name": "Test User" +} diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index b80dd12dc1..3b9d025baa 100755 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -4,6 +4,7 @@ export type ScalarSchema = { items?: ScalarSchema; enum?: string[]; isExample?: boolean; + resolvable?: boolean; directResolveAs?: string; minimum?: number; }; diff --git a/packages/core/src/types/oas2.ts b/packages/core/src/types/oas2.ts index d39e88b285..1b05e3efd3 100644 --- a/packages/core/src/types/oas2.ts +++ b/packages/core/src/types/oas2.ts @@ -429,7 +429,7 @@ const SecurityRequirement: NodeType = { const Example: NodeType = { properties: { - value: { isExample: true }, + value: { isExample: true, resolvable: false }, summary: { type: 'string' }, description: { type: 'string' }, externalValue: { type: 'string' }, diff --git a/packages/core/src/types/oas3.ts b/packages/core/src/types/oas3.ts index 5d9cb8b702..1c6832d9a8 100755 --- a/packages/core/src/types/oas3.ts +++ b/packages/core/src/types/oas3.ts @@ -233,7 +233,7 @@ const MediaType: NodeType = { const Example: NodeType = { properties: { - value: { isExample: true }, + value: { isExample: true, resolvable: false }, summary: { type: 'string' }, description: { type: 'string' }, externalValue: { type: 'string' }, diff --git a/packages/core/src/types/oas3_2.ts b/packages/core/src/types/oas3_2.ts index 9470b06533..446fad22fb 100755 --- a/packages/core/src/types/oas3_2.ts +++ b/packages/core/src/types/oas3_2.ts @@ -194,7 +194,7 @@ const Example: NodeType = { ...Oas3_1Types.Example, properties: { ...Oas3_1Types.Example.properties, - dataValue: { isExample: true }, + dataValue: { isExample: true, resolvable: false }, serializedValue: { type: 'string' }, }, }; From 3ac288193f1e340a7207ed16046ee58f95b728ef Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:10:44 +0200 Subject: [PATCH 2/8] chore: remove console.log --- .../core/src/__tests__/bundle-examples-ref-resolution.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts b/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts index a30eec6fbe..0ba2f6291f 100644 --- a/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts +++ b/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts @@ -47,8 +47,6 @@ describe('Bundle Examples $ref Resolution', () => { types: Oas3Types, }); - console.log(problems); - expect(problems).toHaveLength(0); expect(result.parsed).toMatchInlineSnapshot(` openapi: 3.0.0 From 21a19af4cd3fb2bf2c37f6fe43c43931ef91075e Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:57:48 +0200 Subject: [PATCH 3/8] chore: update changeset --- .changeset/loud-mails-hang.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/loud-mails-hang.md b/.changeset/loud-mails-hang.md index d2f2f4db59..14c60419c1 100644 --- a/.changeset/loud-mails-hang.md +++ b/.changeset/loud-mails-hang.md @@ -2,4 +2,4 @@ "@redocly/openapi-core": patch --- -Do not resolve `$ref` inside `Examples.value` during bundling and linting +Fixed an issue where the content of `$ref`s inside `Examples.value` was erroneously resolved during bundling and linting. From d50276d39a978d0da59fe2a4855903b17494b2ee Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:39:08 +0200 Subject: [PATCH 4/8] fix: oas example types and tests --- .../openapi.yaml | 92 ------------------- .../redocly.yaml | 3 - .../snapshot.txt | 92 ------------------- packages/core/src/types/oas2.ts | 7 +- packages/core/src/types/oas3_1.ts | 11 +++ packages/core/src/types/oas3_2.ts | 8 +- .../example.json | 0 .../openapi.yaml | 32 +++++++ .../redocly.yaml | 6 ++ .../snapshot.txt | 35 +++++++ .../snapshot.txt | 2 +- .../snapshot.txt | 2 +- 12 files changed, 97 insertions(+), 193 deletions(-) delete mode 100644 __tests__/bundle/bundle-example-value-with-ref/openapi.yaml delete mode 100644 __tests__/bundle/bundle-example-value-with-ref/redocly.yaml delete mode 100644 __tests__/bundle/bundle-example-value-with-ref/snapshot.txt rename {__tests__ => tests/e2e}/bundle/bundle-example-value-with-ref/example.json (100%) create mode 100644 tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml create mode 100644 tests/e2e/bundle/bundle-example-value-with-ref/redocly.yaml create mode 100644 tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt diff --git a/__tests__/bundle/bundle-example-value-with-ref/openapi.yaml b/__tests__/bundle/bundle-example-value-with-ref/openapi.yaml deleted file mode 100644 index cda6733edf..0000000000 --- a/__tests__/bundle/bundle-example-value-with-ref/openapi.yaml +++ /dev/null @@ -1,92 +0,0 @@ -openapi: 3.2.0 -info: - title: Test API - version: 1.0.0 -paths: - /test: - get: - summary: Test endpoint - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - id: - type: integer - name: - type: string - active: - type: boolean - example: - $ref: example.json - examples: - Test: - summary: Example with $ref in value (should NOT resolve) - value: - $ref: example.json - - TestNested: - summary: Example with nested $ref in value (should NOT resolve) - value: - user: - $ref: example.json - status: active - - TestExternal: - summary: Example with externalValue (should resolve) - externalValue: example.json - - TestDataValue: - summary: Example with $ref in dataValue (should NOT resolve) - dataValue: - $ref: example.json - - TestSerialized: - summary: Example with serializedValue - serializedValue: '{"id": 123, "name": "Test"}' - - TestEmpty: - summary: Example with empty value - value: {} - - TestPrimitive: - summary: Example with primitive values - value: - string: 'hello' - number: 42 - boolean: true - null: null - array: [1, 2, 3] - object: - nested: true - - TestMultipleRefs: - summary: Example with multiple $ref in value - value: - $ref: example.json - fallback: - $ref: example.json - static: 'constant' - -components: - examples: - UserExample: - summary: User example with $ref in value - value: - $ref: example.json - - UserExternal: - summary: User example with externalValue - externalValue: example.json - - UserDataValue: - summary: User example with dataValue - dataValue: - $ref: example.json - - UserSerialized: - summary: User example with serializedValue - serializedValue: '{"id": 456, "name": "User"}' diff --git a/__tests__/bundle/bundle-example-value-with-ref/redocly.yaml b/__tests__/bundle/bundle-example-value-with-ref/redocly.yaml deleted file mode 100644 index e428bb9945..0000000000 --- a/__tests__/bundle/bundle-example-value-with-ref/redocly.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apis: - main: - root: openapi.yaml diff --git a/__tests__/bundle/bundle-example-value-with-ref/snapshot.txt b/__tests__/bundle/bundle-example-value-with-ref/snapshot.txt deleted file mode 100644 index fcc997fb04..0000000000 --- a/__tests__/bundle/bundle-example-value-with-ref/snapshot.txt +++ /dev/null @@ -1,92 +0,0 @@ -openapi: 3.2.0 -info: - title: Test API - version: 1.0.0 -paths: - /test: - get: - summary: Test endpoint - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - id: - type: integer - name: - type: string - active: - type: boolean - example: - id: 123 - name: Test User - examples: - Test: - summary: Example with $ref in value (should NOT resolve) - value: - $ref: example.json - TestNested: - summary: Example with nested $ref in value (should NOT resolve) - value: - user: - $ref: example.json - status: active - TestExternal: - summary: Example with externalValue (should resolve) - value: - id: 123 - name: Test User - TestDataValue: - summary: Example with $ref in dataValue (should NOT resolve) - dataValue: - $ref: example.json - TestSerialized: - summary: Example with serializedValue - serializedValue: '{"id": 123, "name": "Test"}' - TestEmpty: - summary: Example with empty value - value: {} - TestPrimitive: - summary: Example with primitive values - value: - string: hello - number: 42 - boolean: true - 'null': null - array: - - 1 - - 2 - - 3 - object: - nested: true - TestMultipleRefs: - summary: Example with multiple $ref in value - value: - $ref: example.json - fallback: - $ref: example.json - static: constant -components: - examples: - UserExample: - summary: User example with $ref in value - value: - $ref: example.json - UserExternal: - summary: User example with externalValue - value: - id: 123 - name: Test User - UserDataValue: - summary: User example with dataValue - dataValue: - $ref: example.json - UserSerialized: - summary: User example with serializedValue - serializedValue: '{"id": 456, "name": "User"}' - -bundling openapi.yaml using configuration for api 'main'... -📦 Created a bundle for openapi.yaml at stdout ms. diff --git a/packages/core/src/types/oas2.ts b/packages/core/src/types/oas2.ts index 1b05e3efd3..3df20512c2 100644 --- a/packages/core/src/types/oas2.ts +++ b/packages/core/src/types/oas2.ts @@ -163,7 +163,7 @@ const Parameter: NodeType = { uniqueItems: { type: 'boolean' }, enum: { type: 'array' }, multipleOf: { type: 'number' }, - 'x-example': {}, // any + 'x-example': 'XExample', 'x-examples': 'ExamplesMap', }, required(value) { @@ -427,7 +427,9 @@ const SecurityRequirement: NodeType = { additionalProperties: { type: 'array', items: { type: 'string' } }, }; -const Example: NodeType = { +const Example = { isExample: true, properties: {} }; + +const XExample: NodeType = { properties: { value: { isExample: true, resolvable: false }, summary: { type: 'string' }, @@ -475,4 +477,5 @@ export const Oas2Types = { XCodeSampleList: listOf('XCodeSample'), XServerList: listOf('XServer'), XServer, + XExample, } as const; diff --git a/packages/core/src/types/oas3_1.ts b/packages/core/src/types/oas3_1.ts index 3b96235b71..79d5c43390 100755 --- a/packages/core/src/types/oas3_1.ts +++ b/packages/core/src/types/oas3_1.ts @@ -271,6 +271,16 @@ const DependentRequired: NodeType = { additionalProperties: { type: 'array', items: { type: 'string' } }, }; +const Example: NodeType = { + properties: { + value: { isExample: true, resolvable: false }, + summary: { type: 'string' }, + description: { type: 'string' }, + externalValue: { type: 'string' }, + }, + extensionsPrefix: 'x-', +}; + export const Oas3_1Types = { ...Oas3Types, Info, @@ -284,4 +294,5 @@ export const Oas3_1Types = { SecurityScheme, Operation, DependentRequired, + Example, } as const; diff --git a/packages/core/src/types/oas3_2.ts b/packages/core/src/types/oas3_2.ts index 446fad22fb..db4064c7e9 100755 --- a/packages/core/src/types/oas3_2.ts +++ b/packages/core/src/types/oas3_2.ts @@ -191,12 +191,15 @@ const Discriminator: NodeType = { }; const Example: NodeType = { - ...Oas3_1Types.Example, properties: { - ...Oas3_1Types.Example.properties, + value: { isExample: true, resolvable: false }, + summary: { type: 'string' }, + description: { type: 'string' }, + externalValue: { type: 'string' }, dataValue: { isExample: true, resolvable: false }, serializedValue: { type: 'string' }, }, + extensionsPrefix: 'x-', }; export const Oas3_2Types = { @@ -213,4 +216,5 @@ export const Oas3_2Types = { MediaType, Discriminator, Example, + ExamplesMap: mapOf('Example'), } as const; diff --git a/__tests__/bundle/bundle-example-value-with-ref/example.json b/tests/e2e/bundle/bundle-example-value-with-ref/example.json similarity index 100% rename from __tests__/bundle/bundle-example-value-with-ref/example.json rename to tests/e2e/bundle/bundle-example-value-with-ref/example.json diff --git a/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml b/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml new file mode 100644 index 0000000000..ffdc1569b9 --- /dev/null +++ b/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml @@ -0,0 +1,32 @@ +openapi: 3.2.0 +info: + title: Test API + version: 1.0.0 +paths: + /test: + get: + responses: + '200': + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + active: + type: boolean + example: + $ref: example.json + examples: + Test: + summary: Example with $ref in value (should NOT resolve) + value: + $ref: example.json + + TestDataValue: + summary: Example with $ref in dataValue (should NOT resolve) + dataValue: + $ref: example.json diff --git a/tests/e2e/bundle/bundle-example-value-with-ref/redocly.yaml b/tests/e2e/bundle/bundle-example-value-with-ref/redocly.yaml new file mode 100644 index 0000000000..9e587a9f8e --- /dev/null +++ b/tests/e2e/bundle/bundle-example-value-with-ref/redocly.yaml @@ -0,0 +1,6 @@ +apis: + main: + root: openapi.yaml + +resolve: + doNotResolveExamples: true diff --git a/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt b/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt new file mode 100644 index 0000000000..40fa41e0d8 --- /dev/null +++ b/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt @@ -0,0 +1,35 @@ +openapi: 3.2.0 +info: + title: Test API + version: 1.0.0 +paths: + /test: + get: + responses: + '200': + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + active: + type: boolean + example: + $ref: example.json + examples: + Test: + summary: Example with $ref in value (should NOT resolve) + value: + $ref: example.json + TestDataValue: + summary: Example with $ref in dataValue (should NOT resolve) + dataValue: + $ref: example.json +components: {} + +bundling openapi.yaml using configuration for api 'main'... +📦 Created a bundle for openapi.yaml at stdout ms. diff --git a/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt b/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt index 35ef60f437..170ce77241 100644 --- a/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt +++ b/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt @@ -1,6 +1,6 @@ [1] redocly.yaml:10:13 at #/rules/rule~1metadata-lifecycle/subject/type -`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "XMetaData", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". +`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "XExample", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "XMetaData", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". 8 | rule/metadata-lifecycle: 9 | subject: diff --git a/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt b/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt index c8cc0ca233..4de49c6047 100644 --- a/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt +++ b/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt @@ -1,6 +1,6 @@ [1] redocly.yaml:9:17 at #/rules/rule~1path-item-mutually-required/where/0/subject/type -`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". +`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "XExample", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". 7 | where: 8 | - subject: From ef63eafbd64686a714577a9cc91b2f5285c9df95 Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Thu, 6 Nov 2025 10:11:28 +0200 Subject: [PATCH 5/8] fix: update Example type definitions across OAS specs --- packages/core/src/types/oas2.ts | 9 +++------ packages/core/src/types/oas3.ts | 2 +- packages/core/src/types/oas3_1.ts | 11 ----------- packages/core/src/types/oas3_2.ts | 4 ++-- .../snapshot.txt | 2 +- .../snapshot.txt | 2 +- 6 files changed, 8 insertions(+), 22 deletions(-) diff --git a/packages/core/src/types/oas2.ts b/packages/core/src/types/oas2.ts index 3df20512c2..d39e88b285 100644 --- a/packages/core/src/types/oas2.ts +++ b/packages/core/src/types/oas2.ts @@ -163,7 +163,7 @@ const Parameter: NodeType = { uniqueItems: { type: 'boolean' }, enum: { type: 'array' }, multipleOf: { type: 'number' }, - 'x-example': 'XExample', + 'x-example': {}, // any 'x-examples': 'ExamplesMap', }, required(value) { @@ -427,11 +427,9 @@ const SecurityRequirement: NodeType = { additionalProperties: { type: 'array', items: { type: 'string' } }, }; -const Example = { isExample: true, properties: {} }; - -const XExample: NodeType = { +const Example: NodeType = { properties: { - value: { isExample: true, resolvable: false }, + value: { isExample: true }, summary: { type: 'string' }, description: { type: 'string' }, externalValue: { type: 'string' }, @@ -477,5 +475,4 @@ export const Oas2Types = { XCodeSampleList: listOf('XCodeSample'), XServerList: listOf('XServer'), XServer, - XExample, } as const; diff --git a/packages/core/src/types/oas3.ts b/packages/core/src/types/oas3.ts index 1c6832d9a8..38eb7cca73 100755 --- a/packages/core/src/types/oas3.ts +++ b/packages/core/src/types/oas3.ts @@ -233,7 +233,7 @@ const MediaType: NodeType = { const Example: NodeType = { properties: { - value: { isExample: true, resolvable: false }, + value: { resolvable: false }, summary: { type: 'string' }, description: { type: 'string' }, externalValue: { type: 'string' }, diff --git a/packages/core/src/types/oas3_1.ts b/packages/core/src/types/oas3_1.ts index 79d5c43390..3b96235b71 100755 --- a/packages/core/src/types/oas3_1.ts +++ b/packages/core/src/types/oas3_1.ts @@ -271,16 +271,6 @@ const DependentRequired: NodeType = { additionalProperties: { type: 'array', items: { type: 'string' } }, }; -const Example: NodeType = { - properties: { - value: { isExample: true, resolvable: false }, - summary: { type: 'string' }, - description: { type: 'string' }, - externalValue: { type: 'string' }, - }, - extensionsPrefix: 'x-', -}; - export const Oas3_1Types = { ...Oas3Types, Info, @@ -294,5 +284,4 @@ export const Oas3_1Types = { SecurityScheme, Operation, DependentRequired, - Example, } as const; diff --git a/packages/core/src/types/oas3_2.ts b/packages/core/src/types/oas3_2.ts index db4064c7e9..a9026b1121 100755 --- a/packages/core/src/types/oas3_2.ts +++ b/packages/core/src/types/oas3_2.ts @@ -192,11 +192,11 @@ const Discriminator: NodeType = { const Example: NodeType = { properties: { - value: { isExample: true, resolvable: false }, + value: { resolvable: false }, summary: { type: 'string' }, description: { type: 'string' }, externalValue: { type: 'string' }, - dataValue: { isExample: true, resolvable: false }, + dataValue: { resolvable: false }, serializedValue: { type: 'string' }, }, extensionsPrefix: 'x-', diff --git a/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt b/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt index 170ce77241..35ef60f437 100644 --- a/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt +++ b/tests/e2e/check-config/wrong-config-type-extensions-in-assertions/snapshot.txt @@ -1,6 +1,6 @@ [1] redocly.yaml:10:13 at #/rules/rule~1metadata-lifecycle/subject/type -`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "XExample", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "XMetaData", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". +`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "XMetaData", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". 8 | rule/metadata-lifecycle: 9 | subject: diff --git a/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt b/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt index 4de49c6047..c8cc0ca233 100644 --- a/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt +++ b/tests/e2e/lint-config/invalid-config-assertation-config-type/snapshot.txt @@ -1,6 +1,6 @@ [1] redocly.yaml:9:17 at #/rules/rule~1path-item-mutually-required/where/0/subject/type -`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "XExample", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". +`type` can be one of the following only: "any", "Root", "Tag", "TagList", "TagGroups", "TagGroup", "ExternalDocs", "Example", "ExamplesMap", "EnumDescriptions", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Logo", "Paths", "PathItem", "Parameter", "ParameterItems", "ParameterList", "Operation", "Examples", "Header", "Responses", "Response", "Schema", "Xml", "SchemaProperties", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedSecuritySchemes", "SecurityScheme", "XCodeSample", "XCodeSampleList", "XServerList", "XServer", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Encoding", "EncodingMap", "HeadersMap", "Link", "DiscriminatorMapping", "Discriminator", "Components", "LinksMap", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "XUsePkce", "WebhooksMap", "PatternProperties", "NamedPathItems", "DependentRequired", "DeviceAuthorization", "HttpServerBinding", "HttpChannelBinding", "HttpMessageBinding", "HttpOperationBinding", "WsServerBinding", "WsChannelBinding", "WsMessageBinding", "WsOperationBinding", "KafkaServerBinding", "KafkaTopicConfiguration", "KafkaChannelBinding", "KafkaMessageBinding", "KafkaOperationBinding", "AnypointmqServerBinding", "AnypointmqChannelBinding", "AnypointmqMessageBinding", "AnypointmqOperationBinding", "AmqpServerBinding", "AmqpChannelBinding", "AmqpMessageBinding", "AmqpOperationBinding", "Amqp1ServerBinding", "Amqp1ChannelBinding", "Amqp1MessageBinding", "Amqp1OperationBinding", "MqttServerBindingLastWill", "MqttServerBinding", "MqttChannelBinding", "MqttMessageBinding", "MqttOperationBinding", "Mqtt5ServerBinding", "Mqtt5ChannelBinding", "Mqtt5MessageBinding", "Mqtt5OperationBinding", "NatsServerBinding", "NatsChannelBinding", "NatsMessageBinding", "NatsOperationBinding", "JmsServerBinding", "JmsChannelBinding", "JmsMessageBinding", "JmsOperationBinding", "SolaceServerBinding", "SolaceChannelBinding", "SolaceMessageBinding", "SolaceDestination", "SolaceOperationBinding", "StompServerBinding", "StompChannelBinding", "StompMessageBinding", "StompOperationBinding", "RedisServerBinding", "RedisChannelBinding", "RedisMessageBinding", "RedisOperationBinding", "MercureServerBinding", "MercureChannelBinding", "MercureMessageBinding", "MercureOperationBinding", "ServerBindings", "ChannelBindings", "MessageBindings", "OperationBindings", "ServerMap", "ChannelMap", "Channel", "ParametersMap", "MessageExample", "NamedMessages", "NamedMessageTraits", "NamedOperationTraits", "NamedCorrelationIds", "SecuritySchemeFlows", "Message", "OperationTrait", "OperationTraitList", "MessageTrait", "MessageTraitList", "MessageExampleList", "CorrelationId", "Dependencies", "OperationReply", "OperationReplyAddress", "NamedTags", "NamedExternalDocs", "NamedChannels", "NamedOperations", "NamedOperationReplies", "NamedOperationRelyAddresses", "SecuritySchemeList", "MessageList", "SourceDescriptions", "OpenAPISourceDescription", "ArazzoSourceDescription", "Parameters", "ReusableObject", "Workflows", "Workflow", "Steps", "Step", "Replacement", "ExtendedOperation", "ExtendedSecurityList", "ExtendedSecurity", "Outputs", "CriterionObject", "XPathCriterion", "JSONPathCriterion", "SuccessActionObject", "OnSuccessActionList", "FailureActionObject", "OnFailureActionList", "NamedInputs", "NamedSuccessActions", "NamedFailureActions", "Actions", "Action", "SpecExtension". 7 | where: 8 | - subject: From d16bd721388ca4a3a367f75757e81c84f4b0c940 Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Thu, 6 Nov 2025 10:28:18 +0200 Subject: [PATCH 6/8] fix: update oas3.2 types --- packages/core/src/types/oas3_2.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/core/src/types/oas3_2.ts b/packages/core/src/types/oas3_2.ts index a9026b1121..1cca1eb584 100755 --- a/packages/core/src/types/oas3_2.ts +++ b/packages/core/src/types/oas3_2.ts @@ -191,15 +191,12 @@ const Discriminator: NodeType = { }; const Example: NodeType = { + ...Oas3_1Types.Example, properties: { - value: { resolvable: false }, - summary: { type: 'string' }, - description: { type: 'string' }, - externalValue: { type: 'string' }, + ...Oas3_1Types.Example.properties, dataValue: { resolvable: false }, serializedValue: { type: 'string' }, }, - extensionsPrefix: 'x-', }; export const Oas3_2Types = { @@ -216,5 +213,4 @@ export const Oas3_2Types = { MediaType, Discriminator, Example, - ExamplesMap: mapOf('Example'), } as const; From abc1cf763f16febd528d653bc8e4db0e9e1eed7a Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Thu, 6 Nov 2025 12:41:23 +0200 Subject: [PATCH 7/8] fix: improve docs, changeset and tests --- .changeset/loud-mails-hang.md | 3 +- docs/@v2/configuration/reference/resolve.md | 2 +- docs/@v2/configuration/resolve.yaml | 2 +- .../bundle-examples-ref-resolution.test.ts | 58 ------------------- .../struct/referenceableScalars.test.ts | 34 +++++++++++ 5 files changed, 38 insertions(+), 61 deletions(-) diff --git a/.changeset/loud-mails-hang.md b/.changeset/loud-mails-hang.md index 14c60419c1..7b71f89260 100644 --- a/.changeset/loud-mails-hang.md +++ b/.changeset/loud-mails-hang.md @@ -1,5 +1,6 @@ --- "@redocly/openapi-core": patch +"@redocly/cli": patch --- -Fixed an issue where the content of `$ref`s inside `Examples.value` was erroneously resolved during bundling and linting. +Fixed an issue where the content of `$ref`s inside example values was erroneously resolved during bundling and linting. diff --git a/docs/@v2/configuration/reference/resolve.md b/docs/@v2/configuration/reference/resolve.md index e119bcc344..619098e14f 100644 --- a/docs/@v2/configuration/reference/resolve.md +++ b/docs/@v2/configuration/reference/resolve.md @@ -21,7 +21,7 @@ One HTTP header is supported for each URL resolved. - doNotResolveExamples - boolean -- Set this option to `true` to prevent resolving `$ref` fields in `Example`. This affects both `lint` and `bundle` commands. Resolving `$ref`s in other parts of the API description is unaffected. +- Set this option to `true` to prevent resolving `$ref` fields in singular `example` properties. This affects both `lint` and `bundle` commands. Resolving `$ref`s in other parts of the API description is unaffected. --- diff --git a/docs/@v2/configuration/resolve.yaml b/docs/@v2/configuration/resolve.yaml index 4f81728a99..af61c4f60b 100644 --- a/docs/@v2/configuration/resolve.yaml +++ b/docs/@v2/configuration/resolve.yaml @@ -12,7 +12,7 @@ properties: doNotResolveExamples: type: boolean description: >- - Set this option to `true` to prevent resolving `$ref` fields in `Example`. + Set this option to `true` to prevent resolving `$ref` fields in singular `example` properties. This affects both `lint` and `bundle` commands. This does not affect `$ref` resolution in other parts of the API description. default: false diff --git a/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts b/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts index 0ba2f6291f..841b222612 100644 --- a/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts +++ b/packages/core/src/__tests__/bundle-examples-ref-resolution.test.ts @@ -226,62 +226,4 @@ describe('Bundle Examples $ref Resolution', () => { `); }); }); - - describe('Edge cases and configuration', () => { - it('should work with doNotResolveExamples: true config', async () => { - const testDocument = parseYamlToDocument( - outdent` - openapi: 3.1.0 - info: - title: Test API - version: 1.0.0 - paths: - /test: - get: - responses: - '200': - content: - application/json: - examples: - test-example: - value: - $ref: ./example-data.json - `, - '' - ); - - const config = await createConfig({ - resolve: { - doNotResolveExamples: true, - }, - }); - - const { bundle: result, problems } = await bundleDocument({ - document: testDocument, - externalRefResolver: new BaseResolver(), - config, - types: Oas3Types, - }); - - expect(problems).toHaveLength(0); - expect(result.parsed).toMatchInlineSnapshot(` - openapi: 3.1.0 - info: - title: Test API - version: 1.0.0 - paths: - /test: - get: - responses: - '200': - content: - application/json: - examples: - test-example: - value: - $ref: ./example-data.json - components: {} - `); - }); - }); }); diff --git a/packages/core/src/rules/oas3/__tests__/struct/referenceableScalars.test.ts b/packages/core/src/rules/oas3/__tests__/struct/referenceableScalars.test.ts index 8656d45d32..2f1cd82fff 100644 --- a/packages/core/src/rules/oas3/__tests__/struct/referenceableScalars.test.ts +++ b/packages/core/src/rules/oas3/__tests__/struct/referenceableScalars.test.ts @@ -69,4 +69,38 @@ describe('Referenceable scalars', () => { }); expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`); }); + + it('should not report example value with $ref', async () => { + const document = parseYamlToDocument( + outdent` + openapi: 3.2.0 + info: + title: Test + version: '1.0' + paths: + '/test': + get: + parameters: + - name: test + schema: + type: object + examples: + test: + value: + $ref: not $ref, example + `, + __dirname + '/foobar.yaml' + ); + + const results = await lintDocument({ + externalRefResolver: new BaseResolver(), + document, + config: await createConfig({ + rules: { + 'no-unresolved-refs': 'error', + }, + }), + }); + expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`); + }); }); From 2374fda4fcc79129d31e992e3b985bfbe0825706 Mon Sep 17 00:00:00 2001 From: Vadym Vasylyshyn <51933329+vadyvas@users.noreply.github.com> Date: Fri, 7 Nov 2025 19:31:31 +0200 Subject: [PATCH 8/8] chore: update e2e test --- .../bundle-example-value-with-ref/example.json | 4 ---- .../bundle-example-value-with-ref/openapi.yaml | 12 ++++-------- .../bundle-example-value-with-ref/snapshot.txt | 6 +----- 3 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 tests/e2e/bundle/bundle-example-value-with-ref/example.json diff --git a/tests/e2e/bundle/bundle-example-value-with-ref/example.json b/tests/e2e/bundle/bundle-example-value-with-ref/example.json deleted file mode 100644 index a14f51e285..0000000000 --- a/tests/e2e/bundle/bundle-example-value-with-ref/example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "id": 123, - "name": "Test User" -} diff --git a/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml b/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml index ffdc1569b9..348649a741 100644 --- a/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml +++ b/tests/e2e/bundle/bundle-example-value-with-ref/openapi.yaml @@ -12,21 +12,17 @@ paths: schema: type: object properties: - id: - type: integer - name: + $ref: type: string - active: - type: boolean example: - $ref: example.json + $ref: example.json # should NOT be resolved examples: Test: summary: Example with $ref in value (should NOT resolve) value: - $ref: example.json + $ref: example.json # should NOT be resolved TestDataValue: summary: Example with $ref in dataValue (should NOT resolve) dataValue: - $ref: example.json + $ref: example.json # should NOT be resolved diff --git a/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt b/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt index 40fa41e0d8..205cd72132 100644 --- a/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt +++ b/tests/e2e/bundle/bundle-example-value-with-ref/snapshot.txt @@ -12,12 +12,8 @@ paths: schema: type: object properties: - id: - type: integer - name: + $ref: type: string - active: - type: boolean example: $ref: example.json examples: