@poolse/react 0.1.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/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/index.cjs +695 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +340 -0
- package/dist/index.d.ts +340 -0
- package/dist/index.js +661 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/use-me.ts","../src/use-conversation.ts","../src/use-conversations.ts","../src/use-members.ts","../src/use-messages.ts","../src/use-reactions.ts","../src/use-thread.ts","../src/use-typing.ts","../src/use-presence.ts","../src/use-realtime-status.ts","../src/use-attachment-upload.ts","../src/use-attachment-url.ts"],"names":["useEffect","useState","useCallback","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;\n wsUrl: string | undefined;\n socketPath: string | undefined;\n } | null>(null);\n\n const chat = useMemo(() => {\n const initial = configRef.current;\n initialConnectionRef.current = {\n apiUrl: initial.apiUrl,\n wsUrl: initial.wsUrl,\n socketPath: initial.socketPath,\n };\n return new Poolse({\n apiUrl: initial.apiUrl,\n // Always read the latest callbacks from the ref — they're free\n // to change between renders.\n getToken: () => configRef.current.getToken(),\n ...(initial.fetch\n ? { fetch: ((...args) => configRef.current.fetch!(...args)) as typeof globalThis.fetch }\n : {}),\n ...(initial.maxRetries !== undefined ? { maxRetries: initial.maxRetries } : {}),\n ...(initial.baseBackoffMs !== undefined ? { baseBackoffMs: initial.baseBackoffMs } : {}),\n ...(initial.maxBackoffMs !== undefined ? { maxBackoffMs: initial.maxBackoffMs } : {}),\n ...(initial.generateIdempotencyKey\n ? { generateIdempotencyKey: () => configRef.current.generateIdempotencyKey!() }\n : {}),\n ...(initial.wsUrl !== undefined ? { wsUrl: initial.wsUrl } : {}),\n ...(initial.socketPath !== undefined ? { socketPath: initial.socketPath } : {}),\n ...(initial.onSocketError\n ? { onSocketError: (err) => configRef.current.onSocketError!(err) }\n : {}),\n });\n // Mount-once: the `Poolse` instance owns a WebSocket and channel\n // subscriptions, so it MUST be stable for the life of the mount.\n // Changing `apiUrl` / `wsUrl` / `socketPath` requires a remount.\n }, []);\n\n // Surface mistakes early in dev: connection-shaped fields are\n // captured at construction time, so changing them after mount has\n // no effect (callbacks like `getToken` ARE re-read from the ref).\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const initial = initialConnectionRef.current;\n if (!initial) return;\n if (\n initial.apiUrl !== config.apiUrl ||\n initial.wsUrl !== config.wsUrl ||\n initial.socketPath !== config.socketPath\n ) {\n console.warn(\n '[poolse] connection-shaped config (apiUrl / wsUrl / socketPath) ' +\n 'changed after <PoolseProvider> mounted. These are captured at ' +\n 'construction time — remount the provider with a new `key` to ' +\n 'switch environments.',\n );\n }\n }, [config.apiUrl, config.wsUrl, config.socketPath]);\n }\n\n useEffect(() => {\n return () => {\n chat.destroy();\n };\n }, [chat]);\n\n const value = useMemo(() => ({ chat }), [chat]);\n\n return <PoolseContext.Provider value={value}>{children}</PoolseContext.Provider>;\n}\n\n/**\n * Access the underlying `Poolse` instance. Most app code should prefer\n * higher-level hooks (`useMessages`, `useTyping`, etc.) but the raw\n * client is here for escape-hatch usage (custom REST calls, direct\n * realtime control).\n */\nexport function usePoolse(): Poolse {\n const value = useContext(PoolseContext);\n\n if (!value) {\n throw new Error(\n 'usePoolse(): no <PoolseProvider> in the tree. Wrap your component ' +\n 'with `<PoolseProvider config={{apiUrl, getToken}}>` first.',\n );\n }\n\n return value.chat;\n}\n","import type { Me } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMeState {\n me: Me | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * The currently-signed-in End User (`/v1/me`). Fetches once on mount\n * and never re-fetches automatically — user identity is stable for\n * the JWT's lifetime.\n *\n * Most apps won't need this; the JWT subject is enough. Useful when\n * the UI needs the display name / external_id without re-asking the\n * Customer's backend.\n */\nexport function useMe(): UseMeState {\n const chat = usePoolse();\n const [state, setState] = useState<UseMeState>({\n me: null,\n loading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n const controller = new AbortController();\n\n chat.me\n .show(controller.signal)\n .then((me) => {\n if (!cancelled) setState({ me, loading: false, error: null });\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n setState({\n me: null,\n loading: false,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [chat]);\n\n return state;\n}\n","import type { Conversation, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseConversationState {\n /** The fetched conversation, or `null` while loading or on error. */\n conversation: Conversation | null;\n loading: boolean;\n error: Error | null;\n /** Re-run the GET. Use after a `chat.conversations.one(id).update(...)` to refresh state. */\n refetch: () => Promise<void>;\n}\n\n/**\n * Fetch a single conversation by id. Re-fetches when `id` changes\n * (e.g. routing to a different conversation in the same component).\n *\n * Doesn't subscribe to realtime updates yet — the backend doesn't\n * broadcast `conversation:updated` to user channels. Use `refetch()`\n * after a mutation if you need fresh state in the same render cycle.\n *\n * ```ts\n * const { conversation, loading } = useConversation(convId);\n * if (loading) return <Spinner />;\n * if (!conversation) return <NotFound />;\n * return <h1>{conversation.name ?? 'Untitled'}</h1>;\n * ```\n */\nexport function useConversation(id: Uuid | null): UseConversationState {\n const chat = usePoolse();\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [loading, setLoading] = useState(id !== null);\n const [error, setError] = useState<Error | null>(null);\n\n // The fetcher is wrapped in useCallback so it's stable across\n // renders for the same id — lets callers depend on it in their\n // own effects (e.g. polling) without re-firing on every render.\n const fetcher = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n if (id === null) return;\n setLoading(true);\n setError(null);\n try {\n const conv = await chat.conversations.one(id).show(signal);\n setConversation(conv);\n } catch (err) {\n // Ignore AbortError — the caller hit unmount or a new id.\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n },\n [chat, id],\n );\n\n useEffect(() => {\n if (id === null) {\n setConversation(null);\n setLoading(false);\n setError(null);\n return;\n }\n const controller = new AbortController();\n void fetcher(controller.signal);\n return () => controller.abort();\n }, [fetcher, id]);\n\n const refetch = useCallback(() => fetcher(), [fetcher]);\n\n return { conversation, loading, error, refetch };\n}\n","import type { Conversation, ConversationCreateRequest } from '@poolse/sdk';\nimport { useCallback, useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseConversationsState {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n create: (attrs: ConversationCreateRequest) => Promise<Conversation>;\n}\n\n/**\n * List of conversations the current End User can see.\n *\n * On mount: REST-fetches the list and subscribes to the user's\n * `user:<id>` channel for `conversation:created` events — fired by\n * the server both when this user creates a conversation AND when\n * someone else adds them to one. New rows are prepended to local\n * state with id-based dedup so an optimistic `create()` followed by\n * the realtime echo doesn't insert twice.\n *\n * `refetch()` is still here for explicit re-syncs (e.g. after a\n * mutation that the SDK doesn't yet observe — name changes,\n * settings updates). `create()` returns the canonical server row.\n */\nexport function useConversations(): UseConversationsState {\n const chat = usePoolse();\n const { me } = useMe();\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const refetch = useCallback(async () => {\n setLoading(true);\n try {\n const list = await chat.conversations.list();\n setConversations(list.data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [chat]);\n\n const create = useCallback(\n async (attrs: ConversationCreateRequest) => {\n const conv = await chat.conversations.create(attrs);\n // Optimistically prepend; if the realtime echo arrives later\n // for the same conv (because the server also broadcast it to\n // us as the creator), the id-based dedup in `prepend` keeps\n // it from inserting twice.\n setConversations((prev) => prepend(prev, conv));\n return conv;\n },\n [chat],\n );\n\n useEffect(() => {\n void refetch();\n }, [refetch]);\n\n // Realtime: subscribe to `user:<me.id>:conversation:created` once we\n // know who \"me\" is. Re-subscribes if `me.id` changes (rare — only on\n // sign-in/sign-out within the same provider, which is itself rare).\n useEffect(() => {\n if (!me) return;\n const userChan = chat.realtime.user(me.id);\n const off = userChan.onConversationCreated((conv) => {\n setConversations((prev) => prepend(prev, conv));\n });\n return off;\n }, [chat, me]);\n\n return { conversations, loading, error, refetch, create };\n}\n\n/**\n * Prepend `conv` if its id isn't already in `prev`; otherwise replace\n * the existing row (covers the race where the realtime echo arrives\n * for a conversation our local `create()` already inserted).\n */\nfunction prepend(prev: Conversation[], conv: Conversation): Conversation[] {\n const idx = prev.findIndex((c) => c.id === conv.id);\n if (idx === -1) return [conv, ...prev];\n const next = prev.slice();\n next[idx] = conv;\n return next;\n}\n","import type { AddMemberOptions, MemberRole, Membership, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMembersState {\n members: Membership[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n /**\n * Add one or more users by external_id. The returned memberships\n * are appended to local state on success.\n */\n addMembers: (externalIds: string[], opts?: { role?: MemberRole }) => Promise<Membership[]>;\n /**\n * Remove a member by user_id. Optimistically removes from state;\n * rolls back on server error.\n */\n removeMember: (userId: Uuid) => Promise<void>;\n}\n\n/**\n * Live-ish membership list for a conversation. Initial REST fetch on\n * mount; mutation helpers update local state in place. No realtime\n * sync yet — the backend doesn't broadcast `member:joined` /\n * `member:left` events. For now, callers who depend on\n * cross-client member updates should poll with `refetch()` or\n * remount the hook.\n */\nexport function useMembers(conversationId: Uuid): UseMembersState {\n const chat = usePoolse();\n const [members, setMembers] = useState<Membership[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Shadow ref tracking the latest committed members. Lets the\n // optimistic rollback path capture a snapshot synchronously\n // without racing the React updater queue against an `await`.\n const membersRef = useRef<Membership[]>([]);\n membersRef.current = members;\n\n const fetcher = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n setLoading(true);\n setError(null);\n try {\n const { data } = await chat.conversations.one(conversationId).listMembers(signal);\n setMembers(data);\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n },\n [chat, conversationId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void fetcher(controller.signal);\n return () => controller.abort();\n }, [fetcher]);\n\n const refetch = useCallback(() => fetcher(), [fetcher]);\n\n const addMembers = useCallback(\n async (externalIds: string[], opts: { role?: MemberRole } = {}) => {\n const addOpts: AddMemberOptions = opts.role !== undefined ? { role: opts.role } : {};\n const { data } = await chat.conversations\n .one(conversationId)\n .addMembers(externalIds, addOpts);\n // Dedup by id in case the server returns a row that was already\n // a member (idempotent re-add).\n setMembers((prev) => {\n const byId = new Map(prev.map((m) => [m.id, m]));\n for (const m of data) byId.set(m.id, m);\n return Array.from(byId.values());\n });\n return data;\n },\n [chat, conversationId],\n );\n\n const removeMember = useCallback(\n async (userId: Uuid) => {\n const snapshot = membersRef.current;\n setMembers((prev) => prev.filter((m) => m.user_id !== userId));\n try {\n await chat.conversations.one(conversationId).removeMember(userId);\n } catch (err) {\n setMembers(snapshot);\n throw err;\n }\n },\n [chat, conversationId],\n );\n\n return { members, loading, error, refetch, addMembers, removeMember };\n}\n","import type { Message, MessageCreateRequest } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseMessagesState {\n /** Newest-last array. The wire returns newest-first; we reverse so list rendering matches reading order. */\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasMore: boolean;\n /** Load an older page (lower sequence numbers). Idempotent if no older messages exist. */\n loadMore: () => Promise<void>;\n /** Optimistically append + POST. Replaces the optimistic row with the server response on success. */\n send: (attrs: MessageCreateRequest) => Promise<Message>;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Live message list for `conversationId`. Combines:\n *\n * * Initial REST fetch (newest 50) on mount.\n * * WebSocket subscription for `message:new`, `message:updated`,\n * `message:deleted` — applied in-place to the cached array.\n * * Optimistic-send via `send()` — the message appears immediately\n * under the SAME id the server will assign (we pre-generate it\n * client-side and pass it through), so the realtime echo and the\n * REST response both arrive carrying that id and get deduped by\n * `findIndex(m => m.id === msg.id)`. No heuristic match, no race.\n *\n * Re-mounting with the same `conversationId` reuses the underlying\n * channel — no extra socket traffic.\n */\nexport function useMessages(conversationId: string): UseMessagesState {\n const chat = usePoolse();\n const [messages, setMessages] = useState<Message[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(true);\n\n // Cursor for `loadMore` — the lowest sequence currently in state.\n const oldestSequenceRef = useRef<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setMessages([]);\n setError(null);\n setHasMore(true);\n oldestSequenceRef.current = null;\n\n const handle = chat.conversations.one(conversationId).messages;\n\n handle\n .list({ limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled) return;\n // Wire is newest-first; flip for natural reading order.\n const ordered = [...page.data].reverse();\n setMessages(ordered);\n setHasMore(page.data.length === PAGE_SIZE);\n oldestSequenceRef.current = ordered[0]?.sequence ?? null;\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n // Realtime listeners.\n const conv = chat.realtime.conversation(conversationId);\n\n const offNew = conv.onMessage((msg) => {\n // Simple by-id upsert. Covers three cases with one expression:\n // 1) Brand-new message from another user → append.\n // 2) Echo of our own optimistic send (id we generated below) →\n // replace the temp row in place (preserves position).\n // 3) Re-delivery on channel rejoin → idempotent replace.\n setMessages((prev) => upsertById(prev, msg));\n });\n\n const offUpdated = conv.onMessageUpdated((msg) => {\n setMessages((prev) => prev.map((m) => (m.id === msg.id ? msg : m)));\n });\n\n const offDeleted = conv.onMessageDeleted((evt) => {\n setMessages((prev) =>\n prev.map((m) => (m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m)),\n );\n });\n\n return () => {\n cancelled = true;\n offNew();\n offUpdated();\n offDeleted();\n // Don't leave the channel — another component may still be reading\n // this conversation. The Poolse.destroy() at provider-unmount\n // tears everything down.\n };\n }, [chat, conversationId]);\n\n const loadMore = useCallback(async () => {\n if (!hasMore || loading) return;\n const before = oldestSequenceRef.current;\n if (!before) return;\n\n const opts: { limit: number; before?: number } = { limit: PAGE_SIZE };\n if (before !== null) opts.before = before;\n\n const page = await chat.conversations.one(conversationId).messages.list(opts);\n if (page.data.length === 0) {\n setHasMore(false);\n return;\n }\n const older = [...page.data].reverse();\n setMessages((prev) => [...older, ...prev]);\n setHasMore(page.data.length === PAGE_SIZE);\n oldestSequenceRef.current = older[0]?.sequence ?? oldestSequenceRef.current;\n }, [chat, conversationId, hasMore, loading]);\n\n const send = useCallback(\n async (attrs: MessageCreateRequest) => {\n // Generate the message id client-side and pass it through, so\n // the optimistic row, the REST response, and the realtime echo\n // ALL share one id — id-based upsert handles every race.\n const id = attrs.id ?? crypto.randomUUID();\n const tempMsg: Message = {\n id,\n tenant_id: '',\n conversation_id: conversationId,\n sender_id: null,\n type: attrs.type ?? 'text',\n body: attrs.body,\n reply_to_id: attrs.reply_to_id ?? null,\n thread_root_id: null,\n mentions: attrs.mentions ?? [],\n reactions: {},\n edited_at: null,\n deleted_at: null,\n // MAX_SAFE_INTEGER sorts the temp row to the very end (newest\n // position) until the server returns the real `sequence`.\n sequence: Number.MAX_SAFE_INTEGER,\n inserted_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, tempMsg]);\n\n try {\n const sent = await chat.conversations.one(conversationId).messages.send({ ...attrs, id });\n // Both REST and realtime carry the same id; whichever lands\n // first wins, and the second is an idempotent replace.\n setMessages((prev) => upsertById(prev, sent));\n return sent;\n } catch (err) {\n setMessages((prev) => prev.filter((m) => m.id !== id));\n throw err;\n }\n },\n [chat, conversationId],\n );\n\n return { messages, loading, error, hasMore, loadMore, send };\n}\n\nfunction upsertById(prev: Message[], msg: Message): Message[] {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx === -1) return [...prev, msg];\n const next = prev.slice();\n next[idx] = msg;\n return next;\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\n/**\n * Map of emoji → list of user_ids who reacted with it. Matches the\n * shape of `Message.reactions` so initial seeding from a message you\n * already have in state is a direct assignment.\n */\nexport type ReactionMap = Record<string, Uuid[]>;\n\ninterface UseReactionsState {\n reactions: ReactionMap;\n /** Add the caller's reaction (idempotent server-side). */\n addReaction: (emoji: string) => Promise<void>;\n /** Remove the caller's reaction. No-op if not present. */\n removeReaction: (emoji: string) => Promise<void>;\n}\n\ninterface UseReactionsOptions {\n /**\n * Required for the in-channel subscription — the realtime layer\n * routes reaction events through the conversation channel, not a\n * per-message channel. Pass the conversation id you already know.\n */\n conversationId: Uuid;\n /**\n * Seed the local reaction map from a message you already have\n * (e.g. from `useMessages`). Without this the hook starts empty\n * and only sees deltas from the realtime stream.\n */\n initialReactions?: ReactionMap;\n /**\n * Current user's id. When provided, optimistic mutate updates the\n * local map immediately for that user; when omitted, we wait for\n * the server's `reaction:added` echo to update state.\n */\n currentUserId?: Uuid | null;\n}\n\n/**\n * Live reaction map for a single message. Subscribes to\n * `reaction:added` / `reaction:removed` realtime events filtered to\n * `messageId`, and provides mutation helpers.\n *\n * ```ts\n * const { reactions, addReaction } = useReactions(msg.id, {\n * conversationId: msg.conversation_id,\n * initialReactions: msg.reactions,\n * currentUserId: me?.id,\n * });\n * <button onClick={() => addReaction('🎉')}>🎉 {reactions['🎉']?.length ?? 0}</button>\n * ```\n */\nexport function useReactions(messageId: Uuid, opts: UseReactionsOptions): UseReactionsState {\n const chat = usePoolse();\n const [reactions, setReactions] = useState<ReactionMap>(opts.initialReactions ?? {});\n\n // Keep currentUserId in a ref so the realtime callbacks (set up in\n // the mount effect) always see the latest value without having to\n // re-subscribe when it changes.\n const currentUserIdRef = useRef<Uuid | null>(opts.currentUserId ?? null);\n currentUserIdRef.current = opts.currentUserId ?? null;\n\n // Shadow ref of the latest committed reactions map — used by\n // `removeReaction` for synchronous snapshot capture so the\n // optimistic rollback isn't racing the React updater queue.\n const reactionsRef = useRef<ReactionMap>(reactions);\n reactionsRef.current = reactions;\n\n useEffect(() => {\n const conv = chat.realtime.conversation(opts.conversationId);\n\n const offAdded = conv.onReactionAdded((evt) => {\n if (evt.message_id !== messageId) return;\n setReactions((prev) => addUser(prev, evt.emoji, evt.user_id));\n });\n\n const offRemoved = conv.onReactionRemoved((evt) => {\n if (evt.message_id !== messageId) return;\n setReactions((prev) => removeUser(prev, evt.emoji, evt.user_id));\n });\n\n return () => {\n offAdded();\n offRemoved();\n };\n }, [chat, opts.conversationId, messageId]);\n\n const addReaction = useCallback(\n async (emoji: string) => {\n const uid = currentUserIdRef.current;\n // Optimistic add when we know who we are; otherwise wait for echo.\n if (uid) setReactions((prev) => addUser(prev, emoji, uid));\n try {\n await chat.messages.one(messageId).addReaction(emoji);\n } catch (err) {\n if (uid) setReactions((prev) => removeUser(prev, emoji, uid));\n throw err;\n }\n },\n [chat, messageId],\n );\n\n const removeReaction = useCallback(\n async (emoji: string) => {\n const uid = currentUserIdRef.current;\n const snapshot = reactionsRef.current;\n if (uid) setReactions((prev) => removeUser(prev, emoji, uid));\n try {\n await chat.messages.one(messageId).removeReaction(emoji);\n } catch (err) {\n if (uid) setReactions(snapshot);\n throw err;\n }\n },\n [chat, messageId],\n );\n\n return { reactions, addReaction, removeReaction };\n}\n\nfunction addUser(prev: ReactionMap, emoji: string, userId: Uuid): ReactionMap {\n const existing = prev[emoji] ?? [];\n if (existing.includes(userId)) return prev;\n return { ...prev, [emoji]: [...existing, userId] };\n}\n\nfunction removeUser(prev: ReactionMap, emoji: string, userId: Uuid): ReactionMap {\n const existing = prev[emoji];\n if (!existing || !existing.includes(userId)) return prev;\n const next = existing.filter((id) => id !== userId);\n if (next.length === 0) {\n const { [emoji]: _, ...rest } = prev;\n return rest;\n }\n return { ...prev, [emoji]: next };\n}\n","import type { Message, MessageCreateRequest, Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseThreadState {\n /** Replies, oldest-first (the wire returns oldest-first; we don't flip). */\n replies: Message[];\n loading: boolean;\n error: Error | null;\n /** More older-than-current-page replies available on the server. */\n hasMore: boolean;\n /** Load the next page after the current newest reply. Idempotent if no more. */\n loadMore: () => Promise<void>;\n /**\n * Send a reply into this thread. Fills `reply_to_id` with the root\n * message id automatically; pass `body` (and any other\n * `MessageCreateRequest` fields) as you would to `useMessages.send`.\n */\n sendReply: (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => Promise<Message>;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Thread view rooted at `rootMessageId`. Loads replies oldest-first\n * with cursor pagination (`after: sequence`), subscribes to the\n * conversation channel's `message:new` event filtered by\n * `thread_root_id === rootMessageId`, and provides a `sendReply`\n * that wires `reply_to_id` for you.\n *\n * Like `useMessages`, the optimistic send uses the same id the\n * server will assign (auto-generated by the SDK), so the realtime\n * echo just upserts in place — no double-render.\n */\nexport function useThread(conversationId: Uuid, rootMessageId: Uuid): UseThreadState {\n const chat = usePoolse();\n const [replies, setReplies] = useState<Message[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(true);\n\n // Cursor for `loadMore` — the highest sequence currently in state.\n const newestSequenceRef = useRef<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setReplies([]);\n setError(null);\n setHasMore(true);\n newestSequenceRef.current = null;\n\n chat.messages\n .one(rootMessageId)\n .replies({ limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled) return;\n setReplies(page.data);\n setHasMore(page.data.length === PAGE_SIZE);\n newestSequenceRef.current = page.data[page.data.length - 1]?.sequence ?? null;\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n // Realtime: filter conversation messages for thread membership.\n const conv = chat.realtime.conversation(conversationId);\n const offNew = conv.onMessage((msg) => {\n if (msg.thread_root_id !== rootMessageId) return;\n setReplies((prev) => upsertById(prev, msg));\n });\n const offUpdated = conv.onMessageUpdated((msg) => {\n if (msg.thread_root_id !== rootMessageId) return;\n setReplies((prev) => prev.map((m) => (m.id === msg.id ? msg : m)));\n });\n const offDeleted = conv.onMessageDeleted((evt) => {\n setReplies((prev) =>\n prev.map((m) => (m.id === evt.id ? { ...m, deleted_at: evt.deleted_at, body: null } : m)),\n );\n });\n\n return () => {\n cancelled = true;\n offNew();\n offUpdated();\n offDeleted();\n };\n }, [chat, conversationId, rootMessageId]);\n\n const loadMore = useCallback(async () => {\n if (!hasMore || loading) return;\n const after = newestSequenceRef.current;\n if (after === null) return;\n const page = await chat.messages.one(rootMessageId).replies({ limit: PAGE_SIZE, after });\n if (page.data.length === 0) {\n setHasMore(false);\n return;\n }\n setReplies((prev) => [...prev, ...page.data]);\n setHasMore(page.data.length === PAGE_SIZE);\n newestSequenceRef.current = page.data[page.data.length - 1]?.sequence ?? after;\n }, [chat, rootMessageId, hasMore, loading]);\n\n const sendReply = useCallback(\n async (attrs: Omit<MessageCreateRequest, 'reply_to_id'>) => {\n const id = attrs.id ?? crypto.randomUUID();\n const tempMsg: Message = {\n id,\n tenant_id: '',\n conversation_id: conversationId,\n sender_id: null,\n type: attrs.type ?? 'text',\n body: attrs.body,\n reply_to_id: rootMessageId,\n thread_root_id: rootMessageId,\n mentions: attrs.mentions ?? [],\n reactions: {},\n edited_at: null,\n deleted_at: null,\n sequence: Number.MAX_SAFE_INTEGER,\n inserted_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n };\n setReplies((prev) => [...prev, tempMsg]);\n\n try {\n const sent = await chat.conversations.one(conversationId).messages.send({\n ...attrs,\n id,\n reply_to_id: rootMessageId,\n });\n setReplies((prev) => upsertById(prev, sent));\n return sent;\n } catch (err) {\n setReplies((prev) => prev.filter((m) => m.id !== id));\n throw err;\n }\n },\n [chat, conversationId, rootMessageId],\n );\n\n return { replies, loading, error, hasMore, loadMore, sendReply };\n}\n\nfunction upsertById(prev: Message[], msg: Message): Message[] {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx === -1) return [...prev, msg];\n const next = prev.slice();\n next[idx] = msg;\n return next;\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\nimport { useMe } from './use-me.js';\n\ninterface UseTypingState {\n /** Set of user_ids currently typing. */\n typing: Set<Uuid>;\n /**\n * Send a typing ping to the server. Debounced inside the SDK — the\n * server squashes `typing:start` to one push per (user, conversation,\n * window). Call as often as you want from input handlers.\n */\n signalTyping: () => void;\n}\n\n/**\n * Tracks who's typing in `conversationId`. Subscribes to the\n * `typing:start` / `typing:stop` broadcasts; auto-cleans up entries\n * when stop fires.\n *\n * `signalTyping` debounces on the client side to once per 500 ms so a\n * fast-typing user doesn't flood the channel — poolse does its own\n * server-side debounce too, so both layers are safe.\n */\nexport function useTyping(conversationId: string): UseTypingState {\n const chat = usePoolse();\n const { me } = useMe();\n const [typing, setTyping] = useState<Set<Uuid>>(new Set());\n const lastPingRef = useRef(0);\n\n // `me` resolves asynchronously after first render; read it from a\n // ref inside the event handlers so the subscription doesn't need to\n // re-attach when `me` lands (which would briefly drop incoming\n // typing events from other users).\n const meIdRef = useRef<Uuid | null>(me?.id ?? null);\n meIdRef.current = me?.id ?? null;\n\n useEffect(() => {\n setTyping(new Set());\n\n const conv = chat.realtime.conversation(conversationId);\n\n const offStart = conv.onTypingStart((evt) => {\n // Don't render the current user's own typing — they know they're typing.\n if (meIdRef.current && evt.user_id === meIdRef.current) return;\n setTyping((prev) => {\n if (prev.has(evt.user_id)) return prev;\n const next = new Set(prev);\n next.add(evt.user_id);\n return next;\n });\n });\n\n const offStop = conv.onTypingStop((evt) => {\n if (meIdRef.current && evt.user_id === meIdRef.current) return;\n setTyping((prev) => {\n if (!prev.has(evt.user_id)) return prev;\n const next = new Set(prev);\n next.delete(evt.user_id);\n return next;\n });\n });\n\n return () => {\n offStart();\n offStop();\n };\n }, [chat, conversationId]);\n\n const signalTyping = useCallback(() => {\n const now = Date.now();\n if (now - lastPingRef.current < 500) return;\n lastPingRef.current = now;\n chat.realtime.conversation(conversationId).sendTyping();\n }, [chat, conversationId]);\n\n return { typing, signalTyping };\n}\n","import type { PresenceSnapshot, Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UsePresenceState {\n /** Set of user_ids currently online in this conversation. */\n online: Set<Uuid>;\n}\n\n/**\n * Who's currently joined to `conversationId`'s channel. Backed by\n * Phoenix.Presence broadcasts (`presence_state` snapshot on join,\n * `presence_diff` on changes).\n */\nexport function usePresence(conversationId: string): UsePresenceState {\n const chat = usePoolse();\n const [online, setOnline] = useState<Set<Uuid>>(new Set());\n\n useEffect(() => {\n setOnline(new Set());\n\n const conv = chat.realtime.conversation(conversationId);\n\n const applyState = (state: PresenceSnapshot) => {\n setOnline(new Set(Object.keys(state)));\n };\n\n const applyDiff = (diff: { joins?: PresenceSnapshot; leaves?: PresenceSnapshot }) => {\n setOnline((prev) => {\n const next = new Set(prev);\n if (diff.joins) Object.keys(diff.joins).forEach((id) => next.add(id));\n if (diff.leaves) Object.keys(diff.leaves).forEach((id) => next.delete(id));\n return next;\n });\n };\n\n const offState = conv.onPresenceState(applyState);\n const offDiff = conv.onPresenceDiff(applyDiff as (s: PresenceSnapshot) => void);\n\n return () => {\n offState();\n offDiff();\n };\n }, [chat, conversationId]);\n\n return { online };\n}\n","import type { RealtimeStatus } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\n/**\n * Connection status of the underlying WebSocket. Useful for showing a\n * \"reconnecting…\" banner without coupling to socket internals.\n *\n * Returns one of: `'idle' | 'connecting' | 'connected' | 'reconnecting' | 'closed'`.\n */\nexport function useRealtimeStatus(): RealtimeStatus {\n const chat = usePoolse();\n const [status, setStatus] = useState<RealtimeStatus>(chat.realtime.getStatus());\n\n useEffect(() => {\n setStatus(chat.realtime.getStatus());\n return chat.realtime.onStatus(setStatus);\n }, [chat]);\n\n return status;\n}\n","import type { Attachment, AttachmentUploadInput } from '@poolse/sdk';\nimport { useCallback, useRef, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseAttachmentUploadState {\n /** Last successfully uploaded attachment, or null. */\n attachment: Attachment | null;\n uploading: boolean;\n error: Error | null;\n /**\n * Run the upload pipeline (presigned-URL request + PUT). Updates\n * local state with the resolved attachment on success; sets `error`\n * and rethrows on failure so callers can surface a toast.\n */\n upload: (input: AttachmentUploadInput) => Promise<Attachment>;\n /** Reset state (clears `attachment`, `error`). */\n reset: () => void;\n}\n\n/**\n * Stateful wrapper around `chat.attachments.upload`. Provides\n * `uploading` + `error` flags for the common \"show a spinner while\n * the PUT is in flight\" UI, plus retention of the last attachment\n * so the caller can reference its id when sending a message.\n *\n * ```tsx\n * const { upload, uploading, attachment } = useAttachmentUpload();\n * const onPick = async (file: File) => {\n * const att = await upload({\n * body: file, contentType: file.type, byteSize: file.size, filename: file.name\n * });\n * await chat.conversations.one(convId).messages.send({\n * body: 'attached',\n * custom_data: { attachment_id: att.id },\n * });\n * };\n * ```\n */\nexport function useAttachmentUpload(): UseAttachmentUploadState {\n const chat = usePoolse();\n const [attachment, setAttachment] = useState<Attachment | null>(null);\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n // Track an in-flight upload's AbortController so unmount cancels it.\n const inFlightRef = useRef<AbortController | null>(null);\n\n const upload = useCallback(\n async (input: AttachmentUploadInput): Promise<Attachment> => {\n // Cancel any prior in-flight upload — last-write-wins on intent.\n inFlightRef.current?.abort();\n const controller = new AbortController();\n inFlightRef.current = controller;\n\n setUploading(true);\n setError(null);\n try {\n const att = await chat.attachments.upload(input, { signal: controller.signal });\n if (inFlightRef.current === controller) {\n setAttachment(att);\n }\n return att;\n } catch (err) {\n if ((err as DOMException)?.name === 'AbortError') throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n if (inFlightRef.current === controller) {\n setUploading(false);\n inFlightRef.current = null;\n }\n }\n },\n [chat],\n );\n\n const reset = useCallback(() => {\n inFlightRef.current?.abort();\n inFlightRef.current = null;\n setAttachment(null);\n setError(null);\n setUploading(false);\n }, []);\n\n return { attachment, uploading, error, upload, reset };\n}\n","import type { Uuid } from '@poolse/sdk';\nimport { useEffect, useState } from 'react';\nimport { usePoolse } from './provider.js';\n\ninterface UseAttachmentUrlState {\n /** Presigned GET URL, or null while loading / on error. */\n url: string | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Resolve an attachment's presigned download URL. Pass `null` to\n * skip the fetch — useful in routing-driven views where the id may\n * not be known yet.\n *\n * Doesn't auto-refresh: the server's URL TTL is ~1 hour and most\n * UI lifetimes are much shorter. If you do need a refresh (long-lived\n * dashboard, etc.), remount the hook or wrap it in a parent that\n * re-keys on a timer.\n *\n * ```tsx\n * const { url } = useAttachmentUrl(message.custom_data?.attachment_id ?? null);\n * return url ? <img src={url} /> : <Spinner />;\n * ```\n */\nexport function useAttachmentUrl(attachmentId: Uuid | null): UseAttachmentUrlState {\n const chat = usePoolse();\n const [url, setUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(attachmentId !== null);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (attachmentId === null) {\n setUrl(null);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n const controller = new AbortController();\n setLoading(true);\n setError(null);\n chat.attachments\n .one(attachmentId)\n .downloadUrl({ signal: controller.signal })\n .then((res) => {\n if (cancelled) return;\n setUrl(res.url);\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n if ((err as DOMException)?.name === 'AbortError') return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [chat, attachmentId]);\n\n return { url, loading, error };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poolse/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Headless React hooks for poolse — realtime chat infrastructure. Provider + useMessages / useTyping / usePresence / useReactions / useAttachmentUpload / etc. NO UI.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"poolse",
|
|
8
|
+
"chat",
|
|
9
|
+
"react",
|
|
10
|
+
"hooks",
|
|
11
|
+
"realtime",
|
|
12
|
+
"websocket",
|
|
13
|
+
"messaging"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://poolse.dev",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/poolse-hq/js-sdk.git",
|
|
19
|
+
"directory": "packages/react"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/poolse-hq/js-sdk/issues"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.cjs",
|
|
26
|
+
"module": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"require": {
|
|
35
|
+
"types": "./dist/index.d.cts",
|
|
36
|
+
"default": "./dist/index.cjs"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md",
|
|
43
|
+
"CHANGELOG.md"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@poolse/sdk": "0.1.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"react": ">=18"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@testing-library/react": "^16.1.0",
|
|
53
|
+
"@types/react": "^19.0.0",
|
|
54
|
+
"happy-dom": "^15.11.7",
|
|
55
|
+
"react": "^19.0.0",
|
|
56
|
+
"react-dom": "^19.0.0"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"typecheck": "tsc --noEmit",
|
|
65
|
+
"lint": "eslint src test"
|
|
66
|
+
}
|
|
67
|
+
}
|