ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto

attempt to fix not fully logging out...i don't think it worked

Changed files
+63 -94
dist
netlify
functions
+30 -14
dist/index.html
··· 1 - <!DOCTYPE html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8" /> 5 - <link rel="icon" type="image/svg+xml" href="/vite.svg" /> 6 - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 - <title>ATLast: Sync Your TikTok Follows → ATmosphere (Skylight, Bluesky, etc.)</title> 8 - <script type="module" crossorigin src="/assets/index-8vZ0WHUG.js"></script> 9 - <link rel="stylesheet" crossorigin href="/assets/index-Bs4vTtm8.css"> 10 - </head> 11 - <body> 12 - <div id="root"></div> 13 - </body> 14 - </html> 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <link rel="manifest" href="/site.webmanifest" /> 6 + <link 7 + rel="apple-touch-icon" 8 + sizes="180x180" 9 + href="/apple-touch-icon.png" 10 + /> 11 + <link 12 + rel="icon" 13 + type="image/x-icon" 14 + sizes="32x32" 15 + href="/favicon.ico" 16 + /> 17 + <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 18 + 19 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 20 + <title> 21 + ATLast: Sync Your TikTok Follows → ATmosphere (Skylight, Bluesky, 22 + etc.) 23 + </title> 24 + <script type="module" crossorigin src="/assets/index-Dx_AzG_Q.js"></script> 25 + <link rel="stylesheet" crossorigin href="/assets/index-C69tQ_4S.css"> 26 + </head> 27 + <body> 28 + <div id="root"></div> 29 + </body> 30 + </html>
+4
netlify/functions/logout.ts
··· 27 27 console.log("[logout] Session ID from cookie:", sessionId); 28 28 29 29 if (sessionId) { 30 + // Get the DID before deleting 31 + const userSession = await userSessions.get(sessionId); 32 + const did = userSession?.did; 33 + 30 34 // Delete session from database 31 35 await userSessions.del(sessionId); 32 36 console.log("[logout] Deleted session from database");
+14 -67
netlify/functions/session.ts
··· 16 16 return key; 17 17 } 18 18 19 - // ENHANCED: Two-tier cache system 20 - // Tier 1: In-memory cache for profile data (lives for function instance) 19 + // In-memory cache for profile 21 20 const profileCache = new Map<string, { data: any; timestamp: number }>(); 22 21 const PROFILE_CACHE_TTL = 5 * 60 * 1000; // 5 minutes 23 - 24 - // Tier 2: Session metadata cache (DID -> basic info, faster than full OAuth restore) 25 - const sessionMetadataCache = new Map< 26 - string, 27 - { 28 - did: string; 29 - lastSeen: number; 30 - profileFetchNeeded: boolean; 31 - } 32 - >(); 33 22 34 23 export const handler: Handler = async ( 35 24 event: HandlerEvent, ··· 49 38 }; 50 39 } 51 40 52 - // OPTIMIZATION: Check session metadata cache first (avoids DB query) 53 - const cachedMetadata = sessionMetadataCache.get(sessionId); 54 - const now = Date.now(); 41 + // Check database for session 42 + const userSession = await userSessions.get(sessionId); 55 43 56 - let did: string; 44 + if (!userSession) { 45 + return { 46 + statusCode: 401, 47 + headers: { "Content-Type": "application/json" }, 48 + body: JSON.stringify({ error: "Invalid or expired session" }), 49 + }; 50 + } 57 51 58 - if (cachedMetadata && now - cachedMetadata.lastSeen < 60000) { 59 - // Session seen within last minute, trust the cache 60 - did = cachedMetadata.did; 61 - console.log("Session metadata from cache"); 62 - } else { 63 - // Need to verify session from database 64 - const userSession = await userSessions.get(sessionId); 65 - if (!userSession) { 66 - // Clear stale cache entry 67 - sessionMetadataCache.delete(sessionId); 68 - return { 69 - statusCode: 401, 70 - headers: { "Content-Type": "application/json" }, 71 - body: JSON.stringify({ error: "Invalid or expired session" }), 72 - }; 73 - } 52 + const did = userSession.did; 53 + const now = Date.now(); 74 54 75 - did = userSession.did; 76 - 77 - // Update session metadata cache 78 - sessionMetadataCache.set(sessionId, { 79 - did, 80 - lastSeen: now, 81 - profileFetchNeeded: true, 82 - }); 83 - 84 - // Cleanup: Remove old session metadata entries 85 - if (sessionMetadataCache.size > 200) { 86 - for (const [sid, meta] of sessionMetadataCache.entries()) { 87 - if (now - meta.lastSeen > 300000) { 88 - // 5 minutes 89 - sessionMetadataCache.delete(sid); 90 - } 91 - } 92 - } 93 - } 94 - 95 - // Check profile cache (Tier 1) 55 + // Check profile cache 96 56 const cached = profileCache.get(did); 97 57 if (cached && now - cached.timestamp < PROFILE_CACHE_TTL) { 98 58 console.log("Returning cached profile for", did); 99 - 100 - // Update session metadata last seen 101 - const meta = sessionMetadataCache.get(sessionId); 102 - if (meta) { 103 - meta.lastSeen = now; 104 - } 105 59 106 60 return { 107 61 statusCode: 200, ··· 181 135 description: profile.data.description, 182 136 }; 183 137 184 - // Cache the profile data (Tier 1) 138 + // Cache the profile data 185 139 profileCache.set(did, { 186 140 data: profileData, 187 141 timestamp: now, 188 142 }); 189 - 190 - // Update session metadata (Tier 2) 191 - const meta = sessionMetadataCache.get(sessionId); 192 - if (meta) { 193 - meta.lastSeen = now; 194 - meta.profileFetchNeeded = false; 195 - } 196 143 197 144 // Clean up old profile cache entries 198 145 if (profileCache.size > 100) {
+14 -13
package-lock.json
··· 30 30 "@types/react-dom": "^19.1.9", 31 31 "@vitejs/plugin-react": "^4.2.1", 32 32 "autoprefixer": "^10.4.21", 33 + "baseline-browser-mapping": "^2.8.31", 33 34 "gh-pages": "^6.3.0", 34 35 "postcss": "^8.5.6", 35 36 "tailwindcss": "^3.4.0", ··· 3408 3409 "license": "MIT" 3409 3410 }, 3410 3411 "node_modules/baseline-browser-mapping": { 3411 - "version": "2.8.7", 3412 - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.7.tgz", 3413 - "integrity": "sha512-bxxN2M3a4d1CRoQC//IqsR5XrLh0IJ8TCv2x6Y9N0nckNz/rTjZB3//GGscZziZOxmjP55rzxg/ze7usFI9FqQ==", 3412 + "version": "2.8.31", 3413 + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", 3414 + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", 3414 3415 "dev": true, 3415 3416 "license": "Apache-2.0", 3416 3417 "bin": { ··· 4944 4945 } 4945 4946 }, 4946 4947 "node_modules/glob": { 4947 - "version": "10.4.5", 4948 - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", 4949 - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", 4948 + "version": "10.5.0", 4949 + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", 4950 + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", 4950 4951 "license": "ISC", 4951 4952 "dependencies": { 4952 4953 "foreground-child": "^3.1.0", ··· 7266 7267 } 7267 7268 }, 7268 7269 "node_modules/tar": { 7269 - "version": "7.5.1", 7270 - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz", 7271 - "integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==", 7272 - "license": "ISC", 7270 + "version": "7.5.2", 7271 + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", 7272 + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", 7273 + "license": "BlueOak-1.0.0", 7273 7274 "dependencies": { 7274 7275 "@isaacs/fs-minipass": "^4.0.0", 7275 7276 "chownr": "^3.0.0", ··· 7628 7629 } 7629 7630 }, 7630 7631 "node_modules/vite": { 7631 - "version": "5.4.20", 7632 - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz", 7633 - "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==", 7632 + "version": "5.4.21", 7633 + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", 7634 + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", 7634 7635 "dev": true, 7635 7636 "license": "MIT", 7636 7637 "peer": true,
+1
package.json
··· 34 34 "@types/react-dom": "^19.1.9", 35 35 "@vitejs/plugin-react": "^4.2.1", 36 36 "autoprefixer": "^10.4.21", 37 + "baseline-browser-mapping": "^2.8.31", 37 38 "gh-pages": "^6.3.0", 38 39 "postcss": "^8.5.6", 39 40 "tailwindcss": "^3.4.0",