@liveblocks/emails
Version:
A set of functions and utilities to make sending emails based on Liveblocks notification events easy. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
406 lines (398 loc) • 15.9 kB
text/typescript
import { BaseUserMeta, DU, ResolveUsersArgs, Awaitable, DRI, CommentBodyText, CommentBodyLink, CommentBodyMention } from '@liveblocks/core';
export { ResolveUsersArgs } from '@liveblocks/core';
import { ReactNode, ComponentType } from 'react';
import { Properties } from 'csstype';
import { Liveblocks, TextMentionNotificationEvent, ThreadNotificationEvent } from '@liveblocks/node';
type ResolveRoomInfoArgs = {
/**
* The ID of the room to resolve
*/
roomId: string;
};
/**
* CSS properties object.
* Type alias for DX purposes.
*
*/
type CSSProperties = Properties;
/**
* Liveblocks Text Editor
*
* Expose common types to transform nodes from different editors like `Lexical` or `TipTap`
* and then convert them more easily as React or as html.
*/
type LiveblocksTextEditorTextFormat = {
bold: boolean;
italic: boolean;
strikethrough: boolean;
code: boolean;
};
type LiveblocksTextEditorTextNode = {
type: "text";
text: string;
} & LiveblocksTextEditorTextFormat;
type LiveblocksTextEditorMentionNode = {
type: "mention";
userId: string;
};
/**
* -------------------------------------------------------------------------------------------------
* `LiveblocksTextEditorNode` is common structure to represents text editor nodes coming from
* like `Lexical`, `TipTap` or so.
*
* This (simple) structure is made to be scalable and to accommodate with other text editors we could potentially
* want to support in the future.
*
* It allows to manipulate nodes more easily and converts them with ease either as React nodes or as an html safe string.
* From a DX standpoint it provides to developers the same structure to use when using custom React components or inline css
* to represents a text mention with its surrounding text.
* -------------------------------------------------------------------------------------------------
*/
type LiveblocksTextEditorNode = LiveblocksTextEditorTextNode | LiveblocksTextEditorMentionNode;
type TextEditorContainerComponentProps = {
/**
* The nodes of the text editor
*/
children: ReactNode;
};
type TextEditorMentionComponentProps<U extends BaseUserMeta = DU> = {
/**
* The mention element.
*/
element: LiveblocksTextEditorMentionNode;
/**
* The mention's user info, if the `resolvedUsers` option was provided.
*/
user?: U["info"];
};
type TextEditorTextComponentProps = {
/**
* The text element.
*/
element: LiveblocksTextEditorTextNode;
};
type ConvertTextEditorNodesAsReactComponents<U extends BaseUserMeta = DU> = {
/**
*
* The component used to act as a container to wrap text editor nodes,
*/
Container: ComponentType<TextEditorContainerComponentProps>;
/**
* The component used to display mentions.
*/
Mention: ComponentType<TextEditorMentionComponentProps<U>>;
/**
* The component used to display text nodes.
*/
Text: ComponentType<TextEditorTextComponentProps>;
};
type ConvertTextEditorNodesAsHtmlStyles = {
/**
* The default inline CSS styles used to display container element.
*/
container: CSSProperties;
/**
* The default inline CSS styles used to display text `<strong />` elements.
*/
strong: CSSProperties;
/**
* The default inline CSS styles used to display text `<code />` elements.
*/
code: CSSProperties;
/**
* The default inline CSS styles used to display mentions.
*/
mention: CSSProperties;
};
type MentionEmailBaseData = {
id: string;
roomId: string;
userId: string;
textEditorNodes: LiveblocksTextEditorNode[];
createdAt: Date;
};
type PrepareTextMentionNotificationEmailBaseDataOptions = {
/**
* A function that returns room info from room IDs.
*/
resolveRoomInfo?: (args: ResolveRoomInfoArgs) => Awaitable<DRI | undefined>;
};
type MentionEmailAsReactData<U extends BaseUserMeta = DU> = Omit<MentionEmailBaseData, "userId" | "textEditorNodes"> & {
author: U;
reactContent: ReactNode;
};
type MentionEmailAsHtmlData<U extends BaseUserMeta = DU> = Omit<MentionEmailBaseData, "userId" | "textEditorNodes"> & {
author: U;
htmlContent: string;
};
type PrepareTextMentionNotificationEmailAsReactOptions<U extends BaseUserMeta = DU> = PrepareTextMentionNotificationEmailBaseDataOptions & {
/**
* A function that returns info from user IDs.
*/
resolveUsers?: (args: ResolveUsersArgs) => Awaitable<(U["info"] | undefined)[] | undefined>;
/**
* The components used to customize the resulting React nodes. Each components has
* priority over the base components inherited.
*/
components?: Partial<ConvertTextEditorNodesAsReactComponents<U>>;
};
type TextMentionNotificationEmailData<U extends BaseUserMeta, M extends MentionEmailAsReactData<U> | MentionEmailAsHtmlData<U>> = {
mention: M;
roomInfo: DRI;
};
type TextMentionNotificationEmailDataAsReact = TextMentionNotificationEmailData<BaseUserMeta, MentionEmailAsReactData>;
/**
* Prepares data from a `TextMentionNotificationEvent` and convert content as React nodes.
*
* @param client The `Liveblocks` node client
* @param event The `TextMentionNotificationEvent` received in the webhook handler
* @param options The optional options to provide to resolve users, resolve room info and customize comment bodies React components.
*
* It returns a `TextMentionNotificationEmailDataAsReact` or `null` if there are no existing text mention.
*
* @example
* import { Liveblocks} from "@liveblocks/node"
* import { prepareTextMentionNotificationEmailAsReact } from "@liveblocks/emails"
*
* const liveblocks = new Liveblocks({ secret: "sk_..." })
* const emailData = prepareTextMentionNotificationEmailAsReact(
* liveblocks,
* event,
* {
* resolveUsers,
* resolveRoomInfo,
* components,
* }
* )
*/
declare function prepareTextMentionNotificationEmailAsReact(client: Liveblocks, event: TextMentionNotificationEvent, options?: PrepareTextMentionNotificationEmailAsReactOptions<BaseUserMeta>): Promise<TextMentionNotificationEmailDataAsReact | null>;
type PrepareTextMentionNotificationEmailAsHtmlOptions<U extends BaseUserMeta = DU> = PrepareTextMentionNotificationEmailBaseDataOptions & {
/**
* A function that returns info from user IDs.
*/
resolveUsers?: (args: ResolveUsersArgs) => Awaitable<(U["info"] | undefined)[] | undefined>;
/**
* The styles used to customize the html elements in the resulting html safe string.
* Each styles has priority over the base styles inherited.
*/
styles?: Partial<ConvertTextEditorNodesAsHtmlStyles>;
};
type TextMentionNotificationEmailDataAsHtml = TextMentionNotificationEmailData<BaseUserMeta, MentionEmailAsHtmlData>;
/**
* Prepares data from a `TextMentionNotificationEvent` and convert content as an html safe string.
*
* @param client The `Liveblocks` node client
* @param event The `TextMentionNotificationEvent` received in the webhook handler
* @param options The optional options to provide to resolve users, resolve room info and customize comment bodies React components.
*
* It returns a `TextMentionNotificationEmailDataAsReact` or `null` if there are no existing text mention.
*
* @example
* import { Liveblocks} from "@liveblocks/node"
* import { prepareTextMentionNotificationEmailAsHtml } from "@liveblocks/emails"
*
* const liveblocks = new Liveblocks({ secret: "sk_..." })
* const emailData = prepareTextMentionNotificationEmailAsHtml(
* liveblocks,
* event,
* {
* resolveUsers,
* resolveRoomInfo,
* styles,
* }
* )
*/
declare function prepareTextMentionNotificationEmailAsHtml(client: Liveblocks, event: TextMentionNotificationEvent, options?: PrepareTextMentionNotificationEmailAsHtmlOptions<BaseUserMeta>): Promise<TextMentionNotificationEmailDataAsHtml | null>;
type CommentEmailData<BodyType, U extends BaseUserMeta = DU> = {
id: string;
threadId: string;
roomId: string;
createdAt: Date;
url?: string;
author: U;
body: BodyType;
};
type ThreadNotificationEmailData<BodyType, U extends BaseUserMeta = DU, C extends CommentEmailData<BodyType, U> = CommentEmailData<BodyType, U>> = ({
type: "unreadReplies";
comments: C[];
} | {
type: "unreadMention";
comment: C;
}) & {
roomInfo: DRI;
};
type CommentEmailAsHtmlData<U extends BaseUserMeta = DU> = CommentEmailData<string, U> & {
/** @deprecated Use `body` property instead. */
htmlBody: string;
};
type CommentEmailAsReactData<U extends BaseUserMeta = DU> = CommentEmailData<ReactNode, U> & {
/** @deprecated Use `body` property instead. */
reactBody: ReactNode;
};
type PrepareThreadNotificationEmailOptions<U extends BaseUserMeta = DU> = {
/**
* A function that returns room info from room IDs.
*/
resolveRoomInfo?: (args: ResolveRoomInfoArgs) => Awaitable<DRI | undefined>;
/**
* A function that returns info from user IDs.
*/
resolveUsers?: (args: ResolveUsersArgs) => Awaitable<(U["info"] | undefined)[] | undefined>;
};
/**
* The styles used to customize the html elements in the resulting html safe string.
* Each styles has priority over the base styles inherited.
*/
type ConvertCommentBodyAsHtmlStyles = {
/**
* The default inline CSS styles used to display paragraphs.
*/
paragraph: CSSProperties;
/**
* The default inline CSS styles used to display text `<strong />` elements.
*/
strong: CSSProperties;
/**
* The default inline CSS styles used to display text `<code />` elements.
*/
code: CSSProperties;
/**
* The default inline CSS styles used to display links.
*/
mention: CSSProperties;
/**
* The default inline CSS styles used to display mentions.
*/
link: CSSProperties;
};
type PrepareThreadNotificationEmailAsHtmlOptions<U extends BaseUserMeta = DU> = PrepareThreadNotificationEmailOptions<U> & {
/**
* The styles used to customize the html elements in the resulting html safe string inside a comment body.
* Each styles has priority over the base styles inherited.
*/
styles?: Partial<ConvertCommentBodyAsHtmlStyles>;
};
type ThreadNotificationEmailDataAsHtml<U extends BaseUserMeta = DU> = ThreadNotificationEmailData<string, U, CommentEmailAsHtmlData<U>>;
/**
* Prepares data from a `ThreadNotificationEvent` and convert comment bodies as an html safe string.
*
* @param client The `Liveblocks` node client
* @param event The `ThreadNotificationEvent` received in the webhook handler
* @param options The optional options to provide to resolve users, resolve room info
* and customize comment bodies html elements styles with inline CSS.
*
* It returns a `ThreadNotificationEmailDataAsHtml` or `null` if there are no unread comments (mention or replies).
*
* @example
* import { Liveblocks} from "@liveblocks/node"
* import { prepareThreadNotificationEmailAsHtml } from "@liveblocks/emails"
*
* const liveblocks = new Liveblocks({ secret: "sk_..." })
* const emailData = prepareThreadNotificationEmailAsHtml(
* liveblocks,
* event,
* {
* resolveUsers,
* resolveRoomInfo,
* styles,
* }
* )
*
*/
declare function prepareThreadNotificationEmailAsHtml(client: Liveblocks, event: ThreadNotificationEvent, options?: PrepareThreadNotificationEmailAsHtmlOptions<BaseUserMeta>): Promise<ThreadNotificationEmailDataAsHtml | null>;
type CommentBodyContainerComponentProps = {
/**
* The blocks of the comment body
*/
children: ReactNode;
};
type CommentBodyParagraphComponentProps = {
/**
* The text content of the paragraph.
*/
children: ReactNode;
};
type CommentBodyTextComponentProps = {
/**
* The text element.
*/
element: CommentBodyText;
};
type CommentBodyLinkComponentProps = {
/**
* The link element.
*/
element: CommentBodyLink;
/**
* The absolute URL of the link.
*/
href: string;
};
type CommentBodyMentionComponentProps<U extends BaseUserMeta = DU> = {
/**
* The mention element.
*/
element: CommentBodyMention;
/**
* The mention's user info, if the `resolvedUsers` option was provided.
*/
user?: U["info"];
};
type ConvertCommentBodyAsReactComponents<U extends BaseUserMeta = DU> = {
/**
*
* The component used to act as a container to wrap comment body blocks,
*/
Container: ComponentType<CommentBodyContainerComponentProps>;
/**
* The component used to display paragraphs.
*/
Paragraph: ComponentType<CommentBodyParagraphComponentProps>;
/**
* The component used to display text elements.
*/
Text: ComponentType<CommentBodyTextComponentProps>;
/**
* The component used to display links.
*/
Link: ComponentType<CommentBodyLinkComponentProps>;
/**
* The component used to display mentions.
*/
Mention: ComponentType<CommentBodyMentionComponentProps<U>>;
};
type PrepareThreadNotificationEmailAsReactOptions<U extends BaseUserMeta = DU> = PrepareThreadNotificationEmailOptions<U> & {
/**
* The components used to customize the resulting React nodes inside a comment body.
* Each components has priority over the base components inherited internally defined.
*/
components?: Partial<ConvertCommentBodyAsReactComponents<U>>;
};
type ThreadNotificationEmailDataAsReact<U extends BaseUserMeta = DU> = ThreadNotificationEmailData<ReactNode, U, CommentEmailAsReactData<U>>;
/**
* Prepares data from a `ThreadNotificationEvent` and convert comment bodies as React nodes.
*
* @param client The `Liveblocks` node client
* @param event The `ThreadNotificationEvent` received in the webhook handler
* @param options The optional options to provide to resolve users, resolve room info and customize comment bodies React components.
*
* It returns a `ThreadNotificationEmailDataAsReact` or `null` if there are no unread comments (mention or replies).
*
* @example
* import { Liveblocks} from "@liveblocks/node"
* import { prepareThreadNotificationEmailAsReact } from "@liveblocks/emails"
*
* const liveblocks = new Liveblocks({ secret: "sk_..." })
* const emailData = prepareThreadNotificationEmailAsReact(
* liveblocks,
* event,
* {
* resolveUsers,
* resolveRoomInfo,
* components,
* }
* )
*
*/
declare function prepareThreadNotificationEmailAsReact(client: Liveblocks, event: ThreadNotificationEvent, options?: PrepareThreadNotificationEmailAsReactOptions<BaseUserMeta>): Promise<ThreadNotificationEmailDataAsReact | null>;
export { type CommentBodyContainerComponentProps, type CommentBodyLinkComponentProps, type CommentBodyMentionComponentProps, type CommentBodyParagraphComponentProps, type CommentBodyTextComponentProps, type CommentEmailAsHtmlData, type CommentEmailAsReactData, type ConvertCommentBodyAsHtmlStyles, type ConvertCommentBodyAsReactComponents, type ConvertTextEditorNodesAsHtmlStyles, type ConvertTextEditorNodesAsReactComponents, type MentionEmailAsHtmlData, type MentionEmailAsReactData, type PrepareTextMentionNotificationEmailAsHtmlOptions, type PrepareTextMentionNotificationEmailAsReactOptions, type PrepareThreadNotificationEmailAsHtmlOptions, type PrepareThreadNotificationEmailAsReactOptions, type ResolveRoomInfoArgs, type TextEditorContainerComponentProps, type TextEditorMentionComponentProps, type TextEditorTextComponentProps, type TextMentionNotificationEmailDataAsHtml, type TextMentionNotificationEmailDataAsReact, type ThreadNotificationEmailDataAsHtml, type ThreadNotificationEmailDataAsReact, prepareTextMentionNotificationEmailAsHtml, prepareTextMentionNotificationEmailAsReact, prepareThreadNotificationEmailAsHtml, prepareThreadNotificationEmailAsReact };