diff --git a/packages/downgrader/src/v3.1-to-v3.0.ts b/packages/downgrader/src/v3.1-to-v3.0.ts index f31cfb4..8c3b55c 100644 --- a/packages/downgrader/src/v3.1-to-v3.0.ts +++ b/packages/downgrader/src/v3.1-to-v3.0.ts @@ -513,18 +513,13 @@ function isUnevaluatedAdditional(schema: Record): boolean { // property of its own, which 3.0 can express. A reusable enum is a `$ref` to it. function enumNames(schema: Record, ctx: Context): string[] | undefined { // Followed alone or beside annotations, such as the `description` Zod writes - // for a described use, and along a chain of them, since other keywords - // beside a `$ref` narrow the names further. - let names = schema.propertyNames - const visited = new Set() - for ( - let ref = getRef(names); - ref !== undefined && isAnnotatedRef(names as Record) && !visited.has(names); - ref = getRef(names) - ) { - visited.add(names) - names = resolvePointer(ref, ctx) - } + // for a described use, since other keywords beside it narrow the names + // further. A target that is a `$ref` again holds no names here. + const ref = getRef(schema.propertyNames) + const names = + ref !== undefined && isAnnotatedRef(schema.propertyNames as Record) + ? resolvePointer(ref, ctx) + : schema.propertyNames if (!isRecord(names)) { return 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 3c00ab1..f212f11 100644 --- a/packages/downgrader/tests/v3.1-to-v3.0.test.ts +++ b/packages/downgrader/tests/v3.1-to-v3.0.test.ts @@ -2430,7 +2430,7 @@ describe('downgradeSchemaV31ToV30', () => { }) }) - it('follows a propertyNames $ref on through a $ref beside only annotations, and no further', () => { + it('follows a propertyNames $ref through one $ref only', () => { const r = '#/components/schemas/' const schemas = convert({ components: { @@ -2448,11 +2448,8 @@ describe('downgradeSchemaV31ToV30', () => { }, }, }).components?.schemas - expect(schemas?.ByAlias).toEqual({ - type: 'object', - properties: { en: { type: 'string' }, fr: { type: 'string' } }, - additionalProperties: false, - }) + // A target that is a $ref again holds no names, so the record loses them. + expect(schemas?.ByAlias).toEqual({ type: 'object', additionalProperties: { type: 'string' } }) expect(schemas?.NotEnglish).toEqual({}) })