diff --git a/.eslintrc.json b/.eslintrc.json index 1a0e1b2f..e53198e2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -41,6 +41,7 @@ "RESTAPIMessageReference", "RESTAPIPartialCurrentUserGuild", "RESTAPIPoll", + "RESTOAuth2TokenOptionalClientCredentials", "RESTOAuth2AdvancedBotAuthorizationQuery", "RESTOAuth2AdvancedBotAuthorizationQueryResult", diff --git a/deno/rest/v10/oauth2.ts b/deno/rest/v10/oauth2.ts index b3e0a92a..e9582951 100644 --- a/deno/rest/v10/oauth2.ts +++ b/deno/rest/v10/oauth2.ts @@ -62,15 +62,20 @@ export interface RESTPostOAuth2AuthorizationQueryResult { export type RESTOAuth2AuthorizationQueryResult = RESTPostOAuth2AuthorizationQueryResult; /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-redirect-url-example} */ -export interface RESTPostOAuth2AccessTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2AccessTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'authorization_code'; code: string; redirect_uri?: string; -} +}; + +export type RESTOAuth2TokenOptionalClientCredentials = + | { client_id: Snowflake; client_secret: string } + | { client_id?: never; client_secret?: never }; /** * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-access-token-response} @@ -84,14 +89,15 @@ export interface RESTPostOAuth2AccessTokenResult { } /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-refresh-token-exchange-example} */ -export interface RESTPostOAuth2RefreshTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2RefreshTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'refresh_token'; refresh_token: string; -} +}; export type RESTPostOAuth2RefreshTokenResult = RESTPostOAuth2AccessTokenResult; diff --git a/deno/rest/v9/oauth2.ts b/deno/rest/v9/oauth2.ts index 9ccdf864..2a8f2d88 100644 --- a/deno/rest/v9/oauth2.ts +++ b/deno/rest/v9/oauth2.ts @@ -62,15 +62,20 @@ export interface RESTPostOAuth2AuthorizationQueryResult { export type RESTOAuth2AuthorizationQueryResult = RESTPostOAuth2AuthorizationQueryResult; /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-redirect-url-example} */ -export interface RESTPostOAuth2AccessTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2AccessTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'authorization_code'; code: string; redirect_uri?: string; -} +}; + +export type RESTOAuth2TokenOptionalClientCredentials = + | { client_id: Snowflake; client_secret: string } + | { client_id?: never; client_secret?: never }; /** * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-access-token-response} @@ -84,14 +89,15 @@ export interface RESTPostOAuth2AccessTokenResult { } /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-refresh-token-exchange-example} */ -export interface RESTPostOAuth2RefreshTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2RefreshTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'refresh_token'; refresh_token: string; -} +}; export type RESTPostOAuth2RefreshTokenResult = RESTPostOAuth2AccessTokenResult; diff --git a/rest/v10/oauth2.ts b/rest/v10/oauth2.ts index 0ab85f31..be7a6eef 100644 --- a/rest/v10/oauth2.ts +++ b/rest/v10/oauth2.ts @@ -62,15 +62,20 @@ export interface RESTPostOAuth2AuthorizationQueryResult { export type RESTOAuth2AuthorizationQueryResult = RESTPostOAuth2AuthorizationQueryResult; /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-redirect-url-example} */ -export interface RESTPostOAuth2AccessTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2AccessTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'authorization_code'; code: string; redirect_uri?: string; -} +}; + +export type RESTOAuth2TokenOptionalClientCredentials = + | { client_id: Snowflake; client_secret: string } + | { client_id?: never; client_secret?: never }; /** * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-access-token-response} @@ -84,14 +89,15 @@ export interface RESTPostOAuth2AccessTokenResult { } /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-refresh-token-exchange-example} */ -export interface RESTPostOAuth2RefreshTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2RefreshTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'refresh_token'; refresh_token: string; -} +}; export type RESTPostOAuth2RefreshTokenResult = RESTPostOAuth2AccessTokenResult; diff --git a/rest/v9/oauth2.ts b/rest/v9/oauth2.ts index fe731b26..9949c818 100644 --- a/rest/v9/oauth2.ts +++ b/rest/v9/oauth2.ts @@ -62,15 +62,20 @@ export interface RESTPostOAuth2AuthorizationQueryResult { export type RESTOAuth2AuthorizationQueryResult = RESTPostOAuth2AuthorizationQueryResult; /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-redirect-url-example} */ -export interface RESTPostOAuth2AccessTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2AccessTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'authorization_code'; code: string; redirect_uri?: string; -} +}; + +export type RESTOAuth2TokenOptionalClientCredentials = + | { client_id: Snowflake; client_secret: string } + | { client_id?: never; client_secret?: never }; /** * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-access-token-response} @@ -84,14 +89,15 @@ export interface RESTPostOAuth2AccessTokenResult { } /** + * @remarks + * This endpoint requires either HTTP Basic authentication using `client_id:client_secret`, + * or the `client_id` and `client_secret` must be provided in the form body. * @see {@link https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-refresh-token-exchange-example} */ -export interface RESTPostOAuth2RefreshTokenURLEncodedData { - client_id: Snowflake; - client_secret: string; +export type RESTPostOAuth2RefreshTokenURLEncodedData = RESTOAuth2TokenOptionalClientCredentials & { grant_type: 'refresh_token'; refresh_token: string; -} +}; export type RESTPostOAuth2RefreshTokenResult = RESTPostOAuth2AccessTokenResult; diff --git a/tests/v10/oauth2.ts b/tests/v10/oauth2.ts index b0991022..b89e9512 100644 --- a/tests/v10/oauth2.ts +++ b/tests/v10/oauth2.ts @@ -1,4 +1,10 @@ -import type { OAuth2Scopes, RESTOAuth2BotAuthorizationQuery, RESTOAuth2AdvancedBotAuthorizationQuery } from '../../v10'; +import type { + OAuth2Scopes, + RESTOAuth2BotAuthorizationQuery, + RESTOAuth2AdvancedBotAuthorizationQuery, + RESTPostOAuth2AccessTokenURLEncodedData, + RESTPostOAuth2RefreshTokenURLEncodedData, +} from '../../v10'; import { expectAssignable, expectNotAssignable } from '../__utils__/type-assertions'; declare const validBotScope: @@ -22,3 +28,63 @@ expectNotAssignable(invalidBotScope); expectAssignable(validBotScope); // @ts-expect-error - invalid scope expectNotAssignable(invalidBotScope); + +{ + expectAssignable({ + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); + + expectAssignable({ + client_id: '123456789', + client_secret: 'very secret', + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); + + // @ts-expect-error - client_secret is missing + expectNotAssignable({ + client_id: '123456789', + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); + + // @ts-expect-error - client_id is missing + expectNotAssignable({ + client_secret: 'very secret', + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); +} + +{ + expectAssignable({ + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); + + expectAssignable({ + client_id: '123456789', + client_secret: 'very secret', + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); + + // @ts-expect-error - client_secret is missing + expectNotAssignable({ + client_id: '123456789', + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); + + // @ts-expect-error - client_id is missing + expectNotAssignable({ + client_secret: 'very secret', + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); +} diff --git a/tests/v9/oauth2.ts b/tests/v9/oauth2.ts index d5b613d0..5e0828f9 100644 --- a/tests/v9/oauth2.ts +++ b/tests/v9/oauth2.ts @@ -1,4 +1,10 @@ -import type { OAuth2Scopes, RESTOAuth2BotAuthorizationQuery, RESTOAuth2AdvancedBotAuthorizationQuery } from '../../v9'; +import type { + OAuth2Scopes, + RESTOAuth2BotAuthorizationQuery, + RESTOAuth2AdvancedBotAuthorizationQuery, + RESTPostOAuth2AccessTokenURLEncodedData, + RESTPostOAuth2RefreshTokenURLEncodedData, +} from '../../v9'; import { expectAssignable, expectNotAssignable } from '../__utils__/type-assertions'; declare const validBotScope: @@ -20,3 +26,62 @@ expectNotAssignable(invalidBotScope); expectAssignable(validBotScope); // @ts-expect-error - invalid scope expectNotAssignable(invalidBotScope); +{ + expectAssignable({ + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); + + expectAssignable({ + client_id: '123456789', + client_secret: 'very secret', + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); + + // @ts-expect-error - client_secret is missing + expectNotAssignable({ + client_id: '123456789', + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); + + // @ts-expect-error - client_id is missing + expectNotAssignable({ + client_secret: 'very secret', + code: 'code', + grant_type: 'authorization_code', + redirect_uri: 'https://discord.com', + }); +} + +{ + expectAssignable({ + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); + + expectAssignable({ + client_id: '123456789', + client_secret: 'very secret', + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); + + // @ts-expect-error - client_secret is missing + expectNotAssignable({ + client_id: '123456789', + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); + + // @ts-expect-error - client_id is missing + expectNotAssignable({ + client_secret: 'very secret', + grant_type: 'refresh_token', + refresh_token: 'a real token this is', + }); +}