diff --git a/packages/downgrader/src/v3.1-to-v3.0.ts b/packages/downgrader/src/v3.1-to-v3.0.ts index 7f8df71..f426bd4 100644 --- a/packages/downgrader/src/v3.1-to-v3.0.ts +++ b/packages/downgrader/src/v3.1-to-v3.0.ts @@ -369,7 +369,9 @@ function losesRestriction( return !( names === true || (isRecord(names) && - Object.entries(names).every(([name, item]) => name === 'type' && item === 'string')) + Object.entries(names).every( + ([name, item]) => item === undefined || (name === 'type' && item === 'string'), + )) ) } case 'unevaluatedProperties': @@ -486,7 +488,9 @@ function valueType(value: unknown): string | undefined { function isMediaTypeOnly(value: unknown): boolean { return ( - isRecord(value) && Object.keys(value).length === 1 && typeof value.contentMediaType === 'string' + isRecord(value) && + typeof value.contentMediaType === 'string' && + Object.entries(value).every(([key, item]) => key === 'contentMediaType' || item === undefined) ) } diff --git a/packages/downgrader/tests/v3.1-to-v3.0.test.ts b/packages/downgrader/tests/v3.1-to-v3.0.test.ts index eb2b290..34a585a 100644 --- a/packages/downgrader/tests/v3.1-to-v3.0.test.ts +++ b/packages/downgrader/tests/v3.1-to-v3.0.test.ts @@ -1073,6 +1073,23 @@ describe('unusual input', () => { ]) }) + it('treats keys holding undefined as missing when deciding what to drop or loosen', () => { + expect( + downgradeSchemaV31ToV30({ + type: 'string', + anyOf: [{ contentMediaType: 'image/png', description: undefined }], + }), + ).toEqual({ type: 'string' }) + expect( + downgradeSchemaV31ToV30({ + oneOf: [ + { type: 'object', propertyNames: { type: 'string', description: undefined } }, + { type: 'string' }, + ], + }), + ).toEqual({ oneOf: [{ type: 'object' }, { type: 'string' }] }) + }) + it('tolerates malformed input without throwing', () => { const doc = { openapi: '3.1.2',