@poolse/react 1.0.6 → 2.0.0

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.
package/dist/index.js.map CHANGED
@@ -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","../src/use-user.ts"],"names":["useEffect","useState","useCallback","useMemo","useRef","PAGE_SIZE","upsertById"],"mappings":"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","file":"index.js","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 // Customer's user metadata resolver — name + avatar lookup.\n // Read through the ref so the customer can swap the closure\n // (e.g. switch tenant context) without re-mounting.\n ...(initial.userResolver\n ? { userResolver: (id: string) => configRef.current.userResolver!(id) }\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, MemberReadEvent, 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 // Buffer for `member:read` events that arrive BEFORE the initial\n // fetch lands. The realtime subscription runs almost immediately on\n // mount; the HTTP fetch takes a roundtrip. If another user reads in\n // that window, the broadcast fires while local state is still empty\n // and the `prev.map` no-ops — leaving the read invisible forever.\n // We buffer here and replay inside the fetcher after `setMembers`\n // commits the snapshot.\n const pendingReadsRef = useRef<MemberReadEvent[]>([]);\n const hasFetchedRef = useRef(false);\n\n const applyRead = (list: Membership[], evt: MemberReadEvent): Membership[] =>\n list.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 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 // Drain any buffered `member:read` events that fired before the\n // fetch landed. Without this, reads that arrive in the\n // subscribe→response gap would be lost.\n let next = data;\n if (pendingReadsRef.current.length > 0) {\n for (const evt of pendingReadsRef.current) next = applyRead(next, evt);\n pendingReadsRef.current = [];\n }\n setMembers(next);\n hasFetchedRef.current = true;\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 // Reset per-conversation state so a swap of `conversationId`\n // doesn't carry stale buffered reads from a previous channel.\n hasFetchedRef.current = false;\n pendingReadsRef.current = [];\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 // Buffer if the initial fetch hasn't landed — the fetcher's\n // try-block drains the buffer once it has membership rows to\n // apply the read to. See the matching ref pair above.\n if (!hasFetchedRef.current) {\n pendingReadsRef.current.push(evt);\n return;\n }\n setMembers((prev) => applyRead(prev, evt));\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 // Thread replies don't live in the main feed — they belong to\n // the side-pane that `useThread` populates. So when a reply\n // arrives over realtime, route it to the root's reply_count\n // ONLY, and skip the main-list upsert. The server now mirrors\n // this rule on the REST list (`WHERE thread_root_id IS NULL`),\n // so post-refresh state matches realtime behavior.\n if (msg.thread_root_id) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === msg.thread_root_id ? { ...m, reply_count: (m.reply_count ?? 0) + 1 } : m,\n ),\n );\n return;\n }\n // Top-level message: standard by-id upsert. Covers three cases:\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 // Capture the pre-delete row so we can find the thread root if\n // this message was a reply — the delete payload doesn't carry\n // `thread_root_id`, so we have to look it up locally.\n const target = prev.find((m) => m.id === evt.id);\n const updated = prev.map((m) =>\n m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m,\n );\n if (target?.thread_root_id) {\n return updated.map((m) =>\n m.id === target.thread_root_id\n ? { ...m, reply_count: Math.max(0, (m.reply_count ?? 0) - 1) }\n : m,\n );\n }\n return updated;\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 // Optimistic quote: keep the id locally so the bubble can flag\n // itself as a quote-reply immediately. `quoted_message` (the\n // preview card body/sender) only lands when the server echo\n // arrives — the UI can render a placeholder (\"Quoted message\")\n // in the gap or wait silently; current bubble does the latter.\n quoted_message_id: attrs.quoted_message_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\n// Threads load top-down all-at-once: most discussions stay well under\n// 500 replies, the side-pane has no infinite-scroll affordance, and\n// avoiding pagination keeps the UX simple. `loadMore` remains as an\n// escape hatch in case a thread does exceed this on the rare day.\nconst PAGE_SIZE = 500;\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 // Empty id = \"do nothing\" — same convention as `useMembers` /\n // `useMessages`. Lets callers conditionally enable presence\n // tracking without re-mounting the hook.\n if (!conversationId) return;\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, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\nexport type UploadItemStatus = 'pending' | 'uploading' | 'ready' | 'error' | 'cancelled';\n\nexport interface UploadItem {\n /** Local-only id (random per-enqueue). Stable for keys + `cancel(localId)` / `remove(localId)`. */\n localId: string;\n filename: string;\n contentType: string;\n byteSize: number;\n status: UploadItemStatus;\n /** Bytes uploaded so far; 0 until the PUT actually begins. */\n loaded: number;\n /** Resolved attachment row once `status === 'ready'`. Null otherwise. */\n attachment: Attachment | null;\n /** Set when `status === 'error'`. */\n error: Error | null;\n}\n\ninterface UseAttachmentUploadState {\n /** Every enqueued item, in enqueue order, until removed by `remove()` / `reset()`. */\n queue: UploadItem[];\n /**\n * Last attachment that reached `ready`, for the common one-file\n * \"did the upload finish\" check. Null after `reset()` / `remove()`\n * of the most recent ready item. Multi-file callers should iterate\n * `queue` instead.\n */\n attachment: Attachment | null;\n /** True while at least one item is `pending` or `uploading`. */\n uploading: boolean;\n /** Most recent item-level error, or null. */\n error: Error | null;\n /**\n * Enqueue a single upload. Resolves with the final attachment row.\n * Rejects with the underlying error (item's `status` becomes\n * `'error'`); aborts surface as a DOMException('AbortError') and the\n * item's status becomes `'cancelled'`.\n */\n upload: (input: AttachmentUploadInput) => Promise<Attachment>;\n /**\n * Enqueue many at once — drag-and-drop, multi-file picker. Items run\n * in parallel (the SDK is per-call independent). Resolves with the\n * attachments in the same order as the input; if any item fails the\n * whole promise rejects after the others settle.\n */\n uploadAll: (inputs: AttachmentUploadInput[]) => Promise<Attachment[]>;\n /** Abort an in-flight upload. Sets the item's status to `cancelled`. No-op if not in flight. */\n cancel: (localId: string) => void;\n /** Drop an item from the queue. Cancels first if it's still in flight. */\n remove: (localId: string) => void;\n /** Drop everything + abort any in-flight uploads. */\n reset: () => void;\n}\n\ninterface InFlight {\n controller: AbortController;\n}\n\n/**\n * Stateful wrapper around `chat.attachments.upload`. Exposes a queue\n * of in-flight / completed uploads with per-item progress + per-item\n * cancel — drag-and-drop, multi-file picker, retry chips, all without\n * the host app reimplementing AbortController plumbing.\n *\n * ```tsx\n * const { upload, queue, cancel, remove } = useAttachmentUpload();\n * const onPick = async (files: File[]) => {\n * const atts = await uploadAll(files.map(f => ({\n * body: f, contentType: f.type, byteSize: f.size, filename: f.name\n * })));\n * await chat.conversations.one(convId).messages.send({\n * body: '', attachment_ids: atts.map(a => a.id),\n * });\n * };\n * ```\n *\n * The legacy `upload(input)` → `Promise<Attachment>` shape is preserved\n * so older callers keep working — they just won't render the queue UI.\n */\nexport function useAttachmentUpload(): UseAttachmentUploadState {\n const chat = usePoolse();\n const [queue, setQueue] = useState<UploadItem[]>([]);\n const inFlightRef = useRef<Map<string, InFlight>>(new Map());\n // Track mount status so async resolves don't setState on unmounted\n // components. Strict-mode double-effects re-arm this on remount.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n for (const v of inFlightRef.current.values()) v.controller.abort();\n inFlightRef.current.clear();\n };\n }, []);\n\n const updateItem = useCallback((localId: string, patch: Partial<UploadItem>) => {\n if (!mountedRef.current) return;\n setQueue((q) => q.map((it) => (it.localId === localId ? { ...it, ...patch } : it)));\n }, []);\n\n const runUpload = useCallback(\n async (localId: string, input: AttachmentUploadInput): Promise<Attachment> => {\n const controller = new AbortController();\n inFlightRef.current.set(localId, { controller });\n updateItem(localId, { status: 'uploading', loaded: 0 });\n try {\n const att = await chat.attachments.upload(input, {\n signal: controller.signal,\n onProgress: (e) => updateItem(localId, { loaded: e.loaded }),\n });\n updateItem(localId, {\n status: 'ready',\n loaded: input.byteSize,\n attachment: att,\n error: null,\n });\n return att;\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') {\n updateItem(localId, { status: 'cancelled' });\n throw err;\n }\n const e = err instanceof Error ? err : new Error(String(err));\n updateItem(localId, { status: 'error', error: e });\n throw e;\n } finally {\n inFlightRef.current.delete(localId);\n }\n },\n [chat, updateItem],\n );\n\n const enqueue = useCallback((input: AttachmentUploadInput): UploadItem => {\n const localId = generateLocalId();\n const item: UploadItem = {\n localId,\n filename: input.filename ?? 'file',\n contentType: input.contentType,\n byteSize: input.byteSize,\n status: 'pending',\n loaded: 0,\n attachment: null,\n error: null,\n };\n setQueue((q) => [...q, item]);\n return item;\n }, []);\n\n const upload = useCallback(\n (input: AttachmentUploadInput): Promise<Attachment> => {\n const item = enqueue(input);\n return runUpload(item.localId, input);\n },\n [enqueue, runUpload],\n );\n\n const uploadAll = useCallback(\n (inputs: AttachmentUploadInput[]): Promise<Attachment[]> => {\n // Enqueue all first so the UI shows the full queue immediately,\n // then start the PUTs in parallel. Order in resolved array\n // matches input order regardless of which PUT finishes first.\n const items = inputs.map((inp) => ({ item: enqueue(inp), input: inp }));\n return Promise.all(items.map(({ item, input }) => runUpload(item.localId, input)));\n },\n [enqueue, runUpload],\n );\n\n const cancel = useCallback((localId: string) => {\n const inf = inFlightRef.current.get(localId);\n if (inf) inf.controller.abort();\n }, []);\n\n const remove = useCallback(\n (localId: string) => {\n const inf = inFlightRef.current.get(localId);\n if (inf) inf.controller.abort();\n setQueue((q) => q.filter((it) => it.localId !== localId));\n },\n [],\n );\n\n const reset = useCallback(() => {\n for (const v of inFlightRef.current.values()) v.controller.abort();\n inFlightRef.current.clear();\n setQueue([]);\n }, []);\n\n const uploading = queue.some((it) => it.status === 'pending' || it.status === 'uploading');\n // Last error in queue order — pendings/readies have null, so the\n // most recently transitioned-to-error item wins.\n const error = queue.reduce<Error | null>((acc, it) => it.error ?? acc, null);\n // Last ready attachment — same convenience.\n const attachment = queue.reduce<Attachment | null>((acc, it) => it.attachment ?? acc, null);\n\n return { queue, attachment, uploading, error, upload, uploadAll, cancel, remove, reset };\n}\n\nfunction generateLocalId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c && typeof c.randomUUID === 'function') return c.randomUUID();\n // Fallback for older runtimes (tests on Node 18 without crypto, etc).\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\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","// React binding over `chat.users.get(userId)`.\n//\n// Uses plain useState + useEffect (NOT `useSyncExternalStore`).\n// useSyncExternalStore reaches into React internals and surfaces\n// any latent React-duplication immediately as \"Invalid hook call\".\n// The pattern below works the same way for our purposes — read\n// from the cache on mount, subscribe for updates, update state —\n// without that fragility.\n\nimport type { PoolseUserProfile, Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\nexport interface UseUserState {\n /** Resolved profile, or null when the resolver returned null / errored / isn't configured. */\n profile: PoolseUserProfile | null;\n /** True while the SDK is mid-fetch (or before the first fetch fires). */\n loading: boolean;\n}\n\nconst EMPTY: UseUserState = { profile: null, loading: false };\n\n/**\n * Resolve a poolse user_id to the customer's display name + avatar\n * URL via the configured `userResolver`. Returns `{ profile: null,\n * loading: false }` when:\n * * no resolver is configured (customer hasn't wired one up)\n * * resolver returned null (user not found)\n * * resolver threw (logged once, then cached as null)\n *\n * Pass `null` / empty string to opt out (the hook becomes a no-op).\n * Useful for self bubbles (you already know who you are).\n */\nexport function useUser(userId: Uuid | null | undefined): UseUserState {\n const chat = usePoolse();\n const [state, setState] = useState<UseUserState>(() => {\n if (!userId) return EMPTY;\n const cached = chat.users.peek(userId);\n if (cached === undefined) return { profile: null, loading: true };\n return { profile: cached, loading: false };\n });\n\n useEffect(() => {\n if (!userId) {\n setState(EMPTY);\n return;\n }\n\n const apply = () => {\n const cached = chat.users.peek(userId);\n if (cached === undefined) {\n // Cache miss — either initial load or post-invalidate. Flip\n // to loading + kick off a refetch.\n setState({ profile: null, loading: true });\n void chat.users.get(userId);\n } else {\n setState({ profile: cached, loading: false });\n }\n };\n\n // Subscribe BEFORE triggering the fetch so we never miss the\n // notify if the resolver lands synchronously.\n const off = chat.users.subscribe(userId, apply);\n // Initial pull — also covers the case where the cache already\n // had the entry (subscribe doesn't fire for existing values).\n apply();\n return off;\n }, [chat, userId]);\n\n return state;\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","../src/use-user.ts"],"names":["useEffect","useState","useCallback","useMemo","useRef","PAGE_SIZE","upsertById"],"mappings":"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","file":"index.js","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 // Customer's user metadata resolver — name + avatar lookup.\n // Read through the ref so the customer can swap the closure\n // (e.g. switch tenant context) without re-mounting.\n ...(initial.userResolver\n ? { userResolver: (id: string) => configRef.current.userResolver!(id) }\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, MemberReadEvent, 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`. Unknown ids are\n * auto-provisioned on the server. Returned memberships are\n * appended to local state on success.\n */\n addMembers: (externalIds: string[], opts?: { role?: MemberRole }) => Promise<Membership[]>;\n /**\n * Remove a member by `external_id`. The SDK translates to the\n * internal user_id under the hood. Optimistically removes from\n * state; rolls back on server error.\n */\n removeMember: (externalId: string) => 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 // Buffer for `member:read` events that arrive BEFORE the initial\n // fetch lands. The realtime subscription runs almost immediately on\n // mount; the HTTP fetch takes a roundtrip. If another user reads in\n // that window, the broadcast fires while local state is still empty\n // and the `prev.map` no-ops — leaving the read invisible forever.\n // We buffer here and replay inside the fetcher after `setMembers`\n // commits the snapshot.\n const pendingReadsRef = useRef<MemberReadEvent[]>([]);\n const hasFetchedRef = useRef(false);\n\n const applyRead = (list: Membership[], evt: MemberReadEvent): Membership[] =>\n list.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 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 // Drain any buffered `member:read` events that fired before the\n // fetch landed. Without this, reads that arrive in the\n // subscribe→response gap would be lost.\n let next = data;\n if (pendingReadsRef.current.length > 0) {\n for (const evt of pendingReadsRef.current) next = applyRead(next, evt);\n pendingReadsRef.current = [];\n }\n setMembers(next);\n hasFetchedRef.current = true;\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 // Reset per-conversation state so a swap of `conversationId`\n // doesn't carry stale buffered reads from a previous channel.\n hasFetchedRef.current = false;\n pendingReadsRef.current = [];\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 // Buffer if the initial fetch hasn't landed — the fetcher's\n // try-block drains the buffer once it has membership rows to\n // apply the read to. See the matching ref pair above.\n if (!hasFetchedRef.current) {\n pendingReadsRef.current.push(evt);\n return;\n }\n setMembers((prev) => applyRead(prev, evt));\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 (externalId: string) => {\n const snapshot = membersRef.current;\n // Translate external_id → internal user_id via the loaded member\n // list. The DELETE endpoint takes user_id in the path, but the\n // consumer never has to know that.\n const target = snapshot.find((m) => m.external_id === externalId);\n if (!target) return; // not a member; idempotent no-op\n\n const targetUserId: Uuid = target.user_id;\n setMembers((prev) => prev.filter((m) => m.external_id !== externalId));\n try {\n await chat.conversations.one(conversationId).removeMember(targetUserId);\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 const meExternalIdRef = useRef<string | null>(me?.external_id ?? null);\n meExternalIdRef.current = me?.external_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 // Thread replies don't live in the main feed — they belong to\n // the side-pane that `useThread` populates. So when a reply\n // arrives over realtime, route it to the root's reply_count\n // ONLY, and skip the main-list upsert. The server now mirrors\n // this rule on the REST list (`WHERE thread_root_id IS NULL`),\n // so post-refresh state matches realtime behavior.\n if (msg.thread_root_id) {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === msg.thread_root_id ? { ...m, reply_count: (m.reply_count ?? 0) + 1 } : m,\n ),\n );\n return;\n }\n // Top-level message: standard by-id upsert. Covers three cases:\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 // Capture the pre-delete row so we can find the thread root if\n // this message was a reply — the delete payload doesn't carry\n // `thread_root_id`, so we have to look it up locally.\n const target = prev.find((m) => m.id === evt.id);\n const updated = prev.map((m) =>\n m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m,\n );\n if (target?.thread_root_id) {\n return updated.map((m) =>\n m.id === target.thread_root_id\n ? { ...m, reply_count: Math.max(0, (m.reply_count ?? 0) - 1) }\n : m,\n );\n }\n return updated;\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 sender_external_id: meExternalIdRef.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 // Optimistic quote: keep the id locally so the bubble can flag\n // itself as a quote-reply immediately. `quoted_message` (the\n // preview card body/sender) only lands when the server echo\n // arrives — the UI can render a placeholder (\"Quoted message\")\n // in the gap or wait silently; current bubble does the latter.\n quoted_message_id: attrs.quoted_message_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\n// Threads load top-down all-at-once: most discussions stay well under\n// 500 replies, the side-pane has no infinite-scroll affordance, and\n// avoiding pagination keeps the UX simple. `loadMore` remains as an\n// escape hatch in case a thread does exceed this on the rare day.\nconst PAGE_SIZE = 500;\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 sender_external_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 { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseTypingState {\n /**\n * Set of `external_id`s currently typing (your own user identifiers,\n * the same string you'd pass to `userResolver`). Excludes the\n * current user — they know they're typing.\n */\n typing: Set<string>;\n /**\n * Send a typing ping to the server. Debounced inside the hook to\n * once per 500 ms — the server squashes further with its own\n * per-(user, conversation) window.\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 */\nexport function useTyping(conversationId: string): UseTypingState {\n const chat = usePoolse();\n const { me } = useMe();\n const [typing, setTyping] = useState<Set<string>>(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 meExtRef = useRef<string | null>(me?.external_id ?? null);\n meExtRef.current = me?.external_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 const ext = evt.external_id;\n if (!ext) return;\n // Don't render the current user's own typing — they know.\n if (meExtRef.current && ext === meExtRef.current) return;\n setTyping((prev) => {\n if (prev.has(ext)) return prev;\n const next = new Set(prev);\n next.add(ext);\n return next;\n });\n });\n\n const offStop = conv.onTypingStop((evt) => {\n const ext = evt.external_id;\n if (!ext) return;\n if (meExtRef.current && ext === meExtRef.current) return;\n setTyping((prev) => {\n if (!prev.has(ext)) return prev;\n const next = new Set(prev);\n next.delete(ext);\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 } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UsePresenceState {\n /**\n * Set of `external_id`s currently online in this conversation —\n * the tenant's own user identifiers. Empty set when no one is on\n * the channel (note: an empty result during reconnect is normal;\n * pair with `useRealtimeStatus()` if you need to distinguish).\n */\n online: Set<string>;\n}\n\n// Pull external_id out of the first meta entry for each user_id key.\n// Phoenix.Presence supports multiple metas per join (e.g. same user\n// in two tabs); we surface the external_id once since it's identical\n// across the user's metas.\nfunction externalIdsFrom(state: PresenceSnapshot): string[] {\n const out: string[] = [];\n for (const presence of Object.values(state)) {\n const meta = presence?.metas?.[0];\n if (meta?.external_id) out.push(meta.external_id);\n }\n return out;\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<string>>(new Set());\n\n useEffect(() => {\n setOnline(new Set());\n\n if (!conversationId) return;\n\n const conv = chat.realtime.conversation(conversationId);\n\n const applyState = (state: PresenceSnapshot) => {\n setOnline(new Set(externalIdsFrom(state)));\n };\n\n const applyDiff = (diff: { joins?: PresenceSnapshot; leaves?: PresenceSnapshot }) => {\n setOnline((prev) => {\n const next = new Set(prev);\n if (diff.joins) externalIdsFrom(diff.joins).forEach((ext) => next.add(ext));\n if (diff.leaves) externalIdsFrom(diff.leaves).forEach((ext) => next.delete(ext));\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, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\nexport type UploadItemStatus = 'pending' | 'uploading' | 'ready' | 'error' | 'cancelled';\n\nexport interface UploadItem {\n /** Local-only id (random per-enqueue). Stable for keys + `cancel(localId)` / `remove(localId)`. */\n localId: string;\n filename: string;\n contentType: string;\n byteSize: number;\n status: UploadItemStatus;\n /** Bytes uploaded so far; 0 until the PUT actually begins. */\n loaded: number;\n /** Resolved attachment row once `status === 'ready'`. Null otherwise. */\n attachment: Attachment | null;\n /** Set when `status === 'error'`. */\n error: Error | null;\n}\n\ninterface UseAttachmentUploadState {\n /** Every enqueued item, in enqueue order, until removed by `remove()` / `reset()`. */\n queue: UploadItem[];\n /**\n * Last attachment that reached `ready`, for the common one-file\n * \"did the upload finish\" check. Null after `reset()` / `remove()`\n * of the most recent ready item. Multi-file callers should iterate\n * `queue` instead.\n */\n attachment: Attachment | null;\n /** True while at least one item is `pending` or `uploading`. */\n uploading: boolean;\n /** Most recent item-level error, or null. */\n error: Error | null;\n /**\n * Enqueue a single upload. Resolves with the final attachment row.\n * Rejects with the underlying error (item's `status` becomes\n * `'error'`); aborts surface as a DOMException('AbortError') and the\n * item's status becomes `'cancelled'`.\n */\n upload: (input: AttachmentUploadInput) => Promise<Attachment>;\n /**\n * Enqueue many at once — drag-and-drop, multi-file picker. Items run\n * in parallel (the SDK is per-call independent). Resolves with the\n * attachments in the same order as the input; if any item fails the\n * whole promise rejects after the others settle.\n */\n uploadAll: (inputs: AttachmentUploadInput[]) => Promise<Attachment[]>;\n /** Abort an in-flight upload. Sets the item's status to `cancelled`. No-op if not in flight. */\n cancel: (localId: string) => void;\n /** Drop an item from the queue. Cancels first if it's still in flight. */\n remove: (localId: string) => void;\n /** Drop everything + abort any in-flight uploads. */\n reset: () => void;\n}\n\ninterface InFlight {\n controller: AbortController;\n}\n\n/**\n * Stateful wrapper around `chat.attachments.upload`. Exposes a queue\n * of in-flight / completed uploads with per-item progress + per-item\n * cancel — drag-and-drop, multi-file picker, retry chips, all without\n * the host app reimplementing AbortController plumbing.\n *\n * ```tsx\n * const { upload, queue, cancel, remove } = useAttachmentUpload();\n * const onPick = async (files: File[]) => {\n * const atts = await uploadAll(files.map(f => ({\n * body: f, contentType: f.type, byteSize: f.size, filename: f.name\n * })));\n * await chat.conversations.one(convId).messages.send({\n * body: '', attachment_ids: atts.map(a => a.id),\n * });\n * };\n * ```\n *\n * The legacy `upload(input)` → `Promise<Attachment>` shape is preserved\n * so older callers keep working — they just won't render the queue UI.\n */\nexport function useAttachmentUpload(): UseAttachmentUploadState {\n const chat = usePoolse();\n const [queue, setQueue] = useState<UploadItem[]>([]);\n const inFlightRef = useRef<Map<string, InFlight>>(new Map());\n // Track mount status so async resolves don't setState on unmounted\n // components. Strict-mode double-effects re-arm this on remount.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n for (const v of inFlightRef.current.values()) v.controller.abort();\n inFlightRef.current.clear();\n };\n }, []);\n\n const updateItem = useCallback((localId: string, patch: Partial<UploadItem>) => {\n if (!mountedRef.current) return;\n setQueue((q) => q.map((it) => (it.localId === localId ? { ...it, ...patch } : it)));\n }, []);\n\n const runUpload = useCallback(\n async (localId: string, input: AttachmentUploadInput): Promise<Attachment> => {\n const controller = new AbortController();\n inFlightRef.current.set(localId, { controller });\n updateItem(localId, { status: 'uploading', loaded: 0 });\n try {\n const att = await chat.attachments.upload(input, {\n signal: controller.signal,\n onProgress: (e) => updateItem(localId, { loaded: e.loaded }),\n });\n updateItem(localId, {\n status: 'ready',\n loaded: input.byteSize,\n attachment: att,\n error: null,\n });\n return att;\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') {\n updateItem(localId, { status: 'cancelled' });\n throw err;\n }\n const e = err instanceof Error ? err : new Error(String(err));\n updateItem(localId, { status: 'error', error: e });\n throw e;\n } finally {\n inFlightRef.current.delete(localId);\n }\n },\n [chat, updateItem],\n );\n\n const enqueue = useCallback((input: AttachmentUploadInput): UploadItem => {\n const localId = generateLocalId();\n const item: UploadItem = {\n localId,\n filename: input.filename ?? 'file',\n contentType: input.contentType,\n byteSize: input.byteSize,\n status: 'pending',\n loaded: 0,\n attachment: null,\n error: null,\n };\n setQueue((q) => [...q, item]);\n return item;\n }, []);\n\n const upload = useCallback(\n (input: AttachmentUploadInput): Promise<Attachment> => {\n const item = enqueue(input);\n return runUpload(item.localId, input);\n },\n [enqueue, runUpload],\n );\n\n const uploadAll = useCallback(\n (inputs: AttachmentUploadInput[]): Promise<Attachment[]> => {\n // Enqueue all first so the UI shows the full queue immediately,\n // then start the PUTs in parallel. Order in resolved array\n // matches input order regardless of which PUT finishes first.\n const items = inputs.map((inp) => ({ item: enqueue(inp), input: inp }));\n return Promise.all(items.map(({ item, input }) => runUpload(item.localId, input)));\n },\n [enqueue, runUpload],\n );\n\n const cancel = useCallback((localId: string) => {\n const inf = inFlightRef.current.get(localId);\n if (inf) inf.controller.abort();\n }, []);\n\n const remove = useCallback((localId: string) => {\n const inf = inFlightRef.current.get(localId);\n if (inf) inf.controller.abort();\n setQueue((q) => q.filter((it) => it.localId !== localId));\n }, []);\n\n const reset = useCallback(() => {\n for (const v of inFlightRef.current.values()) v.controller.abort();\n inFlightRef.current.clear();\n setQueue([]);\n }, []);\n\n const uploading = queue.some((it) => it.status === 'pending' || it.status === 'uploading');\n // Last error in queue order — pendings/readies have null, so the\n // most recently transitioned-to-error item wins.\n const error = queue.reduce<Error | null>((acc, it) => it.error ?? acc, null);\n // Last ready attachment — same convenience.\n const attachment = queue.reduce<Attachment | null>((acc, it) => it.attachment ?? acc, null);\n\n return { queue, attachment, uploading, error, upload, uploadAll, cancel, remove, reset };\n}\n\nfunction generateLocalId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c && typeof c.randomUUID === 'function') return c.randomUUID();\n // Fallback for older runtimes (tests on Node 18 without crypto, etc).\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\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","// React binding over `chat.users.get(externalId)`.\n//\n// Uses plain useState + useEffect (NOT `useSyncExternalStore`).\n// useSyncExternalStore reaches into React internals and surfaces\n// any latent React-duplication immediately as \"Invalid hook call\".\n// The pattern below works the same way for our purposes — read\n// from the cache on mount, subscribe for updates, update state —\n// without that fragility.\n\nimport type { PoolseUserProfile } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\nexport interface UseUserState {\n /** Resolved profile, or null when the resolver returned null / errored / isn't configured. */\n profile: PoolseUserProfile | null;\n /** True while the SDK is mid-fetch (or before the first fetch fires). */\n loading: boolean;\n}\n\nconst EMPTY: UseUserState = { profile: null, loading: false };\n\n/**\n * Resolve the tenant's `external_id` (your own user id) to\n * `{ displayName, avatarUrl }` via the configured `userResolver`.\n *\n * Returns `{ profile: null, loading: false }` when:\n * * no resolver is configured\n * * resolver returned null (user not found)\n * * resolver threw (logged once, then cached as null)\n *\n * Pass `null` / empty string to opt out (the hook becomes a no-op).\n * Useful for self bubbles (you already know who you are).\n */\nexport function useUser(externalId: string | null | undefined): UseUserState {\n const chat = usePoolse();\n const [state, setState] = useState<UseUserState>(() => {\n if (!externalId) return EMPTY;\n const cached = chat.users.peek(externalId);\n if (cached === undefined) return { profile: null, loading: true };\n return { profile: cached, loading: false };\n });\n\n useEffect(() => {\n if (!externalId) {\n setState(EMPTY);\n return;\n }\n\n const apply = () => {\n const cached = chat.users.peek(externalId);\n if (cached === undefined) {\n setState({ profile: null, loading: true });\n void chat.users.get(externalId);\n } else {\n setState({ profile: cached, loading: false });\n }\n };\n\n const off = chat.users.subscribe(externalId, apply);\n apply();\n return off;\n }, [chat, externalId]);\n\n return state;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poolse/react",
3
- "version": "1.0.6",
3
+ "version": "2.0.0",
4
4
  "description": "Headless React hooks for poolse — realtime chat infrastructure. Provider + useMessages / useTyping / usePresence / useReactions / useAttachmentUpload / etc. NO UI.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -43,7 +43,7 @@
43
43
  "CHANGELOG.md"
44
44
  ],
45
45
  "dependencies": {
46
- "@poolse/sdk": "1.0.6"
46
+ "@poolse/sdk": "2.0.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "react": ">=18"