@ados-agora/协作
为AdonisJS——Yjs(Hocuspocus),Automerce和PartyKit(对接)驱动程序,Redis后置存在,统一版本控制,锚定评论,Ace代码和React客户端钩. 阿戈拉生态系统的一部分.
安装
node ace add @adonis-agora/collaboration
快开始
node ace configure @adonis-agora/collaboration # provider + config/collaboration.ts
node ace collaboration:init # REST routes, controller, migrations
node ace make:collab-document researches/writing # shared types per document
线 config/collaboration.ts 还有你的 authorize() ( lib 默认从不授权) 和存储后端(LucidStorage, (中文(简体) ), FileSystemStorage 或属于自己的).
发动机
| 发动机 | 同步运行 | 最好还是 |
|---|---|---|
yjs (默认) | Adonis HTTP 服务器上的嵌入式 Hocuspocus | 独立来源 |
automerge | 在 Adonis 服务器上播放自定义房间 | 土著历史 |
partykit | 云浮工人+持久物体(对接) | 全球延迟, 单独来源 |
缔约方 Kit 设置 :
// config/collaboration.ts
{
engine: 'partykit',
partykit: { roomHost: 'meu-app.partykit.dev', jwtSecret: process.env.COLLAB_JWT_SECRET },
}
然后运行 collaboration:init --engine=partykit 脚手架上工人 partykit-worker/ 部署 npx partykit deploy。 。 。 .
接纳和东道主拥有的房间yjs(中文(简体) )
拥有房间耐用状态的应用软件有两个可选的钩子. 两者均适用于自主办 yjs 引擎; 其他引擎忽略它们(但 persistDocument 拒绝任何引擎上的麻黄室:
// config/collaboration.ts
{
// Opened after the token is verified and before `authorize`. It ends exactly once:
// `connected()` when the handshake completes, `closed()` when it never does
// (denied, authorize threw, socket dropped, shutdown). A later disconnect of a
// connected socket is not an admission event.
async beginAdmission(ctx, docName, socketId) {
return { connected: async () => {}, closed: async () => {} }
},
// Loaded through `storage.loadDocument`, but never seeded, stored, flushed on
// unload, versioned or restored by the driver — the app persists it its own way.
isEphemeralRoom: (docName) => docName.startsWith('projects/'),
}
服务器 API
import collaboration from '@adonis-agora/collaboration/services/main'
await collaboration.current.getDocumentText('researches/42/writing')
const version = await collaboration.current.createVersion('researches/42/writing', userId, 'v1')
collaboration.current.comments.list('researches/42/writing', 'text')
版本控制在引擎之间工作:全更新快照(Yjs/PartyKit)或原生头(Autocommerce). 每个空间都固定备注text-range, (中文(简体) ), canvas-object, (中文(简体) ), timestamp通过存储后端持续.
客户端钩子( 反应)
pnpm add @adonis-agora/collaboration-client
import {
CollaborationProvider,
useCollabDoc,
useAwareness,
useComments,
useVersions,
} from '@adonis-agora/collaboration-client'
<CollaborationProvider baseUrl="https://api.app" getHeaders={() => ({ cookie })}>
<Editor docName="researches/42/writing" />
</CollaborationProvider>
function Editor({ docName }: { docName: string }) {
const { doc, status } = useCollabDoc(docName) // Y.Doc + connection status
const { peers } = useAwareness(docName)
const { comments, create, resolve } = useComments(docName, 'text')
const { versions, create: createVersion } = useVersions(docName)
// feed doc into Tiptap/y-prosemirror…
}
从引擎中自动选择运输 GET /collaboration/token (Hocuspocus Provider或YPartyKit提供).
代码
图标
collaboration:init- 脚手架上文件目录、基准迁移(在配置数据库时)和党基特工人(--engine=partykit(中文(简体) )collaboration:prune --keep=20 [--doc=<name>] [--dry-run]——删除每个文档除N最新版本外的所有文本(呼号为:collaboration.pruneVersions({ keep })(中文(简体) )make:collab-document <name>——生成共享文档类型app/collaboration/documents/(空格 + 允许的主锚类型),可由前端导入
命令自动由 configure; 需要手动设置 commands: ['@adonis-agora/collaboration/commands'] 内 adonisrc.ts。 。 。 .
已打入文档登记册
货包装有阿森布勒 init 钩( 注册于 configure扫描 app/collaboration/documents/ 生成 .adonisjs/collaboration/documents.ts数字 :
import type { CollabDocumentName, CollabDocumentDefinition } from '.adonisjs/collaboration/documents.js'
function open(name: CollabDocumentName) { … } // autocomplete + exhaustiveness
刷新为 node ace codegen,dev服务器,测试或构建——与控制器/路由桶相同的生命周期.
REST 终点
内置的十个端点( Ken, 注释 CRUD, 版本, 二进制状态) 自动注册 脚下 /collaboration。 。 。 .
通过配置来保护他们——任何Adonis的中间软件或认证后卫的作品:
// config/collaboration.ts
routes: {
enabled: true,
prefix: '/collaboration',
middleware: [() => import('#middleware/auth_middleware')], // guards apply here
}
更喜欢完全控制? 手动禁用并注册到您想要的地方 :
// routes.enabled = false
import { collaborationRoutes } from '@adonis-agora/collaboration'
collaborationRoutes(router, {
prefix: '/api/collab',
middleware: [authMiddleware],
})
没有解析器, 符号端点会关闭( 401 ) : 通过 routes.resolveUser 或者先运行您的认证中间软件。 二进制 state POST为机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相机相.
路线类型安全警告:自动注册的路线在供应商的
ready()相位,它运行在编码热解后——所以它们可能不会出现在.adonisjs/server/routes.d.ts。如果您的应用程序依赖于生成的路由类型(例如 Tuyau),则使用手动模式: setroutes.enabled = false打电话collaborationRoutes(router)内start/routes.ts,其中总是取道.
编辑器绑定 (Tiptap)
客户会给你一个普通的 Y.Doc - 把它直接喂进Tiptap:
import Collaboration from '@tiptap/extension-collaboration'
import CollaborationCursor from '@tiptap/extension-collaboration-cursor'
import { useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { useCollabDoc, useAwareness } from '@adonis-agora/collaboration-client'
function Editor({ docName, user }: { docName: string; user: { name: string; color: string } }) {
const { doc, status } = useCollabDoc(docName)
const { peers } = useAwareness(docName)
const editor = useEditor({
extensions: [
StarterKit,
Collaboration.configure({ document: doc }),
CollaborationCursor.configure({ user }),
],
editable: status === 'connected',
})
return (
<>
<EditorContent editor={editor} />
{peers.map((peer) => (
<span key={peer.clientId} style={{ color: 'gray' }}>{peer.name ?? 'anon'}</span>
))}
</>
)
}
许可证
麻省理工学院