Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ns-workflows-1): Add Reference Object #3446

Merged
merged 5 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,6 +195,6 @@ 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] [JSON Schema](https://json-schema.org/specification-links#2020-12)
- [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('workflows-spec-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,
isJSONSchemaElement,
} from './predicates';

Expand All @@ -57,6 +58,7 @@ export {
SuccessActionElement,
FailureActionElement,
CriterionElement,
ReferenceElement,
JSONSchemaElement,
} from './refractor/registration';
// NCE types
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';
import JSONSchemaElement from './elements/JSONSchema';

const workflows1 = {
Expand All @@ -22,6 +23,7 @@ const workflows1 = {
base.register('successAction', SuccessActionElement);
base.register('failureAction', FailureActionElement);
base.register('criterion', CriterionElement);
base.register('reference', ReferenceElement);
base.register('jSONSchemaDraft202012', JSONSchemaElement);

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';
import JSONSchemaElement from './elements/JSONSchema';
// NCE types
import SourceDescriptionsElement from './elements/nces/SourceDescriptions';
Expand Down Expand Up @@ -98,6 +99,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 JSONSchemaElement from '../elements/JSONSchema';
import { createRefractor } from './index';

Expand Down Expand Up @@ -60,6 +61,13 @@ CriterionElement.refract = createRefractor([
'Criterion',
'$visitor',
]);
ReferenceElement.refract = createRefractor([
'visitors',
'document',
'objects',
'Reference',
'$visitor',
]);
JSONSchemaElement.refract = createRefractor([
'visitors',
'document',
Expand All @@ -77,5 +85,6 @@ export {
SuccessActionElement,
FailureActionElement,
CriterionElement,
ReferenceElement,
JSONSchemaElement,
};
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 @@ -14,6 +14,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 JSONSchemaVisitor from './visitors/workflows-1/json-schema';
import SpecificationExtensionVisitor from './visitors/SpecificationExtensionVisitor';
import FallbackVisitor from './visitors/FallbackVisitor';
Expand Down Expand Up @@ -103,6 +105,13 @@ const specification = {
type: { $ref: '#/visitors/value' },
},
},
Reference: {
$visitor: ReferenceVisitor,
fixedFields: {
$ref: Reference$RefVisitor,
value: { $ref: '#/visitors/value' },
},
},
Schema: {
/**
* Internally the fixed field visitors are using references to `/document/objects/Schema`.
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,6 +20,7 @@ export const keyMap = {
SuccessActionElement: ['content'],
FailureActionElement: ['content'],
CriterionElement: ['content'],
ReferenceElement: ['content'],
JSONSSchemaDraft202012Element: ['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();
});
});
});
});
Loading