Spaces:
Build error
Build error
import { STORAGE_KEY } from "@/app/constant"; | |
import { SyncStore } from "@/app/store/sync"; | |
import { corsFetch } from "../cors"; | |
import { chunks } from "../format"; | |
export type UpstashConfig = SyncStore["upstash"]; | |
export type UpStashClient = ReturnType<typeof createUpstashClient>; | |
export function createUpstashClient(store: SyncStore) { | |
const config = store.upstash; | |
const storeKey = config.username.length === 0 ? STORAGE_KEY : config.username; | |
const chunkCountKey = `${storeKey}-chunk-count`; | |
const chunkIndexKey = (i: number) => `${storeKey}-chunk-${i}`; | |
const proxyUrl = | |
store.useProxy && store.proxyUrl.length > 0 ? store.proxyUrl : undefined; | |
return { | |
async check() { | |
try { | |
const res = await corsFetch(this.path(`get/${storeKey}`), { | |
method: "GET", | |
headers: this.headers(), | |
proxyUrl, | |
}); | |
console.log("[Upstash] check", res.status, res.statusText); | |
return [200].includes(res.status); | |
} catch (e) { | |
console.error("[Upstash] failed to check", e); | |
} | |
return false; | |
}, | |
async redisGet(key: string) { | |
const res = await corsFetch(this.path(`get/${key}`), { | |
method: "GET", | |
headers: this.headers(), | |
proxyUrl, | |
}); | |
console.log("[Upstash] get key = ", key, res.status, res.statusText); | |
const resJson = (await res.json()) as { result: string }; | |
return resJson.result; | |
}, | |
async redisSet(key: string, value: string) { | |
const res = await corsFetch(this.path(`set/${key}`), { | |
method: "POST", | |
headers: this.headers(), | |
body: value, | |
proxyUrl, | |
}); | |
console.log("[Upstash] set key = ", key, res.status, res.statusText); | |
}, | |
async get() { | |
const chunkCount = Number(await this.redisGet(chunkCountKey)); | |
if (!Number.isInteger(chunkCount)) return; | |
const chunks = await Promise.all( | |
new Array(chunkCount) | |
.fill(0) | |
.map((_, i) => this.redisGet(chunkIndexKey(i))), | |
); | |
console.log("[Upstash] get full chunks", chunks); | |
return chunks.join(""); | |
}, | |
async set(_: string, value: string) { | |
// upstash limit the max request size which is 1Mb for “Free” and “Pay as you go” | |
// so we need to split the data to chunks | |
let index = 0; | |
for await (const chunk of chunks(value)) { | |
await this.redisSet(chunkIndexKey(index), chunk); | |
index += 1; | |
} | |
await this.redisSet(chunkCountKey, index.toString()); | |
}, | |
headers() { | |
return { | |
Authorization: `Bearer ${config.apiKey}`, | |
}; | |
}, | |
path(path: string) { | |
let url = config.endpoint; | |
if (!url.endsWith("/")) { | |
url += "/"; | |
} | |
if (path.startsWith("/")) { | |
path = path.slice(1); | |
} | |
return url + path; | |
}, | |
}; | |
} | |