Skip to content

Commit 10ecaf7

Browse files
feat(ns-workflows-1): add support for Reference Object (#3446)
Refs #3392
1 parent df575f6 commit 10ecaf7

File tree

13 files changed

+196
-1
lines changed

13 files changed

+196
-1
lines changed

packages/apidom-ns-workflows-1/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,6 @@ Only fully implemented specification objects should be checked here.
195195
- [x] [Failure Action Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#failure-action-object)
196196
- [ ] [Component Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#component-object)
197197
- [x] [Criterion Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#criterion-object)
198-
- [ ] [Reference Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#reference-object)
198+
- [x] [Reference Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#reference-object)
199199
- [x] [JSON Schema](https://json-schema.org/specification-links#2020-12)
200200
- [x] [Specification extensions](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#specification-extensions)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { StringElement, ObjectElement, Attributes, Meta } from '@swagger-api/apidom-core';
2+
3+
class Reference extends ObjectElement {
4+
constructor(content?: Record<string, unknown>, meta?: Meta, attributes?: Attributes) {
5+
super(content, meta, attributes);
6+
this.element = 'reference';
7+
this.classes.push('workflows-spec-reference');
8+
}
9+
10+
get $ref(): StringElement | undefined {
11+
return this.get('$ref');
12+
}
13+
14+
set $ref($ref: StringElement | undefined) {
15+
this.set('$ref', $ref);
16+
}
17+
18+
get value(): StringElement | undefined {
19+
return this.get('value');
20+
}
21+
22+
set value(value: StringElement | undefined) {
23+
this.set('value', value);
24+
}
25+
}
26+
27+
export default Reference;

packages/apidom-ns-workflows-1/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export {
3333
isFailureActionElement,
3434
isFailureActionCriteriaElement,
3535
isCriterionElement,
36+
isReferenceElement,
3637
isJSONSchemaElement,
3738
} from './predicates';
3839

@@ -57,6 +58,7 @@ export {
5758
SuccessActionElement,
5859
FailureActionElement,
5960
CriterionElement,
61+
ReferenceElement,
6062
JSONSchemaElement,
6163
} from './refractor/registration';
6264
// NCE types

packages/apidom-ns-workflows-1/src/namespace.ts

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import ParameterElement from './elements/Parameter';
88
import SuccessActionElement from './elements/SuccessAction';
99
import FailureActionElement from './elements/FailureAction';
1010
import CriterionElement from './elements/Criterion';
11+
import ReferenceElement from './elements/Reference';
1112
import JSONSchemaElement from './elements/JSONSchema';
1213

1314
const workflows1 = {
@@ -22,6 +23,7 @@ const workflows1 = {
2223
base.register('successAction', SuccessActionElement);
2324
base.register('failureAction', FailureActionElement);
2425
base.register('criterion', CriterionElement);
26+
base.register('reference', ReferenceElement);
2527
base.register('jSONSchemaDraft202012', JSONSchemaElement);
2628

2729
return base;

packages/apidom-ns-workflows-1/src/predicates.ts

+11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import ParameterElement from './elements/Parameter';
88
import SuccessActionElement from './elements/SuccessAction';
99
import FailureActionElement from './elements/FailureAction';
1010
import CriterionElement from './elements/Criterion';
11+
import ReferenceElement from './elements/Reference';
1112
import JSONSchemaElement from './elements/JSONSchema';
1213
// NCE types
1314
import SourceDescriptionsElement from './elements/nces/SourceDescriptions';
@@ -98,6 +99,16 @@ export const isCriterionElement = createPredicate(
9899
},
99100
);
100101

102+
export const isReferenceElement = createPredicate(
103+
({ hasBasicElementProps, isElementType, primitiveEq }) => {
104+
return (element: unknown): element is ReferenceElement =>
105+
element instanceof ReferenceElement ||
106+
(hasBasicElementProps(element) &&
107+
isElementType('reference', element) &&
108+
primitiveEq('object', element));
109+
},
110+
);
111+
101112
export const isSuccessActionCriteriaElement = createPredicate(
102113
({ hasBasicElementProps, isElementType, primitiveEq, hasClass }) => {
103114
return (element: unknown): element is SuccessActionCriteriaElement =>

packages/apidom-ns-workflows-1/src/refractor/registration.ts

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ParameterElement from '../elements/Parameter';
66
import SuccessActionElement from '../elements/SuccessAction';
77
import FailureActionElement from '../elements/FailureAction';
88
import CriterionElement from '../elements/Criterion';
9+
import ReferenceElement from '../elements/Reference';
910
import JSONSchemaElement from '../elements/JSONSchema';
1011
import { createRefractor } from './index';
1112

@@ -60,6 +61,13 @@ CriterionElement.refract = createRefractor([
6061
'Criterion',
6162
'$visitor',
6263
]);
64+
ReferenceElement.refract = createRefractor([
65+
'visitors',
66+
'document',
67+
'objects',
68+
'Reference',
69+
'$visitor',
70+
]);
6371
JSONSchemaElement.refract = createRefractor([
6472
'visitors',
6573
'document',
@@ -77,5 +85,6 @@ export {
7785
SuccessActionElement,
7886
FailureActionElement,
7987
CriterionElement,
88+
ReferenceElement,
8089
JSONSchemaElement,
8190
};

packages/apidom-ns-workflows-1/src/refractor/specification.ts

+9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import SuccessActionCriteriaVisitor from './visitors/workflows-1/SuccessActionCr
1414
import FailureActionVisitor from './visitors/workflows-1/failure-action';
1515
import FailureActionCriteriaVisitor from './visitors/workflows-1/FailureActionCriteriaVisitor';
1616
import CriterionVisitor from './visitors/workflows-1/criterion';
17+
import ReferenceVisitor from './visitors/workflows-1/reference';
18+
import Reference$RefVisitor from './visitors/workflows-1/reference/$RefVisitor';
1719
import JSONSchemaVisitor from './visitors/workflows-1/json-schema';
1820
import SpecificationExtensionVisitor from './visitors/SpecificationExtensionVisitor';
1921
import FallbackVisitor from './visitors/FallbackVisitor';
@@ -103,6 +105,13 @@ const specification = {
103105
type: { $ref: '#/visitors/value' },
104106
},
105107
},
108+
Reference: {
109+
$visitor: ReferenceVisitor,
110+
fixedFields: {
111+
$ref: Reference$RefVisitor,
112+
value: { $ref: '#/visitors/value' },
113+
},
114+
},
106115
Schema: {
107116
/**
108117
* Internally the fixed field visitors are using references to `/document/objects/Schema`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import stampit from 'stampit';
2+
import { StringElement, BREAK, cloneDeep } from '@swagger-api/apidom-core';
3+
4+
import FallbackVisitor from '../../FallbackVisitor';
5+
6+
const $RefVisitor = stampit(FallbackVisitor, {
7+
methods: {
8+
StringElement(stringElement: StringElement) {
9+
this.element = cloneDeep(stringElement);
10+
this.element.classes.push('reference-value');
11+
12+
return BREAK;
13+
},
14+
},
15+
});
16+
17+
export default $RefVisitor;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import stampit from 'stampit';
2+
import { always } from 'ramda';
3+
import { ObjectElement, isStringElement } from '@swagger-api/apidom-core';
4+
5+
import ReferenceElement from '../../../../elements/Reference';
6+
import FixedFieldsVisitor from '../../generics/FixedFieldsVisitor';
7+
import FallbackVisitor from '../../FallbackVisitor';
8+
9+
const ReferenceVisitor = stampit(FixedFieldsVisitor, FallbackVisitor, {
10+
props: {
11+
specPath: always(['document', 'objects', 'Reference']),
12+
canSupportSpecificationExtensions: false,
13+
},
14+
init() {
15+
this.element = new ReferenceElement();
16+
},
17+
methods: {
18+
ObjectElement(objectElement: ObjectElement) {
19+
// @ts-ignore
20+
const result = FixedFieldsVisitor.compose.methods.ObjectElement.call(this, objectElement);
21+
22+
// mark this ReferenceElement with reference metadata
23+
if (isStringElement(this.element.$ref)) {
24+
this.element.classes.push('reference-element');
25+
}
26+
27+
return result;
28+
},
29+
},
30+
});
31+
32+
export default ReferenceVisitor;

packages/apidom-ns-workflows-1/src/traversal/visitor.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const keyMap = {
2020
SuccessActionElement: ['content'],
2121
FailureActionElement: ['content'],
2222
CriterionElement: ['content'],
23+
ReferenceElement: ['content'],
2324
JSONSSchemaDraft202012Element: ['content'],
2425
...keyMapBase,
2526
};

packages/apidom-ns-workflows-1/test/predicates.ts

+55
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
isFailureActionElement,
1414
isFailureActionCriteriaElement,
1515
isCriterionElement,
16+
isReferenceElement,
1617
WorkflowsSpecification1Element,
1718
WorkflowsSpecElement,
1819
InfoElement,
@@ -24,6 +25,7 @@ import {
2425
FailureActionElement,
2526
FailureActionCriteriaElement,
2627
CriterionElement,
28+
ReferenceElement,
2729
} from '../src';
2830

2931
describe('predicates', function () {
@@ -634,4 +636,57 @@ describe('predicates', function () {
634636
assert.isFalse(isFailureActionElement(FailureActionElementSwan));
635637
});
636638
});
639+
640+
context('isReferenceElement', function () {
641+
context('given ReferenceElement instance value', function () {
642+
specify('should return true', function () {
643+
const element = new ReferenceElement();
644+
645+
assert.isTrue(isReferenceElement(element));
646+
});
647+
});
648+
649+
context('given subtype instance value', function () {
650+
specify('should return true', function () {
651+
class ReferenceSubElement extends ReferenceElement {}
652+
653+
assert.isTrue(isReferenceElement(new ReferenceSubElement()));
654+
});
655+
});
656+
657+
context('given non ReferenceElement instance value', function () {
658+
specify('should return false', function () {
659+
assert.isFalse(isReferenceElement(1));
660+
assert.isFalse(isReferenceElement(null));
661+
assert.isFalse(isReferenceElement(undefined));
662+
assert.isFalse(isReferenceElement({}));
663+
assert.isFalse(isReferenceElement([]));
664+
assert.isFalse(isReferenceElement('string'));
665+
});
666+
});
667+
668+
specify('should support duck-typing', function () {
669+
const referenceElementDuck = {
670+
_storedElement: 'reference',
671+
_content: [],
672+
primitive() {
673+
return 'object';
674+
},
675+
get element() {
676+
return this._storedElement;
677+
},
678+
};
679+
680+
const referenceElementSwan = {
681+
_storedElement: undefined,
682+
_content: undefined,
683+
primitive() {
684+
return 'swan';
685+
},
686+
};
687+
688+
assert.isTrue(isReferenceElement(referenceElementDuck));
689+
assert.isFalse(isReferenceElement(referenceElementSwan));
690+
});
691+
});
637692
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`refractor elements ReferenceElement should refract to semantic ApiDOM tree 1`] = `
4+
(ReferenceElement
5+
(MemberElement
6+
(StringElement)
7+
(StringElement))
8+
(MemberElement
9+
(StringElement)
10+
(StringElement)))
11+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { expect } from 'chai';
2+
import { sexprs } from '@swagger-api/apidom-core';
3+
4+
import { ReferenceElement } from '../../../../src';
5+
6+
describe('refractor', function () {
7+
context('elements', function () {
8+
context('ReferenceElement', function () {
9+
specify('should refract to semantic ApiDOM tree', function () {
10+
const referenceElement = ReferenceElement.refract({
11+
$ref: '#/path/to/somewhere',
12+
value: 'override',
13+
});
14+
15+
expect(sexprs(referenceElement)).toMatchSnapshot();
16+
});
17+
});
18+
});
19+
});

0 commit comments

Comments
 (0)