Skip to content

Commit 5b504e5

Browse files
authored
feat(ns-workflows-1): add support for JSONSchema Object (#3445)
Refs #3392
1 parent 8435e5c commit 5b504e5

File tree

19 files changed

+855
-119
lines changed

19 files changed

+855
-119
lines changed

package-lock.json

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/apidom-ns-openapi-3-1/src/elements/Schema.ts

+3
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ class Schema extends ObjectElement {
584584
return this.get('example');
585585
}
586586

587+
/**
588+
* @deprecated The example property has been deprecated in favor of the JSON Schema examples keyword. Use of example is discouraged, and later versions of this specification may remove it.
589+
*/
587590
set example(example: Element | undefined) {
588591
this.set('example', example);
589592
}

packages/apidom-ns-openapi-3-1/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export { default as refractorPluginNormalizeOperationIds } from './refractor/plu
2424
export { default as refractorPluginNormalizeParameterExamples } from './refractor/plugins/normalize-parameter-examples';
2525
export { default as refractorPluginNormalizeHeaderExamples } from './refractor/plugins/normalize-header-examples';
2626
export { default as createToolbox } from './refractor/toolbox';
27+
export { default as specificationObj } from './refractor/specification';
2728

2829
export {
2930
isCallbackElement,

packages/apidom-ns-openapi-3-1/src/refractor/specification.ts

+115-115
Large diffs are not rendered by default.

packages/apidom-ns-openapi-3-1/src/refractor/visitors/open-api-3-1/schema/index.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@ import { FallbackVisitor, FixedFieldsVisitor } from '@swagger-api/apidom-ns-open
1414

1515
import { isSchemaElement, isJsonSchemaDialectElement } from '../../../../predicates';
1616
import SchemaElement from '../../../../elements/Schema';
17-
import JsonSchemaDialect from '../../../../elements/JsonSchemaDialect';
17+
import JsonSchemaDialectElement from '../../../../elements/JsonSchemaDialect';
1818
import ParentSchemaAwareVisitor from './ParentSchemaAwareVisitor';
1919

2020
const SchemaVisitor = stampit(FixedFieldsVisitor, ParentSchemaAwareVisitor, FallbackVisitor, {
2121
props: {
2222
specPath: always(['document', 'objects', 'Schema']),
2323
canSupportSpecificationExtensions: true,
24+
jsonSchemaDefaultDialect: JsonSchemaDialectElement.default,
2425
},
2526
// @ts-ignore
2627
init() {
28+
this.element = new SchemaElement();
29+
2730
/**
2831
* Private Api.
2932
*/
@@ -47,7 +50,7 @@ const SchemaVisitor = stampit(FixedFieldsVisitor, ParentSchemaAwareVisitor, Fall
4750
) {
4851
jsonSchemaDialect = toValue(this.openApiGenericElement.get('jsonSchemaDialect'));
4952
} else {
50-
jsonSchemaDialect = toValue(JsonSchemaDialect.default);
53+
jsonSchemaDialect = toValue(this.jsonSchemaDefaultDialect);
5154
}
5255

5356
return jsonSchemaDialect;
@@ -78,7 +81,7 @@ const SchemaVisitor = stampit(FixedFieldsVisitor, ParentSchemaAwareVisitor, Fall
7881
// get current $id keyword
7982
const $id = toValue(objectElement.get('$id'));
8083

81-
// remember $id keyword if it's a non empty strings
84+
// remember $id keyword if it's a non-empty strings
8285
if (isNonEmptyString($id)) {
8386
inherited$id.push($id);
8487
}
@@ -91,7 +94,6 @@ const SchemaVisitor = stampit(FixedFieldsVisitor, ParentSchemaAwareVisitor, Fall
9194
*/
9295
// eslint-disable-next-line @typescript-eslint/naming-convention
9396
this.ObjectElement = function _ObjectElement(objectElement: ObjectElement) {
94-
this.element = new SchemaElement();
9597
handle$schema(objectElement);
9698
handle$id(objectElement);
9799

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

+1
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,5 @@ Only fully implemented specification objects should be checked here.
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)
198198
- [ ] [Reference Object](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#reference-object)
199+
- [x] [JSON Schema](https://json-schema.org/specification-links#2020-12)
199200
- [x] [Specification extensions](https://github.com/OAI/sig-workflows/blob/main/versions/1.0.0.md#specification-extensions)

packages/apidom-ns-workflows-1/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"dependencies": {
4545
"@babel/runtime-corejs3": "^7.20.7",
4646
"@swagger-api/apidom-core": "*",
47+
"@swagger-api/apidom-ns-openapi-3-1": "*",
4748
"@types/ramda": "~0.29.6",
4849
"ramda": "~0.29.1",
4950
"ramda-adjunct": "^4.1.1",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { Attributes, Meta } from '@swagger-api/apidom-core';
2+
import { SchemaElement } from '@swagger-api/apidom-ns-openapi-3-1';
3+
4+
class JSONSchema extends SchemaElement {
5+
constructor(content?: Record<string, unknown>, meta?: Meta, attributes?: Attributes) {
6+
super(content, meta, attributes);
7+
this.element = 'jSONSchemaDraft202012';
8+
}
9+
10+
/**
11+
* We're redefining the getters/setters here so that the following keywords
12+
* are not part of the OAS base vocabulary, but rather an arbitrary custom dialect.
13+
*/
14+
get discriminator(): any {
15+
return this.get('discriminator');
16+
}
17+
18+
set discriminator(discriminator: any) {
19+
this.set('discriminator', discriminator);
20+
}
21+
22+
get xml(): any {
23+
return this.get('xml');
24+
}
25+
26+
set xml(xml: any) {
27+
this.set('xml', xml);
28+
}
29+
30+
get externalDocs(): any {
31+
return this.get('externalDocs');
32+
}
33+
34+
set externalDocs(externalDocs: any) {
35+
this.set('externalDocs', externalDocs);
36+
}
37+
38+
get example(): any {
39+
return this.get('example');
40+
}
41+
42+
set example(example: any) {
43+
this.set('example', example);
44+
}
45+
}
46+
47+
export default JSONSchema;

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+
isJSONSchemaElement,
3637
} from './predicates';
3738

3839
export { isWorkflowsSpecificationExtension } from './refractor/predicates';
@@ -56,6 +57,7 @@ export {
5657
SuccessActionElement,
5758
FailureActionElement,
5859
CriterionElement,
60+
JSONSchemaElement,
5961
} from './refractor/registration';
6062
// NCE types
6163
export { default as SourceDescriptionsElement } from './elements/nces/SourceDescriptions';

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 JSONSchemaElement from './elements/JSONSchema';
1112

1213
const workflows1 = {
1314
namespace: (options: NamespacePluginOptions) => {
@@ -21,6 +22,7 @@ const workflows1 = {
2122
base.register('successAction', SuccessActionElement);
2223
base.register('failureAction', FailureActionElement);
2324
base.register('criterion', CriterionElement);
25+
base.register('jSONSchemaDraft202012', JSONSchemaElement);
2426

2527
return base;
2628
},

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 JSONSchemaElement from './elements/JSONSchema';
1112
// NCE types
1213
import SourceDescriptionsElement from './elements/nces/SourceDescriptions';
1314
import SuccessActionCriteriaElement from './elements/nces/SuccessActionCriteria';
@@ -130,3 +131,13 @@ export const isFailureActionCriteriaElement = createPredicate(
130131
hasClass('criteria', element));
131132
},
132133
);
134+
135+
export const isJSONSchemaElement = createPredicate(
136+
({ hasBasicElementProps, isElementType, primitiveEq }) => {
137+
return (element: unknown): element is JSONSchemaElement =>
138+
element instanceof JSONSchemaElement ||
139+
(hasBasicElementProps(element) &&
140+
isElementType('jSONSchemaDraft202012', element) &&
141+
primitiveEq('object', element));
142+
},
143+
);

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 JSONSchemaElement from '../elements/JSONSchema';
910
import { createRefractor } from './index';
1011

1112
InfoElement.refract = createRefractor(['visitors', 'document', 'objects', 'Info', '$visitor']);
@@ -59,6 +60,13 @@ CriterionElement.refract = createRefractor([
5960
'Criterion',
6061
'$visitor',
6162
]);
63+
JSONSchemaElement.refract = createRefractor([
64+
'visitors',
65+
'document',
66+
'objects',
67+
'JSONSchema',
68+
'$visitor',
69+
]);
6270

6371
export {
6472
WorkflowsSpecification1Element,
@@ -69,4 +77,5 @@ export {
6977
SuccessActionElement,
7078
FailureActionElement,
7179
CriterionElement,
80+
JSONSchemaElement,
7281
};

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

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { omit } from 'ramda';
2+
import { specificationObj as OpenApi3_1Specification } from '@swagger-api/apidom-ns-openapi-3-1';
3+
14
import WorkflowsSpecificationVisitor from './visitors/workflows-1/index';
25
import WorkflowsSpecVisitor from './visitors/workflows-1/WorkflowsSpecVisitor';
36
import InfoVisitor from './visitors/workflows-1/info';
@@ -11,6 +14,7 @@ import SuccessActionCriteriaVisitor from './visitors/workflows-1/SuccessActionCr
1114
import FailureActionVisitor from './visitors/workflows-1/failure-action';
1215
import FailureActionCriteriaVisitor from './visitors/workflows-1/FailureActionCriteriaVisitor';
1316
import CriterionVisitor from './visitors/workflows-1/criterion';
17+
import JSONSchemaVisitor from './visitors/workflows-1/json-schema';
1418
import SpecificationExtensionVisitor from './visitors/SpecificationExtensionVisitor';
1519
import FallbackVisitor from './visitors/FallbackVisitor';
1620

@@ -23,6 +27,12 @@ import FallbackVisitor from './visitors/FallbackVisitor';
2327
* Note: Specification object allows to use absolute internal JSON pointers.
2428
*/
2529

30+
const { fixedFields: schemaFixedFields } = OpenApi3_1Specification.visitors.document.objects.Schema;
31+
const jsonSchemaFixedFields = omit(
32+
['discriminator', 'xml', 'externalDocs', 'example'],
33+
schemaFixedFields,
34+
); // getting rid of OAS base dialect keywords
35+
2636
const specification = {
2737
visitors: {
2838
value: FallbackVisitor,
@@ -93,6 +103,19 @@ const specification = {
93103
type: { $ref: '#/visitors/value' },
94104
},
95105
},
106+
Schema: {
107+
/**
108+
* Internally the fixed field visitors are using references to `/document/objects/Schema`.
109+
* Schema spec make sure it's pointing to our JSONSchema visitor and basically acts like
110+
* an alias for it.
111+
*/
112+
$visitor: JSONSchemaVisitor,
113+
fixedFields: jsonSchemaFixedFields,
114+
},
115+
JSONSchema: {
116+
$visitor: JSONSchemaVisitor,
117+
fixedFields: jsonSchemaFixedFields,
118+
},
96119
},
97120
extension: {
98121
$visitor: SpecificationExtensionVisitor,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { always } from 'ramda';
2+
import stampit from 'stampit';
3+
import { specificationObj as OpenApi3_1Specification } from '@swagger-api/apidom-ns-openapi-3-1';
4+
5+
import JSONSchemaElement from '../../../../elements/JSONSchema';
6+
7+
const { $visitor: SchemaVisitor } = OpenApi3_1Specification.visitors.document.objects.Schema;
8+
9+
const JSONSchemaVisitor = stampit(SchemaVisitor, {
10+
props: {
11+
specPath: always(['document', 'objects', 'JSONSchema']),
12+
canSupportSpecificationExtensions: false,
13+
jsonSchemaDefaultDialect: 'https://json-schema.org/draft/2020-12/schema',
14+
},
15+
init() {
16+
this.element = new JSONSchemaElement();
17+
},
18+
});
19+
20+
export default JSONSchemaVisitor;

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

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

0 commit comments

Comments
 (0)