@dabble/patches

中文文档
0.34.2发布于 2026/10/27MITTypeScriptES Module近 30 天下载 2113

基于RFC 6902支持业务转型和最后写作胜负的不可移动 JSON 补丁执行

中文使用文档
文档目录31 节
  1. 这能解决什么问题?
  2. 范围:补丁是什么和不是
  3. 两个同步策略
  4. 目录
  5. 为什么是业务转型?
  6. 关键概念
  7. 安装
  8. 开始
  9. 客户端示例
  10. 服务器示例
  11. LWW 快速启动
  12. 核心组成部分
  13. 客户端
  14. 服务器侧
  15. 联网
  16. 意识( 频度和光标)
  17. 基本工作流程
  18. 客户端
  19. 服务器
  20. 实例
  21. 完成客户端设置
  22. 使用两种战略
  23. 高级主题
  24. 版本历史( H)
  25. 分支
  26. 共享工人
  27. 框架整合
  28. 自定义 OT 操作
  29. JSON 补丁
  30. 捐款
  31. 许可证

补丁

一个用于构建实时协作应用程序的TypeScript库. 您得到了两个同步策略: 协作文本的操作转换, 以及其它的 Last-Write-Wins .

Patches the Dog

这能解决什么问题?

建设实时协作功能难度大. 用户同时编辑,连接会降低中位变化,冲突解决速度会很快. 补丁处理这一切,所以你不必.

你的文档状态只是JSON。 用简单的回调更改它 :

doc.change(state => (state.title = 'New Title'));

更改立即适用于快速用户界面,然后同步到背景中的服务器。 离线? 没问题 重新上线时更改队列并同步 .

范围:补丁是什么和不是

补丁是一个 一般原始文献库它为实时系统提供组件(OT,LWW,同步传输,doc-store接口). 把它编成自己的后端和前端.

补丁知道:

  • JSON文件、JSON补丁操作和快照
  • 业务转型和最后写出冲突解决办法
  • 传送面 (WebSocket, SSE+REST, WebRTC) 移动客户端和服务器之间的变化
  • HTTP 状态代码以 StatusError (401, 403, 404, 410) — 如此消耗的应用程序可以在响应上分出

补丁确实如此 没有 了解情况:

  • 用户、角色、邀请、成员或任何访问控制模式
  • 应用软件、项目、书籍、文件成品或任何特定应用术语
  • 电子邮件发送、姓名/电子邮件查询或任何身份服务
  • 失去访问权限时如何操作的 UX 政策( 耗用应用程序决定 403 是否意味着“ 显示一面旗帜 ” 、 “ 踢出 医生 ” , 或是其它任何内容)

如果一个特性感觉它属于Patches,但提到了一个应用概念(例如"一个项目的邀请"),它不属于这里——它属于一个级别上,在应用自己的客户端SDK或消费应用本身. 帕奇斯表面应该足够通用,可以支持任何实时系统.

两个同步策略

补丁给你两种解决冲突的方法。 为工作选择合适的工具.

业务转型(OT) - 当用户同时编辑相同内容时

  • 变化被明智地合并
  • 需要合作编辑文本
  • 示例: Google Docs 类协作

最后写- Wins (LWW) - 当最新的时标获胜

  • 更简单,更快,更可预测
  • 最适合设置、仪表板、画布对象
  • 图片使用这种方法 他们的多人游戏

决定很简单: 如果用户不编辑相同 文本 合作使用 LWW。 它更快,更容易调试,并完美地处理大多数实时的情景.

需要LWW订购名单吗? 使用 分数索引 维持秩序,没有OT.

大多数应用程序都使用两种策略:OT用于文档内容,LWW用于其他一切.

目录

为什么是业务转型?

"我不该用CRDT吗?"

还有 数量 联 合 国 意见 关于 这个我们在这里学到了什么 达布尔作家: CRDTs对长寿文档不进行缩放.

我们的一些用户有48万+操作的项目. 这些怪物花了几个小时重建 叶杰斯,在最优化的Y.js中负载为~4秒,而~20ms则会添加变化. 我们的OT图书馆? 负载为1-2ms并适用了0.2ms.

随着文件体积增大或寿命延长,OT性能保持平平而CRDTs减速. 对于大多数使用的案例,CRDTs的工作都很好. 但是,如果你正在建设 规模或长寿,OT赢得.

关键概念

集中式OT - 一个服务器充当真相的唯一来源。 没有对等复杂,没有向量钟,没有分布式共识头痛. 服务器查看所有变化的顺序,并广播犬科状态.

重置基础 - 当服务器有新的更改时, 您的客户端还没有看到, 您的待定更改会得到“ 重置” 上面 。 考虑一下 git rebase,但用于实时编辑.

线性历史 - 服务器维持一个直线 没有分支,没有叉子,没有基础设施层面的合并冲突.

抓图 - OT文档随时间而累积变化。 为了避免重放480k操作载荷,我们定期快照. 装入最新的快照, 应用最近的修改, 完成 .

不稳定的国家 - 每一个变化都会产生一个新的状态对象。 未改变的部分保持不变。 这使得React/Vue/Solid变得微不足道并能够进行廉价的平等检查.

更多信息: 业务转型深潜 | 算法函数

安装

npm install @dabble/patches

开始

客户端示例

import { Patches, OTStrategy, InMemoryStore } from '@dabble/patches';
import { PatchesSync } from '@dabble/patches/net';

interface MyDoc {
  text: string;
  count: number;
}

// 1. Create a strategy with its store
const strategy = new OTStrategy(new InMemoryStore());

// 2. Create the Patches instance
const patches = new Patches({
  strategies: { ot: strategy },
  defaultStrategy: 'ot',
});

// 3. Set up real-time sync
const sync = new PatchesSync(patches, 'wss://your-server-url');
await sync.connect();

// 4. Open a document
const doc = await patches.openDoc<MyDoc>('my-doc-1');

// 5. React to updates
doc.subscribe(newState => {
  console.log('Document updated:', newState);
  // Update your UI here
});

// 6. Make changes - they sync automatically
doc.change(draft => {
  draft.text = 'Hello World!';
  draft.count = (draft.count || 0) + 1;
});

见 补丁, (中文(简体) ), 补丁文件,以及 补丁同步 用于完整的API文档.

服务器示例

import express from 'express';
import { OTServer } from '@dabble/patches/server';

// Your backend store implementation
const store = new MyOTStoreBackend();
const server = new OTServer(store);

const app = express();
app.use(express.json());

// Get document state
app.get('/docs/:docId', async (req, res) => {
  const { state, rev } = await server.getDoc(req.params.docId);
  res.json({ state: state ?? {}, rev });
});

// Commit changes
app.post('/docs/:docId/changes', async (req, res) => {
  try {
    const changes = await server.commitChanges(req.params.docId, req.body.changes);
    res.json(changes);
    // Broadcast to other clients via WebSocket
  } catch (error) {
    const status = error.message.includes('out of sync') ? 409 : 500;
    res.status(status).json({ error: error.message });
  }
});

app.listen(3000);

见 服务员 用于完整的API文档.

LWW 快速启动

对于 Last-Write-Wins 同步, 请使用 LWW 特定商店和战略 :

// Client
import { Patches, LWWStrategy, LWWInMemoryStore } from '@dabble/patches';
import { PatchesSync } from '@dabble/patches/net';

const strategy = new LWWStrategy(new LWWInMemoryStore());
const patches = new Patches({
  strategies: { lww: strategy },
  defaultStrategy: 'lww',
});

const sync = new PatchesSync(patches, 'wss://your-server-url');
await sync.connect();

const doc = await patches.openDoc<UserPrefs>('user-prefs');

doc.change(draft => {
  draft.theme = 'dark';
  draft.fontSize = 16;
});
// Server
import { LWWServer } from '@dabble/patches/server';

const store = new MyLWWStoreBackend();
const server = new LWWServer(store);

app.post('/docs/:docId/changes', async (req, res) => {
  const result = await server.commitChanges(req.params.docId, req.body.changes);
  res.json(result);
});

见 劳工服务员 财务报告和审定财务报表 最后写- Wins 概念 更多细节.

核心组成部分

客户端

补丁 - 主入口点。 管理文档生命周期,协调策略,处理持久性.

补丁文件 - 一份合作文件 音轨状态,乐观地应用变化,发布更新事件.

补丁同步 - WebSocket 连接管理器。 处理重接,分批,双向同步.

战略 - 算法特定逻辑:

  • OTStrategy -拥有一个 OTClientStore,处理重新定位和变化跟踪
  • LWWStrategy -拥有一个 LWWClientStore,处理时间戳合并

存储 - 持久性适配器:

  • InMemoryStore 编号 : LWWInMemoryStore - 测试和简单的应用
  • OTIndexedDBStore 编号 : LWWIndexedDBStore - 有离线支持的浏览器持续

服务器侧

服务员 - OT授权。 变换并行的更改,分配修改,保持历史.

劳工服务员 - LWW权威。 比较时间戳,存储当前字段值,没有历史.

补丁历史管理器 - 查询文档版本和历史.

补丁缓冲管理器 - 创建、列出和合并分支.

后端存储 - 为数据库执行这些接口:

  • OTStoreBackend - 对OT:更改、快照、版本
  • LWWStoreBackend - 关于LWW:有时间戳、快照的字段

见 持久性 用于存储模式和 后端存储接口 详细执行情况.

联网

WebSocket 运输 - 通过服务器进行的标准通信 PatchesWebSocket。 。 。 .

WebRTC 运输 - 提高认识的同龄人(诅咒、在场).

JSON-RPC议定书 - 客户端和服务器之间的电线协议.

什么时候用? 文档同步的 WebSocket 。 WebRTC 用于存在/ cursers 来减少服务器负载. 见 联网概况。 。 。 .

意识( 频度和光标)

显示谁在线,光标在哪里,选择什么. WebRTCAwareness 在对等对等的WebRTC连接上携带存在,在您已经打开的同步频道上,信号握手多键 WebSocketTransport 或者说 PatchesREST (SSE+REST) (英语). 没有第二次连接, 相同 clientId。 。 。 .

见 提高认识文件 详细执行情况.

基本工作流程

客户端

  1. 创建一个 Patches 战略实例
  2. 连接 PatchesSync 到您的服务器
  3. 打开文档 patches.openDoc(docId)
  4. 订阅更新 doc.subscribe()
  5. 以 doc.change() - 它们自动同步

服务器

  1. 创建 OTServer 或者说 LWWServer 用您的后端存储器
  2. 处理 commitChanges() 请求
  3. 向其他客户广播承诺的更改
  4. 可选使用 PatchesHistoryManager 用于版本和 PatchesBranchManager 用于分支

实例

完成客户端设置

import { Patches, OTStrategy, OTIndexedDBStore } from '@dabble/patches';
import { PatchesSync } from '@dabble/patches/net';

interface MyDoc {
  title: string;
  content: string;
}

// Production setup with IndexedDB for offline support
const strategy = new OTStrategy(new OTIndexedDBStore('my-app'));
const patches = new Patches({
  strategies: { ot: strategy },
});

const sync = new PatchesSync(patches, 'wss://api.example.com/sync');

// Handle connection state
sync.subscribe(state => {
  if (state.connected) {
    console.log('Connected and syncing');
  } else if (!state.online) {
    console.log('Offline - changes saved locally');
  }
});

// Handle errors
sync.onError((error, context) => {
  console.error(`Sync error for ${context?.docId}:`, error);
});

await sync.connect();

// Open and use a document
const doc = await patches.openDoc<MyDoc>('doc-123');

doc.subscribe(state => {
  renderUI(state);
});

doc.change(draft => {
  draft.title = 'My Document';
  draft.content = 'Hello, world!';
});

使用两种战略

import { Patches, OTStrategy, LWWStrategy, InMemoryStore, LWWInMemoryStore } from '@dabble/patches';

// Configure both strategies
const patches = new Patches({
  strategies: {
    ot: new OTStrategy(new InMemoryStore()),
    lww: new LWWStrategy(new LWWInMemoryStore()),
  },
  defaultStrategy: 'ot',
});

// OT for collaborative document editing
const manuscript = await patches.openDoc('manuscript-123'); // Uses default (ot)

// LWW for user settings
const settings = await patches.openDoc('settings-user-456', { strategy: 'lww' });

高级主题

版本历史( H)

文档在30分钟后自动快照. 浏览版本为 PatchesHistoryManager。 。 。 .

见 OTServer 版本 财务报告和审定财务报表 补丁历史管理器。 。 。 .

分支

创建文档分支,在隔离状态下工作,后合并. 用于"如果"情景或舞台编辑.

见 分支 财务报告和审定财务报表 补丁缓冲管理器。 。 。 .

共享工人

在共享工作人中运行补丁,用于交叉调制协调并减少内存使用.

见 共享工人文档。 。 。 .

框架整合

自定义 OT 操作

扩展操作处理器用于特定域的转换.

见 操作处理器。 。 。 .

JSON 补丁

补丁使用JSON Patch (RFC 6902) 在罩下. 你很少需要直接使用它,但它就在那里.

见 JSON 补丁文档。 。 。 .

捐款

欢迎捐款。 开放问题或提交拉力请求.

许可证

麻省理工学院

版本与发布记录

@dabble/patches 共发布 191 个版本,首次发布于 2025/04/19;过去 12 个月发布了 151 个版本。

版本发布日期距今
0.34.2latest2026/10/2718 天前
0.34.12026/10/071 个月前
0.34.02026/10/071 个月前
0.33.02026/10/011 个月前
0.32.32026/09/291 个月前
0.32.22026/09/261 个月前

关于 @dabble/patches 的常见问题

@dabble/patches 是什么?

基于RFC 6902支持业务转型和最后写作胜负的不可移动 JSON 补丁执行

如何安装 @dabble/patches?

在项目目录运行 npm install @dabble/patches,或使用 pnpm add / yarn add / bun add。

@dabble/patches 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dabble/patches 支持 ESM 还是 CommonJS?

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

@dabble/patches 可以商用吗?

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

@dabble/patches 的下载量有多少?

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

@dabble/patches 还在维护吗?

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