deer social fork for personal usage. but you might see a use idk. github mirror

Upgrade API, implement XRPC rework (#4857)

Co-authored-by: Matthieu Sieben <matthieu.sieben@gmail.com>

authored by hailey.at Matthieu Sieben and committed by GitHub 7df23274 ae883e2d

+3 -6
index.js
··· 1 1 import 'react-native-gesture-handler' // must be first 2 + import '#/platform/polyfills' 3 + 2 4 import {LogBox} from 'react-native' 3 - 4 - import '#/platform/polyfills' 5 - import {IS_TEST} from '#/env' 6 5 import {registerRootComponent} from 'expo' 7 - import {doPolyfill} from '#/lib/api/api-polyfill' 8 6 9 7 import App from '#/App' 10 - 11 - doPolyfill() 8 + import {IS_TEST} from '#/env' 12 9 13 10 if (IS_TEST) { 14 11 LogBox.ignoreAllLogs() // suppress all logs in tests
+2 -3
index.web.js
··· 1 1 import '#/platform/markBundleStartTime' 2 - 3 2 import '#/platform/polyfills' 3 + 4 4 import {registerRootComponent} from 'expo' 5 - import {doPolyfill} from '#/lib/api/api-polyfill' 5 + 6 6 import App from '#/App' 7 7 8 - doPolyfill() 9 8 registerRootComponent(App)
+2 -2
jest/test-pds.ts
··· 156 156 } 157 157 158 158 async createUser(name: string) { 159 - const agent = new BskyAgent({service: this.agent.service}) 159 + const agent = new BskyAgent({service: this.service}) 160 160 161 161 const inviteRes = await agent.api.com.atproto.server.createInviteCode( 162 162 {useCount: 1}, ··· 332 332 } 333 333 334 334 async createInvite(forAccount: string) { 335 - const agent = new BskyAgent({service: this.agent.service}) 335 + const agent = new BskyAgent({service: this.service}) 336 336 await agent.api.com.atproto.server.createInviteCode( 337 337 {useCount: 1, forAccount}, 338 338 {
+2 -2
package.json
··· 52 52 "open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web" 53 53 }, 54 54 "dependencies": { 55 - "@atproto/api": "0.12.29", 55 + "@atproto/api": "0.13.0", 56 56 "@bam.tech/react-native-image-resizer": "^3.0.4", 57 57 "@braintree/sanitize-url": "^6.0.2", 58 58 "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", ··· 208 208 "zod": "^3.20.2" 209 209 }, 210 210 "devDependencies": { 211 - "@atproto/dev-env": "^0.3.5", 211 + "@atproto/dev-env": "^0.3.39", 212 212 "@babel/core": "^7.23.2", 213 213 "@babel/preset-env": "^7.20.0", 214 214 "@babel/runtime": "^7.20.0",
-28
patches/@atproto+lexicon+0.4.0.patch
··· 1 - diff --git a/node_modules/@atproto/lexicon/dist/validators/complex.js b/node_modules/@atproto/lexicon/dist/validators/complex.js 2 - index 32d7798..9d688b7 100644 3 - --- a/node_modules/@atproto/lexicon/dist/validators/complex.js 4 - +++ b/node_modules/@atproto/lexicon/dist/validators/complex.js 5 - @@ -113,7 +113,22 @@ function object(lexicons, path, def, value) { 6 - if (value[key] === null && nullableProps.has(key)) { 7 - continue; 8 - } 9 - - const propDef = def.properties[key]; 10 - + const propDef = def.properties[key] 11 - + if (typeof value[key] === 'undefined' && !requiredProps.has(key)) { 12 - + // Fast path for non-required undefined props. 13 - + if ( 14 - + propDef.type === 'integer' || 15 - + propDef.type === 'boolean' || 16 - + propDef.type === 'string' 17 - + ) { 18 - + if (typeof propDef.default === 'undefined') { 19 - + continue 20 - + } 21 - + } else { 22 - + // Other types have no defaults. 23 - + continue 24 - + } 25 - + } 26 - const propPath = `${path}/${key}`; 27 - const validated = (0, util_1.validateOneOf)(lexicons, propPath, propDef, value[key]); 28 - const propValue = validated.success ? validated.value : value[key];
-85
src/lib/api/api-polyfill.ts
··· 1 - import RNFS from 'react-native-fs' 2 - import {BskyAgent, jsonToLex, stringifyLex} from '@atproto/api' 3 - 4 - const GET_TIMEOUT = 15e3 // 15s 5 - const POST_TIMEOUT = 60e3 // 60s 6 - 7 - export function doPolyfill() { 8 - BskyAgent.configure({fetch: fetchHandler}) 9 - } 10 - 11 - interface FetchHandlerResponse { 12 - status: number 13 - headers: Record<string, string> 14 - body: any 15 - } 16 - 17 - async function fetchHandler( 18 - reqUri: string, 19 - reqMethod: string, 20 - reqHeaders: Record<string, string>, 21 - reqBody: any, 22 - ): Promise<FetchHandlerResponse> { 23 - const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type'] 24 - if (reqMimeType && reqMimeType.startsWith('application/json')) { 25 - reqBody = stringifyLex(reqBody) 26 - } else if ( 27 - typeof reqBody === 'string' && 28 - (reqBody.startsWith('/') || reqBody.startsWith('file:')) 29 - ) { 30 - if (reqBody.endsWith('.jpeg') || reqBody.endsWith('.jpg')) { 31 - // HACK 32 - // React native has a bug that inflates the size of jpegs on upload 33 - // we get around that by renaming the file ext to .bin 34 - // see https://github.com/facebook/react-native/issues/27099 35 - // -prf 36 - const newPath = reqBody.replace(/\.jpe?g$/, '.bin') 37 - await RNFS.moveFile(reqBody, newPath) 38 - reqBody = newPath 39 - } 40 - // NOTE 41 - // React native treats bodies with {uri: string} as file uploads to pull from cache 42 - // -prf 43 - reqBody = {uri: reqBody} 44 - } 45 - 46 - const controller = new AbortController() 47 - const to = setTimeout( 48 - () => controller.abort(), 49 - reqMethod === 'post' ? POST_TIMEOUT : GET_TIMEOUT, 50 - ) 51 - 52 - const res = await fetch(reqUri, { 53 - method: reqMethod, 54 - headers: reqHeaders, 55 - body: reqBody, 56 - signal: controller.signal, 57 - }) 58 - 59 - const resStatus = res.status 60 - const resHeaders: Record<string, string> = {} 61 - res.headers.forEach((value: string, key: string) => { 62 - resHeaders[key] = value 63 - }) 64 - const resMimeType = resHeaders['Content-Type'] || resHeaders['content-type'] 65 - let resBody 66 - if (resMimeType) { 67 - if (resMimeType.startsWith('application/json')) { 68 - resBody = jsonToLex(await res.json()) 69 - } else if (resMimeType.startsWith('text/')) { 70 - resBody = await res.text() 71 - } else if (resMimeType === 'application/vnd.ipld.car') { 72 - resBody = await res.arrayBuffer() 73 - } else { 74 - throw new Error('Non-supported mime type') 75 - } 76 - } 77 - 78 - clearTimeout(to) 79 - 80 - return { 81 - status: resStatus, 82 - headers: resHeaders, 83 - body: resBody, 84 - } 85 - }
-3
src/lib/api/api-polyfill.web.ts
··· 1 - export function doPolyfill() { 2 - // no polyfill is needed on web 3 - }
+11 -14
src/lib/api/feed/custom.ts
··· 1 1 import { 2 2 AppBskyFeedDefs, 3 3 AppBskyFeedGetFeed as GetCustomFeed, 4 - AtpAgent, 5 4 BskyAgent, 6 5 } from '@atproto/api' 7 6 ··· 51 50 const agent = this.agent 52 51 const isBlueskyOwned = isBlueskyOwnedFeed(this.params.feed) 53 52 54 - const res = agent.session 53 + const res = agent.did 55 54 ? await this.agent.app.bsky.feed.getFeed( 56 55 { 57 56 ...this.params, ··· 106 105 let contentLangs = getContentLanguages().join(',') 107 106 108 107 // manually construct fetch call so we can add the `lang` cache-busting param 109 - let res = await AtpAgent.fetch!( 108 + let res = await fetch( 110 109 `https://api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=${feed}${ 111 110 cursor ? `&cursor=${cursor}` : '' 112 111 }&limit=${limit}&lang=${contentLangs}`, 113 - 'GET', 114 - {'Accept-Language': contentLangs}, 115 - undefined, 112 + {method: 'GET', headers: {'Accept-Language': contentLangs}}, 116 113 ) 117 - if (res.body?.feed?.length) { 114 + let data = res.ok ? await res.json() : null 115 + if (data?.feed?.length) { 118 116 return { 119 117 success: true, 120 - data: res.body, 118 + data, 121 119 } 122 120 } 123 121 124 122 // no data, try again with language headers removed 125 - res = await AtpAgent.fetch!( 123 + res = await fetch( 126 124 `https://api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=${feed}${ 127 125 cursor ? `&cursor=${cursor}` : '' 128 126 }&limit=${limit}`, 129 - 'GET', 130 - {'Accept-Language': ''}, 131 - undefined, 127 + {method: 'GET', headers: {'Accept-Language': ''}}, 132 128 ) 133 - if (res.body?.feed?.length) { 129 + data = res.ok ? await res.json() : null 130 + if (data?.feed?.length) { 134 131 return { 135 132 success: true, 136 - data: res.body, 133 + data, 137 134 } 138 135 } 139 136
+5 -34
src/lib/api/index.ts
··· 6 6 AppBskyFeedThreadgate, 7 7 BskyAgent, 8 8 ComAtprotoLabelDefs, 9 - ComAtprotoRepoUploadBlob, 10 9 RichText, 11 10 } from '@atproto/api' 12 11 import {AtUri} from '@atproto/api' ··· 15 14 import {ThreadgateSetting} from '#/state/queries/threadgate' 16 15 import {isNetworkError} from 'lib/strings/errors' 17 16 import {shortenLinks, stripInvalidMentions} from 'lib/strings/rich-text-manip' 18 - import {isNative, isWeb} from 'platform/detection' 17 + import {isNative} from 'platform/detection' 19 18 import {ImageModel} from 'state/models/media/image' 20 19 import {LinkMeta} from '../link-meta/link-meta' 21 20 import {safeDeleteAsync} from '../media/manip' 21 + import {uploadBlob} from './upload-blob' 22 + 23 + export {uploadBlob} 22 24 23 25 export interface ExternalEmbedDraft { 24 26 uri: string ··· 26 28 meta?: LinkMeta 27 29 embed?: AppBskyEmbedRecord.Main 28 30 localThumb?: ImageModel 29 - } 30 - 31 - export async function uploadBlob( 32 - agent: BskyAgent, 33 - blob: string, 34 - encoding: string, 35 - ): Promise<ComAtprotoRepoUploadBlob.Response> { 36 - if (isWeb) { 37 - // `blob` should be a data uri 38 - return agent.uploadBlob(convertDataURIToUint8Array(blob), { 39 - encoding, 40 - }) 41 - } else { 42 - // `blob` should be a path to a file in the local FS 43 - return agent.uploadBlob( 44 - blob, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts 45 - {encoding}, 46 - ) 47 - } 48 31 } 49 32 50 33 interface PostOpts { ··· 301 284 302 285 const postUrip = new AtUri(postUri) 303 286 await agent.api.com.atproto.repo.putRecord({ 304 - repo: agent.session!.did, 287 + repo: agent.accountDid, 305 288 collection: 'app.bsky.feed.threadgate', 306 289 rkey: postUrip.rkey, 307 290 record: { ··· 312 295 }, 313 296 }) 314 297 } 315 - 316 - // helpers 317 - // = 318 - 319 - function convertDataURIToUint8Array(uri: string): Uint8Array { 320 - var raw = window.atob(uri.substring(uri.indexOf(';base64,') + 8)) 321 - var binary = new Uint8Array(new ArrayBuffer(raw.length)) 322 - for (let i = 0; i < raw.length; i++) { 323 - binary[i] = raw.charCodeAt(i) 324 - } 325 - return binary 326 - }
+82
src/lib/api/upload-blob.ts
··· 1 + import RNFS from 'react-native-fs' 2 + import {BskyAgent, ComAtprotoRepoUploadBlob} from '@atproto/api' 3 + 4 + /** 5 + * @param encoding Allows overriding the blob's type 6 + */ 7 + export async function uploadBlob( 8 + agent: BskyAgent, 9 + input: string | Blob, 10 + encoding?: string, 11 + ): Promise<ComAtprotoRepoUploadBlob.Response> { 12 + if (typeof input === 'string' && input.startsWith('file:')) { 13 + const blob = await asBlob(input) 14 + return agent.uploadBlob(blob, {encoding}) 15 + } 16 + 17 + if (typeof input === 'string' && input.startsWith('/')) { 18 + const blob = await asBlob(`file://${input}`) 19 + return agent.uploadBlob(blob, {encoding}) 20 + } 21 + 22 + if (typeof input === 'string' && input.startsWith('data:')) { 23 + const blob = await fetch(input).then(r => r.blob()) 24 + return agent.uploadBlob(blob, {encoding}) 25 + } 26 + 27 + if (input instanceof Blob) { 28 + return agent.uploadBlob(input, {encoding}) 29 + } 30 + 31 + throw new TypeError(`Invalid uploadBlob input: ${typeof input}`) 32 + } 33 + 34 + async function asBlob(uri: string): Promise<Blob> { 35 + return withSafeFile(uri, async safeUri => { 36 + // Note 37 + // Android does not support `fetch()` on `file://` URIs. for this reason, we 38 + // use XMLHttpRequest instead of simply calling: 39 + 40 + // return fetch(safeUri.replace('file:///', 'file:/')).then(r => r.blob()) 41 + 42 + return await new Promise((resolve, reject) => { 43 + const xhr = new XMLHttpRequest() 44 + xhr.onload = () => resolve(xhr.response) 45 + xhr.onerror = () => reject(new Error('Failed to load blob')) 46 + xhr.responseType = 'blob' 47 + xhr.open('GET', safeUri, true) 48 + xhr.send(null) 49 + }) 50 + }) 51 + } 52 + 53 + // HACK 54 + // React native has a bug that inflates the size of jpegs on upload 55 + // we get around that by renaming the file ext to .bin 56 + // see https://github.com/facebook/react-native/issues/27099 57 + // -prf 58 + async function withSafeFile<T>( 59 + uri: string, 60 + fn: (path: string) => Promise<T>, 61 + ): Promise<T> { 62 + if (uri.endsWith('.jpeg') || uri.endsWith('.jpg')) { 63 + // Since we don't "own" the file, we should avoid renaming or modifying it. 64 + // Instead, let's copy it to a temporary file and use that (then remove the 65 + // temporary file). 66 + const newPath = uri.replace(/\.jpe?g$/, '.bin') 67 + try { 68 + await RNFS.copyFile(uri, newPath) 69 + } catch { 70 + // Failed to copy the file, just use the original 71 + return await fn(uri) 72 + } 73 + try { 74 + return await fn(newPath) 75 + } finally { 76 + // Remove the temporary file 77 + await RNFS.unlink(newPath) 78 + } 79 + } else { 80 + return fn(uri) 81 + } 82 + }
+26
src/lib/api/upload-blob.web.ts
··· 1 + import {BskyAgent, ComAtprotoRepoUploadBlob} from '@atproto/api' 2 + 3 + /** 4 + * @note It is recommended, on web, to use the `file` instance of the file 5 + * selector input element, rather than a `data:` URL, to avoid 6 + * loading the file into memory. `File` extends `Blob` "file" instances can 7 + * be passed directly to this function. 8 + */ 9 + export async function uploadBlob( 10 + agent: BskyAgent, 11 + input: string | Blob, 12 + encoding?: string, 13 + ): Promise<ComAtprotoRepoUploadBlob.Response> { 14 + if (typeof input === 'string' && input.startsWith('data:')) { 15 + const blob = await fetch(input).then(r => r.blob()) 16 + return agent.uploadBlob(blob, {encoding}) 17 + } 18 + 19 + if (input instanceof Blob) { 20 + return agent.uploadBlob(input, { 21 + encoding, 22 + }) 23 + } 24 + 25 + throw new TypeError(`Invalid uploadBlob input: ${typeof input}`) 26 + }
+1 -7
src/lib/media/manip.ts
··· 218 218 // Normalize is necessary for Android, otherwise it doesn't delete. 219 219 const normalizedPath = normalizePath(path) 220 220 try { 221 - await Promise.allSettled([ 222 - deleteAsync(normalizedPath, {idempotent: true}), 223 - // HACK: Try this one too. Might exist due to api-polyfill hack. 224 - deleteAsync(normalizedPath.replace(/\.jpe?g$/, '.bin'), { 225 - idempotent: true, 226 - }), 227 - ]) 221 + await deleteAsync(normalizedPath, {idempotent: true}) 228 222 } catch (e) { 229 223 console.error('Failed to delete file', e) 230 224 }
+1 -1
src/screens/SignupQueued.tsx
··· 40 40 const res = await agent.com.atproto.temp.checkSignupQueue() 41 41 if (res.data.activated) { 42 42 // ready to go, exchange the access token for a usable one and kick off onboarding 43 - await agent.refreshSession() 43 + await agent.sessionManager.refreshSession() 44 44 if (!isSignupQueued(agent.session?.accessJwt)) { 45 45 onboardingDispatch({type: 'start'}) 46 46 }
+2 -2
src/state/queries/preferences/index.ts
··· 37 37 refetchOnWindowFocus: true, 38 38 queryKey: preferencesQueryKey, 39 39 queryFn: async () => { 40 - if (agent.session?.did === undefined) { 40 + if (!agent.did) { 41 41 return DEFAULT_LOGGED_OUT_PREFERENCES 42 42 } else { 43 43 const res = await agent.getPreferences() 44 44 45 45 // save to local storage to ensure there are labels on initial requests 46 46 saveLabelers( 47 - agent.session.did, 47 + agent.did, 48 48 res.moderationPrefs.labelers.map(l => l.did), 49 49 ) 50 50
+36 -36
src/state/session/__tests__/session-test.ts
··· 27 27 `) 28 28 29 29 const agent = new BskyAgent({service: 'https://alice.com'}) 30 - agent.session = { 30 + agent.sessionManager.session = { 31 31 active: true, 32 32 did: 'alice-did', 33 33 handle: 'alice.test', ··· 118 118 let state = getInitialState([]) 119 119 120 120 const agent1 = new BskyAgent({service: 'https://alice.com'}) 121 - agent1.session = { 121 + agent1.sessionManager.session = { 122 122 active: true, 123 123 did: 'alice-did', 124 124 handle: 'alice.test', ··· 166 166 `) 167 167 168 168 const agent2 = new BskyAgent({service: 'https://bob.com'}) 169 - agent2.session = { 169 + agent2.sessionManager.session = { 170 170 active: true, 171 171 did: 'bob-did', 172 172 handle: 'bob.test', ··· 230 230 `) 231 231 232 232 const agent3 = new BskyAgent({service: 'https://alice.com'}) 233 - agent3.session = { 233 + agent3.sessionManager.session = { 234 234 active: true, 235 235 did: 'alice-did', 236 236 handle: 'alice-updated.test', ··· 294 294 `) 295 295 296 296 const agent4 = new BskyAgent({service: 'https://jay.com'}) 297 - agent4.session = { 297 + agent4.sessionManager.session = { 298 298 active: true, 299 299 did: 'jay-did', 300 300 handle: 'jay.test', ··· 445 445 let state = getInitialState([]) 446 446 447 447 const agent1 = new BskyAgent({service: 'https://alice.com'}) 448 - agent1.session = { 448 + agent1.sessionManager.session = { 449 449 active: true, 450 450 did: 'alice-did', 451 451 handle: 'alice.test', ··· 502 502 `) 503 503 504 504 const agent2 = new BskyAgent({service: 'https://alice.com'}) 505 - agent2.session = { 505 + agent2.sessionManager.session = { 506 506 active: true, 507 507 did: 'alice-did', 508 508 handle: 'alice.test', ··· 553 553 let state = getInitialState([]) 554 554 555 555 const agent1 = new BskyAgent({service: 'https://alice.com'}) 556 - agent1.session = { 556 + agent1.sessionManager.session = { 557 557 active: true, 558 558 did: 'alice-did', 559 559 handle: 'alice.test', ··· 598 598 let state = getInitialState([]) 599 599 600 600 const agent1 = new BskyAgent({service: 'https://alice.com'}) 601 - agent1.session = { 601 + agent1.sessionManager.session = { 602 602 active: true, 603 603 did: 'alice-did', 604 604 handle: 'alice.test', ··· 606 606 refreshJwt: 'alice-refresh-jwt-1', 607 607 } 608 608 const agent2 = new BskyAgent({service: 'https://bob.com'}) 609 - agent2.session = { 609 + agent2.sessionManager.session = { 610 610 active: true, 611 611 did: 'bob-did', 612 612 handle: 'bob.test', ··· 678 678 let state = getInitialState([]) 679 679 680 680 const agent1 = new BskyAgent({service: 'https://alice.com'}) 681 - agent1.session = { 681 + agent1.sessionManager.session = { 682 682 active: true, 683 683 did: 'alice-did', 684 684 handle: 'alice.test', ··· 695 695 expect(state.accounts.length).toBe(1) 696 696 expect(state.currentAgentState.did).toBe('alice-did') 697 697 698 - agent1.session = { 698 + agent1.sessionManager.session = { 699 699 active: true, 700 700 did: 'alice-did', 701 701 handle: 'alice-updated.test', ··· 748 748 } 749 749 `) 750 750 751 - agent1.session = { 751 + agent1.sessionManager.session = { 752 752 active: true, 753 753 did: 'alice-did', 754 754 handle: 'alice-updated.test', ··· 801 801 } 802 802 `) 803 803 804 - agent1.session = { 804 + agent1.sessionManager.session = { 805 805 active: true, 806 806 did: 'alice-did', 807 807 handle: 'alice-updated.test', ··· 859 859 let state = getInitialState([]) 860 860 861 861 const agent1 = new BskyAgent({service: 'https://alice.com'}) 862 - agent1.session = { 862 + agent1.sessionManager.session = { 863 863 active: true, 864 864 did: 'alice-did', 865 865 handle: 'alice.test', ··· 876 876 expect(state.accounts.length).toBe(1) 877 877 expect(state.currentAgentState.did).toBe('alice-did') 878 878 879 - agent1.session = { 879 + agent1.sessionManager.session = { 880 880 active: true, 881 881 did: 'alice-did', 882 882 handle: 'alice-updated.test', ··· 907 907 ]) 908 908 expect(lastState === state).toBe(true) 909 909 910 - agent1.session = { 910 + agent1.sessionManager.session = { 911 911 active: true, 912 912 did: 'alice-did', 913 913 handle: 'alice-updated.test', ··· 931 931 let state = getInitialState([]) 932 932 933 933 const agent1 = new BskyAgent({service: 'https://alice.com'}) 934 - agent1.session = { 934 + agent1.sessionManager.session = { 935 935 active: true, 936 936 did: 'alice-did', 937 937 handle: 'alice.test', ··· 940 940 } 941 941 942 942 const agent2 = new BskyAgent({service: 'https://bob.com'}) 943 - agent2.session = { 943 + agent2.sessionManager.session = { 944 944 active: true, 945 945 did: 'bob-did', 946 946 handle: 'bob.test', ··· 965 965 expect(state.accounts.length).toBe(2) 966 966 expect(state.currentAgentState.did).toBe('bob-did') 967 967 968 - agent1.session = { 968 + agent1.sessionManager.session = { 969 969 active: true, 970 970 did: 'alice-did', 971 971 handle: 'alice-updated.test', ··· 1032 1032 } 1033 1033 `) 1034 1034 1035 - agent2.session = { 1035 + agent2.sessionManager.session = { 1036 1036 active: true, 1037 1037 did: 'bob-did', 1038 1038 handle: 'bob-updated.test', ··· 1099 1099 1100 1100 // Ignore other events for inactive agent. 1101 1101 const lastState = state 1102 - agent1.session = undefined 1102 + agent1.sessionManager.session = undefined 1103 1103 state = run(state, [ 1104 1104 { 1105 1105 type: 'received-agent-event', ··· 1126 1126 let state = getInitialState([]) 1127 1127 1128 1128 const agent1 = new BskyAgent({service: 'https://alice.com'}) 1129 - agent1.session = { 1129 + agent1.sessionManager.session = { 1130 1130 active: true, 1131 1131 did: 'alice-did', 1132 1132 handle: 'alice.test', ··· 1135 1135 } 1136 1136 1137 1137 const agent2 = new BskyAgent({service: 'https://bob.com'}) 1138 - agent2.session = { 1138 + agent2.sessionManager.session = { 1139 1139 active: true, 1140 1140 did: 'bob-did', 1141 1141 handle: 'bob.test', ··· 1162 1162 expect(state.accounts.length).toBe(1) 1163 1163 expect(state.currentAgentState.did).toBe('bob-did') 1164 1164 1165 - agent1.session = { 1165 + agent1.sessionManager.session = { 1166 1166 active: true, 1167 1167 did: 'alice-did', 1168 1168 handle: 'alice.test', ··· 1188 1188 let state = getInitialState([]) 1189 1189 1190 1190 const agent1 = new BskyAgent({service: 'https://alice.com'}) 1191 - agent1.session = { 1191 + agent1.sessionManager.session = { 1192 1192 active: true, 1193 1193 did: 'alice-did', 1194 1194 handle: 'alice.test', ··· 1206 1206 expect(state.accounts.length).toBe(1) 1207 1207 expect(state.currentAgentState.did).toBe('alice-did') 1208 1208 1209 - agent1.session = undefined 1209 + agent1.sessionManager.session = undefined 1210 1210 state = run(state, [ 1211 1211 { 1212 1212 type: 'received-agent-event', ··· 1255 1255 let state = getInitialState([]) 1256 1256 1257 1257 const agent1 = new BskyAgent({service: 'https://alice.com'}) 1258 - agent1.session = { 1258 + agent1.sessionManager.session = { 1259 1259 active: true, 1260 1260 did: 'alice-did', 1261 1261 handle: 'alice.test', ··· 1273 1273 expect(state.accounts[0].accessJwt).toBe('alice-access-jwt-1') 1274 1274 expect(state.currentAgentState.did).toBe('alice-did') 1275 1275 1276 - agent1.session = undefined 1276 + agent1.sessionManager.session = undefined 1277 1277 state = run(state, [ 1278 1278 { 1279 1279 type: 'received-agent-event', ··· 1320 1320 let state = getInitialState([]) 1321 1321 1322 1322 const agent1 = new BskyAgent({service: 'https://alice.com'}) 1323 - agent1.session = { 1323 + agent1.sessionManager.session = { 1324 1324 active: true, 1325 1325 did: 'alice-did', 1326 1326 handle: 'alice.test', ··· 1338 1338 expect(state.accounts[0].accessJwt).toBe('alice-access-jwt-1') 1339 1339 expect(state.currentAgentState.did).toBe('alice-did') 1340 1340 1341 - agent1.session = undefined 1341 + agent1.sessionManager.session = undefined 1342 1342 state = run(state, [ 1343 1343 { 1344 1344 type: 'received-agent-event', ··· 1385 1385 let state = getInitialState([]) 1386 1386 1387 1387 const agent1 = new BskyAgent({service: 'https://alice.com'}) 1388 - agent1.session = { 1388 + agent1.sessionManager.session = { 1389 1389 active: true, 1390 1390 did: 'alice-did', 1391 1391 handle: 'alice.test', ··· 1393 1393 refreshJwt: 'alice-refresh-jwt-1', 1394 1394 } 1395 1395 const agent2 = new BskyAgent({service: 'https://bob.com'}) 1396 - agent2.session = { 1396 + agent2.sessionManager.session = { 1397 1397 active: true, 1398 1398 did: 'bob-did', 1399 1399 handle: 'bob.test', ··· 1416 1416 expect(state.currentAgentState.did).toBe('bob-did') 1417 1417 1418 1418 const anotherTabAgent1 = new BskyAgent({service: 'https://jay.com'}) 1419 - anotherTabAgent1.session = { 1419 + anotherTabAgent1.sessionManager.session = { 1420 1420 active: true, 1421 1421 did: 'jay-did', 1422 1422 handle: 'jay.test', ··· 1424 1424 refreshJwt: 'jay-refresh-jwt-1', 1425 1425 } 1426 1426 const anotherTabAgent2 = new BskyAgent({service: 'https://alice.com'}) 1427 - anotherTabAgent2.session = { 1427 + anotherTabAgent2.sessionManager.session = { 1428 1428 active: true, 1429 1429 did: 'bob-did', 1430 1430 handle: 'bob.test', ··· 1492 1492 `) 1493 1493 1494 1494 const anotherTabAgent3 = new BskyAgent({service: 'https://clarence.com'}) 1495 - anotherTabAgent3.session = { 1495 + anotherTabAgent3.sessionManager.session = { 1496 1496 active: true, 1497 1497 did: 'clarence-did', 1498 1498 handle: 'clarence.test',
+36 -8
src/state/session/agent.ts
··· 1 - import {AtpSessionData, AtpSessionEvent, BskyAgent} from '@atproto/api' 1 + import { 2 + AtpPersistSessionHandler, 3 + AtpSessionData, 4 + AtpSessionEvent, 5 + BskyAgent, 6 + } from '@atproto/api' 2 7 import {TID} from '@atproto/common-web' 3 8 4 9 import {networkRetry} from '#/lib/async/retry' ··· 20 25 import {SessionAccount} from './types' 21 26 import {isSessionExpired, isSignupQueued} from './util' 22 27 28 + type SetPersistSessionHandler = (cb: AtpPersistSessionHandler) => void 29 + 23 30 export function createPublicAgent() { 24 31 configureModerationForGuest() // Side effect but only relevant for tests 25 32 return new BskyAgent({service: PUBLIC_BSKY_SERVICE}) ··· 32 39 did: string, 33 40 event: AtpSessionEvent, 34 41 ) => void, 42 + setPersistSessionHandler: SetPersistSessionHandler, 35 43 ) { 36 44 const agent = new BskyAgent({service: storedAccount.service}) 37 45 if (storedAccount.pdsUrl) { 38 - agent.pdsUrl = agent.api.xrpc.uri = new URL(storedAccount.pdsUrl) 46 + agent.sessionManager.pdsUrl = new URL(storedAccount.pdsUrl) 39 47 } 40 48 const gates = tryFetchGates(storedAccount.did, 'prefer-low-latency') 41 49 const moderation = configureModerationForAccount(agent, storedAccount) ··· 43 51 if (isSessionExpired(storedAccount)) { 44 52 await networkRetry(1, () => agent.resumeSession(prevSession)) 45 53 } else { 46 - agent.session = prevSession 54 + agent.sessionManager.session = prevSession 47 55 if (!storedAccount.signupQueued) { 48 - // Intentionally not awaited to unblock the UI: 49 56 networkRetry(3, () => agent.resumeSession(prevSession)).catch( 50 57 (e: any) => { 51 58 logger.error(`networkRetry failed to resume session`, { ··· 60 67 } 61 68 } 62 69 63 - return prepareAgent(agent, gates, moderation, onSessionChange) 70 + return prepareAgent( 71 + agent, 72 + gates, 73 + moderation, 74 + onSessionChange, 75 + setPersistSessionHandler, 76 + ) 64 77 } 65 78 66 79 export async function createAgentAndLogin( ··· 80 93 did: string, 81 94 event: AtpSessionEvent, 82 95 ) => void, 96 + setPersistSessionHandler: SetPersistSessionHandler, 83 97 ) { 84 98 const agent = new BskyAgent({service}) 85 99 await agent.login({identifier, password, authFactorToken}) ··· 87 101 const account = agentToSessionAccountOrThrow(agent) 88 102 const gates = tryFetchGates(account.did, 'prefer-fresh-gates') 89 103 const moderation = configureModerationForAccount(agent, account) 90 - return prepareAgent(agent, moderation, gates, onSessionChange) 104 + return prepareAgent( 105 + agent, 106 + moderation, 107 + gates, 108 + onSessionChange, 109 + setPersistSessionHandler, 110 + ) 91 111 } 92 112 93 113 export async function createAgentAndCreateAccount( ··· 115 135 did: string, 116 136 event: AtpSessionEvent, 117 137 ) => void, 138 + setPersistSessionHandler: SetPersistSessionHandler, 118 139 ) { 119 140 const agent = new BskyAgent({service}) 120 141 await agent.createAccount({ ··· 174 195 logger.error(e, {context: `session: failed snoozeEmailConfirmationPrompt`}) 175 196 } 176 197 177 - return prepareAgent(agent, gates, moderation, onSessionChange) 198 + return prepareAgent( 199 + agent, 200 + gates, 201 + moderation, 202 + onSessionChange, 203 + setPersistSessionHandler, 204 + ) 178 205 } 179 206 180 207 async function prepareAgent( ··· 187 214 did: string, 188 215 event: AtpSessionEvent, 189 216 ) => void, 217 + setPersistSessionHandler: (cb: AtpPersistSessionHandler) => void, 190 218 ) { 191 219 // There's nothing else left to do, so block on them here. 192 220 await Promise.all([gates, moderation]) 193 221 194 222 // Now the agent is ready. 195 223 const account = agentToSessionAccountOrThrow(agent) 196 - agent.setPersistSessionHandler(event => { 224 + setPersistSessionHandler(event => { 197 225 onSessionChange(agent, account.did, event) 198 226 if (event !== 'create' && event !== 'update') { 199 227 addSessionErrorLog(account.did, event)
+20 -4
src/state/session/index.tsx
··· 1 1 import React from 'react' 2 - import {AtpSessionEvent, BskyAgent} from '@atproto/api' 2 + import { 3 + AtpPersistSessionHandler, 4 + AtpSessionEvent, 5 + BskyAgent, 6 + } from '@atproto/api' 3 7 4 8 import {track} from '#/lib/analytics/analytics' 5 9 import {logEvent} from '#/lib/statsig/statsig' ··· 47 51 return initialState 48 52 }) 49 53 54 + const persistSessionHandler = React.useRef< 55 + AtpPersistSessionHandler | undefined 56 + >(undefined) 57 + const setPersistSessionHandler = ( 58 + newHandler: AtpPersistSessionHandler | undefined, 59 + ) => { 60 + persistSessionHandler.current = newHandler 61 + } 62 + 50 63 const onAgentSessionChange = React.useCallback( 51 64 (agent: BskyAgent, accountDid: string, sessionEvent: AtpSessionEvent) => { 52 65 const refreshedAccount = agentToSessionAccount(agent) // Mutable, so snapshot it right away. ··· 73 86 const {agent, account} = await createAgentAndCreateAccount( 74 87 params, 75 88 onAgentSessionChange, 89 + setPersistSessionHandler, 76 90 ) 77 91 78 92 if (signal.aborted) { ··· 97 111 const {agent, account} = await createAgentAndLogin( 98 112 params, 99 113 onAgentSessionChange, 114 + setPersistSessionHandler, 100 115 ) 101 116 102 117 if (signal.aborted) { ··· 138 153 const {agent, account} = await createAgentAndResume( 139 154 storedAccount, 140 155 onAgentSessionChange, 156 + setPersistSessionHandler, 141 157 ) 142 158 143 159 if (signal.aborted) { ··· 202 218 } else { 203 219 const agent = state.currentAgentState.agent as BskyAgent 204 220 const prevSession = agent.session 205 - agent.session = sessionAccountToSession(syncedAccount) 221 + agent.sessionManager.session = sessionAccountToSession(syncedAccount) 206 222 addSessionDebugLog({ 207 223 type: 'agent:patch', 208 224 agent, ··· 249 265 addSessionDebugLog({type: 'agent:switch', prevAgent, nextAgent: agent}) 250 266 // We never reuse agents so let's fully neutralize the previous one. 251 267 // This ensures it won't try to consume any refresh tokens. 252 - prevAgent.session = undefined 253 - prevAgent.setPersistSessionHandler(undefined) 268 + prevAgent.sessionManager.session = undefined 269 + setPersistSessionHandler(undefined) 254 270 } 255 271 }, [agent]) 256 272
+1 -1
src/state/session/logging.ts
··· 56 56 type: 'agent:patch' 57 57 agent: object 58 58 prevSession: AtpSessionData | undefined 59 - nextSession: AtpSessionData 59 + nextSession: AtpSessionData | undefined 60 60 } 61 61 62 62 export function wrapSessionReducerForLogging(reducer: Reducer): Reducer {
+312 -123
yarn.lock
··· 34 34 jsonpointer "^5.0.0" 35 35 leven "^3.1.0" 36 36 37 - "@atproto/api@0.12.29": 38 - version "0.12.29" 39 - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.29.tgz#95a19202c2f0eec4c955909685be11009ba9b9a1" 40 - integrity sha512-PyzPLjGWR0qNOMrmj3Nt3N5NuuANSgOk/33Bu3j+rFjjPrHvk9CI6iQPU6zuDaDCoyOTRJRafw8X/aMQw+ilgw== 37 + "@atproto-labs/fetch-node@0.1.0": 38 + version "0.1.0" 39 + resolved "https://registry.yarnpkg.com/@atproto-labs/fetch-node/-/fetch-node-0.1.0.tgz#692666d57ec24a7ba0813077a303baccf26108e0" 40 + integrity sha512-DUHgaGw8LBqiGg51pUDuWK/alMcmNbpcK7ALzlF2Gw//TNLTsgrj0qY9aEtK+np9rEC+x/o3bN4SGnuQEpgqIg== 41 + dependencies: 42 + "@atproto-labs/fetch" "0.1.0" 43 + "@atproto-labs/pipe" "0.1.0" 44 + ipaddr.js "^2.1.0" 45 + psl "^1.9.0" 46 + undici "^6.14.1" 47 + 48 + "@atproto-labs/fetch@0.1.0": 49 + version "0.1.0" 50 + resolved "https://registry.yarnpkg.com/@atproto-labs/fetch/-/fetch-0.1.0.tgz#50a46943fd2f321dd748de28c73ba7cbfa493132" 51 + integrity sha512-uirja+uA/C4HNk7vayM+AJqsccxQn2wVziUHxbsjJGt/K6Q8ZOKDaEX2+GrcXvpUVcqUKh+94JFjuzH+CAEUlg== 52 + dependencies: 53 + "@atproto-labs/pipe" "0.1.0" 54 + optionalDependencies: 55 + zod "^3.23.8" 56 + 57 + "@atproto-labs/pipe@0.1.0": 58 + version "0.1.0" 59 + resolved "https://registry.yarnpkg.com/@atproto-labs/pipe/-/pipe-0.1.0.tgz#c8d86923b6d8e900d39efe6fdcdf0d897c434086" 60 + integrity sha512-ghOqHFyJlQVFPESzlVHjKroP0tPzbmG5Jms0dNI9yLDEfL8xp4OFPWLX4f6T8mRq69wWs4nIDM3sSsFbFqLa1w== 61 + 62 + "@atproto-labs/simple-store-memory@0.1.1": 63 + version "0.1.1" 64 + resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store-memory/-/simple-store-memory-0.1.1.tgz#54526a1f8ec978822be9fad75106ad8b78500dd3" 65 + integrity sha512-PCRqhnZ8NBNBvLku53O56T0lsVOtclfIrQU/rwLCc4+p45/SBPrRYNBi6YFq5rxZbK6Njos9MCmILV/KLQxrWA== 41 66 dependencies: 42 - "@atproto/common-web" "^0.3.0" 43 - "@atproto/lexicon" "^0.4.0" 44 - "@atproto/syntax" "^0.3.0" 45 - "@atproto/xrpc" "^0.5.0" 46 - await-lock "^2.2.2" 47 - multiformats "^9.9.0" 48 - tlds "^1.234.0" 67 + "@atproto-labs/simple-store" "0.1.1" 68 + lru-cache "^10.2.0" 69 + 70 + "@atproto-labs/simple-store@0.1.1": 71 + version "0.1.1" 72 + resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store/-/simple-store-0.1.1.tgz#e743a2722b5d8732166f0a72aca8bd10e9bff106" 73 + integrity sha512-WKILW2b3QbAYKh+w5U2x6p5FqqLl0nAeLwGeDY+KjX01K4Dq3vQTR9b/qNp0jZm48CabPQVrqCv0PPU9LgRRRg== 49 74 50 - "@atproto/api@^0.12.3": 51 - version "0.12.3" 52 - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.3.tgz#5b7b1c7d4210ee9315961504900c8409395cbb17" 53 - integrity sha512-y/kGpIEo+mKGQ7VOphpqCAigTI0LZRmDThNChTfSzDKm9TzEobwiw0zUID0Yw6ot1iLLFx3nKURmuZAYlEuobw== 75 + "@atproto/api@0.13.0", "@atproto/api@^0.13.0": 76 + version "0.13.0" 77 + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.0.tgz#d1c65a407f1c3c6aba5be9425f4f739a01419bd8" 78 + integrity sha512-04kzIDkoEVSP7zMVOT5ezCVQcOrbXWjGYO2YBc3/tBvQ90V1pl9I+mLyz1uUHE+wRE1IRWKACcWhAz8SrYz3pA== 54 79 dependencies: 55 80 "@atproto/common-web" "^0.3.0" 56 - "@atproto/lexicon" "^0.4.0" 81 + "@atproto/lexicon" "^0.4.1" 57 82 "@atproto/syntax" "^0.3.0" 58 - "@atproto/xrpc" "^0.5.0" 83 + "@atproto/xrpc" "^0.6.0" 84 + await-lock "^2.2.2" 59 85 multiformats "^9.9.0" 60 86 tlds "^1.234.0" 61 87 62 - "@atproto/aws@^0.2.0": 63 - version "0.2.0" 64 - resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.0.tgz#17f3faf744824457cabd62f87be8bf08cacf8029" 65 - integrity sha512-F09SHiC9CX3ydfrvYZbkpfES48UGCQNnznNVgJ3QyKSN8ON+BoWmGCpAFtn3AWeEoU0w9h0hypNvUm5nORv+5g== 88 + "@atproto/aws@^0.2.2": 89 + version "0.2.2" 90 + resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.2.tgz#703e5e06f288bcf61c6d99a990738f1e7299e653" 91 + integrity sha512-j7eR7+sQumFsc66/5xyCDez9JtR6dlZc+fOdwdh85nCJD4zmQyU4r1CKrA48wQ3tkzze+ASEb1SgODuIQmIugA== 66 92 dependencies: 67 - "@atproto/common" "^0.4.0" 93 + "@atproto/common" "^0.4.1" 68 94 "@atproto/crypto" "^0.4.0" 69 - "@atproto/repo" "^0.4.0" 95 + "@atproto/repo" "^0.4.2" 70 96 "@aws-sdk/client-cloudfront" "^3.261.0" 71 97 "@aws-sdk/client-kms" "^3.196.0" 72 98 "@aws-sdk/client-s3" "^3.224.0" ··· 76 102 multiformats "^9.9.0" 77 103 uint8arrays "3.0.0" 78 104 79 - "@atproto/bsky@^0.0.45": 80 - version "0.0.45" 81 - resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.45.tgz#c3083d8038fe8c5ff921d9bcb0b5a043cc840827" 82 - integrity sha512-osWeigdYzQH2vZki+eszCR8ta9zdUB4om79aFmnE+zvxw7HFduwAAbcHf6kmmiLCfaOWvCsYb1wS2i3IC66TAg== 105 + "@atproto/bsky@^0.0.74": 106 + version "0.0.74" 107 + resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.74.tgz#b735af6ded16778604378710a2e871350c29570a" 108 + integrity sha512-vyukmlBamoET0sZnDMOeTGAkQNV7KbHg65uIQ6OX4/QGynyaQP8SvSF0OsEBzBqOraxV1w9WT8AZrUbyl3uvIg== 83 109 dependencies: 84 - "@atproto/api" "^0.12.3" 85 - "@atproto/common" "^0.4.0" 110 + "@atproto/api" "^0.13.0" 111 + "@atproto/common" "^0.4.1" 86 112 "@atproto/crypto" "^0.4.0" 87 113 "@atproto/identity" "^0.4.0" 88 - "@atproto/lexicon" "^0.4.0" 89 - "@atproto/repo" "^0.4.0" 114 + "@atproto/lexicon" "^0.4.1" 115 + "@atproto/repo" "^0.4.2" 90 116 "@atproto/syntax" "^0.3.0" 91 - "@atproto/xrpc-server" "^0.5.1" 117 + "@atproto/xrpc-server" "^0.6.1" 92 118 "@bufbuild/protobuf" "^1.5.0" 93 119 "@connectrpc/connect" "^1.1.4" 94 120 "@connectrpc/connect-express" "^1.1.4" ··· 105 131 multiformats "^9.9.0" 106 132 p-queue "^6.6.2" 107 133 pg "^8.10.0" 108 - pino "^8.15.0" 134 + pino "^8.21.0" 109 135 pino-http "^8.2.1" 110 136 sharp "^0.32.6" 137 + statsig-node "^5.23.1" 111 138 structured-headers "^1.0.1" 112 139 typed-emitter "^2.1.0" 113 140 uint8arrays "3.0.0" 114 141 115 - "@atproto/bsync@^0.0.3": 116 - version "0.0.3" 117 - resolved "https://registry.yarnpkg.com/@atproto/bsync/-/bsync-0.0.3.tgz#2b0b8ef3686cf177846a80088317f2e89d1bf88f" 118 - integrity sha512-tJRwNgXzfNV57lzgWPvjtb1OMlMJH9SpsMeYhIii16zcaFUWwsb474BicKpkGRT+iCvtYzBT6gWlZE2Ijnhf7w== 142 + "@atproto/bsync@^0.0.5": 143 + version "0.0.5" 144 + resolved "https://registry.yarnpkg.com/@atproto/bsync/-/bsync-0.0.5.tgz#bf2fa45e4595fda12addcd6784314e4dbe409046" 145 + integrity sha512-xCCMHy14y4tQoXiGrfd0XjSnc4q7I9bUNqju9E8jrP95QTDedH1FQgybStbUIbHt0eEqY5v9E7iZBH3n7Kiz7A== 119 146 dependencies: 120 - "@atproto/common" "^0.4.0" 147 + "@atproto/common" "^0.4.1" 121 148 "@atproto/syntax" "^0.3.0" 122 149 "@bufbuild/protobuf" "^1.5.0" 123 150 "@connectrpc/connect" "^1.1.4" ··· 158 185 pino "^8.6.1" 159 186 zod "^3.14.2" 160 187 161 - "@atproto/common@^0.4.0": 162 - version "0.4.0" 163 - resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.0.tgz#d77696c7eb545426df727837d9ee333b429fe7ef" 164 - integrity sha512-yOXuPlCjT/OK9j+neIGYn9wkxx/AlxQSucysAF0xgwu0Ji8jAtKBf9Jv6R5ObYAjAD/kVUvEYumle+Yq/R9/7g== 188 + "@atproto/common@^0.4.1": 189 + version "0.4.1" 190 + resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.1.tgz#ca6fce47001ce8d031acd3fb4942fbfd81f72c43" 191 + integrity sha512-uL7kQIcBTbvkBDNfxMXL6lBH4fO2DQpHd2BryJxMtbw/4iEPKe9xBYApwECHhEIk9+zhhpTRZ15FJ3gxTXN82Q== 165 192 dependencies: 166 193 "@atproto/common-web" "^0.3.0" 167 194 "@ipld/dag-cbor" "^7.0.3" 168 195 cbor-x "^1.5.1" 169 196 iso-datestring-validator "^2.2.2" 170 197 multiformats "^9.9.0" 171 - pino "^8.15.0" 198 + pino "^8.21.0" 172 199 173 200 "@atproto/crypto@0.1.0": 174 201 version "0.1.0" ··· 190 217 "@noble/hashes" "^1.3.1" 191 218 uint8arrays "3.0.0" 192 219 193 - "@atproto/dev-env@^0.3.5": 194 - version "0.3.5" 195 - resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.5.tgz#cd13313dbc52131731d039a1d22808ee8193505d" 196 - integrity sha512-dqRNihzX1xIHbWPHmfYsliUUXyZn5FFhCeButrGie5soQmHA4okQJTB1XWDly3mdHLjUM90g+5zjRSAKoui77Q== 220 + "@atproto/dev-env@^0.3.39": 221 + version "0.3.39" 222 + resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.39.tgz#f498f087d4da43d5f86805c07d5f2b781e60fd6f" 223 + integrity sha512-rIeUO99DL8/gRKYEAkAFuTn77y8letEbKMXnfpsVX2YHD89VRdDyMxkYzRu2+31UjtGv62I+qTLLKQS4EcFItA== 197 224 dependencies: 198 - "@atproto/api" "^0.12.3" 199 - "@atproto/bsky" "^0.0.45" 200 - "@atproto/bsync" "^0.0.3" 225 + "@atproto/api" "^0.13.0" 226 + "@atproto/bsky" "^0.0.74" 227 + "@atproto/bsync" "^0.0.5" 201 228 "@atproto/common-web" "^0.3.0" 202 229 "@atproto/crypto" "^0.4.0" 203 230 "@atproto/identity" "^0.4.0" 204 - "@atproto/lexicon" "^0.4.0" 205 - "@atproto/ozone" "^0.1.7" 206 - "@atproto/pds" "^0.4.14" 231 + "@atproto/lexicon" "^0.4.1" 232 + "@atproto/ozone" "^0.1.36" 233 + "@atproto/pds" "^0.4.48" 207 234 "@atproto/syntax" "^0.3.0" 208 - "@atproto/xrpc-server" "^0.5.1" 235 + "@atproto/xrpc-server" "^0.6.1" 209 236 "@did-plc/lib" "^0.0.1" 210 237 "@did-plc/server" "^0.0.1" 211 238 axios "^0.27.2" ··· 224 251 "@atproto/crypto" "^0.4.0" 225 252 axios "^0.27.2" 226 253 227 - "@atproto/lexicon@^0.4.0": 228 - version "0.4.0" 229 - resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.0.tgz#63e8829945d80c25524882caa8ed27b1151cc576" 230 - integrity sha512-RvCBKdSI4M8qWm5uTNz1z3R2yIvIhmOsMuleOj8YR6BwRD+QbtUBy3l+xQ7iXf4M5fdfJFxaUNa6Ty0iRwdKqQ== 254 + "@atproto/jwk-jose@0.1.2": 255 + version "0.1.2" 256 + resolved "https://registry.yarnpkg.com/@atproto/jwk-jose/-/jwk-jose-0.1.2.tgz#236eadb740b498689d9a912d1254aa9ff58890a1" 257 + integrity sha512-lDwc/6lLn2aZ/JpyyggyjLFsJPMntrVzryyGUx5aNpuTS8SIuc4Ky0REhxqfLopQXJJZCuRRjagHG3uP05/moQ== 258 + dependencies: 259 + "@atproto/jwk" "0.1.1" 260 + jose "^5.2.0" 261 + 262 + "@atproto/jwk@0.1.1": 263 + version "0.1.1" 264 + resolved "https://registry.yarnpkg.com/@atproto/jwk/-/jwk-0.1.1.tgz#15bcad4a1778eeb20c82108e0ec55fef45cd07b6" 265 + integrity sha512-6h/bj1APUk7QcV9t/oA6+9DB5NZx9SZru9x+/pV5oHFI9Xz4ZuM5+dq1PfsJV54pZyqdnZ6W6M717cxoC7q7og== 266 + dependencies: 267 + multiformats "^9.9.0" 268 + zod "^3.23.8" 269 + 270 + "@atproto/lexicon@^0.4.1": 271 + version "0.4.1" 272 + resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.1.tgz#19155210570a2fafbcc7d4f655d9b813948e72a0" 273 + integrity sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA== 231 274 dependencies: 232 275 "@atproto/common-web" "^0.3.0" 233 276 "@atproto/syntax" "^0.3.0" 234 277 iso-datestring-validator "^2.2.2" 235 278 multiformats "^9.9.0" 236 - zod "^3.21.4" 279 + zod "^3.23.8" 280 + 281 + "@atproto/oauth-provider@^0.1.2": 282 + version "0.1.2" 283 + resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.1.2.tgz#a576a4c7795c7938a994e76192c19a2e73ffcddf" 284 + integrity sha512-z1YKK0XLDfSDtLP5ntPCviEtajvUHbI4TwzYQ5X9CAL9PoXjqhQg0U/csg1wGDs8qkbphF9gni9M2stlpH7H0g== 285 + dependencies: 286 + "@atproto-labs/fetch" "0.1.0" 287 + "@atproto-labs/fetch-node" "0.1.0" 288 + "@atproto-labs/pipe" "0.1.0" 289 + "@atproto-labs/simple-store" "0.1.1" 290 + "@atproto-labs/simple-store-memory" "0.1.1" 291 + "@atproto/jwk" "0.1.1" 292 + "@atproto/jwk-jose" "0.1.2" 293 + "@atproto/oauth-types" "0.1.2" 294 + "@hapi/accept" "^6.0.3" 295 + "@hapi/bourne" "^3.0.0" 296 + cookie "^0.6.0" 297 + http-errors "^2.0.0" 298 + jose "^5.2.0" 299 + oidc-token-hash "^5.0.3" 300 + psl "^1.9.0" 301 + zod "^3.23.8" 302 + optionalDependencies: 303 + ioredis "^5.3.2" 304 + keygrip "^1.1.0" 237 305 238 - "@atproto/ozone@^0.1.7": 239 - version "0.1.7" 240 - resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.7.tgz#248d88e1acfe56936651754975472d03d047d689" 241 - integrity sha512-vvaV0MFynOzZJcL8m8mEW21o1FFIkP+wHTXEC9LJrL3h03+PMaby8Ujmif6WX5eikhfxvr9xsU/Jxbi/iValuQ== 306 + "@atproto/oauth-types@0.1.2": 307 + version "0.1.2" 308 + resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.1.2.tgz#d6c497c8e5f88f1875c630adde4ed9c5d8a8b4f4" 309 + integrity sha512-yySPPTLxteFJ3O3xVWEhvBFx7rczgo4LK2nQNeqAPMZdYd5dpgvuZZ88nQQge074BfuOc0MWTnr0kPdxQMjjPw== 242 310 dependencies: 243 - "@atproto/api" "^0.12.3" 244 - "@atproto/common" "^0.4.0" 311 + "@atproto/jwk" "0.1.1" 312 + zod "^3.23.8" 313 + 314 + "@atproto/ozone@^0.1.36": 315 + version "0.1.36" 316 + resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.36.tgz#6a1a71fdff3ff486c5951a9e491e954b51703d53" 317 + integrity sha512-BQThLU5RFG+/bZli/fj5YrFU8jW5rkium7aplfJX2eHkV6huJnBU5DcgracjH2paPGC5L/zjYtibz5spqatKAg== 318 + dependencies: 319 + "@atproto/api" "^0.13.0" 320 + "@atproto/common" "^0.4.1" 245 321 "@atproto/crypto" "^0.4.0" 246 322 "@atproto/identity" "^0.4.0" 247 - "@atproto/lexicon" "^0.4.0" 323 + "@atproto/lexicon" "^0.4.1" 248 324 "@atproto/syntax" "^0.3.0" 249 - "@atproto/xrpc" "^0.5.0" 250 - "@atproto/xrpc-server" "^0.5.1" 325 + "@atproto/xrpc" "^0.6.0" 326 + "@atproto/xrpc-server" "^0.6.1" 251 327 "@did-plc/lib" "^0.0.1" 252 328 axios "^1.6.7" 253 329 compression "^1.7.4" ··· 255 331 express "^4.17.2" 256 332 http-terminator "^3.2.0" 257 333 kysely "^0.22.0" 334 + lande "^1.0.10" 258 335 multiformats "^9.9.0" 259 336 p-queue "^6.6.2" 260 337 pg "^8.10.0" 261 338 pino-http "^8.2.1" 339 + structured-headers "^1.0.1" 262 340 typed-emitter "^2.1.0" 263 341 uint8arrays "3.0.0" 264 342 265 - "@atproto/pds@^0.4.14": 266 - version "0.4.14" 267 - resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.14.tgz#5b55ef307323bda712f2ddaba5c1fff7740ed91b" 268 - integrity sha512-rqVcvtw5oMuuJIpWZbSSTSx19+JaZyUcg9OEjdlUmyEpToRN88zTEQySEksymrrLQkW/LPRyWGd7WthbGEuEfQ== 343 + "@atproto/pds@^0.4.48": 344 + version "0.4.48" 345 + resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.48.tgz#34f29846a0585f5cc33f1685eb75ad730b7dcb9f" 346 + integrity sha512-B5FpmECkGtA0EyhiB5rfhmQArmGekqqyzFnPlNpO5vOUrTTVKc9mgGfHLVJtrnwDUfGAuIgpigqZ8HgwS0DnMA== 269 347 dependencies: 270 - "@atproto/api" "^0.12.3" 271 - "@atproto/aws" "^0.2.0" 272 - "@atproto/common" "^0.4.0" 348 + "@atproto-labs/fetch-node" "0.1.0" 349 + "@atproto/api" "^0.13.0" 350 + "@atproto/aws" "^0.2.2" 351 + "@atproto/common" "^0.4.1" 273 352 "@atproto/crypto" "^0.4.0" 274 353 "@atproto/identity" "^0.4.0" 275 - "@atproto/lexicon" "^0.4.0" 276 - "@atproto/repo" "^0.4.0" 354 + "@atproto/lexicon" "^0.4.1" 355 + "@atproto/oauth-provider" "^0.1.2" 356 + "@atproto/repo" "^0.4.2" 277 357 "@atproto/syntax" "^0.3.0" 278 - "@atproto/xrpc" "^0.5.0" 279 - "@atproto/xrpc-server" "^0.5.1" 358 + "@atproto/xrpc" "^0.6.0" 359 + "@atproto/xrpc-server" "^0.6.1" 280 360 "@did-plc/lib" "^0.0.4" 281 - better-sqlite3 "^9.4.0" 361 + better-sqlite3 "^10.0.0" 282 362 bytes "^3.1.2" 283 363 compression "^1.7.4" 284 364 cors "^2.8.5" ··· 297 377 nodemailer "^6.8.0" 298 378 nodemailer-html-to-text "^3.2.0" 299 379 p-queue "^6.6.2" 300 - pino "^8.15.0" 380 + pino "^8.21.0" 301 381 pino-http "^8.2.1" 302 382 sharp "^0.32.6" 303 383 typed-emitter "^2.1.0" 304 384 uint8arrays "3.0.0" 305 - zod "^3.21.4" 385 + zod "^3.23.8" 306 386 307 - "@atproto/repo@^0.4.0": 308 - version "0.4.0" 309 - resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.4.0.tgz#e5d3195a8e4233c9bf060737b18ddee905af2d9a" 310 - integrity sha512-LB0DF/D8r8hB+qiGB0sWZuq7TSJYbWel+t572aCrLeCOmbRgnLkGPLUTOOUvLFYv8xz1BPZTbI8hy/vcUV79VA== 387 + "@atproto/repo@^0.4.2": 388 + version "0.4.2" 389 + resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.4.2.tgz#311eef52ef5df0b6f969fb4b329935a32db05313" 390 + integrity sha512-6hEGA3BmasPCoBGaIN/jKAjKJidCf+z8exkx/77V3WB7TboucSLHn/8gg+Xf03U7bJd6mn3F0YmPaRfJwqIT8w== 311 391 dependencies: 312 - "@atproto/common" "^0.4.0" 392 + "@atproto/common" "^0.4.1" 313 393 "@atproto/common-web" "^0.3.0" 314 394 "@atproto/crypto" "^0.4.0" 315 - "@atproto/lexicon" "^0.4.0" 395 + "@atproto/lexicon" "^0.4.1" 316 396 "@ipld/car" "^3.2.3" 317 397 "@ipld/dag-cbor" "^7.0.0" 318 398 multiformats "^9.9.0" 319 399 uint8arrays "3.0.0" 320 - zod "^3.21.4" 400 + zod "^3.23.8" 321 401 322 402 "@atproto/syntax@^0.3.0": 323 403 version "0.3.0" 324 404 resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3" 325 405 integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA== 326 406 327 - "@atproto/xrpc-server@^0.5.1": 328 - version "0.5.1" 329 - resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.5.1.tgz#f63c86ba60bd5b9c5a641ea57191ff83d9db41fd" 330 - integrity sha512-SXU6dscVe5iYxPeV79QIFs/yEEu7LLOzyHGoHG1kSNO6DjwxXTdcWOc8GSYGV6H+7VycOoPZPkyD9q4teJlj/w== 407 + "@atproto/xrpc-server@^0.6.1": 408 + version "0.6.1" 409 + resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.6.1.tgz#c8c75065ab6bc1a7f5c121b558acb5213f2afda6" 410 + integrity sha512-Qm0aJC1LbYYHaRGWoh0D2iG48VwRha1T1NEP/D5UkD4GzfjT8m5PDiZBtcyspJD/BEC7UYX9/BhMYCoZLQMYcA== 331 411 dependencies: 332 - "@atproto/common" "^0.4.0" 412 + "@atproto/common" "^0.4.1" 333 413 "@atproto/crypto" "^0.4.0" 334 - "@atproto/lexicon" "^0.4.0" 414 + "@atproto/lexicon" "^0.4.1" 415 + "@atproto/xrpc" "^0.6.0" 335 416 cbor-x "^1.5.1" 336 417 express "^4.17.2" 337 418 http-errors "^2.0.0" ··· 339 420 rate-limiter-flexible "^2.4.1" 340 421 uint8arrays "3.0.0" 341 422 ws "^8.12.0" 342 - zod "^3.21.4" 423 + zod "^3.23.8" 343 424 344 - "@atproto/xrpc@^0.5.0": 345 - version "0.5.0" 346 - resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.5.0.tgz#dacbfd8f7b13f0ab5bd56f8fdd4b460e132a6032" 347 - integrity sha512-swu+wyOLvYW4l3n+VAuJbHcPcES+tin2Lsrp8Bw5aIXIICiuFn1YMFlwK9JwVUzTH21Py1s1nHEjr4CJeElJog== 425 + "@atproto/xrpc@^0.6.0": 426 + version "0.6.0" 427 + resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.0.tgz#668c3262e67e2afa65951ea79a03bfe3720ddf5c" 428 + integrity sha512-5BbhBTv5j6MC3iIQ4+vYxQE7nLy2dDGQ+LYJrH8PptOCUdq0Pwg6aRccQ3y52kUZlhE/mzOTZ8Ngiy9pSAyfVQ== 348 429 dependencies: 349 - "@atproto/lexicon" "^0.4.0" 350 - zod "^3.21.4" 430 + "@atproto/lexicon" "^0.4.1" 431 + zod "^3.23.8" 351 432 352 433 "@aws-crypto/crc32@3.0.0": 353 434 version "3.0.0" ··· 4001 4082 resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" 4002 4083 integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== 4003 4084 4085 + "@hapi/accept@^6.0.3": 4086 + version "6.0.3" 4087 + resolved "https://registry.yarnpkg.com/@hapi/accept/-/accept-6.0.3.tgz#eef0800a4f89cd969da8e5d0311dc877c37279ab" 4088 + integrity sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw== 4089 + dependencies: 4090 + "@hapi/boom" "^10.0.1" 4091 + "@hapi/hoek" "^11.0.2" 4092 + 4093 + "@hapi/boom@^10.0.1": 4094 + version "10.0.1" 4095 + resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685" 4096 + integrity sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA== 4097 + dependencies: 4098 + "@hapi/hoek" "^11.0.2" 4099 + 4100 + "@hapi/bourne@^3.0.0": 4101 + version "3.0.0" 4102 + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-3.0.0.tgz#f11fdf7dda62fe8e336fa7c6642d9041f30356d7" 4103 + integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w== 4104 + 4105 + "@hapi/hoek@^11.0.2": 4106 + version "11.0.4" 4107 + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-11.0.4.tgz#42a7f244fd3dd777792bfb74b8c6340ae9182f37" 4108 + integrity sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ== 4109 + 4004 4110 "@hapi/hoek@^9.0.0": 4005 4111 version "9.3.0" 4006 4112 resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" ··· 9453 9559 dependencies: 9454 9560 open "^8.0.4" 9455 9561 9456 - better-sqlite3@^9.4.0: 9457 - version "9.4.5" 9458 - resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-9.4.5.tgz#1d3422443a9924637cb06cc3ccc941b2ae932c65" 9459 - integrity sha512-uFVyoyZR9BNcjSca+cp3MWCv6upAv+tbMC4SWM51NIMhoQOm4tjIkyxFO/ZsYdGAF61WJBgdzyJcz4OokJi0gQ== 9562 + better-sqlite3@^10.0.0: 9563 + version "10.1.0" 9564 + resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-10.1.0.tgz#8dc07e496fc014a7cd2211f79e591f6ba92838e8" 9565 + integrity sha512-hqpHJaCfKEZFaAWdMh6crdzRWyzQzfP6Ih8TYI0vFn01a6ZTDSbJIMXN+6AMBaBOh99DzUy8l3PsV9R3qnJDng== 9460 9566 dependencies: 9461 9567 bindings "^1.5.0" 9462 9568 prebuild-install "^7.1.1" ··· 10304 10410 version "0.5.0" 10305 10411 resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 10306 10412 integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 10413 + 10414 + cookie@^0.6.0: 10415 + version "0.6.0" 10416 + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" 10417 + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== 10307 10418 10308 10419 copy-webpack-plugin@^10.2.0: 10309 10420 version "10.2.4" ··· 13779 13890 resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" 13780 13891 integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== 13781 13892 13893 + ip3country@^5.0.0: 13894 + version "5.0.0" 13895 + resolved "https://registry.yarnpkg.com/ip3country/-/ip3country-5.0.0.tgz#f1394b050c51ba9c10cc691c8eb240bba3d7177a" 13896 + integrity sha512-lcFLMFU4eO1Z7tIpbVFZkaZ5ltqpeaRx7L9NsAbA9uA7/O/rj3RF8+evE5gDitooaTTIqjdzZrenFO/OOxQ2ew== 13897 + 13782 13898 ipaddr.js@1.9.1, ipaddr.js@^1.9.0: 13783 13899 version "1.9.1" 13784 13900 resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" ··· 13788 13904 version "2.1.0" 13789 13905 resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" 13790 13906 integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== 13907 + 13908 + ipaddr.js@^2.1.0: 13909 + version "2.2.0" 13910 + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" 13911 + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== 13791 13912 13792 13913 is-arguments@^1.0.4: 13793 13914 version "1.1.1" ··· 15351 15472 resolved "https://registry.yarnpkg.com/jose/-/jose-5.1.3.tgz#303959d85c51b5cb14725f930270b72be56abdca" 15352 15473 integrity sha512-GPExOkcMsCLBTi1YetY2LmkoY559fss0+0KVa6kOfb2YFe84nAM7Nm/XzuZozah4iHgmBGrCOHL5/cy670SBRw== 15353 15474 15475 + jose@^5.2.0: 15476 + version "5.6.3" 15477 + resolved "https://registry.yarnpkg.com/jose/-/jose-5.6.3.tgz#415688bc84875461c86dfe271ea6029112a23e27" 15478 + integrity sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g== 15479 + 15354 15480 js-base64@^3.7.2: 15355 15481 version "3.7.5" 15356 15482 resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" ··· 15603 15729 bn.js "^4.11.8" 15604 15730 elliptic "^6.4.1" 15605 15731 15732 + keygrip@^1.1.0: 15733 + version "1.1.0" 15734 + resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" 15735 + integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== 15736 + dependencies: 15737 + tsscmp "1.0.6" 15738 + 15606 15739 kind-of@^6.0.2: 15607 15740 version "6.0.3" 15608 15741 resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" ··· 16776 16909 dependencies: 16777 16910 whatwg-url "^5.0.0" 16778 16911 16912 + node-fetch@^2.6.13: 16913 + version "2.7.0" 16914 + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" 16915 + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 16916 + dependencies: 16917 + whatwg-url "^5.0.0" 16918 + 16779 16919 node-forge@^1, node-forge@^1.2.1, node-forge@^1.3.1: 16780 16920 version "1.3.1" 16781 16921 resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" ··· 17024 17164 resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" 17025 17165 integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== 17026 17166 17167 + oidc-token-hash@^5.0.3: 17168 + version "5.0.3" 17169 + resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz#9a229f0a1ce9d4fc89bcaee5478c97a889e7b7b6" 17170 + integrity sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw== 17171 + 17027 17172 on-exit-leak-free@^2.1.0: 17028 17173 version "2.1.0" 17029 17174 resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" ··· 17567 17712 resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 17568 17713 integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== 17569 17714 17570 - pino-abstract-transport@v1.0.0: 17571 - version "1.0.0" 17572 - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" 17573 - integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA== 17715 + pino-abstract-transport@^1.2.0: 17716 + version "1.2.0" 17717 + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz#97f9f2631931e242da531b5c66d3079c12c9d1b5" 17718 + integrity sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q== 17574 17719 dependencies: 17575 17720 readable-stream "^4.0.0" 17576 17721 split2 "^4.0.0" 17577 17722 17578 - pino-abstract-transport@v1.1.0: 17579 - version "1.1.0" 17580 - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8" 17581 - integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA== 17723 + pino-abstract-transport@v1.0.0: 17724 + version "1.0.0" 17725 + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" 17726 + integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA== 17582 17727 dependencies: 17583 17728 readable-stream "^4.0.0" 17584 17729 split2 "^4.0.0" ··· 17615 17760 sonic-boom "^3.1.0" 17616 17761 thread-stream "^2.0.0" 17617 17762 17618 - pino@^8.15.0: 17619 - version "8.15.1" 17620 - resolved "https://registry.yarnpkg.com/pino/-/pino-8.15.1.tgz#04b815ff7aa4e46b1bbab88d8010aaa2b17eaba4" 17621 - integrity sha512-Cp4QzUQrvWCRJaQ8Lzv0mJzXVk4z2jlq8JNKMGaixC2Pz5L4l2p95TkuRvYbrEbe85NQsDKrAd4zalf7Ml6WiA== 17763 + pino@^8.21.0: 17764 + version "8.21.0" 17765 + resolved "https://registry.yarnpkg.com/pino/-/pino-8.21.0.tgz#e1207f3675a2722940d62da79a7a55a98409f00d" 17766 + integrity sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q== 17622 17767 dependencies: 17623 17768 atomic-sleep "^1.0.0" 17624 17769 fast-redact "^3.1.1" 17625 17770 on-exit-leak-free "^2.1.0" 17626 - pino-abstract-transport v1.1.0 17771 + pino-abstract-transport "^1.2.0" 17627 17772 pino-std-serializers "^6.0.0" 17628 - process-warning "^2.0.0" 17773 + process-warning "^3.0.0" 17629 17774 quick-format-unescaped "^4.0.3" 17630 17775 real-require "^0.2.0" 17631 17776 safe-stable-stringify "^2.3.1" 17632 - sonic-boom "^3.1.0" 17633 - thread-stream "^2.0.0" 17777 + sonic-boom "^3.7.0" 17778 + thread-stream "^2.6.0" 17634 17779 17635 17780 pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.5: 17636 17781 version "4.0.6" ··· 18391 18536 version "2.2.0" 18392 18537 resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626" 18393 18538 integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg== 18539 + 18540 + process-warning@^3.0.0: 18541 + version "3.0.0" 18542 + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b" 18543 + integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ== 18394 18544 18395 18545 process@^0.11.10: 18396 18546 version "0.11.10" ··· 20229 20379 dependencies: 20230 20380 atomic-sleep "^1.0.0" 20231 20381 20382 + sonic-boom@^3.7.0: 20383 + version "3.8.1" 20384 + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.1.tgz#d5ba8c4e26d6176c9a1d14d549d9ff579a163422" 20385 + integrity sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg== 20386 + dependencies: 20387 + atomic-sleep "^1.0.0" 20388 + 20232 20389 source-list-map@^2.0.0, source-list-map@^2.0.1: 20233 20390 version "2.0.1" 20234 20391 resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" ··· 20419 20576 js-sha256 "^0.10.1" 20420 20577 uuid "^8.3.2" 20421 20578 20579 + statsig-node@^5.23.1: 20580 + version "5.25.1" 20581 + resolved "https://registry.yarnpkg.com/statsig-node/-/statsig-node-5.25.1.tgz#6d8ea9ecaad6c09250e5ff7d33eda9fd0f9c05f4" 20582 + integrity sha512-K8+1psxFVdFr5LyXwDotJqBl7uKt8vbZO2e/9zzbLI4yDOuLDoItG5Ju5QAR0oUfEdEAANOzwV2yA052Wrc/Xw== 20583 + dependencies: 20584 + ip3country "^5.0.0" 20585 + node-fetch "^2.6.13" 20586 + ua-parser-js "^1.0.2" 20587 + uuid "^8.3.2" 20588 + 20422 20589 statsig-react-native-expo@^4.6.1: 20423 20590 version "4.6.1" 20424 20591 resolved "https://registry.yarnpkg.com/statsig-react-native-expo/-/statsig-react-native-expo-4.6.1.tgz#0bdf49fee7112f7f28bff2405f4ba0c1727bb3d6" ··· 21052 21219 dependencies: 21053 21220 real-require "^0.2.0" 21054 21221 21222 + thread-stream@^2.6.0: 21223 + version "2.7.0" 21224 + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.7.0.tgz#d8a8e1b3fd538a6cca8ce69dbe5d3d097b601e11" 21225 + integrity sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw== 21226 + dependencies: 21227 + real-require "^0.2.0" 21228 + 21055 21229 throat@^5.0.0: 21056 21230 version "5.0.0" 21057 21231 resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" ··· 21251 21425 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" 21252 21426 integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== 21253 21427 21428 + tsscmp@1.0.6: 21429 + version "1.0.6" 21430 + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" 21431 + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== 21432 + 21254 21433 tsutils@^3.21.0: 21255 21434 version "3.21.0" 21256 21435 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" ··· 21388 21567 resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz#8bda4827be4f0b1dda91699a29499575a1f1d307" 21389 21568 integrity sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g== 21390 21569 21570 + ua-parser-js@^1.0.2: 21571 + version "1.0.38" 21572 + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2" 21573 + integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ== 21574 + 21391 21575 ua-parser-js@^1.0.35: 21392 21576 version "1.0.35" 21393 21577 resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011" ··· 21431 21615 integrity sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w== 21432 21616 dependencies: 21433 21617 "@fastify/busboy" "^2.0.0" 21618 + 21619 + undici@^6.14.1: 21620 + version "6.19.5" 21621 + resolved "https://registry.yarnpkg.com/undici/-/undici-6.19.5.tgz#5829101361b583b53206e81579f4df71c56d6be8" 21622 + integrity sha512-LryC15SWzqQsREHIOUybavaIHF5IoL0dJ9aWWxL/PgT1KfqAW5225FZpDUFlt9xiDMS2/S7DOKhFWA7RLksWdg== 21434 21623 21435 21624 unfetch@^3.1.1: 21436 21625 version "3.1.2" ··· 22603 22792 resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.3.0.tgz#2cfe81b62d044e0453d1aa3ae7c32a2f36dde9af" 22604 22793 integrity sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw== 22605 22794 22606 - zod@3.23.8, zod@^3.14.2, zod@^3.20.2, zod@^3.21.4, zod@^3.22.4: 22795 + zod@3.23.8, zod@^3.14.2, zod@^3.20.2, zod@^3.21.4, zod@^3.22.4, zod@^3.23.8: 22607 22796 version "3.23.8" 22608 22797 resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" 22609 22798 integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==