Add web polyfills
This commit is contained in:
parent
d6ec627c8c
commit
751dfb20fd
18 changed files with 240 additions and 105 deletions
76
src/state/lib/api-polyfill.ts
Normal file
76
src/state/lib/api-polyfill.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
import {sessionClient as AtpApi} from '@atproto/api'
|
||||
|
||||
export function doPolyfill() {
|
||||
AtpApi.xrpc.fetch = fetchHandler
|
||||
}
|
||||
|
||||
interface FetchHandlerResponse {
|
||||
status: number
|
||||
headers: Record<string, string>
|
||||
body: ArrayBuffer | undefined
|
||||
}
|
||||
|
||||
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 = JSON.stringify(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(), 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 = await res.json()
|
||||
} else if (resMimeType.startsWith('text/')) {
|
||||
resBody = await res.text()
|
||||
} else {
|
||||
throw new Error('TODO: non-textual response body')
|
||||
}
|
||||
}
|
||||
|
||||
clearTimeout(to)
|
||||
|
||||
return {
|
||||
status: resStatus,
|
||||
headers: resHeaders,
|
||||
body: resBody,
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue