@12-apps/chat

中文文档
1.3.0发布于 2026/10/10MITES Module零依赖构建来源已验证近 30 天下载 3.3万

双方对一出作品的对话线索,每出作品仅由主机选择的角色标签显示:框架中立的 HTTP 路由,每个角色写出窗口,一个联系-信息过滤器和快速回复,加上由@12-apps/ui p所建的一出线程屏幕

中文使用文档
文档目录9 节
  1. 盒子里装的是什么
  2. 主持人决定谁在线上
  3. 电线
  4. 联系人过滤器
  5. 保留
  6. 主机自身查询索引
  7. 屏幕
  8. 主机选项
  9. 复制

@ 12- apps/ 聊天

双方就一项工作进行对话,其中每一项 派对是别人知道的 只能通过它的标签无身份证明,姓名 或联系细节穿过电线。 每个观众登上一次航道 同一线程屏幕在网络 SPA 和 React Industrial app 中制作.

盒子里装的是什么

子路径什麽
./servercreateApiChat(config) → { routes }:框架中立 GET /, (中文(简体) ), POST /messages, (中文(简体) ), POST /read。 。 。 . createChatReads 为主机自己的列表提供未读的徽章.
./clientcreateChatClient 财务报告和审定财务报表 useChatThread,这两个平台都是免费的:为主机绘制自己的UI.
./reactcreateWebChat(config) → { ChatThread }:网络表面.
./nativecreateNativeChat(config) → { ChatThread }:反应原生地表.
./manifest*用于服务器、网络和本地运行时间的线条清单.
prisma/chat.prisma (单位:千美元)ChatThread, (中文(简体) ), ChatMessage, (中文(简体) ), ChatReadMarker加上其迁移. pnpm --filter @12-apps/chat prisma:sync 将部分复制到主机计划文件夹.

主持人决定谁在线上

const { routes } = createApiChat({
  db: () => getPrismaClient(),
  authorize: async (request) => {
    // Is this caller a party to the thread the URL names? Under which role?
    // May that role still write? Answer null for "no such thread for you" (404).
    return { tenantId, threadKey: `job:${request.params.id}`, role: "client",
             authorId: user.id, readerId: user.id, canWrite: true };
  },
  roles: {
    client: { label: "Client", shared: false, maxLength: 500, freeText: true,
              blockContact: [], quickReplies: [], rateLimit: { max: 20, windowMs: 60_000 } },
    agent:  { label: "Agent", shared: false, maxLength: 160, freeText: true,
              blockContact: ["phone", "email", "url", "handle"],
              quickReplies: [{ key: "arrived", text: "I have arrived." }],
              rateLimit: { max: 6, windowMs: 60_000 } },
    team:   { label: "Team", shared: true, maxLength: 1000, freeText: true,
              blockContact: [], quickReplies: [], rateLimit: { max: 30, windowMs: 60_000 } },
  },
  copy: EN_US_CHAT_SERVER_COPY,          // or a per-request resolver
  contactVocabulary: { numberWords: { nine: "9" }, atWords: ["at"] },
  onMessage: async (event) => { /* notify, publish a live hint */ },
  onRefused: async (event) => { /* who keeps trying to pass contact info */ },
  onError: (error, { hook }) => logger.error(`chat ${hook} failed`, error),
});

db 可能归还客户或承诺. onMessage 财务报告和审定财务报表 onRefused 在背景中运行:不等待推就发送答案 提供商,并报告投出或拒绝的钩子 onError永远 给发送者.

所有这一切都属于主机: 写出窗口, 一个呼叫者所扮演的角色, 标签,和快速回复的词。 软件包拥有其余:

  • 角色的内容规则;
  • 联系人- info过滤器,它也读取主机的躲避字;
  • 每作者的费率限额;
  • 电线上的信息看起来像什么.

电线

每2个回答 { data }数字 : GET / 给 { thread, messages, unread }, (中文(简体) ), POST /messages 给 { message } (201个)和 POST /read 给 { unread }拒绝答复 { error, message }时 error 这是 软件包的代码 (contact_info, (中文(简体) ), closed, (中文(简体) ), rate_limited,(......)和 message 实值 主持人的句子。 作者只表现为 角色的标签.

POST /read 带 { upTo },则 createdAt 最新讯息 读者实际上被显示。 标记从不向后移动,从不过去 所以在屏幕装入后传到的讯息 仍然没有被读取 阅读 永不创建线程行; 第一个消息会.

联系人过滤器

它在Unicode 正常化后读取文本:全宽和其他标注 数字,隐形字符,看起来像西里尔字母和希腊字母,a 逆向跑 从主机的拼出数字 contactVocabulary电话号码是16个字符中的8位数, 不管他们分开。 时钟时间,货币符号后的金额,以及 匹配主机的横跨 neutralPatterns (地址单位如 apto 1204,最多每个4位数字)先被预留,因此地址与 公寓号码; 预留跨度仍为至少一个 数字. 只有在作为信使写作的价格时,才留出一笔金额 1,最多4个整数85,90, (中文(简体) ), 1.250,00),这样 $54321, (中文(简体) ), $98765,43 财务报告和审定财务报表 $8.765.432 没有。 CEP,全日期,或 单位拒绝前的5位数街道号码;即有文件证明的街道号码 价钱.

在信件中,它只读取一个相接的链条:同一个作者最近写的 免费文本( e)contactLookback,默认在 10 以内的最后 12 个消息 分钟)加入草案,而每条消息结束于下一个开始之处 数字、点或符号。 每个消息中一个数字 一号; Apto 1204 接下来是 Chego 19:30 是两行。 一个作者 发送到线程在每个过程中一次检查一个, 所以并行 请求不能通过对对方缺席的规则(若干请求) 复制品仍可互出). Bidi 控件在消息发出前被移除 因此屏幕显示过滤器读取的内容.

每一次尝试都花一个限速档, 包括一个被拒绝的,所以测试 过滤器已耗尽。 这是一种威慑,而不是一种保证:a 确定通过数字的人总是可以找到编码,没有过滤器 读取 onRefused 东道主如何看待谁一直在尝试。 已知错过, 让一条普通行穿过的代价: 数字的块(98765 e 4321),9个或10个位数的平分数 以一个地址单位或一个价格计算(98 765 ap 4321, (中文(简体) ), 9876 $5.432 a 包括: 第一组内的空间正是街道号码的写法), 单位或价格后面的两块(apto 98765 apto 4321),链断了 写着别的东西和照片 带有区域代码的移动 (偶数) 无法隐藏在一码后。 一个希望 arroba 要计数 向社会手柄增加 extraPatterns。 。 。 .

保留

信件保存 author_id 为节制,包船不删除 或匿名API:保留(LGPD,GDPR)是主机. 这个 chat_messages (tenant_id, created_at) 索引用于主机的扫描. created_at 来源于应用程序的时钟, 和相同的信息 毫秒由id订购.

主机自身查询索引

chat_threads (tenant_id, last_message_at) 1.1.0,移徙 20261003120000_add_chat_thread_activity_index) 服务于主机徽章 将线程数起自某一刻起的活动(tenant_id = ? AND last_message_at >= ?) (中文(简体) ). 复制软件包的移取主机 与它的下个同步; 它是添加剂, 所以它不需要释放的舞蹈.

屏幕

const { ChatThread } = createWebChat({ fetch: credentialedFetch, copy: EN_US_CHAT_UI_COPY, formatTime });
<ChatThread endpoint={`/api/jobs/${id}/chat`} refreshSignal={liveTick} onUnreadChange={setBadge} />

该线条本身 读到它显示的最新信息 onUnreadChange 然后得到服务器的剩余数(通常为0). 过 autoMarkRead={false} 仅用于未读数.

autoMarkRead="visible" 是为一线可挂出视线的 抽屉下半部分: 装入未读信件等待信件列表 显示在屏幕上,然后被标记为读取;在屏幕上找到未读的负载 列表已同时在屏幕标记上。 在网络上,名单被监视 a 一个 IntersectionObserver (在屏幕上从第一个像素开始显示);一个没有 一分一分,作为 true 已经 在本地,一个挂载列表算 屏幕。 jsdom stubs 的主机测试 IntersectionObserver 来驾驶它. 一个主机绘制自己的列表 useChatThread({ autoMarkRead: "visible" }) 通过报告 controls.onVisibleChange(visible)。 。 。 .

仅读线程( E)canWrite: false没有信件只显示关闭的 通知:没有写出第一个信件的空行邀请,也没有列表.

自己发的短信和别人的留言 都从表面上说:读者的 自己的泡泡是主题的一丁点 palette.primary.main 光线为8% 模式,16%在黑暗中),其他人坐在纸张表面. 标签是身体 文字本身的锡和纸上的次级文本; 主要颜色本身 在4.5:1下,它本身的锡,所以它不用于文字。 气泡最多为线宽的80%(60个) 字符,在网络上).

无障碍:清单是一个礼貌的活区(第1段)aria-live 在网上, accessibilityLiveRegion 因此,一个到达的消息被宣布. 在网络上点击一个发送按钮的手聚焦到球场上 角色的 maxLength 坐在这 <input> 自己来.

布局 :

  • 网络 : 留言就坐在这里 ScrollArea (最多60%的取景点) 高高的),它保持了最新的视野. ScrollArea 需求 ResizeObserver, (中文(简体) ), 因此,主机测试 在jsdom 悬浮它.
  • 原生 : 线条是一条"ui" Screen 键盘和它自己的 ScrollView。将其挂入一个有界限高度的母体(一个弹性一视图,或 Screen scroll={false}永远不要在另一个ScrollView。 过 keyboardOffset (dp) 当一头相上而坐.

createNativeChat 使用相同的配置。 两个表面都取出线程 @12-apps/ui 原始人只使用他们的跨平台道具,所以反应 原生的捆绑会把每个原始人 解决成其原生的双胞胎 react-native 出口条件。 每个平台的不同之处是 内部 ChatPlatform一个平台的造型

插槽接收网络本地语言
Frame列表和写入区域(单位:千美元) Stack键盘避免 Screen
MessageList喷出出出水泡, label, (中文(简体) ), scrollKey, (中文(简体) ), onVisibleChange?ScrollArea + 键 IntersectionObserverScrollView,在挂载时可见
Bubble{ mine, children }欧 Box 与 sx (图, min(80%, 60ch)(中文(简体) )欧 Box 与 style (图, 80%(中文(简体) )
Composer控制字段及其发送动作Input + 输入Input + 键盘发送键
QuickReplies芯片的密钥和标签,标题欧 Chips, 包装欧 Chips或药丸; 包装,或一条侧行
Notice发送失败的行、 语气和外观欧 Alert,或图标 + 标题相同,按 onNoticeHeight

软件包没有打开套接字 。 弹出 refreshSignal 当你的直播频道说 线条移动.

主机选项

两个表层都把这些放在配置上,都是可选的;一个没有它们的配置 和以前一样画线条 列出值以外的值抛出 ChatConfigError 当地表被建造的时候.

配置默认变化是什么
quickReplyLabel(key, text)服务器的句子芯片的标签。 对于比较简短的回答名称的芯片:一盘水龙头仍然发送出"关键",因此线程存储了完整的句子. 返回时 text 对于一个你不知道的钥匙.
quickRepliesHeading"visible""label" 滴数 copy.quickReplies 从屏幕上保留它作为行的可访问名称.
emptyDescription"always""withQuickReplies" 显示 copy.emptyDescription 仅在下面绘制芯片时,用于指向芯片的描述.
sendFailureMessage(failure)服务器句子, 否则 copy.sendFailed发送失败的行显示; 返回默认无效 . failure.code 是软件包的( a)contact_info(中文(简体) ).
sendFailureNotice"alert""compact":一个图标,在作曲家上最多两行,一旦编辑草稿就消失;a contact_info 拒绝读作警告, 任何其它的都是错误. "alert" 留在芯片上直到下一个发送.
sendWhenEmpty"disabled""inert" 保留空白字段中所绘制的发送按钮;空白的发送不起作用.

createNativeChat 并且需要两个只画出原生行 :

配置默认变化是什么
quickReplyLook"chip""pill": 中性填充药丸并有粗体标签,至少 NATIVE_CHAT_METRICS.quickReplyMinHeight (40)dp高,取而代之的是i's 32-tall 概述芯片.
quickReplyScrollBelowWidth无( 总是包)在这个窗口宽度下方,在dp中,芯片坐落在一行滚动的侧道上,而不是包接.

芯片坐着 NATIVE_CHAT_METRICS.quickReplyGap (8)dp 分道扬镳.

ChatThread 3个道具 用于一个主机 大小的房间周围 线程( 带键盘的小电话) :

  • foldQuickReplies 把筹码放出去 草稿和名单都留下.
  • onNoticeHeight(height) 发送失败通知的高度为 dp 每个布局,当没有绘制时,则0(除去后,线程转动) 只读,未挂载). 它排除了通知上的空白: theme.spacing(0.5) 在作曲家 在紧凑的外表, theme.spacing(2) 在警戒状态.
  • onComposerFocusChange(focused) 报告田间采取和丢失 重点,以及 false 当它消失的时候,它集中, 所以一个宿主隐藏它 铬,而有人 类型永远不会隐藏.

复制

每个句子都需要配置,没有默认. PT_BR_* 财务报告和审定财务报表 EN_US_* 为航道打包船(CHAT_SERVER_COPY)和屏幕 (单位:千美元)CHAT_UI_COPY;通过一手。 角色标签是角色配置的一部分, 所以每个表面都显示一个角色的同名.

版本与发布记录

@12-apps/chat 共发布 6 个版本,首次发布于 2026/10/02;过去 12 个月发布了 6 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.3.0latest2026/10/1028 天前
1.2.12026/10/061 个月前
1.2.02026/10/061 个月前
1.1.02026/10/021 个月前
1.0.02026/10/021 个月前
0.0.0-stage2026/10/021 个月前

关于 @12-apps/chat 的常见问题

@12-apps/chat 是什么?

双方对一出作品的对话线索,每出作品仅由主机选择的角色标签显示:框架中立的 HTTP 路由,每个角色写出窗口,一个联系-信息过滤器和快速回复,加上由@12-apps/ui p所建的一出线程屏幕

如何安装 @12-apps/chat?

在项目目录运行 npm install @12-apps/chat,或使用 pnpm add / yarn add / bun add。

@12-apps/chat 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/12-apps__chat 是否存在。

@12-apps/chat 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@12-apps/chat 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@12-apps/chat 可以商用吗?

@12-apps/chat 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@12-apps/chat 的下载量有多少?

根据 npm 官方下载统计,@12-apps/chat 在 2026/10/04 – 2026/11/02 这 30 天内被下载 32,654 次,日均约 1,088 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@12-apps/chat 还在维护吗?

最新版本 1.3.0 发布于 2026/10/10(28 天前);至今共发布 6 个版本,其中过去 12 个月发布了 6 个;首次发布于 2026/10/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。