scorezilla 0.3.1 → 0.4.0

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.
package/API.md CHANGED
@@ -156,8 +156,9 @@ for (const e of entries) console.log(`${e.rank}. ${e.playerId}: ${e.score}`);
156
156
 
157
157
  ### `getPlayerRank`
158
158
 
159
- `GET /v1/boards/:boardId/players/:playerId/rank`. Returns 404 (`not_found`) if
160
- the player has no submission yet.
159
+ `GET /v1/boards/:boardId/players/:playerId/rank`. "No entry yet" is a normal
160
+ result (`{ ranked: false }`), **not** an error — narrow on `ranked` before
161
+ reading `rank`. A `not_found` (404) is thrown only when the board doesn't exist.
161
162
 
162
163
  ```ts
163
164
  interface GetPlayerRankInput {
@@ -165,15 +166,24 @@ interface GetPlayerRankInput {
165
166
  playerId: string;
166
167
  }
167
168
 
168
- interface PlayerRankResponse {
169
- ok: true;
170
- boardId: string;
171
- playerId: string;
172
- rank: number;
173
- score: number;
174
- submittedAt: number;
175
- totalEntries: number;
176
- }
169
+ type PlayerRankResponse =
170
+ | {
171
+ ok: true;
172
+ boardId: string;
173
+ playerId: string;
174
+ ranked: true;
175
+ rank: number;
176
+ score: number;
177
+ submittedAt: number;
178
+ totalEntries: number;
179
+ }
180
+ | { ok: true; boardId: string; playerId: string; ranked: false; rank: null; score: null };
181
+ ```
182
+
183
+ ```ts
184
+ const r = await sz.getPlayerRank({ boardId, playerId });
185
+ if (r.ranked) console.log(`Rank ${r.rank} of ${r.totalEntries}`);
186
+ else console.log('No submission yet.');
177
187
  ```
178
188
 
179
189
  ### `getWindowAround`
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#57](https://github.com/isco-tec/scorezilla-js/pull/57) [`cba6107`](https://github.com/isco-tec/scorezilla-js/commit/cba61078b2a66bb4c9d0d911dee8dd776e7b69d5) Thanks [@isco-tec](https://github.com/isco-tec)! - `getPlayerRank` no longer treats "no entry yet" as an error.
8
+
9
+ The rank endpoint now returns `200 { ranked: false }` for a player with no submission instead of a `404` — a 404 forced an un-suppressable red console line in every integrator's devtools for a perfectly normal "has this player scored?" check. `PlayerRankResponse` is now a union discriminated on `ranked`: narrow on it before reading `rank`/`score`. A `not_found` is still thrown only when the board itself doesn't exist.
10
+
11
+ Migration:
12
+
13
+ ```ts
14
+ // Before
15
+ try {
16
+ const { rank } = await sz.getPlayerRank({ boardId, playerId });
17
+ } catch (e) {
18
+ if (e instanceof ScorezillaError && e.isNotFound()) {
19
+ /* no entry */
20
+ }
21
+ }
22
+
23
+ // After
24
+ const r = await sz.getPlayerRank({ boardId, playerId });
25
+ if (r.ranked) {
26
+ /* r.rank, r.score, … */
27
+ } else {
28
+ /* no entry yet */
29
+ }
30
+ ```
31
+
3
32
  ## 0.3.1
4
33
 
5
34
  ### Patch Changes
@@ -178,15 +178,36 @@ interface LeaderboardResponse {
178
178
  limit: number;
179
179
  entries: RankedEntry[];
180
180
  }
181
- /** Payload from `GET /v1/boards/:boardId/players/:playerId/rank`. */
182
- interface PlayerRankResponse {
181
+ /**
182
+ * Payload from `GET /v1/boards/:boardId/players/:playerId/rank`.
183
+ *
184
+ * Discriminated on `ranked`. "No entry yet" is a normal state, not an error:
185
+ * the API returns `200 { ranked: false }` (not a 404 — a 404 spammed an
186
+ * un-suppressable red console line for every benign "has this player scored?"
187
+ * check). A 404 is now reserved for a genuinely missing board.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * const r = await sz.getPlayerRank({ boardId, playerId });
192
+ * if (r.ranked) console.log(`Rank ${r.rank} of ${r.totalEntries}`);
193
+ * else console.log('No submission yet.');
194
+ * ```
195
+ */
196
+ type PlayerRankResponse = {
183
197
  boardId: string;
184
198
  playerId: string;
199
+ ranked: true;
185
200
  rank: number;
186
201
  score: number;
187
202
  submittedAt: number;
188
203
  totalEntries: number;
189
- }
204
+ } | {
205
+ boardId: string;
206
+ playerId: string;
207
+ ranked: false;
208
+ rank: null;
209
+ score: null;
210
+ };
190
211
  /** Payload from `GET /v1/boards/:boardId/players/:playerId/window`. */
191
212
  interface WindowAroundResponse {
192
213
  boardId: string;
@@ -178,15 +178,36 @@ interface LeaderboardResponse {
178
178
  limit: number;
179
179
  entries: RankedEntry[];
180
180
  }
181
- /** Payload from `GET /v1/boards/:boardId/players/:playerId/rank`. */
182
- interface PlayerRankResponse {
181
+ /**
182
+ * Payload from `GET /v1/boards/:boardId/players/:playerId/rank`.
183
+ *
184
+ * Discriminated on `ranked`. "No entry yet" is a normal state, not an error:
185
+ * the API returns `200 { ranked: false }` (not a 404 — a 404 spammed an
186
+ * un-suppressable red console line for every benign "has this player scored?"
187
+ * check). A 404 is now reserved for a genuinely missing board.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * const r = await sz.getPlayerRank({ boardId, playerId });
192
+ * if (r.ranked) console.log(`Rank ${r.rank} of ${r.totalEntries}`);
193
+ * else console.log('No submission yet.');
194
+ * ```
195
+ */
196
+ type PlayerRankResponse = {
183
197
  boardId: string;
184
198
  playerId: string;
199
+ ranked: true;
185
200
  rank: number;
186
201
  score: number;
187
202
  submittedAt: number;
188
203
  totalEntries: number;
189
- }
204
+ } | {
205
+ boardId: string;
206
+ playerId: string;
207
+ ranked: false;
208
+ rank: null;
209
+ score: null;
210
+ };
190
211
  /** Payload from `GET /v1/boards/:boardId/players/:playerId/window`. */
191
212
  interface WindowAroundResponse {
192
213
  boardId: string;
package/dist/index.cjs CHANGED
@@ -656,7 +656,7 @@ function validateMetadata(metadata) {
656
656
  }
657
657
  var Scorezilla = class _Scorezilla {
658
658
  /** The package version, injected at build time from `package.json`. */
659
- static version = "0.3.1";
659
+ static version = "0.4.0";
660
660
  #config;
661
661
  #userAgent;
662
662
  #authHeader;
@@ -746,22 +746,19 @@ var Scorezilla = class _Scorezilla {
746
746
  /**
747
747
  * Fetch a single player's rank on a board.
748
748
  *
749
- * Maps to `GET /v1/boards/:boardId/players/:playerId/rank`. Returns 404
750
- * (`not_found`) if the player has no entry yet.
749
+ * Maps to `GET /v1/boards/:boardId/players/:playerId/rank`. "No entry yet"
750
+ * is a normal result, NOT an error: the response is `{ ranked: false }`
751
+ * (narrow on `ranked` before reading `rank`). A `not_found` is thrown only
752
+ * when the board itself doesn't exist.
751
753
  *
752
754
  * @example
753
755
  * ```ts
754
- * try {
755
- * const { rank, score } = await sz.getPlayerRank({ boardId, playerId: 'alice' });
756
- * console.log(`Alice is rank ${rank} with score ${score}`);
757
- * } catch (e) {
758
- * if (e instanceof ScorezillaError && e.isNotFound()) {
759
- * console.log('Alice has no submission on this board yet.');
760
- * } else throw e;
761
- * }
756
+ * const r = await sz.getPlayerRank({ boardId, playerId: 'alice' });
757
+ * if (r.ranked) console.log(`Alice is rank ${r.rank} with score ${r.score}`);
758
+ * else console.log('Alice has no submission on this board yet.');
762
759
  * ```
763
760
  *
764
- * @throws {ScorezillaError} `not_found` (player has no submission),
761
+ * @throws {ScorezillaError} `not_found` (board does not exist),
765
762
  * `network_error`, `timeout`.
766
763
  * @since 0.1.0
767
764
  * @stability stable
@@ -841,7 +838,7 @@ function createClient(config) {
841
838
  }
842
839
 
843
840
  // src/index.ts
844
- var SDK_VERSION = "0.3.1";
841
+ var SDK_VERSION = "0.4.0";
845
842
 
846
843
  exports.SDK_VERSION = SDK_VERSION;
847
844
  exports.Scorezilla = Scorezilla;