Chatto 客户端
@chatto/client 是查托0.5服务器的客户端. 它连接到一个或
更多服务器,通过实时API保持数据流,并曝光
数据是反应状态 它也有请求和消息循环
和整合用。 它只保存服务器数据:主机状态
UI属于主机. 它不依赖UI框架。 捆绑
Chatto前端,ChattoBot,和"跑步机器人"的例子使用.
安装方式 npm install @chatto/clientnpm 软件包包含 ES 模块
和 TypeScript 声明,包括生成的协议类型。 使用节点.js
22岁或更晚的婴儿。 Svelte 可选; 使用时安装 Svelte 5
@chatto/client/svelte。模块路径可以在1.0之前改变.
客户端和服务器
一个客户端是一组孤立的服务器 具有实时传输和 工作背景。 为每个独立主机创建一个客户端. 一个进程可以 拥有多个客户端,每个客户端可以连接多个服务器:
import { createClient } from '@chatto/client';
const client = createClient();
process.on('SIGTERM', () => client.close());
try {
const eu = client.connect({ serverUrl: 'https://eu.example', apiKey: euKey });
const us = client.connect({ serverUrl: 'https://us.example', apiKey: usKey });
await Promise.all([
eu.run((ctx) => ctx.reply(`Hello from EU, you said: ${ctx.message.body}`)),
us.run((ctx) => ctx.reply('Hello from US'))
]);
} finally {
// Close every server and stop all background work.
client.close();
}
connect() 添加一个带有固定无记名符号的服务器, 如 bot API 密钥,
并归还它。 该标志只保存在记忆中: 它永远不会被更新或
写入设备存储 . client.server(id) 返回服务器
客户有。 都一样 Server 类型:服务器的数据、事件和
请求是一个对象.
server.reportPresence() 在服务器运行时将账户显示为在线
打开:一旦服务器接受密钥,客户端就会发送出存在心跳
每30秒钟一次。 之后 close(),账户显示在60之内的离线
秒数。 它永远不会改变账户 保存的存在选择.
答复信件
server.run(handler) 等待服务器接受密钥, 同时
服务器无法访问,然后调用 handler 发送到
取景者(密钥的帐户)。 默认这些是直接消息,
并回复了观众的留言。 作用,
@here,以及 @all 提及是单独的原因(role_mention, (中文(简体) ),
here_mention, (中文(简体) ), all_mention) 使您能够 reasons。消息为
处理有序。 处理器收到上下文 :
await server.run(
async (ctx) => {
ctx.message; // the addressed message: id, roomId, threadRootId, authorId, body, reasons
const thread = await ctx.readThread(); // messages with `fromViewer`
await ctx.withTyping(async () => {
await ctx.reply(await answer(thread.messages));
});
await ctx.addReaction('eyes');
},
{
signal, // stops the loop; without it, the loop stops when the server closes
reasons: ['mention', 'direct_message'], // default: also 'reply'
onStatus: (status) => console.log(status.state),
onError: (error) => console.error(error) // keep running after a failure
}
);
ctx.signal 当循环因任何理由停止时中止; 传递给
你自己的可以工作. ctx.conversationKey 将对话范围到
观众、房间、线条和发送者. ctx.refreshTyping() 刷新输入
指标一次.
run 何时决定 signal 中止或服务器关闭 。 它拒绝当
服务器拒绝密钥或不支持此客户端,并且,不
onError,与处理器的第一个失败.
事件、状况和状态
server.consumeEvents({ signal, onEvent, onStatus })处理 按顺序排列实时事件.run用起来.onEvent(event, { signal })接收到一个信号,当循环因任何原因停止时,会中止 当服务器结束会话时的例子。 多达1 000起事件等待 对于一个慢处理器;除此之外,它们被放弃,并报告有缺口.onStatus接收connecting, (中文(简体) ),ready,以及reconnectingA级ready状态为gap: true意味着事件可能缺失,例如 因为服务器在重新连接后无法恢复流 。 虽然run等待服务器, aconnecting具有error报告 每一次尝试都失败,例如无法到达的服务器.- 一个服务器
connect添加接收创建时的事件, 也 在此之前ready()决断,并保存在第一个consumeEvents或者说run电话 后一召报先有漏. onEvent(listener)财务报告和审定财务报表onSnapshot(listener)接收事件和新 直接快照,无回环.- 服务器的数据是被动的:例如
roomList.rooms, (中文(简体) ),notifications.occurrences, (中文(简体) ),projection.users,以及rooms.messages(id){\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}一个呼号 直播室时间表.
直播时间表和房间商店
rooms.messages(roomId) 财务报告和审定财务报表 rooms.thread(roomId, rootId) 返回一个活
时间表。 时间线读取它的最新一页 当你第一次得到它。 实时
发送后添加新信件并应用编辑和删除,所以主机
不为每次更改再次读取线程.
isCurrent当装入最新页面而未读取或重新连接时为真 正在等待重新装入 .events然后有最新消息.loadError错误的读取失败, 或失去房间。 打电话restoreLatestWindow()在读取失败后再次读取.- 默认情况下,客户端会保留最近使用的10个房间的商店
(时间线、文件列表、针头列表和成员列表)和最近20个
使用线程.
一个呼叫
rooms.messages, (中文(简体) ),rooms.files, (中文(简体) ),rooms.pins,或rooms.members使用房间;呼叫rooms.thread只使用线程。 客户 处理旧的仓库; 下一个调用返回新商店, 它 又读了 不要同时使用更多的房间或线程. 留着 设置客户端选项keepRecent,例如createClient({ keepRecent: { threads: 50 } })。 。 。 . - 已处理的时间表不再更新, 也永远不会更新 。 如果你坚持
跨越漫长的等待时间,例如直到
isCurrent时停止isDisposed成为真实的, 并再次获得时间线.
使用 readThread 而不是当你需要一个快照 而没有实时更新.
rooms.members(roomId) 在不启动目录的情况下返回成员存储
扫描 打电话 store.loadRoomMembers(roomId) 消费者需要完整名单时;
服务器商店将推迟此请求, 直至得知房间访问 。 使用
members.searchMembers(query) 不装满
列表中选择一个选项。 空查询返回绑定的建议页。 回收刷新器
只有明确要求的目录.
对于引用,呼叫 members.retainMentions(handles) 并释放
当内容离开视图时返回订阅 。 读取 mentionMembers
用于当前配置。 这些共享的, 房间扫描的搜索只匹配
页面,不要求完整目录。 缺少的手柄保持纯文本 .
访问和成员更改了丢弃的缓存匹配和旧的栅栏读取.
准备和失败
ready()当服务器拒绝密钥, 当服务器是 无法到达或失败, 或当服务器发布时不支持此功能 客户端。 背景服务器重试; 调用ready()再来一次 等待下一次尝试.run()等待通过这些重复.sessionEnded当服务器拒绝或撤销密钥时,则变为真实.realtimeUnsupported当服务器不支持时变为真实 客户端的实时协议. 这两起事件都没有到来,而且事件 循环拒绝; 关闭服务器.- 一个服务器
connect添加后保留一个持久的 WebSocket, 也在 客户端,有一个选定的活服务器. server.close()从客户端中删除服务器并停止其实时 交货。 飞行中的请求失败, 即使服务器应用了它们, 没有 发出新的请求。 当最后一个服务器connect增加了关闭, 客户端停止计时器,所以一个节点主机可以退出.
请求
服务器和无国籍者 Api 拥有同样的请求助手。 每个
请求有十秒的超时, 不自动重试; 失败的写入可以
仍然到达服务器 .
| 帮助 | 对 |
|---|---|
getMessage({ roomId, messageId }) | 读取一个信件, 包括没有下载地址的附件元数据 |
createMessage(destination, body, { inReplyTo }) | 发送一个消息; 返回其 id |
prepareMessage(destination, body, { inReplyTo }) | 为明确重试准备一个逻辑发送 |
postMessage(destination, body) | 发送任意长度的文本, 以 8000 个代码点为部分 |
reply(message, body) | 在信件线索中标注 |
readThread(location, { after, limit }) | 读取线程; after 仅读取新信件 |
readAttachment({ roomId, attachmentId }, opts) | 读取文件; maxImageSize 更改服务器上的图像大小 |
refreshTyping(destination) | 刷新打字指标一次 |
withTyping(destination, work) | 显示打字指标,同时 work 运行 |
addReaction({ roomId, messageId }, emoji) | 对消息的反应 |
addressedMessage(event, { reasons }) | 承认一个事件是给观众的讯息 |
请求帮助者接受 { signal } 作为他们最后的论点。 准备的行动
收进去 send({ signal })。 。 。 . postMessage, (中文(简体) ), reply, (中文(简体) ),
财务报告和审定财务报表 ctx.reply 返回 ids 新信件内容。 其他帮助者包括:
conversationKey, (中文(简体) ), replyDestination, (中文(简体) ), withTyping 财务报告和审定财务报表 startTyping 页:1
自定义输入更新,以及 createDeliveryTracker 用于重放过滤器.
等待最后答复 withTyping(destination, work) 发布前
留言。 帮助者停止计时器 等待任何等待更新,与
2秒请求超时。 无法成功刷新
在消息后恢复打字指示符.
信件机构可以包含emoji的短码,例如: Hello :wave:编辑
服务器保存此文本。 客户端选择如何显示. 对于定制渲染器,
@chatto/client/messaging/emojiShortcodes 出口 resolveEmoji(name) 页:1
对大小写敏感的内置名称和 emojiShortcodes(text) 源区域
有 Unicode 或未知结果。 在Unicode 字母、数字和组合旁的标记
标记或下划线. emojiShortcodeQuery(textBeforeCursor)
读取一个部分名称,其自动完成的开放边界相同。 解析
先标出并只扫描出品;留下代码和URL不变. 自定义emoji
未支持资产.
Skin-tone 短码使用 Slack 语法 : :thumbsup::skin-tone-4: 显示为
👍🏽. 通音从2 (光)到6 (暗). 支持的混合通配对使用两个
数字在一个后缀中,例如 :couple::skin-tone-2-6:不支持的组合
保持文字状态。 反应API没有周围的结肠取同名.
旧服务器可以拒绝这些反应名称;没有连接底部增加值
所需经费。 现有名称和Unicode消息内容保持不变.
emojiNameFromUnicode(emoji) 返回选定的稳定反应名称
Unicode emoji,包括其语气. 未知序列返回 undefined。 。 。 .
对新选择使用此帮助; 保持现有反应名称不变 .
mise codegen-emoji 构建客户端语气映射、服务器映射和转换器映射
(单位:千美元)tools/emoji-map.json)来自gemoji和被捆绑的Unicode Emoji 15.0数据.
转换器应该查找此地图中的完整名称, 而不是附加 a
修饰为基格. 生成的地图在运行时不需要网络呼叫 .
对于需要重试安全性的发送,保留准备操作:
const send = server.prepareMessage(destination, 'Hello');
const { id } = await send.send({ signal });
// After a lost response, call send.send() again with the same operation.
每个准备的发送分配一个UUID. 精确重试使用此密钥和相同
参数。 UI 消息 API 也曝光 prepareMessage(input) 并保留
上传附件ID. 准备的寄件留在记忆中。 他们不再重复了
距离第一次投球还有30分钟 MessageSendExpiredError。 。 。 .
在启动新发送前检查原始结果 。 需要重试安全性
所有用于支持信息创建的复制件; 旧服务器可以
忽略密钥. postMessage 财务报告和审定财务报表 reply 能够发送多个部件; 重试
整个帮手开始给这些零件发新信.
对于具有可更新证书的服务器,隐私重置无效保留
发送。 他们的下一个 send() 掷出 StaleResponseError 不再张贴.
在启动新发送前检查原始结果 。 固定托肯寄出还剩
跨隐私重置有效,但服务器关闭后无法发送.
对于任何其他请求, service(Service) 创建输入的连接客户端
服务器的认证. @chatto/client/types 有协议的
信息和服务,以及 @chatto/client/types/admin 行政部门
API : (英语)
import { UserService } from '@chatto/client/types';
const { user } = await server.service(UserService).getUser({
target: { case: 'userId', value: authorId }
});
无国籍请求
createApi 提出没有实时连接或保留状态的请求,
例如,在webhook处理器中,或用于在工作结束后可以继续的工作
服务器关闭 :
import { createApi } from '@chatto/client';
const api = createApi({ serverUrl, apiKey });
const { viewerId } = await api.ready({ signal }); // read once, then reused
await api.reply(message, 'Done', { signal });
它使用Connect JSON,拒绝重定向,并装入没有商店. 过
viewerId 当主机已经知道密钥的账户时, 例如
从 server.ready()· ; ready() 然后不发出请求.
除错输出
除错输出关闭了外部浏览器. 打电话 setDebugLogging(true) 写下来
到操纵台.
隐私
只请求联系所配置的服务器 。 每个服务器都收到主机的 IP地址,其证书,以及请求数据. 客户端不登录 符号或信件内容。 客户端移除其私人数据的复制件 认证、授权和隐私界限,并报告这些 与主机的边框; 参见 东道国国。 。 。 .
带有UI的应用程序
一个应用程序创建了一个拥有设备存储和源服务器的客户端, 启动运行时间,并报告用户查看的服务器。 只有这个 服务器保留一个持久的 WebSocket; 其它的则通过投票赶上:
import { createClient } from '@chatto/client';
export const client = createClient({
storage: 'device', // restore and keep the server catalogue and sessions
originServer: true, // the page's own server uses its cookie session
liveServers: 'selected'
});
client.start(); // pair each start() with a stop(), for example on unmount
client.setActiveServer(serverId);
const server = client.server(serverId);
一个进程可以有一个客户端和设备存储, 以及一个来源 服务器.
如果主机之前获取发现 registry.addServer,将答复作为
serverInfo 在第三个参数中避免另一个启动请求.
server.serverInfo.init() 共享飞行中发现请求。 继续
和解, 读取 server.serverInfo.discovery 用于答复,或 null 打开
失败。 后一通电话提出了新的要求.
本地存储和浏览器登录
本地主机可以通过 persistence: ServerRegistryPersistence 改为 createClient
改为 storage: 'device'此适配器恢复服务器注册和
单独存储认证。 最新的认证记录覆盖
综合目录快照; null 是清场记录。 写作
在返回之前必须持续完成。 失败的写入必须丢出或返回
false 从 writeAuthentication。读取返回必须返回承诺值.
主机拥有加密,访问控制,以及专属流程访问. 别
让两个进程在不进行共同协调的情况下延长同一个保存的会话.
SDK在发送更新前会保存刷新请求ID. 重新启动时 重新使用该标识,然后在替换证书之前保存和核实 返回新访问符 。 更新请求省略 cookie并拒绝 调头 保留所有认证字段,包括 OAuth 客户端ID 和 在持久记录中刷新请求ID .
@chatto/client/auth/oauth 提供 createOAuthFlow, (中文(简体) ), isOAuthCallback,以及
exchangeOAuthCode 为本地主机。 供应发现的授权 URL,the
主机的公开 OAuth 客户端 ID, 和一个字面回回回回 HTTP 调用 URL
或内置 chatto://desktop/servers/callback?mode=popup 调用。 这个
主机在系统浏览器中打开返回的授权 URL并接收
召回电话。 帮助者使用 S256 PKCE, 交易状态, 精确回调
验证,可选的发行人检查,以及有界限的活字交换. 留着
流动和回调记忆。 永远不要登录他们的代码或核查人。 主机拥有
环回听器、取消、同意UI和客户端元数据文档.
通过交回的证书 persistedBearerSession,将其与
emptyServerSession(),并向 registry.addServer。 。 。 .
SDK随后拥有更新和实时状态.
本地密码登录
passwordLogin(origin, { login, password }, { signal }) 返回可再生人类
允许直接密码登录的服务器上的证书。 本地主机供应
他们自己的安全密码域。 请求有15秒的超时和
64 KiB响应限制. 它省略了饼干,拒绝方向调整,并接受HTTPS
或回回回 HTTP 源代码,没有路径、查询或片段.
通过证书 persistedBearerSession 从
@chatto/client/auth/bearerSession,将其与 emptyServerSession()
从 @chatto/client/server/sessions,并向
client.registry.addServer(registration, session)。然后SDK 拥有符号
更新和实时状态。 此函数不保存密码或会话 .
出错会暴露一个状态和一个固定消息,从不显示服务器响应机构.
远程 signOutServer 请求还省略了 cookie 并拒绝重定向 .
东道国国
客户端保存服务器数据. 主机保持自己的状态, 如侧边栏 分组、 搜索结果、 调用媒体或查询缓存, 每个服务器旁边 :
- 尽可能从服务器获取衍生状态 。 随 服务器,不需要清理.
- 复制服务器数据的主机必须在服务器上清除副本
边界事件 :
onReset, (中文(简体) ),onRoomAccessLost, (中文(简体) ),onRoomAccessRestored, (中文(简体) ),onUserDeleted, (中文(简体) ),onAuthorityChanged, (中文(简体) ),onPermissionsChanged, (中文(简体) ),onSessionEnded,以及onDispose。 。 。 .onUpdate报告每个应用事件 资源。 服务器在移除后同步发布每个事件 它的拷贝. - 向隐私边界投放的收听器失败私有数据
清除:然后服务器不报告其投影为当前 。 这个
服务器等待承诺
onPermissionsChanged听众返回 . registry.watchStores(setup)电话setup每个服务器,当 注册在服务器收到实时数据之前创建它.
丝绒
导入 @chatto/client/svelte 一次,在组件读取服务器之前.
斯韦尔特然后用组件读取音轨, $derived,以及 $effect数字 :
<script lang="ts">
import '@chatto/client/svelte';
import { client } from '$lib/client';
let { serverId } = $props();
const server = $derived(client.server(serverId));
</script>
{#each server?.roomList.rooms ?? [] as room (room.id)}
<p>{room.name}</p>
{/each}
其他框架可以使用 setReadHook 财务报告和审定财务报表 subscribe 从
@chatto/client/reactivity 同样的.
语音通话
服务器跟踪其当前呼叫 projection.activeCalls客户端
包含没有媒体执行。 连接呼叫的主机执行
并留一个电话到
onRoomAccessLost 财务报告和审定财务报表 onDispose。 。 。 .
反应
软件包有一个小的信号库 @chatto/client/reactivity数字 :
signal, (中文(简体) ), computed, (中文(简体) ), effect, (中文(简体) ), effectRoot, (中文(简体) ), batch, (中文(简体) ), untrack, (中文(简体) ),
subscribe, (中文(简体) ), ReactiveMap,以及 ReactiveSet。计算值是懒惰的.
当最外层写入结束时,效果会同步运行.
发展
mise test-chatto-client # type checks, lint, and tests
src/types.ts 财务报告和审定财务报表 src/types/admin.ts 从
@chatto/api-types· ; mise codegen-proto 更新它们和软件包
检查过期时失败 .
见 维持状态 用于包检查和放行指令.
客户端和捆绑生成的协议代码使用Apache-2.0;
npm 包包括许可证和 a NOTICE 文档.