fix(openapi): flatten nullable unions to avoid nested anyOf/oneOf

This commit is contained in:
Hampus Kraft 2026-02-17 14:06:58 +00:00
parent 2db02ec255
commit b227bd0a85
No known key found for this signature in database
GPG Key ID: 6090864C465A454D
8 changed files with 131 additions and 102 deletions

View File

@ -30215,7 +30215,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DiscoveryApplicationResponse"
"$ref": "#/components/schemas/DiscoveryStatusResponse"
}
}
}
@ -30326,7 +30326,7 @@
"title": "Get discovery status"
}
},
"description": "Get the current discovery status of a guild. Requires MANAGE_GUILD permission.",
"description": "Get the current discovery status and eligibility of a guild. Requires MANAGE_GUILD permission.",
"security": [
{
"sessionToken": []
@ -60261,6 +60261,7 @@
"DISCOVERY_APPLICATION_ALREADY_REVIEWED",
"DISCOVERY_APPLICATION_NOT_FOUND",
"DISCOVERY_DESCRIPTION_REQUIRED",
"DISCOVERY_DISABLED",
"DISCOVERY_INSUFFICIENT_MEMBERS",
"DISCOVERY_INVALID_CATEGORY",
"DISCOVERY_NOT_DISCOVERABLE",
@ -60543,6 +60544,7 @@
"This discovery application has already been reviewed",
"Discovery application not found",
"A description is required for discovery",
"",
"Community does not meet the minimum member count for discovery",
"Invalid discovery category",
"This community is not listed in discovery",
@ -67236,18 +67238,14 @@
"description": "The slot index"
},
"user_id": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"$ref": "#/components/schemas/SnowflakeType"
},
{
"type": "string",
"enum": [
"-1"
]
}
"$ref": "#/components/schemas/SnowflakeType"
},
{
"type": "string",
"enum": [
"-1"
]
},
{
@ -67302,18 +67300,14 @@
"description": "Slot index to reserve (must be >= 1)"
},
"user_id": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"$ref": "#/components/schemas/SnowflakeType"
},
{
"type": "string",
"enum": [
"-1"
]
}
"$ref": "#/components/schemas/SnowflakeType"
},
{
"type": "string",
"enum": [
"-1"
]
},
{
@ -75272,6 +75266,34 @@
}
}
},
"DiscoveryStatusResponse": {
"type": "object",
"properties": {
"application": {
"anyOf": [
{
"$ref": "#/components/schemas/DiscoveryApplicationResponse"
},
{
"type": "null"
}
],
"description": "Current discovery application, if any"
},
"eligible": {
"type": "boolean",
"description": "Whether the guild meets the requirements to apply for discovery"
},
"min_member_count": {
"type": "number",
"description": "Minimum member count required for discovery eligibility"
}
},
"required": [
"eligible",
"min_member_count"
]
},
"GuildEmojiResponse": {
"type": "object",
"properties": {
@ -81069,20 +81091,16 @@
"type": "object",
"properties": {
"end_time": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
}
]
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
},
{
"type": "null"
@ -81147,20 +81165,16 @@
"type": "object",
"properties": {
"end_time": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
}
]
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
},
{
"type": "null"
@ -81213,20 +81227,16 @@
"type": "object",
"properties": {
"end_time": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
}
]
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
},
{
"type": "null"
@ -82889,20 +82899,16 @@
"$ref": "#/components/schemas/UserStatusType"
},
"status_resets_at": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
}
]
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
},
{
"type": "null"
@ -83179,20 +83185,16 @@
"description": "Custom status text (max 128 characters)"
},
"expires_at": {
"anyOf": [
"oneOf": [
{
"oneOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
}
]
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?$"
},
{
"type": "integer",
"minimum": 0,
"maximum": 8640000000000000,
"format": "int64"
},
{
"type": "null"

View File

@ -648,7 +648,6 @@ description: 'Admin object schemas from the Fluxer API.'
**Related endpoints**
- [`GET /admin/discovery/applications`](/api-reference/admin/list-discovery-applications)
- [`GET /guilds/{guild_id}/discovery`](/api-reference/discovery/get-discovery-status)
- [`POST /admin/discovery/applications/{guild_id}/approve`](/api-reference/admin/approve-discovery-application)
- [`POST /admin/discovery/applications/{guild_id}/reject`](/api-reference/admin/reject-discovery-application)
- [`POST /admin/discovery/guilds/{guild_id}/remove`](/api-reference/admin/remove-guild-from-discovery)
@ -2152,7 +2151,7 @@ Type: [MessageShredStatusNotFoundResponse](#messageshredstatusnotfoundresponse)
| Field | Type | Description |
|-------|------|-------------|
| slot_index | integer (int32) | Slot index to reserve (must be >= 1) |
| user_id | ?[SnowflakeType](#snowflaketype) \| enum<`-1`> | User ID to reserve the slot for, or null to unreserve (special value -1 is also valid) |
| user_id | [SnowflakeType](#snowflaketype) \| enum<`-1`> \| null | User ID to reserve the slot for, or null to unreserve (special value -1 is also valid) |
<a id="resolvereportrequest"></a>

View File

@ -167,6 +167,20 @@ Type: [DiscoveryCategoryResponse](#discoverycategoryresponse)[]
| online_count | number | Approximate online member count |
| verification_level | number | Verification level |
<a id="discoverystatusresponse"></a>
## DiscoveryStatusResponse
**Related endpoints**
- [`GET /guilds/{guild_id}/discovery`](/api-reference/discovery/get-discovery-status)
| Field | Type | Description |
|-------|------|-------------|
| application? | ?[DiscoveryApplicationResponse](#discoveryapplicationresponse) | Current discovery application, if any |
| eligible | boolean | Whether the guild meets the requirements to apply for discovery |
| min_member_count | number | Minimum member count required for discovery eligibility |
<a id="donationcheckoutrequest"></a>
## DonationCheckoutRequest

View File

@ -68,7 +68,7 @@ Type: [ApplicationResponse](#applicationresponse)[]
|-------|------|-------------|
| bot | ?[ApplicationBotResponse](#applicationbotresponse) | The bot user associated with the application |
| bot_public | boolean | Whether the bot can be invited by anyone |
| description | null | The description of the application |
| description | ?string | The description of the application |
| icon | ?string | The icon hash of the application |
| id | [SnowflakeType](#snowflaketype) | The unique identifier of the application |
| name | string | The name of the application |
@ -109,9 +109,9 @@ Type: [ApplicationResponse](#applicationresponse)[]
| bot? | [ApplicationBotResponse](#applicationbotresponse) | |
| bot_public | boolean | Whether the bot can be invited by anyone |
| bot_require_code_grant | boolean | Whether the bot requires OAuth2 code grant |
| description | null | The description of the application |
| description | ?string | The description of the application |
| flags | [ApplicationFlags](#applicationflags) | |
| icon | null | The icon hash of the application |
| icon | ?string | The icon hash of the application |
| id | [SnowflakeType](#snowflaketype) | The unique identifier of the application |
| name | string | The name of the application |
@ -381,7 +381,7 @@ The application that was authorized
| Field | Type | Description |
|-------|------|-------------|
| bot_public | boolean | Whether the bot can be invited by anyone |
| description | null | The description of the application |
| description | ?string | The description of the application |
| icon | ?string | The icon hash of the application |
| id | [SnowflakeType](#snowflaketype) | The unique identifier of the application |
| name | string | The name of the application |
@ -396,9 +396,9 @@ The application associated with the token
|-------|------|-------------|
| bot_public | boolean | Whether the bot can be invited by anyone |
| bot_require_code_grant | boolean | Whether the bot requires OAuth2 code grant |
| description | null | The description of the application |
| description | ?string | The description of the application |
| flags | [ApplicationFlags](#applicationflags) | |
| icon | null | The icon hash of the application |
| icon | ?string | The icon hash of the application |
| id | [SnowflakeType](#snowflaketype) | The unique identifier of the application |
| name | string | The name of the application |

View File

@ -22,7 +22,7 @@ Resource tables use a compact notation:
- [Auth](/resources/auth) (37 schemas)
- [Billing](/resources/billing) (3 schemas)
- [Channels](/resources/channels) (66 schemas)
- [Common](/resources/common) (34 schemas)
- [Common](/resources/common) (35 schemas)
- [Gateway](/resources/gateway) (2 schemas)
- [Gifts](/resources/gifts) (1 schemas)
- [Guilds](/resources/guilds) (63 schemas)
@ -163,6 +163,7 @@ Resource tables use a compact notation:
- [DiscoveryCategoryResponse](/resources/common#discoverycategoryresponse)
- [DiscoveryGuildListResponse](/resources/common#discoveryguildlistresponse)
- [DiscoveryGuildResponse](/resources/common#discoveryguildresponse)
- [DiscoveryStatusResponse](/resources/common#discoverystatusresponse)
- [DonationCheckoutRequest](/resources/common#donationcheckoutrequest)
- [DonationCheckoutResponse](/resources/common#donationcheckoutresponse)
- [DonationRequestLinkRequest](/resources/common#donationrequestlinkrequest)

View File

@ -26,7 +26,7 @@ description: 'Premium object schemas from the Fluxer API.'
| Field | Type | Description |
|-------|------|-------------|
| slot_index | integer (int32) | The slot index |
| user_id | ?[SnowflakeType](#snowflaketype) \| enum&lt;`-1`&gt; | User ID that reserved this slot, or null if unreserved (special value -1 is also valid) |
| user_id | [SnowflakeType](#snowflaketype) \| enum&lt;`-1`&gt; \| null | User ID that reserved this slot, or null if unreserved (special value -1 is also valid) |
<a id="priceidsresponsecurrency"></a>

View File

@ -24,7 +24,7 @@ description: 'Users object schemas from the Fluxer API.'
|-------|------|-------------|
| emoji_id? | ?[SnowflakeType](#snowflaketype) | ID of custom emoji to display |
| emoji_name? | ?string | Unicode emoji or custom emoji name |
| expires_at? | ?string \| integer (int64) | When the custom status expires |
| expires_at? | string \| integer (int64) \| null | When the custom status expires |
| text? | ?string | Custom status text (max 128 characters) |
<a id="disabletotprequest"></a>
@ -1186,7 +1186,7 @@ Category of the user report
| render_spoilers? | [RenderSpoilers](#renderspoilers) | Spoiler rendering preference |
| restricted_guilds? | [SnowflakeType](#snowflaketype)[] | Guilds with DM restrictions |
| status? | [UserStatusType](#userstatustype) | |
| status_resets_at? | ?string \| integer (int64) | When status resets |
| status_resets_at? | string \| integer (int64) \| null | When status resets |
| status_resets_to? | ?[UserStatusType](#userstatustype) | |
| theme? | [UserThemeType](#userthemetype) | |
| time_format? | [TimeFormatTypes](#timeformattypes) | Time format preference |
@ -1394,7 +1394,7 @@ Guild mute configuration
| Field | Type | Description |
|-------|------|-------------|
| end_time? | ?string \| integer (int64) | When the mute expires |
| end_time? | string \| integer (int64) \| null | When the mute expires |
| selected_time_window | integer (int53) | Selected mute duration |
<a id="userprivateresponsependingbulkmessagedeletion"></a>

View File

@ -1017,6 +1017,19 @@ function isOpenAPISchema(schema: OpenAPISchemaOrRef): schema is OpenAPISchema {
}
function makeNullableSchema(inner: OpenAPISchemaOrRef): OpenAPISchema {
if (isOpenAPISchema(inner)) {
const keys = Object.keys(inner).filter((k) => k !== 'description');
if (inner.oneOf && keys.length === 1) {
const result: OpenAPISchema = {oneOf: [...inner.oneOf, {type: 'null'}]};
if (inner.description) result.description = inner.description;
return result;
}
if (inner.anyOf && keys.length === 1) {
const result: OpenAPISchema = {anyOf: [...inner.anyOf, {type: 'null'}]};
if (inner.description) result.description = inner.description;
return result;
}
}
return {
anyOf: [inner, {type: 'null'}],
};