Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion packages/downgrader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Accepts the default OAS dialect, which adds `discriminator`, `xml`, `externalDoc
| 3.1 | In 3.0 |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`type`][js-type] with `"null"` | `nullable: true` beside the other type. `type: "null"` alone becomes `type: "string", nullable: true, enum: [null]`, since 3.0 allows `nullable` only beside `type`, and code generators drop a bare `enum: [null]`. |
| [`type`][js-type] with several types | `anyOf` with one branch per type, which takes `items` for `"array"`. |
| [`type`][js-type] with several types | `anyOf` with one branch per type, which takes `items` for `"array"`. `"null"` gets its own branch, written as for `type: "null"` alone, since code generators ignore `nullable` inside an `anyOf` branch. |
| [`const`][js-const] | `enum` with its one value, and the `type` of that value when it has none, since code generators drop or leave untyped a bare `enum`. `const: null` becomes the same schema as `type: "null"`. |
| Numeric [`exclusiveMinimum`][js-exclusive-minimum] and [`exclusiveMaximum`][js-exclusive-maximum] | `minimum` or `maximum` with a boolean `exclusiveMinimum` or `exclusiveMaximum`, unless `minimum` or `maximum` is stricter. |
| [`examples`][js-examples] | The first entry fills `example` when that is missing. |
Expand Down
27 changes: 13 additions & 14 deletions packages/downgrader/src/v3.1-to-v3.0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,14 +440,11 @@ function convertType(out: Record<string, unknown>, type: unknown): void {
out.nullable = true
}
} else if (rest.length > 1) {
addAnyOf(
out,
rest.map((item) => ({
type: item,
...(item === 'array' && { items: out.items ?? {} }),
...(nullable && { nullable: true }),
})),
)
// Code generators ignore `nullable` inside an `anyOf` branch, so null gets its own.
addAnyOf(out, [
...rest.map((item) => ({ type: item, ...(item === 'array' && { items: out.items ?? {} }) })),
...(nullable ? [onlyNull()] : []),
])
delete out.items
} else if (nullable) {
// 3.0 has no null type, so only null may match, and an `enum` without it matches nothing.
Expand All @@ -459,6 +456,12 @@ function convertType(out: Record<string, unknown>, type: unknown): void {
}
}

// Only null matches it. 3.0 admits null only through `nullable`, which
// needs a `type` beside it, and code generators drop a bare `enum: [null]`.
function onlyNull(): Record<string, unknown> {
return { type: 'string', nullable: true, enum: [null] }
}

function isOnlyNull(values: unknown): boolean {
return Array.isArray(values) && values.length === 1 && values[0] === null
}
Expand Down Expand Up @@ -538,14 +541,10 @@ function finishSchema(
out.nullable = true
loose = true
}
// Only null matches it. 3.0 admits null only through `nullable`, which
// needs a `type` beside it, and code generators drop a bare `enum: [null]`.
// `enum` is set again to follow them.
// Only null matches it. `enum` is set again to follow `type` and `nullable`.
if (out.type === undefined && isOnlyNull(out.enum)) {
delete out.enum
out.type = 'string'
out.nullable = true
out.enum = [null]
Object.assign(out, onlyNull())
}
// Code generators drop or leave untyped an `enum` with no `type`, as a
// `const` becomes, so it gets the type of its value.
Expand Down
5 changes: 3 additions & 2 deletions packages/downgrader/tests/v3.1-to-v3.0.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,9 @@ describe('downgradeSchemaV31ToV30', () => {
).toEqual({
maxLength: 3,
anyOf: [
{ type: 'array', items: { type: 'number' }, nullable: true },
{ type: 'string', nullable: true },
{ type: 'array', items: { type: 'number' } },
{ type: 'string' },
{ type: 'string', nullable: true, enum: [null] },
],
})
})
Expand Down
Loading