Upgrade API, implement XRPC rework (#4857)

Co-authored-by: Matthieu Sieben <matthieu.sieben@gmail.com>
zio/stable
Hailey 2024-08-12 14:00:15 -07:00 committed by GitHub
parent ae883e2df7
commit 7df2327424
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 543 additions and 360 deletions

View File

@ -1,14 +1,11 @@
import 'react-native-gesture-handler' // must be first
import {LogBox} from 'react-native'
import '#/platform/polyfills'
import {IS_TEST} from '#/env'
import {LogBox} from 'react-native'
import {registerRootComponent} from 'expo'
import {doPolyfill} from '#/lib/api/api-polyfill'
import App from '#/App'
doPolyfill()
import {IS_TEST} from '#/env'
if (IS_TEST) {
LogBox.ignoreAllLogs() // suppress all logs in tests

View File

@ -1,9 +1,8 @@
import '#/platform/markBundleStartTime'
import '#/platform/polyfills'
import {registerRootComponent} from 'expo'
import {doPolyfill} from '#/lib/api/api-polyfill'
import App from '#/App'
doPolyfill()
registerRootComponent(App)

View File

@ -156,7 +156,7 @@ class Mocker {
}
async createUser(name: string) {
const agent = new BskyAgent({service: this.agent.service})
const agent = new BskyAgent({service: this.service})
const inviteRes = await agent.api.com.atproto.server.createInviteCode(
{useCount: 1},
@ -332,7 +332,7 @@ class Mocker {
}
async createInvite(forAccount: string) {
const agent = new BskyAgent({service: this.agent.service})
const agent = new BskyAgent({service: this.service})
await agent.api.com.atproto.server.createInviteCode(
{useCount: 1, forAccount},
{

View File

@ -52,7 +52,7 @@
"open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web"
},
"dependencies": {
"@atproto/api": "0.12.29",
"@atproto/api": "0.13.0",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
@ -208,7 +208,7 @@
"zod": "^3.20.2"
},
"devDependencies": {
"@atproto/dev-env": "^0.3.5",
"@atproto/dev-env": "^0.3.39",
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",

View File

@ -1,28 +0,0 @@
diff --git a/node_modules/@atproto/lexicon/dist/validators/complex.js b/node_modules/@atproto/lexicon/dist/validators/complex.js
index 32d7798..9d688b7 100644
--- a/node_modules/@atproto/lexicon/dist/validators/complex.js
+++ b/node_modules/@atproto/lexicon/dist/validators/complex.js
@@ -113,7 +113,22 @@ function object(lexicons, path, def, value) {
if (value[key] === null && nullableProps.has(key)) {
continue;
}
- const propDef = def.properties[key];
+ const propDef = def.properties[key]
+ if (typeof value[key] === 'undefined' && !requiredProps.has(key)) {
+ // Fast path for non-required undefined props.
+ if (
+ propDef.type === 'integer' ||
+ propDef.type === 'boolean' ||
+ propDef.type === 'string'
+ ) {
+ if (typeof propDef.default === 'undefined') {
+ continue
+ }
+ } else {
+ // Other types have no defaults.
+ continue
+ }
+ }
const propPath = `${path}/${key}`;
const validated = (0, util_1.validateOneOf)(lexicons, propPath, propDef, value[key]);
const propValue = validated.success ? validated.value : value[key];

View File

@ -1,85 +0,0 @@
import RNFS from 'react-native-fs'
import {BskyAgent, jsonToLex, stringifyLex} from '@atproto/api'
const GET_TIMEOUT = 15e3 // 15s
const POST_TIMEOUT = 60e3 // 60s
export function doPolyfill() {
BskyAgent.configure({fetch: fetchHandler})
}
interface FetchHandlerResponse {
status: number
headers: Record<string, string>
body: any
}
async function fetchHandler(
reqUri: string,
reqMethod: string,
reqHeaders: Record<string, string>,
reqBody: any,
): Promise<FetchHandlerResponse> {
const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type']
if (reqMimeType && reqMimeType.startsWith('application/json')) {
reqBody = stringifyLex(reqBody)
} else if (
typeof reqBody === 'string' &&
(reqBody.startsWith('/') || reqBody.startsWith('file:'))
) {
if (reqBody.endsWith('.jpeg') || reqBody.endsWith('.jpg')) {
// HACK
// React native has a bug that inflates the size of jpegs on upload
// we get around that by renaming the file ext to .bin
// see https://github.com/facebook/react-native/issues/27099
// -prf
const newPath = reqBody.replace(/\.jpe?g$/, '.bin')
await RNFS.moveFile(reqBody, newPath)
reqBody = newPath
}
// NOTE
// React native treats bodies with {uri: string} as file uploads to pull from cache
// -prf
reqBody = {uri: reqBody}
}
const controller = new AbortController()
const to = setTimeout(
() => controller.abort(),
reqMethod === 'post' ? POST_TIMEOUT : GET_TIMEOUT,
)
const res = await fetch(reqUri, {
method: reqMethod,
headers: reqHeaders,
body: reqBody,
signal: controller.signal,
})
const resStatus = res.status
const resHeaders: Record<string, string> = {}
res.headers.forEach((value: string, key: string) => {
resHeaders[key] = value
})
const resMimeType = resHeaders['Content-Type'] || resHeaders['content-type']
let resBody
if (resMimeType) {
if (resMimeType.startsWith('application/json')) {
resBody = jsonToLex(await res.json())
} else if (resMimeType.startsWith('text/')) {
resBody = await res.text()
} else if (resMimeType === 'application/vnd.ipld.car') {
resBody = await res.arrayBuffer()
} else {
throw new Error('Non-supported mime type')
}
}
clearTimeout(to)
return {
status: resStatus,
headers: resHeaders,
body: resBody,
}
}

View File

@ -1,3 +0,0 @@
export function doPolyfill() {
// no polyfill is needed on web
}

View File

@ -1,7 +1,6 @@
import {
AppBskyFeedDefs,
AppBskyFeedGetFeed as GetCustomFeed,
AtpAgent,
BskyAgent,
} from '@atproto/api'
@ -51,7 +50,7 @@ export class CustomFeedAPI implements FeedAPI {
const agent = this.agent
const isBlueskyOwned = isBlueskyOwnedFeed(this.params.feed)
const res = agent.session
const res = agent.did
? await this.agent.app.bsky.feed.getFeed(
{
...this.params,
@ -106,34 +105,32 @@ async function loggedOutFetch({
let contentLangs = getContentLanguages().join(',')
// manually construct fetch call so we can add the `lang` cache-busting param
let res = await AtpAgent.fetch!(
let res = await fetch(
`https://api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=${feed}${
cursor ? `&cursor=${cursor}` : ''
}&limit=${limit}&lang=${contentLangs}`,
'GET',
{'Accept-Language': contentLangs},
undefined,
{method: 'GET', headers: {'Accept-Language': contentLangs}},
)
if (res.body?.feed?.length) {
let data = res.ok ? await res.json() : null
if (data?.feed?.length) {
return {
success: true,
data: res.body,
data,
}
}
// no data, try again with language headers removed
res = await AtpAgent.fetch!(
res = await fetch(
`https://api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=${feed}${
cursor ? `&cursor=${cursor}` : ''
}&limit=${limit}`,
'GET',
{'Accept-Language': ''},
undefined,
{method: 'GET', headers: {'Accept-Language': ''}},
)
if (res.body?.feed?.length) {
data = res.ok ? await res.json() : null
if (data?.feed?.length) {
return {
success: true,
data: res.body,
data,
}
}

View File

@ -6,7 +6,6 @@ import {
AppBskyFeedThreadgate,
BskyAgent,
ComAtprotoLabelDefs,
ComAtprotoRepoUploadBlob,
RichText,
} from '@atproto/api'
import {AtUri} from '@atproto/api'
@ -15,10 +14,13 @@ import {logger} from '#/logger'
import {ThreadgateSetting} from '#/state/queries/threadgate'
import {isNetworkError} from 'lib/strings/errors'
import {shortenLinks, stripInvalidMentions} from 'lib/strings/rich-text-manip'
import {isNative, isWeb} from 'platform/detection'
import {isNative} from 'platform/detection'
import {ImageModel} from 'state/models/media/image'
import {LinkMeta} from '../link-meta/link-meta'
import {safeDeleteAsync} from '../media/manip'
import {uploadBlob} from './upload-blob'
export {uploadBlob}
export interface ExternalEmbedDraft {
uri: string
@ -28,25 +30,6 @@ export interface ExternalEmbedDraft {
localThumb?: ImageModel
}
export async function uploadBlob(
agent: BskyAgent,
blob: string,
encoding: string,
): Promise<ComAtprotoRepoUploadBlob.Response> {
if (isWeb) {
// `blob` should be a data uri
return agent.uploadBlob(convertDataURIToUint8Array(blob), {
encoding,
})
} else {
// `blob` should be a path to a file in the local FS
return agent.uploadBlob(
blob, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts
{encoding},
)
}
}
interface PostOpts {
rawText: string
replyTo?: string
@ -301,7 +284,7 @@ export async function createThreadgate(
const postUrip = new AtUri(postUri)
await agent.api.com.atproto.repo.putRecord({
repo: agent.session!.did,
repo: agent.accountDid,
collection: 'app.bsky.feed.threadgate',
rkey: postUrip.rkey,
record: {
@ -312,15 +295,3 @@ export async function createThreadgate(
},
})
}
// helpers
// =
function convertDataURIToUint8Array(uri: string): Uint8Array {
var raw = window.atob(uri.substring(uri.indexOf(';base64,') + 8))
var binary = new Uint8Array(new ArrayBuffer(raw.length))
for (let i = 0; i < raw.length; i++) {
binary[i] = raw.charCodeAt(i)
}
return binary
}

View File

@ -0,0 +1,82 @@
import RNFS from 'react-native-fs'
import {BskyAgent, ComAtprotoRepoUploadBlob} from '@atproto/api'
/**
* @param encoding Allows overriding the blob's type
*/
export async function uploadBlob(
agent: BskyAgent,
input: string | Blob,
encoding?: string,
): Promise<ComAtprotoRepoUploadBlob.Response> {
if (typeof input === 'string' && input.startsWith('file:')) {
const blob = await asBlob(input)
return agent.uploadBlob(blob, {encoding})
}
if (typeof input === 'string' && input.startsWith('/')) {
const blob = await asBlob(`file://${input}`)
return agent.uploadBlob(blob, {encoding})
}
if (typeof input === 'string' && input.startsWith('data:')) {
const blob = await fetch(input).then(r => r.blob())
return agent.uploadBlob(blob, {encoding})
}
if (input instanceof Blob) {
return agent.uploadBlob(input, {encoding})
}
throw new TypeError(`Invalid uploadBlob input: ${typeof input}`)
}
async function asBlob(uri: string): Promise<Blob> {
return withSafeFile(uri, async safeUri => {
// Note
// Android does not support `fetch()` on `file://` URIs. for this reason, we
// use XMLHttpRequest instead of simply calling:
// return fetch(safeUri.replace('file:///', 'file:/')).then(r => r.blob())
return await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onload = () => resolve(xhr.response)
xhr.onerror = () => reject(new Error('Failed to load blob'))
xhr.responseType = 'blob'
xhr.open('GET', safeUri, true)
xhr.send(null)
})
})
}
// HACK
// React native has a bug that inflates the size of jpegs on upload
// we get around that by renaming the file ext to .bin
// see https://github.com/facebook/react-native/issues/27099
// -prf
async function withSafeFile<T>(
uri: string,
fn: (path: string) => Promise<T>,
): Promise<T> {
if (uri.endsWith('.jpeg') || uri.endsWith('.jpg')) {
// Since we don't "own" the file, we should avoid renaming or modifying it.
// Instead, let's copy it to a temporary file and use that (then remove the
// temporary file).
const newPath = uri.replace(/\.jpe?g$/, '.bin')
try {
await RNFS.copyFile(uri, newPath)
} catch {
// Failed to copy the file, just use the original
return await fn(uri)
}
try {
return await fn(newPath)
} finally {
// Remove the temporary file
await RNFS.unlink(newPath)
}
} else {
return fn(uri)
}
}

View File

@ -0,0 +1,26 @@
import {BskyAgent, ComAtprotoRepoUploadBlob} from '@atproto/api'
/**
* @note It is recommended, on web, to use the `file` instance of the file
* selector input element, rather than a `data:` URL, to avoid
* loading the file into memory. `File` extends `Blob` "file" instances can
* be passed directly to this function.
*/
export async function uploadBlob(
agent: BskyAgent,
input: string | Blob,
encoding?: string,
): Promise<ComAtprotoRepoUploadBlob.Response> {
if (typeof input === 'string' && input.startsWith('data:')) {
const blob = await fetch(input).then(r => r.blob())
return agent.uploadBlob(blob, {encoding})
}
if (input instanceof Blob) {
return agent.uploadBlob(input, {
encoding,
})
}
throw new TypeError(`Invalid uploadBlob input: ${typeof input}`)
}

View File

@ -218,13 +218,7 @@ export async function safeDeleteAsync(path: string) {
// Normalize is necessary for Android, otherwise it doesn't delete.
const normalizedPath = normalizePath(path)
try {
await Promise.allSettled([
deleteAsync(normalizedPath, {idempotent: true}),
// HACK: Try this one too. Might exist due to api-polyfill hack.
deleteAsync(normalizedPath.replace(/\.jpe?g$/, '.bin'), {
idempotent: true,
}),
])
await deleteAsync(normalizedPath, {idempotent: true})
} catch (e) {
console.error('Failed to delete file', e)
}

View File

@ -40,7 +40,7 @@ export function SignupQueued() {
const res = await agent.com.atproto.temp.checkSignupQueue()
if (res.data.activated) {
// ready to go, exchange the access token for a usable one and kick off onboarding
await agent.refreshSession()
await agent.sessionManager.refreshSession()
if (!isSignupQueued(agent.session?.accessJwt)) {
onboardingDispatch({type: 'start'})
}

View File

@ -37,14 +37,14 @@ export function usePreferencesQuery() {
refetchOnWindowFocus: true,
queryKey: preferencesQueryKey,
queryFn: async () => {
if (agent.session?.did === undefined) {
if (!agent.did) {
return DEFAULT_LOGGED_OUT_PREFERENCES
} else {
const res = await agent.getPreferences()
// save to local storage to ensure there are labels on initial requests
saveLabelers(
agent.session.did,
agent.did,
res.moderationPrefs.labelers.map(l => l.did),
)

View File

@ -27,7 +27,7 @@ describe('session', () => {
`)
const agent = new BskyAgent({service: 'https://alice.com'})
agent.session = {
agent.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -118,7 +118,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -166,7 +166,7 @@ describe('session', () => {
`)
const agent2 = new BskyAgent({service: 'https://bob.com'})
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob.test',
@ -230,7 +230,7 @@ describe('session', () => {
`)
const agent3 = new BskyAgent({service: 'https://alice.com'})
agent3.session = {
agent3.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -294,7 +294,7 @@ describe('session', () => {
`)
const agent4 = new BskyAgent({service: 'https://jay.com'})
agent4.session = {
agent4.sessionManager.session = {
active: true,
did: 'jay-did',
handle: 'jay.test',
@ -445,7 +445,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -502,7 +502,7 @@ describe('session', () => {
`)
const agent2 = new BskyAgent({service: 'https://alice.com'})
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -553,7 +553,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -598,7 +598,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -606,7 +606,7 @@ describe('session', () => {
refreshJwt: 'alice-refresh-jwt-1',
}
const agent2 = new BskyAgent({service: 'https://bob.com'})
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob.test',
@ -678,7 +678,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -695,7 +695,7 @@ describe('session', () => {
expect(state.accounts.length).toBe(1)
expect(state.currentAgentState.did).toBe('alice-did')
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -748,7 +748,7 @@ describe('session', () => {
}
`)
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -801,7 +801,7 @@ describe('session', () => {
}
`)
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -859,7 +859,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -876,7 +876,7 @@ describe('session', () => {
expect(state.accounts.length).toBe(1)
expect(state.currentAgentState.did).toBe('alice-did')
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -907,7 +907,7 @@ describe('session', () => {
])
expect(lastState === state).toBe(true)
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -931,7 +931,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -940,7 +940,7 @@ describe('session', () => {
}
const agent2 = new BskyAgent({service: 'https://bob.com'})
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob.test',
@ -965,7 +965,7 @@ describe('session', () => {
expect(state.accounts.length).toBe(2)
expect(state.currentAgentState.did).toBe('bob-did')
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice-updated.test',
@ -1032,7 +1032,7 @@ describe('session', () => {
}
`)
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob-updated.test',
@ -1099,7 +1099,7 @@ describe('session', () => {
// Ignore other events for inactive agent.
const lastState = state
agent1.session = undefined
agent1.sessionManager.session = undefined
state = run(state, [
{
type: 'received-agent-event',
@ -1126,7 +1126,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -1135,7 +1135,7 @@ describe('session', () => {
}
const agent2 = new BskyAgent({service: 'https://bob.com'})
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob.test',
@ -1162,7 +1162,7 @@ describe('session', () => {
expect(state.accounts.length).toBe(1)
expect(state.currentAgentState.did).toBe('bob-did')
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -1188,7 +1188,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -1206,7 +1206,7 @@ describe('session', () => {
expect(state.accounts.length).toBe(1)
expect(state.currentAgentState.did).toBe('alice-did')
agent1.session = undefined
agent1.sessionManager.session = undefined
state = run(state, [
{
type: 'received-agent-event',
@ -1255,7 +1255,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -1273,7 +1273,7 @@ describe('session', () => {
expect(state.accounts[0].accessJwt).toBe('alice-access-jwt-1')
expect(state.currentAgentState.did).toBe('alice-did')
agent1.session = undefined
agent1.sessionManager.session = undefined
state = run(state, [
{
type: 'received-agent-event',
@ -1320,7 +1320,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -1338,7 +1338,7 @@ describe('session', () => {
expect(state.accounts[0].accessJwt).toBe('alice-access-jwt-1')
expect(state.currentAgentState.did).toBe('alice-did')
agent1.session = undefined
agent1.sessionManager.session = undefined
state = run(state, [
{
type: 'received-agent-event',
@ -1385,7 +1385,7 @@ describe('session', () => {
let state = getInitialState([])
const agent1 = new BskyAgent({service: 'https://alice.com'})
agent1.session = {
agent1.sessionManager.session = {
active: true,
did: 'alice-did',
handle: 'alice.test',
@ -1393,7 +1393,7 @@ describe('session', () => {
refreshJwt: 'alice-refresh-jwt-1',
}
const agent2 = new BskyAgent({service: 'https://bob.com'})
agent2.session = {
agent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob.test',
@ -1416,7 +1416,7 @@ describe('session', () => {
expect(state.currentAgentState.did).toBe('bob-did')
const anotherTabAgent1 = new BskyAgent({service: 'https://jay.com'})
anotherTabAgent1.session = {
anotherTabAgent1.sessionManager.session = {
active: true,
did: 'jay-did',
handle: 'jay.test',
@ -1424,7 +1424,7 @@ describe('session', () => {
refreshJwt: 'jay-refresh-jwt-1',
}
const anotherTabAgent2 = new BskyAgent({service: 'https://alice.com'})
anotherTabAgent2.session = {
anotherTabAgent2.sessionManager.session = {
active: true,
did: 'bob-did',
handle: 'bob.test',
@ -1492,7 +1492,7 @@ describe('session', () => {
`)
const anotherTabAgent3 = new BskyAgent({service: 'https://clarence.com'})
anotherTabAgent3.session = {
anotherTabAgent3.sessionManager.session = {
active: true,
did: 'clarence-did',
handle: 'clarence.test',

View File

@ -1,4 +1,9 @@
import {AtpSessionData, AtpSessionEvent, BskyAgent} from '@atproto/api'
import {
AtpPersistSessionHandler,
AtpSessionData,
AtpSessionEvent,
BskyAgent,
} from '@atproto/api'
import {TID} from '@atproto/common-web'
import {networkRetry} from '#/lib/async/retry'
@ -20,6 +25,8 @@ import {
import {SessionAccount} from './types'
import {isSessionExpired, isSignupQueued} from './util'
type SetPersistSessionHandler = (cb: AtpPersistSessionHandler) => void
export function createPublicAgent() {
configureModerationForGuest() // Side effect but only relevant for tests
return new BskyAgent({service: PUBLIC_BSKY_SERVICE})
@ -32,10 +39,11 @@ export async function createAgentAndResume(
did: string,
event: AtpSessionEvent,
) => void,
setPersistSessionHandler: SetPersistSessionHandler,
) {
const agent = new BskyAgent({service: storedAccount.service})
if (storedAccount.pdsUrl) {
agent.pdsUrl = agent.api.xrpc.uri = new URL(storedAccount.pdsUrl)
agent.sessionManager.pdsUrl = new URL(storedAccount.pdsUrl)
}
const gates = tryFetchGates(storedAccount.did, 'prefer-low-latency')
const moderation = configureModerationForAccount(agent, storedAccount)
@ -43,9 +51,8 @@ export async function createAgentAndResume(
if (isSessionExpired(storedAccount)) {
await networkRetry(1, () => agent.resumeSession(prevSession))
} else {
agent.session = prevSession
agent.sessionManager.session = prevSession
if (!storedAccount.signupQueued) {
// Intentionally not awaited to unblock the UI:
networkRetry(3, () => agent.resumeSession(prevSession)).catch(
(e: any) => {
logger.error(`networkRetry failed to resume session`, {
@ -60,7 +67,13 @@ export async function createAgentAndResume(
}
}
return prepareAgent(agent, gates, moderation, onSessionChange)
return prepareAgent(
agent,
gates,
moderation,
onSessionChange,
setPersistSessionHandler,
)
}
export async function createAgentAndLogin(
@ -80,6 +93,7 @@ export async function createAgentAndLogin(
did: string,
event: AtpSessionEvent,
) => void,
setPersistSessionHandler: SetPersistSessionHandler,
) {
const agent = new BskyAgent({service})
await agent.login({identifier, password, authFactorToken})
@ -87,7 +101,13 @@ export async function createAgentAndLogin(
const account = agentToSessionAccountOrThrow(agent)
const gates = tryFetchGates(account.did, 'prefer-fresh-gates')
const moderation = configureModerationForAccount(agent, account)
return prepareAgent(agent, moderation, gates, onSessionChange)
return prepareAgent(
agent,
moderation,
gates,
onSessionChange,
setPersistSessionHandler,
)
}
export async function createAgentAndCreateAccount(
@ -115,6 +135,7 @@ export async function createAgentAndCreateAccount(
did: string,
event: AtpSessionEvent,
) => void,
setPersistSessionHandler: SetPersistSessionHandler,
) {
const agent = new BskyAgent({service})
await agent.createAccount({
@ -174,7 +195,13 @@ export async function createAgentAndCreateAccount(
logger.error(e, {context: `session: failed snoozeEmailConfirmationPrompt`})
}
return prepareAgent(agent, gates, moderation, onSessionChange)
return prepareAgent(
agent,
gates,
moderation,
onSessionChange,
setPersistSessionHandler,
)
}
async function prepareAgent(
@ -187,13 +214,14 @@ async function prepareAgent(
did: string,
event: AtpSessionEvent,
) => void,
setPersistSessionHandler: (cb: AtpPersistSessionHandler) => void,
) {
// There's nothing else left to do, so block on them here.
await Promise.all([gates, moderation])
// Now the agent is ready.
const account = agentToSessionAccountOrThrow(agent)
agent.setPersistSessionHandler(event => {
setPersistSessionHandler(event => {
onSessionChange(agent, account.did, event)
if (event !== 'create' && event !== 'update') {
addSessionErrorLog(account.did, event)

View File

@ -1,5 +1,9 @@
import React from 'react'
import {AtpSessionEvent, BskyAgent} from '@atproto/api'
import {
AtpPersistSessionHandler,
AtpSessionEvent,
BskyAgent,
} from '@atproto/api'
import {track} from '#/lib/analytics/analytics'
import {logEvent} from '#/lib/statsig/statsig'
@ -47,6 +51,15 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
return initialState
})
const persistSessionHandler = React.useRef<
AtpPersistSessionHandler | undefined
>(undefined)
const setPersistSessionHandler = (
newHandler: AtpPersistSessionHandler | undefined,
) => {
persistSessionHandler.current = newHandler
}
const onAgentSessionChange = React.useCallback(
(agent: BskyAgent, accountDid: string, sessionEvent: AtpSessionEvent) => {
const refreshedAccount = agentToSessionAccount(agent) // Mutable, so snapshot it right away.
@ -73,6 +86,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const {agent, account} = await createAgentAndCreateAccount(
params,
onAgentSessionChange,
setPersistSessionHandler,
)
if (signal.aborted) {
@ -97,6 +111,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const {agent, account} = await createAgentAndLogin(
params,
onAgentSessionChange,
setPersistSessionHandler,
)
if (signal.aborted) {
@ -138,6 +153,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const {agent, account} = await createAgentAndResume(
storedAccount,
onAgentSessionChange,
setPersistSessionHandler,
)
if (signal.aborted) {
@ -202,7 +218,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
} else {
const agent = state.currentAgentState.agent as BskyAgent
const prevSession = agent.session
agent.session = sessionAccountToSession(syncedAccount)
agent.sessionManager.session = sessionAccountToSession(syncedAccount)
addSessionDebugLog({
type: 'agent:patch',
agent,
@ -249,8 +265,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
addSessionDebugLog({type: 'agent:switch', prevAgent, nextAgent: agent})
// We never reuse agents so let's fully neutralize the previous one.
// This ensures it won't try to consume any refresh tokens.
prevAgent.session = undefined
prevAgent.setPersistSessionHandler(undefined)
prevAgent.sessionManager.session = undefined
setPersistSessionHandler(undefined)
}
}, [agent])

View File

@ -56,7 +56,7 @@ type Log =
type: 'agent:patch'
agent: object
prevSession: AtpSessionData | undefined
nextSession: AtpSessionData
nextSession: AtpSessionData | undefined
}
export function wrapSessionReducerForLogging(reducer: Reducer): Reducer {

437
yarn.lock
View File

@ -34,39 +34,65 @@
jsonpointer "^5.0.0"
leven "^3.1.0"
"@atproto/api@0.12.29":
version "0.12.29"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.29.tgz#95a19202c2f0eec4c955909685be11009ba9b9a1"
integrity sha512-PyzPLjGWR0qNOMrmj3Nt3N5NuuANSgOk/33Bu3j+rFjjPrHvk9CI6iQPU6zuDaDCoyOTRJRafw8X/aMQw+ilgw==
"@atproto-labs/fetch-node@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch-node/-/fetch-node-0.1.0.tgz#692666d57ec24a7ba0813077a303baccf26108e0"
integrity sha512-DUHgaGw8LBqiGg51pUDuWK/alMcmNbpcK7ALzlF2Gw//TNLTsgrj0qY9aEtK+np9rEC+x/o3bN4SGnuQEpgqIg==
dependencies:
"@atproto-labs/fetch" "0.1.0"
"@atproto-labs/pipe" "0.1.0"
ipaddr.js "^2.1.0"
psl "^1.9.0"
undici "^6.14.1"
"@atproto-labs/fetch@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch/-/fetch-0.1.0.tgz#50a46943fd2f321dd748de28c73ba7cbfa493132"
integrity sha512-uirja+uA/C4HNk7vayM+AJqsccxQn2wVziUHxbsjJGt/K6Q8ZOKDaEX2+GrcXvpUVcqUKh+94JFjuzH+CAEUlg==
dependencies:
"@atproto-labs/pipe" "0.1.0"
optionalDependencies:
zod "^3.23.8"
"@atproto-labs/pipe@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@atproto-labs/pipe/-/pipe-0.1.0.tgz#c8d86923b6d8e900d39efe6fdcdf0d897c434086"
integrity sha512-ghOqHFyJlQVFPESzlVHjKroP0tPzbmG5Jms0dNI9yLDEfL8xp4OFPWLX4f6T8mRq69wWs4nIDM3sSsFbFqLa1w==
"@atproto-labs/simple-store-memory@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store-memory/-/simple-store-memory-0.1.1.tgz#54526a1f8ec978822be9fad75106ad8b78500dd3"
integrity sha512-PCRqhnZ8NBNBvLku53O56T0lsVOtclfIrQU/rwLCc4+p45/SBPrRYNBi6YFq5rxZbK6Njos9MCmILV/KLQxrWA==
dependencies:
"@atproto-labs/simple-store" "0.1.1"
lru-cache "^10.2.0"
"@atproto-labs/simple-store@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store/-/simple-store-0.1.1.tgz#e743a2722b5d8732166f0a72aca8bd10e9bff106"
integrity sha512-WKILW2b3QbAYKh+w5U2x6p5FqqLl0nAeLwGeDY+KjX01K4Dq3vQTR9b/qNp0jZm48CabPQVrqCv0PPU9LgRRRg==
"@atproto/api@0.13.0", "@atproto/api@^0.13.0":
version "0.13.0"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.0.tgz#d1c65a407f1c3c6aba5be9425f4f739a01419bd8"
integrity sha512-04kzIDkoEVSP7zMVOT5ezCVQcOrbXWjGYO2YBc3/tBvQ90V1pl9I+mLyz1uUHE+wRE1IRWKACcWhAz8SrYz3pA==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc" "^0.5.0"
"@atproto/xrpc" "^0.6.0"
await-lock "^2.2.2"
multiformats "^9.9.0"
tlds "^1.234.0"
"@atproto/api@^0.12.3":
version "0.12.3"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.3.tgz#5b7b1c7d4210ee9315961504900c8409395cbb17"
integrity sha512-y/kGpIEo+mKGQ7VOphpqCAigTI0LZRmDThNChTfSzDKm9TzEobwiw0zUID0Yw6ot1iLLFx3nKURmuZAYlEuobw==
"@atproto/aws@^0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.2.tgz#703e5e06f288bcf61c6d99a990738f1e7299e653"
integrity sha512-j7eR7+sQumFsc66/5xyCDez9JtR6dlZc+fOdwdh85nCJD4zmQyU4r1CKrA48wQ3tkzze+ASEb1SgODuIQmIugA==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc" "^0.5.0"
multiformats "^9.9.0"
tlds "^1.234.0"
"@atproto/aws@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.0.tgz#17f3faf744824457cabd62f87be8bf08cacf8029"
integrity sha512-F09SHiC9CX3ydfrvYZbkpfES48UGCQNnznNVgJ3QyKSN8ON+BoWmGCpAFtn3AWeEoU0w9h0hypNvUm5nORv+5g==
dependencies:
"@atproto/common" "^0.4.0"
"@atproto/common" "^0.4.1"
"@atproto/crypto" "^0.4.0"
"@atproto/repo" "^0.4.0"
"@atproto/repo" "^0.4.2"
"@aws-sdk/client-cloudfront" "^3.261.0"
"@aws-sdk/client-kms" "^3.196.0"
"@aws-sdk/client-s3" "^3.224.0"
@ -76,19 +102,19 @@
multiformats "^9.9.0"
uint8arrays "3.0.0"
"@atproto/bsky@^0.0.45":
version "0.0.45"
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.45.tgz#c3083d8038fe8c5ff921d9bcb0b5a043cc840827"
integrity sha512-osWeigdYzQH2vZki+eszCR8ta9zdUB4om79aFmnE+zvxw7HFduwAAbcHf6kmmiLCfaOWvCsYb1wS2i3IC66TAg==
"@atproto/bsky@^0.0.74":
version "0.0.74"
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.74.tgz#b735af6ded16778604378710a2e871350c29570a"
integrity sha512-vyukmlBamoET0sZnDMOeTGAkQNV7KbHg65uIQ6OX4/QGynyaQP8SvSF0OsEBzBqOraxV1w9WT8AZrUbyl3uvIg==
dependencies:
"@atproto/api" "^0.12.3"
"@atproto/common" "^0.4.0"
"@atproto/api" "^0.13.0"
"@atproto/common" "^0.4.1"
"@atproto/crypto" "^0.4.0"
"@atproto/identity" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/repo" "^0.4.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/repo" "^0.4.2"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc-server" "^0.5.1"
"@atproto/xrpc-server" "^0.6.1"
"@bufbuild/protobuf" "^1.5.0"
"@connectrpc/connect" "^1.1.4"
"@connectrpc/connect-express" "^1.1.4"
@ -105,19 +131,20 @@
multiformats "^9.9.0"
p-queue "^6.6.2"
pg "^8.10.0"
pino "^8.15.0"
pino "^8.21.0"
pino-http "^8.2.1"
sharp "^0.32.6"
statsig-node "^5.23.1"
structured-headers "^1.0.1"
typed-emitter "^2.1.0"
uint8arrays "3.0.0"
"@atproto/bsync@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@atproto/bsync/-/bsync-0.0.3.tgz#2b0b8ef3686cf177846a80088317f2e89d1bf88f"
integrity sha512-tJRwNgXzfNV57lzgWPvjtb1OMlMJH9SpsMeYhIii16zcaFUWwsb474BicKpkGRT+iCvtYzBT6gWlZE2Ijnhf7w==
"@atproto/bsync@^0.0.5":
version "0.0.5"
resolved "https://registry.yarnpkg.com/@atproto/bsync/-/bsync-0.0.5.tgz#bf2fa45e4595fda12addcd6784314e4dbe409046"
integrity sha512-xCCMHy14y4tQoXiGrfd0XjSnc4q7I9bUNqju9E8jrP95QTDedH1FQgybStbUIbHt0eEqY5v9E7iZBH3n7Kiz7A==
dependencies:
"@atproto/common" "^0.4.0"
"@atproto/common" "^0.4.1"
"@atproto/syntax" "^0.3.0"
"@bufbuild/protobuf" "^1.5.0"
"@connectrpc/connect" "^1.1.4"
@ -158,17 +185,17 @@
pino "^8.6.1"
zod "^3.14.2"
"@atproto/common@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.0.tgz#d77696c7eb545426df727837d9ee333b429fe7ef"
integrity sha512-yOXuPlCjT/OK9j+neIGYn9wkxx/AlxQSucysAF0xgwu0Ji8jAtKBf9Jv6R5ObYAjAD/kVUvEYumle+Yq/R9/7g==
"@atproto/common@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.1.tgz#ca6fce47001ce8d031acd3fb4942fbfd81f72c43"
integrity sha512-uL7kQIcBTbvkBDNfxMXL6lBH4fO2DQpHd2BryJxMtbw/4iEPKe9xBYApwECHhEIk9+zhhpTRZ15FJ3gxTXN82Q==
dependencies:
"@atproto/common-web" "^0.3.0"
"@ipld/dag-cbor" "^7.0.3"
cbor-x "^1.5.1"
iso-datestring-validator "^2.2.2"
multiformats "^9.9.0"
pino "^8.15.0"
pino "^8.21.0"
"@atproto/crypto@0.1.0":
version "0.1.0"
@ -190,22 +217,22 @@
"@noble/hashes" "^1.3.1"
uint8arrays "3.0.0"
"@atproto/dev-env@^0.3.5":
version "0.3.5"
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.5.tgz#cd13313dbc52131731d039a1d22808ee8193505d"
integrity sha512-dqRNihzX1xIHbWPHmfYsliUUXyZn5FFhCeButrGie5soQmHA4okQJTB1XWDly3mdHLjUM90g+5zjRSAKoui77Q==
"@atproto/dev-env@^0.3.39":
version "0.3.39"
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.39.tgz#f498f087d4da43d5f86805c07d5f2b781e60fd6f"
integrity sha512-rIeUO99DL8/gRKYEAkAFuTn77y8letEbKMXnfpsVX2YHD89VRdDyMxkYzRu2+31UjtGv62I+qTLLKQS4EcFItA==
dependencies:
"@atproto/api" "^0.12.3"
"@atproto/bsky" "^0.0.45"
"@atproto/bsync" "^0.0.3"
"@atproto/api" "^0.13.0"
"@atproto/bsky" "^0.0.74"
"@atproto/bsync" "^0.0.5"
"@atproto/common-web" "^0.3.0"
"@atproto/crypto" "^0.4.0"
"@atproto/identity" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/ozone" "^0.1.7"
"@atproto/pds" "^0.4.14"
"@atproto/lexicon" "^0.4.1"
"@atproto/ozone" "^0.1.36"
"@atproto/pds" "^0.4.48"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc-server" "^0.5.1"
"@atproto/xrpc-server" "^0.6.1"
"@did-plc/lib" "^0.0.1"
"@did-plc/server" "^0.0.1"
axios "^0.27.2"
@ -224,30 +251,79 @@
"@atproto/crypto" "^0.4.0"
axios "^0.27.2"
"@atproto/lexicon@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.0.tgz#63e8829945d80c25524882caa8ed27b1151cc576"
integrity sha512-RvCBKdSI4M8qWm5uTNz1z3R2yIvIhmOsMuleOj8YR6BwRD+QbtUBy3l+xQ7iXf4M5fdfJFxaUNa6Ty0iRwdKqQ==
"@atproto/jwk-jose@0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@atproto/jwk-jose/-/jwk-jose-0.1.2.tgz#236eadb740b498689d9a912d1254aa9ff58890a1"
integrity sha512-lDwc/6lLn2aZ/JpyyggyjLFsJPMntrVzryyGUx5aNpuTS8SIuc4Ky0REhxqfLopQXJJZCuRRjagHG3uP05/moQ==
dependencies:
"@atproto/jwk" "0.1.1"
jose "^5.2.0"
"@atproto/jwk@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@atproto/jwk/-/jwk-0.1.1.tgz#15bcad4a1778eeb20c82108e0ec55fef45cd07b6"
integrity sha512-6h/bj1APUk7QcV9t/oA6+9DB5NZx9SZru9x+/pV5oHFI9Xz4ZuM5+dq1PfsJV54pZyqdnZ6W6M717cxoC7q7og==
dependencies:
multiformats "^9.9.0"
zod "^3.23.8"
"@atproto/lexicon@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.1.tgz#19155210570a2fafbcc7d4f655d9b813948e72a0"
integrity sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/syntax" "^0.3.0"
iso-datestring-validator "^2.2.2"
multiformats "^9.9.0"
zod "^3.21.4"
zod "^3.23.8"
"@atproto/ozone@^0.1.7":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.7.tgz#248d88e1acfe56936651754975472d03d047d689"
integrity sha512-vvaV0MFynOzZJcL8m8mEW21o1FFIkP+wHTXEC9LJrL3h03+PMaby8Ujmif6WX5eikhfxvr9xsU/Jxbi/iValuQ==
"@atproto/oauth-provider@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.1.2.tgz#a576a4c7795c7938a994e76192c19a2e73ffcddf"
integrity sha512-z1YKK0XLDfSDtLP5ntPCviEtajvUHbI4TwzYQ5X9CAL9PoXjqhQg0U/csg1wGDs8qkbphF9gni9M2stlpH7H0g==
dependencies:
"@atproto/api" "^0.12.3"
"@atproto/common" "^0.4.0"
"@atproto-labs/fetch" "0.1.0"
"@atproto-labs/fetch-node" "0.1.0"
"@atproto-labs/pipe" "0.1.0"
"@atproto-labs/simple-store" "0.1.1"
"@atproto-labs/simple-store-memory" "0.1.1"
"@atproto/jwk" "0.1.1"
"@atproto/jwk-jose" "0.1.2"
"@atproto/oauth-types" "0.1.2"
"@hapi/accept" "^6.0.3"
"@hapi/bourne" "^3.0.0"
cookie "^0.6.0"
http-errors "^2.0.0"
jose "^5.2.0"
oidc-token-hash "^5.0.3"
psl "^1.9.0"
zod "^3.23.8"
optionalDependencies:
ioredis "^5.3.2"
keygrip "^1.1.0"
"@atproto/oauth-types@0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.1.2.tgz#d6c497c8e5f88f1875c630adde4ed9c5d8a8b4f4"
integrity sha512-yySPPTLxteFJ3O3xVWEhvBFx7rczgo4LK2nQNeqAPMZdYd5dpgvuZZ88nQQge074BfuOc0MWTnr0kPdxQMjjPw==
dependencies:
"@atproto/jwk" "0.1.1"
zod "^3.23.8"
"@atproto/ozone@^0.1.36":
version "0.1.36"
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.36.tgz#6a1a71fdff3ff486c5951a9e491e954b51703d53"
integrity sha512-BQThLU5RFG+/bZli/fj5YrFU8jW5rkium7aplfJX2eHkV6huJnBU5DcgracjH2paPGC5L/zjYtibz5spqatKAg==
dependencies:
"@atproto/api" "^0.13.0"
"@atproto/common" "^0.4.1"
"@atproto/crypto" "^0.4.0"
"@atproto/identity" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc" "^0.5.0"
"@atproto/xrpc-server" "^0.5.1"
"@atproto/xrpc" "^0.6.0"
"@atproto/xrpc-server" "^0.6.1"
"@did-plc/lib" "^0.0.1"
axios "^1.6.7"
compression "^1.7.4"
@ -255,30 +331,34 @@
express "^4.17.2"
http-terminator "^3.2.0"
kysely "^0.22.0"
lande "^1.0.10"
multiformats "^9.9.0"
p-queue "^6.6.2"
pg "^8.10.0"
pino-http "^8.2.1"
structured-headers "^1.0.1"
typed-emitter "^2.1.0"
uint8arrays "3.0.0"
"@atproto/pds@^0.4.14":
version "0.4.14"
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.14.tgz#5b55ef307323bda712f2ddaba5c1fff7740ed91b"
integrity sha512-rqVcvtw5oMuuJIpWZbSSTSx19+JaZyUcg9OEjdlUmyEpToRN88zTEQySEksymrrLQkW/LPRyWGd7WthbGEuEfQ==
"@atproto/pds@^0.4.48":
version "0.4.48"
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.48.tgz#34f29846a0585f5cc33f1685eb75ad730b7dcb9f"
integrity sha512-B5FpmECkGtA0EyhiB5rfhmQArmGekqqyzFnPlNpO5vOUrTTVKc9mgGfHLVJtrnwDUfGAuIgpigqZ8HgwS0DnMA==
dependencies:
"@atproto/api" "^0.12.3"
"@atproto/aws" "^0.2.0"
"@atproto/common" "^0.4.0"
"@atproto-labs/fetch-node" "0.1.0"
"@atproto/api" "^0.13.0"
"@atproto/aws" "^0.2.2"
"@atproto/common" "^0.4.1"
"@atproto/crypto" "^0.4.0"
"@atproto/identity" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/repo" "^0.4.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/oauth-provider" "^0.1.2"
"@atproto/repo" "^0.4.2"
"@atproto/syntax" "^0.3.0"
"@atproto/xrpc" "^0.5.0"
"@atproto/xrpc-server" "^0.5.1"
"@atproto/xrpc" "^0.6.0"
"@atproto/xrpc-server" "^0.6.1"
"@did-plc/lib" "^0.0.4"
better-sqlite3 "^9.4.0"
better-sqlite3 "^10.0.0"
bytes "^3.1.2"
compression "^1.7.4"
cors "^2.8.5"
@ -297,41 +377,42 @@
nodemailer "^6.8.0"
nodemailer-html-to-text "^3.2.0"
p-queue "^6.6.2"
pino "^8.15.0"
pino "^8.21.0"
pino-http "^8.2.1"
sharp "^0.32.6"
typed-emitter "^2.1.0"
uint8arrays "3.0.0"
zod "^3.21.4"
zod "^3.23.8"
"@atproto/repo@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.4.0.tgz#e5d3195a8e4233c9bf060737b18ddee905af2d9a"
integrity sha512-LB0DF/D8r8hB+qiGB0sWZuq7TSJYbWel+t572aCrLeCOmbRgnLkGPLUTOOUvLFYv8xz1BPZTbI8hy/vcUV79VA==
"@atproto/repo@^0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.4.2.tgz#311eef52ef5df0b6f969fb4b329935a32db05313"
integrity sha512-6hEGA3BmasPCoBGaIN/jKAjKJidCf+z8exkx/77V3WB7TboucSLHn/8gg+Xf03U7bJd6mn3F0YmPaRfJwqIT8w==
dependencies:
"@atproto/common" "^0.4.0"
"@atproto/common" "^0.4.1"
"@atproto/common-web" "^0.3.0"
"@atproto/crypto" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/lexicon" "^0.4.1"
"@ipld/car" "^3.2.3"
"@ipld/dag-cbor" "^7.0.0"
multiformats "^9.9.0"
uint8arrays "3.0.0"
zod "^3.21.4"
zod "^3.23.8"
"@atproto/syntax@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3"
integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA==
"@atproto/xrpc-server@^0.5.1":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.5.1.tgz#f63c86ba60bd5b9c5a641ea57191ff83d9db41fd"
integrity sha512-SXU6dscVe5iYxPeV79QIFs/yEEu7LLOzyHGoHG1kSNO6DjwxXTdcWOc8GSYGV6H+7VycOoPZPkyD9q4teJlj/w==
"@atproto/xrpc-server@^0.6.1":
version "0.6.1"
resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.6.1.tgz#c8c75065ab6bc1a7f5c121b558acb5213f2afda6"
integrity sha512-Qm0aJC1LbYYHaRGWoh0D2iG48VwRha1T1NEP/D5UkD4GzfjT8m5PDiZBtcyspJD/BEC7UYX9/BhMYCoZLQMYcA==
dependencies:
"@atproto/common" "^0.4.0"
"@atproto/common" "^0.4.1"
"@atproto/crypto" "^0.4.0"
"@atproto/lexicon" "^0.4.0"
"@atproto/lexicon" "^0.4.1"
"@atproto/xrpc" "^0.6.0"
cbor-x "^1.5.1"
express "^4.17.2"
http-errors "^2.0.0"
@ -339,15 +420,15 @@
rate-limiter-flexible "^2.4.1"
uint8arrays "3.0.0"
ws "^8.12.0"
zod "^3.21.4"
zod "^3.23.8"
"@atproto/xrpc@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.5.0.tgz#dacbfd8f7b13f0ab5bd56f8fdd4b460e132a6032"
integrity sha512-swu+wyOLvYW4l3n+VAuJbHcPcES+tin2Lsrp8Bw5aIXIICiuFn1YMFlwK9JwVUzTH21Py1s1nHEjr4CJeElJog==
"@atproto/xrpc@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.0.tgz#668c3262e67e2afa65951ea79a03bfe3720ddf5c"
integrity sha512-5BbhBTv5j6MC3iIQ4+vYxQE7nLy2dDGQ+LYJrH8PptOCUdq0Pwg6aRccQ3y52kUZlhE/mzOTZ8Ngiy9pSAyfVQ==
dependencies:
"@atproto/lexicon" "^0.4.0"
zod "^3.21.4"
"@atproto/lexicon" "^0.4.1"
zod "^3.23.8"
"@aws-crypto/crc32@3.0.0":
version "3.0.0"
@ -4001,6 +4082,31 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
"@hapi/accept@^6.0.3":
version "6.0.3"
resolved "https://registry.yarnpkg.com/@hapi/accept/-/accept-6.0.3.tgz#eef0800a4f89cd969da8e5d0311dc877c37279ab"
integrity sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==
dependencies:
"@hapi/boom" "^10.0.1"
"@hapi/hoek" "^11.0.2"
"@hapi/boom@^10.0.1":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685"
integrity sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==
dependencies:
"@hapi/hoek" "^11.0.2"
"@hapi/bourne@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-3.0.0.tgz#f11fdf7dda62fe8e336fa7c6642d9041f30356d7"
integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==
"@hapi/hoek@^11.0.2":
version "11.0.4"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-11.0.4.tgz#42a7f244fd3dd777792bfb74b8c6340ae9182f37"
integrity sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==
"@hapi/hoek@^9.0.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
@ -9453,10 +9559,10 @@ better-opn@~3.0.2:
dependencies:
open "^8.0.4"
better-sqlite3@^9.4.0:
version "9.4.5"
resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-9.4.5.tgz#1d3422443a9924637cb06cc3ccc941b2ae932c65"
integrity sha512-uFVyoyZR9BNcjSca+cp3MWCv6upAv+tbMC4SWM51NIMhoQOm4tjIkyxFO/ZsYdGAF61WJBgdzyJcz4OokJi0gQ==
better-sqlite3@^10.0.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-10.1.0.tgz#8dc07e496fc014a7cd2211f79e591f6ba92838e8"
integrity sha512-hqpHJaCfKEZFaAWdMh6crdzRWyzQzfP6Ih8TYI0vFn01a6ZTDSbJIMXN+6AMBaBOh99DzUy8l3PsV9R3qnJDng==
dependencies:
bindings "^1.5.0"
prebuild-install "^7.1.1"
@ -10305,6 +10411,11 @@ cookie@0.5.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
cookie@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
copy-webpack-plugin@^10.2.0:
version "10.2.4"
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe"
@ -13779,6 +13890,11 @@ ip-regex@^2.1.0:
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==
ip3country@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ip3country/-/ip3country-5.0.0.tgz#f1394b050c51ba9c10cc691c8eb240bba3d7177a"
integrity sha512-lcFLMFU4eO1Z7tIpbVFZkaZ5ltqpeaRx7L9NsAbA9uA7/O/rj3RF8+evE5gDitooaTTIqjdzZrenFO/OOxQ2ew==
ipaddr.js@1.9.1, ipaddr.js@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
@ -13789,6 +13905,11 @@ ipaddr.js@^2.0.1:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f"
integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==
ipaddr.js@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
is-arguments@^1.0.4:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
@ -15351,6 +15472,11 @@ jose@^5.0.1:
resolved "https://registry.yarnpkg.com/jose/-/jose-5.1.3.tgz#303959d85c51b5cb14725f930270b72be56abdca"
integrity sha512-GPExOkcMsCLBTi1YetY2LmkoY559fss0+0KVa6kOfb2YFe84nAM7Nm/XzuZozah4iHgmBGrCOHL5/cy670SBRw==
jose@^5.2.0:
version "5.6.3"
resolved "https://registry.yarnpkg.com/jose/-/jose-5.6.3.tgz#415688bc84875461c86dfe271ea6029112a23e27"
integrity sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==
js-base64@^3.7.2:
version "3.7.5"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca"
@ -15603,6 +15729,13 @@ key-encoder@^2.0.3:
bn.js "^4.11.8"
elliptic "^6.4.1"
keygrip@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226"
integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==
dependencies:
tsscmp "1.0.6"
kind-of@^6.0.2:
version "6.0.3"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
@ -16776,6 +16909,13 @@ node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, nod
dependencies:
whatwg-url "^5.0.0"
node-fetch@^2.6.13:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
dependencies:
whatwg-url "^5.0.0"
node-forge@^1, node-forge@^1.2.1, node-forge@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
@ -17024,6 +17164,11 @@ obuf@^1.0.0, obuf@^1.1.2:
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
oidc-token-hash@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz#9a229f0a1ce9d4fc89bcaee5478c97a889e7b7b6"
integrity sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==
on-exit-leak-free@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4"
@ -17567,18 +17712,18 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==
pino-abstract-transport@v1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
pino-abstract-transport@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz#97f9f2631931e242da531b5c66d3079c12c9d1b5"
integrity sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==
dependencies:
readable-stream "^4.0.0"
split2 "^4.0.0"
pino-abstract-transport@v1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8"
integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==
pino-abstract-transport@v1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
dependencies:
readable-stream "^4.0.0"
split2 "^4.0.0"
@ -17615,22 +17760,22 @@ pino@^8.0.0, pino@^8.11.0, pino@^8.6.1:
sonic-boom "^3.1.0"
thread-stream "^2.0.0"
pino@^8.15.0:
version "8.15.1"
resolved "https://registry.yarnpkg.com/pino/-/pino-8.15.1.tgz#04b815ff7aa4e46b1bbab88d8010aaa2b17eaba4"
integrity sha512-Cp4QzUQrvWCRJaQ8Lzv0mJzXVk4z2jlq8JNKMGaixC2Pz5L4l2p95TkuRvYbrEbe85NQsDKrAd4zalf7Ml6WiA==
pino@^8.21.0:
version "8.21.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-8.21.0.tgz#e1207f3675a2722940d62da79a7a55a98409f00d"
integrity sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.1.1"
on-exit-leak-free "^2.1.0"
pino-abstract-transport v1.1.0
pino-abstract-transport "^1.2.0"
pino-std-serializers "^6.0.0"
process-warning "^2.0.0"
process-warning "^3.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.2.0"
safe-stable-stringify "^2.3.1"
sonic-boom "^3.1.0"
thread-stream "^2.0.0"
sonic-boom "^3.7.0"
thread-stream "^2.6.0"
pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.5:
version "4.0.6"
@ -18392,6 +18537,11 @@ process-warning@^2.0.0:
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626"
integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==
process-warning@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b"
integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
@ -20229,6 +20379,13 @@ sonic-boom@^3.1.0:
dependencies:
atomic-sleep "^1.0.0"
sonic-boom@^3.7.0:
version "3.8.1"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.1.tgz#d5ba8c4e26d6176c9a1d14d549d9ff579a163422"
integrity sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==
dependencies:
atomic-sleep "^1.0.0"
source-list-map@^2.0.0, source-list-map@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
@ -20419,6 +20576,16 @@ statsig-js@4.45.1:
js-sha256 "^0.10.1"
uuid "^8.3.2"
statsig-node@^5.23.1:
version "5.25.1"
resolved "https://registry.yarnpkg.com/statsig-node/-/statsig-node-5.25.1.tgz#6d8ea9ecaad6c09250e5ff7d33eda9fd0f9c05f4"
integrity sha512-K8+1psxFVdFr5LyXwDotJqBl7uKt8vbZO2e/9zzbLI4yDOuLDoItG5Ju5QAR0oUfEdEAANOzwV2yA052Wrc/Xw==
dependencies:
ip3country "^5.0.0"
node-fetch "^2.6.13"
ua-parser-js "^1.0.2"
uuid "^8.3.2"
statsig-react-native-expo@^4.6.1:
version "4.6.1"
resolved "https://registry.yarnpkg.com/statsig-react-native-expo/-/statsig-react-native-expo-4.6.1.tgz#0bdf49fee7112f7f28bff2405f4ba0c1727bb3d6"
@ -21052,6 +21219,13 @@ thread-stream@^2.0.0:
dependencies:
real-require "^0.2.0"
thread-stream@^2.6.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.7.0.tgz#d8a8e1b3fd538a6cca8ce69dbe5d3d097b601e11"
integrity sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==
dependencies:
real-require "^0.2.0"
throat@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
@ -21251,6 +21425,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
tsscmp@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==
tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
@ -21388,6 +21567,11 @@ ua-parser-js@^0.7.33:
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz#8bda4827be4f0b1dda91699a29499575a1f1d307"
integrity sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==
ua-parser-js@^1.0.2:
version "1.0.38"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2"
integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==
ua-parser-js@^1.0.35:
version "1.0.35"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011"
@ -21432,6 +21616,11 @@ undici@^5.28.2:
dependencies:
"@fastify/busboy" "^2.0.0"
undici@^6.14.1:
version "6.19.5"
resolved "https://registry.yarnpkg.com/undici/-/undici-6.19.5.tgz#5829101361b583b53206e81579f4df71c56d6be8"
integrity sha512-LryC15SWzqQsREHIOUybavaIHF5IoL0dJ9aWWxL/PgT1KfqAW5225FZpDUFlt9xiDMS2/S7DOKhFWA7RLksWdg==
unfetch@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-3.1.2.tgz#dc271ef77a2800768f7b459673c5604b5101ef77"
@ -22603,7 +22792,7 @@ zod-validation-error@^3.0.3:
resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.3.0.tgz#2cfe81b62d044e0453d1aa3ae7c32a2f36dde9af"
integrity sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==
zod@3.23.8, zod@^3.14.2, zod@^3.20.2, zod@^3.21.4, zod@^3.22.4:
zod@3.23.8, zod@^3.14.2, zod@^3.20.2, zod@^3.21.4, zod@^3.22.4, zod@^3.23.8:
version "3.23.8"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==