Skip to content

Commit

Permalink
feat(ns-json-schema-draft-4): handle inheritance of $schema and id
Browse files Browse the repository at this point in the history
Refs #1819
  • Loading branch information
glowcloud committed Jan 15, 2025
1 parent d5cbaf0 commit f829677
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,33 +1,96 @@
import { Mixin } from 'ts-mixer';
import { always } from 'ramda';
import { always, defaultTo } from 'ramda';
import { isNonEmptyString, isUndefined } from 'ramda-adjunct';
import {
ObjectElement,
ArrayElement,
isStringElement,
cloneDeep,
toValue,
} from '@swagger-api/apidom-core';

import FixedFieldsVisitor, {
FixedFieldsVisitorOptions,
SpecPath,
} from '../generics/FixedFieldsVisitor.ts';
import ParentSchemaAwareVisitor, {
ParentSchemaAwareVisitorOptions,
} from './ParentSchemaAwareVisitor.ts';
import FallbackVisitor, { FallbackVisitorOptions } from '../FallbackVisitor.ts';
import JSONSchemaElement from '../../../elements/JSONSchema.ts';
import { isJSONSchemaElement } from '../../../predicates.ts';

/**
* @public
*/
export interface JSONSchemaVisitorOptions
extends FixedFieldsVisitorOptions,
ParentSchemaAwareVisitorOptions,
FallbackVisitorOptions {}

/**
* @public
*/
class JSONSchemaVisitor extends Mixin(FixedFieldsVisitor, FallbackVisitor) {
class JSONSchemaVisitor extends Mixin(
FixedFieldsVisitor,
ParentSchemaAwareVisitor,
FallbackVisitor,
) {
declare public element: JSONSchemaElement;

declare protected readonly specPath: SpecPath<['document', 'objects', 'JSONSchema']>;

protected readonly default$schema = 'http://json-schema.org/draft-04/schema#';

constructor(options: JSONSchemaVisitorOptions) {
super(options);
this.element = new JSONSchemaElement();
this.specPath = always(['document', 'objects', 'JSONSchema']);
}

ObjectElement(objectElement: ObjectElement) {
this.handle$schema(objectElement);
this.handleId(objectElement);

// for further processing consider this Schema Element as parent for all embedded Schema Elements
this.parent = this.element;
const result = FixedFieldsVisitor.prototype.ObjectElement.call(this, objectElement);

return result;
}

handle$schema(objectElement: ObjectElement): void {
// handle $schema keyword in embedded resources
if (isUndefined(this.parent) && !isStringElement(objectElement.get('$schema'))) {
// no parent available and no $schema is defined, set default$schema
this.element.setMetaProperty('inherited$schema', this.default$schema);
} else if (isJSONSchemaElement(this.parent) && !isStringElement(objectElement.get('$schema'))) {
// parent is available and no $schema is defined, set parent $schema
const inherited$schema = defaultTo(
toValue(this.parent.meta.get('inherited$schema')),
toValue(this.parent.$schema),
);
this.element.setMetaProperty('inherited$schema', inherited$schema);
}
}

handleId(objectElement: ObjectElement): void {
// handle id keyword in embedded resources
// fetch parent's inheritedId
const inheritedId =
this.parent !== undefined
? cloneDeep(this.parent.getMetaProperty('inheritedId', []))
: new ArrayElement();
// get current id keyword
const id = toValue(objectElement.get('id'));

// remember id keyword if it's a non-empty strings
if (isNonEmptyString(id)) {
inheritedId.push(id);
}

this.element.setMetaProperty('inheritedId', inheritedId);
}
}

export default JSONSchemaVisitor;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape should refract to JSONSchema Element 1`] = `
{
"element": "JSONSchemaDraft4",
"meta": {
"inheritedId": {
"element": "array",
"content": [
{
"element": "string",
"content": "http://x.y.z/rootschema.json#"
}
]
}
},
"content": [
{
"element": "member",
Expand Down Expand Up @@ -263,7 +274,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "additionalItems"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
},
Expand Down Expand Up @@ -300,7 +320,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
},
"content": [
{
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
]
}
Expand Down Expand Up @@ -521,7 +550,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "prop1"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
}
Expand All @@ -548,7 +586,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "additionalProperties"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
},
Expand Down Expand Up @@ -603,7 +650,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "[a-z]+"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
}
Expand Down Expand Up @@ -662,7 +718,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "dep1"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
}
Expand Down Expand Up @@ -786,7 +851,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
},
"content": [
{
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
]
}
Expand Down Expand Up @@ -825,7 +899,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
},
"content": [
{
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
]
}
Expand Down Expand Up @@ -864,7 +947,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
},
"content": [
{
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
]
}
Expand All @@ -889,7 +981,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "not"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
},
Expand Down Expand Up @@ -944,7 +1045,16 @@ exports[`refractor given generic ApiDOM object in JSON Schema Draft 4 shape shou
"content": "def1"
},
"value": {
"element": "JSONSchemaDraft4"
"element": "JSONSchemaDraft4",
"meta": {
"inherited$schema": {
"element": "string",
"content": "http://json-schema.org/draft-04/schema#"
},
"inheritedId": {
"element": "array"
}
}
}
}
}
Expand Down

0 comments on commit f829677

Please sign in to comment.