65 lines
2.3 KiB
TypeScript
65 lines
2.3 KiB
TypeScript
import {Client} from '@atproto/lex'
|
|
import {PasswordSession} from '@atproto/lex-password-session'
|
|
|
|
import {isJwtExpired} from '#/lib/jwt'
|
|
import {type TemporaryPushClient} from '#/lib/notifications/notifications'
|
|
import * as persisted from '#/state/persisted'
|
|
import {networkAwareFetch, sessionAccountToSessionData} from './session-core'
|
|
import {type SessionAccount} from './types'
|
|
|
|
/*
|
|
* Canonical implementation moved to session-core.ts so that module stays
|
|
* dependency-light (this file transitively pulls in a large chunk of the app).
|
|
* Re-exported here for existing consumers.
|
|
*/
|
|
export {isSignupQueued} from './session-core'
|
|
|
|
export function readLastActiveAccount() {
|
|
const {currentAccount, accounts} = persisted.get('session')
|
|
return accounts.find(a => a.did === currentAccount?.did)
|
|
}
|
|
|
|
export function isSessionExpired(account: SessionAccount) {
|
|
if (account.accessJwt) {
|
|
return isJwtExpired(account.accessJwt)
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates and resumes a throwaway session for every stored account.
|
|
* Intended to send push token revocations just before logout.
|
|
*
|
|
* Each returned {@link TemporaryPushClient} wraps a temporary `PasswordSession`
|
|
* resumed over the network to obtain a valid access token. These sessions are
|
|
* deliberately hook-free (no `onUpdated`/`onDeleted`): they must NEVER persist
|
|
* or race the active session. They are used once for the unregister call and
|
|
* discarded (reclaimed by GC), so we never call `logout()` on them.
|
|
*
|
|
* Each session is wrapped in a plain account-shaped `Client` (no proxy header)
|
|
* paired with the account's service origin and handle, matching the contract
|
|
* {@link unregisterPushToken} consumes.
|
|
*/
|
|
export async function createTemporaryClientsAndResume(
|
|
accounts: SessionAccount[],
|
|
): Promise<TemporaryPushClient[]> {
|
|
const settled = await Promise.allSettled(
|
|
accounts.map(async account => {
|
|
const session = await PasswordSession.resume(
|
|
sessionAccountToSessionData(account),
|
|
{fetch: networkAwareFetch},
|
|
)
|
|
return {
|
|
client: new Client(session),
|
|
service: session.session.service,
|
|
handle: session.session.handle,
|
|
} satisfies TemporaryPushClient
|
|
}),
|
|
)
|
|
|
|
return settled
|
|
.filter(x => x.status === 'fulfilled')
|
|
.map(promise => promise.value)
|
|
}
|