@liveblocks/chat-sdk-adapter 0.0.0 → 3.16.0-flow2
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/README.md +57 -0
- package/dist/index.cjs +972 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +67 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +972 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts"],"sourcesContent":["import {\n type Awaitable,\n type BaseGroupInfo,\n type BaseUserMeta,\n type CommentBody,\n type CommentBodyInlineElement,\n type CommentBodyParagraph,\n getMentionsFromCommentBody,\n isCommentBodyLink,\n isCommentBodyMention,\n isCommentBodyText,\n type ResolveGroupsInfoArgs,\n type ResolveUsersArgs,\n} from \"@liveblocks/core\";\nimport {\n type CommentData,\n Liveblocks,\n LiveblocksError,\n type WebhookEvent,\n WebhookHandler,\n} from \"@liveblocks/node\";\nimport {\n type Adapter,\n type AdapterPostableMessage,\n type Attachment,\n type CardChild,\n type CardElement,\n type ChannelInfo,\n type ChatInstance,\n ConsoleLogger,\n defaultEmojiResolver,\n type EmojiValue,\n type FetchOptions,\n type FetchResult,\n type FormattedContent,\n type Link,\n type ListThreadsOptions,\n type ListThreadsResult,\n type Logger,\n Message,\n type Paragraph,\n parseMarkdown,\n type RawMessage,\n type Root,\n tableToAscii,\n type Text,\n type ThreadInfo,\n toPlainText,\n type WebhookOptions,\n type Delete,\n type Emphasis,\n type InlineCode,\n type Strong,\n} from \"chat\";\n\ntype PhrasingContent = Paragraph[\"children\"][number];\n\nconst ADAPTER_PREFIX = \"liveblocks\";\nexport class LiveblocksAdapter<\n U extends BaseUserMeta = BaseUserMeta,\n DGI extends BaseGroupInfo = BaseGroupInfo,\n> implements Adapter<{ roomId: string; threadId: string }, CommentData>\n{\n readonly name = \"liveblocks\";\n readonly userName: string;\n readonly #client: Liveblocks;\n readonly #webhookHandler: WebhookHandler;\n readonly #resolveUsers:\n | ((\n args: ResolveUsersArgs\n ) => Awaitable<(U[\"info\"] | undefined)[] | undefined>)\n | undefined;\n readonly #resolveGroupsInfo:\n | ((\n args: ResolveGroupsInfoArgs\n ) => Awaitable<(DGI | undefined)[] | undefined>)\n | undefined;\n readonly #logger: Logger;\n readonly #botUserId: string;\n #chat: ChatInstance | null = null;\n constructor(config: LiveblocksAdapterConfig<U, DGI>) {\n this.#client = new Liveblocks({ secret: config.apiKey });\n this.#webhookHandler = new WebhookHandler(config.webhookSecret);\n this.#resolveUsers = config.resolveUsers;\n this.#resolveGroupsInfo = config.resolveGroupsInfo;\n this.#botUserId = config.botUserId;\n this.userName = config.botUserName ?? \"liveblocks-bot\";\n this.#logger =\n config.logger ?? new ConsoleLogger(\"info\").child(ADAPTER_PREFIX);\n }\n\n async initialize(chat: ChatInstance): Promise<void> {\n this.#chat = chat;\n }\n\n async handleWebhook(\n request: Request,\n options?: WebhookOptions\n ): Promise<Response> {\n let event: WebhookEvent;\n try {\n event = this.#webhookHandler.verifyRequest({\n headers: request.headers,\n rawBody: await request.text(),\n });\n } catch (error) {\n this.#logger.error(\"Failed to verify webhook request\", { error });\n return new Response(\"Invalid webhook request\", { status: 401 });\n }\n\n if (event.type === \"commentCreated\") {\n const threadId = this.encodeThreadId({\n roomId: event.data.roomId,\n threadId: event.data.threadId,\n });\n\n const comment = await this.#client.getComment({\n roomId: event.data.roomId,\n threadId: event.data.threadId,\n commentId: event.data.commentId,\n });\n if (comment.deletedAt !== undefined) {\n return new Response(null, { status: 200 });\n }\n\n this.#chat?.processMessage(\n this,\n threadId,\n () => this.#convertLiveblocksCommentDataToChatMessage(comment),\n options\n );\n } else if (\n event.type === \"commentReactionAdded\" ||\n event.type === \"commentReactionRemoved\"\n ) {\n const threadId = this.encodeThreadId({\n roomId: event.data.roomId,\n threadId: event.data.threadId,\n });\n\n const userId =\n event.type === \"commentReactionAdded\"\n ? event.data.addedBy\n : event.data.removedBy;\n\n const resolvedUsers = await this.#resolveUsers?.({ userIds: [userId] });\n const user = resolvedUsers?.[0];\n\n this.#chat?.processReaction(\n {\n added: event.type === \"commentReactionAdded\",\n emoji: defaultEmojiResolver.fromGChat(event.data.emoji),\n rawEmoji: event.data.emoji,\n messageId: event.data.commentId,\n threadId,\n user: {\n userId,\n userName: user?.name ?? userId,\n fullName: user?.name ?? userId,\n // This assumes that the current bot is the only bot in the thread; if we want\n // to support multiple bots, we need to add a way to determine the bot's user id.\n isBot: userId === this.#botUserId,\n isMe: userId === this.#botUserId,\n },\n raw: event.data,\n adapter: this,\n },\n options\n );\n }\n\n return new Response(null, { status: 200 });\n }\n\n async postMessage(\n threadId: string,\n message: AdapterPostableMessage\n ): Promise<RawMessage<CommentData>> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n const comment = await this.#client.createComment({\n roomId,\n threadId: threadId_liveblocks,\n data: {\n userId: this.#botUserId,\n body: convertPostableMessageToCommentBody(message),\n },\n });\n return { id: comment.id, threadId, raw: comment };\n }\n\n async editMessage(\n threadId: string,\n messageId: string,\n message: AdapterPostableMessage\n ): Promise<RawMessage<CommentData>> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n\n const comment = await this.#client.editComment({\n roomId,\n threadId: threadId_liveblocks,\n commentId: messageId,\n data: {\n body: convertPostableMessageToCommentBody(message),\n },\n });\n\n return { id: comment.id, threadId, raw: comment };\n }\n\n async deleteMessage(threadId: string, messageId: string): Promise<void> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n await this.#client.deleteComment({\n roomId,\n threadId: threadId_liveblocks,\n commentId: messageId,\n });\n }\n\n async addReaction(\n threadId: string,\n messageId: string,\n emoji: EmojiValue | string\n ): Promise<void> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n\n await this.#client.addCommentReaction({\n roomId,\n threadId: threadId_liveblocks,\n commentId: messageId,\n data: {\n // Liveblocks expects unicode emoji; 'toGChat' converts normalized names (e.g. 'thumbs_up') to unicode ('👍').\n // Unknown normalized names (e.g. 'custom_emoji') will fail Liveblocks validation since they are not valid unicode emoji.\n emoji: defaultEmojiResolver.toGChat(emoji),\n userId: this.#botUserId,\n },\n });\n }\n\n async removeReaction(\n threadId: string,\n messageId: string,\n emoji: EmojiValue | string\n ): Promise<void> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n\n await this.#client.removeCommentReaction({\n roomId,\n threadId: threadId_liveblocks,\n commentId: messageId,\n data: {\n emoji: defaultEmojiResolver.toGChat(emoji),\n userId: this.#botUserId,\n },\n });\n }\n\n async fetchMessages(\n threadId: string,\n options?: FetchOptions\n ): Promise<FetchResult<CommentData>> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n\n const thread = await this.#client.getThread({\n roomId,\n threadId: threadId_liveblocks,\n });\n\n const comments = thread.comments.filter(\n (comment) => comment.deletedAt === undefined\n );\n\n const direction = options?.direction ?? \"backward\";\n const limit = options?.limit;\n const startingAfter = options?.cursor;\n\n // The 'Get thread' API returns all comments in the thread in chronological order,\n // so we perform in-memory pagination to match Chat SDK's expected behavior.\n const sliced = slicePageByCreatedAt(comments, {\n direction: direction === \"forward\" ? \"ascending\" : \"descending\",\n limit,\n startingAfter,\n });\n\n const messages = await Promise.all(\n sliced.data.map((comment) =>\n this.#convertLiveblocksCommentDataToChatMessage(comment)\n )\n );\n\n return { messages, nextCursor: sliced.nextCursor };\n }\n\n async fetchThread(threadId: string): Promise<ThreadInfo> {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n\n const thread = await this.#client.getThread({\n roomId,\n threadId: threadId_liveblocks,\n });\n\n return {\n id: threadId,\n channelId: `${ADAPTER_PREFIX}:${roomId}`,\n metadata: {\n resolved: thread.resolved,\n ...thread.metadata,\n },\n channelName: thread.roomId,\n isDM: false,\n };\n }\n\n async fetchMessage(\n threadId: string,\n messageId: string\n ): Promise<Message<CommentData> | null> {\n try {\n const { roomId, threadId: threadId_liveblocks } =\n this.decodeThreadId(threadId);\n\n const comment = await this.#client.getComment({\n roomId,\n threadId: threadId_liveblocks,\n commentId: messageId,\n });\n if (comment.deletedAt !== undefined) {\n return null;\n }\n return this.#convertLiveblocksCommentDataToChatMessage(comment);\n } catch (error) {\n if (error instanceof LiveblocksError && error.status === 404) {\n return null;\n }\n throw error;\n }\n }\n\n async listThreads(\n channelId: string,\n options?: ListThreadsOptions\n ): Promise<ListThreadsResult<CommentData>> {\n const roomId = getRoomIdFromChannelId(channelId);\n const { data } = await this.#client.getThreads({ roomId });\n const threads = data\n .map((thread) => {\n const nonDeletedComments = thread.comments\n .filter((comment) => comment.deletedAt === undefined)\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());\n\n const firstNonDeletedComment = nonDeletedComments[0];\n if (firstNonDeletedComment === undefined) return null;\n\n return {\n id: this.encodeThreadId({\n roomId,\n threadId: thread.id,\n }),\n updatedAt: thread.updatedAt,\n numOfComments: nonDeletedComments.length,\n firstComment: firstNonDeletedComment,\n };\n })\n .filter((thread) => thread !== null);\n\n const limit = options?.limit;\n const startingAfter = options?.cursor;\n\n // The 'Get threads' API returns all threads in the room in chronological order,\n // so we perform in-memory pagination to match Chat SDK's expected behavior.\n const sliced = slicePageByUpdatedAt(threads, {\n limit,\n startingAfter,\n });\n\n return {\n threads: await Promise.all(\n sliced.data.map(async (thread) => ({\n id: thread.id,\n rootMessage: await this.#convertLiveblocksCommentDataToChatMessage(\n thread.firstComment\n ),\n lastReplyAt: thread.updatedAt,\n replyCount: thread.numOfComments - 1,\n }))\n ),\n nextCursor: sliced.nextCursor,\n };\n }\n\n async fetchChannelInfo(channelId: string): Promise<ChannelInfo> {\n const room = await this.#client.getRoom(getRoomIdFromChannelId(channelId));\n return {\n id: room.id,\n name: room.id,\n isDM: false,\n metadata: {},\n };\n }\n\n async fetchChannelMessages(\n channelId: string,\n options?: FetchOptions\n ): Promise<FetchResult<CommentData>> {\n const roomId = getRoomIdFromChannelId(channelId);\n const { data } = await this.#client.getThreads({ roomId });\n\n const comments = data\n .map((thread) => {\n const nonDeletedComments = thread.comments\n .filter((comment) => comment.deletedAt === undefined)\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());\n const firstNonDeletedComment = nonDeletedComments[0];\n if (firstNonDeletedComment !== undefined) {\n return firstNonDeletedComment;\n }\n return null;\n })\n .filter((comment) => comment !== null);\n\n const direction = options?.direction ?? \"backward\";\n const limit = options?.limit;\n const startingAfter = options?.cursor;\n\n // The 'Get threads' API returns all threads in the room (sorted by creation date in ascending order)\n // and each thread contains all comments in the thread (sorted by creation date in ascending order),\n // so we perform in-memory pagination to match Chat SDK's expected behavior.\n const sliced = slicePageByCreatedAt(comments, {\n direction: direction === \"forward\" ? \"ascending\" : \"descending\",\n limit,\n startingAfter,\n });\n\n const messages = await Promise.all(\n sliced.data.map((comment) =>\n this.#convertLiveblocksCommentDataToChatMessage(comment)\n )\n );\n\n return { messages, nextCursor: sliced.nextCursor };\n }\n\n async postChannelMessage(\n channelId: string,\n message: AdapterPostableMessage\n ): Promise<RawMessage<CommentData>> {\n const roomId = getRoomIdFromChannelId(channelId);\n const thread = await this.#client.createThread({\n roomId,\n data: {\n comment: {\n userId: this.#botUserId,\n body: convertPostableMessageToCommentBody(message),\n },\n },\n });\n const firstComment = thread.comments[0];\n if (firstComment === undefined) {\n throw new Error(`Failed to create thread in room ${channelId}`);\n }\n return {\n id: firstComment.id,\n threadId: this.encodeThreadId({\n roomId,\n threadId: thread.id,\n }),\n raw: firstComment,\n };\n }\n\n // This method isn't used by the Chat SDK, but it's required to implement the Adapter interface,\n // so we will return a less rich message here. We have a separate (asynchronous) method for converting a comment to a message.\n parseMessage(data: CommentData): Message<CommentData> {\n return new Message({\n id: data.id,\n threadId: this.encodeThreadId({\n roomId: data.roomId,\n threadId: data.threadId,\n }),\n raw: data,\n formatted: { type: \"root\", children: [] },\n text: \"\",\n author: {\n userId: data.userId,\n userName: data.userId,\n fullName: data.userId,\n isBot: data.userId === this.#botUserId,\n isMe: data.userId === this.#botUserId,\n },\n metadata: {\n dateSent: data.createdAt,\n edited: !!data.editedAt,\n editedAt: data.editedAt,\n },\n attachments: data.attachments.map((att) =>\n this.#createAttachment(data.roomId, att)\n ),\n });\n }\n\n renderFormatted(content: FormattedContent): string {\n // Liveblocks comments do not support markdown as input, so we convert the content to plain text.\n return toPlainText(content);\n }\n\n channelIdFromThreadId(threadId: string): string {\n const { roomId } = this.decodeThreadId(threadId);\n return `${ADAPTER_PREFIX}:${roomId}`;\n }\n\n /**\n * This method is a no-op as typing indicators are not supported by Liveblocks Comments.\n */\n startTyping(_threadId: string, _status?: string): Promise<void> {\n return Promise.resolve();\n }\n\n #createAttachment(\n roomId: string,\n attachment: CommentData[\"attachments\"][number]\n ): Attachment {\n const client = this.#client;\n return {\n type: getAttachmentType(attachment.mimeType),\n name: attachment.name,\n mimeType: attachment.mimeType,\n size: attachment.size,\n fetchData: async () => {\n const { url } = await client.getAttachment({\n roomId,\n attachmentId: attachment.id,\n });\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch attachment \"${attachment.name}\": ${response.status} ${response.statusText}`\n );\n }\n return Buffer.from(await response.arrayBuffer());\n },\n };\n }\n\n /**\n * Encodes a Liveblocks room ID and thread ID into a single thread ID string.\n *\n * Format: `liveblocks:{roomId}:{threadId}`\n *\n * **Note**: Room IDs may contain colons (':'), which are preserved during encoding/decoding.\n * However, Liveblocks thread IDs must not contain colons as the last colon is used as the delimiter when decoding.\n */\n encodeThreadId(data: { roomId: string; threadId: string }): string {\n return `${ADAPTER_PREFIX}:${data.roomId}:${data.threadId}`;\n }\n\n /**\n * Decodes an encoded thread ID string back into its room ID and thread ID components.\n *\n * @throws {Error} If the thread ID format is invalid\n */\n decodeThreadId(threadId: string): { roomId: string; threadId: string } {\n const parts = threadId.split(\":\");\n if (parts.length < 3 || parts[0] !== ADAPTER_PREFIX) {\n throw new Error(\n `Invalid thread ID: ${threadId}. Expected format: liveblocks:{roomId}:{threadId}`\n );\n }\n return {\n roomId: parts.slice(1, -1).join(\":\"),\n threadId: parts[parts.length - 1]!,\n };\n }\n\n async #convertLiveblocksCommentDataToChatMessage(\n comment: Extract<CommentData, { body: CommentBody }>\n ): Promise<Message<CommentData>> {\n const mentions = getMentionsFromCommentBody(comment.body);\n const userIds = new Set<string>([comment.userId]); // Initialize with the author's user id\n const groupIds = new Set<string>();\n for (const mention of mentions) {\n if (mention.kind === \"user\") {\n userIds.add(mention.id);\n } else if (mention.kind === \"group\") {\n groupIds.add(mention.id);\n }\n }\n\n const [users, groups] = await Promise.all([\n this.#resolveUsers\n ? this.#resolveUsers({ userIds: Array.from(userIds) })\n : undefined,\n this.#resolveGroupsInfo && groupIds.size > 0\n ? this.#resolveGroupsInfo({ groupIds: Array.from(groupIds) })\n : undefined,\n ]);\n\n const resolvedUsers = new Map<string, U[\"info\"]>();\n if (users !== undefined) {\n for (const [index, userId] of Array.from(userIds).entries()) {\n const user = users[index];\n if (user === undefined) continue;\n resolvedUsers.set(userId, user);\n }\n }\n const resolvedGroups = new Map<string, DGI>();\n if (groups !== undefined) {\n for (const [index, groupId] of Array.from(groupIds).entries()) {\n const group = groups[index];\n if (group === undefined) continue;\n resolvedGroups.set(groupId, group);\n }\n }\n\n const links = new Set<string>();\n\n const nodes: Paragraph[] = comment.body.content.map((block) => {\n const children: Array<\n Text | Link | Emphasis | Strong | InlineCode | Delete\n > = [];\n for (const inline of block.children) {\n if (isCommentBodyMention(inline)) {\n if (inline.kind === \"user\") {\n children.push({\n type: \"text\",\n value: resolvedUsers.get(inline.id)?.name ?? inline.id,\n });\n } else {\n children.push({\n type: \"text\",\n value: resolvedGroups.get(inline.id)?.name ?? inline.id,\n });\n }\n } else if (isCommentBodyLink(inline)) {\n links.add(inline.url);\n children.push({\n type: \"link\",\n children: [{ type: \"text\", value: inline.text ?? \"\" }],\n url: inline.url,\n });\n } else if (isCommentBodyText(inline)) {\n if (inline.code) {\n children.push({\n type: \"inlineCode\",\n value: inline.text,\n });\n } else {\n // Build nested structure for combined styles (bold, italic, strikethrough)\n let node: Text | Emphasis | Strong | Delete = {\n type: \"text\",\n value: inline.text,\n };\n\n if (inline.strikethrough) {\n node = { type: \"delete\", children: [node] };\n }\n if (inline.italic) {\n node = { type: \"emphasis\", children: [node] };\n }\n if (inline.bold) {\n node = { type: \"strong\", children: [node] };\n }\n\n children.push(node);\n }\n }\n }\n return { type: \"paragraph\", children };\n });\n\n const text = comment.body.content.reduce((acc, block) => {\n return (\n acc +\n block.children.reduce((acc, inline) => {\n if (isCommentBodyMention(inline)) {\n if (inline.kind === \"user\") {\n return acc + (resolvedUsers.get(inline.id)?.name ?? inline.id);\n } else {\n return acc + (resolvedGroups.get(inline.id)?.name ?? inline.id);\n }\n } else if (isCommentBodyLink(inline)) {\n if (inline.text) {\n return acc + inline.text;\n } else {\n return acc + inline.url;\n }\n } else if (isCommentBodyText(inline)) {\n return acc + inline.text;\n }\n return acc;\n }, \"\")\n );\n }, \"\");\n\n return new Message({\n id: comment.id,\n threadId: this.encodeThreadId({\n roomId: comment.roomId,\n threadId: comment.threadId,\n }),\n raw: comment,\n formatted: { type: \"root\", children: nodes },\n text,\n isMention: resolvedUsers.has(this.#botUserId),\n links: Array.from(links.values()).map((url) => ({ url })),\n author: {\n userId: comment.userId,\n userName: resolvedUsers.get(comment.userId)?.name ?? comment.userId,\n fullName: resolvedUsers.get(comment.userId)?.name ?? comment.userId,\n // This assumes that the current bot is the only bot in the thread; if we want\n // to support multiple bots, we need to add a way to determine the bot's user id.\n isBot: comment.userId === this.#botUserId,\n isMe: comment.userId === this.#botUserId,\n },\n metadata: {\n dateSent: comment.createdAt,\n edited: comment.editedAt !== undefined,\n editedAt: comment.editedAt,\n },\n attachments: comment.attachments.map((attachment) =>\n this.#createAttachment(comment.roomId, attachment)\n ),\n });\n }\n}\n\n/**\n * Parses a Chat SDK channel id into the Liveblocks room id for REST API calls.\n *\n * @throws {Error} If `channelId` is missing the `liveblocks:` prefix or has an empty room segment.\n */\nexport function getRoomIdFromChannelId(channelId: string): string {\n const prefix = `${ADAPTER_PREFIX}:`;\n if (!channelId.startsWith(prefix)) {\n throw new Error(\n `Invalid channel ID: \"${channelId}\". Expected format: ${prefix}{roomId}`\n );\n }\n const roomId = channelId.slice(prefix.length);\n if (roomId === \"\") {\n throw new Error(\n `Invalid channel ID: \"${channelId}\". Expected format: ${prefix}{roomId}`\n );\n }\n return roomId;\n}\n\nexport function convertPostableMessageToCommentBody(\n message: AdapterPostableMessage\n): CommentBody {\n if (typeof message === \"string\") {\n return convertChatRootElementToCommentBodyRootElement(\n parseMarkdown(message)\n );\n } else if (\"raw\" in message) {\n return convertChatRootElementToCommentBodyRootElement(\n parseMarkdown(message.raw)\n );\n } else if (\"markdown\" in message) {\n return convertChatRootElementToCommentBodyRootElement(\n parseMarkdown(message.markdown)\n );\n } else if (\"ast\" in message) {\n return convertChatRootElementToCommentBodyRootElement(message.ast);\n } else if (\"card\" in message) {\n // Liveblocks comments do not support cards and card elements, so we convert the message to markdown and then to a comment body\n return convertChatRootElementToCommentBodyRootElement(\n parseMarkdown(\n message.fallbackText ?? convertCardToMarkdownString(message.card)\n )\n );\n } else if (\"type\" in message && message.type === \"card\") {\n return convertChatRootElementToCommentBodyRootElement(\n parseMarkdown(convertCardToMarkdownString(message))\n );\n } else {\n console.error(`Unexpected message type: ${JSON.stringify(message)}`);\n return {\n version: 1,\n content: [],\n };\n }\n}\n\nfunction convertCardToMarkdownString(card: CardElement): string {\n const parts: string[] = [];\n if (card.title) {\n parts.push(`**${card.title}**`);\n }\n if (card.subtitle) {\n parts.push(card.subtitle);\n }\n for (const child of card.children) {\n parts.push(convertCardChildToMarkdownString(child));\n }\n return parts.join(\"\\n\");\n}\n\nfunction convertCardChildToMarkdownString(child: CardChild): string {\n switch (child.type) {\n case \"text\":\n return child.content;\n case \"fields\":\n return child.children\n .map((field) => `**${field.label}**: ${field.value}`)\n .join(\"\\n\");\n case \"actions\":\n // Actions are interactive-only — exclude from fallback text. See: https://docs.slack.dev/reference/methods/chat.postMessage\n return \"\";\n case \"table\": {\n let markdown = \"|\";\n for (const header of child.headers) {\n markdown += ` ${header} |`;\n }\n markdown += \"\\n|\";\n for (const _ of child.headers) {\n markdown += \"--- |\";\n }\n markdown += \"\\n\";\n for (const row of child.rows) {\n markdown += \"|\";\n for (const cell of row) {\n markdown += ` ${cell} |`;\n }\n markdown += \"\\n\";\n }\n return markdown;\n }\n case \"section\":\n return child.children\n .map((c) => convertCardChildToMarkdownString(c))\n .filter(Boolean)\n .join(\"\\n\");\n case \"link\":\n return `[${child.label}](${child.url})`;\n case \"divider\":\n return \"---\";\n case \"image\":\n return ``;\n default:\n return \"\";\n }\n}\n\nfunction convertChatRootElementToCommentBodyRootElement(\n root: Root\n): CommentBody {\n return {\n version: 1,\n content: root.children.flatMap((child) =>\n convertChatBlockElementToCommentBodyBlockElement(child)\n ),\n };\n}\n\nfunction convertChatBlockElementToCommentBodyBlockElement(\n node: Root[\"children\"][number]\n): CommentBodyParagraph | CommentBodyParagraph[] {\n switch (node.type) {\n case \"paragraph\": {\n const children: CommentBodyInlineElement[] = [];\n for (const child of node.children) {\n children.push(\n convertChatInlineElementToCommentBodyInlineElement(child)\n );\n }\n return {\n type: \"paragraph\",\n children,\n };\n }\n case \"blockquote\": {\n return node.children.flatMap((child) => {\n return convertChatBlockElementToCommentBodyBlockElement(child);\n });\n }\n case \"list\": {\n return node.children.flatMap((child) => {\n return convertChatBlockElementToCommentBodyBlockElement(child);\n });\n }\n case \"listItem\": {\n return node.children.flatMap((child) => {\n return convertChatBlockElementToCommentBodyBlockElement(child);\n });\n }\n case \"heading\": {\n // Render headings as paragraphs as Liveblocks comments do not support headings\n return convertChatBlockElementToCommentBodyBlockElement({\n type: \"paragraph\",\n children: node.children,\n });\n }\n case \"code\": {\n // Render code blocks as paragraphs as Liveblocks comments do not support code blocks\n return convertChatBlockElementToCommentBodyBlockElement({\n type: \"paragraph\",\n children: [{ type: \"text\", value: node.value }],\n });\n }\n case \"html\": {\n // Render HTML as paragraphs as Liveblocks comments do not support HTML\n return convertChatBlockElementToCommentBodyBlockElement({\n type: \"paragraph\",\n children: [{ type: \"text\", value: node.value }],\n });\n }\n case \"table\": {\n // Convert table to ASCII table string and render as paragraph as Liveblocks comments do not support tables\n return {\n type: \"paragraph\",\n children: [{ text: tableToAscii(node) }],\n };\n }\n case \"link\":\n case \"image\":\n case \"strong\":\n case \"emphasis\":\n case \"inlineCode\":\n case \"delete\":\n case \"text\": {\n return {\n type: \"paragraph\",\n children: [convertChatInlineElementToCommentBodyInlineElement(node)],\n };\n }\n case \"break\":\n case \"thematicBreak\":\n case \"definition\":\n case \"tableCell\":\n case \"tableRow\":\n case \"yaml\":\n case \"footnoteDefinition\":\n case \"footnoteReference\":\n case \"imageReference\":\n case \"linkReference\":\n default: {\n return [];\n }\n }\n}\n\nfunction convertChatInlineElementToCommentBodyInlineElement(\n inline: PhrasingContent\n): CommentBodyInlineElement {\n switch (inline.type) {\n case \"text\":\n return { text: inline.value };\n case \"link\":\n return {\n type: \"link\",\n url: inline.url,\n // Link elements in Liveblocks comments are considered leaf nodes (i.e. they do not have inline elements as children),\n // so we convert the children to plain text to match the expected format\n text: inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\"),\n };\n case \"image\":\n return { text: inline.url };\n case \"emphasis\":\n return {\n // Emphasis elements in Liveblocks comments are considered leaf nodes (i.e. they do not have inline elements as children),\n // so we convert the children to plain text to match the expected format\n text: inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\"),\n italic: true,\n };\n case \"strong\":\n return {\n text: inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\"),\n bold: true,\n };\n case \"delete\":\n return {\n text: inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\"),\n strikethrough: true,\n };\n case \"inlineCode\":\n return {\n text: inline.value,\n code: true,\n };\n case \"html\":\n return { text: inline.value };\n case \"break\":\n case \"linkReference\":\n case \"imageReference\":\n case \"footnoteReference\":\n default: {\n return { text: \"\" };\n }\n }\n}\n\nfunction convertChatInlineElementToPlainText(inline: PhrasingContent): string {\n switch (inline.type) {\n case \"text\":\n return inline.value;\n case \"link\":\n return inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\");\n case \"image\":\n return inline.url;\n case \"emphasis\":\n return inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\");\n case \"strong\":\n return inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\");\n case \"delete\":\n return inline.children\n .map((child) => {\n return convertChatInlineElementToPlainText(child);\n })\n .join(\"\");\n case \"inlineCode\":\n return inline.value;\n case \"html\":\n return inline.value;\n case \"break\":\n case \"linkReference\":\n case \"imageReference\":\n case \"footnoteReference\":\n default:\n return \"\";\n }\n}\n\n/**\n * Encode a pagination cursor using the format `base64url( [[\"id\", <string>], [\"createdAt\", <number>]] )`\n */\nexport function encodePaginationCursorByCreatedAt(\n id: string,\n createdAt: Date\n): string {\n return base64UrlEncode(\n JSON.stringify([\n [\"id\", id],\n [\"createdAt\", createdAt.getTime()],\n ])\n );\n}\n\nexport function decodePaginationCursorByCreatedAt(cursor: string): {\n id: string;\n createdAt: Date;\n} {\n try {\n const parsed = JSON.parse(base64UrlDecode(cursor));\n if (\n !Array.isArray(parsed) ||\n parsed.length !== 2 ||\n parsed[0]?.[0] !== \"id\" ||\n parsed[1]?.[0] !== \"createdAt\"\n ) {\n throw new Error(\"Invalid cursor structure\");\n }\n return {\n id: parsed[0][1] as string,\n createdAt: new Date(parsed[1][1] as number),\n };\n } catch {\n throw new Error(`Invalid pagination cursor: ${cursor}`);\n }\n}\n\nexport function encodePaginationCursorByUpdatedAt(\n id: string,\n updatedAt: Date\n): string {\n return base64UrlEncode(\n JSON.stringify([\n [\"id\", id],\n [\"updatedAt\", updatedAt.getTime()],\n ])\n );\n}\n\nexport function decodePaginationCursorByUpdatedAt(cursor: string): {\n id: string;\n updatedAt: Date;\n} {\n try {\n const parsed = JSON.parse(base64UrlDecode(cursor));\n if (\n !Array.isArray(parsed) ||\n parsed.length !== 2 ||\n parsed[0]?.[0] !== \"id\" ||\n parsed[1]?.[0] !== \"updatedAt\"\n ) {\n throw new Error(\"Invalid cursor structure\");\n }\n return {\n id: parsed[0][1] as string,\n updatedAt: new Date(parsed[1][1] as number),\n };\n } catch {\n throw new Error(`Invalid pagination cursor: ${cursor}`);\n }\n}\n\nfunction base64UrlEncode(str: string): string {\n const bytes = new TextEncoder().encode(str);\n const binary = String.fromCharCode(...bytes);\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nfunction base64UrlDecode(str: string): string {\n let s = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n while (s.length % 4) s += \"=\";\n const binary = atob(s);\n const bytes = Uint8Array.from(binary, (c) => c.codePointAt(0)!);\n return new TextDecoder().decode(bytes);\n}\n\n/**\n * Slice a page from an in-memory list sorted by `createdAt` (oldest first).\n *\n * Cursors use the same `[[\"id\", ...], [\"createdAt\", ...]]` format as the\n * Liveblocks REST API so that they will be forward-compatible if the backend\n * adds server-side pagination.\n *\n * The cursor is always built from the boundary item of the current page and\n * means \"start after this item\" in the current traversal direction — matching\n * the `startingAfter` semantics used throughout the backend.\n *\n * When no `limit` is provided, all matching items are returned (preserving the\n * pre-pagination behaviour of returning the full list).\n */\nfunction slicePageByCreatedAt<T extends { id: string; createdAt: Date }>(\n data: T[],\n options: {\n /**\n * The direction to slice the page in.\n * - \"ascending\": Slice the page from the oldest item to the newest item.\n * - \"descending\": Slice the page from the newest item to the oldest item.\n */\n direction: \"ascending\" | \"descending\";\n limit?: number;\n startingAfter?: string;\n }\n): { data: T[]; nextCursor: string | undefined } {\n const { direction, limit, startingAfter } = options;\n\n // Sort data by 'createdAt' (oldest first) and use 'id' as a tie-breaker\n data = data.slice().sort((a, b) => {\n if (a.createdAt.getTime() !== b.createdAt.getTime()) {\n return a.createdAt.getTime() - b.createdAt.getTime();\n }\n return b.id.localeCompare(a.id);\n });\n\n let startIndex: number;\n let endIndex: number;\n\n if (direction === \"descending\") {\n if (startingAfter) {\n const cursor = decodePaginationCursorByCreatedAt(startingAfter);\n // Find the cursor's position in sort order, then take everything before it.\n endIndex = data.findIndex(\n (c) =>\n c.createdAt.getTime() > cursor.createdAt.getTime() ||\n (c.createdAt.getTime() === cursor.createdAt.getTime() &&\n c.id <= cursor.id)\n );\n if (endIndex === -1) {\n endIndex = data.length;\n }\n } else {\n endIndex = data.length;\n }\n startIndex = limit !== undefined ? Math.max(0, endIndex - limit) : 0;\n } else {\n if (startingAfter) {\n const cursor = decodePaginationCursorByCreatedAt(startingAfter);\n // Find the first item strictly after the cursor in sort order.\n startIndex = data.findIndex(\n (c) =>\n c.createdAt.getTime() > cursor.createdAt.getTime() ||\n (c.createdAt.getTime() === cursor.createdAt.getTime() &&\n c.id < cursor.id)\n );\n if (startIndex === -1) {\n return { data: [], nextCursor: undefined };\n }\n } else {\n startIndex = 0;\n }\n endIndex =\n limit !== undefined\n ? Math.min(data.length, startIndex + limit)\n : data.length;\n }\n\n const page = data.slice(startIndex, endIndex);\n\n if (page.length === 0) {\n return { data: [], nextCursor: undefined };\n }\n\n let nextCursor: string | undefined;\n if (direction === \"descending\") {\n nextCursor =\n startIndex > 0\n ? encodePaginationCursorByCreatedAt(page[0]!.id, page[0]!.createdAt)\n : undefined;\n } else {\n nextCursor =\n endIndex < data.length\n ? encodePaginationCursorByCreatedAt(\n page[page.length - 1]!.id,\n page[page.length - 1]!.createdAt\n )\n : undefined;\n }\n\n return { data: page, nextCursor };\n}\n\n/**\n * Same as {@link slicePageByCreatedAt} (descending direction only) but sorts and\n * paginates on `updatedAt`. Thread listing does not expose forward pagination.\n */\nfunction slicePageByUpdatedAt<T extends { id: string; updatedAt: Date }>(\n data: T[],\n options: {\n limit?: number;\n startingAfter?: string;\n }\n): { data: T[]; nextCursor: string | undefined } {\n const { limit, startingAfter } = options;\n\n // Sort data by 'updatedAt' (oldest first) and use 'id' as a tie-breaker\n data = data.slice().sort((a, b) => {\n if (a.updatedAt.getTime() !== b.updatedAt.getTime()) {\n return a.updatedAt.getTime() - b.updatedAt.getTime();\n }\n return b.id.localeCompare(a.id);\n });\n\n let endIndex: number;\n if (startingAfter) {\n const cursor = decodePaginationCursorByUpdatedAt(startingAfter);\n // Find the cursor's position in sort order, then take everything before it.\n endIndex = data.findIndex(\n (c) =>\n c.updatedAt.getTime() > cursor.updatedAt.getTime() ||\n (c.updatedAt.getTime() === cursor.updatedAt.getTime() &&\n c.id <= cursor.id)\n );\n if (endIndex === -1) {\n endIndex = data.length;\n }\n } else {\n endIndex = data.length;\n }\n const startIndex = limit !== undefined ? Math.max(0, endIndex - limit) : 0;\n\n const page = data.slice(startIndex, endIndex);\n\n if (page.length === 0) {\n return { data: [], nextCursor: undefined };\n }\n\n const nextCursor =\n startIndex > 0\n ? encodePaginationCursorByUpdatedAt(page[0]!.id, page[0]!.updatedAt)\n : undefined;\n\n return { data: page, nextCursor };\n}\n\nfunction getAttachmentType(mimeType: string): Attachment[\"type\"] {\n if (mimeType.startsWith(\"image/\")) {\n return \"image\";\n } else if (mimeType.startsWith(\"video/\")) {\n return \"video\";\n } else if (mimeType.startsWith(\"audio/\")) {\n return \"audio\";\n }\n return \"file\";\n}\n\nexport interface LiveblocksAdapterConfig<\n U extends BaseUserMeta,\n DGI extends BaseGroupInfo,\n> {\n apiKey: string;\n webhookSecret: string;\n resolveUsers?: (\n args: ResolveUsersArgs\n ) => Awaitable<(U[\"info\"] | undefined)[] | undefined>;\n resolveGroupsInfo?: (\n args: ResolveGroupsInfoArgs\n ) => Awaitable<(DGI | undefined)[] | undefined>;\n botUserId: string;\n botUserName?: string;\n logger?: Logger;\n}\n\nexport function createLiveblocksAdapter<\n U extends BaseUserMeta = BaseUserMeta,\n DGI extends BaseGroupInfo = BaseGroupInfo,\n>(config: LiveblocksAdapterConfig<U, DGI>): LiveblocksAdapter<U, DGI> {\n return new LiveblocksAdapter(config);\n}\n"],"mappings":"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","names":["acc"]}
|
package/package.json
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/chat-sdk-adapter",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.16.0-flow2",
|
|
4
|
+
"description": "Liveblocks adapter for the Chat SDK.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Liveblocks Inc.",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"types": "./dist/index.d.cts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"default": "./dist/index.cjs"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist/**",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"format": "(eslint --fix src/ || true) && prettier --write src/",
|
|
31
|
+
"lint": "eslint src/",
|
|
32
|
+
"lint:package": "publint --strict && attw --pack",
|
|
33
|
+
"test": "NODE_OPTIONS=\"--no-deprecation\" vitest run",
|
|
34
|
+
"test:ci": "NODE_OPTIONS=\"--no-deprecation\" vitest run",
|
|
35
|
+
"test:watch": "NODE_OPTIONS=\"--no-deprecation\" vitest"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@liveblocks/core": "3.16.0-flow2",
|
|
39
|
+
"@liveblocks/node": "3.16.0-flow2"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"chat": ">=4.20.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@liveblocks/eslint-config": "*",
|
|
46
|
+
"@liveblocks/vitest-config": "*",
|
|
47
|
+
"chat": "^4.21.0"
|
|
48
|
+
},
|
|
49
|
+
"sideEffects": false,
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/liveblocks/liveblocks/issues"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/liveblocks/liveblocks.git",
|
|
56
|
+
"directory": "packages/liveblocks-chat"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://liveblocks.io",
|
|
59
|
+
"keywords": [
|
|
60
|
+
"liveblocks",
|
|
61
|
+
"chat-sdk",
|
|
62
|
+
"comments",
|
|
63
|
+
"collaboration"
|
|
64
|
+
]
|
|
5
65
|
}
|