From 5a37923a9c63189159b624cfe5175ab42117fd4a Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sat, 12 Oct 2024 11:59:49 -0400 Subject: [PATCH 1/4] refactor: simplify authorization API --- README.md | 17 ++++------------ package.json | 2 +- src/achievement/getAchievementUnlocks.ts | 9 ++++----- src/console/getConsoleIds.ts | 7 +++---- src/console/getGameList.ts | 7 +++---- src/feed/getAchievementOfTheWeek.ts | 7 +++---- src/feed/getActiveClaims.ts | 7 +++---- src/feed/getClaims.ts | 21 ++++++++++++++++++-- src/feed/getRecentGameAwards.ts | 7 +++---- src/feed/getTopTenUsers.ts | 7 +++---- src/game/getAchievementCount.ts | 7 +++---- src/game/getAchievementDistribution.ts | 7 +++---- src/game/getGame.ts | 7 +++---- src/game/getGameExtended.ts | 7 +++---- src/game/getGameRankAndScore.ts | 7 +++---- src/game/getGameRating.ts | 7 +++---- src/ticket/getTicketData.ts | 19 +++++++++--------- src/user/getAchievementsEarnedBetween.ts | 7 +++---- src/user/getAchievementsEarnedOnDay.ts | 7 +++---- src/user/getGameInfoAndUserProgress.ts | 7 +++---- src/user/getUserAwards.ts | 7 +++---- src/user/getUserClaims.ts | 7 +++---- src/user/getUserCompletedGames.ts | 7 +++---- src/user/getUserCompletionProgress.ts | 7 +++---- src/user/getUserGameRankAndScore.ts | 7 +++---- src/user/getUserPoints.ts | 7 +++---- src/user/getUserProfile.ts | 7 +++---- src/user/getUserProgress.ts | 7 +++---- src/user/getUserRecentAchievements.ts | 7 +++---- src/user/getUserRecentlyPlayedGames.ts | 7 +++---- src/user/getUserSummary.ts | 7 +++---- src/utils/internal/buildRequestUrl.test.ts | 4 ++-- src/utils/internal/buildRequestUrl.ts | 14 +++++++------ src/utils/public/buildAuthorization.ts | 6 ++++-- src/utils/public/models/auth-object.model.ts | 12 ++++++++--- 35 files changed, 138 insertions(+), 148 deletions(-) diff --git a/README.md b/README.md index 7a75baa..5b5f1b2 100644 --- a/README.md +++ b/README.md @@ -45,29 +45,20 @@ Learn how to authenticate and start pulling data from RetroAchievements on our d To use any endpoint function in the API, you must first be authorized by RetroAchievements. Fortunately, this is a fairly straightforward process. -1. Visit [your control panel](https://retroachievements.org/controlpanel.php) on the RA website. +1. Visit [settings page](https://retroachievements.org/settings) on the RA website. 2. Find the "Keys" section on the page. Copy the web API key value. **Do not expose your API key anywhere publicly.** -3. You can now create your authorization object using your web API key. +3. You now have all you need to use any function from the API. Each function takes this web API key as its first argument. Here's an example: ```ts -import { buildAuthorization } from "@retroachievements/api"; +import { getGame } from "@retroachievements/api"; -const username = ""; const webApiKey = ""; -const authorization = buildAuthorization({ username, webApiKey }); -``` - -4. You now have all you need to use any function in the API. Each function takes this authorization object as its first argument. Here's an example: - -```ts -import { getGame } from "@retroachievements/api"; - // This returns basic metadata about the game on this page: // https://retroachievements.org/game/14402 -const game = await getGame(authorization, { gameId: 14402 }); +const game = await getGame(webApiKey, { gameId: 14402 }); ``` ## API diff --git a/package.json b/package.json index e6d23cd..b67f4f6 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "format:check": "prettier --check . '**/*.{json,md,js,ts,tsx}'", "lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .", "lint:fix": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx . --fix", - "test": "vitest run", + "test": "vitest run --reporter=dot", "test:watch": "vitest", "test:coverage": "vitest run --coverage", "verify": "pnpm format:check && pnpm lint && pnpm test:coverage && pnpm build", diff --git a/src/achievement/getAchievementUnlocks.ts b/src/achievement/getAchievementUnlocks.ts index 34e0141..a824a2d 100644 --- a/src/achievement/getAchievementUnlocks.ts +++ b/src/achievement/getAchievementUnlocks.ts @@ -5,7 +5,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { AchievementUnlocksMetadata, GetAchievementUnlocksResponse, @@ -15,8 +15,7 @@ import type { * A call to this function will retrieve a list of users who * have earned a given achievement, targeted by the achievement's ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.achievementId The target achievement we want to * retrieve the unlocks list for. If unknown, this can be found @@ -31,7 +30,7 @@ import type { * @example * ``` * const achievementUnlocks = await getAchievementUnlocks( - * authorization, + * webApiKey, * { achievementId: 13876 } * ); * ``` @@ -50,7 +49,7 @@ import type { * ``` */ export const getAchievementUnlocks = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { achievementId: ID; offset?: number; count?: number } ): Promise => { const { achievementId, offset, count } = payload; diff --git a/src/console/getConsoleIds.ts b/src/console/getConsoleIds.ts index e120dce..9b6b155 100644 --- a/src/console/getConsoleIds.ts +++ b/src/console/getConsoleIds.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { FetchedSystem, GetConsoleIdsResponse } from "./models"; /** @@ -12,8 +12,7 @@ import type { FetchedSystem, GetConsoleIdsResponse } from "./models"; * of console ID and name pairs on the RetroAchievements.org * platform. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.shouldOnlyRetrieveActiveSystems If true, only systems that * officially support achievements will be returned. @@ -39,7 +38,7 @@ import type { FetchedSystem, GetConsoleIdsResponse } from "./models"; * ``` */ export const getConsoleIds = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload?: { shouldOnlyRetrieveActiveSystems: boolean; shouldOnlyRetrieveGameSystems: boolean; diff --git a/src/console/getGameList.ts b/src/console/getGameList.ts index c5c761a..2fd077d 100644 --- a/src/console/getGameList.ts +++ b/src/console/getGameList.ts @@ -5,15 +5,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GameList, GetGameListResponse } from "./models"; /** * A call to this function will retrieve the complete list * of games for a specified console on the RetroAchievements.org * platform. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.consoleId The unique console ID to retrieve a list of * games from. The list of consoleIds can be retrieved using the `getConsoleIds()` @@ -53,7 +52,7 @@ import type { GameList, GetGameListResponse } from "./models"; * ``` */ export const getGameList = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { consoleId: ID; shouldOnlyRetrieveGamesWithAchievements?: boolean; diff --git a/src/feed/getAchievementOfTheWeek.ts b/src/feed/getAchievementOfTheWeek.ts index d22dba0..85ebb20 100644 --- a/src/feed/getAchievementOfTheWeek.ts +++ b/src/feed/getAchievementOfTheWeek.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { AchievementOfTheWeek, GetAchievementOfTheWeekResponse, @@ -14,8 +14,7 @@ import type { * A call to this function will retrieve comprehensive * metadata about the current Achievement of the Week. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @example * ``` @@ -59,7 +58,7 @@ import type { * ``` */ export const getAchievementOfTheWeek = async ( - authorization: AuthObject + authorization: ApiAuthorization ): Promise => { const url = buildRequestUrl( apiBaseUrl, diff --git a/src/feed/getActiveClaims.ts b/src/feed/getActiveClaims.ts index ab9bac9..77f89bc 100644 --- a/src/feed/getActiveClaims.ts +++ b/src/feed/getActiveClaims.ts @@ -4,15 +4,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetSetClaimsResponse, SetClaim } from "./models"; /** * A call to this function returns information about all * (1000 max) active set claims. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @example * ``` @@ -45,7 +44,7 @@ import type { GetSetClaimsResponse, SetClaim } from "./models"; * ``` */ export const getActiveClaims = async ( - authorization: AuthObject + authorization: ApiAuthorization ): Promise => { const url = buildRequestUrl( apiBaseUrl, diff --git a/src/feed/getClaims.ts b/src/feed/getClaims.ts index 69b4548..f9e3e73 100644 --- a/src/feed/getClaims.ts +++ b/src/feed/getClaims.ts @@ -4,13 +4,30 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetSetClaimsResponse, SetClaim } from "./models"; type ClaimKind = "completed" | "dropped" | "expired"; +/** + * A call to this function will retrieve a list of achievement set claims. + * + * @param authorization Your web API key retrieved from retroachievements.org/settings. + * + * @param payload.claimKind The specific kind of claims you'd like to retrieve a list of. + * + * @example + * ``` + * const claims = await getClaims( + * authorization, + * { claimKind: "completed" } + * ); + * ``` + * + * @returns An array containing all the specified claims. + */ export const getClaims = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { claimKind: ClaimKind } ): Promise => { const { claimKind } = payload; diff --git a/src/feed/getRecentGameAwards.ts b/src/feed/getRecentGameAwards.ts index 01ee1f7..e4933e4 100644 --- a/src/feed/getRecentGameAwards.ts +++ b/src/feed/getRecentGameAwards.ts @@ -4,15 +4,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject, AwardKind } from "../utils/public"; +import type { ApiAuthorization, AwardKind } from "../utils/public"; import type { GetRecentGameAwardsResponse, RecentGameAwards } from "./models"; /** * A call to this function will retrieve all recently granted game * awards across the site's userbase. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.startDate The date to fetch awards from. * @@ -50,7 +49,7 @@ import type { GetRecentGameAwardsResponse, RecentGameAwards } from "./models"; * ``` */ export const getRecentGameAwards = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload?: Partial<{ startDate: string; offset: number; diff --git a/src/feed/getTopTenUsers.ts b/src/feed/getTopTenUsers.ts index d7bad0a..1bd7d89 100644 --- a/src/feed/getTopTenUsers.ts +++ b/src/feed/getTopTenUsers.ts @@ -1,5 +1,5 @@ import { apiBaseUrl, buildRequestUrl, call } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetTopTenUsersResponse, TopTenUsers, @@ -10,8 +10,7 @@ import type { * A call to this function will retrieve the current top ten users * on the site. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @example * ``` @@ -28,7 +27,7 @@ import type { * ``` */ export const getTopTenUsers = async ( - authorization: AuthObject + authorization: ApiAuthorization ): Promise => { const url = buildRequestUrl( apiBaseUrl, diff --git a/src/game/getAchievementCount.ts b/src/game/getAchievementCount.ts index f952fb6..743ba62 100644 --- a/src/game/getAchievementCount.ts +++ b/src/game/getAchievementCount.ts @@ -5,15 +5,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { AchievementCount, GetAchievementCountResponse } from "./models"; /** * A call to this function will retrieve the list of * achievement IDs for a game, targeted by game ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -35,7 +34,7 @@ import type { AchievementCount, GetAchievementCountResponse } from "./models"; * ``` */ export const getAchievementCount = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID } ): Promise => { const { gameId } = payload; diff --git a/src/game/getAchievementDistribution.ts b/src/game/getAchievementDistribution.ts index 88acc26..134a36c 100644 --- a/src/game/getAchievementDistribution.ts +++ b/src/game/getAchievementDistribution.ts @@ -1,6 +1,6 @@ import type { ID } from "../utils/internal"; import { apiBaseUrl, buildRequestUrl, call } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { AchievementDistributionFlags, GetAchievementDistributionResponse, @@ -11,8 +11,7 @@ import type { * of the number of players who have earned a specific * number of achievements for a given game ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -57,7 +56,7 @@ import type { * ``` */ export const getAchievementDistribution = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID; flags?: AchievementDistributionFlags; diff --git a/src/game/getGame.ts b/src/game/getGame.ts index 4f2e6f7..23a95d6 100644 --- a/src/game/getGame.ts +++ b/src/game/getGame.ts @@ -5,15 +5,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { Game, GetGameResponse } from "./models"; /** * A call to this function will retrieve basic metadata about * a game, targeted via its unique ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -52,7 +51,7 @@ import type { Game, GetGameResponse } from "./models"; * ``` */ export const getGame = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID } ): Promise => { const { gameId } = payload; diff --git a/src/game/getGameExtended.ts b/src/game/getGameExtended.ts index 37da0b0..1ede090 100644 --- a/src/game/getGameExtended.ts +++ b/src/game/getGameExtended.ts @@ -5,15 +5,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GameExtended, GetGameExtendedResponse } from "./models"; /** * A call to this function will retrieve extended metadata * about a game, targeted via its unique ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -72,7 +71,7 @@ import type { GameExtended, GetGameExtendedResponse } from "./models"; * ``` */ export const getGameExtended = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID; isRequestingUnofficialAchievements?: boolean } ): Promise => { const { gameId, isRequestingUnofficialAchievements } = payload; diff --git a/src/game/getGameRankAndScore.ts b/src/game/getGameRankAndScore.ts index 7d8367d..564b985 100644 --- a/src/game/getGameRankAndScore.ts +++ b/src/game/getGameRankAndScore.ts @@ -5,7 +5,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GameRankAndScoreEntity, GetGameRankAndScoreResponse, @@ -17,8 +17,7 @@ import type { * points earners for a game. The game is targeted via * its unique ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -44,7 +43,7 @@ import type { * ``` */ export const getGameRankAndScore = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID; type: "latest-masters" | "high-scores" } ): Promise => { const { gameId, type } = payload; diff --git a/src/game/getGameRating.ts b/src/game/getGameRating.ts index a0dd400..b7073bb 100644 --- a/src/game/getGameRating.ts +++ b/src/game/getGameRating.ts @@ -5,15 +5,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GameRating, GetGameRatingResponse } from "./models"; /** * A call to this function will retrieve metadata about * how users have rated the game and its set. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -42,7 +41,7 @@ import type { GameRating, GetGameRatingResponse } from "./models"; * ``` */ export const getGameRating = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID } ): Promise => { const { gameId } = payload; diff --git a/src/ticket/getTicketData.ts b/src/ticket/getTicketData.ts index 98e5e39..90fc655 100644 --- a/src/ticket/getTicketData.ts +++ b/src/ticket/getTicketData.ts @@ -5,7 +5,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { AchievementTicketStats, GameTicketStats, @@ -51,7 +51,7 @@ interface GetTicketDataAllPayloadValues { * @returns An object containing metadata about a target ticket. */ export function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { ticketId: ID } ): Promise; @@ -76,7 +76,7 @@ export function getTicketData( * @returns A list of the most recently opened tickets on the site. */ export function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload?: Partial<{ offset: number; count: number }> ): Promise; @@ -104,7 +104,7 @@ export function getTicketData( * @returns A list of the most recently opened tickets on the site. */ export function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { isGettingMostTicketedGames: true; offset?: number; count?: number } ): Promise; @@ -129,7 +129,7 @@ export function getTicketData( * @returns An achievement developer's ticket stats. */ export function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string } ): Promise; @@ -160,7 +160,7 @@ export function getTicketData( * @returns A game's ticket stats, potentially also including the ticket list. */ export function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID; isGettingTicketsForUnofficialAchievements?: true; @@ -174,8 +174,7 @@ export function getTicketData( * of an achievement's ID, open its page on the RetroAchievements * website and copy the number at the end of the URL. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.achievementId The ID of the achievement to fetch ticket * stats for. @@ -191,7 +190,7 @@ export function getTicketData( * @returns An achievement developer's ticket stats. */ export function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { achievementId: ID } ): Promise; @@ -200,7 +199,7 @@ export function getTicketData( */ export async function getTicketData( - authorization: AuthObject, + authorization: ApiAuthorization, payload: GetTicketDataAllPayloadValues = {} ) { const queryParams = buildGetTicketDataQueryParams(payload); diff --git a/src/user/getAchievementsEarnedBetween.ts b/src/user/getAchievementsEarnedBetween.ts index a496b22..c9d9a1e 100644 --- a/src/user/getAchievementsEarnedBetween.ts +++ b/src/user/getAchievementsEarnedBetween.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { DatedUserAchievement, DatedUserAchievementsResponse, @@ -14,8 +14,7 @@ import type { * A call to this function will retrieve a list of achievements * earned by a given user between two provided dates. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the * list of achievements for. @@ -64,7 +63,7 @@ import type { * ``` */ export const getAchievementsEarnedBetween = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; fromDate: Date; toDate: Date } ): Promise => { const { username, fromDate, toDate } = payload; diff --git a/src/user/getAchievementsEarnedOnDay.ts b/src/user/getAchievementsEarnedOnDay.ts index 8867b8d..c512b57 100644 --- a/src/user/getAchievementsEarnedOnDay.ts +++ b/src/user/getAchievementsEarnedOnDay.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { DatedUserAchievement, DatedUserAchievementsResponse, @@ -14,8 +14,7 @@ import type { * A call to this function will retrieve a list of achievements * earned by a given user on a specified date. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the * list of achievements for. @@ -63,7 +62,7 @@ import type { * ``` */ export const getAchievementsEarnedOnDay = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; onDate: Date } ): Promise => { const { username, onDate } = payload; diff --git a/src/user/getGameInfoAndUserProgress.ts b/src/user/getGameInfoAndUserProgress.ts index c7a7b05..4a28071 100644 --- a/src/user/getGameInfoAndUserProgress.ts +++ b/src/user/getGameInfoAndUserProgress.ts @@ -5,7 +5,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GameInfoAndUserProgress, GetGameInfoAndUserProgressResponse, @@ -16,8 +16,7 @@ import type { * about a game, in addition to a user's progress about a game. * This is targeted via a game's unique ID and a given username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -89,7 +88,7 @@ import type { * ``` */ export const getGameInfoAndUserProgress = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID; username: string; diff --git a/src/user/getUserAwards.ts b/src/user/getUserAwards.ts index b45f9eb..bdf581f 100644 --- a/src/user/getUserAwards.ts +++ b/src/user/getUserAwards.ts @@ -4,15 +4,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserAwardsResponse, UserAwards } from "./models"; /** * A call to this function will retrieve metadata about the target user's * site awards, via their username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the site awards for. * @@ -52,7 +51,7 @@ import type { GetUserAwardsResponse, UserAwards } from "./models"; * ``` */ export const getUserAwards = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string } ): Promise => { const { username } = payload; diff --git a/src/user/getUserClaims.ts b/src/user/getUserClaims.ts index c4c4f71..400c37e 100644 --- a/src/user/getUserClaims.ts +++ b/src/user/getUserClaims.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserClaimsResponse, UserClaims } from "./models"; /** @@ -12,8 +12,7 @@ import type { GetUserClaimsResponse, UserClaims } from "./models"; * achievement set claims made over the lifetime of a given * user, targeted by their username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the historical * achievement set claims list for. @@ -30,7 +29,7 @@ import type { GetUserClaimsResponse, UserClaims } from "./models"; * made over the lifetime of the given user. */ export const getUserClaims = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string } ): Promise => { const { username } = payload; diff --git a/src/user/getUserCompletedGames.ts b/src/user/getUserCompletedGames.ts index e37679e..762a0b9 100644 --- a/src/user/getUserCompletedGames.ts +++ b/src/user/getUserCompletedGames.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserCompletedGamesResponse, UserCompletedGames, @@ -17,8 +17,7 @@ import type { * one for the hardcore completion. These are designated by * the `hardcoreMode` property on each completion object. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the * completion metadata for. @@ -62,7 +61,7 @@ import type { * ``` */ export const getUserCompletedGames = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string } ): Promise => { const { username } = payload; diff --git a/src/user/getUserCompletionProgress.ts b/src/user/getUserCompletionProgress.ts index a888035..5ca8aab 100644 --- a/src/user/getUserCompletionProgress.ts +++ b/src/user/getUserCompletionProgress.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserCompletionProgressResponse, UserCompletionProgress, @@ -14,8 +14,7 @@ import type { * A call to this function will retrieve a given user's completion * progress, targeted by their username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the progress for. * @@ -55,7 +54,7 @@ import type { * ``` */ export const getUserCompletionProgress = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; offset?: number; count?: number } ): Promise => { const { username, offset, count } = payload; diff --git a/src/user/getUserGameRankAndScore.ts b/src/user/getUserGameRankAndScore.ts index 77aabd6..2ed427b 100644 --- a/src/user/getUserGameRankAndScore.ts +++ b/src/user/getUserGameRankAndScore.ts @@ -5,7 +5,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserGameRankAndScoreResponse, UserGameRankAndScore, @@ -16,8 +16,7 @@ import type { * how a particular user has performed/ranked on a particular * game, targeted by game ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.gameId The unique game ID. If you are unsure, open the * game's page on the RetroAchievements.org website. For example, Dragster's @@ -50,7 +49,7 @@ import type { * ``` */ export const getUserGameRankAndScore = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { gameId: ID; username: string } ): Promise => { const { gameId, username } = payload; diff --git a/src/user/getUserPoints.ts b/src/user/getUserPoints.ts index 2b75e37..ccdba4f 100644 --- a/src/user/getUserPoints.ts +++ b/src/user/getUserPoints.ts @@ -4,15 +4,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserPointsResponse, UserPoints } from "./models"; /** * A call to this function will retrieve a given user's hardcore * and softcore points. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the point totals for. * @@ -33,7 +32,7 @@ import type { GetUserPointsResponse, UserPoints } from "./models"; * ``` */ export const getUserPoints = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string } ): Promise => { const { username } = payload; diff --git a/src/user/getUserProfile.ts b/src/user/getUserProfile.ts index 2e6b4eb..c6c9d06 100644 --- a/src/user/getUserProfile.ts +++ b/src/user/getUserProfile.ts @@ -4,15 +4,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserProfileResponse, UserProfile } from "./models"; /** * A call to this function will retrieve summary information about * a given user, targeted by username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the summary for. * @@ -27,7 +26,7 @@ import type { GetUserProfileResponse, UserProfile } from "./models"; * @returns An object containing profile summary metadata about a target user. */ export const getUserProfile = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; } diff --git a/src/user/getUserProgress.ts b/src/user/getUserProgress.ts index a06cae1..d63ca21 100644 --- a/src/user/getUserProgress.ts +++ b/src/user/getUserProgress.ts @@ -5,15 +5,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserProgressResponse, UserProgress } from "./models"; /** * A call to this function will retrieve a given user's * progress on a given list of games, targeted by game ID. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the progress for. * @@ -52,7 +51,7 @@ import type { GetUserProgressResponse, UserProgress } from "./models"; * ``` */ export const getUserProgress = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; gameIds: ID[] } ): Promise => { const { username, gameIds } = payload; diff --git a/src/user/getUserRecentAchievements.ts b/src/user/getUserRecentAchievements.ts index eec65b4..3934ae6 100644 --- a/src/user/getUserRecentAchievements.ts +++ b/src/user/getUserRecentAchievements.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserRecentAchievementsResponse, UserRecentAchievement, @@ -15,8 +15,7 @@ import type { * recently earned achievements, via their username. By default, it * fetches achievements earned in the last hour. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the recent achievements for. * @@ -54,7 +53,7 @@ import type { * ``` */ export const getUserRecentAchievements = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; recentMinutes?: number } ): Promise => { const { username, recentMinutes } = payload; diff --git a/src/user/getUserRecentlyPlayedGames.ts b/src/user/getUserRecentlyPlayedGames.ts index 47dbe62..784407b 100644 --- a/src/user/getUserRecentlyPlayedGames.ts +++ b/src/user/getUserRecentlyPlayedGames.ts @@ -4,7 +4,7 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserRecentlyPlayedGamesResponse, UserRecentlyPlayedGames, @@ -14,8 +14,7 @@ import type { * A call to this function will retrieve a list of a target user's * recently played games, via their username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the summary for. * @@ -54,7 +53,7 @@ import type { * ``` */ export const getUserRecentlyPlayedGames = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; offset?: number; count?: number } ): Promise => { const { username, offset, count } = payload; diff --git a/src/user/getUserSummary.ts b/src/user/getUserSummary.ts index e1176a1..29f36b4 100644 --- a/src/user/getUserSummary.ts +++ b/src/user/getUserSummary.ts @@ -4,15 +4,14 @@ import { call, serializeProperties, } from "../utils/internal"; -import type { AuthObject } from "../utils/public"; +import type { ApiAuthorization } from "../utils/public"; import type { GetUserSummaryResponse, UserSummary } from "./models"; /** * A call to this function will retrieve summary information about * a given user, targeted by username. * - * @param authorization An object containing your username and webApiKey. - * This can be constructed with `buildAuthorization()`. + * @param authorization Your web API key retrieved from retroachievements.org/settings. * * @param payload.username The user for which to retrieve the summary for. * @@ -33,7 +32,7 @@ import type { GetUserSummaryResponse, UserSummary } from "./models"; * @returns An object containing summary metadata about a target user. */ export const getUserSummary = async ( - authorization: AuthObject, + authorization: ApiAuthorization, payload: { username: string; recentGamesCount?: number; diff --git a/src/utils/internal/buildRequestUrl.test.ts b/src/utils/internal/buildRequestUrl.test.ts index decb453..2eb907c 100644 --- a/src/utils/internal/buildRequestUrl.test.ts +++ b/src/utils/internal/buildRequestUrl.test.ts @@ -28,7 +28,7 @@ describe("Util: buildRequestUrl", () => { // ASSERT expect(requestUrl).toEqual( - "https://retroachievements.org/API/myBazValue/API_GetConsoleIDs.php?z=TestUser&y=mockWebApiKey&limit=10&offset=2" + "https://retroachievements.org/API/myBazValue/API_GetConsoleIDs.php?y=mockWebApiKey&limit=10&offset=2" ); }); @@ -45,7 +45,7 @@ describe("Util: buildRequestUrl", () => { // ASSERT expect(requestUrl).toEqual( - "https://retroachievements.org/API/:baz/API_GetConsoleIDs.php?z=TestUser&y=mockWebApiKey" + "https://retroachievements.org/API/:baz/API_GetConsoleIDs.php?y=mockWebApiKey" ); }); }); diff --git a/src/utils/internal/buildRequestUrl.ts b/src/utils/internal/buildRequestUrl.ts index 0ab00ec..9c0941b 100644 --- a/src/utils/internal/buildRequestUrl.ts +++ b/src/utils/internal/buildRequestUrl.ts @@ -1,9 +1,9 @@ -import type { AuthObject } from "../public/models"; +import type { ApiAuthorization } from "../public/models"; export const buildRequestUrl = ( baseUrl: string, endpointUrl: string, - authObject: AuthObject, + authorization: ApiAuthorization, args: Record = {} ) => { const concatenated = `${baseUrl}/${endpointUrl}`; @@ -11,11 +11,13 @@ export const buildRequestUrl = ( let withArgs = withoutDoubleSlashes; - // `z` and `y` are expected query params from the RA API. - // Authentication is handled purely by query params. + // `y` is an always-required query param of the RA API. + // Authentication is handled purely by this query param. const queryParamValues: Record = { - z: authObject.username, - y: authObject.webApiKey, + y: + typeof authorization === "string" + ? authorization + : authorization.webApiKey, }; for (const [argKey, argValue] of Object.entries(args)) { diff --git a/src/utils/public/buildAuthorization.ts b/src/utils/public/buildAuthorization.ts index d95c007..4419bc6 100644 --- a/src/utils/public/buildAuthorization.ts +++ b/src/utils/public/buildAuthorization.ts @@ -1,4 +1,4 @@ -import type { AuthObject } from "./models"; +import type { ApiAuthorization } from "./models"; /** * Accepts your RetroAchievements.org username and web API key. After @@ -20,7 +20,9 @@ import type { AuthObject } from "./models"; * }); * ``` */ -export const buildAuthorization = (options: AuthObject): AuthObject => { +export const buildAuthorization = ( + options: ApiAuthorization +): ApiAuthorization => { if (!options.username || !options.webApiKey) { throw new Error(` buildAuthorization() requires an object containing a diff --git a/src/utils/public/models/auth-object.model.ts b/src/utils/public/models/auth-object.model.ts index c79f23a..9f92f33 100644 --- a/src/utils/public/models/auth-object.model.ts +++ b/src/utils/public/models/auth-object.model.ts @@ -1,9 +1,13 @@ /** * Each RetroAchievements API call is uniquely authenticated - * using a username + API key combination. Your account's personal - * Web API Key can be found on the Settings page. + * using a web API key. Your account's personal Web API Key can + * be found on the /settings page. */ -export interface AuthObject { + +/** + * @deprecated `username` is no longer required for web API calls. Pass a string containing just your webApiKey instead. + */ +interface LegacyAuthObject { /** * You or your app's exact username on the RetroAchievements.org website. * For example, https://retroachievements.org/user/Scott would have a value @@ -18,3 +22,5 @@ export interface AuthObject { */ webApiKey: string; } + +export type ApiAuthorization = string | LegacyAuthObject; From 6162a84dc90827a4b692e78a598b8273fa51604b Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sat, 12 Oct 2024 12:02:25 -0400 Subject: [PATCH 2/4] chore: deprecate buildAuthorization --- src/utils/public/buildAuthorization.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/utils/public/buildAuthorization.ts b/src/utils/public/buildAuthorization.ts index 4419bc6..738710a 100644 --- a/src/utils/public/buildAuthorization.ts +++ b/src/utils/public/buildAuthorization.ts @@ -19,11 +19,19 @@ import type { ApiAuthorization } from "./models"; * webApiKey: "LtjCwW16nJI7cqOyPIQtXk8v1cfF0tmO" * }); * ``` + * + * @deprecated You can just pass your API key directly to the functions instead, eg: + * ```ts + * const game = await getGame(webApiKey, { gameId: 14402 }); + * ``` */ export const buildAuthorization = ( options: ApiAuthorization ): ApiAuthorization => { - if (!options.username || !options.webApiKey) { + if ( + typeof options !== "string" && + (!options.username || !options.webApiKey) + ) { throw new Error(` buildAuthorization() requires an object containing a username and webApiKey. eg: From ebf543be47c666a05a22db34174b0cf5f48a6b74 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sat, 12 Oct 2024 12:04:17 -0400 Subject: [PATCH 3/4] chore: typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b5f1b2..6a28fac 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Learn how to authenticate and start pulling data from RetroAchievements on our d To use any endpoint function in the API, you must first be authorized by RetroAchievements. Fortunately, this is a fairly straightforward process. -1. Visit [settings page](https://retroachievements.org/settings) on the RA website. +1. Visit the [settings page](https://retroachievements.org/settings) on the RA website. 2. Find the "Keys" section on the page. Copy the web API key value. **Do not expose your API key anywhere publicly.** From 24894ae4f43eb75b2d58f5d06cb2e9c50fc63ce9 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sat, 12 Oct 2024 12:05:26 -0400 Subject: [PATCH 4/4] chore: no breaking changes --- .../{auth-object.model.ts => api-authorization.model.ts} | 4 ++-- src/utils/public/models/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/utils/public/models/{auth-object.model.ts => api-authorization.model.ts} (89%) diff --git a/src/utils/public/models/auth-object.model.ts b/src/utils/public/models/api-authorization.model.ts similarity index 89% rename from src/utils/public/models/auth-object.model.ts rename to src/utils/public/models/api-authorization.model.ts index 9f92f33..004a73d 100644 --- a/src/utils/public/models/auth-object.model.ts +++ b/src/utils/public/models/api-authorization.model.ts @@ -7,7 +7,7 @@ /** * @deprecated `username` is no longer required for web API calls. Pass a string containing just your webApiKey instead. */ -interface LegacyAuthObject { +export interface AuthObject { /** * You or your app's exact username on the RetroAchievements.org website. * For example, https://retroachievements.org/user/Scott would have a value @@ -23,4 +23,4 @@ interface LegacyAuthObject { webApiKey: string; } -export type ApiAuthorization = string | LegacyAuthObject; +export type ApiAuthorization = string | AuthObject; diff --git a/src/utils/public/models/index.ts b/src/utils/public/models/index.ts index 04c545d..d9535c7 100644 --- a/src/utils/public/models/index.ts +++ b/src/utils/public/models/index.ts @@ -1,2 +1,2 @@ -export * from "./auth-object.model"; +export * from "./api-authorization.model"; export * from "./award-kind.model";