Personal Site

Skip unused "item" field in spotify api

vielle.dev d5d60bb7 f01e3563

verified
+42 -26
+26 -6
src/components/playing/spotify/api.ts
··· 1 1 import getAccessCode from "./access"; 2 2 import { SpotifyError, throws } from "./errors"; 3 3 import { isNowPlaying, type nowPlaying } from "./types"; 4 + import { isObj } from "/utils"; 4 5 5 6 /** 6 7 * Wrapper for authorizing a spotify API with default headers etc ··· 33 34 * @throws `SpotifyError` of NO_AUTH | UNHANDLED_API_ERR | INVALID_AUTH_RES | RATE_LIMITED | NO_CONTENT | MALFORMED_SPOTIFY_RES 34 35 */ 35 36 export async function spotifyNowPlaying() { 36 - type success = nowPlaying["item"]; 37 + type success = nowPlaying; 37 38 let res: (v: success) => void, rej: (v: unknown) => void; 38 39 const output = new Promise<success>((_res, _rej) => { 39 40 (res = _res), (rej = _rej); ··· 138 139 // quit early if it rejected last time 139 140 if (!resp) return; 140 141 try { 141 - const json = await resp.json(); 142 - 142 + const json = await resp 143 + .json() 144 + .then((res) => 145 + isObj(res) && "item" in res && isObj(res.item) 146 + ? res.item 147 + : throws("Item field missing"), 148 + ); 143 149 144 150 // verify structure 145 151 if (!isNowPlaying(json)) { 146 - rej(new SpotifyError("MALFORMED_SPOTIFY_RES", json, "Response missing required fields.")); 152 + rej( 153 + new SpotifyError( 154 + "MALFORMED_SPOTIFY_RES", 155 + json, 156 + "Response missing required fields.", 157 + ), 158 + ); 147 159 return; 148 160 } 149 161 150 - res(json.item) 151 - } catch (e) {} 162 + res(json); 163 + } catch (e) { 164 + rej( 165 + new SpotifyError( 166 + "MALFORMED_SPOTIFY_RES", 167 + e, 168 + "Could not parse JSON.", 169 + ), 170 + ); 171 + } 152 172 }); 153 173 154 174 return output;
+16 -20
src/components/playing/spotify/types.ts
··· 37 37 return isRefreshToken(obj) && "refresh_token" in obj; 38 38 } 39 39 40 - export type nowPlaying = { 41 - item: null | { 40 + export type nowPlaying =null | { 42 41 type: "track"; 43 42 id: string; 44 43 name: string; ··· 54 53 id: string; 55 54 }[]; 56 55 }; 57 - }; 58 56 59 - export function isNowPlaying(obj: object): obj is nowPlaying { 57 + export function isNowPlaying(obj: unknown): obj is nowPlaying { 60 58 return ( 61 59 isObj(obj) && 62 - "item" in obj && 63 - isObj(obj.item) && 64 - "type" in obj.item && 65 - obj.item.type === "track" && 66 - "id" in obj.item && 67 - typeof obj.item.id === "string" && 68 - "name" in obj.item && 69 - typeof obj.item.name === "string" && 70 - "album" in obj.item && 71 - isObj(obj.item.album) && 72 - "images" in obj.item.album && 73 - Array.isArray(obj.item.album.images) && 74 - obj.item.album.images.reduce( 60 + "type" in obj && 61 + obj.type === "track" && 62 + "id" in obj && 63 + typeof obj.id === "string" && 64 + "name" in obj && 65 + typeof obj.name === "string" && 66 + "album" in obj && 67 + isObj(obj.album) && 68 + "images" in obj.album && 69 + Array.isArray(obj.album.images) && 70 + obj.album.images.reduce( 75 71 (acc, curr) => 76 72 acc && 77 73 "url" in curr && ··· 82 78 typeof curr.width === "number", 83 79 true, 84 80 ) && 85 - "artists" in obj.item && 86 - Array.isArray(obj.item.artists) && 87 - obj.item.artists.reduce( 81 + "artists" in obj && 82 + Array.isArray(obj.artists) && 83 + obj.artists.reduce( 88 84 (acc, curr) => 89 85 acc && 90 86 "name" in curr &&