mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import RNFS from 'react-native-fs' 2import {BskyAgent, jsonToLex, stringifyLex} from '@atproto/api' 3 4const GET_TIMEOUT = 15e3 // 15s 5const POST_TIMEOUT = 60e3 // 60s 6 7export function doPolyfill() { 8 BskyAgent.configure({fetch: fetchHandler}) 9} 10 11interface FetchHandlerResponse { 12 status: number 13 headers: Record<string, string> 14 body: any 15} 16 17async 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}