cedarstalking with keyboard shortcuts
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

bug: handle error state in getterms and person info

+21 -10
+14 -6
src/api.ts
··· 121 121 ): Promise<Term[]> { 122 122 const url = `${BASE_URL}/CedarInfo/Json/GetTerms?id=${id}&past=5&future=2&summer=true`; 123 123 const res = await fetch(url, { headers: makeHeaders(cookie) }); 124 - if (!res.ok) return []; 125 - const data = await res.json(); 126 - return Array.isArray(data) ? data : []; 124 + if (!res.ok || !res.headers.get("content-type")?.includes("json")) return []; 125 + try { 126 + const data = await res.json(); 127 + return Array.isArray(data) ? data : []; 128 + } catch { 129 + return []; 130 + } 127 131 } 128 132 129 133 export async function getPersonInfo( ··· 133 137 ): Promise<PersonInfo | null> { 134 138 const url = `${BASE_URL}/CedarInfo/Info/Json?id=${id}&term=${term}`; 135 139 const res = await fetch(url, { headers: makeHeaders(cookie) }); 136 - if (!res.ok) return null; 137 - const data = await res.json(); 138 - return data as PersonInfo; 140 + if (!res.ok || !res.headers.get("content-type")?.includes("json")) return null; 141 + try { 142 + const data = await res.json(); 143 + return data as PersonInfo; 144 + } catch { 145 + return null; 146 + } 139 147 } 140 148 141 149 export async function searchDirectory(
+7 -4
src/auth.ts
··· 35 35 // grants it proper window-server access. Cookie is returned through a temp file. 36 36 export async function launchAuthBrowser(signInUrl: string): Promise<string> { 37 37 const binaryPath = await ensureBinary(); 38 - const appBundle = await ensureAppBundle(binaryPath); 39 - const cookieFile = path.join(os.tmpdir(), "cedarstalk-cookie.txt"); 38 + const sessionId = Date.now().toString(36); 39 + const appBundle = await ensureAppBundle(binaryPath, sessionId); 40 + const cookieFile = path.join(os.tmpdir(), `cedarstalk-cookie-${sessionId}.txt`); 40 41 41 42 await unlink(cookieFile).catch(() => {}); 42 43 ··· 61 62 .then((s) => s.trim()) 62 63 .catch(() => ""); 63 64 await unlink(cookieFile).catch(() => {}); 65 + // Clean up the ephemeral app bundle 66 + await execAsync(`rm -rf "${appBundle}"`).catch(() => {}); 64 67 65 68 if (!cookie) throw new Error("Sign-in cancelled"); 66 69 return cookie; ··· 93 96 } 94 97 } 95 98 96 - async function ensureAppBundle(binaryPath: string): Promise<string> { 97 - const appDir = path.join(os.tmpdir(), "CedarStalkAuth.app"); 99 + async function ensureAppBundle(binaryPath: string, sessionId: string): Promise<string> { 100 + const appDir = path.join(os.tmpdir(), `CedarStalkAuth-${sessionId}.app`); 98 101 const macosDir = path.join(appDir, "Contents", "MacOS"); 99 102 const plistPath = path.join(appDir, "Contents", "Info.plist"); 100 103 const bundledBinary = path.join(macosDir, "CedarStalkAuth");