diff --git a/packages/downgrader/README.md b/packages/downgrader/README.md index f9cff55..3a3c118 100644 --- a/packages/downgrader/README.md +++ b/packages/downgrader/README.md @@ -280,7 +280,7 @@ Accepts the default OAS dialect, which adds `discriminator`, `xml`, `externalDoc - OpenAPI Generator's Java client with the `native` or `jersey3` library coerces scalars while it reads a `oneOf`, and wants exactly one branch to match, so it rejects a value that two branches take once coerced, such as `1` or `"1"` against the `oneOf` that `string | number` becomes, or `true` against `string | boolean`. It also rejects null in a tuple member that may be null, as in `z.tuple([z.number(), z.string().nullable()])`, since that null sits in a branch of the `anyOf` that `items` becomes. Its Java clients and Spring server, and its C# client with the default `generichost` library, also write an enum that does not compile for `{ type: "null" }` alone, as Zod's `z.null()` writes for a property, an array item or a component, and its Python FastAPI server does for such a component. With the Java `native` or the C# `generichost` library, a union with a `contentEncoding: base64` string branch does not compile either, since they name the member for that branch, now `format: byte`, `getbyte[]` or `Byte[]`. OpenAPI Generator reads 3.1 too, which keeps the `type` list or `anyOf` and `{ type: "null" }`, leaves `prefixItems` untyped, and reads `contentEncoding` as a plain string. - datamodel-code-generator reads a required property with `nullable: true` as never null. Pass `--strict-nullable` to keep null. Even then, it leaves null out of an array item or map value that is a nullable array or record, such as Zod's `z.array(z.array(z.string()).nullable())`. It reads 3.1 too, which keeps the `"null"` type. It also makes a discriminator's tag property required when the tag is a one-value `enum` with a `default`, as a `const` with a `default` becomes, such as Pydantic's `Literal["a"] = "a"` in a tagged union. From 3.1's `const` it keeps the `default`, as it does with `--enum-field-as-literal one`. - aiopenapi3 fails to load a 3.0 document that holds the `"null"` branch: it takes `null` out of a nullable `enum` and builds an empty `Literal` from what is left. aiopenapi3 reads 3.1 too, which keeps `{ type: "null" }`. -- oapi-codegen 2.8 rejects, and the OpenAPI Generator C# client breaks on, a string enum with a `format` such as `uuid`, which a `const` with a `format` becomes, as ArkType writes for `string.uuid`. oapi-codegen also stops on a `oneOf` that holds the `"null"` branch beside a `discriminator` with a `mapping`, as typia writes a nullable tagged union, since it wants every branch other than `{ type: "null" }` there to be a `$ref`. It reads 3.1 too, which keeps `{ type: "null" }` there. It also stops on a number, integer or boolean enum with null that is a parameter, or a property of an object written inline in an operation, such as `{ type: "integer", nullable: true, enum: [1, 2, null] }`, which an `enum` with null and no `type` becomes, as Zod writes `z.literal([1, 2, null])`. In 3.1 that `enum` keeps no `type`, which oapi-codegen reads. +- oapi-codegen 2.8 rejects, and the OpenAPI Generator C# client breaks on, a string enum with a `format` such as `uuid`, which a `const` with a `format` becomes, as ArkType writes for `string.uuid`. oapi-codegen also stops on a `oneOf` that holds the `"null"` branch beside a `discriminator` with a `mapping`, as typia writes a nullable tagged union, since it wants every branch other than `{ type: "null" }` there to be a `$ref`. It reads 3.1 too, which keeps `{ type: "null" }` there. It also stops on a number, integer or boolean enum with null that is a parameter, or a property of an object written inline in an operation, such as `{ type: "integer", nullable: true, enum: [1, 2, null] }`, which an `enum` with null and no `type` becomes, as Zod writes `z.literal([1, 2, null])`. In 3.1 that `enum` keeps no `type`, which oapi-codegen reads. Its generated server reads a parameter that is a `oneOf`, as a nullable `$ref` or enum becomes, such as Zod's `z.enum(["x", "y"]).nullable()`, into a union with no accessor, so it leaves a query parameter unset and rejects a header parameter with a 400. Its 3.1 reading binds the `anyOf` as the type itself. - Validators that coerce a value to each branch's `type`, as Prism, express-openapi-validator and openapi-backend do for parameters, and Fastify and Ruby's committee (through openapi_parser) by default for bodies too, match a value such as `1` or `"1"` to two branches of the `oneOf` a union of scalar types becomes, and reject it. So a query flag that takes `"true"`, `"false"`, `"0"`, `"1"` or a boolean, as GrowthBook writes, rejects `?flag=true`, since `"true"` matches the string and, coerced, the boolean. Fastify by default also wraps a value in an array, so it rejects a single value, and an array of one item, against the `oneOf` a union of a scalar type and an array becomes, as for `string | string[]`. It also coerces in place, so a branch of a `oneOf` can change the value that later branches and the handler see. A number in Effect's `Schema.Number`, a `oneOf` of a number and a string enum, arrives as a string, and null in a nullable enum, a nullable `$ref` to an enum, or a nullable union of literals becomes a value such as `""`, which the `"null"` branch rejects where 3.1's `{ type: "null" }` turns it back into null. Prism, express-openapi-validator, openapi-backend and fastify-openapi-glue read 3.1 too, which keeps the `type` list or the `anyOf`. - kin-openapi's request validation (`openapi3filter`, which oapi-codegen's validator middleware wraps) decodes a parameter value (query, path, header or cookie) or a field of a form-encoded body with each branch of a `oneOf` and keeps the value of the last branch that decodes it. The `"null"` branch decodes any value as a string, so where it comes last, as Zod writes it, a parameter or field whose other branches take no string rejects every value, such as `?prio=5` against the `oneOf` that a nullable `$ref` to a number or integer schema or a number enum becomes, as for Zod's `.nullable()` on such a schema with its own id, or a nullable union of a number and a boolean. kin-openapi reads 3.1 too, which keeps the `anyOf`, where the first branch that decodes the value wins. In a `multipart/form-data` body it reads a text part whose schema has no `type` as null, so a part whose schema is a `type` list without `"null"`, such as `["string", "integer"]`, which becomes a `oneOf` in 3.0, rejects every value (with `"null"` in the list, the null branch takes that null). - Kiota reads the `"null"` branch's `type: "string"` as a real type, so array items that may be null, and a union of several types with null, come out as strings. It also skips a `oneOf` or `anyOf` branch that is an `allOf` holding a `$ref`, as a `$ref` with siblings becomes, other than one with only annotations beside a `discriminator` or to a schema with one, so a nullable `$ref` with a `description`, such as Zod's `.describe()` on a schema with its own id before `.nullable()`, comes out as an enum holding only Kiota's null sentinel, and a union of such branches as `UntypedNode` or as its other branches alone. Its TypeScript client reads every value of a `oneOf` of objects with the first branch, so it drops the tag of a value from any other branch, since `const` becomes a one-value `enum` that the first branch rejects, as for Zod's `z.discriminatedUnion()`. It also reads an array of `format: byte` strings, which an array of `contentEncoding: base64` strings such as `z.array(z.base64())` becomes, as one byte array, so it drops the array, and its C# client throws on it. Kiota reads 3.1 too, which keeps their types and the `$ref` beside its siblings, and reads `const` and `contentEncoding` strings as plain strings.