mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at rnw 79 lines 2.2 kB view raw
1import AtpAgent from '@atproto/api' 2import RNFS from 'react-native-fs' 3 4const TIMEOUT = 10e3 // 10s 5 6export function doPolyfill() { 7 AtpAgent.configure({fetch: fetchHandler}) 8} 9 10interface FetchHandlerResponse { 11 status: number 12 headers: Record<string, string> 13 body: ArrayBuffer | undefined 14} 15 16async function fetchHandler( 17 reqUri: string, 18 reqMethod: string, 19 reqHeaders: Record<string, string>, 20 reqBody: any, 21): Promise<FetchHandlerResponse> { 22 const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type'] 23 if (reqMimeType && reqMimeType.startsWith('application/json')) { 24 reqBody = JSON.stringify(reqBody) 25 } else if ( 26 typeof reqBody === 'string' && 27 (reqBody.startsWith('/') || reqBody.startsWith('file:')) 28 ) { 29 if (reqBody.endsWith('.jpeg') || reqBody.endsWith('.jpg')) { 30 // HACK 31 // React native has a bug that inflates the size of jpegs on upload 32 // we get around that by renaming the file ext to .bin 33 // see https://github.com/facebook/react-native/issues/27099 34 // -prf 35 const newPath = reqBody.replace(/\.jpe?g$/, '.bin') 36 await RNFS.moveFile(reqBody, newPath) 37 reqBody = newPath 38 } 39 // NOTE 40 // React native treats bodies with {uri: string} as file uploads to pull from cache 41 // -prf 42 reqBody = {uri: reqBody} 43 } 44 45 const controller = new AbortController() 46 const to = setTimeout(() => controller.abort(), TIMEOUT) 47 48 const res = await fetch(reqUri, { 49 method: reqMethod, 50 headers: reqHeaders, 51 body: reqBody, 52 signal: controller.signal, 53 }) 54 55 const resStatus = res.status 56 const resHeaders: Record<string, string> = {} 57 res.headers.forEach((value: string, key: string) => { 58 resHeaders[key] = value 59 }) 60 const resMimeType = resHeaders['Content-Type'] || resHeaders['content-type'] 61 let resBody 62 if (resMimeType) { 63 if (resMimeType.startsWith('application/json')) { 64 resBody = await res.json() 65 } else if (resMimeType.startsWith('text/')) { 66 resBody = await res.text() 67 } else { 68 throw new Error('TODO: non-textual response body') 69 } 70 } 71 72 clearTimeout(to) 73 74 return { 75 status: resStatus, 76 headers: resHeaders, 77 body: resBody, 78 } 79}