@retroachievements/api 0.0.0-development

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +103 -0
  3. package/dist/__playground.d.ts +7 -0
  4. package/dist/achievement/getAchievementUnlocks.d.ts +45 -0
  5. package/dist/achievement/index.d.ts +2 -0
  6. package/dist/achievement/models/achievement-unlock-entity.model.d.ts +6 -0
  7. package/dist/achievement/models/get-achievement-unlocks-response.model.d.ts +8 -0
  8. package/dist/achievement/models/index.d.ts +2 -0
  9. package/dist/api.cjs.development.js +2363 -0
  10. package/dist/api.cjs.development.js.map +1 -0
  11. package/dist/api.cjs.production.min.js +2 -0
  12. package/dist/api.cjs.production.min.js.map +1 -0
  13. package/dist/api.esm.js +2333 -0
  14. package/dist/api.esm.js.map +1 -0
  15. package/dist/console/getConsoleIds.d.ts +22 -0
  16. package/dist/console/getGameList.d.ts +52 -0
  17. package/dist/console/index.d.ts +3 -0
  18. package/dist/console/models/console-id.model.d.ts +4 -0
  19. package/dist/console/models/game-list.model.d.ts +15 -0
  20. package/dist/console/models/get-console-ids-response.model.d.ts +4 -0
  21. package/dist/console/models/get-game-list-response.model.d.ts +15 -0
  22. package/dist/console/models/index.d.ts +4 -0
  23. package/dist/feed/getAchievementOfTheWeek.d.ts +48 -0
  24. package/dist/feed/getActiveClaims.d.ts +38 -0
  25. package/dist/feed/getTicketData.d.ts +158 -0
  26. package/dist/feed/getTopTenUsers.d.ts +24 -0
  27. package/dist/feed/index.d.ts +5 -0
  28. package/dist/feed/models/achievement-of-the-week.model.d.ts +32 -0
  29. package/dist/feed/models/achievement-ticket-stats-response.model.d.ts +7 -0
  30. package/dist/feed/models/achievement-ticket-stats.model.d.ts +7 -0
  31. package/dist/feed/models/active-claim.model.d.ts +49 -0
  32. package/dist/feed/models/game-ticket-stats.model.d.ts +9 -0
  33. package/dist/feed/models/game-tickets-response.model.d.ts +7 -0
  34. package/dist/feed/models/get-achievement-of-the-week-response.model.d.ts +32 -0
  35. package/dist/feed/models/get-active-claims-response.model.d.ts +19 -0
  36. package/dist/feed/models/get-top-ten-users-response.model.d.ts +10 -0
  37. package/dist/feed/models/index.d.ts +19 -0
  38. package/dist/feed/models/most-ticketed-games-response.model.d.ts +12 -0
  39. package/dist/feed/models/most-ticketed-games.model.d.ts +12 -0
  40. package/dist/feed/models/recent-tickets-response.model.d.ts +6 -0
  41. package/dist/feed/models/recent-tickets.model.d.ts +6 -0
  42. package/dist/feed/models/response-ticket-entity.model.d.ts +24 -0
  43. package/dist/feed/models/ticket-entity.model.d.ts +24 -0
  44. package/dist/feed/models/tickets-by-user-response.model.d.ts +8 -0
  45. package/dist/feed/models/top-ten-users-entity.model.d.ts +5 -0
  46. package/dist/feed/models/top-ten-users.model.d.ts +2 -0
  47. package/dist/feed/models/user-ticket-stats.model.d.ts +8 -0
  48. package/dist/game/getAchievementCount.d.ts +31 -0
  49. package/dist/game/getAchievementDistribution.d.ts +57 -0
  50. package/dist/game/getGame.d.ts +48 -0
  51. package/dist/game/getGameExtended.d.ts +68 -0
  52. package/dist/game/getGameRankAndScore.d.ts +38 -0
  53. package/dist/game/getGameRating.d.ts +38 -0
  54. package/dist/game/index.d.ts +7 -0
  55. package/dist/game/models/achievement-count.model.d.ts +4 -0
  56. package/dist/game/models/achievement-distribution-flags.model.d.ts +4 -0
  57. package/dist/game/models/game-extended-achievement-entity.model.d.ts +15 -0
  58. package/dist/game/models/game-extended-claim-entity.model.d.ts +7 -0
  59. package/dist/game/models/game-extended.model.d.ts +25 -0
  60. package/dist/game/models/game-rank-and-score-entity.model.d.ts +6 -0
  61. package/dist/game/models/game-rating.model.d.ts +9 -0
  62. package/dist/game/models/game.model.d.ts +19 -0
  63. package/dist/game/models/get-achievement-count-response.model.d.ts +4 -0
  64. package/dist/game/models/get-achievement-distribution-response.model.d.ts +1 -0
  65. package/dist/game/models/get-game-extended-response.model.d.ts +50 -0
  66. package/dist/game/models/get-game-rank-and-score-response.model.d.ts +8 -0
  67. package/dist/game/models/get-game-rating-response.model.d.ts +9 -0
  68. package/dist/game/models/get-game-response.model.d.ts +19 -0
  69. package/dist/game/models/index.d.ts +14 -0
  70. package/dist/index.d.ts +6 -0
  71. package/dist/index.js +8 -0
  72. package/dist/user/getAchievementsEarnedBetween.d.ts +59 -0
  73. package/dist/user/getAchievementsEarnedOnDay.d.ts +57 -0
  74. package/dist/user/getGameInfoAndUserProgress.d.ts +80 -0
  75. package/dist/user/getUserGameRankAndScore.d.ts +44 -0
  76. package/dist/user/getUserPoints.d.ts +30 -0
  77. package/dist/user/getUserProgress.d.ts +49 -0
  78. package/dist/user/getUserRecentlyPlayedGames.d.ts +50 -0
  79. package/dist/user/getUserSummary.d.ts +32 -0
  80. package/dist/user/index.d.ts +9 -0
  81. package/dist/user/models/dated-user-achievement.model.d.ts +17 -0
  82. package/dist/user/models/dated-user-achievements-response.model.d.ts +19 -0
  83. package/dist/user/models/game-info-and-user-progress.model.d.ts +12 -0
  84. package/dist/user/models/get-game-info-and-user-progress-response.model.d.ts +14 -0
  85. package/dist/user/models/get-user-game-rank-and-score-response.model.d.ts +8 -0
  86. package/dist/user/models/get-user-points-response.model.d.ts +4 -0
  87. package/dist/user/models/get-user-progress-response.model.d.ts +10 -0
  88. package/dist/user/models/get-user-recently-played-games-response.model.d.ts +16 -0
  89. package/dist/user/models/get-user-summary-response.model.d.ts +82 -0
  90. package/dist/user/models/index.d.ts +14 -0
  91. package/dist/user/models/user-game-rank-and-score.model.d.ts +8 -0
  92. package/dist/user/models/user-points.model.d.ts +4 -0
  93. package/dist/user/models/user-progress.model.d.ts +10 -0
  94. package/dist/user/models/user-recently-played-games.model.d.ts +16 -0
  95. package/dist/user/models/user-summary.model.d.ts +83 -0
  96. package/dist/utils/internal/apiBaseUrl.d.ts +1 -0
  97. package/dist/utils/internal/buildRequestUrl.d.ts +2 -0
  98. package/dist/utils/internal/call.d.ts +20 -0
  99. package/dist/utils/internal/index.d.ts +4 -0
  100. package/dist/utils/internal/serializeProperties.d.ts +4 -0
  101. package/dist/utils/public/buildAuthorization.d.ts +22 -0
  102. package/dist/utils/public/index.d.ts +3 -0
  103. package/dist/utils/public/models/auth-object.model.d.ts +19 -0
  104. package/dist/utils/public/models/index.d.ts +1 -0
  105. package/package.json +117 -0
  106. package/src/__playground.ts +27 -0
  107. package/src/achievement/getAchievementUnlocks.test.ts +71 -0
  108. package/src/achievement/getAchievementUnlocks.ts +80 -0
  109. package/src/achievement/index.ts +2 -0
  110. package/src/achievement/models/achievement-unlock-entity.model.ts +6 -0
  111. package/src/achievement/models/get-achievement-unlocks-response.model.ts +8 -0
  112. package/src/achievement/models/index.ts +2 -0
  113. package/src/console/getConsoleIds.test.ts +53 -0
  114. package/src/console/getConsoleIds.ts +43 -0
  115. package/src/console/getGameList.test.ts +82 -0
  116. package/src/console/getGameList.ts +94 -0
  117. package/src/console/index.ts +3 -0
  118. package/src/console/models/console-id.model.ts +4 -0
  119. package/src/console/models/game-list.model.ts +16 -0
  120. package/src/console/models/get-console-ids-response.model.ts +1 -0
  121. package/src/console/models/get-game-list-response.model.ts +16 -0
  122. package/src/console/models/index.ts +4 -0
  123. package/src/feed/getAchievementOfTheWeek.test.ts +167 -0
  124. package/src/feed/getAchievementOfTheWeek.ts +80 -0
  125. package/src/feed/getActiveClaims.test.ts +81 -0
  126. package/src/feed/getActiveClaims.ts +68 -0
  127. package/src/feed/getTicketData.test.ts +349 -0
  128. package/src/feed/getTicketData.ts +286 -0
  129. package/src/feed/getTopTenUsers.test.ts +101 -0
  130. package/src/feed/getTopTenUsers.ts +51 -0
  131. package/src/feed/index.ts +5 -0
  132. package/src/feed/models/achievement-of-the-week.model.ts +27 -0
  133. package/src/feed/models/achievement-ticket-stats-response.model.ts +7 -0
  134. package/src/feed/models/achievement-ticket-stats.model.ts +7 -0
  135. package/src/feed/models/active-claim.model.ts +66 -0
  136. package/src/feed/models/game-ticket-stats.model.ts +11 -0
  137. package/src/feed/models/game-tickets-response.model.ts +7 -0
  138. package/src/feed/models/get-achievement-of-the-week-response.model.ts +27 -0
  139. package/src/feed/models/get-active-claims-response.model.ts +19 -0
  140. package/src/feed/models/get-top-ten-users-response.model.ts +12 -0
  141. package/src/feed/models/index.ts +19 -0
  142. package/src/feed/models/most-ticketed-games-response.model.ts +12 -0
  143. package/src/feed/models/most-ticketed-games.model.ts +12 -0
  144. package/src/feed/models/recent-tickets-response.model.ts +7 -0
  145. package/src/feed/models/recent-tickets.model.ts +7 -0
  146. package/src/feed/models/response-ticket-entity.model.ts +25 -0
  147. package/src/feed/models/ticket-entity.model.ts +24 -0
  148. package/src/feed/models/tickets-by-user-response.model.ts +8 -0
  149. package/src/feed/models/top-ten-users-entity.model.ts +5 -0
  150. package/src/feed/models/top-ten-users.model.ts +3 -0
  151. package/src/feed/models/user-ticket-stats.model.ts +8 -0
  152. package/src/game/getAchievementCount.test.ts +49 -0
  153. package/src/game/getAchievementCount.ts +52 -0
  154. package/src/game/getAchievementDistribution.test.ts +187 -0
  155. package/src/game/getAchievementDistribution.ts +88 -0
  156. package/src/game/getGame.test.ts +81 -0
  157. package/src/game/getGame.ts +74 -0
  158. package/src/game/getGameExtended.test.ts +121 -0
  159. package/src/game/getGameExtended.ts +103 -0
  160. package/src/game/getGameRankAndScore.test.ts +62 -0
  161. package/src/game/getGameRankAndScore.ts +66 -0
  162. package/src/game/getGameRating.test.ts +59 -0
  163. package/src/game/getGameRating.ts +59 -0
  164. package/src/game/index.ts +7 -0
  165. package/src/game/models/achievement-count.model.ts +4 -0
  166. package/src/game/models/achievement-distribution-flags.model.ts +4 -0
  167. package/src/game/models/game-extended-achievement-entity.model.ts +15 -0
  168. package/src/game/models/game-extended-claim-entity.model.ts +7 -0
  169. package/src/game/models/game-extended.model.ts +26 -0
  170. package/src/game/models/game-rank-and-score-entity.model.ts +6 -0
  171. package/src/game/models/game-rating.model.ts +9 -0
  172. package/src/game/models/game.model.ts +19 -0
  173. package/src/game/models/get-achievement-count-response.model.ts +4 -0
  174. package/src/game/models/get-achievement-distribution-response.model.ts +1 -0
  175. package/src/game/models/get-game-extended-response.model.ts +56 -0
  176. package/src/game/models/get-game-rank-and-score-response.model.ts +8 -0
  177. package/src/game/models/get-game-rating-response.model.ts +9 -0
  178. package/src/game/models/get-game-response.model.ts +19 -0
  179. package/src/game/models/index.ts +14 -0
  180. package/src/index.ts +8 -0
  181. package/src/user/getAchievementsEarnedBetween.test.ts +84 -0
  182. package/src/user/getAchievementsEarnedBetween.ts +88 -0
  183. package/src/user/getAchievementsEarnedOnDay.test.ts +83 -0
  184. package/src/user/getAchievementsEarnedOnDay.ts +87 -0
  185. package/src/user/getGameInfoAndUserProgress.test.ts +135 -0
  186. package/src/user/getGameInfoAndUserProgress.ts +118 -0
  187. package/src/user/getUserGameRankAndScore.test.ts +60 -0
  188. package/src/user/getUserGameRankAndScore.ts +69 -0
  189. package/src/user/getUserPoints.test.ts +49 -0
  190. package/src/user/getUserPoints.ts +51 -0
  191. package/src/user/getUserProgress.test.ts +80 -0
  192. package/src/user/getUserProgress.ts +78 -0
  193. package/src/user/getUserRecentlyPlayedGames.test.ts +76 -0
  194. package/src/user/getUserRecentlyPlayedGames.ts +93 -0
  195. package/src/user/getUserSummary.test.ts +251 -0
  196. package/src/user/getUserSummary.ts +96 -0
  197. package/src/user/index.ts +9 -0
  198. package/src/user/models/dated-user-achievement.model.ts +17 -0
  199. package/src/user/models/dated-user-achievements-response.model.ts +20 -0
  200. package/src/user/models/game-info-and-user-progress.model.ts +19 -0
  201. package/src/user/models/get-game-info-and-user-progress-response.model.ts +28 -0
  202. package/src/user/models/get-user-game-rank-and-score-response.model.ts +9 -0
  203. package/src/user/models/get-user-points-response.model.ts +4 -0
  204. package/src/user/models/get-user-progress-response.model.ts +13 -0
  205. package/src/user/models/get-user-recently-played-games-response.model.ts +17 -0
  206. package/src/user/models/get-user-summary-response.model.ts +92 -0
  207. package/src/user/models/index.ts +14 -0
  208. package/src/user/models/user-game-rank-and-score.model.ts +8 -0
  209. package/src/user/models/user-points.model.ts +4 -0
  210. package/src/user/models/user-progress.model.ts +10 -0
  211. package/src/user/models/user-recently-played-games.model.ts +16 -0
  212. package/src/user/models/user-summary.model.ts +92 -0
  213. package/src/utils/internal/apiBaseUrl.ts +1 -0
  214. package/src/utils/internal/buildRequestUrl.test.ts +51 -0
  215. package/src/utils/internal/buildRequestUrl.ts +32 -0
  216. package/src/utils/internal/call.test.ts +39 -0
  217. package/src/utils/internal/call.ts +29 -0
  218. package/src/utils/internal/index.ts +4 -0
  219. package/src/utils/internal/serializeProperties.test.ts +141 -0
  220. package/src/utils/internal/serializeProperties.ts +75 -0
  221. package/src/utils/public/buildAuthorization.test.ts +36 -0
  222. package/src/utils/public/buildAuthorization.ts +40 -0
  223. package/src/utils/public/index.ts +3 -0
  224. package/src/utils/public/models/auth-object.model.ts +20 -0
  225. package/src/utils/public/models/index.ts +1 -0
@@ -0,0 +1,187 @@
1
+ import { rest } from "msw";
2
+ import { setupServer } from "msw/node";
3
+
4
+ import { apiBaseUrl } from "../utils/internal";
5
+ import { buildAuthorization } from "../utils/public";
6
+ import { getAchievementDistribution } from "./getAchievementDistribution";
7
+ import {
8
+ type GetAchievementDistributionResponse,
9
+ AchievementDistributionFlags
10
+ } from "./models";
11
+
12
+ const server = setupServer();
13
+
14
+ describe("Function: getAchievementDistribution", () => {
15
+ // MSW Setup
16
+ beforeAll(() => server.listen());
17
+ afterEach(() => server.resetHandlers());
18
+ afterAll(() => server.close());
19
+
20
+ it("is defined #sanity", () => {
21
+ // ASSERT
22
+ expect(getAchievementDistribution).toBeDefined();
23
+ });
24
+
25
+ it("given a game ID, retrieves the achievement distribution associated with the game", async () => {
26
+ // ARRANGE
27
+ const authorization = buildAuthorization({
28
+ userName: "mockUserName",
29
+ webApiKey: "mockWebApiKey"
30
+ });
31
+
32
+ const mockResponse: GetAchievementDistributionResponse = {
33
+ "1": 20,
34
+ "2": 10,
35
+ "3": 8,
36
+ "4": 4,
37
+ "5": 1
38
+ };
39
+
40
+ let detectedSearchParams: URLSearchParams;
41
+
42
+ server.use(
43
+ rest.get(
44
+ `${apiBaseUrl}/API_GetAchievementDistribution.php`,
45
+ (req, res, ctx) => {
46
+ detectedSearchParams = req.url.searchParams;
47
+ return res(ctx.json(mockResponse));
48
+ }
49
+ )
50
+ );
51
+
52
+ // ACT
53
+ const response = await getAchievementDistribution(authorization, {
54
+ gameId: 14_402
55
+ });
56
+
57
+ // ASSERT
58
+ expect(response).toEqual(mockResponse);
59
+
60
+ expect(detectedSearchParams!.get("i")).toEqual("14402");
61
+ expect(detectedSearchParams!.has("f")).toBeFalsy();
62
+ expect(detectedSearchParams!.has("h")).toBeFalsy();
63
+ });
64
+
65
+ it("given flags, successfully attaches the option to the call", async () => {
66
+ // ARRANGE
67
+ const authorization = buildAuthorization({
68
+ userName: "mockUserName",
69
+ webApiKey: "mockWebApiKey"
70
+ });
71
+
72
+ const mockResponse: GetAchievementDistributionResponse = {
73
+ "1": 20,
74
+ "2": 10,
75
+ "3": 8,
76
+ "4": 4,
77
+ "5": 1
78
+ };
79
+
80
+ let detectedSearchParams: URLSearchParams;
81
+
82
+ server.use(
83
+ rest.get(
84
+ `${apiBaseUrl}/API_GetAchievementDistribution.php`,
85
+ (req, res, ctx) => {
86
+ detectedSearchParams = req.url.searchParams;
87
+ return res(ctx.json(mockResponse));
88
+ }
89
+ )
90
+ );
91
+
92
+ // ACT
93
+ const response = await getAchievementDistribution(authorization, {
94
+ gameId: 14_402,
95
+ flags: AchievementDistributionFlags.UnofficialAchievements
96
+ });
97
+
98
+ // ASSERT
99
+ expect(response).toEqual(mockResponse);
100
+
101
+ expect(detectedSearchParams!.get("i")).toEqual("14402");
102
+ expect(detectedSearchParams!.get("f")).toEqual(
103
+ String(AchievementDistributionFlags.UnofficialAchievements)
104
+ );
105
+ expect(detectedSearchParams!.has("h")).toBeFalsy();
106
+ });
107
+
108
+ it("given a truthy hardcore value, successfully attaches the option to the call", async () => {
109
+ // ARRANGE
110
+ const authorization = buildAuthorization({
111
+ userName: "mockUserName",
112
+ webApiKey: "mockWebApiKey"
113
+ });
114
+
115
+ const mockResponse: GetAchievementDistributionResponse = {
116
+ "1": 20,
117
+ "2": 10,
118
+ "3": 8,
119
+ "4": 4,
120
+ "5": 1
121
+ };
122
+
123
+ let detectedSearchParams: URLSearchParams;
124
+
125
+ server.use(
126
+ rest.get(
127
+ `${apiBaseUrl}/API_GetAchievementDistribution.php`,
128
+ (req, res, ctx) => {
129
+ detectedSearchParams = req.url.searchParams;
130
+ return res(ctx.json(mockResponse));
131
+ }
132
+ )
133
+ );
134
+
135
+ // ACT
136
+ const response = await getAchievementDistribution(authorization, {
137
+ gameId: 14_402,
138
+ hardcore: true
139
+ });
140
+
141
+ // ASSERT
142
+ expect(response).toEqual(mockResponse);
143
+
144
+ expect(detectedSearchParams!.get("i")).toEqual("14402");
145
+ expect(detectedSearchParams!.get("h")).toEqual("1");
146
+ });
147
+
148
+ it("given a falsy hardcore value, successfully attaches the option to the call", async () => {
149
+ // ARRANGE
150
+ const authorization = buildAuthorization({
151
+ userName: "mockUserName",
152
+ webApiKey: "mockWebApiKey"
153
+ });
154
+
155
+ const mockResponse: GetAchievementDistributionResponse = {
156
+ "1": 20,
157
+ "2": 10,
158
+ "3": 8,
159
+ "4": 4,
160
+ "5": 1
161
+ };
162
+
163
+ let detectedSearchParams: URLSearchParams;
164
+
165
+ server.use(
166
+ rest.get(
167
+ `${apiBaseUrl}/API_GetAchievementDistribution.php`,
168
+ (req, res, ctx) => {
169
+ detectedSearchParams = req.url.searchParams;
170
+ return res(ctx.json(mockResponse));
171
+ }
172
+ )
173
+ );
174
+
175
+ // ACT
176
+ const response = await getAchievementDistribution(authorization, {
177
+ gameId: 14_402,
178
+ hardcore: false
179
+ });
180
+
181
+ // ASSERT
182
+ expect(response).toEqual(mockResponse);
183
+
184
+ expect(detectedSearchParams!.get("i")).toEqual("14402");
185
+ expect(detectedSearchParams!.get("h")).toEqual("0");
186
+ });
187
+ });
@@ -0,0 +1,88 @@
1
+ import { apiBaseUrl, buildRequestUrl, call } from "../utils/internal";
2
+ import type { AuthObject } from "../utils/public";
3
+ import type {
4
+ AchievementDistributionFlags,
5
+ GetAchievementDistributionResponse
6
+ } from "./models";
7
+
8
+ /**
9
+ * A call to this function will retrieve a dictionary
10
+ * of the number of players who have earned a specific
11
+ * number of achievements for a given game ID.
12
+ *
13
+ * @param authorization An object containing your userName and webApiKey.
14
+ * This can be constructed with `buildAuthorization()`.
15
+ *
16
+ * @param payload.gameId The unique game ID. If you are unsure, open the
17
+ * game's page on the RetroAchievements.org website. For example, Dragster's
18
+ * URL is https://retroachievements.org/game/14402. We can see from the
19
+ * URL that the game ID is "14402".
20
+ *
21
+ * @param payload.flags Optional. By default, only official achievement
22
+ * tallies are returned in the response. Import the `AchievementDistributionFlags`
23
+ * enum for possible values. This lets you see the count of players who have
24
+ * unlocked unofficial achievements.
25
+ *
26
+ * @param payload.hardcore Optional. By default, set to false, with both
27
+ * softcore and hardcore tallies returned in the response. If this option
28
+ * is set to true, only hardcore unlocks will be included in the totals.
29
+ *
30
+ * @example
31
+ * ```
32
+ * const achievementDistribution = await getAchievementDistribution(
33
+ * authorization,
34
+ * { gameId: 14402, hardcore: true }
35
+ * );
36
+ * ```
37
+ *
38
+ * @returns A dictionary where the keys represent the earned achievement
39
+ * count and the values represent the number of players who have unlocked
40
+ * that many achievements.
41
+ * ```
42
+ * {
43
+ * '1': 64,
44
+ * '2': 19,
45
+ * '3': 11,
46
+ * '4': 18,
47
+ * '5': 25,
48
+ * '6': 20,
49
+ * '7': 26,
50
+ * '8': 29,
51
+ * '9': 54,
52
+ * '10': 17,
53
+ * '11': 29,
54
+ * '12': 4
55
+ * }
56
+ * ```
57
+ */
58
+ export const getAchievementDistribution = async (
59
+ authorization: AuthObject,
60
+ payload: {
61
+ gameId: number;
62
+ flags?: AchievementDistributionFlags;
63
+ hardcore?: boolean;
64
+ }
65
+ ) => {
66
+ const { gameId, flags, hardcore } = payload;
67
+
68
+ const queryParams: Record<string, any> = { i: gameId };
69
+
70
+ if (flags !== undefined) {
71
+ queryParams["f"] = flags;
72
+ }
73
+
74
+ if (hardcore !== undefined) {
75
+ queryParams["h"] = hardcore === true ? 1 : 0;
76
+ }
77
+
78
+ const url = buildRequestUrl(
79
+ apiBaseUrl,
80
+ "/API_GetAchievementDistribution.php",
81
+ authorization,
82
+ queryParams
83
+ );
84
+
85
+ return await call<GetAchievementDistributionResponse>({
86
+ url
87
+ });
88
+ };
@@ -0,0 +1,81 @@
1
+ /* eslint-disable sonarjs/no-duplicate-string */
2
+
3
+ import { rest } from "msw";
4
+ import { setupServer } from "msw/node";
5
+
6
+ import { apiBaseUrl } from "../utils/internal";
7
+ import { buildAuthorization } from "../utils/public";
8
+ import { getGame } from "./getGame";
9
+ import type { GetGameResponse } from "./models";
10
+
11
+ const server = setupServer();
12
+
13
+ describe("Function: getGame", () => {
14
+ // MSW Setup
15
+ beforeAll(() => server.listen());
16
+ afterEach(() => server.resetHandlers());
17
+ afterAll(() => server.close());
18
+
19
+ it("is defined #sanity", () => {
20
+ // ASSERT
21
+ expect(getGame).toBeDefined();
22
+ });
23
+
24
+ it("given a game ID, retrieves basic metadata about the game", async () => {
25
+ // ARRANGE
26
+ const authorization = buildAuthorization({
27
+ userName: "mockUserName",
28
+ webApiKey: "mockWebApiKey"
29
+ });
30
+
31
+ const mockResponse: GetGameResponse = {
32
+ ID: "14402",
33
+ Title: "Dragster",
34
+ ForumTopicID: "9145",
35
+ ConsoleID: "25",
36
+ ConsoleName: "Atari 2600",
37
+ Flags: "0",
38
+ ImageIcon: "/Images/026368.png",
39
+ GameIcon: "/Images/026368.png",
40
+ ImageTitle: "/Images/026366.png",
41
+ ImageIngame: "/Images/026367.png",
42
+ ImageBoxArt: "/Images/026365.png",
43
+ Publisher: "Activision ",
44
+ Developer: "David Crane",
45
+ Genre: "Racing",
46
+ Released: "1980",
47
+ GameTitle: "Dragster",
48
+ Console: "Atari 2600"
49
+ };
50
+
51
+ server.use(
52
+ rest.get(`${apiBaseUrl}/API_GetGame.php`, (_, res, ctx) =>
53
+ res(ctx.json(mockResponse))
54
+ )
55
+ );
56
+
57
+ // ACT
58
+ const response = await getGame(authorization, { gameId: 14_402 });
59
+
60
+ // ASSERT
61
+ expect(response).toEqual({
62
+ id: 14_402,
63
+ title: "Dragster",
64
+ forumTopicId: 9145,
65
+ consoleId: 25,
66
+ consoleName: "Atari 2600",
67
+ flags: 0,
68
+ imageIcon: "/Images/026368.png",
69
+ gameIcon: "/Images/026368.png",
70
+ imageTitle: "/Images/026366.png",
71
+ imageIngame: "/Images/026367.png",
72
+ imageBoxArt: "/Images/026365.png",
73
+ publisher: "Activision ",
74
+ developer: "David Crane",
75
+ genre: "Racing",
76
+ released: 1980,
77
+ gameTitle: "Dragster",
78
+ console: "Atari 2600"
79
+ });
80
+ });
81
+ });
@@ -0,0 +1,74 @@
1
+ import {
2
+ apiBaseUrl,
3
+ buildRequestUrl,
4
+ call,
5
+ serializeProperties
6
+ } from "../utils/internal";
7
+ import type { AuthObject } from "../utils/public";
8
+ import type { Game, GetGameResponse } from "./models";
9
+
10
+ /**
11
+ * A call to this function will retrieve basic metadata about
12
+ * a game, targeted via its unique ID.
13
+ *
14
+ * @param authorization An object containing your userName and webApiKey.
15
+ * This can be constructed with `buildAuthorization()`.
16
+ *
17
+ * @param payload.gameId The unique game ID. If you are unsure, open the
18
+ * game's page on the RetroAchievements.org website. For example, Dragster's
19
+ * URL is https://retroachievements.org/game/14402. We can see from the
20
+ * URL that the game ID is "14402".
21
+ *
22
+ * @example
23
+ * ```
24
+ * const game = await getGame(
25
+ * authorization,
26
+ * { gameId: 14402 }
27
+ * );
28
+ * ```
29
+ *
30
+ * @returns An object containing basic metadata about a target game.
31
+ * ```json
32
+ * {
33
+ * id: 14402,
34
+ * title: "Dragster",
35
+ * forumTopicId: 9145,
36
+ * consoleId: 25,
37
+ * consoleName: "Atari 2600",
38
+ * flags: 0,
39
+ * imageIcon: "/Images/026368.png",
40
+ * gameIcon: "/Images/026368.png",
41
+ * imageTitle: "/Images/026366.png",
42
+ * imageIngame: "/Images/026367.png",
43
+ * imageBoxArt: "/Images/026365.png",
44
+ * publisher: "Activision",
45
+ * developer: "David Crane",
46
+ * genre: "Racing",
47
+ * released: 1980,
48
+ * gameTitle: "Dragster",
49
+ * console: "Atari 2600"
50
+ * }
51
+ * ```
52
+ */
53
+ export const getGame = async (
54
+ authorization: AuthObject,
55
+ payload: { gameId: number }
56
+ ): Promise<Game> => {
57
+ const { gameId } = payload;
58
+
59
+ const url = buildRequestUrl(apiBaseUrl, "/API_GetGame.php", authorization, {
60
+ i: gameId
61
+ });
62
+
63
+ const rawResponse = await call<GetGameResponse>({ url });
64
+
65
+ return serializeProperties(rawResponse, {
66
+ shouldCastToNumbers: [
67
+ "ID",
68
+ "ForumTopicID",
69
+ "ConsoleID",
70
+ "Flags",
71
+ "Released"
72
+ ]
73
+ });
74
+ };
@@ -0,0 +1,121 @@
1
+ /* eslint-disable sonarjs/no-duplicate-string */
2
+
3
+ import { rest } from "msw";
4
+ import { setupServer } from "msw/node";
5
+
6
+ import { apiBaseUrl } from "../utils/internal";
7
+ import { buildAuthorization } from "../utils/public";
8
+ import { getGameExtended } from "./getGameExtended";
9
+ import type { GetGameExtendedResponse } from "./models";
10
+
11
+ const server = setupServer();
12
+
13
+ describe("Function: getGameExtended", () => {
14
+ // MSW Setup
15
+ beforeAll(() => server.listen());
16
+ afterEach(() => server.resetHandlers());
17
+ afterAll(() => server.close());
18
+
19
+ it("is defined #sanity", () => {
20
+ // ASSERT
21
+ expect(getGameExtended).toBeDefined();
22
+ });
23
+
24
+ it("given a game ID, retrieves extended metadata about the game", async () => {
25
+ // ARRANGE
26
+ const authorization = buildAuthorization({
27
+ userName: "mockUserName",
28
+ webApiKey: "mockWebApiKey"
29
+ });
30
+
31
+ const mockResponse: GetGameExtendedResponse = {
32
+ ID: 14_402,
33
+ Title: "Dragster",
34
+ ConsoleID: 25,
35
+ ForumTopicID: 9145,
36
+ Flags: 0,
37
+ ImageIcon: "/Images/026368.png",
38
+ ImageTitle: "/Images/026366.png",
39
+ ImageIngame: "/Images/026367.png",
40
+ ImageBoxArt: "/Images/026365.png",
41
+ Publisher: "Activision ",
42
+ Developer: "David Crane",
43
+ Genre: "Racing",
44
+ Released: "1980",
45
+ IsFinal: false,
46
+ ConsoleName: "Atari 2600",
47
+ RichPresencePatch: "2b92fa1bf9635c303b3b7f8feea3ed3c",
48
+ NumAchievements: 12,
49
+ NumDistinctPlayersCasual: "454",
50
+ NumDistinctPlayersHardcore: "323",
51
+ Claims: [],
52
+ Achievements: {
53
+ "79434": {
54
+ ID: "79434",
55
+ NumAwarded: "338",
56
+ NumAwardedHardcore: "253",
57
+ Title: "Novice Dragster Driver 1",
58
+ Description: "Complete your very first race in game 1.",
59
+ Points: "1",
60
+ TrueRatio: "1",
61
+ Author: "Boldewin",
62
+ DateModified: "2019-08-01 19:03:46",
63
+ DateCreated: "2019-07-31 18:49:57",
64
+ BadgeName: "85541",
65
+ DisplayOrder: "0",
66
+ MemAddr: "f5c41fa0b5fa0d5fbb8a74c598f18582"
67
+ }
68
+ }
69
+ };
70
+
71
+ server.use(
72
+ rest.get(`${apiBaseUrl}/API_GetGameExtended.php`, (_, res, ctx) =>
73
+ res(ctx.json(mockResponse))
74
+ )
75
+ );
76
+
77
+ // ACT
78
+ const response = await getGameExtended(authorization, { gameId: 14_402 });
79
+
80
+ // ASSERT
81
+ expect(response).toEqual({
82
+ id: 14_402,
83
+ title: "Dragster",
84
+ consoleId: 25,
85
+ forumTopicId: 9145,
86
+ flags: 0,
87
+ imageIcon: "/Images/026368.png",
88
+ imageTitle: "/Images/026366.png",
89
+ imageIngame: "/Images/026367.png",
90
+ imageBoxArt: "/Images/026365.png",
91
+ publisher: "Activision ",
92
+ developer: "David Crane",
93
+ genre: "Racing",
94
+ released: 1980,
95
+ isFinal: false,
96
+ consoleName: "Atari 2600",
97
+ richPresencePatch: "2b92fa1bf9635c303b3b7f8feea3ed3c",
98
+ numAchievements: 12,
99
+ numDistinctPlayersCasual: 454,
100
+ numDistinctPlayersHardcore: 323,
101
+ claims: [],
102
+ achievements: {
103
+ "79434": {
104
+ id: 79_434,
105
+ numAwarded: 338,
106
+ numAwardedHardcore: 253,
107
+ title: "Novice Dragster Driver 1",
108
+ description: "Complete your very first race in game 1.",
109
+ points: 1,
110
+ trueRatio: 1,
111
+ author: "Boldewin",
112
+ dateModified: "2019-08-01 19:03:46",
113
+ dateCreated: "2019-07-31 18:49:57",
114
+ badgeName: "85541",
115
+ displayOrder: 0,
116
+ memAddr: "f5c41fa0b5fa0d5fbb8a74c598f18582"
117
+ }
118
+ }
119
+ });
120
+ });
121
+ });
@@ -0,0 +1,103 @@
1
+ import {
2
+ apiBaseUrl,
3
+ buildRequestUrl,
4
+ call,
5
+ serializeProperties
6
+ } from "../utils/internal";
7
+ import type { AuthObject } from "../utils/public";
8
+ import type { GameExtended, GetGameExtendedResponse } from "./models";
9
+
10
+ /**
11
+ * A call to this function will retrieve extended metadata
12
+ * about a game, targeted via its unique ID.
13
+ *
14
+ * @param authorization An object containing your userName and webApiKey.
15
+ * This can be constructed with `buildAuthorization()`.
16
+ *
17
+ * @param payload.gameId The unique game ID. If you are unsure, open the
18
+ * game's page on the RetroAchievements.org website. For example, Dragster's
19
+ * URL is https://retroachievements.org/game/14402. We can see from the
20
+ * URL that the game ID is "14402".
21
+ *
22
+ * @example
23
+ * ```
24
+ * const gameExtended = await getGameExtended(
25
+ * authorization,
26
+ * { gameId: 14402 }
27
+ * );
28
+ * ```
29
+ *
30
+ * @returns An object containing extended metadata about a target game.
31
+ * ```json
32
+ * {
33
+ * id: 14402,
34
+ * title: "Dragster",
35
+ * consoleId: 25,
36
+ * forumTopicId: 9145,
37
+ * flags: 0,
38
+ * imageIcon: "/Images/026368.png",
39
+ * imageTitle: "/Images/026366.png",
40
+ * imageIngame: "/Images/026367.png",
41
+ * imageBoxArt: "/Images/026365.png",
42
+ * publisher: "Activision",
43
+ * developer: "David Crane",
44
+ * genre: "Racing",
45
+ * released: 1980,
46
+ * isFinal: false,
47
+ * consoleName: "Atari 2600",
48
+ * richPresencePatch: "2b92fa1bf9635c303b3b7f8feea3ed3c",
49
+ * numAchievements: 12,
50
+ * numDistinctPlayersCasual: 454,
51
+ * numDistinctPlayersHardcore, 323
52
+ * claims: [],
53
+ * achievements: {
54
+ * '79434': {
55
+ * id: 79434,
56
+ * numAwarded: 338,
57
+ * numAwardedHardcore: 253,
58
+ * title: "Novice Dragster Driver 1",
59
+ * description: "Complete your very first race in game 1.",
60
+ * points: 1,
61
+ * trueRatio: 1,
62
+ * author: "Boldewin",
63
+ * dateModified: "2019-08-01 19:03:46",
64
+ * dateCreated: "2019-07-31 18:49:57",
65
+ * badgeName: "85541",
66
+ * displayOrder: 0,
67
+ * memAddr: "f5c41fa0b5fa0d5fbb8a74c598f18582"
68
+ * }
69
+ * }
70
+ * }
71
+ * ```
72
+ */
73
+ export const getGameExtended = async (
74
+ authorization: AuthObject,
75
+ payload: { gameId: number }
76
+ ): Promise<GameExtended> => {
77
+ const { gameId } = payload;
78
+
79
+ const url = buildRequestUrl(
80
+ apiBaseUrl,
81
+ "/API_GetGameExtended.php",
82
+ authorization,
83
+ {
84
+ i: gameId
85
+ }
86
+ );
87
+
88
+ const rawResponse = await call<GetGameExtendedResponse>({ url });
89
+
90
+ return serializeProperties(rawResponse, {
91
+ shouldCastToNumbers: [
92
+ "ID",
93
+ "NumAwarded",
94
+ "NumAwardedHardcore",
95
+ "Points",
96
+ "TrueRatio",
97
+ "DisplayOrder",
98
+ "NumDistinctPlayersCasual",
99
+ "NumDistinctPlayersHardcore",
100
+ "Released"
101
+ ]
102
+ });
103
+ };