this repo has no description
1import { 2 type Fetch, 3 type OAuthClientMetadataInput, 4 type OAuthClientOptions, 5 type OAuthResponseMode, 6 atprotoLoopbackClientMetadata, 7 OAuthClient, 8 OAuthSession, 9} from '@atproto/oauth-client' 10import { ExpoRuntimeImplementation } from './expo-runtime-implementation' 11import { ExpoOAuthDatabase } from './expo-oauth-database' 12import { openAuthSessionAsync, WebBrowserResultType } from 'expo-web-browser' 13 14export type Simplify<T> = { [K in keyof T]: T[K] } & NonNullable<unknown> 15 16export type ExpoOAuthClientOptions = Simplify< 17 { 18 clientMetadata?: Readonly<OAuthClientMetadataInput> 19 responseMode?: Exclude<OAuthResponseMode, 'form_post'> 20 fetch?: Fetch 21 } & Omit< 22 OAuthClientOptions, 23 | 'clientMetadata' 24 | 'responseMode' 25 | 'keyset' 26 | 'fetch' 27 | 'runtimeImplementation' 28 | 'sessionStore' 29 | 'stateStore' 30 | 'didCache' 31 | 'handleCache' 32 | 'dpopNonceCache' 33 | 'authorizationServerMetadataCache' 34 | 'protectedResourceMetadataCache' 35 > 36> 37 38export class ExpoOAuthClient extends OAuthClient { 39 constructor({ 40 responseMode = 'fragment', 41 ...options 42 }: ExpoOAuthClientOptions) { 43 const database = new ExpoOAuthDatabase() 44 45 if (!['query', 'fragment'].includes(responseMode)) { 46 throw new TypeError(`Invalid response mode: ${responseMode}`) 47 } 48 49 if (!options.clientMetadata) { 50 throw new TypeError(`No client metadata provided`) 51 } 52 53 super({ 54 ...options, 55 clientMetadata: 56 options.clientMetadata ?? atprotoLoopbackClientMetadata('localhost'), // HACK: this fixes a type error for now, look into it later 57 responseMode, 58 keyset: undefined, 59 runtimeImplementation: new ExpoRuntimeImplementation(), 60 sessionStore: database.getSessionStore(), 61 stateStore: database.getStateStore(), 62 didCache: database.getDidCache(), 63 handleCache: database.getHandleCache(), 64 dpopNonceCache: database.getDpopNonceCache(), 65 authorizationServerMetadataCache: 66 database.getAuthorizationServerMetadataCache(), 67 protectedResourceMetadataCache: 68 database.getProtectedResourceMetadataCache(), 69 }) 70 } 71 72 async signIn( 73 input: string 74 ): Promise< 75 | { status: WebBrowserResultType } 76 | { status: 'error'; error: unknown } 77 | { status: 'success'; session: OAuthSession } 78 > { 79 let url: URL 80 try { 81 url = await this.authorize(input) 82 } catch (e: unknown) { 83 return { status: 'error', error: e } 84 } 85 86 const res = await openAuthSessionAsync( 87 url.toString(), 88 this.clientMetadata.redirect_uris[0], 89 { 90 createTask: false, 91 } 92 ) 93 94 if (res.type === 'success') { 95 const resUrl = new URL(res.url) 96 const params = new URLSearchParams(resUrl.hash.substring(1)) 97 const callbackRes = await this.callback(params) 98 return { status: 'success', session: callbackRes.session } 99 } else { 100 return { status: res.type } 101 } 102 } 103}