Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5382810
fix(downgrader): a $ref cut at recursion in a copy reused later tells…
claude Nov 1, 2026
479b9ac
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
34ef504
fix(downgrader): keep a oneOf of object literals, and an additionalPr…
claude Nov 1, 2026
c750171
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
39f4ca4
fix(downgrader): follow a propertyNames $ref on only through $refs be…
claude Nov 1, 2026
f695074
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
c09da8c
fix(downgrader): rerun the conversion for a schema that loses a restr…
claude Nov 1, 2026
e9f7f25
fix(downgrader): follow an alias chain through inlined $refs and tagg…
claude Nov 1, 2026
905a75a
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
997f21b
perf(downgrader): skip the second pass when no not or oneOf kept its …
claude Nov 1, 2026
cb16050
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
7d46cbc
fix(downgrader): count an object that requires a readOnly or writeOnl…
claude Nov 1, 2026
9962db1
perf(downgrader): check one-way required properties without a closure…
claude Nov 1, 2026
9811aeb
refactor(downgrader): count any readOnly or writeOnly schema as loose
claude Nov 1, 2026
b320e25
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
6de99ef
refactor(downgrader): count a schema met again mid-cycle as loose, in…
claude Nov 1, 2026
11a7506
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
dd53f1c
refactor(downgrader): replace any $ref into items or additionalProper…
claude Nov 1, 2026
811283c
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
3c7ab4b
refactor(downgrader): follow a propertyNames $ref through one $ref only
claude Nov 1, 2026
8ba0f5a
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
37fdc08
fix(downgrader): replace a percent-encoded $ref with its target
claude Nov 1, 2026
c607746
docs(downgrader): note that a percent-encoded $ref is replaced by its…
claude Nov 1, 2026
a7b6f48
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
98c8199
fix(downgrader): write */* as the contentType of an Encoding Object t…
claude Nov 1, 2026
6270b78
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
ab1cc0e
fix(downgrader): leave out 3.2 security requirement names that are no…
claude Nov 1, 2026
8e0b9e3
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
261d141
fix(downgrader): write schema {} for a 3.2 path or cookie value sent …
claude Nov 1, 2026
b6fdfc6
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 1, 2026
45dd5bc
fix(downgrader): write {} for a 3.2 content $ref that does not resolve
claude Nov 1, 2026
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
4 changes: 2 additions & 2 deletions packages/downgrader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ The output `openapi` is the latest patch release, `3.1.2` from `downgradeSpecV32

The input is never changed, and the output shares no plain objects or arrays with it. Input is read as JSON would see it: an object counts whatever realm it comes from or null prototype it has, as in a document oRPC returns, and a key holding `undefined`, as spreading options often leaves, counts as missing. Other values, such as a `Date`, are kept as they are.

External `$ref`s are left as written, except in a 3.2 `content` map, where 3.1 allows none and the entry is removed. The files they point at are not converted, so bundle a multi-file document into one first.
External `$ref`s are left as written, except in a 3.2 `content` map, where 3.1 allows none and the entry becomes `{}`, which takes any payload. The files they point at are not converted, so bundle a multi-file document into one first.

## 3.2 → 3.1

Expand Down Expand Up @@ -120,7 +120,7 @@ Schema Objects inside the document convert as in [Schema](#schema-downgradeschem
#### Limitations

- Other `$ref`s into a removed part, such as a schema `$ref` into `components.mediaTypes`, and Links or discriminator `mapping` values that point at a removed operation, are left as written and dangle.
- A `content` `$ref` that does not resolve is removed, which can leave a parameter or header without the one entry it needs.
- A `content` `$ref` that does not resolve, such as an external one or one through `$self`, becomes `{}`, which takes any payload.
- A security requirement that names its scheme by URI reference loses it, so 3.1 tools can read the operation as needing no credentials for it.
- `$self`-relative references pass through unchanged.

Expand Down
6 changes: 5 additions & 1 deletion packages/downgrader/src/v3.2-to-v3.1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,13 @@ function convertMediaType(value: unknown, ctx: Context): unknown {
}

// A 3.1 content map cannot hold a `$ref`, such as one to `components.mediaTypes`.
// One that does not resolve, such as an external one, becomes `{}`, which takes
// any payload, where removing the entry would take none of that media type.
function convertMediaTypeEntry(value: unknown, ctx: Context): unknown {
const ref = getRef(value)
return ref === undefined ? convertMediaType(value, ctx) : inline(ref, ctx, convertMediaTypeEntry)
const out =
ref === undefined ? convertMediaType(value, ctx) : inline(ref, ctx, convertMediaTypeEntry)
return out === DROP ? {} : out
}

function convertRequestBody(value: unknown, ctx: Context): unknown {
Expand Down
8 changes: 6 additions & 2 deletions packages/downgrader/tests/v3.2-to-v3.1.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,20 @@ describe('downgradeSpecV32ToV31', () => {
expect(out.components).toEqual({ schemas: { Pet: { type: 'object' } } })
})

it('drops a content $ref that does not resolve or loops', () => {
it('writes {} for a content $ref that does not resolve or loops', () => {
const out = convertOperation({
requestBody: {
content: {
'application/json': { $ref: '#/components/mediaTypes/Missing' },
'text/plain': { $ref: '#/paths/~1a/get/requestBody/content/text~1plain' },
'text/csv': { $ref: 'https://example.com/other.json#/components/mediaTypes/Csv' },
},
},
})
expect(out?.requestBody).toStrictEqual({ content: {} })
// A media type with no schema takes any payload.
expect(out?.requestBody).toStrictEqual({
content: { 'application/json': {}, 'text/plain': {}, 'text/csv': {} },
})
})
})

Expand Down
Loading