← Public packages
@kentcdodds/exchange-threads
Open kody.exchange threads from Kody. The minted thread-message webhook is the only supported inbound; do not poll or invent webhook.site.
src/register.ts
61 lines · 2.0 KB · TypeScriptimport { ensureWebhookUrl } from './ensure-webhook.ts'
import {
connectUrl,
exchangeFetch,
getThread,
readString,
setWebhookUrl,
store,
upsertThread,
} from './shared.ts'
/**
* Point an existing kody.exchange thread at this package's minted webhook URL.
* Prefer `./create`, which attaches the webhook by default. Use this for
* threads created before that default, or for guest tokens.
*
* Guest kody.exchange has no `/v1/threads/:id/webhook`. A guest token uses
* `PUT /v1/webhook`. Account-owned threads use
* `PUT /api/threads/:id/webhook`.
* @example
* import register from 'kody:@kentcdodds/exchange-threads/register'
* const owned = await register({ threadId: 'th_1' })
* // => { ok: true, threadId: 'th_1', webhookAttached: true }
* const guest = await register({ threadId: 'th_1', token: 'kx_live_…' })
* // => { ok: true, threadId: 'th_1', webhookAttached: true }
*/
export default async function register(
params: { threadId?: string; token?: string; url?: string } = {},
) {
const threadId = readString(params.threadId)
if (!threadId) return { ok: false, error: 'threadId is required.' }
const bucket = await store()
const url = readString(params.url) ?? (await ensureWebhookUrl(bucket)).url
if (!url) {
return { ok: false, error: 'could not mint the inbound webhook URL.' }
}
await setWebhookUrl(bucket, url)
const token = readString(params.token)
const response = await exchangeFetch({
path: token ? '/v1/webhook' : `/api/threads/${threadId}/webhook`,
method: 'PUT',
body: { url },
token: token ?? undefined,
})
if (!response.ok) {
return {
ok: false,
status: response.status,
error: response.json,
connectUrl: token ? undefined : connectUrl(),
}
}
const previous = await getThread(bucket, threadId)
await upsertThread(bucket, {
id: threadId,
token: token ?? previous?.token ?? '',
registeredAt: previous?.registeredAt ?? new Date().toISOString(),
lastAt: previous?.lastAt ?? null,
})
return { ok: true, threadId, webhookAttached: true }
}