← Public packages
@kentcdodds/grok-bot
Wake a named Grok Bot from Kody by posting a prompt to that bot's own Cursor webhook.
src/plain.ts
63 lines · 1.8 KB · TypeScript/**
* Turn Workers RPC Proxies / stubs into plain JSON data.
* Subscription and execute results cannot carry Proxies across the isolate
* boundary ("Proxy could not be serialized...").
*
* packageStorage object values hit the same wall on get/list — store JSON
* strings instead, and always plainClone on read.
*/
export function plainClone<T>(value: T): T {
if (value === null || value === undefined) return value
const t = typeof value
if (t === 'string' || t === 'number' || t === 'boolean' || t === 'bigint') {
return value
}
try {
return JSON.parse(JSON.stringify(value)) as T
} catch {
if (Array.isArray(value)) return [] as unknown as T
if (value && t === 'object') return {} as T
return value
}
}
function isProxySerializeError(error: unknown): boolean {
const message = error instanceof Error ? error.message : String(error)
return /Proxy could not be serialized/i.test(message)
}
/** Read packageStorage.get and always return structured-cloneable data. */
export async function storageGet(
get: (key: string) => Promise<unknown>,
key: string,
): Promise<unknown> {
try {
const raw = await get(key)
if (raw === null || raw === undefined) return null
return plainClone(raw)
} catch (error) {
if (isProxySerializeError(error)) return null
throw error
}
}
/**
* Write packageStorage values as JSON strings when they are objects/arrays.
* String/number/boolean stay as-is. Avoids unreadable Proxy object values.
*/
export async function storageSet(
set: (key: string, value: unknown) => Promise<unknown>,
key: string,
value: unknown,
): Promise<void> {
if (value === null || value === undefined) {
await set(key, value as never)
return
}
const t = typeof value
if (t === 'string' || t === 'number' || t === 'boolean') {
await set(key, value)
return
}
await set(key, JSON.stringify(value))
}