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

fix: refactoring allOf schemas to be pre-merged when we generate JSON Schema #579

Merged
merged 8 commits into from
Jan 12, 2022

Conversation

erunion
Copy link
Member

@erunion erunion commented Jan 11, 2022

🧰 Changes

Last week we received an API definition that contained an allOf that contained another allOf with two things:

  • An object with a data property that evaluated to a {}.
  • An object with a data property that evaluated to a complete object.

Because we have handling in place to not repair allOf children if they are missing a type declaration, this case was falling through that and the empty data object was getting a type: string property added to it because we thought that it was malformed. Further up the stack when we render this schema out we later attempt to merge this newly "fixed" allOf and because type: string and type: object are incompatible we either wouldn't render out anything, or in some cases would fully crash.

Less than ideal!

Since we don't have any great way of determining if a sub-object property is contained within an allOf and isn't malformed and will be okay when it's merged with another schema we decided to completely forgo this repair work that we had to repair schemas that were missing a type (and weren't either implicitly an object or an array), and instead merge all allOf schemas when we generate JSON Schema.

Going forward, with this work any tooling that ingests JSON Schema generated with getParametersAsJsonSchema() will no longer need to worry about allOf cases.

Fix in support of RM-3146.

🧬 QA & Testing

There's a lot going on here, but all tests should no longer have any allOf expectations.

As for the case that uncovered this issue lives, it in __tests__/__datasets__/polymorphism-quirks.json and is tested within __tests__/operation/get-parameters-as-json-schema.test.js.

@erunion erunion added bug Something isn't working enhancement New feature or request refactor Issues about tackling technical debt labels Jan 11, 2022
@@ -222,11 +222,9 @@
"deprecated": true,
"allOf": [
{
"title": "option 1",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed these because they were always going to be merged into a single title property.

Comment on lines +440 to +450
if (
Array.isArray(schema.properties[prop]) ||
(typeof schema.properties[prop] === 'object' && schema.properties[prop] !== null)
) {
schema.properties[prop] = toJSONSchema(schema.properties[prop] as RMOAS.SchemaObject, {
currentLocation: `${currentLocation}/${encodePointer(prop)}`,
globalDefaults,
prevSchemas,
refLogger,
});
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made this change because I discovered that if there was an x- extension, and it was a primitive, in an object we'd run it through the generator again and completely the value.

screen_shot_2022-01-10_at_3 44 13_pm

Though thinking about it, maybe this should instead just exclude anything that starts with x-?

Comment on lines 278 to 284
// If we can't merge the `allOf` for whatever reason (like if one item is a `string` and the other is a
// `object`) then we should completely remove it from the schema and continue with whatever we've got. Why?
// If we don't, any tooling that's ingesting this will need to account for the incompatible `allOf` and it may
// be subject to more breakages than just not having it present would be.
const { ...schemaWithoutAllOf } = schema;
schema = schemaWithoutAllOf as RMOAS.SchemaObject;
delete schema.allOf;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still kind of iffy on this but this is how our schema form currently handles this case, but I still need to follow up this PR with changes to our schema form to handle if type isn't present and treat them as a string.

Comment on lines +326 to +328
const mapping = schema.discriminator.mapping;
Object.keys(mapping).forEach(k => {
refLogger(mapping[k]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to make this change because TS didn't like how we were accessing schema.discriminator here and didn't think that discriminator was present on the schema type (despite the same code working two lines above).

@@ -227,7 +214,12 @@ describe('polymorphism / inheritance', () => {
},
},
{
type: 'integer',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this because integer and object schemas can't be merged.

minimum: min,
maximum: max,
])('`type: %s`', (type, format, min, max) => {
describe(`\`format: ${format}\``, () => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this because we were duping all of these integer + format tests under the same describe block and they weren't properly exposing themselves in the test output. Thankfully they were still being run, it just wasn't clear what was being run for what.

@erunion erunion requested review from a team, Dashron and julshotal and removed request for a team January 11, 2022 20:20
Copy link
Contributor

@Dashron Dashron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just one small comment, otherwise stuff looks good. will test more on the readme merge.

src/lib/openapi-to-json-schema.ts Outdated Show resolved Hide resolved
@erunion erunion merged commit cc16e05 into main Jan 12, 2022
@erunion erunion deleted the fix/pre-merge-allof-schemas branch January 12, 2022 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request refactor Issues about tackling technical debt
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants