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-openapi-2): add support for Schema Object #3273

Merged
merged 2 commits into from
Oct 17, 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-openapi-2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Only fully implemented specification objects should be checked here.
- [x] [Header Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-header-object)
- [x] [Tag Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-tag-object)
- [x] [Reference Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-reference-object)
- [ ] [Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-schema-object)
- [x] [Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-schema-object)
- [x] [XML Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-xml-object)
- [ ] [Definitions Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-definitions-object)
- [ ] [Parameters Definitions Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#user-content-paramters-definitions-object)
Expand Down
22 changes: 0 additions & 22 deletions packages/apidom-ns-openapi-2/src/elements/Header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,28 +216,6 @@ class Header extends JSONSchemaElement {
throw new UnsupportedOperationError('title setter in Header class is not not supported.');
}

get description(): StringElement | undefined {
return this.get('description');
}

set description(description: StringElement | undefined) {
this.set('description,', description);
}

/**
* Semantic validation with "format"
*
* URI: https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-7
*/

get format(): StringElement | undefined {
return this.get('format');
}

set format(format: StringElement | undefined) {
this.set('format', format);
}

/**
* JSON Hyper-Schema
*
Expand Down
14 changes: 0 additions & 14 deletions packages/apidom-ns-openapi-2/src/elements/Items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,20 +219,6 @@ class Items extends JSONSchemaElement {
throw new UnsupportedOperationError('description setter in Items class is not not supported.');
}

/**
* Semantic validation with "format"
*
* URI: https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-7
*/

get format(): StringElement | undefined {
return this.get('format');
}

set format(format: StringElement | undefined) {
this.set('format', format);
}

/**
* JSON Hyper-Schema
*
Expand Down
148 changes: 146 additions & 2 deletions packages/apidom-ns-openapi-2/src/elements/Schema.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,156 @@
import { Attributes, Meta } from '@swagger-api/apidom-core';
import { JSONSchemaElement } from '@swagger-api/apidom-ns-json-schema-draft-4';
import {
Attributes,
Meta,
ArrayElement,
BooleanElement,
ObjectElement,
StringElement,
} from '@swagger-api/apidom-core';
import { UnsupportedOperationError } from '@swagger-api/apidom-error';
import {
JSONReferenceElement,
JSONSchemaElement,
MediaElement,
} from '@swagger-api/apidom-ns-json-schema-draft-4';

/* eslint-disable class-methods-use-this */
class Schema extends JSONSchemaElement {
constructor(content?: Record<string, unknown>, meta?: Meta, attributes?: Attributes) {
super(content, meta, attributes);
this.element = 'schema';
this.classes.push('json-schema-draft-4');
}

/**
* Core vocabulary
*
* URI: https://tools.ietf.org/html/draft-wright-json-schema-00
*/
get idProp(): StringElement | undefined {
throw new UnsupportedOperationError('idProp getter in Schema class is not not supported.');
}

set idProp(idProps: StringElement | undefined) {
throw new UnsupportedOperationError('idProp setter in Schema class is not not supported.');
}

get $schema(): StringElement | undefined {
throw new UnsupportedOperationError('$schema getter in Schema class is not not supported.');
}

set $schema($schema: StringElement | undefined) {
throw new UnsupportedOperationError('$schema setter in Schema class is not not supported.');
}

/**
* Validation keywords for arrays
*/

get additionalItems(): this | JSONReferenceElement | BooleanElement | undefined {
throw new UnsupportedOperationError(
'additionalItems getter in Schema class is not not supported.',
);
}

set additionalItems(additionalItems: this | JSONReferenceElement | BooleanElement | undefined) {
throw new UnsupportedOperationError(
'additionalItems setter in Schema class is not not supported.',
);
}

/**
* Validation keywords for objects
*/

get patternProperties(): ObjectElement | undefined {
throw new UnsupportedOperationError(
'patternProperties getter in Schema class is not not supported.',
);
}

set patternProperties(patternProperties: ObjectElement | undefined) {
throw new UnsupportedOperationError(
'patternProperties setter in Schema class is not not supported.',
);
}

get dependencies(): ObjectElement | undefined {
throw new UnsupportedOperationError(
'dependencies getter in Schema class is not not supported.',
);
}

set dependencies(dependencies: ObjectElement | undefined) {
throw new UnsupportedOperationError(
'dependencies setter in Schema class is not not supported.',
);
}

/**
* Validation keywords for any instance type
*/
get anyOf(): ArrayElement | undefined {
throw new UnsupportedOperationError('anyOf getter in Schema class is not not supported.');
}

set anyOf(anyOf: ArrayElement | undefined) {
throw new UnsupportedOperationError('anyOf setter in Schema class is not not supported.');
}

get oneOf(): ArrayElement | undefined {
throw new UnsupportedOperationError('oneOf getter in Schema class is not not supported.');
}

set oneOf(oneOf: ArrayElement | undefined) {
throw new UnsupportedOperationError('oneOf setter in Schema class is not not supported.');
}

get not(): this | JSONReferenceElement | undefined {
throw new UnsupportedOperationError('not getter in Schema class is not not supported.');
}

set not(not: this | JSONReferenceElement | undefined) {
throw new UnsupportedOperationError('not setter in Schema class is not not supported.');
}

get definitions(): ObjectElement | undefined {
throw new UnsupportedOperationError('definitions getter in Schema class is not not supported.');
}

set definitions(definitions: ObjectElement | undefined) {
throw new UnsupportedOperationError('definitions setter in Schema class is not not supported.');
}

/**
* JSON Hyper-Schema
*
* URI: https://datatracker.ietf.org/doc/html/draft-wright-json-schema-hyperschema-00
*/

get base(): StringElement | undefined {
throw new UnsupportedOperationError('base getter in Schema class is not not supported.');
}

set base(base: StringElement | undefined) {
throw new UnsupportedOperationError('base setter in Schema class is not not supported.');
}

get links(): ArrayElement | undefined {
throw new UnsupportedOperationError('links getter in Schema class is not not supported.');
}

set links(links: ArrayElement | undefined) {
throw new UnsupportedOperationError('links setter in Schema class is not not supported.');
}

get media(): MediaElement | undefined {
throw new UnsupportedOperationError('media getter in Schema class is not not supported.');
}

set media(media: MediaElement | undefined) {
throw new UnsupportedOperationError('media setter in Schema class is not not supported.');
}
}
/* eslint-enable class-methods-use-this */

export default Schema;
2 changes: 2 additions & 0 deletions packages/apidom-ns-openapi-2/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export {
isHeaderElement,
isTagElement,
isReferenceElement,
isSchemaElement,
isXmlElement,
isSecurityDefinitionsElement,
isSecuritySchemeElement,
Expand All @@ -53,6 +54,7 @@ export {
HeaderElement,
TagElement,
ReferenceElement,
SchemaElement,
XmlElement,
SecurityDefinitionsElement,
SecuritySchemeElement,
Expand Down
2 changes: 2 additions & 0 deletions packages/apidom-ns-openapi-2/src/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ExampleElement from './elements/Example';
import HeadersElement from './elements/Headers';
import HeaderElement from './elements/Header';
import TagElement from './elements/Tag';
import SchemaElement from './elements/Schema';
import XmlElement from './elements/Xml';
import ReferenceElement from './elements/Reference';
import SecurityDefinitionsElement from './elements/SecurityDefinitions';
Expand All @@ -32,6 +33,7 @@ const openApi2 = {
base.register('header', HeaderElement);
base.register('tag', TagElement);
base.register('reference', ReferenceElement);
base.register('schema', SchemaElement);
base.register('xml', XmlElement);
base.register('securityDefinitions', SecurityDefinitionsElement);
base.register('securityScheme', SecuritySchemeElement);
Expand Down
11 changes: 11 additions & 0 deletions packages/apidom-ns-openapi-2/src/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import HeadersElement from './elements/Headers';
import HeaderElement from './elements/Header';
import TagElement from './elements/Tag';
import ReferenceElement from './elements/Reference';
import SchemaElement from './elements/Schema';
import XmlElement from './elements/Xml';
import SecurityDefinitionsElement from './elements/SecurityDefinitions';
import SecuritySchemeElement from './elements/SecurityScheme';
Expand Down Expand Up @@ -126,6 +127,16 @@ export const isReferenceElement = createPredicate(
},
);

export const isSchemaElement = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq }) => {
return (element: unknown) =>
element instanceof SchemaElement ||
(hasBasicElementProps(element) &&
isElementType('schema', element) &&
primitiveEq('object', element));
},
);

export const isXmlElement = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq }) => {
return (element: unknown) =>
Expand Down
3 changes: 3 additions & 0 deletions packages/apidom-ns-openapi-2/src/refractor/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ExampleElement from '../elements/Example';
import HeaderElement from '../elements/Header';
import TagElement from '../elements/Tag';
import ReferenceElement from '../elements/Reference';
import SchemaElement from '../elements/Schema';
import XmlElement from '../elements/Xml';
import SecurityDefinitionsElement from '../elements/SecurityDefinitions';
import SecuritySchemeElement from '../elements/SecurityScheme';
Expand Down Expand Up @@ -70,6 +71,7 @@ ReferenceElement.refract = createRefractor([
'Reference',
'$visitor',
]);
SchemaElement.refract = createRefractor(['visitors', 'document', 'objects', 'Schema', '$visitor']);
XmlElement.refract = createRefractor(['visitors', 'document', 'objects', 'XML', '$visitor']);
SecurityDefinitionsElement.refract = createRefractor([
'visitors',
Expand Down Expand Up @@ -106,6 +108,7 @@ export {
HeaderElement,
TagElement,
ReferenceElement,
SchemaElement,
XmlElement,
SecurityDefinitionsElement,
SecuritySchemeElement,
Expand Down
46 changes: 46 additions & 0 deletions packages/apidom-ns-openapi-2/src/refractor/specification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import TagVisitor from './visitors/open-api-2/tag';
import ReferenceVisitor from './visitors/open-api-2/reference';
import Reference$RefVisitor from './visitors/open-api-2/reference/$RefVisitor';
import SchemaVisitor from './visitors/open-api-2/schema';
import SchemaAllOfVisitor from './visitors/open-api-2/schema/AllOfVisitor';
import SchemaItemsVisitor from './visitors/open-api-2/schema/ItemsVisitor';
import SchemaPropertiesVisitor from './visitors/open-api-2/schema/PropertiesVisitor';
import SchemaOrJSONReferenceVisitor from './visitors/open-api-2/schema/SchemaOrJSONReferenceVisitor';
import XmlVisitor from './visitors/open-api-2/xml';
import SecurityDefinitionsVisitor from './visitors/open-api-2/security-definitions';
import SecuritySchemeVisitor from './visitors/open-api-2/security-scheme';
Expand Down Expand Up @@ -178,8 +182,50 @@ const specification = {
$ref: Reference$RefVisitor,
},
},
JSONReference: JSONSchemaDraft4Specification.visitors.document.objects.JSONReference,
JSONSchema: {
$ref: '#/visitors/document/objects/Schema',
},
Schema: {
$visitor: SchemaVisitor,
fixedFields: {
// the following properties are taken directly from the JSON Schema definition and follow the same specifications
format: jsonSchemaFixedFields.format,
title: jsonSchemaFixedFields.title,
description: jsonSchemaFixedFields.description,
default: jsonSchemaFixedFields.default,
multipleOf: jsonSchemaFixedFields.multipleOf,
maximum: jsonSchemaFixedFields.maximum,
exclusiveMaximum: jsonSchemaFixedFields.exclusiveMaximum,
minimum: jsonSchemaFixedFields.minimum,
exclusiveMinimum: jsonSchemaFixedFields.exclusiveMinimum,
maxLength: jsonSchemaFixedFields.maxLength,
minLength: jsonSchemaFixedFields.minLength,
pattern: jsonSchemaFixedFields.pattern,
maxItems: jsonSchemaFixedFields.maxItems,
minItems: jsonSchemaFixedFields.minItems,
uniqueItems: jsonSchemaFixedFields.uniqueItems,
maxProperties: jsonSchemaFixedFields.maxProperties,
minProperties: jsonSchemaFixedFields.minProperties,
required: jsonSchemaFixedFields.required,
enum: jsonSchemaFixedFields.enum,
type: jsonSchemaFixedFields.type,
readOnly: jsonSchemaFixedFields.readOnly,
// the following properties are taken from the JSON Schema definition but their definitions were adjusted to the Swagger Specification
items: SchemaItemsVisitor,
allOf: SchemaAllOfVisitor,
properties: SchemaPropertiesVisitor,
additionalProperties: SchemaOrJSONReferenceVisitor,
// OpenAPI vocabulary
discriminator: FallbackVisitor,
xml: {
$ref: '#/visitors/document/objects/XML',
},
externalDocs: {
$ref: '#/visitors/document/objects/ExternalDocumentation',
},
example: FallbackVisitor,
},
},
XML: {
$visitor: XmlVisitor,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import stampit from 'stampit';
import { ArrayElement } from '@swagger-api/apidom-core';
import {
specificationObj as JSONSchemaDraft4Specification,
isJSONReferenceElement,
JSONReferenceElement,
} from '@swagger-api/apidom-ns-json-schema-draft-4';

const { allOf: JSONSchemaAllOfVisitor } =
JSONSchemaDraft4Specification.visitors.document.objects.JSONSchema.fixedFields;

const AllOfVisitor = stampit(JSONSchemaAllOfVisitor, {
methods: {
ArrayElement(arrayElement: ArrayElement) {
// @ts-ignore
const result = JSONSchemaAllOfVisitor.compose.methods.ArrayElement.call(this, arrayElement);

this.element
.filter(isJSONReferenceElement)
.forEach((referenceElement: JSONReferenceElement) => {
referenceElement.setMetaProperty('referenced-element', 'schema');
});

return result;
},
},
});

export default AllOfVisitor;
Loading