更新记录

1.0.0(2026-07-19)

首发:离线优先 + 实时协作的 CRDT 同步插件:自研(内置 CRDT 协同引擎,即 Yjs 的 原生实现)核心 + 本地 sqlite 持久化 + UTS Web


平台兼容性

uni-app x(5.14)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × 5.0 12 × ×

nex-sync —— 离线优先 CRDT 同步

自研离线优先 + 实时协作的 CRDT 同步核心, 经原生绑定层提供,UTS 做桥接层(对象包装 + WebSocket 长连接编排), 把能力暴露成 uni-app 可调的 JS 对象 API。仅支持 App 端(Android / iOS),H5 / 小程序加载不了原生库。

同一份 utssdk 插件同时支持 uni-app x(uvue)经典 uni-app(vue3),无需分叉。 本插件是本仓最复杂的对象型 + 异步 + 长连接插件:本地 sqlite 持久化(write-behind + snapshot 合并)、 兼容 y-sync v1 协议、Awareness 实时存在感、Collection 文档集合。自研 + bundled sqlite,无 OpenSSL/C 依赖。

API 速览(共 1 个工厂函数 + 8 个对象类,44 个对外方法)

顶层

成员 签名 说明
工厂 init(opts: SyncInitOptions): Promise<SyncEngine> 打开 sqlite、确定 deviceId、记录默认 serverUrl

SyncInitOptions = { dbPath: string; serverUrl?: string; deviceId?: string }

SyncEngine(5)

方法 签名 说明
openDoc openDoc(docId, opts?: OpenDocOptions): Promise<Doc> 从 sqlite 恢复 + 按 autoConnect 起 WS
getDoc getDoc(docId): Doc \| null 取已打开的 doc
closeDoc closeDoc(docId): Promise<void> flush + 停定时器 + 断连 + 移除
shutdown shutdown(): Promise<void> 所有 doc flush+close、刷盘、关 db
deviceId deviceId(): string 设备标识

OpenDocOptions = { serverUrl?: string; token?: string; autoConnect?: boolean }(autoConnect 默认 true)

Doc(11)

getMap(name) / getArray(name) / getText(name) / getCounter(name) 懒创建共享类型; collection(name) 取文档集合;awareness() 取存在感句柄;onChange(cb) 注册变更回调; toJson() 整文档 JSON;connect() / disconnect() 手动连接管理;flush(): Promise<void> 强制刷盘。

共享类型

类型 方法
YMap(6) set(key, valueJson) / get(key) / delete(key) / has(key) / keys() / toJson()
YArray(6) push(valueJson) / insert(index, valueJson) / delete(index, len) / get(index) / length() / toJson()
YText(4) insert(index, chunk) / delete(index, len) / length() / toString()
YCounter(3) increment(delta) / decrement(delta) / value()
Collection(5) upsert(id, valueJson) / findById(id) / list() / delete(id) / toJson()
Awareness(3) setLocalState(json) / getStates() / clearLocalState()
  • YMap / YArray / Collection 的 value 是 JSON 字符串;YText 是原生 string;YCounter 是整数。
  • 索引 / 长度 / 计数 delta 在 JS 侧是 number(桥接层转 i64 过 跨语言边界)。
  • 单个 JSON value ≤ 1MB、YText ≤ 1M 字符、单 state ≤ 64KB,超限抛错 / 静默丢弃(见 CRDT 收敛与守卫)。

用法

import { init } from "@/uni_modules/nex-sync";

// 1. 启动引擎(异步)
const engine = await init({
  dbPath: `${plus.io.PUBLIC_DOCUMENTS}/app-sync.db`,  // 平台可写路径
  serverUrl: "wss://sync.example.com/ws",
});

// 2. 打开文档(自动起 WS 同步)
const doc = await engine.openDoc("note-123", { autoConnect: true });

// 3. 协同读写(同步、即时)
const title = doc.getText("title");
title.insert(0, "Hello");

const meta = doc.getMap("meta");
meta.set("tag", JSON.stringify(["draft"]));

const todos = doc.collection("todos");
todos.upsert("t1", JSON.stringify({ text: "买菜", done: false }));

// 4. 监听变更(v1 走 UTS 端 poll 派发)
doc.onChange((eventJson: string) => {
  // {"docId":"note-123","kind":"update"} / {"kind":"awareness",...} / {"kind":"error",...}
  console.log("changed:", eventJson, doc.toJson());
});

// 5. 实时存在感
doc.awareness().setLocalState(JSON.stringify({ cursor: 5, name: "Alice" }));

// 6. 重要写强制刷盘
await doc.flush();

// 7. 收尾
await engine.shutdown();

CRDT 收敛与守卫

  • 离线写后合并:两端独立离线写,重连后经 y-sync v1 双向 state vector reconcile,最终收敛到同一状态(无丢失/无重复)。
  • 同 key / 同位置冲突:YMap 同 key 走 内置 CRDT 协同引擎 LWW 收敛;YText 同位置插入由 内置 CRDT 协同引擎 决定顺序但两端一致;YCounter 跨端单调(各端只写自己 key)。
  • 守卫不破坏 engine:超大 value(ValueTooLarge)/ 超长文本(DocLimitExceeded)/ 非法参数(InvalidParam)触发后,同 doc 后续操作仍正常;异步路径(observer / awareness / write-behind / WS)错误不抛主线程,经 onChange 的 error 事件 / flush().reject 传播。

平台与验证边界(诚实标注)

  • 仅 app-android / app-ios;H5、各家小程序不支持(加载不了原生库)。
  • 需自定义调试基座 / 云打包:本插件用到 ① 原生绑定层 的 原生运行依赖(Android)② OkHttp(Android 远程 Maven)③ 自编 原生扩展库(iOS)——标准基座 --compile 不解析这些依赖(报「找不到名称 jna/okhttp3」属环境墙,非桥接 bug);真机/整包须自定义基座。
  • iOS 慢操作 v1 同步执行init / openDoc / closeDoc / shutdown / flush 在 iOS v1 于 Promise executor 内同步执行(UTS-iOS 无本仓已验通用 GCD 后台范式);签名与 Android 一致(都 Promise),调用方 await 无差异,仅 iOS 这几个调用会短暂阻塞。真·GCD 后台化留后续。
  • observer v1 走 polldoc.onChange(cb) 由桥接层 200ms 轮询 doc.pollEvents() + awareness pollEvents() 派发(避开 callback-interface 跨 UTS 桥的零验证风险,「先 poll 后 callback」);原生 setChangeObserver 形态保留待后续。
  • 桥接编译/真机待验(gated):自研核心 107 测试全绿;UTS 桥接尚未经 HBuilderX cli --compile / 真机验证(与本仓 modbus/sheet/tuner 同状态),关键 gated 点见各端 index.uts 顶部 TODO:
    • Androidclass extends okhttp3.WebSocketListener + override 多方法(本仓首例);Uint8Array↔ByteArray/ByteString 转换;后台 Thread 内构造 Doc 时 setInterval 的线程亲和。
    • 真机 T1–T12:两端实时同步、离线写合并(T4/T5/T6 收敛硬门)、Awareness、重连退避、冷启动恢复待真机双端(内置 CRDT 协同引擎-warp / y-websocket 服务端)验收。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据。所有计算/处理均在本地完成,无任何网络请求、不发送数据到任何服务器。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。