a tool for shared writing and social publishing
0
fork

Configure Feed

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

add request lock if in production

+54
+35
package-lock.json
··· 33 33 "@supabase/supabase-js": "^2.43.2", 34 34 "@tiptap/core": "^2.11.5", 35 35 "@types/mdx": "^2.0.13", 36 + "@upstash/redis": "^1.35.0", 36 37 "@vercel/analytics": "^1.5.0", 37 38 "@vercel/sdk": "^1.3.1", 38 39 "babel-plugin-react-compiler": "^19.1.0-rc.1", ··· 57 58 "react-day-picker": "^9.3.0", 58 59 "react-dom": "19.1.0", 59 60 "react-use-measure": "^2.1.1", 61 + "redlock": "^5.0.0-beta.2", 60 62 "rehype-parse": "^9.0.0", 61 63 "rehype-remark": "^10.0.0", 62 64 "rehype-stringify": "^10.0.0", ··· 6168 6170 "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", 6169 6171 "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" 6170 6172 }, 6173 + "node_modules/@upstash/redis": { 6174 + "version": "1.35.0", 6175 + "resolved": "https://registry.npmjs.org/@upstash/redis/-/redis-1.35.0.tgz", 6176 + "integrity": "sha512-WUm0Jz1xN4DBDGeJIi2Y0kVsolWRB2tsVds4SExaiLg4wBdHFMB+8IfZtBWr+BP0FvhuBr5G1/VLrJ9xzIWHsg==", 6177 + "license": "MIT", 6178 + "dependencies": { 6179 + "uncrypto": "^0.1.3" 6180 + } 6181 + }, 6171 6182 "node_modules/@vercel/analytics": { 6172 6183 "version": "1.5.0", 6173 6184 "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.5.0.tgz", ··· 12856 12867 "node": "^10 || ^12 || >=14" 12857 12868 } 12858 12869 }, 12870 + "node_modules/node-abort-controller": { 12871 + "version": "3.1.1", 12872 + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", 12873 + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", 12874 + "license": "MIT" 12875 + }, 12859 12876 "node_modules/node-domexception": { 12860 12877 "version": "1.0.0", 12861 12878 "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", ··· 14383 14400 "url": "https://opencollective.com/unified" 14384 14401 } 14385 14402 }, 14403 + "node_modules/redlock": { 14404 + "version": "5.0.0-beta.2", 14405 + "resolved": "https://registry.npmjs.org/redlock/-/redlock-5.0.0-beta.2.tgz", 14406 + "integrity": "sha512-2RDWXg5jgRptDrB1w9O/JgSZC0j7y4SlaXnor93H/UJm/QyDiFgBKNtrh0TI6oCXqYSaSoXxFh6Sd3VtYfhRXw==", 14407 + "license": "MIT", 14408 + "dependencies": { 14409 + "node-abort-controller": "^3.0.1" 14410 + }, 14411 + "engines": { 14412 + "node": ">=12" 14413 + } 14414 + }, 14386 14415 "node_modules/reflect.getprototypeof": { 14387 14416 "version": "1.0.10", 14388 14417 "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", ··· 16175 16204 "funding": { 16176 16205 "url": "https://github.com/sponsors/ljharb" 16177 16206 } 16207 + }, 16208 + "node_modules/uncrypto": { 16209 + "version": "0.1.3", 16210 + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", 16211 + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", 16212 + "license": "MIT" 16178 16213 }, 16179 16214 "node_modules/undici": { 16180 16215 "version": "6.21.2",
+19
src/atproto-oauth.ts
··· 2 2 NodeOAuthClient, 3 3 NodeSavedSession, 4 4 NodeSavedState, 5 + RuntimeLock, 5 6 Session, 6 7 } from "@atproto/oauth-client-node"; 7 8 import { JoseKey } from "@atproto/jwk-jose"; 8 9 import { oauth_metadata } from "app/api/oauth/[route]/oauth-metadata"; 9 10 import { supabaseServerClient } from "supabase/serverClient"; 10 11 12 + import { Redis } from "@upstash/redis"; 13 + import Redlock from "redlock"; 11 14 export async function createOauthClient() { 12 15 let keyset = 13 16 process.env.NODE_ENV === "production" ··· 15 18 JoseKey.fromImportable(process.env.JOSE_PRIVATE_KEY_1!), 16 19 ]) 17 20 : undefined; 21 + let requestLock: RuntimeLock | undefined; 22 + if (process.env.NODE_ENV === "production") { 23 + const redis = Redis.fromEnv(); 24 + const redlock = new Redlock([redis]); 25 + requestLock = async (key, fn) => { 26 + // 30 seconds should be enough. Since we will be using one lock per user id 27 + // we can be quite liberal with the lock duration here. 28 + const lock = await redlock.acquire([key], 45e3); 29 + try { 30 + return await fn(); 31 + } finally { 32 + await lock.release(); 33 + } 34 + }; 35 + } 18 36 return new NodeOAuthClient({ 19 37 // This object will be used to build the payload of the /client-metadata.json 20 38 // endpoint metadata, exposing the client metadata to the OAuth server. ··· 28 46 stateStore, 29 47 // Interface to store authenticated session data 30 48 sessionStore, 49 + requestLock, 31 50 }); 32 51 } 33 52