From 13c5d19fe205bff0730037303e08769d43e02024 Mon Sep 17 00:00:00 2001 From: Frank Kilcommins Date: Thu, 23 Nov 2023 15:55:39 +0000 Subject: [PATCH 1/3] feat(ns-workflows-1): Add Reference Object --- packages/apidom-ns-workflows-1/README.md | 2 +- .../src/elements/Reference.ts | 27 +++++++++ packages/apidom-ns-workflows-1/src/index.ts | 2 + .../apidom-ns-workflows-1/src/namespace.ts | 2 + .../apidom-ns-workflows-1/src/predicates.ts | 11 ++++ .../src/refractor/registration.ts | 9 +++ .../src/refractor/specification.ts | 9 +++ .../workflows-1/reference/$RefVisitor.ts | 17 ++++++ .../visitors/workflows-1/reference/index.ts | 32 +++++++++++ .../src/traversal/visitor.ts | 1 + .../apidom-ns-workflows-1/test/predicates.ts | 55 +++++++++++++++++++ .../Reference/__snapshots__/index.ts.snap | 11 ++++ .../refractor/elements/Reference/index.ts | 19 +++++++ 13 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 packages/apidom-ns-workflows-1/src/elements/Reference.ts create mode 100644 packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/$RefVisitor.ts create mode 100644 packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/index.ts create mode 100644 packages/apidom-ns-workflows-1/test/refractor/elements/Reference/__snapshots__/index.ts.snap create mode 100644 packages/apidom-ns-workflows-1/test/refractor/elements/Reference/index.ts diff --git a/packages/apidom-ns-workflows-1/README.md b/packages/apidom-ns-workflows-1/README.md index 8d985183cf..a5539fe622 100644 --- a/packages/apidom-ns-workflows-1/README.md +++ b/packages/apidom-ns-workflows-1/README.md @@ -195,5 +195,5 @@ Only fully implemented specification objects should be checked here. - [x] [Failure Action Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#failure-action-object) - [ ] [Component Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#component-object) - [x] [Criterion Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#criterion-object) -- [ ] [Reference Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#reference-object) +- [x] [Reference Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#reference-object) - [x] [Specification extensions](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#specification-extensions) diff --git a/packages/apidom-ns-workflows-1/src/elements/Reference.ts b/packages/apidom-ns-workflows-1/src/elements/Reference.ts new file mode 100644 index 0000000000..1d7e0b7d7b --- /dev/null +++ b/packages/apidom-ns-workflows-1/src/elements/Reference.ts @@ -0,0 +1,27 @@ +import { StringElement, ObjectElement, Attributes, Meta } from '@swagger-api/apidom-core'; + +class Reference extends ObjectElement { + constructor(content?: Record, meta?: Meta, attributes?: Attributes) { + super(content, meta, attributes); + this.element = 'reference'; + this.classes.push('workflowsSpec-reference'); + } + + get $ref(): StringElement | undefined { + return this.get('$ref'); + } + + set $ref($ref: StringElement | undefined) { + this.set('$ref', $ref); + } + + get value(): StringElement | undefined { + return this.get('value'); + } + + set value(value: StringElement | undefined) { + this.set('value', value); + } +} + +export default Reference; diff --git a/packages/apidom-ns-workflows-1/src/index.ts b/packages/apidom-ns-workflows-1/src/index.ts index bb4b5a7f08..60a5ee14e0 100644 --- a/packages/apidom-ns-workflows-1/src/index.ts +++ b/packages/apidom-ns-workflows-1/src/index.ts @@ -33,6 +33,7 @@ export { isFailureActionElement, isFailureActionCriteriaElement, isCriterionElement, + isReferenceElement, } from './predicates'; export { isWorkflowsSpecificationExtension } from './refractor/predicates'; @@ -56,6 +57,7 @@ export { SuccessActionElement, FailureActionElement, CriterionElement, + ReferenceElement, } from './refractor/registration'; // NCE types export { default as SourceDescriptionsElement } from './elements/nces/SourceDescriptions'; diff --git a/packages/apidom-ns-workflows-1/src/namespace.ts b/packages/apidom-ns-workflows-1/src/namespace.ts index 629a6e316b..2639e49b73 100644 --- a/packages/apidom-ns-workflows-1/src/namespace.ts +++ b/packages/apidom-ns-workflows-1/src/namespace.ts @@ -8,6 +8,7 @@ import ParameterElement from './elements/Parameter'; import SuccessActionElement from './elements/SuccessAction'; import FailureActionElement from './elements/FailureAction'; import CriterionElement from './elements/Criterion'; +import ReferenceElement from './elements/Reference'; const workflows1 = { namespace: (options: NamespacePluginOptions) => { @@ -21,6 +22,7 @@ const workflows1 = { base.register('successAction', SuccessActionElement); base.register('failureAction', FailureActionElement); base.register('criterion', CriterionElement); + base.register('reference', ReferenceElement); return base; }, diff --git a/packages/apidom-ns-workflows-1/src/predicates.ts b/packages/apidom-ns-workflows-1/src/predicates.ts index 18e22eb212..6d21d55128 100644 --- a/packages/apidom-ns-workflows-1/src/predicates.ts +++ b/packages/apidom-ns-workflows-1/src/predicates.ts @@ -8,6 +8,7 @@ import ParameterElement from './elements/Parameter'; import SuccessActionElement from './elements/SuccessAction'; import FailureActionElement from './elements/FailureAction'; import CriterionElement from './elements/Criterion'; +import ReferenceElement from './elements/Reference'; // NCE types import SourceDescriptionsElement from './elements/nces/SourceDescriptions'; import SuccessActionCriteriaElement from './elements/nces/SuccessActionCriteria'; @@ -97,6 +98,16 @@ export const isCriterionElement = createPredicate( }, ); +export const isReferenceElement = createPredicate( + ({ hasBasicElementProps, isElementType, primitiveEq }) => { + return (element: unknown): element is ReferenceElement => + element instanceof ReferenceElement || + (hasBasicElementProps(element) && + isElementType('reference', element) && + primitiveEq('object', element)); + }, +); + export const isSuccessActionCriteriaElement = createPredicate( ({ hasBasicElementProps, isElementType, primitiveEq, hasClass }) => { return (element: unknown): element is SuccessActionCriteriaElement => diff --git a/packages/apidom-ns-workflows-1/src/refractor/registration.ts b/packages/apidom-ns-workflows-1/src/refractor/registration.ts index d29f971f5c..c0602f963e 100644 --- a/packages/apidom-ns-workflows-1/src/refractor/registration.ts +++ b/packages/apidom-ns-workflows-1/src/refractor/registration.ts @@ -6,6 +6,7 @@ import ParameterElement from '../elements/Parameter'; import SuccessActionElement from '../elements/SuccessAction'; import FailureActionElement from '../elements/FailureAction'; import CriterionElement from '../elements/Criterion'; +import ReferenceElement from '../elements/Reference'; import { createRefractor } from './index'; InfoElement.refract = createRefractor(['visitors', 'document', 'objects', 'Info', '$visitor']); @@ -59,6 +60,13 @@ CriterionElement.refract = createRefractor([ 'Criterion', '$visitor', ]); +ReferenceElement.refract = createRefractor([ + 'visitors', + 'document', + 'objects', + 'Reference', + '$visitor', +]); export { WorkflowsSpecification1Element, @@ -69,4 +77,5 @@ export { SuccessActionElement, FailureActionElement, CriterionElement, + ReferenceElement, }; diff --git a/packages/apidom-ns-workflows-1/src/refractor/specification.ts b/packages/apidom-ns-workflows-1/src/refractor/specification.ts index 7648581960..a89eb1fcdd 100644 --- a/packages/apidom-ns-workflows-1/src/refractor/specification.ts +++ b/packages/apidom-ns-workflows-1/src/refractor/specification.ts @@ -11,6 +11,8 @@ import SuccessActionCriteriaVisitor from './visitors/workflows-1/SuccessActionCr import FailureActionVisitor from './visitors/workflows-1/failure-action'; import FailureActionCriteriaVisitor from './visitors/workflows-1/FailureActionCriteriaVisitor'; import CriterionVisitor from './visitors/workflows-1/criterion'; +import ReferenceVisitor from './visitors/workflows-1/reference'; +import Reference$RefVisitor from './visitors/workflows-1/reference/$RefVisitor'; import SpecificationExtensionVisitor from './visitors/SpecificationExtensionVisitor'; import FallbackVisitor from './visitors/FallbackVisitor'; @@ -93,6 +95,13 @@ const specification = { type: { $ref: '#/visitors/value' }, }, }, + Reference: { + $visitor: ReferenceVisitor, + fixedFields: { + $ref: Reference$RefVisitor, + value: { $ref: '#/visitors/value' }, + }, + }, }, extension: { $visitor: SpecificationExtensionVisitor, diff --git a/packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/$RefVisitor.ts b/packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/$RefVisitor.ts new file mode 100644 index 0000000000..b142b7a4ad --- /dev/null +++ b/packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/$RefVisitor.ts @@ -0,0 +1,17 @@ +import stampit from 'stampit'; +import { StringElement, BREAK, cloneDeep } from '@swagger-api/apidom-core'; + +import FallbackVisitor from '../../FallbackVisitor'; + +const $RefVisitor = stampit(FallbackVisitor, { + methods: { + StringElement(stringElement: StringElement) { + this.element = cloneDeep(stringElement); + this.element.classes.push('reference-value'); + + return BREAK; + }, + }, +}); + +export default $RefVisitor; diff --git a/packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/index.ts b/packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/index.ts new file mode 100644 index 0000000000..62d8e01e7b --- /dev/null +++ b/packages/apidom-ns-workflows-1/src/refractor/visitors/workflows-1/reference/index.ts @@ -0,0 +1,32 @@ +import stampit from 'stampit'; +import { always } from 'ramda'; +import { ObjectElement, isStringElement } from '@swagger-api/apidom-core'; + +import ReferenceElement from '../../../../elements/Reference'; +import FixedFieldsVisitor from '../../generics/FixedFieldsVisitor'; +import FallbackVisitor from '../../FallbackVisitor'; + +const ReferenceVisitor = stampit(FixedFieldsVisitor, FallbackVisitor, { + props: { + specPath: always(['document', 'objects', 'Reference']), + canSupportSpecificationExtensions: false, + }, + init() { + this.element = new ReferenceElement(); + }, + methods: { + ObjectElement(objectElement: ObjectElement) { + // @ts-ignore + const result = FixedFieldsVisitor.compose.methods.ObjectElement.call(this, objectElement); + + // mark this ReferenceElement with reference metadata + if (isStringElement(this.element.$ref)) { + this.element.classes.push('reference-element'); + } + + return result; + }, + }, +}); + +export default ReferenceVisitor; diff --git a/packages/apidom-ns-workflows-1/src/traversal/visitor.ts b/packages/apidom-ns-workflows-1/src/traversal/visitor.ts index 47be2bde4f..8582af2ae0 100644 --- a/packages/apidom-ns-workflows-1/src/traversal/visitor.ts +++ b/packages/apidom-ns-workflows-1/src/traversal/visitor.ts @@ -20,5 +20,6 @@ export const keyMap = { SuccessActionElement: ['content'], FailureActionElement: ['content'], CriterionElement: ['content'], + ReferenceElement: ['content'], ...keyMapBase, }; diff --git a/packages/apidom-ns-workflows-1/test/predicates.ts b/packages/apidom-ns-workflows-1/test/predicates.ts index fb08201264..0532fab540 100644 --- a/packages/apidom-ns-workflows-1/test/predicates.ts +++ b/packages/apidom-ns-workflows-1/test/predicates.ts @@ -13,6 +13,7 @@ import { isFailureActionElement, isFailureActionCriteriaElement, isCriterionElement, + isReferenceElement, WorkflowsSpecification1Element, WorkflowsSpecElement, InfoElement, @@ -24,6 +25,7 @@ import { FailureActionElement, FailureActionCriteriaElement, CriterionElement, + ReferenceElement, } from '../src'; describe('predicates', function () { @@ -634,4 +636,57 @@ describe('predicates', function () { assert.isFalse(isFailureActionElement(FailureActionElementSwan)); }); }); + + context('isReferenceElement', function () { + context('given ReferenceElement instance value', function () { + specify('should return true', function () { + const element = new ReferenceElement(); + + assert.isTrue(isReferenceElement(element)); + }); + }); + + context('given subtype instance value', function () { + specify('should return true', function () { + class ReferenceSubElement extends ReferenceElement {} + + assert.isTrue(isReferenceElement(new ReferenceSubElement())); + }); + }); + + context('given non ReferenceElement instance value', function () { + specify('should return false', function () { + assert.isFalse(isReferenceElement(1)); + assert.isFalse(isReferenceElement(null)); + assert.isFalse(isReferenceElement(undefined)); + assert.isFalse(isReferenceElement({})); + assert.isFalse(isReferenceElement([])); + assert.isFalse(isReferenceElement('string')); + }); + }); + + specify('should support duck-typing', function () { + const referenceElementDuck = { + _storedElement: 'reference', + _content: [], + primitive() { + return 'object'; + }, + get element() { + return this._storedElement; + }, + }; + + const referenceElementSwan = { + _storedElement: undefined, + _content: undefined, + primitive() { + return 'swan'; + }, + }; + + assert.isTrue(isReferenceElement(referenceElementDuck)); + assert.isFalse(isReferenceElement(referenceElementSwan)); + }); + }); }); diff --git a/packages/apidom-ns-workflows-1/test/refractor/elements/Reference/__snapshots__/index.ts.snap b/packages/apidom-ns-workflows-1/test/refractor/elements/Reference/__snapshots__/index.ts.snap new file mode 100644 index 0000000000..abb20a0fbe --- /dev/null +++ b/packages/apidom-ns-workflows-1/test/refractor/elements/Reference/__snapshots__/index.ts.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`refractor elements ReferenceElement should refract to semantic ApiDOM tree 1`] = ` +(ReferenceElement + (MemberElement + (StringElement) + (StringElement)) + (MemberElement + (StringElement) + (StringElement))) +`; diff --git a/packages/apidom-ns-workflows-1/test/refractor/elements/Reference/index.ts b/packages/apidom-ns-workflows-1/test/refractor/elements/Reference/index.ts new file mode 100644 index 0000000000..f3e70868b4 --- /dev/null +++ b/packages/apidom-ns-workflows-1/test/refractor/elements/Reference/index.ts @@ -0,0 +1,19 @@ +import { expect } from 'chai'; +import { sexprs } from '@swagger-api/apidom-core'; + +import { ReferenceElement } from '../../../../src'; + +describe('refractor', function () { + context('elements', function () { + context('ReferenceElement', function () { + specify('should refract to semantic ApiDOM tree', function () { + const referenceElement = ReferenceElement.refract({ + $ref: '#/path/to/somewhere', + value: 'override', + }); + + expect(sexprs(referenceElement)).toMatchSnapshot(); + }); + }); + }); +}); From 2d5cf54554aafea4c32139040e8acd88e8945fab Mon Sep 17 00:00:00 2001 From: Frank Kilcommins Date: Thu, 23 Nov 2023 16:56:09 +0000 Subject: [PATCH 2/3] chore: fix merge conflict --- packages/apidom-ns-workflows-1/src/refractor/registration.ts | 2 ++ packages/apidom-ns-workflows-1/src/refractor/specification.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/apidom-ns-workflows-1/src/refractor/registration.ts b/packages/apidom-ns-workflows-1/src/refractor/registration.ts index 60eced42a6..c5dbf8eb6a 100644 --- a/packages/apidom-ns-workflows-1/src/refractor/registration.ts +++ b/packages/apidom-ns-workflows-1/src/refractor/registration.ts @@ -66,6 +66,8 @@ ReferenceElement.refract = createRefractor([ 'document', 'objects', 'Reference', + '$visitor', +]); JSONSchemaElement.refract = createRefractor([ 'visitors', 'document', diff --git a/packages/apidom-ns-workflows-1/src/refractor/specification.ts b/packages/apidom-ns-workflows-1/src/refractor/specification.ts index 710ff140bc..3c160adb06 100644 --- a/packages/apidom-ns-workflows-1/src/refractor/specification.ts +++ b/packages/apidom-ns-workflows-1/src/refractor/specification.ts @@ -111,6 +111,7 @@ const specification = { $ref: Reference$RefVisitor, value: { $ref: '#/visitors/value' }, }, + }, Schema: { /** * Internally the fixed field visitors are using references to `/document/objects/Schema`. From 2a97925abb9dc0e281deaca9454c2b7c8879711f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Gorej?= Date: Fri, 24 Nov 2023 09:44:51 +0100 Subject: [PATCH 3/3] Update packages/apidom-ns-workflows-1/src/elements/Reference.ts --- packages/apidom-ns-workflows-1/src/elements/Reference.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apidom-ns-workflows-1/src/elements/Reference.ts b/packages/apidom-ns-workflows-1/src/elements/Reference.ts index 1d7e0b7d7b..c52195bf95 100644 --- a/packages/apidom-ns-workflows-1/src/elements/Reference.ts +++ b/packages/apidom-ns-workflows-1/src/elements/Reference.ts @@ -4,7 +4,7 @@ class Reference extends ObjectElement { constructor(content?: Record, meta?: Meta, attributes?: Attributes) { super(content, meta, attributes); this.element = 'reference'; - this.classes.push('workflowsSpec-reference'); + this.classes.push('workflows-spec-reference'); } get $ref(): StringElement | undefined {