@可持久流/y可持久流
Yjs 持久流提供商 - 同步 Yjs在HTTP上的文档,带有自动服务器侧收缩和可选意识(存在)支持.
概览
此软件包提供使用 Yjs 持久流协议同步文档的 Yjs 提供者 。 与基于WebSocket的供应商不同,它使用标准的HTTP(默认的SSE,以长波为替代品)外加自动服务器侧收缩,使得部署和规模更加简单.
主要好处:
- 无 WebSocket 基础设施 - 使用标准HTTP负载平衡器和CDN的工程
- 自动收缩 - 服务器管理文档快照以保持快速同步
- 抓图网点 - 唤醒外部工人坚持最新快照
- 可缩放 - 无国籍服务器设计、储存在可持久流中的文档
- 在场支助 - 光标、选择和用户状态的可选意识
安装
npm install @durable-streams/y-durable-streams yjs y-protocols lib0
快速启动
import { YjsProvider } from "@durable-streams/y-durable-streams"
import * as Y from "yjs"
import { Awareness } from "y-protocols/awareness"
const doc = new Y.Doc()
const awareness = new Awareness(doc)
const provider = new YjsProvider({
doc,
baseUrl: "http://localhost:4438/v1/yjs/my-service",
docId: "my-document",
awareness,
})
provider.on("synced", (synced) => {
console.log("Synced:", synced)
})
使用量
仅文档( 无出席)
const provider = new YjsProvider({
doc,
baseUrl: "http://localhost:4438/v1/yjs/my-service",
docId: "my-document",
})
有认证
const provider = new YjsProvider({
doc,
baseUrl: "http://localhost:4438/v1/yjs/my-service",
docId: "my-document",
awareness,
headers: {
Authorization: "Bearer your-token",
},
})
手动连接
const provider = new YjsProvider({
doc,
baseUrl,
docId,
connect: false, // Don't connect automatically
})
// Set up listeners first
provider.on("synced", handleSync)
provider.on("error", handleError)
// Then connect
await provider.connect()
事件处理
// Sync state changes
provider.on("synced", (synced: boolean) => {
if (synced) {
console.log("Document is synced with server")
}
})
// Connection status changes
provider.on("status", (status: YjsProviderStatus) => {
console.log("Status:", status) // "disconnected" | "connecting" | "connected"
})
// Error handling
provider.on("error", (error: Error) => {
console.error("Provider error:", error)
})
清理
// Disconnect temporarily
provider.disconnect()
// Reconnect
await provider.connect()
// Destroy permanently
provider.destroy()
API 密码
伊兹提供商
class YjsProvider {
constructor(options: YjsProviderOptions)
// Properties
readonly doc: Y.Doc
readonly synced: boolean
readonly connected: boolean
readonly connecting: boolean
// Methods
connect(): Promise<void>
disconnect(): Promise<void>
destroy(): void
// Events
on(event: "synced", handler: (synced: boolean) => void): void
on(event: "status", handler: (status: YjsProviderStatus) => void): void
on(event: "error", handler: (error: Error) => void): void
}
选项
interface YjsProviderOptions {
doc: Y.Doc
baseUrl: string // Yjs server URL, e.g. "http://localhost:4438/v1/yjs/my-service"
docId: string // Document identifier (may contain forward slashes)
awareness?: Awareness // Optional awareness for presence
headers?: HeadersRecord // Optional auth headers (static strings or () => string)
liveMode?: "sse" | "long-poll" // Live update transport (default: "sse")
connect?: boolean // Auto-connect on construction (default: true)
}
服务器
软件包包括一个执行协议的Yjs服务器. 用于开发/试验:
import { YjsServer } from "@durable-streams/y-durable-streams/server"
const server = new YjsServer({
port: 4438,
dsServerUrl: "http://localhost:4437", // Durable streams server
})
await server.start()
console.log(`Yjs server running at ${server.url}`)
抓图网点
订阅一个可被唤醒的网页 匹配文档 :
await fetch(
`${server.url}/v1/yjs/my-service/__ds/subscriptions/snapshot-archive`,
{
method: "PUT",
headers: { "content-type": "application/json" },
body: JSON.stringify({
type: "webhook",
events: ["snapshot.available"],
document_pattern: "projects/**",
webhook: { url: "https://archive.example/hooks/yjs" },
lease_ttl_ms: 30_000,
}),
}
)
document_pattern 相对于服务的文档名称空间. *
匹配一个路径段并 ** 连续匹配。 根本的持久性
流服务器必须支持 Webhook 订阅 .
Webhook请求使用标准的持久流订阅有效载荷
签名。 通知是指有一个或多个更新的快照
不携带快照字节,并可能结合多个收缩。 对于
每项待定 .index 中,生成文档路径并获取其最新
速记 ?offset=snapshot返回时 { "done": true } 仅在
肖像画一直得到成功的坚持。 新订户观察未来
抓图,不要重放当时的抓图
创建.
符合性测试
包件包括检验是否合格 Yjs 服务器执行 。 默认情况下,测试会针对本地测试服务器运行. 要测试外部服务器:
# Run tests against an external Yjs server
YJS_CONFORMANCE_URL=http://localhost:4438/v1/yjs/test pnpm vitest run --project y-durable-streams
# Run tests with local test servers (default)
pnpm vitest run --project y-durable-streams
注意: 使用外部 URL 时会跳过“ 服务器重新启动” 测试, 因为需要启动/ 停止本地服务器 .
服务器协议 API
完整的协议规格见 YJS-PROTOCOL.md (英语)。 。 。 .
基础 URL 结构
每个文件通过一个有查询参数的单一URL访问:
{baseUrl}/docs/{docPath}?{queryParams}
地点:
baseUrl通常为http://host:port/v1/yjs/{service}docPath可包括前鞭(例如,project/chapter-1(中文(简体) )
关键操作
快照发现
GET {baseUrl}/docs/{docPath}?offset=snapshot
回返a 307 重新定向 改为:
?offset={N}_snapshot如果快照存在?offset=-1如果没有快照( 从开始读取)
读取快照
GET {baseUrl}/docs/{docPath}?offset={N}_snapshot
返回二进制 Yjs 速记 stream-next-offset 显示继续读取更新的页眉 .
读取/写入更新
GET {baseUrl}/docs/{docPath}?offset={N}&live=true
POST {baseUrl}/docs/{docPath}
- 读取: 从偏移处获取更新, 可选择为
live=true长花花花 - 写入: POST 原始 Yjs 更新字节(服务器处理 lib0 框架)
认识(现行)
GET {baseUrl}/docs/{docPath}?awareness=default&offset=now&live=true
POST {baseUrl}/docs/{docPath}?awareness=default
通过查询参数命名了意识流 。 使用SSE进行实时快递.
压缩
当更新超过阈值时, 服务器会自动压缩文档 :
- 读取当前状态( snapshot + 更新)
- 在当前平移时创建新快照
- 更新内部索引流
- 删除旧快照
压缩对客户透明 - 现有连接持续不间断.
错误回复
| 状态 | 代码 | 含义 |
|---|---|---|
| 400个 | INVALID_REQUEST | 无效路径或偏移 |
| 401 (中文(简体) ) | UNAUTHORIZED | 缺少/无效认证 |
| 404 (韩语) | SNAPSHOT_NOT_FOUND | 快照已删除( 重试) |
| 404 (韩语) | DOCUMENT_NOT_FOUND | 文档不存在 |
| 410个 | OFFSET_EXPIRED | 偏移太旧了 |
如何运作
提供商连接到使用耐用流管理文档存储的Yjs服务器:
- 快照发现 - 客户请求
?offset=snapshot,服务器重定向到当前快照或开始 - 快照装入 - 二进制 Yjs 状态为
stream-next-offset继续的页眉 - 实时更新 - 冲抵后逐步更新的长期民意调查
- 意识 - 可选的SSE流用于存在(浏览器、选择、用户信息)
服务器会在更新超过阈值时自动压缩文档,从而创建出新的快照. 这保持了新客户端的初始同步速度. 协议每个文档使用一个具有不同操作的查询参数的单一URL.
许可证
阿帕奇 - 2.0