From 12e319706875f2b6ae6d6882a84bd360315083b5 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Thu, 29 Apr 2021 16:13:16 +0200 Subject: [PATCH] feat(reference): add additional metadata during dereference Metadata is taken from original referencing element and translated as metadata to referenced element. Closes #384 --- .../strategies/asyncapi-2-0/visitor.ts | 6 ++++ .../strategies/openapi-3-1/visitor.ts | 34 +++++++++++++------ .../asyncapi-2-0/reference-object/index.ts | 16 +++++++++ .../openapi-3-1/reference-object/index.ts | 20 +++++++++++ .../openapi-3-1/schema-object/index.ts | 19 +++++++++++ 5 files changed, 84 insertions(+), 11 deletions(-) diff --git a/apidom/packages/apidom-reference/src/dereference/strategies/asyncapi-2-0/visitor.ts b/apidom/packages/apidom-reference/src/dereference/strategies/asyncapi-2-0/visitor.ts index c95bf59705..bdba7b6b5f 100644 --- a/apidom/packages/apidom-reference/src/dereference/strategies/asyncapi-2-0/visitor.ts +++ b/apidom/packages/apidom-reference/src/dereference/strategies/asyncapi-2-0/visitor.ts @@ -119,6 +119,12 @@ const AsyncApi2_0DereferenceVisitor = stampit({ }); fragment = await visitAsync(fragment, visitor, { keyMap, nodeTypeGetter: getNodeType }); + // annotate fragment with info about original Reference element + fragment = fragment.clone(); + fragment.setMetaProperty('ref-fields', { + $ref: referenceElement.$ref.toValue(), + }); + this.indirections.pop(); // transclude the element for a fragment diff --git a/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts b/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts index cd1bcf6b23..71a8aa4870 100644 --- a/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts +++ b/apidom/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts @@ -160,20 +160,27 @@ const OpenApi3_1DereferenceVisitor = stampit({ }); fragment = await visitAsync(fragment, visitor, { keyMap, nodeTypeGetter: getNodeType }); + fragment = fragment.clone(); + + // annotate fragment with info about original Reference element + fragment.setMetaProperty('ref-fields', { + $ref: referenceElement.$ref.toValue(), + // @ts-ignore + description: referenceElement.description?.toValue(), + // @ts-ignore + summary: referenceElement.summary?.toValue(), + }); + // override description and summary (outer has higher priority then inner) const hasDescription = pathSatisfies(isNotUndefined, ['description'], referenceElement); const hasSummary = pathSatisfies(isNotUndefined, ['summary'], referenceElement); - if (hasDescription || hasSummary) { - fragment = fragment.clone(); - - if (hasDescription && hasIn('description', fragment)) { - // @ts-ignore - fragment.description = referenceElement.description; - } - if (hasSummary && hasIn('summary', fragment)) { - // @ts-ignore - fragment.summary = referenceElement.summary; - } + if (hasDescription && hasIn('description', fragment)) { + // @ts-ignore + fragment.description = referenceElement.description; + } + if (hasSummary && hasIn('summary', fragment)) { + // @ts-ignore + fragment.summary = referenceElement.summary; } this.indirections.pop(); @@ -281,6 +288,11 @@ const OpenApi3_1DereferenceVisitor = stampit({ }); mergedResult.remove('$ref'); + // annotate referencing element with info about original referenced element + mergedResult.setMetaProperty('ref-fields', { + $ref: referencingElement.$ref?.toValue(), + }); + // transclude referencing element with merged referenced element return mergedResult; }, diff --git a/apidom/packages/apidom-reference/test/dereference/strategies/asyncapi-2-0/reference-object/index.ts b/apidom/packages/apidom-reference/test/dereference/strategies/asyncapi-2-0/reference-object/index.ts index cac66f26ef..5013a833e4 100644 --- a/apidom/packages/apidom-reference/test/dereference/strategies/asyncapi-2-0/reference-object/index.ts +++ b/apidom/packages/apidom-reference/test/dereference/strategies/asyncapi-2-0/reference-object/index.ts @@ -40,6 +40,22 @@ describe('dereference', function () { assert.isTrue(isParameterElement(fragment)); }); + + specify( + 'should annotate transcluded element with additional metadata', + async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const dereferenced = await dereference(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + const fragment = evaluate('/0/components/parameters/userId', dereferenced); + + assert.strictEqual( + fragment.meta.get('ref-fields').get('$ref').toValue(), + '#/components/parameters/indirection1', + ); + }, + ); }); context('given Reference Objects pointing internally only', function () { diff --git a/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/reference-object/index.ts b/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/reference-object/index.ts index 974b8362be..6a0b09e452 100644 --- a/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/reference-object/index.ts +++ b/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/reference-object/index.ts @@ -40,6 +40,26 @@ describe('dereference', function () { assert.isTrue(isParameterElement(fragment)); }); + + specify( + 'should annotate transcluded element with additional metadata', + async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const dereferenced = await dereference(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + const fragment = evaluate('/0/components/parameters/userId', dereferenced); + + assert.strictEqual( + fragment.meta.get('ref-fields').get('$ref').toValue(), + '#/components/parameters/indirection1', + ); + assert.strictEqual( + fragment.meta.get('ref-fields').get('description').toValue(), + 'override', + ); + }, + ); }); }); diff --git a/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts b/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts index 8b64e390b6..5d55d6f2b6 100644 --- a/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts +++ b/apidom/packages/apidom-reference/test/dereference/strategies/openapi-3-1/schema-object/index.ts @@ -41,6 +41,25 @@ describe('dereference', function () { assert.isTrue(isSchemaElement(fragment)); }); + + specify( + 'should annotate transcluded element with additional metadata', + async function () { + const rootFilePath = path.join(fixturePath, 'root.json'); + const dereferenced = await dereference(rootFilePath, { + parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' }, + }); + const fragment = evaluate( + '/0/components/schemas/User/properties/profile', + dereferenced, + ); + + assert.strictEqual( + fragment.meta.get('ref-fields').get('$ref').toValue(), + '#/components/schemas/UserProfile', + ); + }, + ); }); context('given Schema Objects pointing internally only', function () {