@poolse/react 0.1.0 → 0.2.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider.tsx","../src/use-me.ts","../src/use-conversation.ts","../src/use-conversations.ts","../src/use-members.ts","../src/use-messages.ts","../src/use-reactions.ts","../src/use-thread.ts","../src/use-typing.ts","../src/use-presence.ts","../src/use-realtime-status.ts","../src/use-attachment-upload.ts","../src/use-attachment-url.ts"],"names":["createContext","useRef","useMemo","Poolse","useEffect","jsx","useContext","useState","useCallback","PAGE_SIZE","upsertById"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Poolse, type PoolseConfig } from '@poolse/sdk';\nimport { createContext, useContext, useEffect, useMemo, useRef, type ReactNode } from 'react';\n\ninterface PoolseContextValue {\n chat: Poolse;\n}\n\nconst PoolseContext = createContext<PoolseContextValue | null>(null);\n\nexport interface PoolseProviderProps {\n /**\n * SDK configuration. The provider builds the `Poolse` instance ONCE\n * per mount and reads `getToken` (and the other function-typed\n * options) from a ref on each call, so it's safe to pass a fresh\n * callback or a fresh object literal on every render.\n *\n * Re-mount the provider (give it a new `key`) when you genuinely\n * want a fresh client — typically after a sign-out, a tenant swap,\n * or an `apiUrl` change. Mutating `apiUrl` / `wsUrl` / `socketPath`\n * after mount is a no-op (the values are captured at construction\n * time); dev mode logs a warning when this happens.\n */\n config: PoolseConfig;\n children: ReactNode;\n}\n\n/**\n * Top-level provider. Wrap your tree once with this; every hook in\n * `@poolse/react` reads from the context.\n *\n * ```tsx\n * <PoolseProvider config={{apiUrl, getToken}}>\n * <App />\n * </PoolseProvider>\n * ```\n *\n * The `Poolse` instance is destroyed on unmount — closes the WebSocket\n * and drops every joined channel.\n */\nexport function PoolseProvider({ config, children }: PoolseProviderProps) {\n // Hold the latest config in a ref so the SDK reads current callbacks\n // without us rebuilding the client. Without this, the standard call\n // site `<Provider config={{apiUrl, getToken}}>` re-creates `Poolse`\n // on every parent render — closing the socket mid-flight and\n // re-firing every REST call. Refs let us keep ONE SDK instance per\n // mount while still honoring a freshly-bound `getToken` closed over\n // new auth state.\n const configRef = useRef(config);\n configRef.current = config;\n\n // Captured at mount for the dev-mode change warning below.\n const initialConnectionRef = useRef<{\n apiUrl: string;\n wsUrl: string | undefined;\n socketPath: string | undefined;\n } | null>(null);\n\n const chat = useMemo(() => {\n const initial = configRef.current;\n initialConnectionRef.current = {\n apiUrl: initial.apiUrl,\n wsUrl: initial.wsUrl,\n socketPath: initial.socketPath,\n };\n return new Poolse({\n apiUrl: initial.apiUrl,\n // Always read the latest callbacks from the ref — they're free\n // to change between renders.\n getToken: () => configRef.current.getToken(),\n ...(initial.fetch\n ? { fetch: ((...args) => configRef.current.fetch!(...args)) as typeof globalThis.fetch }\n : {}),\n ...(initial.maxRetries !== undefined ? { maxRetries: initial.maxRetries } : {}),\n ...(initial.baseBackoffMs !== undefined ? { baseBackoffMs: initial.baseBackoffMs } : {}),\n ...(initial.maxBackoffMs !== undefined ? { maxBackoffMs: initial.maxBackoffMs } : {}),\n ...(initial.generateIdempotencyKey\n ? { generateIdempotencyKey: () => configRef.current.generateIdempotencyKey!() }\n : {}),\n ...(initial.wsUrl !== undefined ? { wsUrl: initial.wsUrl } : {}),\n ...(initial.socketPath !== undefined ? { socketPath: initial.socketPath } : {}),\n ...(initial.onSocketError\n ? { onSocketError: (err) => configRef.current.onSocketError!(err) }\n : {}),\n });\n // Mount-once: the `Poolse` instance owns a WebSocket and channel\n // subscriptions, so it MUST be stable for the life of the mount.\n // Changing `apiUrl` / `wsUrl` / `socketPath` requires a remount.\n }, []);\n\n // Surface mistakes early in dev: connection-shaped fields are\n // captured at construction time, so changing them after mount has\n // no effect (callbacks like `getToken` ARE re-read from the ref).\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const initial = initialConnectionRef.current;\n if (!initial) return;\n if (\n initial.apiUrl !== config.apiUrl ||\n initial.wsUrl !== config.wsUrl ||\n initial.socketPath !== config.socketPath\n ) {\n console.warn(\n '[poolse] connection-shaped config (apiUrl / wsUrl / socketPath) ' +\n 'changed after <PoolseProvider> mounted. These are captured at ' +\n 'construction time — remount the provider with a new `key` to ' +\n 'switch environments.',\n );\n }\n }, [config.apiUrl, config.wsUrl, config.socketPath]);\n }\n\n useEffect(() => {\n return () => {\n chat.destroy();\n };\n }, [chat]);\n\n const value = useMemo(() => ({ chat }), [chat]);\n\n return <PoolseContext.Provider value={value}>{children}</PoolseContext.Provider>;\n}\n\n/**\n * Access the underlying `Poolse` instance. Most app code should prefer\n * higher-level hooks (`useMessages`, `useTyping`, etc.) but the raw\n * client is here for escape-hatch usage (custom REST calls, direct\n * realtime control).\n */\nexport function usePoolse(): Poolse {\n const value = useContext(PoolseContext);\n\n if (!value) {\n throw new Error(\n 'usePoolse(): no <PoolseProvider> in the tree. Wrap your component ' +\n 'with `<PoolseProvider config={{apiUrl, getToken}}>` first.',\n );\n }\n\n return value.chat;\n}\n","import type { Me } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMeState {\n me: Me | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * The currently-signed-in End User (`/v1/me`). Fetches once on mount\n * and never re-fetches automatically — user identity is stable for\n * the JWT's lifetime.\n *\n * Most apps won't need this; the JWT subject is enough. Useful when\n * the UI needs the display name / external_id without re-asking the\n * Customer's backend.\n */\nexport function useMe(): UseMeState {\n const chat = usePoolse();\n const [state, setState] = useState<UseMeState>({\n me: null,\n loading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n const controller = new AbortController();\n\n chat.me\n .show(controller.signal)\n .then((me) => {\n if (!cancelled) setState({ me, loading: false, error: null });\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n setState({\n me: null,\n loading: false,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [chat]);\n\n return state;\n}\n","import type { Conversation, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseConversationState {\n /** The fetched conversation, or `null` while loading or on error. */\n conversation: Conversation | null;\n loading: boolean;\n error: Error | null;\n /** Re-run the GET. Use after a `chat.conversations.one(id).update(...)` to refresh state. */\n refetch: () => Promise<void>;\n}\n\n/**\n * Fetch a single conversation by id. Re-fetches when `id` changes\n * (e.g. routing to a different conversation in the same component).\n *\n * Doesn't subscribe to realtime updates yet — the backend doesn't\n * broadcast `conversation:updated` to user channels. Use `refetch()`\n * after a mutation if you need fresh state in the same render cycle.\n *\n * ```ts\n * const { conversation, loading } = useConversation(convId);\n * if (loading) return <Spinner />;\n * if (!conversation) return <NotFound />;\n * return <h1>{conversation.name ?? 'Untitled'}</h1>;\n * ```\n */\nexport function useConversation(id: Uuid | null): UseConversationState {\n const chat = usePoolse();\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [loading, setLoading] = useState(id !== null);\n const [error, setError] = useState<Error | null>(null);\n\n // The fetcher is wrapped in useCallback so it's stable across\n // renders for the same id — lets callers depend on it in their\n // own effects (e.g. polling) without re-firing on every render.\n const fetcher = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n if (id === null) return;\n setLoading(true);\n setError(null);\n try {\n const conv = await chat.conversations.one(id).show(signal);\n setConversation(conv);\n } catch (err) {\n // Ignore AbortError — the caller hit unmount or a new id.\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n },\n [chat, id],\n );\n\n useEffect(() => {\n if (id === null) {\n setConversation(null);\n setLoading(false);\n setError(null);\n return;\n }\n const controller = new AbortController();\n void fetcher(controller.signal);\n return () => controller.abort();\n }, [fetcher, id]);\n\n const refetch = useCallback(() => fetcher(), [fetcher]);\n\n return { conversation, loading, error, refetch };\n}\n","import type { Conversation, ConversationCreateRequest } from '@poolse/sdk';\nimport { useCallback, useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseConversationsState {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n create: (attrs: ConversationCreateRequest) => Promise<Conversation>;\n}\n\n/**\n * List of conversations the current End User can see.\n *\n * On mount: REST-fetches the list and subscribes to the user's\n * `user:<id>` channel for `conversation:created` events — fired by\n * the server both when this user creates a conversation AND when\n * someone else adds them to one. New rows are prepended to local\n * state with id-based dedup so an optimistic `create()` followed by\n * the realtime echo doesn't insert twice.\n *\n * `refetch()` is still here for explicit re-syncs (e.g. after a\n * mutation that the SDK doesn't yet observe — name changes,\n * settings updates). `create()` returns the canonical server row.\n */\nexport function useConversations(): UseConversationsState {\n const chat = usePoolse();\n const { me } = useMe();\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const refetch = useCallback(async () => {\n setLoading(true);\n try {\n const list = await chat.conversations.list();\n setConversations(list.data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [chat]);\n\n const create = useCallback(\n async (attrs: ConversationCreateRequest) => {\n const conv = await chat.conversations.create(attrs);\n // Optimistically prepend; if the realtime echo arrives later\n // for the same conv (because the server also broadcast it to\n // us as the creator), the id-based dedup in `prepend` keeps\n // it from inserting twice.\n setConversations((prev) => prepend(prev, conv));\n return conv;\n },\n [chat],\n );\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n // Realtime: subscribe to `user:<me.id>:conversation:created` once we\n // know who \"me\" is. Re-subscribes if `me.id` changes (rare — only on\n // sign-in/sign-out within the same provider, which is itself rare).\n useEffect(() => {\n if (!me) return;\n const userChan = chat.realtime.user(me.id);\n const off = userChan.onConversationCreated((conv) => {\n setConversations((prev) => prepend(prev, conv));\n });\n return off;\n }, [chat, me]);\n\n return { conversations, loading, error, refetch, create };\n}\n\n/**\n * Prepend `conv` if its id isn't already in `prev`; otherwise replace\n * the existing row (covers the race where the realtime echo arrives\n * for a conversation our local `create()` already inserted).\n */\nfunction prepend(prev: Conversation[], conv: Conversation): Conversation[] {\n const idx = prev.findIndex((c) => c.id === conv.id);\n if (idx === -1) return [conv, ...prev];\n const next = prev.slice();\n next[idx] = conv;\n return next;\n}\n","import type { AddMemberOptions, MemberRole, Membership, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMembersState {\n members: Membership[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n /**\n * Add one or more users by external_id. The returned memberships\n * are appended to local state on success.\n */\n addMembers: (externalIds: string[], opts?: { role?: MemberRole }) => Promise<Membership[]>;\n /**\n * Remove a member by user_id. Optimistically removes from state;\n * rolls back on server error.\n */\n removeMember: (userId: Uuid) => Promise<void>;\n}\n\n/**\n * Live-ish membership list for a conversation. Initial REST fetch on\n * mount; mutation helpers update local state in place. No realtime\n * sync yet — the backend doesn't broadcast `member:joined` /\n * `member:left` events. For now, callers who depend on\n * cross-client member updates should poll with `refetch()` or\n * remount the hook.\n */\nexport function useMembers(conversationId: Uuid): UseMembersState {\n const chat = usePoolse();\n const [members, setMembers] = useState<Membership[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Shadow ref tracking the latest committed members. Lets the\n // optimistic rollback path capture a snapshot synchronously\n // without racing the React updater queue against an `await`.\n const membersRef = useRef<Membership[]>([]);\n membersRef.current = members;\n\n const fetcher = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n setLoading(true);\n setError(null);\n try {\n const { data } = await chat.conversations.one(conversationId).listMembers(signal);\n setMembers(data);\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n },\n [chat, conversationId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void fetcher(controller.signal);\n return () => controller.abort();\n }, [fetcher]);\n\n const refetch = useCallback(() => fetcher(), [fetcher]);\n\n const addMembers = useCallback(\n async (externalIds: string[], opts: { role?: MemberRole } = {}) => {\n const addOpts: AddMemberOptions = opts.role !== undefined ? { role: opts.role } : {};\n const { data } = await chat.conversations\n .one(conversationId)\n .addMembers(externalIds, addOpts);\n // Dedup by id in case the server returns a row that was already\n // a member (idempotent re-add).\n setMembers((prev) => {\n const byId = new Map(prev.map((m) => [m.id, m]));\n for (const m of data) byId.set(m.id, m);\n return Array.from(byId.values());\n });\n return data;\n },\n [chat, conversationId],\n );\n\n const removeMember = useCallback(\n async (userId: Uuid) => {\n const snapshot = membersRef.current;\n setMembers((prev) => prev.filter((m) => m.user_id !== userId));\n try {\n await chat.conversations.one(conversationId).removeMember(userId);\n } catch (err) {\n setMembers(snapshot);\n throw err;\n }\n },\n [chat, conversationId],\n );\n\n return { members, loading, error, refetch, addMembers, removeMember };\n}\n","import type { Message, MessageCreateRequest } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMessagesState {\n /** Newest-last array. The wire returns newest-first; we reverse so list rendering matches reading order. */\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasMore: boolean;\n /** Load an older page (lower sequence numbers). Idempotent if no older messages exist. */\n loadMore: () => Promise<void>;\n /** Optimistically append + POST. Replaces the optimistic row with the server response on success. */\n send: (attrs: MessageCreateRequest) => Promise<Message>;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Live message list for `conversationId`. Combines:\n *\n * * Initial REST fetch (newest 50) on mount.\n * * WebSocket subscription for `message:new`, `message:updated`,\n * `message:deleted` — applied in-place to the cached array.\n * * Optimistic-send via `send()` — the message appears immediately\n * under the SAME id the server will assign (we pre-generate it\n * client-side and pass it through), so the realtime echo and the\n * REST response both arrive carrying that id and get deduped by\n * `findIndex(m => m.id === msg.id)`. No heuristic match, no race.\n *\n * Re-mounting with the same `conversationId` reuses the underlying\n * channel — no extra socket traffic.\n */\nexport function useMessages(conversationId: string): UseMessagesState {\n const chat = usePoolse();\n const [messages, setMessages] = useState<Message[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(true);\n\n // Cursor for `loadMore` — the lowest sequence currently in state.\n const oldestSequenceRef = useRef<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setMessages([]);\n setError(null);\n setHasMore(true);\n oldestSequenceRef.current = null;\n\n const handle = chat.conversations.one(conversationId).messages;\n\n handle\n .list({ limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled) return;\n // Wire is newest-first; flip for natural reading order.\n const ordered = [...page.data].reverse();\n setMessages(ordered);\n setHasMore(page.data.length === PAGE_SIZE);\n oldestSequenceRef.current = ordered[0]?.sequence ?? null;\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n // Realtime listeners.\n const conv = chat.realtime.conversation(conversationId);\n\n const offNew = conv.onMessage((msg) => {\n // Simple by-id upsert. Covers three cases with one expression:\n // 1) Brand-new message from another user → append.\n // 2) Echo of our own optimistic send (id we generated below) →\n // replace the temp row in place (preserves position).\n // 3) Re-delivery on channel rejoin → idempotent replace.\n setMessages((prev) => upsertById(prev, msg));\n });\n\n const offUpdated = conv.onMessageUpdated((msg) => {\n setMessages((prev) => prev.map((m) => (m.id === msg.id ? msg : m)));\n });\n\n const offDeleted = conv.onMessageDeleted((evt) => {\n setMessages((prev) =>\n prev.map((m) => (m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m)),\n );\n });\n\n return () => {\n cancelled = true;\n offNew();\n offUpdated();\n offDeleted();\n // Don't leave the channel — another component may still be reading\n // this conversation. The Poolse.destroy() at provider-unmount\n // tears everything down.\n };\n }, [chat, conversationId]);\n\n const loadMore = useCallback(async () => {\n if (!hasMore || loading) return;\n const before = oldestSequenceRef.current;\n if (!before) return;\n\n const opts: { limit: number; before?: number } = { limit: PAGE_SIZE };\n if (before !== null) opts.before = before;\n\n const page = await chat.conversations.one(conversationId).messages.list(opts);\n if (page.data.length === 0) {\n setHasMore(false);\n return;\n }\n const older = [...page.data].reverse();\n setMessages((prev) => [...older, ...prev]);\n setHasMore(page.data.length === PAGE_SIZE);\n oldestSequenceRef.current = older[0]?.sequence ?? oldestSequenceRef.current;\n }, [chat, conversationId, hasMore, loading]);\n\n const send = useCallback(\n async (attrs: MessageCreateRequest) => {\n // Generate the message id client-side and pass it through, so\n // the optimistic row, the REST response, and the realtime echo\n // ALL share one id — id-based upsert handles every race.\n const id = attrs.id ?? crypto.randomUUID();\n const tempMsg: Message = {\n id,\n tenant_id: '',\n conversation_id: conversationId,\n sender_id: null,\n type: attrs.type ?? 'text',\n body: attrs.body,\n reply_to_id: attrs.reply_to_id ?? null,\n thread_root_id: null,\n mentions: attrs.mentions ?? [],\n reactions: {},\n edited_at: null,\n deleted_at: null,\n // MAX_SAFE_INTEGER sorts the temp row to the very end (newest\n // position) until the server returns the real `sequence`.\n sequence: Number.MAX_SAFE_INTEGER,\n inserted_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, tempMsg]);\n\n try {\n const sent = await chat.conversations.one(conversationId).messages.send({ ...attrs, id });\n // Both REST and realtime carry the same id; whichever lands\n // first wins, and the second is an idempotent replace.\n setMessages((prev) => upsertById(prev, sent));\n return sent;\n } catch (err) {\n setMessages((prev) => prev.filter((m) => m.id !== id));\n throw err;\n }\n },\n [chat, conversationId],\n );\n\n return { messages, loading, error, hasMore, loadMore, send };\n}\n\nfunction upsertById(prev: Message[], msg: Message): Message[] {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx === -1) return [...prev, msg];\n const next = prev.slice();\n next[idx] = msg;\n return next;\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\n/**\n * Map of emoji → list of user_ids who reacted with it. Matches the\n * shape of `Message.reactions` so initial seeding from a message you\n * already have in state is a direct assignment.\n */\nexport type ReactionMap = Record<string, Uuid[]>;\n\ninterface UseReactionsState {\n reactions: ReactionMap;\n /** Add the caller's reaction (idempotent server-side). */\n addReaction: (emoji: string) => Promise<void>;\n /** Remove the caller's reaction. No-op if not present. */\n removeReaction: (emoji: string) => Promise<void>;\n}\n\ninterface UseReactionsOptions {\n /**\n * Required for the in-channel subscription — the realtime layer\n * routes reaction events through the conversation channel, not a\n * per-message channel. Pass the conversation id you already know.\n */\n conversationId: Uuid;\n /**\n * Seed the local reaction map from a message you already have\n * (e.g. from `useMessages`). Without this the hook starts empty\n * and only sees deltas from the realtime stream.\n */\n initialReactions?: ReactionMap;\n /**\n * Current user's id. When provided, optimistic mutate updates the\n * local map immediately for that user; when omitted, we wait for\n * the server's `reaction:added` echo to update state.\n */\n currentUserId?: Uuid | null;\n}\n\n/**\n * Live reaction map for a single message. Subscribes to\n * `reaction:added` / `reaction:removed` realtime events filtered to\n * `messageId`, and provides mutation helpers.\n *\n * ```ts\n * const { reactions, addReaction } = useReactions(msg.id, {\n * conversationId: msg.conversation_id,\n * initialReactions: msg.reactions,\n * currentUserId: me?.id,\n * });\n * <button onClick={() => addReaction('🎉')}>🎉 {reactions['🎉']?.length ?? 0}</button>\n * ```\n */\nexport function useReactions(messageId: Uuid, opts: UseReactionsOptions): UseReactionsState {\n const chat = usePoolse();\n const [reactions, setReactions] = useState<ReactionMap>(opts.initialReactions ?? {});\n\n // Keep currentUserId in a ref so the realtime callbacks (set up in\n // the mount effect) always see the latest value without having to\n // re-subscribe when it changes.\n const currentUserIdRef = useRef<Uuid | null>(opts.currentUserId ?? null);\n currentUserIdRef.current = opts.currentUserId ?? null;\n\n // Shadow ref of the latest committed reactions map — used by\n // `removeReaction` for synchronous snapshot capture so the\n // optimistic rollback isn't racing the React updater queue.\n const reactionsRef = useRef<ReactionMap>(reactions);\n reactionsRef.current = reactions;\n\n useEffect(() => {\n const conv = chat.realtime.conversation(opts.conversationId);\n\n const offAdded = conv.onReactionAdded((evt) => {\n if (evt.message_id !== messageId) return;\n setReactions((prev) => addUser(prev, evt.emoji, evt.user_id));\n });\n\n const offRemoved = conv.onReactionRemoved((evt) => {\n if (evt.message_id !== messageId) return;\n setReactions((prev) => removeUser(prev, evt.emoji, evt.user_id));\n });\n\n return () => {\n offAdded();\n offRemoved();\n };\n }, [chat, opts.conversationId, messageId]);\n\n const addReaction = useCallback(\n async (emoji: string) => {\n const uid = currentUserIdRef.current;\n // Optimistic add when we know who we are; otherwise wait for echo.\n if (uid) setReactions((prev) => addUser(prev, emoji, uid));\n try {\n await chat.messages.one(messageId).addReaction(emoji);\n } catch (err) {\n if (uid) setReactions((prev) => removeUser(prev, emoji, uid));\n throw err;\n }\n },\n [chat, messageId],\n );\n\n const removeReaction = useCallback(\n async (emoji: string) => {\n const uid = currentUserIdRef.current;\n const snapshot = reactionsRef.current;\n if (uid) setReactions((prev) => removeUser(prev, emoji, uid));\n try {\n await chat.messages.one(messageId).removeReaction(emoji);\n } catch (err) {\n if (uid) setReactions(snapshot);\n throw err;\n }\n },\n [chat, messageId],\n );\n\n return { reactions, addReaction, removeReaction };\n}\n\nfunction addUser(prev: ReactionMap, emoji: string, userId: Uuid): ReactionMap {\n const existing = prev[emoji] ?? [];\n if (existing.includes(userId)) return prev;\n return { ...prev, [emoji]: [...existing, userId] };\n}\n\nfunction removeUser(prev: ReactionMap, emoji: string, userId: Uuid): ReactionMap {\n const existing = prev[emoji];\n if (!existing || !existing.includes(userId)) return prev;\n const next = existing.filter((id) => id !== userId);\n if (next.length === 0) {\n const { [emoji]: _, ...rest } = prev;\n return rest;\n }\n return { ...prev, [emoji]: next };\n}\n","import type { Message, MessageCreateRequest, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseThreadState {\n /** Replies, oldest-first (the wire returns oldest-first; we don't flip). */\n replies: Message[];\n loading: boolean;\n error: Error | null;\n /** More older-than-current-page replies available on the server. */\n hasMore: boolean;\n /** Load the next page after the current newest reply. Idempotent if no more. */\n loadMore: () => Promise<void>;\n /**\n * Send a reply into this thread. Fills `reply_to_id` with the root\n * message id automatically; pass `body` (and any other\n * `MessageCreateRequest` fields) as you would to `useMessages.send`.\n */\n sendReply: (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => Promise<Message>;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Thread view rooted at `rootMessageId`. Loads replies oldest-first\n * with cursor pagination (`after: sequence`), subscribes to the\n * conversation channel's `message:new` event filtered by\n * `thread_root_id === rootMessageId`, and provides a `sendReply`\n * that wires `reply_to_id` for you.\n *\n * Like `useMessages`, the optimistic send uses the same id the\n * server will assign (auto-generated by the SDK), so the realtime\n * echo just upserts in place — no double-render.\n */\nexport function useThread(conversationId: Uuid, rootMessageId: Uuid): UseThreadState {\n const chat = usePoolse();\n const [replies, setReplies] = useState<Message[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(true);\n\n // Cursor for `loadMore` — the highest sequence currently in state.\n const newestSequenceRef = useRef<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setReplies([]);\n setError(null);\n setHasMore(true);\n newestSequenceRef.current = null;\n\n chat.messages\n .one(rootMessageId)\n .replies({ limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled) return;\n setReplies(page.data);\n setHasMore(page.data.length === PAGE_SIZE);\n newestSequenceRef.current = page.data[page.data.length - 1]?.sequence ?? null;\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n // Realtime: filter conversation messages for thread membership.\n const conv = chat.realtime.conversation(conversationId);\n const offNew = conv.onMessage((msg) => {\n if (msg.thread_root_id !== rootMessageId) return;\n setReplies((prev) => upsertById(prev, msg));\n });\n const offUpdated = conv.onMessageUpdated((msg) => {\n if (msg.thread_root_id !== rootMessageId) return;\n setReplies((prev) => prev.map((m) => (m.id === msg.id ? msg : m)));\n });\n const offDeleted = conv.onMessageDeleted((evt) => {\n setReplies((prev) =>\n prev.map((m) => (m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m)),\n );\n });\n\n return () => {\n cancelled = true;\n offNew();\n offUpdated();\n offDeleted();\n };\n }, [chat, conversationId, rootMessageId]);\n\n const loadMore = useCallback(async () => {\n if (!hasMore || loading) return;\n const after = newestSequenceRef.current;\n if (after === null) return;\n const page = await chat.messages.one(rootMessageId).replies({ limit: PAGE_SIZE, after });\n if (page.data.length === 0) {\n setHasMore(false);\n return;\n }\n setReplies((prev) => [...prev, ...page.data]);\n setHasMore(page.data.length === PAGE_SIZE);\n newestSequenceRef.current = page.data[page.data.length - 1]?.sequence ?? after;\n }, [chat, rootMessageId, hasMore, loading]);\n\n const sendReply = useCallback(\n async (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => {\n const id = attrs.id ?? crypto.randomUUID();\n const tempMsg: Message = {\n id,\n tenant_id: '',\n conversation_id: conversationId,\n sender_id: null,\n type: attrs.type ?? 'text',\n body: attrs.body,\n reply_to_id: rootMessageId,\n thread_root_id: rootMessageId,\n mentions: attrs.mentions ?? [],\n reactions: {},\n edited_at: null,\n deleted_at: null,\n sequence: Number.MAX_SAFE_INTEGER,\n inserted_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n };\n setReplies((prev) => [...prev, tempMsg]);\n\n try {\n const sent = await chat.conversations.one(conversationId).messages.send({\n ...attrs,\n id,\n reply_to_id: rootMessageId,\n });\n setReplies((prev) => upsertById(prev, sent));\n return sent;\n } catch (err) {\n setReplies((prev) => prev.filter((m) => m.id !== id));\n throw err;\n }\n },\n [chat, conversationId, rootMessageId],\n );\n\n return { replies, loading, error, hasMore, loadMore, sendReply };\n}\n\nfunction upsertById(prev: Message[], msg: Message): Message[] {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx === -1) return [...prev, msg];\n const next = prev.slice();\n next[idx] = msg;\n return next;\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseTypingState {\n /** Set of user_ids currently typing. */\n typing: Set<Uuid>;\n /**\n * Send a typing ping to the server. Debounced inside the SDK — the\n * server squashes `typing:start` to one push per (user, conversation,\n * window). Call as often as you want from input handlers.\n */\n signalTyping: () => void;\n}\n\n/**\n * Tracks who's typing in `conversationId`. Subscribes to the\n * `typing:start` / `typing:stop` broadcasts; auto-cleans up entries\n * when stop fires.\n *\n * `signalTyping` debounces on the client side to once per 500 ms so a\n * fast-typing user doesn't flood the channel — poolse does its own\n * server-side debounce too, so both layers are safe.\n */\nexport function useTyping(conversationId: string): UseTypingState {\n const chat = usePoolse();\n const { me } = useMe();\n const [typing, setTyping] = useState<Set<Uuid>>(new Set());\n const lastPingRef = useRef(0);\n\n // `me` resolves asynchronously after first render; read it from a\n // ref inside the event handlers so the subscription doesn't need to\n // re-attach when `me` lands (which would briefly drop incoming\n // typing events from other users).\n const meIdRef = useRef<Uuid | null>(me?.id ?? null);\n meIdRef.current = me?.id ?? null;\n\n useEffect(() => {\n setTyping(new Set());\n\n const conv = chat.realtime.conversation(conversationId);\n\n const offStart = conv.onTypingStart((evt) => {\n // Don't render the current user's own typing — they know they're typing.\n if (meIdRef.current && evt.user_id === meIdRef.current) return;\n setTyping((prev) => {\n if (prev.has(evt.user_id)) return prev;\n const next = new Set(prev);\n next.add(evt.user_id);\n return next;\n });\n });\n\n const offStop = conv.onTypingStop((evt) => {\n if (meIdRef.current && evt.user_id === meIdRef.current) return;\n setTyping((prev) => {\n if (!prev.has(evt.user_id)) return prev;\n const next = new Set(prev);\n next.delete(evt.user_id);\n return next;\n });\n });\n\n return () => {\n offStart();\n offStop();\n };\n }, [chat, conversationId]);\n\n const signalTyping = useCallback(() => {\n const now = Date.now();\n if (now - lastPingRef.current < 500) return;\n lastPingRef.current = now;\n chat.realtime.conversation(conversationId).sendTyping();\n }, [chat, conversationId]);\n\n return { typing, signalTyping };\n}\n","import type { PresenceSnapshot, Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UsePresenceState {\n /** Set of user_ids currently online in this conversation. */\n online: Set<Uuid>;\n}\n\n/**\n * Who's currently joined to `conversationId`'s channel. Backed by\n * Phoenix.Presence broadcasts (`presence_state` snapshot on join,\n * `presence_diff` on changes).\n */\nexport function usePresence(conversationId: string): UsePresenceState {\n const chat = usePoolse();\n const [online, setOnline] = useState<Set<Uuid>>(new Set());\n\n useEffect(() => {\n setOnline(new Set());\n\n const conv = chat.realtime.conversation(conversationId);\n\n const applyState = (state: PresenceSnapshot) => {\n setOnline(new Set(Object.keys(state)));\n };\n\n const applyDiff = (diff: { joins?: PresenceSnapshot; leaves?: PresenceSnapshot }) => {\n setOnline((prev) => {\n const next = new Set(prev);\n if (diff.joins) Object.keys(diff.joins).forEach((id) => next.add(id));\n if (diff.leaves) Object.keys(diff.leaves).forEach((id) => next.delete(id));\n return next;\n });\n };\n\n const offState = conv.onPresenceState(applyState);\n const offDiff = conv.onPresenceDiff(applyDiff as (s: PresenceSnapshot) => void);\n\n return () => {\n offState();\n offDiff();\n };\n }, [chat, conversationId]);\n\n return { online };\n}\n","import type { RealtimeStatus } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\n/**\n * Connection status of the underlying WebSocket. Useful for showing a\n * \"reconnecting…\" banner without coupling to socket internals.\n *\n * Returns one of: `'idle' | 'connecting' | 'connected' | 'reconnecting' | 'closed'`.\n */\nexport function useRealtimeStatus(): RealtimeStatus {\n const chat = usePoolse();\n const [status, setStatus] = useState<RealtimeStatus>(chat.realtime.getStatus());\n\n useEffect(() => {\n setStatus(chat.realtime.getStatus());\n return chat.realtime.onStatus(setStatus);\n }, [chat]);\n\n return status;\n}\n","import type { Attachment, AttachmentUploadInput } from '@poolse/sdk';\nimport { useCallback, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseAttachmentUploadState {\n /** Last successfully uploaded attachment, or null. */\n attachment: Attachment | null;\n uploading: boolean;\n error: Error | null;\n /**\n * Run the upload pipeline (presigned-URL request + PUT). Updates\n * local state with the resolved attachment on success; sets `error`\n * and rethrows on failure so callers can surface a toast.\n */\n upload: (input: AttachmentUploadInput) => Promise<Attachment>;\n /** Reset state (clears `attachment`, `error`). */\n reset: () => void;\n}\n\n/**\n * Stateful wrapper around `chat.attachments.upload`. Provides\n * `uploading` + `error` flags for the common \"show a spinner while\n * the PUT is in flight\" UI, plus retention of the last attachment\n * so the caller can reference its id when sending a message.\n *\n * ```tsx\n * const { upload, uploading, attachment } = useAttachmentUpload();\n * const onPick = async (file: File) => {\n * const att = await upload({\n * body: file, contentType: file.type, byteSize: file.size, filename: file.name\n * });\n * await chat.conversations.one(convId).messages.send({\n * body: 'attached',\n * custom_data: { attachment_id: att.id },\n * });\n * };\n * ```\n */\nexport function useAttachmentUpload(): UseAttachmentUploadState {\n const chat = usePoolse();\n const [attachment, setAttachment] = useState<Attachment | null>(null);\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n // Track an in-flight upload's AbortController so unmount cancels it.\n const inFlightRef = useRef<AbortController | null>(null);\n\n const upload = useCallback(\n async (input: AttachmentUploadInput): Promise<Attachment> => {\n // Cancel any prior in-flight upload — last-write-wins on intent.\n inFlightRef.current?.abort();\n const controller = new AbortController();\n inFlightRef.current = controller;\n\n setUploading(true);\n setError(null);\n try {\n const att = await chat.attachments.upload(input, { signal: controller.signal });\n if (inFlightRef.current === controller) {\n setAttachment(att);\n }\n return att;\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n if (inFlightRef.current === controller) {\n setUploading(false);\n inFlightRef.current = null;\n }\n }\n },\n [chat],\n );\n\n const reset = useCallback(() => {\n inFlightRef.current?.abort();\n inFlightRef.current = null;\n setAttachment(null);\n setError(null);\n setUploading(false);\n }, []);\n\n return { attachment, uploading, error, upload, reset };\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseAttachmentUrlState {\n /** Presigned GET URL, or null while loading / on error. */\n url: string | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Resolve an attachment's presigned download URL. Pass `null` to\n * skip the fetch — useful in routing-driven views where the id may\n * not be known yet.\n *\n * Doesn't auto-refresh: the server's URL TTL is ~1 hour and most\n * UI lifetimes are much shorter. If you do need a refresh (long-lived\n * dashboard, etc.), remount the hook or wrap it in a parent that\n * re-keys on a timer.\n *\n * ```tsx\n * const { url } = useAttachmentUrl(message.custom_data?.attachment_id ?? null);\n * return url ? <img src={url} /> : <Spinner />;\n * ```\n */\nexport function useAttachmentUrl(attachmentId: Uuid | null): UseAttachmentUrlState {\n const chat = usePoolse();\n const [url, setUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(attachmentId !== null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (attachmentId === null) {\n setUrl(null);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n const controller = new AbortController();\n setLoading(true);\n setError(null);\n chat.attachments\n .one(attachmentId)\n .downloadUrl({ signal: controller.signal })\n .then((res) => {\n if (cancelled) return;\n setUrl(res.url);\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [chat, attachmentId]);\n\n return { url, loading, error };\n}\n"]}
1
+ {"version":3,"sources":["../src/provider.tsx","../src/use-me.ts","../src/use-conversation.ts","../src/use-conversations.ts","../src/use-members.ts","../src/use-messages.ts","../src/use-reactions.ts","../src/use-thread.ts","../src/use-typing.ts","../src/use-presence.ts","../src/use-realtime-status.ts","../src/use-attachment-upload.ts","../src/use-attachment-url.ts"],"names":["createContext","useRef","useMemo","Poolse","useEffect","jsx","useContext","useState","useCallback","PAGE_SIZE","upsertById"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Poolse, type PoolseConfig } from '@poolse/sdk';\nimport { createContext, useContext, useEffect, useMemo, useRef, type ReactNode } from 'react';\n\ninterface PoolseContextValue {\n chat: Poolse;\n}\n\nconst PoolseContext = createContext<PoolseContextValue | null>(null);\n\nexport interface PoolseProviderProps {\n /**\n * SDK configuration. The provider builds the `Poolse` instance ONCE\n * per mount and reads `getToken` (and the other function-typed\n * options) from a ref on each call, so it's safe to pass a fresh\n * callback or a fresh object literal on every render.\n *\n * Re-mount the provider (give it a new `key`) when you genuinely\n * want a fresh client — typically after a sign-out, a tenant swap,\n * or an `apiUrl` change. Mutating `apiUrl` / `wsUrl` / `socketPath`\n * after mount is a no-op (the values are captured at construction\n * time); dev mode logs a warning when this happens.\n */\n config: PoolseConfig;\n children: ReactNode;\n}\n\n/**\n * Top-level provider. Wrap your tree once with this; every hook in\n * `@poolse/react` reads from the context.\n *\n * ```tsx\n * <PoolseProvider config={{apiUrl, getToken}}>\n * <App />\n * </PoolseProvider>\n * ```\n *\n * The `Poolse` instance is destroyed on unmount — closes the WebSocket\n * and drops every joined channel.\n */\nexport function PoolseProvider({ config, children }: PoolseProviderProps) {\n // Hold the latest config in a ref so the SDK reads current callbacks\n // without us rebuilding the client. Without this, the standard call\n // site `<Provider config={{apiUrl, getToken}}>` re-creates `Poolse`\n // on every parent render — closing the socket mid-flight and\n // re-firing every REST call. Refs let us keep ONE SDK instance per\n // mount while still honoring a freshly-bound `getToken` closed over\n // new auth state.\n const configRef = useRef(config);\n configRef.current = config;\n\n // Captured at mount for the dev-mode change warning below.\n const initialConnectionRef = useRef<{\n apiUrl: string | undefined;\n wsUrl: string | undefined;\n socketPath: string | undefined;\n } | null>(null);\n\n const chat = useMemo(() => {\n const initial = configRef.current;\n initialConnectionRef.current = {\n apiUrl: initial.apiUrl,\n wsUrl: initial.wsUrl,\n socketPath: initial.socketPath,\n };\n return new Poolse({\n // apiUrl is optional in PoolseConfig — only forward when set\n // so the SDK can fall back to its hosted-endpoint default.\n ...(initial.apiUrl !== undefined ? { apiUrl: initial.apiUrl } : {}),\n // Always read the latest callbacks from the ref — they're free\n // to change between renders.\n getToken: () => configRef.current.getToken(),\n ...(initial.fetch\n ? { fetch: ((...args) => configRef.current.fetch!(...args)) as typeof globalThis.fetch }\n : {}),\n ...(initial.maxRetries !== undefined ? { maxRetries: initial.maxRetries } : {}),\n ...(initial.baseBackoffMs !== undefined ? { baseBackoffMs: initial.baseBackoffMs } : {}),\n ...(initial.maxBackoffMs !== undefined ? { maxBackoffMs: initial.maxBackoffMs } : {}),\n ...(initial.generateIdempotencyKey\n ? { generateIdempotencyKey: () => configRef.current.generateIdempotencyKey!() }\n : {}),\n ...(initial.wsUrl !== undefined ? { wsUrl: initial.wsUrl } : {}),\n ...(initial.socketPath !== undefined ? { socketPath: initial.socketPath } : {}),\n ...(initial.onSocketError\n ? { onSocketError: (err) => configRef.current.onSocketError!(err) }\n : {}),\n });\n // Mount-once: the `Poolse` instance owns a WebSocket and channel\n // subscriptions, so it MUST be stable for the life of the mount.\n // Changing `apiUrl` / `wsUrl` / `socketPath` requires a remount.\n }, []);\n\n // Surface mistakes early in dev: connection-shaped fields are\n // captured at construction time, so changing them after mount has\n // no effect (callbacks like `getToken` ARE re-read from the ref).\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const initial = initialConnectionRef.current;\n if (!initial) return;\n if (\n initial.apiUrl !== config.apiUrl ||\n initial.wsUrl !== config.wsUrl ||\n initial.socketPath !== config.socketPath\n ) {\n console.warn(\n '[poolse] connection-shaped config (apiUrl / wsUrl / socketPath) ' +\n 'changed after <PoolseProvider> mounted. These are captured at ' +\n 'construction time — remount the provider with a new `key` to ' +\n 'switch environments.',\n );\n }\n }, [config.apiUrl, config.wsUrl, config.socketPath]);\n }\n\n useEffect(() => {\n return () => {\n chat.destroy();\n };\n }, [chat]);\n\n const value = useMemo(() => ({ chat }), [chat]);\n\n return <PoolseContext.Provider value={value}>{children}</PoolseContext.Provider>;\n}\n\n/**\n * Access the underlying `Poolse` instance. Most app code should prefer\n * higher-level hooks (`useMessages`, `useTyping`, etc.) but the raw\n * client is here for escape-hatch usage (custom REST calls, direct\n * realtime control).\n */\nexport function usePoolse(): Poolse {\n const value = useContext(PoolseContext);\n\n if (!value) {\n throw new Error(\n 'usePoolse(): no <PoolseProvider> in the tree. Wrap your component ' +\n 'with `<PoolseProvider config={{apiUrl, getToken}}>` first.',\n );\n }\n\n return value.chat;\n}\n","import type { Me } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMeState {\n me: Me | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * The currently-signed-in End User (`/v1/me`). Fetches once on mount\n * and never re-fetches automatically — user identity is stable for\n * the JWT's lifetime.\n *\n * Most apps won't need this; the JWT subject is enough. Useful when\n * the UI needs the display name / external_id without re-asking the\n * Customer's backend.\n */\nexport function useMe(): UseMeState {\n const chat = usePoolse();\n const [state, setState] = useState<UseMeState>({\n me: null,\n loading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n const controller = new AbortController();\n\n chat.me\n .show(controller.signal)\n .then((me) => {\n if (!cancelled) setState({ me, loading: false, error: null });\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n setState({\n me: null,\n loading: false,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [chat]);\n\n return state;\n}\n","import type { Conversation, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseConversationState {\n /** The fetched conversation, or `null` while loading or on error. */\n conversation: Conversation | null;\n loading: boolean;\n error: Error | null;\n /** Re-run the GET. Use after a `chat.conversations.one(id).update(...)` to refresh state. */\n refetch: () => Promise<void>;\n}\n\n/**\n * Fetch a single conversation by id. Re-fetches when `id` changes\n * (e.g. routing to a different conversation in the same component).\n *\n * Doesn't subscribe to realtime updates yet — the backend doesn't\n * broadcast `conversation:updated` to user channels. Use `refetch()`\n * after a mutation if you need fresh state in the same render cycle.\n *\n * ```ts\n * const { conversation, loading } = useConversation(convId);\n * if (loading) return <Spinner />;\n * if (!conversation) return <NotFound />;\n * return <h1>{conversation.name ?? 'Untitled'}</h1>;\n * ```\n */\nexport function useConversation(id: Uuid | null): UseConversationState {\n const chat = usePoolse();\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [loading, setLoading] = useState(id !== null);\n const [error, setError] = useState<Error | null>(null);\n\n // The fetcher is wrapped in useCallback so it's stable across\n // renders for the same id — lets callers depend on it in their\n // own effects (e.g. polling) without re-firing on every render.\n const fetcher = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n if (id === null) return;\n setLoading(true);\n setError(null);\n try {\n const conv = await chat.conversations.one(id).show(signal);\n setConversation(conv);\n } catch (err) {\n // Ignore AbortError — the caller hit unmount or a new id.\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n },\n [chat, id],\n );\n\n useEffect(() => {\n if (id === null) {\n setConversation(null);\n setLoading(false);\n setError(null);\n return;\n }\n const controller = new AbortController();\n void fetcher(controller.signal);\n return () => controller.abort();\n }, [fetcher, id]);\n\n const refetch = useCallback(() => fetcher(), [fetcher]);\n\n return { conversation, loading, error, refetch };\n}\n","import type { Conversation, ConversationCreateRequest, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseConversationsState {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n create: (attrs: ConversationCreateRequest) => Promise<Conversation>;\n /**\n * Per-conversation unread count, keyed by conversation id. Sourced\n * from `Conversation.unread_count` on the initial fetch and kept\n * fresh as the caller marks conversations read (via `markRead`).\n *\n * Note: cross-conversation incrementing on a new inbound message\n * requires subscribing to every conversation channel, which the SDK\n * doesn't do by default. Counts in this map are accurate for the\n * conversation the caller has open + correct at fetch time for the\n * rest; refetch on a fresh tab focus for true reconciliation.\n */\n unreadCounts: Record<Uuid, number>;\n /** Force a conversation's unread to 0 — invoked by `markReadUpTo`. */\n markConversationRead: (conversationId: Uuid) => void;\n}\n\n/**\n * List of conversations the current End User can see.\n *\n * On mount: REST-fetches the list and subscribes to the user's\n * `user:<id>` channel for `conversation:created` events — fired by\n * the server both when this user creates a conversation AND when\n * someone else adds them to one. New rows are prepended to local\n * state with id-based dedup so an optimistic `create()` followed by\n * the realtime echo doesn't insert twice.\n *\n * `refetch()` is still here for explicit re-syncs (e.g. after a\n * mutation that the SDK doesn't yet observe — name changes,\n * settings updates). `create()` returns the canonical server row.\n */\nexport function useConversations(): UseConversationsState {\n const chat = usePoolse();\n const { me } = useMe();\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const refetch = useCallback(async () => {\n setLoading(true);\n try {\n const list = await chat.conversations.list();\n setConversations(list.data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [chat]);\n\n const create = useCallback(\n async (attrs: ConversationCreateRequest) => {\n const conv = await chat.conversations.create(attrs);\n // Optimistically prepend; if the realtime echo arrives later\n // for the same conv (because the server also broadcast it to\n // us as the creator), the id-based dedup in `prepend` keeps\n // it from inserting twice.\n setConversations((prev) => prepend(prev, conv));\n return conv;\n },\n [chat],\n );\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n // Realtime: subscribe to `user:<me.id>:conversation:created` once we\n // know who \"me\" is. Re-subscribes if `me.id` changes (rare — only on\n // sign-in/sign-out within the same provider, which is itself rare).\n useEffect(() => {\n if (!me) return;\n const userChan = chat.realtime.user(me.id);\n const off = userChan.onConversationCreated((conv) => {\n setConversations((prev) => prepend(prev, conv));\n });\n return off;\n }, [chat, me]);\n\n // Force-zero an unread count without mutating the conversation row.\n // Wired by ConversationView's auto-mark-read on scroll so the sidebar\n // badge clears the moment the caller's IntersectionObserver fires\n // — before the server roundtrip + realtime echo for `member:read`.\n const markConversationRead = useCallback((conversationId: Uuid) => {\n setConversations((prev) =>\n prev.map((c) => (c.id === conversationId ? { ...c, unread_count: 0 } : c)),\n );\n }, []);\n\n const unreadCounts = useMemo<Record<Uuid, number>>(() => {\n const out: Record<Uuid, number> = {};\n for (const c of conversations) {\n if (typeof c.unread_count === 'number' && c.unread_count > 0) {\n out[c.id] = c.unread_count;\n }\n }\n return out;\n }, [conversations]);\n\n return { conversations, loading, error, refetch, create, unreadCounts, markConversationRead };\n}\n\n/**\n * Prepend `conv` if its id isn't already in `prev`; otherwise replace\n * the existing row (covers the race where the realtime echo arrives\n * for a conversation our local `create()` already inserted).\n */\nfunction prepend(prev: Conversation[], conv: Conversation): Conversation[] {\n const idx = prev.findIndex((c) => c.id === conv.id);\n if (idx === -1) return [conv, ...prev];\n const next = prev.slice();\n next[idx] = conv;\n return next;\n}\n","import type { AddMemberOptions, MemberRole, Membership, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMembersState {\n members: Membership[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n /**\n * Add one or more users by external_id. The returned memberships\n * are appended to local state on success.\n */\n addMembers: (externalIds: string[], opts?: { role?: MemberRole }) => Promise<Membership[]>;\n /**\n * Remove a member by user_id. Optimistically removes from state;\n * rolls back on server error.\n */\n removeMember: (userId: Uuid) => Promise<void>;\n}\n\n/**\n * Live-ish membership list for a conversation. Initial REST fetch on\n * mount; mutation helpers update local state in place.\n *\n * Realtime: subscribes to `member:read` on the conversation channel\n * and advances the matching membership's `last_read_message_id` /\n * `last_read_at` so the sender's read-receipt glyph flips from \"sent\"\n * to \"read\" without a refetch. `member:joined` / `member:left` aren't\n * broadcast yet — for cross-client adds/removes, call `refetch()`.\n */\nexport function useMembers(conversationId: Uuid): UseMembersState {\n const chat = usePoolse();\n const [members, setMembers] = useState<Membership[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Shadow ref tracking the latest committed members. Lets the\n // optimistic rollback path capture a snapshot synchronously\n // without racing the React updater queue against an `await`.\n const membersRef = useRef<Membership[]>([]);\n membersRef.current = members;\n\n const fetcher = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n // Empty id = \"skip fetch\" — used by callers that conditionally\n // want member data (e.g. ConversationView's `mentions={false}\n // readReceipts={false}` configuration). Better than asking\n // every caller to wrap in `enabled ? useMembers(id) : null`.\n if (!conversationId) {\n setLoading(false);\n setMembers([]);\n setError(null);\n return;\n }\n setLoading(true);\n setError(null);\n try {\n const { data } = await chat.conversations.one(conversationId).listMembers(signal);\n setMembers(data);\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n },\n [chat, conversationId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void fetcher(controller.signal);\n return () => controller.abort();\n }, [fetcher]);\n\n // Real-time read-cursor sync. When ANY member reads, advance their\n // membership row locally — the sender's UI uses\n // max(memberships.last_read_message_id.sequence) to decide whether\n // to show the \"read\" glyph, so this single state edit drives the\n // whole receipt UI.\n useEffect(() => {\n if (!conversationId) return;\n const channel = chat.realtime.conversation(conversationId);\n const off = channel.onMemberRead((evt) => {\n setMembers((prev) =>\n prev.map((m) =>\n m.user_id === evt.user_id\n ? {\n ...m,\n last_read_message_id: evt.last_read_message_id,\n last_read_at: evt.last_read_at,\n }\n : m,\n ),\n );\n });\n return () => off();\n }, [chat, conversationId]);\n\n const refetch = useCallback(() => fetcher(), [fetcher]);\n\n const addMembers = useCallback(\n async (externalIds: string[], opts: { role?: MemberRole } = {}) => {\n const addOpts: AddMemberOptions = opts.role !== undefined ? { role: opts.role } : {};\n const { data } = await chat.conversations\n .one(conversationId)\n .addMembers(externalIds, addOpts);\n // Dedup by id in case the server returns a row that was already\n // a member (idempotent re-add).\n setMembers((prev) => {\n const byId = new Map(prev.map((m) => [m.id, m]));\n for (const m of data) byId.set(m.id, m);\n return Array.from(byId.values());\n });\n return data;\n },\n [chat, conversationId],\n );\n\n const removeMember = useCallback(\n async (userId: Uuid) => {\n const snapshot = membersRef.current;\n setMembers((prev) => prev.filter((m) => m.user_id !== userId));\n try {\n await chat.conversations.one(conversationId).removeMember(userId);\n } catch (err) {\n setMembers(snapshot);\n throw err;\n }\n },\n [chat, conversationId],\n );\n\n return { members, loading, error, refetch, addMembers, removeMember };\n}\n","import type { Message, MessageCreateRequest, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseMessagesState {\n /** Newest-last array. The wire returns newest-first; we reverse so list rendering matches reading order. */\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasMore: boolean;\n /** Load an older page (lower sequence numbers). Idempotent if no older messages exist. */\n loadMore: () => Promise<void>;\n /** Optimistically append + POST. Replaces the optimistic row with the server response on success. */\n send: (attrs: MessageCreateRequest) => Promise<Message>;\n /**\n * Edit a message you previously sent. Optimistically updates the\n * local row, rolls back on server error. Server enforces\n * sender-only authorization — calling this for a message you didn't\n * send will throw an ApiError.\n */\n edit: (messageId: Uuid, body: string) => Promise<Message>;\n /**\n * Soft-delete a message you sent (or that you have admin authority\n * over). Optimistically applies the tombstone (`deleted_at` + null\n * body) locally, rolls back on error.\n */\n delete: (messageId: Uuid) => Promise<void>;\n /**\n * Advance the caller's read cursor to `messageId`. Server emits\n * read-receipt updates to other members; the conversation's\n * unread count drops to zero. No local state mutation — this is\n * \"tell the server we read up to here\".\n */\n markReadUpTo: (messageId: Uuid) => Promise<void>;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Live message list for `conversationId`. Combines:\n *\n * * Initial REST fetch (newest 50) on mount.\n * * WebSocket subscription for `message:new`, `message:updated`,\n * `message:deleted` — applied in-place to the cached array.\n * * Optimistic-send via `send()` — the message appears immediately\n * under the SAME id the server will assign (we pre-generate it\n * client-side and pass it through), so the realtime echo and the\n * REST response both arrive carrying that id and get deduped by\n * `findIndex(m => m.id === msg.id)`. No heuristic match, no race.\n *\n * Re-mounting with the same `conversationId` reuses the underlying\n * channel — no extra socket traffic.\n */\nexport function useMessages(conversationId: string): UseMessagesState {\n const chat = usePoolse();\n const { me } = useMe();\n const [messages, setMessages] = useState<Message[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(true);\n\n // Cursor for `loadMore` — the lowest sequence currently in state.\n const oldestSequenceRef = useRef<number | null>(null);\n\n // Hold `me.id` in a ref so `send()` stays stable across renders\n // (otherwise its identity changes every time `me` reloads, which\n // would re-create handlers in calling components).\n const meIdRef = useRef<string | null>(me?.id ?? null);\n meIdRef.current = me?.id ?? null;\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setMessages([]);\n setError(null);\n setHasMore(true);\n oldestSequenceRef.current = null;\n\n const handle = chat.conversations.one(conversationId).messages;\n\n handle\n .list({ limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled) return;\n // Wire is newest-first; flip for natural reading order.\n const ordered = [...page.data].reverse();\n setMessages(ordered);\n setHasMore(page.data.length === PAGE_SIZE);\n oldestSequenceRef.current = ordered[0]?.sequence ?? null;\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n // Realtime listeners.\n const conv = chat.realtime.conversation(conversationId);\n\n const offNew = conv.onMessage((msg) => {\n // Simple by-id upsert. Covers three cases with one expression:\n // 1) Brand-new message from another user → append.\n // 2) Echo of our own optimistic send (id we generated below) →\n // replace the temp row in place (preserves position).\n // 3) Re-delivery on channel rejoin → idempotent replace.\n setMessages((prev) => upsertById(prev, msg));\n });\n\n const offUpdated = conv.onMessageUpdated((msg) => {\n setMessages((prev) => prev.map((m) => (m.id === msg.id ? msg : m)));\n });\n\n const offDeleted = conv.onMessageDeleted((evt) => {\n setMessages((prev) =>\n prev.map((m) => (m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m)),\n );\n });\n\n return () => {\n cancelled = true;\n offNew();\n offUpdated();\n offDeleted();\n // Don't leave the channel — another component may still be reading\n // this conversation. The Poolse.destroy() at provider-unmount\n // tears everything down.\n };\n }, [chat, conversationId]);\n\n const loadMore = useCallback(async () => {\n if (!hasMore || loading) return;\n const before = oldestSequenceRef.current;\n if (!before) return;\n\n const opts: { limit: number; before?: number } = { limit: PAGE_SIZE };\n if (before !== null) opts.before = before;\n\n const page = await chat.conversations.one(conversationId).messages.list(opts);\n if (page.data.length === 0) {\n setHasMore(false);\n return;\n }\n const older = [...page.data].reverse();\n setMessages((prev) => [...older, ...prev]);\n setHasMore(page.data.length === PAGE_SIZE);\n oldestSequenceRef.current = older[0]?.sequence ?? oldestSequenceRef.current;\n }, [chat, conversationId, hasMore, loading]);\n\n const send = useCallback(\n async (attrs: MessageCreateRequest) => {\n // Generate the message id client-side and pass it through, so\n // the optimistic row, the REST response, and the realtime echo\n // ALL share one id — id-based upsert handles every race.\n const id = attrs.id ?? crypto.randomUUID();\n const tempMsg: Message = {\n id,\n tenant_id: '',\n conversation_id: conversationId,\n // Stamp the current user's id so the optimistic row renders\n // on the right (self) side from the moment it appears. Null\n // here would briefly flash the row on the \"other\" side until\n // the realtime echo replaced it with the canonical row.\n sender_id: meIdRef.current,\n type: attrs.type ?? 'text',\n body: attrs.body ?? null,\n reply_to_id: attrs.reply_to_id ?? null,\n thread_root_id: null,\n mentions: attrs.mentions ?? [],\n reactions: {},\n edited_at: null,\n deleted_at: null,\n // MAX_SAFE_INTEGER sorts the temp row to the very end (newest\n // position) until the server returns the real `sequence`.\n sequence: Number.MAX_SAFE_INTEGER,\n inserted_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, tempMsg]);\n\n try {\n const sent = await chat.conversations.one(conversationId).messages.send({ ...attrs, id });\n // Both REST and realtime carry the same id; whichever lands\n // first wins, and the second is an idempotent replace.\n setMessages((prev) => upsertById(prev, sent));\n return sent;\n } catch (err) {\n setMessages((prev) => prev.filter((m) => m.id !== id));\n throw err;\n }\n },\n [chat, conversationId],\n );\n\n const edit = useCallback(\n async (messageId: Uuid, body: string): Promise<Message> => {\n // Optimistic: capture the previous body so we can roll back if the\n // PATCH fails. `edited_at` is set to \"now\" client-side; the server\n // will overwrite with its authoritative timestamp on the realtime\n // echo + REST response.\n let previous: Message | undefined;\n setMessages((prev) =>\n prev.map((m) => {\n if (m.id !== messageId) return m;\n previous = m;\n return { ...m, body, edited_at: new Date().toISOString() };\n }),\n );\n\n try {\n const updated = await chat.messages.one(messageId).update({ body });\n // Replace with the canonical row (right edited_at, etc).\n setMessages((prev) => prev.map((m) => (m.id === messageId ? updated : m)));\n return updated;\n } catch (err) {\n if (previous) {\n const restore = previous;\n setMessages((prev) => prev.map((m) => (m.id === messageId ? restore : m)));\n }\n throw err;\n }\n },\n [chat],\n );\n\n const deleteMessage = useCallback(\n async (messageId: Uuid): Promise<void> => {\n // Optimistic tombstone — same shape the realtime delete handler\n // applies, so the UI is consistent regardless of which path\n // (REST response or WS push) lands first.\n let previous: Message | undefined;\n setMessages((prev) =>\n prev.map((m) => {\n if (m.id !== messageId) return m;\n previous = m;\n return { ...m, body: null, deleted_at: new Date().toISOString() };\n }),\n );\n\n try {\n await chat.messages.one(messageId).delete();\n } catch (err) {\n if (previous) {\n const restore = previous;\n setMessages((prev) => prev.map((m) => (m.id === messageId ? restore : m)));\n }\n throw err;\n }\n },\n [chat],\n );\n\n const markReadUpTo = useCallback(\n async (messageId: Uuid): Promise<void> => {\n // Fire-and-forget — server updates the caller's last_read_message_id\n // and broadcasts the resulting membership update to other clients\n // (which is what drives read-receipt glyphs in their UIs).\n await chat.conversations.one(conversationId).messages.markRead(messageId);\n },\n [chat, conversationId],\n );\n\n return {\n messages,\n loading,\n error,\n hasMore,\n loadMore,\n send,\n edit,\n delete: deleteMessage,\n markReadUpTo,\n };\n}\n\nfunction upsertById(prev: Message[], msg: Message): Message[] {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx === -1) return [...prev, msg];\n const next = prev.slice();\n next[idx] = msg;\n return next;\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\n/**\n * Map of emoji → list of user_ids who reacted with it. Matches the\n * shape of `Message.reactions` so initial seeding from a message you\n * already have in state is a direct assignment.\n */\nexport type ReactionMap = Record<string, Uuid[]>;\n\ninterface UseReactionsState {\n reactions: ReactionMap;\n /** Add the caller's reaction (idempotent server-side). */\n addReaction: (emoji: string) => Promise<void>;\n /** Remove the caller's reaction. No-op if not present. */\n removeReaction: (emoji: string) => Promise<void>;\n}\n\ninterface UseReactionsOptions {\n /**\n * Required for the in-channel subscription — the realtime layer\n * routes reaction events through the conversation channel, not a\n * per-message channel. Pass the conversation id you already know.\n */\n conversationId: Uuid;\n /**\n * Seed the local reaction map from a message you already have\n * (e.g. from `useMessages`). Without this the hook starts empty\n * and only sees deltas from the realtime stream.\n */\n initialReactions?: ReactionMap;\n /**\n * Current user's id. When provided, optimistic mutate updates the\n * local map immediately for that user; when omitted, we wait for\n * the server's `reaction:added` echo to update state.\n */\n currentUserId?: Uuid | null;\n}\n\n/**\n * Live reaction map for a single message. Subscribes to\n * `reaction:added` / `reaction:removed` realtime events filtered to\n * `messageId`, and provides mutation helpers.\n *\n * ```ts\n * const { reactions, addReaction } = useReactions(msg.id, {\n * conversationId: msg.conversation_id,\n * initialReactions: msg.reactions,\n * currentUserId: me?.id,\n * });\n * <button onClick={() => addReaction('🎉')}>🎉 {reactions['🎉']?.length ?? 0}</button>\n * ```\n */\nexport function useReactions(messageId: Uuid, opts: UseReactionsOptions): UseReactionsState {\n const chat = usePoolse();\n const [reactions, setReactions] = useState<ReactionMap>(opts.initialReactions ?? {});\n\n // Keep currentUserId in a ref so the realtime callbacks (set up in\n // the mount effect) always see the latest value without having to\n // re-subscribe when it changes.\n const currentUserIdRef = useRef<Uuid | null>(opts.currentUserId ?? null);\n currentUserIdRef.current = opts.currentUserId ?? null;\n\n // Shadow ref of the latest committed reactions map — used by\n // `removeReaction` for synchronous snapshot capture so the\n // optimistic rollback isn't racing the React updater queue.\n const reactionsRef = useRef<ReactionMap>(reactions);\n reactionsRef.current = reactions;\n\n useEffect(() => {\n const conv = chat.realtime.conversation(opts.conversationId);\n\n const offAdded = conv.onReactionAdded((evt) => {\n if (evt.message_id !== messageId) return;\n setReactions((prev) => addUser(prev, evt.emoji, evt.user_id));\n });\n\n const offRemoved = conv.onReactionRemoved((evt) => {\n if (evt.message_id !== messageId) return;\n setReactions((prev) => removeUser(prev, evt.emoji, evt.user_id));\n });\n\n return () => {\n offAdded();\n offRemoved();\n };\n }, [chat, opts.conversationId, messageId]);\n\n const addReaction = useCallback(\n async (emoji: string) => {\n const uid = currentUserIdRef.current;\n // Optimistic add when we know who we are; otherwise wait for echo.\n if (uid) setReactions((prev) => addUser(prev, emoji, uid));\n try {\n await chat.messages.one(messageId).addReaction(emoji);\n } catch (err) {\n if (uid) setReactions((prev) => removeUser(prev, emoji, uid));\n throw err;\n }\n },\n [chat, messageId],\n );\n\n const removeReaction = useCallback(\n async (emoji: string) => {\n const uid = currentUserIdRef.current;\n const snapshot = reactionsRef.current;\n if (uid) setReactions((prev) => removeUser(prev, emoji, uid));\n try {\n await chat.messages.one(messageId).removeReaction(emoji);\n } catch (err) {\n if (uid) setReactions(snapshot);\n throw err;\n }\n },\n [chat, messageId],\n );\n\n return { reactions, addReaction, removeReaction };\n}\n\nfunction addUser(prev: ReactionMap, emoji: string, userId: Uuid): ReactionMap {\n const existing = prev[emoji] ?? [];\n if (existing.includes(userId)) return prev;\n return { ...prev, [emoji]: [...existing, userId] };\n}\n\nfunction removeUser(prev: ReactionMap, emoji: string, userId: Uuid): ReactionMap {\n const existing = prev[emoji];\n if (!existing || !existing.includes(userId)) return prev;\n const next = existing.filter((id) => id !== userId);\n if (next.length === 0) {\n const { [emoji]: _, ...rest } = prev;\n return rest;\n }\n return { ...prev, [emoji]: next };\n}\n","import type { Message, MessageCreateRequest, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseThreadState {\n /** Replies, oldest-first (the wire returns oldest-first; we don't flip). */\n replies: Message[];\n loading: boolean;\n error: Error | null;\n /** More older-than-current-page replies available on the server. */\n hasMore: boolean;\n /** Load the next page after the current newest reply. Idempotent if no more. */\n loadMore: () => Promise<void>;\n /**\n * Send a reply into this thread. Fills `reply_to_id` with the root\n * message id automatically; pass `body` (and any other\n * `MessageCreateRequest` fields) as you would to `useMessages.send`.\n */\n sendReply: (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => Promise<Message>;\n /**\n * Edit a reply (or the root message). Optimistic with rollback —\n * mirrors `useMessages.edit`. Server enforces sender-only authz.\n */\n edit: (messageId: Uuid, body: string) => Promise<Message>;\n /**\n * Soft-delete a reply (or the root message). Optimistic tombstone\n * (`deleted_at` + null body) — mirrors `useMessages.delete`.\n */\n delete: (messageId: Uuid) => Promise<void>;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Thread view rooted at `rootMessageId`. Loads replies oldest-first\n * with cursor pagination (`after: sequence`), subscribes to the\n * conversation channel's `message:new` event filtered by\n * `thread_root_id === rootMessageId`, and provides a `sendReply`\n * that wires `reply_to_id` for you.\n *\n * Like `useMessages`, the optimistic send uses the same id the\n * server will assign (auto-generated by the SDK), so the realtime\n * echo just upserts in place — no double-render.\n */\nexport function useThread(conversationId: Uuid, rootMessageId: Uuid): UseThreadState {\n const chat = usePoolse();\n const [replies, setReplies] = useState<Message[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(true);\n\n // Cursor for `loadMore` — the highest sequence currently in state.\n const newestSequenceRef = useRef<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setReplies([]);\n setError(null);\n setHasMore(true);\n newestSequenceRef.current = null;\n\n chat.messages\n .one(rootMessageId)\n .replies({ limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled) return;\n setReplies(page.data);\n setHasMore(page.data.length === PAGE_SIZE);\n newestSequenceRef.current = page.data[page.data.length - 1]?.sequence ?? null;\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n // Realtime: filter conversation messages for thread membership.\n const conv = chat.realtime.conversation(conversationId);\n const offNew = conv.onMessage((msg) => {\n if (msg.thread_root_id !== rootMessageId) return;\n setReplies((prev) => upsertById(prev, msg));\n });\n const offUpdated = conv.onMessageUpdated((msg) => {\n if (msg.thread_root_id !== rootMessageId) return;\n setReplies((prev) => prev.map((m) => (m.id === msg.id ? msg : m)));\n });\n const offDeleted = conv.onMessageDeleted((evt) => {\n setReplies((prev) =>\n prev.map((m) => (m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m)),\n );\n });\n\n return () => {\n cancelled = true;\n offNew();\n offUpdated();\n offDeleted();\n };\n }, [chat, conversationId, rootMessageId]);\n\n const loadMore = useCallback(async () => {\n if (!hasMore || loading) return;\n const after = newestSequenceRef.current;\n if (after === null) return;\n const page = await chat.messages.one(rootMessageId).replies({ limit: PAGE_SIZE, after });\n if (page.data.length === 0) {\n setHasMore(false);\n return;\n }\n setReplies((prev) => [...prev, ...page.data]);\n setHasMore(page.data.length === PAGE_SIZE);\n newestSequenceRef.current = page.data[page.data.length - 1]?.sequence ?? after;\n }, [chat, rootMessageId, hasMore, loading]);\n\n const sendReply = useCallback(\n async (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => {\n const id = attrs.id ?? crypto.randomUUID();\n const tempMsg: Message = {\n id,\n tenant_id: '',\n conversation_id: conversationId,\n sender_id: null,\n type: attrs.type ?? 'text',\n body: attrs.body ?? null,\n reply_to_id: rootMessageId,\n thread_root_id: rootMessageId,\n mentions: attrs.mentions ?? [],\n reactions: {},\n edited_at: null,\n deleted_at: null,\n sequence: Number.MAX_SAFE_INTEGER,\n inserted_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n };\n setReplies((prev) => [...prev, tempMsg]);\n\n try {\n const sent = await chat.conversations.one(conversationId).messages.send({\n ...attrs,\n id,\n reply_to_id: rootMessageId,\n });\n setReplies((prev) => upsertById(prev, sent));\n return sent;\n } catch (err) {\n setReplies((prev) => prev.filter((m) => m.id !== id));\n throw err;\n }\n },\n [chat, conversationId, rootMessageId],\n );\n\n const edit = useCallback(\n async (messageId: Uuid, body: string): Promise<Message> => {\n let previous: Message | undefined;\n setReplies((prev) =>\n prev.map((m) => {\n if (m.id !== messageId) return m;\n previous = m;\n return { ...m, body, edited_at: new Date().toISOString() };\n }),\n );\n\n try {\n const updated = await chat.messages.one(messageId).update({ body });\n setReplies((prev) => prev.map((m) => (m.id === messageId ? updated : m)));\n return updated;\n } catch (err) {\n if (previous) {\n const restore = previous;\n setReplies((prev) => prev.map((m) => (m.id === messageId ? restore : m)));\n }\n throw err;\n }\n },\n [chat],\n );\n\n const deleteReply = useCallback(\n async (messageId: Uuid): Promise<void> => {\n let previous: Message | undefined;\n setReplies((prev) =>\n prev.map((m) => {\n if (m.id !== messageId) return m;\n previous = m;\n return { ...m, body: null, deleted_at: new Date().toISOString() };\n }),\n );\n\n try {\n await chat.messages.one(messageId).delete();\n } catch (err) {\n if (previous) {\n const restore = previous;\n setReplies((prev) => prev.map((m) => (m.id === messageId ? restore : m)));\n }\n throw err;\n }\n },\n [chat],\n );\n\n return {\n replies,\n loading,\n error,\n hasMore,\n loadMore,\n sendReply,\n edit,\n delete: deleteReply,\n };\n}\n\nfunction upsertById(prev: Message[], msg: Message): Message[] {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx === -1) return [...prev, msg];\n const next = prev.slice();\n next[idx] = msg;\n return next;\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseTypingState {\n /** Set of user_ids currently typing. */\n typing: Set<Uuid>;\n /**\n * Send a typing ping to the server. Debounced inside the SDK — the\n * server squashes `typing:start` to one push per (user, conversation,\n * window). Call as often as you want from input handlers.\n */\n signalTyping: () => void;\n}\n\n/**\n * Tracks who's typing in `conversationId`. Subscribes to the\n * `typing:start` / `typing:stop` broadcasts; auto-cleans up entries\n * when stop fires.\n *\n * `signalTyping` debounces on the client side to once per 500 ms so a\n * fast-typing user doesn't flood the channel — poolse does its own\n * server-side debounce too, so both layers are safe.\n */\nexport function useTyping(conversationId: string): UseTypingState {\n const chat = usePoolse();\n const { me } = useMe();\n const [typing, setTyping] = useState<Set<Uuid>>(new Set());\n const lastPingRef = useRef(0);\n\n // `me` resolves asynchronously after first render; read it from a\n // ref inside the event handlers so the subscription doesn't need to\n // re-attach when `me` lands (which would briefly drop incoming\n // typing events from other users).\n const meIdRef = useRef<Uuid | null>(me?.id ?? null);\n meIdRef.current = me?.id ?? null;\n\n useEffect(() => {\n setTyping(new Set());\n\n const conv = chat.realtime.conversation(conversationId);\n\n const offStart = conv.onTypingStart((evt) => {\n // Don't render the current user's own typing — they know they're typing.\n if (meIdRef.current && evt.user_id === meIdRef.current) return;\n setTyping((prev) => {\n if (prev.has(evt.user_id)) return prev;\n const next = new Set(prev);\n next.add(evt.user_id);\n return next;\n });\n });\n\n const offStop = conv.onTypingStop((evt) => {\n if (meIdRef.current && evt.user_id === meIdRef.current) return;\n setTyping((prev) => {\n if (!prev.has(evt.user_id)) return prev;\n const next = new Set(prev);\n next.delete(evt.user_id);\n return next;\n });\n });\n\n return () => {\n offStart();\n offStop();\n };\n }, [chat, conversationId]);\n\n const signalTyping = useCallback(() => {\n const now = Date.now();\n if (now - lastPingRef.current < 500) return;\n lastPingRef.current = now;\n chat.realtime.conversation(conversationId).sendTyping();\n }, [chat, conversationId]);\n\n return { typing, signalTyping };\n}\n","import type { PresenceSnapshot, Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UsePresenceState {\n /** Set of user_ids currently online in this conversation. */\n online: Set<Uuid>;\n}\n\n/**\n * Who's currently joined to `conversationId`'s channel. Backed by\n * Phoenix.Presence broadcasts (`presence_state` snapshot on join,\n * `presence_diff` on changes).\n */\nexport function usePresence(conversationId: string): UsePresenceState {\n const chat = usePoolse();\n const [online, setOnline] = useState<Set<Uuid>>(new Set());\n\n useEffect(() => {\n setOnline(new Set());\n\n const conv = chat.realtime.conversation(conversationId);\n\n const applyState = (state: PresenceSnapshot) => {\n setOnline(new Set(Object.keys(state)));\n };\n\n const applyDiff = (diff: { joins?: PresenceSnapshot; leaves?: PresenceSnapshot }) => {\n setOnline((prev) => {\n const next = new Set(prev);\n if (diff.joins) Object.keys(diff.joins).forEach((id) => next.add(id));\n if (diff.leaves) Object.keys(diff.leaves).forEach((id) => next.delete(id));\n return next;\n });\n };\n\n const offState = conv.onPresenceState(applyState);\n const offDiff = conv.onPresenceDiff(applyDiff as (s: PresenceSnapshot) => void);\n\n return () => {\n offState();\n offDiff();\n };\n }, [chat, conversationId]);\n\n return { online };\n}\n","import type { RealtimeStatus } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\n/**\n * Connection status of the underlying WebSocket. Useful for showing a\n * \"reconnecting…\" banner without coupling to socket internals.\n *\n * Returns one of: `'idle' | 'connecting' | 'connected' | 'reconnecting' | 'closed'`.\n */\nexport function useRealtimeStatus(): RealtimeStatus {\n const chat = usePoolse();\n const [status, setStatus] = useState<RealtimeStatus>(chat.realtime.getStatus());\n\n useEffect(() => {\n setStatus(chat.realtime.getStatus());\n return chat.realtime.onStatus(setStatus);\n }, [chat]);\n\n return status;\n}\n","import type { Attachment, AttachmentUploadInput } from '@poolse/sdk';\nimport { useCallback, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseAttachmentUploadState {\n /** Last successfully uploaded attachment, or null. */\n attachment: Attachment | null;\n uploading: boolean;\n error: Error | null;\n /**\n * Run the upload pipeline (presigned-URL request + PUT). Updates\n * local state with the resolved attachment on success; sets `error`\n * and rethrows on failure so callers can surface a toast.\n */\n upload: (input: AttachmentUploadInput) => Promise<Attachment>;\n /** Reset state (clears `attachment`, `error`). */\n reset: () => void;\n}\n\n/**\n * Stateful wrapper around `chat.attachments.upload`. Provides\n * `uploading` + `error` flags for the common \"show a spinner while\n * the PUT is in flight\" UI, plus retention of the last attachment\n * so the caller can reference its id when sending a message.\n *\n * ```tsx\n * const { upload, uploading, attachment } = useAttachmentUpload();\n * const onPick = async (file: File) => {\n * const att = await upload({\n * body: file, contentType: file.type, byteSize: file.size, filename: file.name\n * });\n * await chat.conversations.one(convId).messages.send({\n * body: 'attached',\n * custom_data: { attachment_id: att.id },\n * });\n * };\n * ```\n */\nexport function useAttachmentUpload(): UseAttachmentUploadState {\n const chat = usePoolse();\n const [attachment, setAttachment] = useState<Attachment | null>(null);\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n // Track an in-flight upload's AbortController so unmount cancels it.\n const inFlightRef = useRef<AbortController | null>(null);\n\n const upload = useCallback(\n async (input: AttachmentUploadInput): Promise<Attachment> => {\n // Cancel any prior in-flight upload — last-write-wins on intent.\n inFlightRef.current?.abort();\n const controller = new AbortController();\n inFlightRef.current = controller;\n\n setUploading(true);\n setError(null);\n try {\n const att = await chat.attachments.upload(input, { signal: controller.signal });\n if (inFlightRef.current === controller) {\n setAttachment(att);\n }\n return att;\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n if (inFlightRef.current === controller) {\n setUploading(false);\n inFlightRef.current = null;\n }\n }\n },\n [chat],\n );\n\n const reset = useCallback(() => {\n inFlightRef.current?.abort();\n inFlightRef.current = null;\n setAttachment(null);\n setError(null);\n setUploading(false);\n }, []);\n\n return { attachment, uploading, error, upload, reset };\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseAttachmentUrlState {\n /** Presigned GET URL, or null while loading / on error. */\n url: string | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Resolve an attachment's presigned download URL. Pass `null` to\n * skip the fetch — useful in routing-driven views where the id may\n * not be known yet.\n *\n * Doesn't auto-refresh: the server's URL TTL is ~1 hour and most\n * UI lifetimes are much shorter. If you do need a refresh (long-lived\n * dashboard, etc.), remount the hook or wrap it in a parent that\n * re-keys on a timer.\n *\n * ```tsx\n * const { url } = useAttachmentUrl(message.custom_data?.attachment_id ?? null);\n * return url ? <img src={url} /> : <Spinner />;\n * ```\n */\nexport function useAttachmentUrl(attachmentId: Uuid | null): UseAttachmentUrlState {\n const chat = usePoolse();\n const [url, setUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(attachmentId !== null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (attachmentId === null) {\n setUrl(null);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n const controller = new AbortController();\n setLoading(true);\n setError(null);\n chat.attachments\n .one(attachmentId)\n .downloadUrl({ signal: controller.signal })\n .then((res) => {\n if (cancelled) return;\n setUrl(res.url);\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [chat, attachmentId]);\n\n return { url, loading, error };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -88,6 +88,20 @@ interface UseConversationsState {
88
88
  error: Error | null;
89
89
  refetch: () => Promise<void>;
90
90
  create: (attrs: ConversationCreateRequest) => Promise<Conversation>;
91
+ /**
92
+ * Per-conversation unread count, keyed by conversation id. Sourced
93
+ * from `Conversation.unread_count` on the initial fetch and kept
94
+ * fresh as the caller marks conversations read (via `markRead`).
95
+ *
96
+ * Note: cross-conversation incrementing on a new inbound message
97
+ * requires subscribing to every conversation channel, which the SDK
98
+ * doesn't do by default. Counts in this map are accurate for the
99
+ * conversation the caller has open + correct at fetch time for the
100
+ * rest; refetch on a fresh tab focus for true reconciliation.
101
+ */
102
+ unreadCounts: Record<Uuid, number>;
103
+ /** Force a conversation's unread to 0 — invoked by `markReadUpTo`. */
104
+ markConversationRead: (conversationId: Uuid) => void;
91
105
  }
92
106
  /**
93
107
  * List of conversations the current End User can see.
@@ -125,11 +139,13 @@ interface UseMembersState {
125
139
  }
126
140
  /**
127
141
  * Live-ish membership list for a conversation. Initial REST fetch on
128
- * mount; mutation helpers update local state in place. No realtime
129
- * sync yet — the backend doesn't broadcast `member:joined` /
130
- * `member:left` events. For now, callers who depend on
131
- * cross-client member updates should poll with `refetch()` or
132
- * remount the hook.
142
+ * mount; mutation helpers update local state in place.
143
+ *
144
+ * Realtime: subscribes to `member:read` on the conversation channel
145
+ * and advances the matching membership's `last_read_message_id` /
146
+ * `last_read_at` so the sender's read-receipt glyph flips from "sent"
147
+ * to "read" without a refetch. `member:joined` / `member:left` aren't
148
+ * broadcast yet — for cross-client adds/removes, call `refetch()`.
133
149
  */
134
150
  declare function useMembers(conversationId: Uuid): UseMembersState;
135
151
 
@@ -143,6 +159,26 @@ interface UseMessagesState {
143
159
  loadMore: () => Promise<void>;
144
160
  /** Optimistically append + POST. Replaces the optimistic row with the server response on success. */
145
161
  send: (attrs: MessageCreateRequest) => Promise<Message>;
162
+ /**
163
+ * Edit a message you previously sent. Optimistically updates the
164
+ * local row, rolls back on server error. Server enforces
165
+ * sender-only authorization — calling this for a message you didn't
166
+ * send will throw an ApiError.
167
+ */
168
+ edit: (messageId: Uuid, body: string) => Promise<Message>;
169
+ /**
170
+ * Soft-delete a message you sent (or that you have admin authority
171
+ * over). Optimistically applies the tombstone (`deleted_at` + null
172
+ * body) locally, rolls back on error.
173
+ */
174
+ delete: (messageId: Uuid) => Promise<void>;
175
+ /**
176
+ * Advance the caller's read cursor to `messageId`. Server emits
177
+ * read-receipt updates to other members; the conversation's
178
+ * unread count drops to zero. No local state mutation — this is
179
+ * "tell the server we read up to here".
180
+ */
181
+ markReadUpTo: (messageId: Uuid) => Promise<void>;
146
182
  }
147
183
  /**
148
184
  * Live message list for `conversationId`. Combines:
@@ -225,6 +261,16 @@ interface UseThreadState {
225
261
  * `MessageCreateRequest` fields) as you would to `useMessages.send`.
226
262
  */
227
263
  sendReply: (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => Promise<Message>;
264
+ /**
265
+ * Edit a reply (or the root message). Optimistic with rollback —
266
+ * mirrors `useMessages.edit`. Server enforces sender-only authz.
267
+ */
268
+ edit: (messageId: Uuid, body: string) => Promise<Message>;
269
+ /**
270
+ * Soft-delete a reply (or the root message). Optimistic tombstone
271
+ * (`deleted_at` + null body) — mirrors `useMessages.delete`.
272
+ */
273
+ delete: (messageId: Uuid) => Promise<void>;
228
274
  }
229
275
  /**
230
276
  * Thread view rooted at `rootMessageId`. Loads replies oldest-first
package/dist/index.d.ts CHANGED
@@ -88,6 +88,20 @@ interface UseConversationsState {
88
88
  error: Error | null;
89
89
  refetch: () => Promise<void>;
90
90
  create: (attrs: ConversationCreateRequest) => Promise<Conversation>;
91
+ /**
92
+ * Per-conversation unread count, keyed by conversation id. Sourced
93
+ * from `Conversation.unread_count` on the initial fetch and kept
94
+ * fresh as the caller marks conversations read (via `markRead`).
95
+ *
96
+ * Note: cross-conversation incrementing on a new inbound message
97
+ * requires subscribing to every conversation channel, which the SDK
98
+ * doesn't do by default. Counts in this map are accurate for the
99
+ * conversation the caller has open + correct at fetch time for the
100
+ * rest; refetch on a fresh tab focus for true reconciliation.
101
+ */
102
+ unreadCounts: Record<Uuid, number>;
103
+ /** Force a conversation's unread to 0 — invoked by `markReadUpTo`. */
104
+ markConversationRead: (conversationId: Uuid) => void;
91
105
  }
92
106
  /**
93
107
  * List of conversations the current End User can see.
@@ -125,11 +139,13 @@ interface UseMembersState {
125
139
  }
126
140
  /**
127
141
  * Live-ish membership list for a conversation. Initial REST fetch on
128
- * mount; mutation helpers update local state in place. No realtime
129
- * sync yet — the backend doesn't broadcast `member:joined` /
130
- * `member:left` events. For now, callers who depend on
131
- * cross-client member updates should poll with `refetch()` or
132
- * remount the hook.
142
+ * mount; mutation helpers update local state in place.
143
+ *
144
+ * Realtime: subscribes to `member:read` on the conversation channel
145
+ * and advances the matching membership's `last_read_message_id` /
146
+ * `last_read_at` so the sender's read-receipt glyph flips from "sent"
147
+ * to "read" without a refetch. `member:joined` / `member:left` aren't
148
+ * broadcast yet — for cross-client adds/removes, call `refetch()`.
133
149
  */
134
150
  declare function useMembers(conversationId: Uuid): UseMembersState;
135
151
 
@@ -143,6 +159,26 @@ interface UseMessagesState {
143
159
  loadMore: () => Promise<void>;
144
160
  /** Optimistically append + POST. Replaces the optimistic row with the server response on success. */
145
161
  send: (attrs: MessageCreateRequest) => Promise<Message>;
162
+ /**
163
+ * Edit a message you previously sent. Optimistically updates the
164
+ * local row, rolls back on server error. Server enforces
165
+ * sender-only authorization — calling this for a message you didn't
166
+ * send will throw an ApiError.
167
+ */
168
+ edit: (messageId: Uuid, body: string) => Promise<Message>;
169
+ /**
170
+ * Soft-delete a message you sent (or that you have admin authority
171
+ * over). Optimistically applies the tombstone (`deleted_at` + null
172
+ * body) locally, rolls back on error.
173
+ */
174
+ delete: (messageId: Uuid) => Promise<void>;
175
+ /**
176
+ * Advance the caller's read cursor to `messageId`. Server emits
177
+ * read-receipt updates to other members; the conversation's
178
+ * unread count drops to zero. No local state mutation — this is
179
+ * "tell the server we read up to here".
180
+ */
181
+ markReadUpTo: (messageId: Uuid) => Promise<void>;
146
182
  }
147
183
  /**
148
184
  * Live message list for `conversationId`. Combines:
@@ -225,6 +261,16 @@ interface UseThreadState {
225
261
  * `MessageCreateRequest` fields) as you would to `useMessages.send`.
226
262
  */
227
263
  sendReply: (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => Promise<Message>;
264
+ /**
265
+ * Edit a reply (or the root message). Optimistic with rollback —
266
+ * mirrors `useMessages.edit`. Server enforces sender-only authz.
267
+ */
268
+ edit: (messageId: Uuid, body: string) => Promise<Message>;
269
+ /**
270
+ * Soft-delete a reply (or the root message). Optimistic tombstone
271
+ * (`deleted_at` + null body) — mirrors `useMessages.delete`.
272
+ */
273
+ delete: (messageId: Uuid) => Promise<void>;
228
274
  }
229
275
  /**
230
276
  * Thread view rooted at `rootMessageId`. Loads replies oldest-first