@marktiderman/genesis-chat 0.1.0 → 0.2.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.
Files changed (162) hide show
  1. package/README.md +304 -13
  2. package/dist/{chunk-SAY24E6V.js → chunk-5D5A7I4Q.js} +166 -45
  3. package/dist/chunk-5D5A7I4Q.js.map +1 -0
  4. package/dist/{chunk-JQXZUEEL.js → chunk-7S6HYNWW.js} +382 -8
  5. package/dist/chunk-7S6HYNWW.js.map +1 -0
  6. package/dist/chunk-BJCE5O7V.js +70 -0
  7. package/dist/chunk-BJCE5O7V.js.map +1 -0
  8. package/dist/chunk-PZTOY2LY.js +576 -0
  9. package/dist/chunk-PZTOY2LY.js.map +1 -0
  10. package/dist/chunk-VEPZROQB.js +187 -0
  11. package/dist/chunk-VEPZROQB.js.map +1 -0
  12. package/dist/{client-BtdALFCx.d.ts → client-DMa2j7kz.d.ts} +152 -11
  13. package/dist/index.d.ts +78 -163
  14. package/dist/index.js +3 -2
  15. package/dist/native.d.ts +1910 -1
  16. package/dist/native.js +4900 -0
  17. package/dist/native.js.map +1 -1
  18. package/dist/outbox-B0y3phE0.d.ts +151 -0
  19. package/dist/push.d.ts +206 -0
  20. package/dist/push.js +3 -0
  21. package/dist/push.js.map +1 -0
  22. package/dist/react.d.ts +149 -7
  23. package/dist/react.js +3 -3
  24. package/dist/server.d.ts +510 -21
  25. package/dist/server.js +863 -21
  26. package/dist/server.js.map +1 -1
  27. package/dist/thread-DWXHKPdw.d.ts +57 -0
  28. package/dist/web.d.ts +313 -10
  29. package/dist/web.js +1731 -60
  30. package/dist/web.js.map +1 -1
  31. package/migrations/0002_genesis_chat_coaching.sql +934 -0
  32. package/migrations/tests/0002_genesis_chat_coaching.test.sql +265 -0
  33. package/package.json +74 -6
  34. package/src/__tests__/coaching-core.test.ts +332 -0
  35. package/src/__tests__/coaching-react.test.tsx +248 -0
  36. package/src/__tests__/coaching-web.test.tsx +449 -0
  37. package/src/__tests__/core.test.ts +91 -0
  38. package/src/__tests__/outbox.test.ts +122 -0
  39. package/src/__tests__/realtime.test.ts +70 -0
  40. package/src/__tests__/review-fixes-core.test.ts +193 -0
  41. package/src/__tests__/review-fixes-web.test.tsx +402 -0
  42. package/src/__tests__/server-effects.test.ts +158 -0
  43. package/src/__tests__/server-fakes.ts +90 -0
  44. package/src/__tests__/server-integrations.test.ts +247 -0
  45. package/src/__tests__/server-providers.test.ts +246 -0
  46. package/src/__tests__/server-runner.test.ts +277 -0
  47. package/src/__tests__/server-safety.test.ts +290 -0
  48. package/src/__tests__/web-markdown.test.tsx +88 -0
  49. package/src/__tests__/web.test.tsx +333 -0
  50. package/src/core/availability.ts +223 -0
  51. package/src/core/client.ts +757 -0
  52. package/src/core/extras.ts +106 -0
  53. package/src/core/media.ts +144 -0
  54. package/src/core/outbox.ts +429 -0
  55. package/src/core/thread.ts +171 -0
  56. package/src/core/types.ts +311 -0
  57. package/src/index.ts +13 -0
  58. package/src/native/__tests__/auto-retry.test.tsx +128 -0
  59. package/src/native/__tests__/composer-mic-lock.test.tsx +115 -0
  60. package/src/native/__tests__/composer-state.test.ts +188 -0
  61. package/src/native/__tests__/composer.test.tsx +133 -0
  62. package/src/native/__tests__/emoji.test.tsx +238 -0
  63. package/src/native/__tests__/inbox-screen.test.tsx +48 -0
  64. package/src/native/__tests__/message-bubble.test.tsx +127 -0
  65. package/src/native/__tests__/organise-logic.test.ts +164 -0
  66. package/src/native/__tests__/organise-screens.test.tsx +344 -0
  67. package/src/native/__tests__/photo-viewer.test.tsx +226 -0
  68. package/src/native/__tests__/push-payload.test.ts +66 -0
  69. package/src/native/__tests__/push.test.ts +209 -0
  70. package/src/native/__tests__/recorder-machine.test.ts +96 -0
  71. package/src/native/__tests__/rows-actions.test.ts +76 -0
  72. package/src/native/__tests__/thread-layout.test.ts +41 -0
  73. package/src/native/__tests__/thread-screen.test.tsx +116 -0
  74. package/src/native/__tests__/tus.test.ts +154 -0
  75. package/src/native/__tests__/use-voice-recorder.test.tsx +316 -0
  76. package/src/native/__tests__/video-media.test.tsx +421 -0
  77. package/src/native/__tests__/video-recorder-state.test.ts +87 -0
  78. package/src/native/__tests__/video-upload.test.ts +227 -0
  79. package/src/native/access-error.tsx +31 -0
  80. package/src/native/actions.ts +42 -0
  81. package/src/native/attachment-cards.tsx +116 -0
  82. package/src/native/auto-retry.ts +69 -0
  83. package/src/native/availability.tsx +376 -0
  84. package/src/native/broadcast-sheet.tsx +193 -0
  85. package/src/native/composer-state.ts +302 -0
  86. package/src/native/composer.tsx +453 -0
  87. package/src/native/context.tsx +70 -0
  88. package/src/native/copy.ts +296 -0
  89. package/src/native/emoji-data.ts +21 -0
  90. package/src/native/emoji-picker.tsx +229 -0
  91. package/src/native/emoji.ts +118 -0
  92. package/src/native/icon-button.tsx +40 -0
  93. package/src/native/inbox-screen.tsx +116 -0
  94. package/src/native/index.ts +184 -0
  95. package/src/native/link-preview.tsx +104 -0
  96. package/src/native/media-colors.ts +15 -0
  97. package/src/native/media.tsx +187 -0
  98. package/src/native/message-actions-sheet.tsx +121 -0
  99. package/src/native/message-bubble.tsx +374 -0
  100. package/src/native/moderation.tsx +42 -0
  101. package/src/native/modules.ts +275 -0
  102. package/src/native/organise-copy.ts +195 -0
  103. package/src/native/photo-viewer.tsx +531 -0
  104. package/src/native/push.ts +375 -0
  105. package/src/native/recorder-machine.ts +176 -0
  106. package/src/native/rows.ts +81 -0
  107. package/src/native/schedule-sheet.tsx +314 -0
  108. package/src/native/search-screen.tsx +168 -0
  109. package/src/native/stack-options.ts +36 -0
  110. package/src/native/start-sheet.tsx +87 -0
  111. package/src/native/thread-screen.tsx +620 -0
  112. package/src/native/topics.tsx +179 -0
  113. package/src/native/tus.ts +282 -0
  114. package/src/native/use-composer.ts +71 -0
  115. package/src/native/use-jump.ts +91 -0
  116. package/src/native/use-voice-recorder.ts +234 -0
  117. package/src/native/video-player.tsx +370 -0
  118. package/src/native/video-recorder-state.ts +140 -0
  119. package/src/native/video-recorder.tsx +271 -0
  120. package/src/native/video-upload-tray.tsx +77 -0
  121. package/src/native/video-upload.ts +432 -0
  122. package/src/native/voice-player.tsx +283 -0
  123. package/src/react/index.tsx +810 -0
  124. package/src/server/assistant.ts +235 -0
  125. package/src/server/crypto.ts +86 -0
  126. package/src/server/expo.ts +119 -0
  127. package/src/server/handler.ts +32 -0
  128. package/src/server/index.ts +57 -0
  129. package/src/server/moderation.ts +155 -0
  130. package/src/server/mux.ts +290 -0
  131. package/src/server/notifications.ts +130 -0
  132. package/src/server/runner.ts +468 -0
  133. package/src/server/transcribers.ts +111 -0
  134. package/src/server/types.ts +171 -0
  135. package/src/server/unfurl.ts +480 -0
  136. package/src/server/upload.ts +158 -0
  137. package/src/web/attachments.tsx +379 -0
  138. package/src/web/availability.tsx +299 -0
  139. package/src/web/broadcast.tsx +166 -0
  140. package/src/web/bubble.tsx +563 -0
  141. package/src/web/cards.tsx +136 -0
  142. package/src/web/composer.tsx +571 -0
  143. package/src/web/emoji-picker.tsx +84 -0
  144. package/src/web/error-boundary.tsx +33 -0
  145. package/src/web/format.ts +55 -0
  146. package/src/web/inbox.tsx +195 -0
  147. package/src/web/index.ts +75 -0
  148. package/src/web/markdown.tsx +245 -0
  149. package/src/web/memory-client.ts +706 -0
  150. package/src/web/panel.tsx +135 -0
  151. package/src/web/schedule.tsx +192 -0
  152. package/src/web/search.tsx +129 -0
  153. package/src/web/thread-context.ts +64 -0
  154. package/src/web/thread.tsx +802 -0
  155. package/src/web/topics.tsx +160 -0
  156. package/src/web/use-voice-recorder.ts +264 -0
  157. package/src/web/video.tsx +522 -0
  158. package/src/web/voice-note.tsx +197 -0
  159. package/dist/chunk-27UTR5FW.js +0 -322
  160. package/dist/chunk-27UTR5FW.js.map +0 -1
  161. package/dist/chunk-JQXZUEEL.js.map +0 -1
  162. package/dist/chunk-SAY24E6V.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/media.ts","../src/core/client.ts"],"names":["rows"],"mappings":"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","file":"chunk-JQXZUEEL.js","sourcesContent":["/**\n * @feat:chat\n * Media rules shared by every platform: which files may be sent (the same list\n * migration 0001 checks), what kind an upload becomes, the default limits, and\n * the waveform a voice note carries so its bubble draws before the audio loads.\n */\nimport type { AttachmentKind } from \"./types\";\n\n/**\n * A random UUID (v4): `crypto.randomUUID` where the platform has it (some React Native\n * runtimes don't), else `crypto.getRandomValues`, else Math.random as a last resort. Ids\n * only need to be unique per sender: the server checks (sender, client_id).\n */\nexport function randomId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string; getRandomValues?: (a: Uint8Array) => Uint8Array } }).crypto;\n if (c?.randomUUID) return c.randomUUID();\n const b = new Uint8Array(16);\n if (c?.getRandomValues) c.getRandomValues(b);\n else for (let i = 0; i < 16; i++) b[i] = Math.floor(Math.random() * 256);\n b[6] = (b[6]! & 0x0f) | 0x40;\n b[8] = (b[8]! & 0x3f) | 0x80;\n const h = [...b].map((x) => x.toString(16).padStart(2, \"0\")).join(\"\");\n return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;\n}\n\n/** Mirrors genesis_chat.allowed_extension. Never SVG or HTML, which a browser runs as a page. */\nexport const ALLOWED_EXTENSIONS = [\n \"png\", \"jpg\", \"jpeg\", \"webp\", \"gif\", \"heic\", \"heif\",\n \"m4a\", \"aac\", \"mp3\", \"ogg\", \"oga\", \"opus\", \"weba\", \"webm\",\n \"mp4\", \"mov\", \"pdf\", \"txt\", \"csv\", \"docx\", \"xlsx\", \"pptx\",\n] as const;\n\nconst MIME_EXTENSIONS: Record<string, string> = {\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/webp\": \"webp\",\n \"image/gif\": \"gif\",\n \"image/heic\": \"heic\",\n \"image/heif\": \"heif\",\n \"audio/mp4\": \"m4a\",\n \"audio/x-m4a\": \"m4a\",\n \"audio/aac\": \"aac\",\n \"audio/mpeg\": \"mp3\",\n \"audio/ogg\": \"ogg\",\n \"audio/webm\": \"webm\",\n \"video/mp4\": \"mp4\",\n \"video/quicktime\": \"mov\",\n \"video/webm\": \"webm\",\n \"application/pdf\": \"pdf\",\n \"text/plain\": \"txt\",\n \"text/csv\": \"csv\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\": \"docx\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": \"xlsx\",\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\": \"pptx\",\n};\n\n/** The extension a file is stored under: from its content type, else its name. */\nexport function fileExtension(name: string, contentType?: string): string {\n const base = (contentType ?? \"\").split(\";\")[0]!.trim().toLowerCase();\n const fromType = MIME_EXTENSIONS[base];\n if (fromType) return fromType;\n const dot = name.lastIndexOf(\".\");\n return dot >= 0 ? name.slice(dot + 1).toLowerCase() : \"\";\n}\n\nexport function isAllowedExtension(ext: string): boolean {\n return (ALLOWED_EXTENSIONS as readonly string[]).includes(ext.toLowerCase());\n}\n\n/** What an upload becomes in a message. */\nexport function attachmentKindFor(contentType: string, opts: { recordedVoice?: boolean } = {}): AttachmentKind {\n const t = contentType.toLowerCase();\n if (opts.recordedVoice || t.startsWith(\"audio/\")) return \"voice\";\n if (t.startsWith(\"image/\")) return \"image\";\n if (t.startsWith(\"video/\")) return \"video\";\n return \"file\";\n}\n\n/** Default limits (decision 5): an app may lower them, not raise them past the bucket's 100 MB. */\nexport const CHAT_LIMITS = {\n /** Voice notes and videos, for members. */\n recordingMs: 5 * 60_000,\n /** For owners, admins and observers (coaches, staff). */\n staffRecordingMs: 10 * 60_000,\n fileBytes: 50 * 1024 * 1024,\n videoBytes: 100 * 1024 * 1024,\n attachmentsPerMessage: 20,\n bodyChars: 10_000,\n} as const;\n\n/** The longest recording this role may make. */\nexport function recordingLimitMs(role: string | null | undefined): number {\n return role === \"owner\" || role === \"admin\" || role === \"observer\" ? CHAT_LIMITS.staffRecordingMs : CHAT_LIMITS.recordingMs;\n}\n\n/**\n * Peaks for a waveform: `count` values 0–100 from raw samples (-1…1), the loudest\n * in each bucket, scaled so the loudest bucket is 100. Quiet recordings still show\n * a shape; silence shows a flat line.\n */\nexport function waveformPeaks(samples: ArrayLike<number>, count = 48): number[] {\n const n = Math.max(1, Math.min(128, Math.floor(count)));\n if (samples.length === 0) return new Array(n).fill(0);\n const size = samples.length / n;\n const raw: number[] = [];\n for (let i = 0; i < n; i++) {\n let peak = 0;\n const end = Math.min(samples.length, Math.floor((i + 1) * size));\n for (let j = Math.floor(i * size); j < end; j++) {\n const v = Math.abs(samples[j]!);\n if (v > peak) peak = v;\n }\n raw.push(peak);\n }\n const max = Math.max(...raw);\n if (max < 0.01) return raw.map(() => 0);\n return raw.map((v) => Math.round((v / max) * 100));\n}\n\n/**\n * Peaks from a level meter read while recording (expo-audio's `metering`, in dB,\n * about -160…0): resampled to `count` values 0–100.\n */\nexport function waveformFromMetering(levelsDb: number[], count = 48): number[] {\n const linear = levelsDb.map((db) => (Number.isFinite(db) ? Math.pow(10, Math.max(-60, Math.min(0, db)) / 20) : 0));\n return waveformPeaks(linear, count);\n}\n\n/** 0:42, 1:05:09. */\nexport function formatDuration(ms: number | null | undefined): string {\n const total = Math.max(0, Math.round((ms ?? 0) / 1000));\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n return h > 0 ? `${h}:${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}` : `${m}:${String(s).padStart(2, \"0\")}`;\n}\n\n/** Playback speeds offered for voice and video (free for everyone, decision 5). */\nexport const PLAYBACK_RATES = [1, 1.5, 2] as const;\n\nexport function nextPlaybackRate(rate: number): number {\n const i = PLAYBACK_RATES.indexOf(rate as (typeof PLAYBACK_RATES)[number]);\n return PLAYBACK_RATES[(i + 1) % PLAYBACK_RATES.length]!;\n}\n","/**\n * @feat:chat\n * The chat client: the app's own Supabase (migration 0001, the genesis_chat\n * schema) under row level security. Reads are table selects; every write is a\n * genesis_chat function. Live updates are hints on private Realtime topics,\n * after which the client fetches again, so nothing is trusted from the wire.\n */\nimport type { RealtimeChannel, SupabaseClient } from \"@supabase/supabase-js\";\nimport type {\n AttachmentInput,\n ChatActivity,\n ChatAttachment,\n ChatConversation,\n ChatInboxItem,\n ChatKindRules,\n ChatMember,\n ChatMessage,\n ChatRole,\n ChatSignal,\n SendInput,\n} from \"./types\";\nimport { fileExtension, isAllowedExtension, randomId } from \"./media\";\n\n/** Any supabase-js client; the app's generated Database types don't need to list genesis_chat. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ChatSupabase = SupabaseClient<any, any, any>;\n\nexport const CHAT_SCHEMA = \"genesis_chat\";\nexport const CHAT_BUCKET = \"genesis-chat\";\n\nexport const conversationTopic = (conversationId: string) => `genesis-chat:conv:${conversationId}`;\nexport const userTopic = (userId: string) => `genesis-chat:user:${userId}`;\n\n/** A refusal from the database, with its SQLSTATE (`42501` not allowed, `22023` bad input, `GS429` too many). */\nexport class ChatError extends Error {\n constructor(\n message: string,\n readonly code: string | undefined,\n readonly operation: string,\n ) {\n super(message);\n this.name = \"ChatError\";\n }\n get forbidden(): boolean {\n return this.code === \"42501\";\n }\n get rateLimited(): boolean {\n return this.code === \"GS429\";\n }\n /** Worth trying again: the network, not the database, said no. */\n get transient(): boolean {\n return this.code === undefined || this.code === \"\" || /^(08|57|53)/.test(this.code) || this.code === \"PGRST000\";\n }\n}\n\nfunction must<T>(operation: string, result: { data: T | null; error: { message: string; code?: string } | null }): T {\n if (result.error) throw new ChatError(result.error.message, result.error.code, operation);\n return result.data as T;\n}\n\ntype Row = Record<string, unknown>;\nconst str = (v: unknown) => (v == null ? null : String(v));\nconst num = (v: unknown) => (v == null ? null : Number(v));\n\nexport function toAttachment(r: Row): ChatAttachment {\n return {\n id: String(r.id),\n messageId: String(r.message_id),\n position: Number(r.position ?? 0),\n kind: String(r.kind),\n ref: (r.ref as Record<string, unknown>) ?? {},\n provider: (r.provider as ChatAttachment[\"provider\"]) ?? \"storage\",\n path: str(r.path),\n providerId: str(r.provider_id),\n playbackId: str(r.playback_id),\n url: str(r.url),\n status: (r.status as ChatAttachment[\"status\"]) ?? \"ready\",\n name: str(r.name),\n mime: str(r.mime),\n bytes: num(r.bytes),\n width: num(r.width),\n height: num(r.height),\n durationMs: num(r.duration_ms),\n waveform: (r.waveform as number[] | null) ?? null,\n posterPath: str(r.poster_path),\n thumbhash: str(r.thumbhash),\n transcript: str(r.transcript),\n transcriptStatus: (r.transcript_status as ChatAttachment[\"transcriptStatus\"]) ?? null,\n };\n}\n\nexport function toMessage(r: Row): ChatMessage {\n const attachments = ((r.attachments as Row[] | undefined) ?? []).map(toAttachment).sort((a, b) => a.position - b.position);\n const reactions = ((r.reactions as Row[] | undefined) ?? []).map((x) => ({ emoji: String(x.emoji), userId: String(x.user_id) }));\n return {\n id: String(r.id),\n conversationId: String(r.conversation_id),\n seq: Number(r.seq),\n clientId: String(r.client_id),\n senderId: str(r.sender_id),\n senderRole: r.sender_role as ChatMessage[\"senderRole\"],\n kind: (r.kind as ChatMessage[\"kind\"]) ?? \"text\",\n body: String(r.body ?? \"\"),\n mentions: (r.mentions as string[]) ?? [],\n replyToId: str(r.reply_to_id),\n threadRootId: str(r.thread_root_id),\n threadCount: Number(r.thread_count ?? 0),\n threadLastAt: str(r.thread_last_at),\n topic: str(r.topic),\n visibility: (r.visibility as ChatMessage[\"visibility\"]) ?? \"everyone\",\n silent: Boolean(r.silent),\n meta: (r.meta as Record<string, unknown>) ?? {},\n createdAt: String(r.created_at),\n editedAt: str(r.edited_at),\n deletedAt: str(r.deleted_at),\n attachments,\n reactions,\n };\n}\n\nfunction toConversation(r: Row): ChatConversation {\n return {\n id: String(r.id),\n kind: String(r.kind),\n title: str(r.title),\n subjectType: str(r.subject_type),\n subjectId: str(r.subject_id),\n settings: (r.settings as ChatConversation[\"settings\"]) ?? {},\n status: (r.status as ChatConversation[\"status\"]) ?? null,\n assigneeId: str(r.assignee_id),\n lastSeq: Number(r.last_seq ?? 0),\n lastMessageAt: str(r.last_message_at),\n createdAt: String(r.created_at),\n archivedAt: str(r.archived_at),\n };\n}\n\nfunction toInboxItem(r: Row): ChatInboxItem {\n const last = r.last_message as Row | null;\n return {\n conversationId: String(r.conversation_id),\n kind: String(r.kind),\n title: str(r.title),\n subjectType: str(r.subject_type),\n subjectId: str(r.subject_id),\n status: (r.status as ChatInboxItem[\"status\"]) ?? null,\n role: r.role as ChatRole,\n otherUserId: str(r.other_user_id),\n memberCount: Number(r.member_count ?? 0),\n lastSeq: Number(r.last_seq ?? 0),\n lastReadSeq: Number(r.last_read_seq ?? 0),\n unread: Number(r.unread ?? 0),\n mentioned: Boolean(r.mentioned),\n muted: Boolean(r.muted),\n pinned: Boolean(r.pinned),\n archived: Boolean(r.archived),\n lastMessageAt: str(r.last_message_at),\n lastMessage: last\n ? {\n id: String(last.id),\n seq: Number(last.seq),\n senderId: str(last.sender_id),\n kind: (last.kind as \"text\" | \"system\") ?? \"text\",\n body: String(last.body ?? \"\"),\n deleted: Boolean(last.deleted),\n createdAt: String(last.created_at),\n attachment: (last.attachment as string | null) ?? null,\n }\n : null,\n };\n}\n\nconst MESSAGE_COLUMNS = \"*, attachments(*), reactions(emoji, user_id)\";\n\nexport interface MessagePage {\n messages: ChatMessage[];\n /** More, older messages exist before the first one. */\n hasEarlier: boolean;\n}\n\nexport interface ChatClientOptions {\n /** Signed file links live this long (seconds). Default an hour. */\n signedUrlSeconds?: number;\n}\n\nexport interface Subscription {\n unsubscribe(): void;\n}\n\nexport interface ConversationChannel extends Subscription {\n /** Tell the others you are typing or recording (throttle to once every 3 seconds). */\n signal(activity: ChatActivity[\"activity\"]): void;\n}\n\nexport function createChatClient(supabase: ChatSupabase, options: ChatClientOptions = {}) {\n const db = () => supabase.schema(CHAT_SCHEMA);\n const signedUrlSeconds = options.signedUrlSeconds ?? 3600;\n const signedCache = new Map<string, { url: string; until: number }>();\n\n /**\n * Private Realtime channels authorise with the signed-in user's token; set it before\n * joining (supabase-js doesn't for a channel joined before the session loads), or the\n * join is refused and no hint ever arrives. A refusal to set it still joins and retries.\n */\n const unsubscribed = new WeakSet<RealtimeChannel>();\n function join(channel: RealtimeChannel, onStatus?: (status: string) => void) {\n const realtime = (supabase as unknown as { realtime?: { setAuth?: (token?: string | null) => Promise<void> | void } }).realtime;\n void Promise.resolve(realtime?.setAuth?.())\n .catch(() => undefined)\n .then(() => {\n if (!unsubscribed.has(channel)) channel.subscribe(onStatus);\n });\n return () => {\n unsubscribed.add(channel);\n void supabase.removeChannel(channel);\n };\n }\n\n async function rpc<T>(fn: string, args: Record<string, unknown>): Promise<T> {\n return must<T>(fn, await db().rpc(fn, args));\n }\n\n return {\n supabase,\n\n async inbox(opts: { kind?: string; archived?: boolean; limit?: number; before?: string } = {}): Promise<ChatInboxItem[]> {\n const rows = await rpc<Row[]>(\"inbox\", {\n p_kind: opts.kind ?? null,\n p_archived: opts.archived ?? false,\n p_limit: opts.limit ?? 50,\n p_before: opts.before ?? null,\n });\n return rows.map(toInboxItem);\n },\n\n async observed(kind: string, opts: { status?: string; limit?: number; before?: string } = {}) {\n return rpc<Row[]>(\"observed\", { p_kind: kind, p_status: opts.status ?? null, p_limit: opts.limit ?? 50, p_before: opts.before ?? null });\n },\n\n async unreadTotal(): Promise<number> {\n return rpc<number>(\"unread_total\", {});\n },\n\n async conversation(id: string): Promise<ChatConversation | null> {\n const row = must(\"conversation\", await db().from(\"conversations\").select(\"*\").eq(\"id\", id).maybeSingle());\n return row ? toConversation(row as Row) : null;\n },\n\n /** A kind's rules (how many members, who posts, threads), for what the UI offers. */\n async kind(kind: string): Promise<ChatKindRules | null> {\n const row = must(\"kind\", await db().from(\"kinds\").select(\"kind, label, max_members, who_posts, membership, threads, observers_post\").eq(\"kind\", kind).maybeSingle()) as Row | null;\n return row\n ? {\n kind: String(row.kind),\n label: String(row.label),\n maxMembers: row.max_members == null ? null : Number(row.max_members),\n whoPosts: row.who_posts as ChatKindRules[\"whoPosts\"],\n membership: row.membership as ChatKindRules[\"membership\"],\n threads: Boolean(row.threads),\n observersPost: Boolean(row.observers_post),\n }\n : null;\n },\n\n async myRole(id: string): Promise<ChatRole | null> {\n return rpc<ChatRole | null>(\"my_role\", { p_conversation_id: id });\n },\n\n async canPost(id: string): Promise<boolean> {\n return rpc<boolean>(\"can_post\", { p_conversation_id: id });\n },\n\n async members(id: string): Promise<ChatMember[]> {\n const rows = must<Row[]>(\n \"members\",\n await db().from(\"members\").select(\"*\").eq(\"conversation_id\", id).is(\"left_at\", null).neq(\"role\", \"observer\"),\n );\n return rows.map((r) => ({\n conversationId: String(r.conversation_id),\n userId: String(r.user_id),\n role: r.role as ChatRole,\n lastReadSeq: Number(r.last_read_seq ?? 0),\n joinedAt: String(r.joined_at),\n }));\n },\n\n /**\n * A page of messages, oldest first: the latest `limit` (default 50), or those\n * before `beforeSeq`, or (to catch up after a reconnect) those after `afterSeq`.\n * A thread's replies with `threadRootId`; one topic's with `topic`.\n */\n async messages(\n conversationId: string,\n opts: { beforeSeq?: number; afterSeq?: number; limit?: number; threadRootId?: string; topic?: string } = {},\n ): Promise<MessagePage> {\n const limit = Math.min(Math.max(opts.limit ?? 50, 1), 200);\n let q = db().from(\"messages\").select(MESSAGE_COLUMNS).eq(\"conversation_id\", conversationId);\n q = opts.threadRootId ? q.eq(\"thread_root_id\", opts.threadRootId) : q.is(\"thread_root_id\", null);\n if (opts.topic) q = q.eq(\"topic\", opts.topic);\n if (opts.afterSeq != null) {\n const rows = must<Row[]>(\"messages\", await q.gt(\"seq\", opts.afterSeq).order(\"seq\", { ascending: true }).limit(limit));\n return { messages: rows.map(toMessage), hasEarlier: false };\n }\n if (opts.beforeSeq != null) q = q.lt(\"seq\", opts.beforeSeq);\n const rows = must<Row[]>(\"messages\", await q.order(\"seq\", { ascending: false }).limit(limit + 1));\n const hasEarlier = rows.length > limit;\n return { messages: rows.slice(0, limit).map(toMessage).reverse(), hasEarlier };\n },\n\n async message(id: string): Promise<ChatMessage | null> {\n const row = must(\"message\", await db().from(\"messages\").select(MESSAGE_COLUMNS).eq(\"id\", id).maybeSingle());\n return row ? toMessage(row as Row) : null;\n },\n\n async startConversation(kind: string, memberIds: string[], opts: { title?: string; subjectType?: string; subjectId?: string } = {}) {\n return rpc<string>(\"start_conversation\", {\n p_kind: kind,\n p_member_ids: memberIds,\n p_title: opts.title ?? null,\n p_subject_type: opts.subjectType ?? null,\n p_subject_id: opts.subjectId ?? null,\n });\n },\n\n /** Sends a message. Safe to retry with the same clientId. */\n async send(input: SendInput): Promise<ChatMessage> {\n const row = await rpc<Row>(\"send_message\", {\n p_conversation_id: input.conversationId,\n p_client_id: input.clientId,\n p_body: input.body ?? \"\",\n p_attachments: (input.attachments ?? []).map(attachmentArg),\n p_reply_to_id: input.replyToId ?? null,\n p_thread_root_id: input.threadRootId ?? null,\n p_topic: input.topic ?? null,\n p_mentions: input.mentions ?? [],\n p_visibility: input.visibility ?? \"everyone\",\n p_silent: input.silent ?? false,\n });\n // The function returns the message row; fetch it again for its attachments.\n return (await this.message(String(row.id))) ?? toMessage(row);\n },\n\n async edit(messageId: string, body: string, mentions: string[] = []) {\n return toMessage(await rpc<Row>(\"edit_message\", { p_message_id: messageId, p_body: body, p_mentions: mentions }));\n },\n\n async remove(messageId: string) {\n await rpc(\"delete_message\", { p_message_id: messageId });\n },\n\n async react(messageId: string, emoji: string, on = true) {\n await rpc(\"react\", { p_message_id: messageId, p_emoji: emoji, p_on: on });\n },\n\n async markRead(conversationId: string, seq?: number) {\n return rpc<number>(\"mark_read\", { p_conversation_id: conversationId, p_seq: seq ?? null });\n },\n\n async setMySettings(\n conversationId: string,\n s: { mutedUntil?: string | null; notify?: \"all\" | \"mentions\" | \"none\"; archived?: boolean; pinned?: boolean },\n ) {\n await rpc(\"set_my_settings\", {\n p_conversation_id: conversationId,\n p_muted_until: s.mutedUntil ?? null,\n p_notify: s.notify ?? null,\n p_archived: s.archived ?? null,\n p_pinned: s.pinned ?? null,\n p_clear_mute: s.mutedUntil === null,\n });\n },\n\n async updateConversation(conversationId: string, s: { title?: string; settings?: Record<string, unknown> }) {\n await rpc(\"update_conversation\", { p_conversation_id: conversationId, p_title: s.title ?? null, p_settings: s.settings ?? null });\n },\n\n async addMembers(conversationId: string, userIds: string[]) {\n await rpc(\"add_members\", { p_conversation_id: conversationId, p_user_ids: userIds });\n },\n\n async removeMember(conversationId: string, userId?: string) {\n await rpc(\"remove_member\", { p_conversation_id: conversationId, p_user_id: userId ?? null });\n },\n\n async setStatus(conversationId: string, status: ChatConversation[\"status\"], assigneeId?: string | null) {\n await rpc(\"set_status\", { p_conversation_id: conversationId, p_status: status, p_assignee_id: assigneeId ?? null });\n },\n\n async pin(messageId: string, on = true) {\n await rpc(\"pin_message\", { p_message_id: messageId, p_on: on });\n },\n\n async pins(conversationId: string): Promise<string[]> {\n const rows = must<Row[]>(\"pins\", await db().from(\"pins\").select(\"message_id\").eq(\"conversation_id\", conversationId));\n return rows.map((r) => String(r.message_id));\n },\n\n async save(messageId: string, on = true, note?: string) {\n await rpc(\"save_message\", { p_message_id: messageId, p_on: on, p_note: note ?? null });\n },\n\n async report(messageId: string, reason: \"spam\" | \"harassment\" | \"safety\" | \"other\", note?: string) {\n return rpc<string>(\"report_message\", { p_message_id: messageId, p_reason: reason, p_note: note ?? null });\n },\n\n /**\n * Uploads a file into the conversation's folder for the signed-in person and\n * returns its path, ready to attach. Resumable for big files is the native\n * renderer's job (Supabase TUS); this is the plain upload.\n */\n async upload(conversationId: string, userId: string, file: Blob | ArrayBuffer, opts: { name: string; contentType: string; id?: string }) {\n const ext = fileExtension(opts.name, opts.contentType);\n if (!isAllowedExtension(ext)) throw new ChatError(`Files of type .${ext} can't be sent`, \"22023\", \"upload\");\n const id = opts.id ?? randomId();\n const path = `${conversationId}/${userId}/${id}.${ext}`;\n must(\"upload\", await supabase.storage.from(CHAT_BUCKET).upload(path, file, { contentType: opts.contentType, upsert: false }));\n return path;\n },\n\n /** Signed links for files, cached until shortly before they expire. */\n async fileUrls(paths: string[]): Promise<Record<string, string>> {\n const now = Date.now();\n const out: Record<string, string> = {};\n const missing: string[] = [];\n for (const p of new Set(paths)) {\n const hit = signedCache.get(p);\n if (hit && hit.until > now) out[p] = hit.url;\n else missing.push(p);\n }\n if (missing.length) {\n const { data, error } = await supabase.storage.from(CHAT_BUCKET).createSignedUrls(missing, signedUrlSeconds);\n if (error) throw new ChatError(error.message, undefined, \"fileUrls\");\n for (const d of data ?? []) {\n if (d.signedUrl && d.path) {\n out[d.path] = d.signedUrl;\n signedCache.set(d.path, { url: d.signedUrl, until: now + (signedUrlSeconds - 60) * 1000 });\n }\n }\n }\n return out;\n },\n\n /** Your inbox's live hints (a new message anywhere you are, a membership change). */\n subscribeInbox(userId: string, onSignal: (s: ChatSignal) => void): Subscription {\n const channel = supabase\n .channel(userTopic(userId), { config: { private: true } })\n .on(\"broadcast\", { event: \"inbox\" }, ({ payload }) =>\n onSignal({ type: \"inbox\", conversationId: String(payload?.conversation_id), seq: payload?.seq }),\n );\n return { unsubscribe: join(channel) };\n },\n\n /**\n * A conversation's live hints, plus who is typing or recording. `onReconnect`\n * runs whenever the channel (re)joins, the moment to fetch what was missed.\n */\n subscribeConversation(\n conversationId: string,\n me: string,\n handlers: { onSignal: (s: ChatSignal) => void; onActivity?: (a: ChatActivity) => void; onReconnect?: () => void },\n ): ConversationChannel {\n let joinedOnce = false;\n const channel: RealtimeChannel = supabase\n .channel(conversationTopic(conversationId), { config: { private: true, broadcast: { self: false } } })\n .on(\"broadcast\", { event: \"message\" }, ({ payload }) =>\n handlers.onSignal({ type: \"message\", conversationId, id: String(payload?.id), seq: payload?.seq, op: payload?.op ?? \"insert\" }),\n )\n .on(\"broadcast\", { event: \"reaction\" }, ({ payload }) =>\n handlers.onSignal({ type: \"reaction\", conversationId, messageId: String(payload?.message_id) }),\n )\n .on(\"broadcast\", { event: \"members\" }, () => handlers.onSignal({ type: \"members\", conversationId }))\n .on(\"broadcast\", { event: \"conversation\" }, () => handlers.onSignal({ type: \"conversation\", conversationId }))\n .on(\"broadcast\", { event: \"activity\" }, ({ payload }) => {\n if (payload?.userId && payload.userId !== me) handlers.onActivity?.({ userId: payload.userId, activity: payload.activity, at: Date.now() });\n });\n const leave = join(channel, (status) => {\n if (status === \"SUBSCRIBED\") {\n if (joinedOnce) handlers.onReconnect?.();\n joinedOnce = true;\n }\n });\n return {\n signal(activity) {\n void channel.send({ type: \"broadcast\", event: \"activity\", payload: { userId: me, activity } });\n },\n unsubscribe: leave,\n };\n },\n };\n}\n\nexport type ChatClient = ReturnType<typeof createChatClient>;\n\nfunction attachmentArg(a: AttachmentInput) {\n return {\n kind: a.kind,\n path: a.path,\n provider: a.provider,\n provider_id: a.providerId,\n url: a.url,\n ref: a.ref,\n status: a.status,\n name: a.name,\n mime: a.mime,\n bytes: a.bytes,\n width: a.width,\n height: a.height,\n duration_ms: a.durationMs,\n waveform: a.waveform,\n poster_path: a.posterPath,\n thumbhash: a.thumbhash,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/thread.ts","../src/core/outbox.ts"],"names":[],"mappings":"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","file":"chunk-SAY24E6V.js","sourcesContent":["/**\n * @feat:chat\n * Pure thread logic, the same on every platform: merging the server's messages\n * with ones still on their way, grouping a run of messages from one sender,\n * day dividers, the unread line, reactions by emoji, and the typing line.\n */\nimport type { ChatActivity, ChatMessage, PendingMessage } from \"./types\";\n\nexport type ThreadItem =\n | { type: \"message\"; message: ChatMessage; pending?: undefined }\n | { type: \"pending\"; pending: PendingMessage; message?: undefined };\n\n/**\n * The server's messages (by seq), then what is still sending, oldest first. A\n * pending message the server already has (same clientId) is dropped, so a send\n * that landed never shows twice.\n */\nexport function mergeThread(server: ChatMessage[], pending: PendingMessage[]): ThreadItem[] {\n const byId = new Map<string, ChatMessage>();\n for (const m of server) byId.set(m.id, m);\n const sorted = [...byId.values()].sort((a, b) => a.seq - b.seq);\n const landed = new Set(sorted.map((m) => m.clientId));\n const waiting = pending\n .filter((p) => !landed.has(p.clientId))\n .sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n return [\n ...sorted.map((message) => ({ type: \"message\" as const, message })),\n ...waiting.map((p) => ({ type: \"pending\" as const, pending: p })),\n ];\n}\n\n/** Adds or replaces messages in a page, keeping it sorted and free of duplicates. */\nexport function upsertMessages(existing: ChatMessage[], incoming: ChatMessage[]): ChatMessage[] {\n const byId = new Map(existing.map((m) => [m.id, m]));\n for (const m of incoming) byId.set(m.id, m);\n return [...byId.values()].sort((a, b) => a.seq - b.seq);\n}\n\nexport function itemSender(item: ThreadItem): string | null {\n return item.type === \"message\" ? item.message.senderId : item.pending.senderId;\n}\n\nexport function itemTime(item: ThreadItem): string {\n return item.type === \"message\" ? item.message.createdAt : item.pending.createdAt;\n}\n\n/** Runs of one sender within five minutes share a header (name, avatar). */\nexport function startsGroup(items: ThreadItem[], index: number, gapMs = 5 * 60_000): boolean {\n if (index === 0) return true;\n const prev = items[index - 1]!;\n const cur = items[index]!;\n if (cur.type === \"message\" && cur.message.kind === \"system\") return true;\n if (prev.type === \"message\" && prev.message.kind === \"system\") return true;\n if (itemSender(prev) !== itemSender(cur)) return true;\n return Date.parse(itemTime(cur)) - Date.parse(itemTime(prev)) > gapMs || !sameDay(itemTime(prev), itemTime(cur));\n}\n\nexport function sameDay(a: string, b: string): boolean {\n const x = new Date(a);\n const y = new Date(b);\n return x.getFullYear() === y.getFullYear() && x.getMonth() === y.getMonth() && x.getDate() === y.getDate();\n}\n\n/** A day divider goes before this item. */\nexport function startsDay(items: ThreadItem[], index: number): boolean {\n return index === 0 || !sameDay(itemTime(items[index - 1]!), itemTime(items[index]!));\n}\n\n/** \"Today\", \"Yesterday\", \"Monday\", or \"12 Mar 2026\". */\nexport function dayLabel(iso: string, now = new Date(), locale?: string): string {\n const d = new Date(iso);\n const startOf = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const days = Math.round((startOf(now) - startOf(d)) / 86_400_000);\n if (days === 0) return \"Today\";\n if (days === 1) return \"Yesterday\";\n if (days > 1 && days < 7) return d.toLocaleDateString(locale, { weekday: \"long\" });\n return d.toLocaleDateString(locale, { day: \"numeric\", month: \"short\", year: d.getFullYear() === now.getFullYear() ? undefined : \"numeric\" });\n}\n\n/** The first message after what you had read, from someone else: where \"New\" goes. */\nexport function firstUnreadId(messages: ChatMessage[], lastReadSeq: number, me: string): string | null {\n return messages.find((m) => m.seq > lastReadSeq && m.senderId !== me && !m.deletedAt)?.id ?? null;\n}\n\nexport interface ReactionSummary {\n emoji: string;\n count: number;\n mine: boolean;\n userIds: string[];\n}\n\n/** Reactions by emoji, most first, then in first-used order. */\nexport function summarizeReactions(message: ChatMessage, me: string): ReactionSummary[] {\n const order: string[] = [];\n const by = new Map<string, string[]>();\n for (const r of message.reactions) {\n if (!by.has(r.emoji)) {\n by.set(r.emoji, []);\n order.push(r.emoji);\n }\n by.get(r.emoji)!.push(r.userId);\n }\n return order\n .map((emoji) => ({ emoji, count: by.get(emoji)!.length, mine: by.get(emoji)!.includes(me), userIds: by.get(emoji)! }))\n .sort((a, b) => b.count - a.count || order.indexOf(a.emoji) - order.indexOf(b.emoji));\n}\n\n/** Who is doing what now: activity older than six seconds has stopped. */\nexport function currentActivity(activity: ChatActivity[], now = Date.now(), staleMs = 6000): ChatActivity[] {\n const latest = new Map<string, ChatActivity>();\n for (const a of activity) {\n if (now - a.at > staleMs) continue;\n const prev = latest.get(a.userId);\n if (!prev || prev.at < a.at) latest.set(a.userId, a);\n }\n return [...latest.values()];\n}\n\n/** \"Sam is typing…\", \"Sam and Lee are typing…\", \"Sam is recording a voice message…\". */\nexport function activityLine(activity: ChatActivity[], nameOf: (userId: string) => string): string | null {\n if (activity.length === 0) return null;\n const recording = activity.find((a) => a.activity !== \"typing\");\n if (recording) {\n return `${nameOf(recording.userId)} is recording ${recording.activity === \"recording-video\" ? \"a video\" : \"a voice message\"}…`;\n }\n const names = activity.map((a) => nameOf(a.userId));\n if (names.length === 1) return `${names[0]} is typing…`;\n if (names.length === 2) return `${names[0]} and ${names[1]} are typing…`;\n return \"Several people are typing…\";\n}\n\n/** Sends activity at most once every `everyMs`. */\nexport function throttle(fn: () => void, everyMs = 3000): () => void {\n let last = 0;\n return () => {\n const now = Date.now();\n if (now - last >= everyMs) {\n last = now;\n fn();\n }\n };\n}\n\n/** The ids @mentioned in markdown written as `@[Name](user:<uuid>)`. */\nexport function parseMentions(body: string): string[] {\n const ids = new Set<string>();\n for (const m of body.matchAll(/@\\[[^\\]]{1,80}\\]\\(user:([0-9a-f-]{36})\\)/gi)) ids.add(m[1]!.toLowerCase());\n return [...ids];\n}\n\n/** A one-line preview: text, or what was attached. */\nexport function previewText(body: string, attachment: string | null | undefined, deleted = false): string {\n if (deleted) return \"Message deleted\";\n const text = body.replace(/@\\[([^\\]]+)\\]\\(user:[0-9a-f-]{36}\\)/gi, \"@$1\").replace(/[*_`#>~]/g, \"\").trim();\n if (text) return text.length > 140 ? `${text.slice(0, 139)}…` : text;\n switch (attachment) {\n case \"image\":\n return \"Photo\";\n case \"voice\":\n return \"Voice message\";\n case \"video\":\n return \"Video\";\n case \"file\":\n return \"File\";\n case null:\n case undefined:\n return \"\";\n default:\n return \"Attachment\";\n }\n}\n","/**\n * @feat:chat\n * The send queue: a message shows at once as pending, its files upload, then it\n * is sent with the clientId made when it was written, so a retry (after a lost\n * connection, a closed app) never posts twice. Messages to one conversation go\n * in the order they were written. Storage is the platform's (memory by default;\n * localStorage on web, MMKV or SQLite on native), behind OutboxStore.\n */\nimport type { ChatClient } from \"./client\";\nimport { ChatError } from \"./client\";\nimport { attachmentKindFor, randomId } from \"./media\";\nimport type { AttachmentInput, ChatMessage, PendingFile, PendingMessage, SendInput } from \"./types\";\n\n/** A file still on the device, uploaded when its message is sent. */\nexport interface LocalFile {\n /** The bytes, or (native) a file URI the platform reads in `readFile`. */\n data: Blob | ArrayBuffer | string;\n name: string;\n contentType: string;\n /** A preview to show while it uploads (an object URL, a file URI). */\n previewUrl?: string;\n /** Known up front: a voice note's duration and waveform, a photo's size. */\n meta?: Partial<Omit<AttachmentInput, \"path\" | \"kind\">> & { kind?: AttachmentInput[\"kind\"] };\n}\n\nexport interface QueuedMessage extends Omit<PendingMessage, \"files\"> {\n files: LocalFile[];\n /** What each file is, kept with the saved copy (PendingMessage.files). */\n pendingFiles?: PendingFile[];\n /** Files lost on a relaunch (bytes that weren't persisted). */\n lostFiles?: number;\n attempts: number;\n}\n\nfunction describe(f: LocalFile): PendingFile {\n return { name: f.name, contentType: f.contentType, kind: f.meta?.kind ?? attachmentKindFor(f.contentType), meta: f.meta };\n}\n\nexport interface OutboxStore {\n load(): Promise<QueuedMessage[]>;\n save(queue: QueuedMessage[]): Promise<void>;\n}\n\nexport const memoryOutboxStore = (): OutboxStore => {\n let saved: QueuedMessage[] = [];\n return { load: async () => saved, save: async (q) => void (saved = q) };\n};\n\nexport interface OutboxOptions {\n client: ChatClient;\n userId: string;\n store?: OutboxStore;\n /** Reads a native file URI into bytes for upload. */\n readFile?: (uri: string) => Promise<Blob | ArrayBuffer>;\n /** Upload hook, e.g. resumable uploads on native. Defaults to client.upload. */\n upload?: (conversationId: string, file: LocalFile) => Promise<string>;\n /** Called with every change, for the UI. */\n onChange?: (queue: QueuedMessage[]) => void;\n /** Called when a message lands. */\n onSent?: (message: ChatMessage, clientId: string) => void;\n /** Makes client ids. Default: a random UUID (works where crypto.randomUUID is missing). */\n newId?: () => string;\n /**\n * Keeps a file held as bytes (a pasted image, a recording) between launches: write it\n * somewhere and return a URI `readFile` can read (native: the app's cache directory).\n * Without it, such a file isn't saved, and after a relaunch its message asks for it again.\n */\n persistFile?: (file: LocalFile) => Promise<string>;\n}\n\n\nexport function createOutbox(opts: OutboxOptions) {\n const store = opts.store ?? memoryOutboxStore();\n let queue: QueuedMessage[] = [];\n let loaded = false;\n const running = new Set<string>();\n const uploaded = new Map<string, string>(); // clientId:index -> path\n\n const newId = opts.newId ?? randomId;\n\n // Saved copies: a file held as bytes is kept only as a URI (persistFile) or marked lost.\n const saveable = (q: QueuedMessage): QueuedMessage => ({\n ...q,\n files: q.files.filter((f) => typeof f.data === \"string\"),\n pendingFiles: q.files.map((f) => ({ ...describe(f), lost: typeof f.data !== \"string\" })),\n });\n\n const emit = () => {\n opts.onChange?.([...queue]);\n void store.save(queue.map(saveable));\n };\n\n /** Swaps a byte file for a saved URI, so it survives a relaunch. */\n async function persist(q: QueuedMessage) {\n if (!opts.persistFile) return;\n for (let i = 0; i < q.files.length; i++) {\n const f = q.files[i]!;\n if (typeof f.data === \"string\") continue;\n try {\n q.files[i] = { ...f, data: await opts.persistFile(f) };\n } catch {\n // Kept in memory only; a relaunch asks for it again.\n }\n }\n }\n\n async function ensureLoaded() {\n if (loaded) return;\n loaded = true;\n const saved = await store.load();\n // A file held as bytes that wasn't persisted doesn't survive a relaunch: its message waits,\n // failed, for the file to be attached again (never sent without it) or discarded.\n queue = saved.map((q) => {\n const lost = (q.pendingFiles ?? []).filter((f) => f.lost).length;\n return {\n ...q,\n status: q.status === \"sending\" || lost > 0 ? \"failed\" : q.status,\n error: lost > 0 ? \"Attach the file again to send\" : (q.error ?? \"Not sent\"),\n files: q.files ?? [],\n attempts: q.attempts ?? 0,\n lostFiles: lost,\n };\n });\n if (queue.length) opts.onChange?.([...queue]);\n }\n\n async function uploadFile(conversationId: string, file: LocalFile): Promise<string> {\n if (opts.upload) return opts.upload(conversationId, file);\n const data = typeof file.data === \"string\" ? await (opts.readFile ?? notReadable)(file.data) : file.data;\n return opts.client.upload(conversationId, opts.userId, data, { name: file.name, contentType: file.contentType });\n }\n\n async function run(conversationId: string) {\n if (running.has(conversationId)) return;\n running.add(conversationId);\n try {\n for (;;) {\n const next = queue.find((q) => q.input.conversationId === conversationId && q.status === \"sending\");\n if (!next) break;\n if ((next.lostFiles ?? 0) > 0) {\n next.status = \"failed\";\n next.error = \"Attach the file again to send\";\n emit();\n break;\n }\n try {\n const attachments: AttachmentInput[] = [...(next.input.attachments ?? [])];\n for (let i = 0; i < next.files.length; i++) {\n const file = next.files[i]!;\n const key = `${next.clientId}:${i}`;\n let path = uploaded.get(key);\n if (!path) {\n path = await uploadFile(conversationId, file);\n uploaded.set(key, path);\n }\n attachments.push({\n ...file.meta,\n kind: file.meta?.kind ?? attachmentKindFor(file.contentType),\n path,\n name: file.meta?.name ?? file.name,\n mime: file.contentType,\n });\n }\n const message = await opts.client.send({ ...next.input, attachments });\n queue = queue.filter((q) => q.clientId !== next.clientId);\n for (let i = 0; i < next.files.length; i++) uploaded.delete(`${next.clientId}:${i}`);\n emit();\n opts.onSent?.(message, next.clientId);\n } catch (e) {\n const err = e instanceof ChatError ? e : new ChatError(e instanceof Error ? e.message : String(e), undefined, \"send\");\n next.attempts += 1;\n next.status = \"failed\";\n next.error = err.forbidden ? \"You can't post here\" : err.transient ? \"Not sent. Check your connection.\" : err.message;\n emit();\n // Later messages to this conversation wait behind a failed one, so order holds.\n break;\n }\n }\n } finally {\n running.delete(conversationId);\n }\n }\n\n return {\n /** Queues a message; it shows at once and sends in order. Returns its clientId. */\n async send(input: Omit<SendInput, \"clientId\"> & { clientId?: string }, files: LocalFile[] = []): Promise<string> {\n await ensureLoaded();\n const clientId = input.clientId ?? newId();\n const previews: Record<number, string> = {};\n files.forEach((f, i) => {\n if (f.previewUrl) previews[i] = f.previewUrl;\n });\n const queued: QueuedMessage = {\n clientId,\n input: { ...input, clientId },\n senderId: opts.userId,\n createdAt: new Date().toISOString(),\n status: \"sending\",\n previews,\n files: [...files],\n pendingFiles: files.map(describe),\n attempts: 0,\n };\n queue.push(queued);\n opts.onChange?.([...queue]);\n await persist(queued);\n emit();\n void run(input.conversationId);\n return clientId;\n },\n\n async retry(clientId: string) {\n await ensureLoaded();\n const q = queue.find((x) => x.clientId === clientId);\n if (!q) return;\n // Retrying one retries everything behind it in that conversation.\n for (const x of queue) if (x.input.conversationId === q.input.conversationId && x.status === \"failed\") x.status = \"sending\";\n emit();\n void run(q.input.conversationId);\n },\n\n /** Gives a message whose files were lost on a relaunch its files again, and sends it. */\n async reattach(clientId: string, files: LocalFile[]) {\n await ensureLoaded();\n const q = queue.find((x) => x.clientId === clientId);\n if (!q) return;\n q.files = [...files];\n q.pendingFiles = files.map(describe);\n q.lostFiles = 0;\n await persist(q);\n q.status = \"sending\";\n emit();\n void run(q.input.conversationId);\n },\n\n /** Retries every failed message (after the connection comes back). */\n async retryAll() {\n await ensureLoaded();\n const conversations = new Set<string>();\n for (const x of queue) {\n if (x.status === \"failed\" && !(x.lostFiles ?? 0) && x.files.every((f) => typeof f.data !== \"string\" || opts.readFile || opts.upload)) {\n x.status = \"sending\";\n conversations.add(x.input.conversationId);\n }\n }\n emit();\n for (const c of conversations) void run(c);\n },\n\n async discard(clientId: string) {\n await ensureLoaded();\n queue = queue.filter((q) => q.clientId !== clientId);\n emit();\n },\n\n pending(conversationId?: string): PendingMessage[] {\n return queue\n .filter((q) => !conversationId || q.input.conversationId === conversationId)\n .map((q) => ({ ...q, files: q.pendingFiles }));\n },\n\n /** A new client id, made the way this outbox makes them. */\n newId,\n\n load: ensureLoaded,\n };\n}\n\nexport type Outbox = ReturnType<typeof createOutbox>;\n\nasync function notReadable(): Promise<never> {\n throw new ChatError(\"This file can't be read on this device\", \"22023\", \"upload\");\n}\n"]}