Skip to content

Commit

Permalink
feat(ns-workflows-1): Add Reference Object
Browse files Browse the repository at this point in the history
  • Loading branch information
frankkilcommins committed Nov 23, 2023
1 parent 8435e5c commit 13c5d19
Show file tree
Hide file tree
Showing 13 changed files with 196 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/apidom-ns-workflows-1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
27 changes: 27 additions & 0 deletions packages/apidom-ns-workflows-1/src/elements/Reference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { StringElement, ObjectElement, Attributes, Meta } from '@swagger-api/apidom-core';

class Reference extends ObjectElement {
constructor(content?: Record<string, unknown>, 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;
2 changes: 2 additions & 0 deletions packages/apidom-ns-workflows-1/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export {
isFailureActionElement,
isFailureActionCriteriaElement,
isCriterionElement,
isReferenceElement,
} from './predicates';

export { isWorkflowsSpecificationExtension } from './refractor/predicates';
Expand All @@ -56,6 +57,7 @@ export {
SuccessActionElement,
FailureActionElement,
CriterionElement,
ReferenceElement,
} from './refractor/registration';
// NCE types
export { default as SourceDescriptionsElement } from './elements/nces/SourceDescriptions';
Expand Down
2 changes: 2 additions & 0 deletions packages/apidom-ns-workflows-1/src/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -21,6 +22,7 @@ const workflows1 = {
base.register('successAction', SuccessActionElement);
base.register('failureAction', FailureActionElement);
base.register('criterion', CriterionElement);
base.register('reference', ReferenceElement);

return base;
},
Expand Down
11 changes: 11 additions & 0 deletions packages/apidom-ns-workflows-1/src/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 =>
Expand Down
9 changes: 9 additions & 0 deletions packages/apidom-ns-workflows-1/src/refractor/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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']);
Expand Down Expand Up @@ -59,6 +60,13 @@ CriterionElement.refract = createRefractor([
'Criterion',
'$visitor',
]);
ReferenceElement.refract = createRefractor([
'visitors',
'document',
'objects',
'Reference',
'$visitor',
]);

export {
WorkflowsSpecification1Element,
Expand All @@ -69,4 +77,5 @@ export {
SuccessActionElement,
FailureActionElement,
CriterionElement,
ReferenceElement,
};
9 changes: 9 additions & 0 deletions packages/apidom-ns-workflows-1/src/refractor/specification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -93,6 +95,13 @@ const specification = {
type: { $ref: '#/visitors/value' },
},
},
Reference: {
$visitor: ReferenceVisitor,
fixedFields: {
$ref: Reference$RefVisitor,
value: { $ref: '#/visitors/value' },
},
},
},
extension: {
$visitor: SpecificationExtensionVisitor,
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
1 change: 1 addition & 0 deletions packages/apidom-ns-workflows-1/src/traversal/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export const keyMap = {
SuccessActionElement: ['content'],
FailureActionElement: ['content'],
CriterionElement: ['content'],
ReferenceElement: ['content'],
...keyMapBase,
};
55 changes: 55 additions & 0 deletions packages/apidom-ns-workflows-1/test/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
isFailureActionElement,
isFailureActionCriteriaElement,
isCriterionElement,
isReferenceElement,
WorkflowsSpecification1Element,
WorkflowsSpecElement,
InfoElement,
Expand All @@ -24,6 +25,7 @@ import {
FailureActionElement,
FailureActionCriteriaElement,
CriterionElement,
ReferenceElement,
} from '../src';

describe('predicates', function () {
Expand Down Expand Up @@ -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));
});
});
});
Original file line number Diff line number Diff line change
@@ -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)))
`;
Original file line number Diff line number Diff line change
@@ -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();
});
});
});
});

0 comments on commit 13c5d19

Please sign in to comment.