@univerjs-pro/collaboration-service 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -0
- package/README.zh-CN.md +241 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +492 -0
- package/dist/index.mjs +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# @univerjs-pro/collaboration-service
|
|
2
|
+
|
|
3
|
+
English | [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
The collaboration core of a Univer Collaboration server assembly, with support for Sheet, Doc, Slide, Board, and Base. The Service owns authoritative OT, continuous revisions, submission idempotency, snapshots, and the Unit lifecycle. When using Univer Collaboration Client, `@univerjs-pro/collaboration-endpoint` calls the Service according to the frontend protocol.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
Node Transport
|
|
9
|
+
→ UniverCollabEndpoint
|
|
10
|
+
→ UniverCollabService
|
|
11
|
+
→ IDatabaseAdapter
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This README focuses on Service middleware, lifecycle, and advanced APIs. For a first integration,
|
|
15
|
+
assemble Transport, Endpoint, Service, and a Database Adapter as described in the
|
|
16
|
+
[Collaboration quick start](https://office.univer.ai/collaboration/quick-start).
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add \
|
|
22
|
+
@univerjs-pro/collaboration-service \
|
|
23
|
+
@univerjs-pro/collaboration-endpoint \
|
|
24
|
+
@univerjs-pro/collaboration-transport-node \
|
|
25
|
+
@univerjs-pro/collaboration-database-sqlite \
|
|
26
|
+
@univerjs/protocol
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The Service, Database Adapter, and Univer SDK must use matching versions from the same release cohort.
|
|
30
|
+
|
|
31
|
+
## Create the Service
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { SQLiteDatabaseAdapter } from '@univerjs-pro/collaboration-database-sqlite';
|
|
35
|
+
import { UniverCollabService } from '@univerjs-pro/collaboration-service';
|
|
36
|
+
|
|
37
|
+
const database = new SQLiteDatabaseAdapter({
|
|
38
|
+
filename: './data/collaboration.sqlite',
|
|
39
|
+
});
|
|
40
|
+
const collabService = new UniverCollabService({ dbAdapter: database });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Next, create a `UniverCollabEndpoint` with this Service and register the Endpoint with Node Transport.
|
|
44
|
+
|
|
45
|
+
## Service API
|
|
46
|
+
|
|
47
|
+
`UniverCollabService` provides APIs for reading collaboration data, submitting changesets, and managing the Unit lifecycle. When integrated through Endpoint, `UniverCollabEndpoint` calls these APIs according to the frontend protocol:
|
|
48
|
+
|
|
49
|
+
- `getUnitLoadData()`: read the recovery data for the latest or a specific revision.
|
|
50
|
+
- `getUnitLoadDataWithBlocks()`: retrieve the same recovery data as `getUnitLoadData()`, together with all Sheet
|
|
51
|
+
blocks referenced by the snapshot. To replay subsequent changesets into a complete snapshot at
|
|
52
|
+
the target revision, use `UnitSnapshotMaterializer`.
|
|
53
|
+
- `getChangesets()`: read missing confirmed changesets.
|
|
54
|
+
- `submitChangeset()`: submit a client changeset.
|
|
55
|
+
- `createUnitFromData()`: create a Unit from Sheet, Doc, Slide, Board, or Base Unit data.
|
|
56
|
+
- `createUnitFromSnapshot()`: create a Unit from a Protocol `ISnapshot` and its Sheet blocks.
|
|
57
|
+
- `deleteUnits()`: soft-delete or permanently delete Units in a batch.
|
|
58
|
+
- `recoverUnits()`: recover soft-deleted Units in a batch.
|
|
59
|
+
|
|
60
|
+
For `createUnitFromData()`, `data.id` is the globally unique Unit ID and the initial revision must be `1`; the first confirmed changeset has revision `2`. A single delete or recover call accepts at most `MAX_UNIT_LIFECYCLE_BATCH_SIZE` Units, currently `100`, and the whole batch is all-or-nothing. After a hard delete, the Unit is permanently inaccessible and the same ID cannot be reused.
|
|
61
|
+
|
|
62
|
+
## Service middleware
|
|
63
|
+
|
|
64
|
+
Service middleware is the general lifecycle extension point for authorization, logging, external integrations, and similar concerns. The following example integrates Unit permissions.
|
|
65
|
+
|
|
66
|
+
The Service does not define roles or an ACL store. Applications protect Unit reads, creation, submissions, deletion, and recovery in the corresponding lifecycle middleware:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { CollabError } from '@univerjs-pro/collaboration-service';
|
|
70
|
+
|
|
71
|
+
collabService.use('submitChangeset', async (ctx, next) => {
|
|
72
|
+
const role = await acl.getRole(
|
|
73
|
+
ctx.userID,
|
|
74
|
+
ctx.request.changeset.unitID
|
|
75
|
+
);
|
|
76
|
+
ctx.customData.role = role;
|
|
77
|
+
|
|
78
|
+
if (role !== 'owner' && role !== 'editor') {
|
|
79
|
+
throw new CollabError('PERMISSION_DENIED', 'Unit is read-only');
|
|
80
|
+
}
|
|
81
|
+
await next();
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
| Action | When it runs | Visible fields | Retry semantics | Typical uses |
|
|
86
|
+
| --- | --- | --- | --- | --- |
|
|
87
|
+
| `readUnitData` | After Request creation, before reading the Adapter | `userID`, `customData`, and the concrete `request` | Once per Service API call | Read ACL, tenant, audit |
|
|
88
|
+
| `createUnit` | After preparing the initial snapshot, before atomic creation | `userID`, `customData`, `request.snapshot`, `request.sheetBlocks` | Once per create call | Creation permission, quotas, type restrictions |
|
|
89
|
+
| `deleteUnits` | After batch normalization, before calling the Adapter | `userID`, `customData`, `request.unitIDs`, `request.hardDelete` | Once per call; database races do not repeat it | Per-Unit delete ACL |
|
|
90
|
+
| `recoverUnits` | After batch normalization, before calling the Adapter | `userID`, `customData`, `request.unitIDs` | Once per call; database races do not repeat it | Per-Unit recovery ACL |
|
|
91
|
+
| `submitChangeset` | After creating the logical submission Request, before idempotency and OT | `userID`, `memberID`, `customData`, `request` | Once per logical submission; not repeated on database revision conflicts | Edit ACL, size limits, trace |
|
|
92
|
+
| `applyChangeset` | After OT aligns the changeset to the current revision, before applying it to the pending Unit state | `userID`, `memberID`, `customData`, `request`, `changeset`, `currentRevision`, `attempt` | Repeated after a database revision conflict | Validation of aligned mutations |
|
|
93
|
+
| `commitChangeset` | After applying the changeset to pending Unit state, before the Adapter checks the revision and writes | `userID`, `memberID`, `customData`, `request`, `changeset`, `expectedHeadRevision`, `attempt` | Repeated after a database revision conflict | Final revision checks and metrics |
|
|
94
|
+
|
|
95
|
+
`applyChangeset` and `commitChangeset` must be retry-safe. Non-reversible post-commit side effects belong in the corresponding event, or in a transactional outbox implemented by the concrete Database Adapter.
|
|
96
|
+
|
|
97
|
+
When Endpoint calls the Service, it passes the current HTTP `userID/customData` established by Transport middleware. Service middleware can therefore access the authenticated user, tenant, trace, and request-scoped ACL cache.
|
|
98
|
+
|
|
99
|
+
## Identity and customData
|
|
100
|
+
|
|
101
|
+
- `userID`: an application-provided identity string and the author of a confirmed changeset. The Service does not interpret its business meaning.
|
|
102
|
+
- `memberID`: the member ID of an online WebSocket Session; only submit and other calls associated with a realtime member provide it.
|
|
103
|
+
- `(unitID, sid, reqId)`: the client submission idempotency key.
|
|
104
|
+
- `context.customData`: data scoped to the current Service call, suitable for tracing, ACL caches, and timing.
|
|
105
|
+
|
|
106
|
+
Regular methods accept `CollabContext`; `submitChangeset()` accepts `CollabMemberContext`, which additionally contains `memberID`. Middleware in the same call can share trace data, ACL results, or timing data through `ctx.customData`. This data is not automatically persisted, logged, or sent to clients.
|
|
107
|
+
|
|
108
|
+
## Capability boundary and disposal
|
|
109
|
+
|
|
110
|
+
The Service does not provide HTTP, WebSocket, rooms, Presence, users, login, ACL storage, file management, or sharing. Transport, Endpoint, and the application provide these capabilities in the server assembly.
|
|
111
|
+
|
|
112
|
+
The application owns the injected Database Adapter. Dispose the Service before the Adapter during shutdown:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
await collabService.dispose();
|
|
116
|
+
await database.dispose();
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Advanced integration: wrap an application API
|
|
120
|
+
|
|
121
|
+
Applications may call the Service API directly from their own HTTP/RPC endpoints and business workflows. The caller must construct `CollabContext` and own the identity, external protocol, and error-mapping boundaries.
|
|
122
|
+
|
|
123
|
+
For example, expose an application endpoint `POST /api/units` on an existing Express `app`, reusing the `collabService` created above:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pnpm add express
|
|
127
|
+
pnpm add -D @types/express
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { randomUUID } from 'node:crypto';
|
|
132
|
+
import { json } from 'express';
|
|
133
|
+
import { UniverType } from '@univerjs/protocol';
|
|
134
|
+
|
|
135
|
+
app.post('/api/units', json({ limit: '1mb' }), async (request, response, next) => {
|
|
136
|
+
try {
|
|
137
|
+
const user = response.locals.user as { readonly userId: string };
|
|
138
|
+
const workbookData = request.body.data;
|
|
139
|
+
const unitID = randomUUID();
|
|
140
|
+
|
|
141
|
+
const result = await collabService.createUnitFromData(
|
|
142
|
+
{
|
|
143
|
+
type: UniverType.UNIVER_SHEET,
|
|
144
|
+
data: { ...workbookData, id: unitID, rev: 1 },
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
userID: user.userId,
|
|
148
|
+
customData: { traceId: randomUUID() },
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
response
|
|
153
|
+
.status(result.status === 'created' ? 201 : 200)
|
|
154
|
+
.json(result);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
next(error);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`POST /api/units` is an application API, not a protocol route used by Univer Collaboration Client. This example assumes Express authentication middleware has set `response.locals.user`. The application must also validate `request.body.data` and map `CollabError` to application API responses in error middleware. If the application needs a product record or owner ACL, create it explicitly in the same business workflow and handle compensation on failure.
|
|
162
|
+
|
|
163
|
+
## Advanced integration: submit changesets from background jobs
|
|
164
|
+
|
|
165
|
+
A background job can read the latest Unit revision and call `submitChangeset()` directly. The following example assumes `task` is the current task supplied by the job system, `task.id` remains stable across retries, and `task.mutations` already uses a mutation format supported by Univer:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
const context = {
|
|
169
|
+
userID: task.userID,
|
|
170
|
+
memberID: `background:${task.id}`,
|
|
171
|
+
customData: { taskID: task.id },
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const current = await collabService.getUnitLoadData(
|
|
175
|
+
{
|
|
176
|
+
unitID: task.unitID,
|
|
177
|
+
type: task.type,
|
|
178
|
+
revision: 0,
|
|
179
|
+
},
|
|
180
|
+
context
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
const result = await collabService.submitChangeset(
|
|
184
|
+
{
|
|
185
|
+
changeset: {
|
|
186
|
+
unitID: task.unitID,
|
|
187
|
+
type: task.type,
|
|
188
|
+
baseRev: current.targetRevision,
|
|
189
|
+
revision: current.targetRevision + 1,
|
|
190
|
+
sid: `background:${task.id}`,
|
|
191
|
+
reqId: 1,
|
|
192
|
+
userID: context.userID,
|
|
193
|
+
memberID: context.memberID,
|
|
194
|
+
mutations: task.mutations,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
context
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (result.status === 'rejected' || result.status === 'retry') {
|
|
201
|
+
throw result.error;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`sid/reqId` is the submission idempotency key. A retry keeps `unitID/type/sid/reqId`; its `baseRev` may advance only as the awaiting submission is transformed by confirmed changesets ordered before it, and must not advance past its own confirmed revision. Callers are responsible for this causal API contract. `memberID` only identifies the source of the submission. Background jobs do not need to create a WebSocket Session, and the Service does not check whether that member is online.
|
|
206
|
+
|
|
207
|
+
`collabService` itself is network-agnostic and does not send WebSocket messages. When a `UniverCollabEndpoint` is created, the Endpoint listens to the same `collabService` instance's `changesetCommitted` event. After a background submission succeeds, the Endpoint broadcasts the confirmed changeset to online clients in the current process that have JOINed the Unit. Because the background job's `memberID` does not correspond to an online Session, no submitter is excluded and all of those clients receive the change in realtime.
|
|
208
|
+
|
|
209
|
+
This event subscription only works within the current process and Service instance. If the background job runs in another process or uses another `UniverCollabService` instance, the database commit remains correct, but the current Endpoint does not automatically receive a broadcast event. Clients can subsequently recover through missing changesets.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# @univerjs-pro/collaboration-service
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
Univer Collaboration 服务端组装中的协同核心,支持 Sheet、Doc、Slide、Board 和 Base。
|
|
6
|
+
Service 负责权威 OT、连续 revision、提交幂等、snapshot 和 Unit 生命周期。使用 Univer
|
|
7
|
+
Collaboration Client 时,由 `@univerjs-pro/collaboration-endpoint` 根据前端协议调用。
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Node Transport
|
|
11
|
+
→ UniverCollabEndpoint
|
|
12
|
+
→ UniverCollabService
|
|
13
|
+
→ IDatabaseAdapter
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
本 README 重点说明 Service middleware、生命周期和高级 API。第一次接入应先按
|
|
17
|
+
[协同编辑快速开始](https://office.univer.ai/zh-CN/collaboration/quick-start)
|
|
18
|
+
完成 Transport、Endpoint、Service 和 Database Adapter 的组装。
|
|
19
|
+
|
|
20
|
+
## 安装
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add \
|
|
24
|
+
@univerjs-pro/collaboration-service \
|
|
25
|
+
@univerjs-pro/collaboration-endpoint \
|
|
26
|
+
@univerjs-pro/collaboration-transport-node \
|
|
27
|
+
@univerjs-pro/collaboration-database-sqlite \
|
|
28
|
+
@univerjs/protocol
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Service、Database Adapter 和 Univer SDK 必须使用同一 release cohort 的匹配版本。
|
|
32
|
+
|
|
33
|
+
## 创建 Service
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { SQLiteDatabaseAdapter } from '@univerjs-pro/collaboration-database-sqlite';
|
|
37
|
+
import { UniverCollabService } from '@univerjs-pro/collaboration-service';
|
|
38
|
+
|
|
39
|
+
const database = new SQLiteDatabaseAdapter({
|
|
40
|
+
filename: './data/collaboration.sqlite',
|
|
41
|
+
});
|
|
42
|
+
const collabService = new UniverCollabService({ dbAdapter: database });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
接着用这个 Service 创建 `UniverCollabEndpoint`,再把 Endpoint 注册到
|
|
46
|
+
Node Transport。
|
|
47
|
+
|
|
48
|
+
## Service API
|
|
49
|
+
|
|
50
|
+
`UniverCollabService` 提供协同数据读取、changeset 提交和 Unit 生命周期 API。通过
|
|
51
|
+
Endpoint 接入时,这些 API 由 `UniverCollabEndpoint` 根据前端协议调用:
|
|
52
|
+
|
|
53
|
+
- `getUnitLoadData()`:读取最新或指定 revision 的恢复数据。
|
|
54
|
+
- `getUnitLoadDataWithBlocks()`:获取与 `getUnitLoadData()` 相同的恢复数据,并附带 snapshot 引用的全部
|
|
55
|
+
Sheet blocks。若需将后续 changesets 重放为目标 revision 的完整 snapshot,可使用
|
|
56
|
+
`UnitSnapshotMaterializer`。
|
|
57
|
+
- `getChangesets()`:读取缺失的 confirmed changesets。
|
|
58
|
+
- `submitChangeset()`:提交客户端 changeset。
|
|
59
|
+
- `createUnitFromData()`:从 Sheet、Doc、Slide、Board 或 Base 的 Unit data 创建 Unit。
|
|
60
|
+
- `createUnitFromSnapshot()`:从 Protocol `ISnapshot` 及其 Sheet blocks 创建 Unit。
|
|
61
|
+
- `deleteUnits()`:批量软删除或永久删除。
|
|
62
|
+
- `recoverUnits()`:批量恢复软删除 Unit。
|
|
63
|
+
|
|
64
|
+
`createUnitFromData()` 的 `data.id` 是全局唯一 Unit ID,初始 revision 必须为 `1`;第一条
|
|
65
|
+
confirmed changeset 的 revision 为 `2`。单次删除或恢复最多接受
|
|
66
|
+
`MAX_UNIT_LIFECYCLE_BATCH_SIZE` 个 Unit,当前为 `100`,整批全有或全无。hard delete 后
|
|
67
|
+
Unit 永久不可访问,且相同 ID 不可复用。
|
|
68
|
+
|
|
69
|
+
## Service middleware
|
|
70
|
+
|
|
71
|
+
Service middleware 是通用的生命周期扩展点,可用于权限控制、日志和外部系统集成等。
|
|
72
|
+
下面以接入 Unit 权限为例。
|
|
73
|
+
|
|
74
|
+
Service 不定义角色或 ACL 存储。应用在对应的生命周期 middleware 中保护 Unit 读取、创建、
|
|
75
|
+
提交、删除和恢复:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { CollabError } from '@univerjs-pro/collaboration-service';
|
|
79
|
+
|
|
80
|
+
collabService.use('submitChangeset', async (ctx, next) => {
|
|
81
|
+
const role = await acl.getRole(
|
|
82
|
+
ctx.userID,
|
|
83
|
+
ctx.request.changeset.unitID
|
|
84
|
+
);
|
|
85
|
+
ctx.customData.role = role;
|
|
86
|
+
|
|
87
|
+
if (role !== 'owner' && role !== 'editor') {
|
|
88
|
+
throw new CollabError('PERMISSION_DENIED', 'Unit is read-only');
|
|
89
|
+
}
|
|
90
|
+
await next();
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
| Action | 触发时机 | 可见字段 | 重试语义 | 典型用途 |
|
|
95
|
+
| --- | --- | --- | --- | --- |
|
|
96
|
+
| `readUnitData` | Request 创建后、读取 Adapter 前 | `userID`、`customData`、具体 `request` | 每次 Service API 调用一次 | 读取 ACL、tenant、审计 |
|
|
97
|
+
| `createUnit` | 初始 snapshot 准备后、原子创建前 | `userID`、`customData`、`request.snapshot`、`request.sheetBlocks` | 每次创建调用一次 | 创建权限、配额和类型限制 |
|
|
98
|
+
| `deleteUnits` | 批次规范化后、调用 Adapter 前 | `userID`、`customData`、`request.unitIDs`、`request.hardDelete` | 每次调用一次;数据库竞态不重复 | 逐 Unit 删除 ACL |
|
|
99
|
+
| `recoverUnits` | 批次规范化后、调用 Adapter 前 | `userID`、`customData`、`request.unitIDs` | 每次调用一次;数据库竞态不重复 | 逐 Unit 恢复 ACL |
|
|
100
|
+
| `submitChangeset` | 逻辑提交 Request 创建后、幂等与 OT 前 | `userID`、`memberID`、`customData`、`request` | 每次逻辑提交一次;数据库 revision 冲突重试时不重复 | 编辑 ACL、大小限制和 trace |
|
|
101
|
+
| `applyChangeset` | changeset 已通过 OT 与当前 revision 对齐、应用到待提交 Unit 状态前 | `userID`、`memberID`、`customData`、`request`、`changeset`、`currentRevision`、`attempt` | 数据库 revision 冲突后重复 | 对齐后的 mutation 检查 |
|
|
102
|
+
| `commitChangeset` | changeset 已应用到待提交 Unit 状态、Adapter 检查 revision 并写入前 | `userID`、`memberID`、`customData`、`request`、`changeset`、`expectedHeadRevision`、`attempt` | 数据库 revision 冲突后重复 | 最终 revision 检查和指标 |
|
|
103
|
+
|
|
104
|
+
`applyChangeset` 和 `commitChangeset` 必须可重试。不可回滚的提交后副作用应放进对应 event
|
|
105
|
+
或由具体 Database Adapter 使用 transactional outbox。
|
|
106
|
+
|
|
107
|
+
Endpoint 调用 Service 时,会把 Transport middleware 建立的当前 HTTP
|
|
108
|
+
`userID/customData` 传入 Service,所以 Service middleware 可以读取认证用户、tenant、trace
|
|
109
|
+
和请求级 ACL 缓存。
|
|
110
|
+
|
|
111
|
+
## 身份与 customData
|
|
112
|
+
|
|
113
|
+
- `userID`:应用提供的身份字符串和 confirmed changeset 作者,Service 不解释其业务含义。
|
|
114
|
+
- `memberID`:在线 WebSocket Session 的成员 ID;只有 submit 等需要关联实时成员的调用传入。
|
|
115
|
+
- `(unitID, sid, reqId)`:客户端提交幂等键。
|
|
116
|
+
- `context.customData`:只属于当前 Service 调用,适合 trace、ACL 缓存和计时。
|
|
117
|
+
|
|
118
|
+
普通方法接收 `CollabContext`;`submitChangeset()` 接收额外包含 `memberID` 的
|
|
119
|
+
`CollabMemberContext`。同一次调用的 middleware 可以通过 `ctx.customData` 共享 trace、
|
|
120
|
+
ACL 查询结果或计时数据;这些内容不会自动持久化、记录日志或发送给客户端。
|
|
121
|
+
|
|
122
|
+
## 能力边界与资源释放
|
|
123
|
+
|
|
124
|
+
Service 不提供 HTTP、WebSocket、房间、Presence、用户、登录、ACL 存储、文件管理或分享。
|
|
125
|
+
在服务端组装中,这些能力由 Transport、Endpoint 和应用自己提供。
|
|
126
|
+
|
|
127
|
+
应用拥有注入的 Database Adapter。停止时先释放 Service,再释放 Adapter:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
await collabService.dispose();
|
|
131
|
+
await database.dispose();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 高级集成:封装应用 API
|
|
135
|
+
|
|
136
|
+
应用也可以直接使用 Service API 封装自己的 HTTP/RPC 接口和业务编排。调用方需要自己
|
|
137
|
+
建立 `CollabContext`,并承担身份、对外协议和错误映射边界。
|
|
138
|
+
|
|
139
|
+
例如,在已有 Express `app` 上提供应用接口 `POST /api/units`,并复用前文创建的
|
|
140
|
+
`collabService`:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
pnpm add express
|
|
144
|
+
pnpm add -D @types/express
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { randomUUID } from 'node:crypto';
|
|
149
|
+
import { json } from 'express';
|
|
150
|
+
import { UniverType } from '@univerjs/protocol';
|
|
151
|
+
|
|
152
|
+
app.post('/api/units', json({ limit: '1mb' }), async (request, response, next) => {
|
|
153
|
+
try {
|
|
154
|
+
const user = response.locals.user as { readonly userId: string };
|
|
155
|
+
const workbookData = request.body.data;
|
|
156
|
+
const unitID = randomUUID();
|
|
157
|
+
|
|
158
|
+
const result = await collabService.createUnitFromData(
|
|
159
|
+
{
|
|
160
|
+
type: UniverType.UNIVER_SHEET,
|
|
161
|
+
data: { ...workbookData, id: unitID, rev: 1 },
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
userID: user.userId,
|
|
165
|
+
customData: { traceId: randomUUID() },
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
response
|
|
170
|
+
.status(result.status === 'created' ? 201 : 200)
|
|
171
|
+
.json(result);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
next(error);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`POST /api/units` 是应用自己的 API,不是 Univer Collaboration Client 使用的协议路由。
|
|
179
|
+
示例假设 Express 认证 middleware 已设置 `response.locals.user`;应用还应校验
|
|
180
|
+
`request.body.data`,并在 error middleware 中把 `CollabError` 映射为应用 API 响应。需要
|
|
181
|
+
应用记录或 owner ACL 时,应在同一业务流程中显式创建并处理失败补偿。
|
|
182
|
+
|
|
183
|
+
## 高级集成:后台任务直接提交 changeset
|
|
184
|
+
|
|
185
|
+
后台任务也可以直接读取 Unit 的最新 revision,再调用 `submitChangeset()`。下面假设
|
|
186
|
+
`task` 是任务系统提供的当前任务,`task.id` 在重试时保持不变,`task.mutations` 已按 Univer
|
|
187
|
+
支持的 mutation 格式构造:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
const context = {
|
|
191
|
+
userID: task.userID,
|
|
192
|
+
memberID: `background:${task.id}`,
|
|
193
|
+
customData: { taskID: task.id },
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const current = await collabService.getUnitLoadData(
|
|
197
|
+
{
|
|
198
|
+
unitID: task.unitID,
|
|
199
|
+
type: task.type,
|
|
200
|
+
revision: 0,
|
|
201
|
+
},
|
|
202
|
+
context
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const result = await collabService.submitChangeset(
|
|
206
|
+
{
|
|
207
|
+
changeset: {
|
|
208
|
+
unitID: task.unitID,
|
|
209
|
+
type: task.type,
|
|
210
|
+
baseRev: current.targetRevision,
|
|
211
|
+
revision: current.targetRevision + 1,
|
|
212
|
+
sid: `background:${task.id}`,
|
|
213
|
+
reqId: 1,
|
|
214
|
+
userID: context.userID,
|
|
215
|
+
memberID: context.memberID,
|
|
216
|
+
mutations: task.mutations,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
context
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
if (result.status === 'rejected' || result.status === 'retry') {
|
|
223
|
+
throw result.error;
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`sid/reqId` 是提交幂等键。任务重试保持 `unitID/type/sid/reqId`;awaiting submission
|
|
228
|
+
仅可在被排在它之前的 confirmed changesets transform 后推进 `baseRev`,不能越过自身
|
|
229
|
+
已经 confirmed 的 revision。调用方负责遵守这一因果 API 契约。
|
|
230
|
+
`memberID` 只表示这次提交的来源;
|
|
231
|
+
后台任务不需要创建 WebSocket Session,Service 也不会检查该成员是否在线。
|
|
232
|
+
|
|
233
|
+
`collabService` 本身不感知网络,也不直接发送 WebSocket 消息。创建
|
|
234
|
+
`UniverCollabEndpoint` 时,Endpoint 会监听同一个 `collabService` 的
|
|
235
|
+
`changesetCommitted` event。后台任务提交成功后,Endpoint 会把 confirmed changeset
|
|
236
|
+
广播给当前进程中已经 JOIN 该 Unit 的在线客户端。由于后台任务的 `memberID` 不对应在线
|
|
237
|
+
Session,不会排除某个提交者,因此这些客户端都会实时收到变更。
|
|
238
|
+
|
|
239
|
+
这个事件监听只在当前进程、当前 Service 实例内生效。如果后台任务运行在其他进程,或使用
|
|
240
|
+
另一个 `UniverCollabService` 实例,数据库提交仍然正确,但当前 Endpoint 不会自动收到广播
|
|
241
|
+
事件;客户端随后可以通过缺失 changesets 恢复。
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object['defineProperty'](exports,Symbol['toStringTag'],{'value':'Module'});var e=Object['create'],t=Object['defineProperty'],n=Object['getOwnPropertyDescriptor'],r=Object['getOwnPropertyNames'],i=Object['getPrototypeOf'],a=Object['prototype']['hasOwnProperty'],o=(_0x1a3086,_0x256bd7,_0x300d0c,_0x53f2f2)=>{if(_0x256bd7&&typeof _0x256bd7=='object'||typeof _0x256bd7=='function'){for(var _0x467614=r(_0x256bd7),_0x1d7c26=0x0,_0xca0d6=_0x467614['length'],_0x4f1cb6;_0x1d7c26<_0xca0d6;_0x1d7c26++)_0x4f1cb6=_0x467614[_0x1d7c26],!a['call'](_0x1a3086,_0x4f1cb6)&&_0x4f1cb6!==_0x300d0c&&t(_0x1a3086,_0x4f1cb6,{'get':(_0x416c44=>_0x256bd7[_0x416c44])['bind'](null,_0x4f1cb6),'enumerable':!(_0x53f2f2=n(_0x256bd7,_0x4f1cb6))||_0x53f2f2['enumerable']});}return _0x1a3086;},s=(_0x17c74d,_0x516f10,_0x1e08c5)=>(_0x1e08c5=_0x17c74d==null?{}:e(i(_0x17c74d)),o(_0x516f10||!_0x17c74d||!_0x17c74d['__esModule']?t(_0x1e08c5,'default',{'value':_0x17c74d,'enumerable':!0x0}):_0x1e08c5,_0x17c74d));let c=require('@univerjs/protocol'),l=require('@univerjs-pro/collaboration'),u=require('@univerjs/core'),d=require('@univerjs/engine-formula'),f=require('@univerjs/sheets/locale/en-US');f=s(f,0x1);let p=require('node:async_hooks'),m=require('@univerjs-pro/bases'),ee=require('@univerjs-pro/boards'),te=require('@univerjs-pro/boards-chart'),ne=require('@univerjs-pro/boards-mind'),re=require('@univerjs-pro/boards-table'),ie=require('@univerjs-pro/docs-callout'),ae=require('@univerjs-pro/docs-chart'),oe=require('@univerjs-pro/docs-code'),se=require('@univerjs-pro/docs-latex'),ce=require('@univerjs-pro/docs-shape'),le=require('@univerjs-pro/docs-table'),ue=require('@univerjs-pro/embed'),de=require('@univerjs-pro/engine-formula-rust'),fe=require('@univerjs-pro/sheets-chart'),pe=require('@univerjs-pro/sheets-outline'),me=require('@univerjs-pro/sheets-pivot'),he=require('@univerjs-pro/sheets-shape'),ge=require('@univerjs-pro/sheets-sparkline'),_e=require('@univerjs-pro/slides'),ve=require('@univerjs-pro/slides-chart'),ye=require('@univerjs-pro/slides-table'),be=require('@univerjs-pro/thread-comment-resource'),xe=require('@univerjs/data-validation'),Se=require('@univerjs/docs-drawing'),Ce=require('@univerjs/docs-hyper-link'),we=require('@univerjs/drawing'),Te=require('@univerjs/sheets'),Ee=require('@univerjs/sheets-conditional-formatting'),De=require('@univerjs/sheets-drawing'),Oe=require('@univerjs/sheets-filter'),ke=require('@univerjs/sheets-formula'),Ae=require('@univerjs/sheets-hyper-link'),je=require('@univerjs/sheets-note'),Me=require('@univerjs/sheets-sort'),Ne=require('@univerjs/sheets-table'),h=require('@univerjs/thread-comment');var g=class extends Error{['code'];['retryable'];['details'];constructor(_0x34c3e6,_0x2940ee,_0x3fa39c={}){super(_0x2940ee,{'cause':_0x3fa39c['cause']}),this['name']='CollabError',this['code']=_0x34c3e6,this['retryable']=_0x3fa39c['retryable']??!0x1,_0x3fa39c['details']!==void 0x0&&(this['details']=_0x3fa39c['details']);}},_=0xa*0x400*0x400,v={'shouldCreate'(_0x489982){if(_0x489982['changesetBytes']>_)return!0x0;let _0x443f75=_0x489982['type']===c['UniverType']['UNIVER_DOC']?0x32:_0x489982['type']===c['UniverType']['UNIVER_SHEET']||_0x489982['type']===c['UniverType']['UNIVER_SLIDE']||_0x489982['type']===c['UniverType']['UNIVER_BOARD']||_0x489982['type']===c['UniverType']['UNIVER_BASE']?0x5:0x0;return _0x443f75>0x0&&_0x489982['revision']%_0x443f75===0x0;}};function y(_0x179013){return x(_0x179013),{'userID':_0x179013['userID'],'customData':_0x179013['customData']??Object['create'](null)};}function b(_0x2cb17e){if(x(_0x2cb17e),typeof _0x2cb17e['memberID']!='string'||_0x2cb17e['memberID']['length']===0x0)throw S('memberID\x20must\x20be\x20a\x20non-empty\x20string');return{'userID':_0x2cb17e['userID'],'memberID':_0x2cb17e['memberID'],'customData':_0x2cb17e['customData']??Object['create'](null)};}function x(_0x202832){if(!_0x202832||typeof _0x202832!='object')throw S('context\x20must\x20be\x20an\x20object');if(typeof _0x202832['userID']!='string'||_0x202832['userID']['length']===0x0)throw S('userID\x20must\x20be\x20a\x20non-empty\x20string');if(_0x202832['customData']!==void 0x0&&(_0x202832['customData']===null||typeof _0x202832['customData']!='object'||Array['isArray'](_0x202832['customData'])))throw S('customData\x20must\x20be\x20an\x20object');}function S(_0x1767f9){return new g('INVALID_REQUEST',_0x1767f9);}var Pe=class{['_middlewares']=new Map();['use'](_0x562bd2,_0x2826a6){let _0x411eb5=this['_middlewares']['get'](_0x562bd2)??[],_0xd0e653=_0x2826a6;_0x411eb5['push'](_0xd0e653),this['_middlewares']['set'](_0x562bd2,_0x411eb5);let _0x4670d4=!0x1;return{'dispose':()=>{if(_0x4670d4)return;_0x4670d4=!0x0;let _0x121f9f=_0x411eb5['indexOf'](_0xd0e653);_0x121f9f>=0x0&&_0x411eb5['splice'](_0x121f9f,0x1);}};}async['run'](_0x10b86e,_0x16042e,_0x1e19aa){let _0x5dbc19=[...this['_middlewares']['get'](_0x10b86e)??[]],_0x222381=async _0x20c45b=>{let _0x478017=_0x5dbc19[_0x20c45b];if(!_0x478017){await _0x1e19aa();return;}let _0x5dbda8=!0x1,_0x1474e5,_0x280b71=()=>{if(_0x5dbda8)throw Error('Middleware\x20for\x20action\x20'+String(_0x10b86e)+'\x20called\x20next()\x20more\x20than\x20once');return _0x5dbda8=!0x0,_0x1474e5=_0x222381(_0x20c45b+0x1),_0x1474e5;};try{await _0x478017(_0x16042e,_0x280b71);}catch(_0x23eb75){if(_0x1474e5)try{await _0x1474e5;}catch{}throw _0x23eb75;}if(!_0x5dbda8)throw Error('Middleware\x20for\x20action\x20'+String(_0x10b86e)+'\x20completed\x20without\x20calling\x20next()');await _0x1474e5;};await _0x222381(0x0);}['clear'](){this['_middlewares']['clear']();}},Fe={'debug':()=>void 0x0,'info':()=>void 0x0,'warn':()=>void 0x0,'error':()=>void 0x0},Ie={'increment':()=>void 0x0,'observe':()=>void 0x0};function Le(_0x50dc84){return _0x50dc84?{'debug':(..._0x39b970)=>C(()=>_0x50dc84['debug'](..._0x39b970)),'info':(..._0x44994a)=>C(()=>_0x50dc84['info'](..._0x44994a)),'warn':(..._0x340ba6)=>C(()=>_0x50dc84['warn'](..._0x340ba6)),'error':(..._0x13f93a)=>C(()=>_0x50dc84['error'](..._0x13f93a))}:Fe;}function Re(_0x4be7a1){return _0x4be7a1?{'increment':(..._0x2e4a75)=>C(()=>_0x4be7a1['increment'](..._0x2e4a75)),'observe':(..._0x1bfd51)=>C(()=>_0x4be7a1['observe'](..._0x1bfd51))}:Ie;}function C(_0x516678){try{_0x516678();}catch{}}function w(_0x16e73e){return{..._0x16e73e};}function ze(_0x3546d7){return{..._0x3546d7};}function Be(_0x2d4399){return{..._0x2d4399};}function Ve(_0x47a828){return{..._0x47a828};}function He(_0x22797d){return{'unitIDs':_0x22797d['unitIDs'],'hardDelete':_0x22797d['hardDelete']??!0x1};}function Ue(_0x4695cf){return{'unitIDs':_0x4695cf['unitIDs']};}function We(_0x5b8da1,_0x1225b7){return{'changeset':{..._0x5b8da1['changeset'],'userID':_0x1225b7['userID'],'memberID':_0x1225b7['memberID']}};}async function Ge(_0x635c41){let _0x3b7d12=qe(),_0x1b1bfb=(await Ke(_0x635c41,_0x3b7d12['service']))['snapshot']??_0x3b7d12['snapshot'];if(!_0x1b1bfb||_0x1b1bfb['unitID']!==_0x635c41['data']['id']||_0x1b1bfb['type']!==_0x635c41['type']||_0x1b1bfb['rev']!==0x1)throw Error('SDK\x20Unit\x20data\x20transform\x20returned\x20an\x20invalid\x20snapshot');return{'snapshot':_0x1b1bfb,..._0x3b7d12['sheetBlocks']['length']>0x0?{'sheetBlocks':_0x3b7d12['sheetBlocks']}:{}};}function Ke(_0x2fe8c4,_0x4567e2){switch(_0x2fe8c4['type']){case c['UniverType']['UNIVER_SHEET']:{let _0x31633f=structuredClone(_0x2fe8c4['data']);return(0x0,l['transformWorkbookDataToSnapshot'])({},_0x31633f,_0x31633f['id'],0x1,_0x4567e2);}case c['UniverType']['UNIVER_DOC']:{let _0x426862=structuredClone(_0x2fe8c4['data']);return(0x0,l['transformDocumentDataToSnapshot'])({},_0x426862,_0x426862['id'],0x1,_0x4567e2);}case c['UniverType']['UNIVER_SLIDE']:{let _0x142e42=structuredClone(_0x2fe8c4['data']);return(0x0,l['transformSlideDataToSnapshot'])(_0x142e42['resources'],_0x142e42,_0x142e42['id'],0x1,_0x4567e2);}case c['UniverType']['UNIVER_BOARD']:{let _0x2bb3d8=structuredClone(_0x2fe8c4['data']);return(0x0,l['transformBoardDataToSnapshot'])(_0x2bb3d8['resources'],_0x2bb3d8,_0x2bb3d8['id'],0x1,_0x4567e2);}case c['UniverType']['UNIVER_BASE']:{let _0x516480=structuredClone(_0x2fe8c4['data']);return(0x0,l['transformBaseDataToSnapshot'])({},_0x516480,_0x516480['id'],0x1,_0x4567e2);}}}function qe(){let _0x562220={},_0x658219=[],_0x191dee={'code':c['ErrorCode']['OK'],'message':''},_0x2ab31d=async(_0xad8a1e,_0x323728)=>{if(!_0x323728['snapshot'])throw Error('SDK\x20transform\x20attempted\x20to\x20save\x20an\x20empty\x20snapshot');return _0x562220['snapshot']=_0x323728['snapshot'],{'error':_0x191dee};};return{'service':{'saveSnapshot':_0x2ab31d,'updateSnapshot':_0x2ab31d,'saveSheetBlock':async(_0x4d4d24,_0x3ba436)=>{if(!_0x3ba436['block'])throw Error('SDK\x20transform\x20attempted\x20to\x20save\x20an\x20empty\x20block');return _0x658219['push'](_0x3ba436['block']),{'error':_0x191dee,'blockID':_0x3ba436['block']['id']};}},'sheetBlocks':_0x658219,get 'snapshot'(){return _0x562220['snapshot'];}};}function T(_0x192c22){if(_0x192c22['type']!==c['UniverType']['UNIVER_SHEET'])return[];let _0x4065e8=[],_0x48b012=new Set();for(let _0x232bcf of Object['values'](_0x192c22['workbook']?.['blockMeta']??{}))for(let _0x50197b of _0x232bcf['blocks'])_0x48b012['has'](_0x50197b)||(_0x48b012['add'](_0x50197b),_0x4065e8['push'](_0x50197b));return _0x4065e8;}var E={'code':c['ErrorCode']['OK'],'message':''},Je=class{['_dbAdapter'];['_contexts']=new WeakMap();['_capture']=new p['AsyncLocalStorage']();constructor(_0x3e95df){this['_dbAdapter']=_0x3e95df;}['createContext'](_0x6cb614,_0x5e3d92){let _0x13dafd={};return this['_contexts']['set'](_0x13dafd,{'databaseContext':_0x6cb614,..._0x5e3d92?{'snapshot':_0x5e3d92}:{}}),_0x13dafd;}async['capture'](_0xf1a27d){let _0x368c3a={'sheetBlocks':[]};return{'result':await this['_capture']['run'](_0x368c3a,_0xf1a27d),..._0x368c3a['snapshot']?{'snapshot':_0x368c3a['snapshot']}:{},'sheetBlocks':_0x368c3a['sheetBlocks']};}async['getUnitOnRev'](_0x5123eb,_0x42f3c2){let _0x5dd1c7=this['_requireBinding'](_0x5123eb),_0x5294ea=_0x5dd1c7['snapshot']?.['unitID']===_0x42f3c2['unitID']&&_0x5dd1c7['snapshot']['type']===_0x42f3c2['type']&&_0x5dd1c7['snapshot']['rev']===_0x42f3c2['revision']?_0x5dd1c7['snapshot']:await this['_database'](()=>this['_dbAdapter']['getSnapshot'](_0x5dd1c7['databaseContext'],_0x42f3c2['unitID'],{'revision':_0x42f3c2['revision']}));if(!_0x5294ea)throw O('Stored\x20Unit\x20snapshot\x20is\x20missing');if(_0x5294ea['unitID']!==_0x42f3c2['unitID']||_0x5294ea['type']!==_0x42f3c2['type']||!Number['isSafeInteger'](_0x5294ea['rev'])||_0x5294ea['rev']<0x1||_0x5294ea['rev']>_0x42f3c2['revision']||!Ye(_0x5294ea))throw O('Stored\x20Unit\x20snapshot\x20is\x20invalid');let _0x537d3b=await this['_database'](()=>this['_dbAdapter']['getChangesets'](_0x5dd1c7['databaseContext'],_0x42f3c2['unitID'],{'from':_0x5294ea['rev'],'to':_0x42f3c2['revision']}));return Xe(_0x42f3c2,_0x5294ea,_0x537d3b),{'error':void 0x0,'snapshot':_0x5294ea,'changesets':[..._0x537d3b['changesets']]};}async['getSheetBlock'](_0x254c88,_0x4fe561){let _0x486de0=await this['_database'](()=>this['_dbAdapter']['getSheetBlock'](this['_requireContext'](_0x254c88),_0x4fe561['unitID'],_0x4fe561['blockID']));if(!_0x486de0)throw O('Stored\x20Sheet\x20block\x20'+_0x4fe561['blockID']+'\x20is\x20missing');return{'error':void 0x0,'block':_0x486de0};}['getDeserializedSheetBlock'](_0x55ef4a,_0x365a46){return this['getSheetBlock'](_0x55ef4a,_0x365a46);}async['fetchMissingChangesets'](_0x140db5,_0x29513a){let _0x557e5a=await this['_database'](()=>this['_dbAdapter']['getChangesets'](this['_requireContext'](_0x140db5),_0x29513a['unitID'],{'from':_0x29513a['from'],'to':_0x29513a['to']}));return{'error':void 0x0,'changesets':[..._0x557e5a['changesets']],'latestRevision':_0x557e5a['latestRevision']};}['getResourcesRequest'](_0xdfa51,_0x21670a){return Promise['resolve']({'error':void 0x0,'resources':{}});}async['saveSnapshot'](_0xc76dd4,_0x2e0a9f){let _0x5604e0=this['_requireCapture']();if(!_0x2e0a9f['snapshot'])throw Error('SnapshotService\x20attempted\x20to\x20save\x20an\x20empty\x20snapshot');return _0x5604e0['snapshot']=_0x2e0a9f['snapshot'],{'error':E};}['updateSnapshot'](_0x564f02,_0x474873){return this['saveSnapshot'](_0x564f02,_0x474873);}async['saveSheetBlock'](_0x1f2ee6,_0x16e34e){let _0x43deca=this['_requireCapture']();if(!_0x16e34e['block'])throw Error('SnapshotService\x20attempted\x20to\x20save\x20an\x20empty\x20Sheet\x20block');return _0x43deca['sheetBlocks']['push'](_0x16e34e['block']),{'error':E,'blockID':_0x16e34e['block']['id']};}['saveChangeset'](_0x2ce53c,_0x409289){return D('saveChangeset');}['copyFileMeta'](_0xaeb4f,_0x16d14d){return D('copyFileMeta');}['getLatestCsReqIdBySid'](_0x3601fd,_0x5e1d29){return D('getLatestCsReqIdBySid');}['_requireBinding'](_0x28d529){let _0x55d720=this['_contexts']['get'](_0x28d529);if(!_0x55d720)throw Error('Snapshot\x20operation\x20is\x20missing\x20its\x20Database\x20context');return _0x55d720;}['_requireContext'](_0x298a6b){return this['_requireBinding'](_0x298a6b)['databaseContext'];}['_requireCapture'](){let _0x17e3da=this['_capture']['getStore']();if(!_0x17e3da)throw Error('Snapshot\x20save\x20was\x20called\x20outside\x20a\x20capture\x20operation');return _0x17e3da;}async['_database'](_0x4a87b2){try{return await _0x4a87b2();}catch(_0x4452bf){throw _0x4452bf instanceof g?_0x4452bf:new g('ADAPTER_FAILURE','Database\x20Adapter\x20failed',{'retryable':!0x0,'cause':_0x4452bf});}}};function D(_0x2f5280){return Promise['reject'](Error('SnapshotAdapterBridge\x20does\x20not\x20support\x20'+_0x2f5280));}function O(_0x2bd166){return new g('ADAPTER_FAILURE',_0x2bd166,{'retryable':!0x0});}function Ye(_0x338caf){switch(_0x338caf['type']){case c['UniverType']['UNIVER_SHEET']:case c['UniverType']['UNIVER_BASE']:return _0x338caf['workbook']!==void 0x0;case c['UniverType']['UNIVER_DOC']:return _0x338caf['doc']!==void 0x0;case c['UniverType']['UNIVER_SLIDE']:return _0x338caf['slide']!==void 0x0;case c['UniverType']['UNIVER_BOARD']:return _0x338caf['board']!==void 0x0;default:return!0x1;}}function Xe(_0x447f0d,_0x162677,_0x44d0ee){let _0x1e2f49=_0x162677['rev']+0x1;for(let _0x5b3309 of _0x44d0ee['changesets']){if(_0x5b3309['unitID']!==_0x447f0d['unitID']||_0x5b3309['type']!==_0x447f0d['type']||_0x5b3309['baseRev']!==_0x1e2f49-0x1||_0x5b3309['revision']!==_0x1e2f49)throw O('Stored\x20changeset\x20history\x20is\x20not\x20contiguous');_0x1e2f49+=0x1;}if(_0x1e2f49-0x1!==_0x447f0d['revision']||_0x44d0ee['latestRevision']<_0x447f0d['revision'])throw O('Stored\x20changeset\x20history\x20is\x20incomplete');}var k=new WeakSet();function Ze(_0x46e135){if(!k['has'](_0x46e135)){for(let _0x14c8c8 of[Qe,$e])_0x46e135['hasCommand'](_0x14c8c8['id'])&&_0x46e135['unregisterCommand'](_0x14c8c8['id']),_0x46e135['registerCommand'](_0x14c8c8);k['add'](_0x46e135);}}var Qe={'id':'doc.mutation.rich-text-editing','type':u['CommandType']['MUTATION'],'handler'(_0x5018fc,_0x30bcc8){let _0x17e3db=_0x5018fc['get'](u['IUniverInstanceService'])['getUnit'](_0x30bcc8['unitId'],u['UniverInstanceType']['UNIVER_DOC']);if(!_0x17e3db)return!0x1;if(!_0x30bcc8['actions']||u['JSONX']['isNoop'](_0x30bcc8['actions']))return!0x0;let _0x32fb6d=_0x17e3db['getSnapshot'](),_0x282e7a=u['JSONX']['invertWithDoc'](_0x30bcc8['actions'],_0x32fb6d);_0x17e3db['apply'](_0x30bcc8['actions']);let _0x4436cd=(0x0,l['validateDocumentAfterApply'])(_0x17e3db['getSnapshot']());if(!_0x4436cd['ok'])throw _0x17e3db['apply'](_0x282e7a),Error('Invalid\x20Doc\x20mutation\x20result:\x20'+_0x4436cd['errors']['join']('\x20'));return!0x0;}},$e={'id':'doc.mutation.rename-doc','type':u['CommandType']['MUTATION'],'handler'(_0x129a75,_0x12e653){if(!_0x12e653)return!0x1;let _0x3cc8b5=_0x129a75['get'](u['IUniverInstanceService'])['getUnit'](_0x12e653['unitId'],u['UniverInstanceType']['UNIVER_DOC']);return _0x3cc8b5?(_0x3cc8b5['setName'](_0x12e653['name']),!0x0):!0x1;}};function et(_0xe89987){_0xe89987['registerPlugin'](l['UniverCollaborationPlugin']),tt(_0xe89987),nt(_0xe89987),rt(_0xe89987),it(_0xe89987),at(_0xe89987),_0xe89987['registerPlugin'](m['UniverBasesPlugin']);}function tt(_0x518c0e){_0x518c0e['registerPlugin'](h['UniverThreadCommentPlugin']),_0x518c0e['registerPlugin'](be['UniverThreadCommentResourcePlugin']),_0x518c0e['registerPlugin'](we['UniverDrawingPlugin']),_0x518c0e['registerPlugin'](ue['UniverEmbedPlugin']);}function nt(_0x2e1533){_0x2e1533['registerPlugin'](Ce['UniverDocsHyperLinkPlugin']),_0x2e1533['registerPlugin'](Se['UniverDocsDrawingPlugin']),_0x2e1533['registerPlugin'](ie['UniverDocsCalloutPlugin']),_0x2e1533['registerPlugin'](ae['UniverDocsChartPlugin']),_0x2e1533['registerPlugin'](oe['UniverDocsCodePlugin']),_0x2e1533['registerPlugin'](se['UniverDocsLatexPlugin']),_0x2e1533['registerPlugin'](ce['UniverDocsShapePlugin']),_0x2e1533['registerPlugin'](le['UniverDocsTablePlugin']);}function rt(_0x323a36){_0x323a36['registerPlugin'](Te['UniverSheetsPlugin']),_0x323a36['registerPlugin'](de['UniverRustFormulaEnginePlugin'],{}),_0x323a36['registerPlugin'](ke['UniverSheetsFormulaPlugin']),_0x323a36['registerPlugin'](Ee['UniverSheetsConditionalFormattingPlugin']),_0x323a36['registerPlugin'](xe['UniverDataValidationPlugin']),_0x323a36['registerPlugin'](Oe['UniverSheetsFilterPlugin']),_0x323a36['registerPlugin'](Ae['UniverSheetsHyperLinkPlugin']),_0x323a36['registerPlugin'](me['UniverSheetsPivotTablePlugin']),_0x323a36['registerPlugin'](Ne['UniverSheetsTablePlugin']),_0x323a36['registerPlugin'](pe['UniverSheetsOutlinePlugin']),_0x323a36['registerPlugin'](ge['UniverSheetSparklinePlugin']),_0x323a36['registerPlugin'](De['UniverSheetsDrawingPlugin']),_0x323a36['registerPlugin'](Me['UniverSheetsSortPlugin']),_0x323a36['registerPlugin'](fe['UniverSheetsChartPlugin']),_0x323a36['registerPlugin'](je['UniverSheetsNotePlugin']),_0x323a36['registerPlugin'](he['UniverSheetsShapePlugin']);}function it(_0x1285fd){_0x1285fd['registerPlugin'](_e['UniverSlidesPlugin']),_0x1285fd['registerPlugin'](ve['UniverSlidesChartPlugin']),_0x1285fd['registerPlugin'](ye['UniverSlidesTablePlugin']);}function at(_0x490356){_0x490356['registerPlugin'](ee['UniverBoardsPlugin']),_0x490356['registerPlugin'](te['UniverBoardsChartPlugin']),_0x490356['registerPlugin'](re['UniverBoardsTablePlugin']),_0x490356['registerPlugin'](ne['UniverBoardsMindPlugin']);}var ot=class{['_transformService'];constructor(_0x3c65a0){this['_transformService']=_0x3c65a0;}['parseClient'](_0x4ad910){try{return(0x0,l['parseProtocolChangeset'])(structuredClone(_0x4ad910));}catch(_0x439b90){throw new g('INVALID_REQUEST','Changeset\x20is\x20malformed',{'cause':_0x439b90});}}['transform'](_0x12fe20,_0x370315){let _0x5b7fc0;try{_0x5b7fc0=_0x370315['map'](_0xbf060f=>(0x0,l['parseProtocolChangeset'])(structuredClone(_0xbf060f)));}catch(_0x328bab){throw new g('ADAPTER_FAILURE','Stored\x20changeset\x20cannot\x20be\x20parsed',{'retryable':!0x0,'cause':_0x328bab});}let _0x324491=_0x12fe20;if(_0x5b7fc0['length']>0x0){let _0x1df9c8=this['_transformService']['transformChangesets'](_0x5b7fc0,[_0x12fe20],!0x1);if((0x0,l['isTransformChangesetsFailure'])(_0x1df9c8)||!_0x1df9c8['c2Prime'][0x0])throw new g('OT_CONFLICT','Changeset\x20cannot\x20be\x20transformed',{'cause':(0x0,l['isTransformChangesetsFailure'])(_0x1df9c8)?_0x1df9c8['error']:void 0x0});_0x324491=_0x1df9c8['c2Prime'][0x0];}try{return(0x0,l['parseChangesetToProtocol'])(_0x324491);}catch(_0x11f2ba){throw new g('INTERNAL_ERROR','Transformed\x20changeset\x20cannot\x20be\x20serialized',{'retryable':!0x0,'cause':_0x11f2ba});}}},st=0x32,ct=0x2bf20,lt=0x7530,A=class{['unitID'];['type'];['_revision'];constructor(_0x5bbd37,_0x42fcd3,_0x5d6670){this['unitID']=_0x5bbd37,this['type']=_0x42fcd3,this['_revision']=_0x5d6670;}get['revision'](){return this['_revision'];}['advanceTo'](_0x247c3f){this['_revision']=_0x247c3f;}},j=class{['changesetTransformer'];['_dbAdapter'];['_maxLoadedUnits'];['_idleTimeoutMs'];['_univer'];['_instanceService'];['_commandService'];['_revisionService'];['_compressMutationService'];['_snapshotService'];['_snapshotSaveService'];['_formulaCalculationSessionService'];['_snapshotBridge'];['_entries']=new Map();['_ensuring']=new Map();['_disposed']=!0x1;constructor(_0xe6b3a0){if(this['_dbAdapter']=_0xe6b3a0['dbAdapter'],this['_maxLoadedUnits']=_0xe6b3a0['maxLoadedUnits']??st,this['_idleTimeoutMs']=_0xe6b3a0['idleTimeoutMs']??ct,!Number['isSafeInteger'](this['_maxLoadedUnits'])||this['_maxLoadedUnits']<0x1)throw TypeError('maxLoadedUnits\x20must\x20be\x20a\x20positive\x20safe\x20integer');if(!Number['isSafeInteger'](this['_idleTimeoutMs'])||this['_idleTimeoutMs']<0x1)throw TypeError('idleTimeoutMs\x20must\x20be\x20a\x20positive\x20safe\x20integer');this['_univer']=new u['Univer']({'locale':u['LocaleType']['EN_US'],'locales':{[u['LocaleType']['EN_US']]:f['default']},'logLevel':u['LogLevel']['SILENT']}),this['_snapshotBridge']=new Je(this['_dbAdapter']);let _0x5cd6c5=this['_univer']['__getInjector']();_0x5cd6c5['add']([l['ISnapshotServerService'],{'useValue':this['_snapshotBridge']}]),_0x5cd6c5['add']([l['SnapshotSaveService']]),et(this['_univer']),this['_instanceService']=_0x5cd6c5['get'](u['IUniverInstanceService']),this['_commandService']=_0x5cd6c5['get'](u['ICommandService']),this['_revisionService']=_0x5cd6c5['get'](l['RevisionService']),this['_compressMutationService']=_0x5cd6c5['get'](l['CompressMutationService']),this['changesetTransformer']=new ot(_0x5cd6c5['get'](l['ITransformService'])),this['_snapshotService']=_0x5cd6c5['get'](l['SnapshotService']),this['_snapshotSaveService']=_0x5cd6c5['get'](l['SnapshotSaveService']),this['_formulaCalculationSessionService']=_0x5cd6c5['get'](d['FormulaCalculationSessionService']);}['ensureUnit'](_0x2f0ad8,_0x3e080f,_0x18a0bb){this['_assertOpen']();let _0x22e705=this['_ensuring']['get'](_0x3e080f);if(_0x22e705)return _0x22e705['then'](_0x142d17=>this['_retain'](_0x142d17));let _0x137d23=this['_ensureUnit'](_0x2f0ad8,_0x3e080f,_0x18a0bb)['finally'](()=>{this['_ensuring']['get'](_0x3e080f)===_0x137d23&&this['_ensuring']['delete'](_0x3e080f);});return this['_ensuring']['set'](_0x3e080f,_0x137d23),_0x137d23['then'](_0xf7cda5=>this['_adoptReservation'](_0xf7cda5));}['releaseUnit'](_0x261fdf){let _0x4ace90=this['_entries']['get'](_0x261fdf['unitID']);if(!(!_0x4ace90||_0x4ace90['handle']!==_0x261fdf)){if(_0x4ace90['busy']<0x1)throw Error('Unit\x20Runtime\x20lease\x20was\x20released\x20more\x20than\x20once');--_0x4ace90['busy'],this['_touch'](_0x4ace90),this['_evictOverCapacity']();}}async['applyChangeset'](_0x2b48dd,_0x1d8bc1,_0x4614be){this['_assertOpen']();let _0x561198=this['_requireEntry'](_0x1d8bc1);await this['_withBusy'](_0x561198,async()=>{try{await this['_applyConfirmedChangeset'](_0x2b48dd,_0x561198['handle'],_0x4614be);}catch(_0x19c4a5){throw this['disposeUnit'](_0x1d8bc1['unitID']),_0x19c4a5 instanceof g?_0x19c4a5:new g('INTERNAL_ERROR','Failed\x20to\x20apply\x20changeset\x20to\x20Unit\x20Runtime',{'retryable':!0x0,'cause':_0x19c4a5});}});}async['createSnapshot'](_0x429e31){this['_assertOpen']();let _0x47ea12=this['_requireEntry'](_0x429e31);return this['_withBusy'](_0x47ea12,async()=>{try{let _0x1a9573=await this['_snapshotBridge']['capture'](()=>this['_createProtocolSnapshot'](_0x47ea12['handle'])),_0x5da177=_0x1a9573['result']['snapshot']??_0x1a9573['snapshot'];if(!_0x5da177)throw Error('SDK\x20snapshot\x20generation\x20returned\x20no\x20snapshot');return{'snapshot':_0x5da177,..._0x1a9573['sheetBlocks']['length']>0x0?{'sheetBlocks':_0x1a9573['sheetBlocks']}:{}};}catch(_0x29f3eb){throw this['disposeUnit'](_0x429e31['unitID']),new g('INTERNAL_ERROR','Failed\x20to\x20create\x20Unit\x20Runtime\x20snapshot',{'retryable':!0x0,'cause':_0x29f3eb});}});}['disposeUnit'](_0x2536f9){let _0x36a714=this['_entries']['get'](_0x2536f9);_0x36a714?.['idleTimer']&&clearTimeout(_0x36a714['idleTimer']),this['_entries']['delete'](_0x2536f9),this['_instanceService']['disposeUnit'](_0x2536f9);}async['dispose'](){if(!this['_disposed']){this['_disposed']=!0x0;for(let _0x4e6f9e of[...this['_entries']['keys']()])this['disposeUnit'](_0x4e6f9e);this['_ensuring']['clear'](),this['_univer']['dispose']();}}async['_ensureUnit'](_0xdd08db,_0x132da6,_0x26909f){ut(_0x132da6,_0x26909f);let _0x5f7bd9=await this['_database'](()=>this['_dbAdapter']['getUnit'](_0xdd08db,_0x132da6));if(!_0x5f7bd9)throw new g('UNIT_NOT_FOUND','Unit\x20'+_0x132da6+'\x20does\x20not\x20exist');if(_0x5f7bd9['unitID']!==_0x132da6)throw new g('ADAPTER_FAILURE','Stored\x20Unit\x20metadata\x20belongs\x20to\x20a\x20different\x20identity',{'retryable':!0x0});if(_0x5f7bd9['type']!==_0x26909f)throw new g('INVALID_REQUEST','Unit\x20type\x20does\x20not\x20match\x20the\x20stored\x20Unit');if(!Number['isSafeInteger'](_0x5f7bd9['headRevision'])||_0x5f7bd9['headRevision']<0x1)throw new g('ADAPTER_FAILURE','Stored\x20Unit\x20metadata\x20is\x20invalid',{'retryable':!0x0});let _0x186d0a=this['_entries']['get'](_0x132da6);if(_0x186d0a&&_0x186d0a['handle']['type']!==_0x26909f&&(this['disposeUnit'](_0x132da6),_0x186d0a=void 0x0),_0x186d0a&&_0x186d0a['handle']['revision']>_0x5f7bd9['headRevision']&&(this['disposeUnit'](_0x132da6),_0x186d0a=void 0x0),_0x186d0a)try{return await this['_withBusy'](_0x186d0a,async()=>{_0x186d0a['handle']['revision']<_0x5f7bd9['headRevision']&&await this['_replayRange'](_0xdd08db,_0x186d0a['handle'],_0x186d0a['handle']['revision'],_0x5f7bd9['headRevision']);},!0x1),_0x186d0a['busy']+=0x1,_0x186d0a['handle'];}catch{this['disposeUnit'](_0x132da6);}return this['_loadUnit'](_0xdd08db,_0x132da6,_0x26909f,_0x5f7bd9['headRevision']);}async['_loadUnit'](_0x391c62,_0x2a9daa,_0x23c3c8,_0x57b144){let _0x5e9508=await this['_database'](()=>this['_dbAdapter']['getSnapshot'](_0x391c62,_0x2a9daa,{'revision':_0x57b144}));if(!_0x5e9508||_0x5e9508['unitID']!==_0x2a9daa||_0x5e9508['type']!==_0x23c3c8||!Number['isSafeInteger'](_0x5e9508['rev'])||_0x5e9508['rev']<0x1||_0x5e9508['rev']>_0x57b144)throw new g('ADAPTER_FAILURE','Stored\x20Unit\x20snapshot\x20is\x20invalid',{'retryable':!0x0});try{if(await this['_loadSdkUnit'](_0x391c62,_0x2a9daa,_0x23c3c8,_0x5e9508['rev'],_0x5e9508),this['_revisionService']['getCurrentRevOfUnit'](_0x2a9daa)!==_0x5e9508['rev'])throw Error('SDK\x20loaded\x20Unit\x20at\x20an\x20unexpected\x20revision');let _0x27ec63=new A(_0x2a9daa,_0x23c3c8,_0x5e9508['rev']),_0x2da073={'handle':_0x27ec63,'busy':0x1};if(this['_entries']['set'](_0x2a9daa,_0x2da073),_0x5e9508['rev']<_0x57b144&&await this['_replayRange'](_0x391c62,_0x27ec63,_0x5e9508['rev'],_0x57b144),_0x27ec63['revision']!==_0x57b144)throw Error('Runtime\x20did\x20not\x20reach\x20the\x20requested\x20revision');return _0x27ec63;}catch(_0x462932){throw this['disposeUnit'](_0x2a9daa),_0x462932 instanceof g?_0x462932:new g('INTERNAL_ERROR','Failed\x20to\x20load\x20Unit\x20Runtime',{'retryable':!0x0,'cause':_0x462932});}}async['_loadSdkUnit'](_0x945050,_0x1f2423,_0xae1f03,_0x4d6b0d,_0x18d9ee){let _0x137095=this['_snapshotBridge']['createContext'](_0x945050,_0x18d9ee);switch(_0xae1f03){case c['UniverType']['UNIVER_SHEET']:await this['_snapshotService']['loadSheet'](_0x1f2423,_0x4d6b0d,_0x137095);return;case c['UniverType']['UNIVER_DOC']:await this['_snapshotService']['loadDoc'](_0x1f2423,_0x4d6b0d,_0x137095),Ze(this['_commandService']);return;case c['UniverType']['UNIVER_SLIDE']:await this['_snapshotService']['loadSlide'](_0x1f2423,_0x4d6b0d,_0x137095);return;case c['UniverType']['UNIVER_BOARD']:await this['_snapshotService']['loadBoard'](_0x1f2423,_0x4d6b0d,_0x137095);return;case c['UniverType']['UNIVER_BASE']:await this['_snapshotService']['loadBase'](_0x1f2423,_0x4d6b0d,_0x137095);return;}throw Error('Unsupported\x20Unit\x20type:\x20'+_0xae1f03);}async['_createProtocolSnapshot'](_0x51309){let _0x23989e={};switch(_0x51309['type']){case c['UniverType']['UNIVER_SHEET']:{await this['_formulaCalculationSessionService']['waitForLatestApplied'](lt);let _0x37c1b5=this['_requireSdkUnit'](_0x51309,u['UniverInstanceType']['UNIVER_SHEET']),_0x233a2c=await this['_snapshotSaveService']['getSheet'](_0x23989e,_0x51309['unitID'],_0x51309['revision'],_0x37c1b5);if(!_0x233a2c['snapshot']['workbook'])throw Error('SDK\x20Sheet\x20snapshot\x20has\x20no\x20workbook\x20payload');return{..._0x233a2c,'snapshot':{..._0x233a2c['snapshot'],'workbook':{..._0x233a2c['snapshot']['workbook'],'sheetOrder':_0x37c1b5['getSheets']()['map'](_0x513408=>_0x513408['getSheetId']())}}};}case c['UniverType']['UNIVER_DOC']:{let _0x42a4dc=this['_requireSdkUnit'](_0x51309,u['UniverInstanceType']['UNIVER_DOC']);return this['_snapshotSaveService']['getDoc'](_0x23989e,_0x51309['unitID'],_0x51309['revision'],_0x42a4dc);}case c['UniverType']['UNIVER_SLIDE']:{let _0x4f0eea=this['_requireSdkUnit'](_0x51309,u['UniverInstanceType']['UNIVER_SLIDE']);return this['_snapshotService']['saveSlide'](_0x51309['unitID'],_0x4f0eea['getSnapshot'](),_0x51309['revision']);}case c['UniverType']['UNIVER_BOARD']:{let _0x54c28f=this['_requireSdkUnit'](_0x51309,u['UniverInstanceType']['UNIVER_BOARD']);return this['_snapshotService']['saveBoard'](_0x51309['unitID'],_0x54c28f['getSnapshot'](),_0x51309['revision']);}case c['UniverType']['UNIVER_BASE']:{let _0x59357f=this['_requireSdkUnit'](_0x51309,u['UniverInstanceType']['UNIVER_BASE']);return this['_snapshotSaveService']['getBase'](_0x23989e,_0x51309['unitID'],_0x51309['revision'],_0x59357f);}}throw Error('Unsupported\x20Unit\x20type:\x20'+_0x51309['type']);}['_requireSdkUnit'](_0x46c783,_0x13d9f1){let _0x1f13da=this['_instanceService']['getUnit'](_0x46c783['unitID'],_0x13d9f1);if(!_0x1f13da||this['_revisionService']['getCurrentRevOfUnit'](_0x46c783['unitID'])!==_0x46c783['revision'])throw Error('Runtime\x20Unit\x20or\x20revision\x20is\x20unavailable');return _0x1f13da;}async['_replayRange'](_0x422897,_0x4a8c6a,_0xe48e4a,_0x3ffb82){let _0x558300=await this['_database'](()=>this['_dbAdapter']['getChangesets'](_0x422897,_0x4a8c6a['unitID'],{'from':_0xe48e4a,'to':_0x3ffb82})),_0x4b243c=_0xe48e4a+0x1;for(let _0x39cf13 of _0x558300['changesets']){if(_0x39cf13['unitID']!==_0x4a8c6a['unitID']||_0x39cf13['type']!==_0x4a8c6a['type']||_0x39cf13['baseRev']!==_0x4b243c-0x1||_0x39cf13['revision']!==_0x4b243c)throw new g('ADAPTER_FAILURE','Stored\x20changeset\x20history\x20is\x20not\x20contiguous',{'retryable':!0x0});await this['_applyConfirmedChangeset'](_0x422897,_0x4a8c6a,_0x39cf13),_0x4b243c+=0x1;}if(_0x4b243c-0x1!==_0x3ffb82||_0x558300['latestRevision']<_0x3ffb82)throw new g('ADAPTER_FAILURE','Stored\x20changeset\x20history\x20is\x20incomplete',{'retryable':!0x0});}async['_applyConfirmedChangeset'](_0x3aa87d,_0x274735,_0x52befb){if(_0x52befb['unitID']!==_0x274735['unitID']||_0x52befb['type']!==_0x274735['type']||_0x52befb['baseRev']!==_0x274735['revision']||_0x52befb['revision']!==_0x274735['revision']+0x1)throw Error('Changeset\x20does\x20not\x20follow\x20the\x20Runtime\x20revision');let _0x47f3f2=(0x0,l['parseProtocolChangeset'])(_0x52befb),_0x1b6b03=_0x47f3f2['mutations']['find'](_0x25af77=>_0x25af77['id']===l['RevertRevisionMutation']['id']);if(_0x1b6b03){if(_0x47f3f2['mutations']['length']!==0x1)throw new g('INVALID_REQUEST','A\x20restore\x20changeset\x20cannot\x20contain\x20other\x20mutations');let _0x5e0ee2=_0x1b6b03['params'];if(_0x5e0ee2['unitId']!==_0x274735['unitID']||!Number['isSafeInteger'](_0x5e0ee2['revision'])||_0x5e0ee2['revision']<0x1||_0x5e0ee2['revision']>_0x52befb['baseRev'])throw new g('INVALID_REQUEST','Restore\x20target\x20must\x20identify\x20an\x20existing\x20revision\x20of\x20this\x20Unit');await this['_restoreHistoricalRevision'](_0x3aa87d,_0x274735,_0x52befb,_0x5e0ee2['revision']);return;}let _0x35d6a6=this['_compressMutationService']['interceptor']['fetchThroughInterceptors'](this['_compressMutationService']['interceptor']['getInterceptPoints']()['COMPRESS_MUTATION_APPLY'])(_0x47f3f2['mutations'],null)??_0x47f3f2['mutations'],_0x5ac824=(0x0,u['sequenceExecute'])(_0x35d6a6,this['_commandService'],{'fromChangeset':!0x0});if(!_0x5ac824['result']){let _0x3539e8=_0x35d6a6[_0x5ac824['index']];throw new g('INTERNAL_ERROR','Unit\x20Runtime\x20failed\x20to\x20execute\x20mutation\x20\x22'+_0x3539e8['id']+'\x22\x20for\x20Unit\x20\x22'+_0x274735['unitID']+'\x22\x20at\x20revision\x20'+_0x52befb['revision']+'\x20(index\x20'+_0x5ac824['index']+')',{'retryable':!0x0,'cause':_0x5ac824['error']});}let _0x414a02=this['_revisionService']['incrementRevOfUnit'](_0x274735['unitID']);if(_0x414a02!==_0x52befb['revision'])throw Error('Univer\x20Runtime\x20revision\x20did\x20not\x20advance\x20as\x20expected');_0x274735['advanceTo'](_0x414a02);}async['_restoreHistoricalRevision'](_0x519e4c,_0xc87e5c,_0xac7f0f,_0x431f85){let _0x237964=await this['_database'](()=>this['_dbAdapter']['getSnapshot'](_0x519e4c,_0xc87e5c['unitID'],{'revision':_0x431f85}));if(!_0x237964||_0x237964['unitID']!==_0xc87e5c['unitID']||_0x237964['type']!==_0xc87e5c['type']||!Number['isSafeInteger'](_0x237964['rev'])||_0x237964['rev']<0x1||_0x237964['rev']>_0x431f85)throw new g('ADAPTER_FAILURE','Stored\x20restore\x20snapshot\x20is\x20invalid',{'retryable':!0x0});this['_instanceService']['disposeUnit'](_0xc87e5c['unitID']),await this['_loadSdkUnit'](_0x519e4c,_0xc87e5c['unitID'],_0xc87e5c['type'],_0x237964['rev'],_0x237964);let _0x369e6b=new A(_0xc87e5c['unitID'],_0xc87e5c['type'],_0x237964['rev']);if(_0x369e6b['revision']<_0x431f85&&await this['_replayRange'](_0x519e4c,_0x369e6b,_0x369e6b['revision'],_0x431f85),_0x369e6b['revision']!==_0x431f85)throw new g('ADAPTER_FAILURE','Restore\x20history\x20did\x20not\x20reach\x20its\x20target\x20revision',{'retryable':!0x0});if(this['_revisionService']['setRevOfUnit'](_0xc87e5c['unitID'],_0xac7f0f['revision']),this['_revisionService']['getCurrentRevOfUnit'](_0xc87e5c['unitID'])!==_0xac7f0f['revision'])throw Error('Univer\x20Runtime\x20did\x20not\x20adopt\x20the\x20restored\x20revision');_0xc87e5c['advanceTo'](_0xac7f0f['revision']);}['_requireEntry'](_0x5eee7d){let _0x3c47e8=this['_entries']['get'](_0x5eee7d['unitID']);if(!_0x3c47e8||_0x3c47e8['handle']!==_0x5eee7d||_0x3c47e8['handle']['type']!==_0x5eee7d['type'])throw new g('INTERNAL_ERROR','Unit\x20Runtime\x20handle\x20is\x20stale',{'retryable':!0x0});return _0x3c47e8;}async['_withBusy'](_0x9934d7,_0x257402,_0x1da25c=!0x0){_0x9934d7['busy']+=0x1,_0x9934d7['idleTimer']&&(clearTimeout(_0x9934d7['idleTimer']),delete _0x9934d7['idleTimer']);try{return await _0x257402();}finally{--_0x9934d7['busy'],_0x1da25c&&this['_entries']['get'](_0x9934d7['handle']['unitID'])===_0x9934d7&&(this['_touch'](_0x9934d7),this['_evictOverCapacity']());}}['_retain'](_0x241492){let _0x47f01c=this['_entries']['get'](_0x241492['unitID']);if(!_0x47f01c||_0x47f01c['handle']!==_0x241492)throw new g('INTERNAL_ERROR','Unit\x20Runtime\x20was\x20disposed\x20before\x20its\x20lease\x20could\x20be\x20acquired',{'retryable':!0x0});return _0x47f01c['busy']+=0x1,this['_touch'](_0x47f01c),this['_evictOverCapacity'](),_0x241492;}['_adoptReservation'](_0x214765){let _0x4c28ca=this['_entries']['get'](_0x214765['unitID']);if(!_0x4c28ca||_0x4c28ca['handle']!==_0x214765||_0x4c28ca['busy']<0x1)throw new g('INTERNAL_ERROR','Unit\x20Runtime\x20load\x20reservation\x20is\x20unavailable',{'retryable':!0x0});return this['_touch'](_0x4c28ca),this['_evictOverCapacity'](),_0x214765;}['_touch'](_0x5d3d68){let {unitID:_0x10855d}=_0x5d3d68['handle'];if(_0x5d3d68['idleTimer']&&clearTimeout(_0x5d3d68['idleTimer']),this['_entries']['delete'](_0x10855d),this['_entries']['set'](_0x10855d,_0x5d3d68),_0x5d3d68['busy']>0x0){delete _0x5d3d68['idleTimer'];return;}_0x5d3d68['idleTimer']=setTimeout(()=>{_0x5d3d68['busy']===0x0&&this['_entries']['get'](_0x10855d)===_0x5d3d68&&this['disposeUnit'](_0x10855d);},this['_idleTimeoutMs']),_0x5d3d68['idleTimer']['unref']?.();}['_evictOverCapacity'](){for(;this['_entries']['size']>this['_maxLoadedUnits'];){let _0x23b437=[...this['_entries']['values']()]['find'](_0x3b71e4=>_0x3b71e4['busy']===0x0);if(!_0x23b437)return;this['disposeUnit'](_0x23b437['handle']['unitID']);}}async['_database'](_0x53f685){try{return await _0x53f685();}catch(_0x5352cf){throw _0x5352cf instanceof g?_0x5352cf:new g('ADAPTER_FAILURE','Database\x20Adapter\x20failed',{'retryable':!0x0,'cause':_0x5352cf});}}['_assertOpen'](){if(this['_disposed'])throw new g('INTERNAL_ERROR','Unit\x20Runtime\x20is\x20disposed',{'retryable':!0x0});}};function ut(_0x558341,_0x24c5a6){if(!_0x558341)throw new g('INVALID_REQUEST','unitID\x20is\x20required');if(!dt['has'](_0x24c5a6))throw new g('INVALID_REQUEST','Unsupported\x20Unit\x20type:\x20'+_0x24c5a6);}var dt=new Set([c['UniverType']['UNIVER_SHEET'],c['UniverType']['UNIVER_DOC'],c['UniverType']['UNIVER_SLIDE'],c['UniverType']['UNIVER_BOARD'],c['UniverType']['UNIVER_BASE']]),ft=class{['_options'];constructor(_0x137632){this['_options']=_0x137632;}async['submit'](_0x46649e,_0x275b09){let _0x30ff2a=_0x275b09['changeset'];pt(_0x30ff2a);let _0x448c38={..._0x46649e,'request':_0x275b09};try{return await this['_options']['coordinator']['runExclusive'](_0x30ff2a['unitID'],async()=>{let _0x3a46e5=this['_options']['maxRevisionRetries']+0x1;for(let _0x2d59b9=0x1;_0x2d59b9<=_0x3a46e5;_0x2d59b9+=0x1){let _0x1aaf78=await this['_attempt'](_0x448c38,_0x46649e,_0x275b09,_0x30ff2a,_0x2d59b9);if(_0x1aaf78['status']!=='retry-attempt')return _0x1aaf78;}throw this['_options']['runtime']['disposeUnit'](_0x30ff2a['unitID']),new g('REVISION_MISMATCH','Changeset\x20could\x20not\x20be\x20committed\x20after\x20bounded\x20retries',{'retryable':!0x0});});}catch(_0xf1bfe3){throw _0xf1bfe3 instanceof g&&_0xf1bfe3['code']==='UNIT_NOT_FOUND'&&this['_options']['runtime']['disposeUnit'](_0x30ff2a['unitID']),_0xf1bfe3;}}async['_attempt'](_0x446083,_0x1ab9ca,_0x178052,_0x4dc9a9,_0x3f7f74){let _0xbffee1=await this['_measure']('load',()=>this['_options']['runtime']['ensureUnit'](_0x446083,_0x4dc9a9['unitID'],_0x4dc9a9['type']));try{let _0x20308a=_0xbffee1['revision'];if(_0x4dc9a9['baseRev']>_0x20308a)throw new g('REVISION_MISMATCH','Changeset\x20base\x20revision\x20is\x20ahead\x20of\x20the\x20Unit\x20head');let _0x38b5da=await this['_getHistory'](_0x446083,_0x4dc9a9['unitID'],_0x4dc9a9['type'],_0x4dc9a9['baseRev'],_0x20308a),_0x468dd1=N(_0x38b5da,_0x4dc9a9);if(_0x468dd1)return M(_0x468dd1,_0x4dc9a9),P(_0x468dd1)&&await this['_ensureRestoreSnapshot'](_0x446083,_0xbffee1,_0x468dd1)?(await this['_options']['onCommitted'](_0x1ab9ca,_0x178052,_0x468dd1),{'status':'committed','changeset':_0x468dd1}):{'status':'already-committed','changeset':_0x468dd1};let _0x58ab56=await this['_measure']('transform',async()=>this['_createCandidate'](_0x4dc9a9,_0x38b5da,_0x20308a)),_0x3c2fc3=!0x1;try{let _0x576627={'userID':_0x1ab9ca['userID'],'memberID':_0x1ab9ca['memberID'],'customData':_0x1ab9ca['customData'],'request':_0x178052,'attempt':_0x3f7f74,'currentRevision':_0x20308a,'changeset':_0x58ab56};await this['_measure']('applyMiddleware',()=>this['_options']['middleware']['run']('applyChangeset',_0x576627,async()=>{await this['_measure']('executeMutations',()=>this['_options']['runtime']['applyChangeset'](_0x446083,_0xbffee1,_0x58ab56)),_0x3c2fc3=!0x0;}));let _0x9edfa4=await this['_runCommitMiddleware'](_0x446083,_0x1ab9ca,_0x178052,_0x58ab56,_0x3f7f74,_0x20308a);if(!_0x9edfa4)return this['_options']['runtime']['disposeUnit'](_0x4dc9a9['unitID']),{'status':'retry-attempt'};switch(_0x9edfa4['status']){case'revision-mismatch':if(!Number['isSafeInteger'](_0x9edfa4['actualHeadRevision'])||_0x9edfa4['actualHeadRevision']<0x1)throw I('Database\x20returned\x20an\x20invalid\x20head\x20revision\x20mismatch');return this['_options']['runtime']['disposeUnit'](_0x4dc9a9['unitID']),this['_options']['metrics']['increment']('collaboration.submit.retry',{'reason':'revision-mismatch'}),{'status':'retry-attempt'};case'recovered-committed':return P(_0x9edfa4['changeset'])?(await this['_ensureRestoreSnapshot'](_0x446083,_0xbffee1,_0x9edfa4['changeset']),await this['_options']['onCommitted'](_0x1ab9ca,_0x178052,_0x9edfa4['changeset']),{'status':'committed','changeset':_0x9edfa4['changeset']}):(this['_options']['runtime']['disposeUnit'](_0x4dc9a9['unitID']),await this['_options']['onCommitted'](_0x1ab9ca,_0x178052,_0x9edfa4['changeset']),await this['_snapshotBestEffort'](_0x446083,void 0x0,_0x9edfa4['changeset']),{'status':'committed','changeset':_0x9edfa4['changeset']});case'committed':return M(_0x9edfa4['changeset'],_0x58ab56,!0x0),P(_0x9edfa4['changeset'])?(await this['_ensureRestoreSnapshot'](_0x446083,_0xbffee1,_0x9edfa4['changeset']),await this['_options']['onCommitted'](_0x1ab9ca,_0x178052,_0x9edfa4['changeset']),{'status':'committed','changeset':_0x9edfa4['changeset']}):(await this['_options']['onCommitted'](_0x1ab9ca,_0x178052,_0x9edfa4['changeset']),await this['_snapshotBestEffort'](_0x446083,_0xbffee1,_0x9edfa4['changeset']),{'status':'committed','changeset':_0x9edfa4['changeset']});}}catch(_0x219e46){throw _0x3c2fc3&&this['_options']['runtime']['disposeUnit'](_0x4dc9a9['unitID']),_0x219e46;}}finally{this['_options']['runtime']['releaseUnit'](_0xbffee1);}}async['_runCommitMiddleware'](_0x3c1222,_0x38152c,_0x45c223,_0x35747f,_0x2c3c17,_0x22f016){let _0x2faced,_0x570d76,_0x538d9e={'userID':_0x38152c['userID'],'memberID':_0x38152c['memberID'],'customData':_0x38152c['customData'],'request':_0x45c223,'attempt':_0x2c3c17,'expectedHeadRevision':_0x22f016,'changeset':_0x35747f};try{await this['_measure']('commitMiddleware',()=>this['_options']['middleware']['run']('commitChangeset',_0x538d9e,async()=>{try{_0x2faced=await this['_measure']('databaseCommit',()=>this['_database'](()=>this['_options']['dbAdapter']['commitChangeset'](_0x3c1222,{'changeset':_0x35747f})));}catch(_0x2fa552){throw _0x570d76=_0x2fa552,_0x2fa552;}}));}catch(_0x5ea145){if(_0x2faced)return this['_options']['logger']['error']('commitChangeset\x20middleware\x20failed\x20after\x20database\x20commit',{'error':L(_0x5ea145)}),_0x2faced;if(!_0x570d76)throw _0x5ea145;if(_0x570d76 instanceof g&&!_0x570d76['retryable'])throw _0x570d76;}if(_0x2faced)return _0x2faced;let _0x1840cb=N(await this['_getHistoryToLatest'](_0x3c1222,_0x35747f['unitID'],_0x35747f['type'],_0x22f016),_0x35747f);return _0x1840cb?(M(_0x1840cb,_0x35747f),{'status':'recovered-committed','changeset':_0x1840cb}):(this['_options']['metrics']['increment']('collaboration.submit.retry',{'reason':'unknown-commit'}),null);}async['_getHistory'](_0x12a8c4,_0x19b7a2,_0x13c445,_0x117ee9,_0x154475){if(_0x117ee9===_0x154475)return[];let _0x4a37c8=await this['_database'](()=>this['_options']['dbAdapter']['getChangesets'](_0x12a8c4,_0x19b7a2,{'from':_0x117ee9,'to':_0x154475})),_0x211415=_0x117ee9+0x1;for(let _0x40960d of _0x4a37c8['changesets']){if(_0x40960d['unitID']!==_0x19b7a2||_0x40960d['type']!==_0x13c445||_0x40960d['baseRev']!==_0x211415-0x1||_0x40960d['revision']!==_0x211415)throw I('Stored\x20changeset\x20history\x20is\x20not\x20contiguous');_0x211415+=0x1;}if(_0x211415-0x1!==_0x154475||_0x4a37c8['latestRevision']<_0x154475)throw I('Stored\x20changeset\x20history\x20is\x20incomplete');return _0x4a37c8['changesets'];}async['_getHistoryToLatest'](_0x4465c5,_0xb5555d,_0x4cc957,_0x3f43b5){let _0x455eed=await this['_database'](()=>this['_options']['dbAdapter']['getChangesets'](_0x4465c5,_0xb5555d,{'from':_0x3f43b5,'to':0x0}));if(_0x455eed['latestRevision']<_0x3f43b5)throw I('Stored\x20changeset\x20history\x20is\x20incomplete');let _0x462ec6=_0x3f43b5+0x1;for(let _0x547405 of _0x455eed['changesets']){if(_0x547405['unitID']!==_0xb5555d||_0x547405['type']!==_0x4cc957||_0x547405['baseRev']!==_0x462ec6-0x1||_0x547405['revision']!==_0x462ec6)throw I('Stored\x20changeset\x20history\x20is\x20not\x20contiguous');_0x462ec6+=0x1;}if(_0x462ec6-0x1!==_0x455eed['latestRevision'])throw I('Stored\x20changeset\x20history\x20is\x20incomplete');return _0x455eed['changesets'];}['_createCandidate'](_0x49797e,_0x457263,_0x32e504){let _0x196dcd=this['_options']['transformer']['parseClient'](_0x49797e);return{...this['_options']['transformer']['transform'](_0x196dcd,_0x457263),'unitID':_0x49797e['unitID'],'type':_0x49797e['type'],'baseRev':_0x32e504,'revision':_0x32e504+0x1,'sid':_0x49797e['sid'],'reqId':_0x49797e['reqId']};}async['_snapshotBestEffort'](_0x585a0a,_0x5d2b3d,_0x265a50){let _0x260e8c=this['_options']['snapshotPolicy'];if(!_0x260e8c)return;let _0x4458d1;try{await this['_measure']('snapshot',async()=>{let _0xf78d52=await this['_database'](()=>this['_options']['dbAdapter']['getSnapshot'](_0x585a0a,_0x265a50['unitID'],{'revision':_0x265a50['revision']}));if(!_0xf78d52||_0xf78d52['unitID']!==_0x265a50['unitID']||_0xf78d52['type']!==_0x265a50['type']||!Number['isSafeInteger'](_0xf78d52['rev'])||_0xf78d52['rev']<0x1||_0xf78d52['rev']>_0x265a50['revision'])throw I('Database\x20returned\x20an\x20invalid\x20nearest\x20snapshot');let _0x331c87=_0x265a50['revision']-_0xf78d52['rev'];if(!P(_0x265a50)&&!_0x260e8c['shouldCreate']({'unitID':_0x265a50['unitID'],'type':_0x265a50['type'],'revision':_0x265a50['revision'],'changesetBytes':ht(_0x265a50),'revisionsSinceLastSnapshot':_0x331c87}))return;let _0x322b0d=_0x5d2b3d??(_0x4458d1=await this['_options']['runtime']['ensureUnit'](_0x585a0a,_0x265a50['unitID'],_0x265a50['type'])),_0x2002f6=await this['_options']['runtime']['createSnapshot'](_0x322b0d);await this['_database'](()=>this['_options']['dbAdapter']['saveSnapshot'](_0x585a0a,_0x2002f6));});}catch(_0x4dd76d){_0x4dd76d instanceof g&&_0x4dd76d['code']==='UNIT_NOT_FOUND'&&this['_options']['runtime']['disposeUnit'](_0x265a50['unitID']),this['_options']['metrics']['increment']('collaboration.snapshot.failure'),this['_options']['logger']['warn']('Best-effort\x20snapshot\x20failed',{'unitID':_0x265a50['unitID'],'revision':_0x265a50['revision'],'error':L(_0x4dd76d)});}finally{_0x4458d1&&this['_options']['runtime']['releaseUnit'](_0x4458d1);}}async['_ensureRestoreSnapshot'](_0x5297f3,_0x46fb37,_0x3249f5){let _0xaecec2;try{return await this['_measure']('restoreSnapshot',async()=>{if((await this['_getValidatedSnapshot'](_0x5297f3,_0x3249f5))['rev']===_0x3249f5['revision'])return!0x1;let _0x131eae=_0x46fb37??(_0xaecec2=await this['_options']['runtime']['ensureUnit'](_0x5297f3,_0x3249f5['unitID'],_0x3249f5['type']));if(_0x131eae['revision']!==_0x3249f5['revision'])throw I('Unit\x20Runtime\x20is\x20not\x20at\x20the\x20committed\x20restore\x20revision');let _0x3cdb96=await this['_options']['runtime']['createSnapshot'](_0x131eae);if(_0x3cdb96['snapshot']['unitID']!==_0x3249f5['unitID']||_0x3cdb96['snapshot']['type']!==_0x3249f5['type']||_0x3cdb96['snapshot']['rev']!==_0x3249f5['revision'])throw I('Unit\x20Runtime\x20returned\x20an\x20invalid\x20restore\x20snapshot');try{await this['_database'](()=>this['_options']['dbAdapter']['saveSnapshot'](_0x5297f3,_0x3cdb96));}catch(_0x39a836){if((await this['_getValidatedSnapshot'](_0x5297f3,_0x3249f5))['rev']!==_0x3249f5['revision'])throw _0x39a836;}return!0x0;});}catch(_0x51245c){throw this['_options']['metrics']['increment']('collaboration.snapshot.failure',{'reason':'restore-required'}),this['_options']['logger']['warn']('Required\x20restore\x20snapshot\x20failed',{'unitID':_0x3249f5['unitID'],'revision':_0x3249f5['revision'],'error':L(_0x51245c)}),_0x51245c;}finally{_0xaecec2&&this['_options']['runtime']['releaseUnit'](_0xaecec2);}}async['_getValidatedSnapshot'](_0x545dd4,_0x1b8af8){let _0xd91229=await this['_database'](()=>this['_options']['dbAdapter']['getSnapshot'](_0x545dd4,_0x1b8af8['unitID'],{'revision':_0x1b8af8['revision']}));if(!_0xd91229||_0xd91229['unitID']!==_0x1b8af8['unitID']||_0xd91229['type']!==_0x1b8af8['type']||!Number['isSafeInteger'](_0xd91229['rev'])||_0xd91229['rev']<0x1||_0xd91229['rev']>_0x1b8af8['revision'])throw I('Database\x20returned\x20an\x20invalid\x20nearest\x20snapshot');return _0xd91229;}async['_database'](_0x426c7e){try{return await _0x426c7e();}catch(_0x3859fd){throw _0x3859fd instanceof g?_0x3859fd:new g('ADAPTER_FAILURE','Database\x20Adapter\x20failed',{'retryable':!0x0,'cause':_0x3859fd});}}async['_measure'](_0x30770e,_0x43cf75){let _0x26151c=performance['now']();try{return await _0x43cf75();}finally{this['_options']['metrics']['observe']('collaboration.submit.duration',performance['now']()-_0x26151c,{'stage':_0x30770e});}}};function pt(_0x2fa8ab){if(!_0x2fa8ab['unitID'])throw F('unitID\x20is\x20required');if(!mt['has'](_0x2fa8ab['type']))throw F('Unsupported\x20Unit\x20type');if(!Number['isSafeInteger'](_0x2fa8ab['baseRev'])||_0x2fa8ab['baseRev']<0x1)throw F('baseRev\x20must\x20be\x20a\x20positive\x20safe\x20integer');if(!_0x2fa8ab['sid'])throw F('sid\x20is\x20required');if(!Number['isSafeInteger'](_0x2fa8ab['reqId'])||_0x2fa8ab['reqId']<0x1)throw F('reqId\x20must\x20be\x20a\x20positive\x20safe\x20integer');if(!Array['isArray'](_0x2fa8ab['mutations']))throw F('changeset\x20mutations\x20must\x20be\x20an\x20array');}var mt=new Set([c['UniverType']['UNIVER_SHEET'],c['UniverType']['UNIVER_DOC'],c['UniverType']['UNIVER_SLIDE'],c['UniverType']['UNIVER_BOARD'],c['UniverType']['UNIVER_BASE']]);function M(_0x1bb130,_0x5f1786,_0x1775ce=!0x1){if(_0x1bb130['unitID']!==_0x5f1786['unitID']||_0x1bb130['type']!==_0x5f1786['type']||_0x1bb130['sid']!==_0x5f1786['sid']||_0x1bb130['reqId']!==_0x5f1786['reqId']||!Number['isSafeInteger'](_0x1bb130['baseRev'])||_0x1bb130['baseRev']<0x1||!Number['isSafeInteger'](_0x1bb130['revision'])||_0x1bb130['revision']!==_0x1bb130['baseRev']+0x1||_0x1775ce&&(_0x1bb130['baseRev']!==_0x5f1786['baseRev']||_0x1bb130['revision']!==_0x5f1786['revision']||_0x1bb130['userID']!==_0x5f1786['userID']||_0x1bb130['memberID']!==_0x5f1786['memberID']))throw I('Database\x20returned\x20an\x20invalid\x20committed\x20changeset');}function N(_0xad69a7,_0x209f56){return _0xad69a7['find'](_0x5064ac=>_0x5064ac['sid']===_0x209f56['sid']&&_0x5064ac['reqId']===_0x209f56['reqId']);}function ht(_0x37db58){try{return new TextEncoder()['encode'](JSON['stringify'](_0x37db58))['byteLength'];}catch{return _0x37db58['mutationSize']??0x0;}}function P(_0x318760){return _0x318760['mutations']['some'](_0xe2e67=>_0xe2e67['id']==='univer.mutation.revert-version');}function F(_0x19ce0d){return new g('INVALID_REQUEST',_0x19ce0d);}function I(_0x47dd5c){return new g('ADAPTER_FAILURE',_0x47dd5c,{'retryable':!0x0});}function L(_0x349abc){return _0x349abc instanceof Error?_0x349abc['message']:String(_0x349abc);}var R=class{['_queues']=new Map();async['runExclusive'](_0xe48776,_0x124334){let _0xb621f0=this['_queues']['get'](_0xe48776)??{'tail':Promise['resolve'](),'pending':0x0};_0xb621f0['pending']+=0x1,this['_queues']['set'](_0xe48776,_0xb621f0);let _0x53f263=_0xb621f0['tail'],_0x4fe0c0;_0xb621f0['tail']=new Promise(_0x228a3c=>{_0x4fe0c0=_0x228a3c;}),await _0x53f263;try{return await _0x124334();}finally{_0x4fe0c0(),--_0xb621f0['pending'],_0xb621f0['pending']===0x0&&this['_queues']['get'](_0xe48776)===_0xb621f0&&this['_queues']['delete'](_0xe48776);}}['runExclusiveMany'](_0x5c31f9,_0x2bbd64){let _0xe8239e=[...new Set(_0x5c31f9)]['sort'](),_0x456743=_0x2b9473=>{let _0x16e7be=_0xe8239e[_0x2b9473];return _0x16e7be===void 0x0?_0x2bbd64():this['runExclusive'](_0x16e7be,()=>_0x456743(_0x2b9473+0x1));};return _0x456743(0x0);}},gt=class{['_onListenerError'];['_listeners']=new Map();constructor(_0x3e1376){this['_onListenerError']=_0x3e1376;}['on'](_0x39354e,_0x3ddbf3){let _0x1cef33=this['_listeners']['get'](_0x39354e)??[],_0x449098=_0x3ddbf3;_0x1cef33['push'](_0x449098),this['_listeners']['set'](_0x39354e,_0x1cef33);let _0x429868=!0x1;return{'dispose':()=>{if(_0x429868)return;_0x429868=!0x0;let _0x1fcc42=_0x1cef33['indexOf'](_0x449098);_0x1fcc42>=0x0&&_0x1cef33['splice'](_0x1fcc42,0x1);}};}async['emit'](_0x1aed6c,_0x59c861){let _0x2eb9dd=[...this['_listeners']['get'](_0x1aed6c)??[]];for(let _0x1e5419 of _0x2eb9dd)try{await _0x1e5419(_0x59c861);}catch(_0x1548b0){try{this['_onListenerError'](_0x1548b0);}catch{}}}['clear'](){this['_listeners']['clear']();}},z=class{['_owner'];['_state']='running';['_activeCalls']=0x0;['_drainPromise'];['_resolveDrain'];['_disposePromise'];constructor(_0x54d952){this['_owner']=_0x54d952;}get['state'](){return this['_state'];}['run'](_0x1aba20){return this['_state']==='running'?(this['_activeCalls']+=0x1,Promise['resolve']()['then'](_0x1aba20)['finally'](()=>{--this['_activeCalls'],this['_activeCalls']===0x0&&(this['_resolveDrain']?.(),this['_resolveDrain']=void 0x0,this['_drainPromise']=void 0x0);})):Promise['reject'](new g('INTERNAL_ERROR',this['_owner']+'\x20is\x20'+this['_state'],{'retryable':!0x0}));}['dispose'](_0x306750){return this['_disposePromise']?this['_disposePromise']:(this['_state']='disposing',this['_disposePromise']=this['_finishDispose'](_0x306750),this['_disposePromise']);}async['_finishDispose'](_0x5172a9){this['_activeCalls']>0x0&&(this['_drainPromise']=new Promise(_0x17abce=>{this['_resolveDrain']=_0x17abce;}),await this['_drainPromise']);try{await _0x5172a9();}finally{this['_state']='disposed';}}},B=new Set([c['UniverType']['UNIVER_SHEET'],c['UniverType']['UNIVER_DOC'],c['UniverType']['UNIVER_SLIDE'],c['UniverType']['UNIVER_BOARD'],c['UniverType']['UNIVER_BASE']]),_t=0x64,vt=class{['_dbAdapter'];['_middleware']=new Pe();['_lifecycle']=new z('Collaboration\x20Service');['_logger'];['_metrics'];['_events'];['_runtime'];['_coordinator'];['_submitEngine'];constructor(_0xb96696){if(!_0xb96696?.['dbAdapter'])throw TypeError('UniverCollabService\x20requires\x20a\x20dbAdapter');this['_dbAdapter']=_0xb96696['dbAdapter'],this['_logger']=Le(_0xb96696['logger']),this['_metrics']=Re(_0xb96696['metrics']),this['_events']=new gt(_0x131ba4=>{this['_logger']['error']('Collaboration\x20Service\x20event\x20listener\x20failed',{'error':X(_0x131ba4)});});let _0x37b744=_0xb96696['submitChangeset']?.['maxRevisionRetries']??0x3;if(!Number['isSafeInteger'](_0x37b744)||_0x37b744<0x0)throw TypeError('submitChangeset.maxRevisionRetries\x20must\x20be\x20a\x20non-negative\x20safe\x20integer');this['_runtime']=new j({'dbAdapter':this['_dbAdapter'],..._0xb96696['runtime']?.['maxLoadedUnits']===void 0x0?{}:{'maxLoadedUnits':_0xb96696['runtime']['maxLoadedUnits']},..._0xb96696['runtime']?.['idleTimeoutMs']===void 0x0?{}:{'idleTimeoutMs':_0xb96696['runtime']['idleTimeoutMs']}}),this['_coordinator']=new R(),this['_submitEngine']=new ft({'dbAdapter':this['_dbAdapter'],'middleware':this['_middleware'],'runtime':this['_runtime'],'transformer':this['_runtime']['changesetTransformer'],'coordinator':this['_coordinator'],..._0xb96696['snapshotPolicy']===!0x1?{}:{'snapshotPolicy':_0xb96696['snapshotPolicy']??v},'maxRevisionRetries':_0x37b744,'logger':this['_logger'],'metrics':this['_metrics'],'onCommitted':(_0x584596,_0x1528c0,_0x5948fa)=>this['_events']['emit']('changesetCommitted',{'userID':_0x584596['userID'],'memberID':_0x584596['memberID'],'customData':_0x584596['customData'],'request':_0x1528c0,'changeset':_0x5948fa,'committedAt':Date['now']()})});}['use'](_0x4221db,_0x3adb42){return this['_assertRunning'](),this['_middleware']['use'](_0x4221db,_0x3adb42);}['on'](_0x1fba59,_0x4eed49){return this['_assertRunning'](),this['_events']['on'](_0x1fba59,_0x4eed49);}['getUnitLoadData'](_0x31af66,_0x5b9acb){return this['_call']('getUnitLoadData',async()=>{let _0x2714cf=y(_0x5b9acb),_0x3bd585=w(_0x31af66),_0x5573d7={..._0x2714cf,'request':_0x3bd585},_0x50fe91;return await this['_middleware']['run']('readUnitData',_0x5573d7,async()=>{_0x50fe91=await this['_getUnitLoadData'](_0x5573d7,_0x31af66);}),_0x50fe91;});}['getUnitLoadDataWithBlocks'](_0x57bf24,_0x2899f8){return this['_call']('getUnitLoadDataWithBlocks',async()=>{let _0x39c233=y(_0x2899f8),_0x4dbe34=w(_0x57bf24),_0x504408={..._0x39c233,'request':_0x4dbe34},_0x33f47e;return await this['_middleware']['run']('readUnitData',_0x504408,async()=>{let _0x5d5889=await this['_getUnitLoadData'](_0x504408,_0x57bf24),_0x214469=await this['_getSnapshotSheetBlocks'](_0x504408,_0x5d5889['snapshot']);_0x33f47e={..._0x5d5889,'sheetBlocks':_0x214469};}),_0x33f47e;});}['getChangesets'](_0x3dab17,_0x173c8a){return this['_call']('getChangesets',async()=>{let _0x36bf6c=y(_0x173c8a),_0x2acd2a=ze(_0x3dab17),_0x4bf254={..._0x36bf6c,'request':_0x2acd2a},_0x4e4cba;return await this['_middleware']['run']('readUnitData',_0x4bf254,async()=>{V(_0x3dab17['unitID'],_0x3dab17['type']),W('from',_0x3dab17['from']),W('to',_0x3dab17['to']);let _0x1d6752=await this['_requireUnit'](_0x4bf254,_0x3dab17['unitID'],_0x3dab17['type']),_0x286de6=G(_0x3dab17['to'],_0x1d6752);if(_0x3dab17['from']>_0x286de6)throw J('Changeset\x20range\x20starts\x20after\x20its\x20target');let _0x56c82b=await this['_database'](()=>this['_dbAdapter']['getChangesets'](_0x4bf254,_0x3dab17['unitID'],{'from':_0x3dab17['from'],'to':_0x286de6}));q(_0x56c82b['latestRevision'],_0x286de6),K(_0x56c82b['changesets'],_0x3dab17['unitID'],_0x3dab17['type'],Math['max'](_0x3dab17['from']+0x1,0x2),_0x286de6),_0x4e4cba={'changesets':_0x56c82b['changesets'],'latestRevision':_0x56c82b['latestRevision']};}),_0x4e4cba;});}['getSheetBlock'](_0x16a3fb,_0x47652c){return this['_call']('getSheetBlock',async()=>{let _0x487591=y(_0x47652c),_0x287de1=Be(_0x16a3fb),_0x4a631a={..._0x487591,'request':_0x287de1},_0x4e2026;return await this['_middleware']['run']('readUnitData',_0x4a631a,async()=>{if(V(_0x16a3fb['unitID'],_0x16a3fb['type']),!_0x16a3fb['blockID'])throw J('blockID\x20is\x20required');await this['_requireUnit'](_0x4a631a,_0x16a3fb['unitID'],_0x16a3fb['type']),_0x4e2026={'block':await this['_database'](()=>this['_dbAdapter']['getSheetBlock'](_0x4a631a,_0x16a3fb['unitID'],_0x16a3fb['blockID']))};}),_0x4e2026;});}['createUnitFromSnapshot'](_0x4c97f6,_0x267e94){return this['_call']('createUnitFromSnapshot',()=>this['_createUnit'](_0x4c97f6,y(_0x267e94)));}['createUnitFromData'](_0x4ce632,_0x35848d){return this['_call']('createUnitFromData',async()=>{if(!_0x4ce632||!B['has'](_0x4ce632['type']))throw J('Unsupported\x20unit\x20type');if(!_0x4ce632['data']?.['id'])throw J('data.id\x20is\x20required');if(_0x4ce632['data']['rev']!==0x1)throw J('Initial\x20Unit\x20data\x20revision\x20must\x20be\x201');let _0x11f720=y(_0x35848d),_0x5b6636=await Ge(_0x4ce632);return this['_createUnit'](_0x5b6636,_0x11f720);});}['deleteUnits'](_0x4458f4,_0x54c739){return this['_call']('deleteUnits',async()=>{let _0x2b532a=y(_0x54c739),_0xa1a1d8=H(_0x4458f4?.['unitIDs']);if(_0x4458f4['hardDelete']!==void 0x0&&typeof _0x4458f4['hardDelete']!='boolean')throw J('hardDelete\x20must\x20be\x20a\x20boolean');let _0x493742=He({'unitIDs':_0xa1a1d8,'hardDelete':_0x4458f4['hardDelete']??!0x1}),_0x415dfe={..._0x2b532a,'request':_0x493742},_0x559d7c;return await this['_coordinator']['runExclusiveMany'](_0xa1a1d8,()=>this['_middleware']['run']('deleteUnits',_0x415dfe,async()=>{let _0x7892ff=await this['_database'](()=>this['_dbAdapter']['deleteUnits'](_0x415dfe,{'unitIDs':_0xa1a1d8,'hardDelete':_0x493742['hardDelete']}));for(let _0xc75d87 of _0xa1a1d8)this['_runtime']['disposeUnit'](_0xc75d87);yt(_0x7892ff,_0xa1a1d8,_0x493742['hardDelete']),_0x559d7c=_0x7892ff,await this['_events']['emit']('unitsDeleted',{'userID':_0x2b532a['userID'],'customData':_0x2b532a['customData'],'request':_0x493742,'result':_0x7892ff,'deletedAt':Date['now']()});})),_0x559d7c;});}['recoverUnits'](_0x17fd9b,_0x404c02){return this['_call']('recoverUnits',async()=>{let _0x3835e9=y(_0x404c02),_0x2dc52a=H(_0x17fd9b?.['unitIDs']),_0x4097bc=Ue({'unitIDs':_0x2dc52a}),_0x105d7e={..._0x3835e9,'request':_0x4097bc},_0x4718d6;return await this['_coordinator']['runExclusiveMany'](_0x2dc52a,()=>this['_middleware']['run']('recoverUnits',_0x105d7e,async()=>{let _0x3b2f73=await this['_database'](()=>this['_dbAdapter']['recoverUnits'](_0x105d7e,{'unitIDs':_0x2dc52a}));bt(_0x3b2f73,_0x2dc52a),_0x4718d6=_0x3b2f73,await this['_events']['emit']('unitsRecovered',{'userID':_0x3835e9['userID'],'customData':_0x3835e9['customData'],'request':_0x4097bc,'result':_0x3b2f73,'recoveredAt':Date['now']()});})),_0x4718d6;});}async['submitChangeset'](_0x34aa92,_0x2ffd4a){try{return await this['_lifecycle']['run'](async()=>{let _0x359261=b(_0x2ffd4a),_0x4a6bc2=We(_0x34aa92,_0x359261),_0x2f95fe={..._0x359261,'request':_0x4a6bc2},_0x52fc81;return await this['_middleware']['run']('submitChangeset',_0x2f95fe,async()=>{_0x52fc81=await this['_submitEngine']['submit'](_0x2f95fe,_0x4a6bc2);}),_0x52fc81;});}catch(_0xf45b85){let _0x18f8ed=this['_normalizeError']('submitChangeset',_0xf45b85);return{'status':_0x18f8ed['retryable']?'retry':'rejected','error':_0x18f8ed};}}['dispose'](){return this['_lifecycle']['dispose'](async()=>{this['_middleware']['clear'](),this['_events']['clear'](),await this['_runtime']['dispose']();});}async['_getUnitLoadData'](_0x27bab7,_0x3e121e){V(_0x3e121e['unitID'],_0x3e121e['type']),W('revision',_0x3e121e['revision']);let _0x1fd086=await this['_requireUnit'](_0x27bab7,_0x3e121e['unitID'],_0x3e121e['type']),_0x55f737=G(_0x3e121e['revision'],_0x1fd086),_0x55dd13=await this['_database'](()=>this['_dbAdapter']['getSnapshot'](_0x27bab7,_0x3e121e['unitID'],{'revision':_0x55f737}));if(!_0x55dd13)throw new g('ADAPTER_FAILURE','Database\x20returned\x20a\x20unit\x20without\x20a\x20recoverable\x20snapshot',{'retryable':!0x0});if(_0x55dd13['unitID']!==_0x3e121e['unitID']||_0x55dd13['type']!==_0x3e121e['type']||!Number['isSafeInteger'](_0x55dd13['rev'])||_0x55dd13['rev']<0x1||_0x55dd13['rev']>_0x55f737)throw new g('ADAPTER_FAILURE','Database\x20returned\x20an\x20invalid\x20snapshot',{'retryable':!0x0});let _0x1bac66=await this['_database'](()=>this['_dbAdapter']['getChangesets'](_0x27bab7,_0x3e121e['unitID'],{'from':_0x55dd13['rev'],'to':_0x55f737}));return q(_0x1bac66['latestRevision'],_0x55f737),K(_0x1bac66['changesets'],_0x3e121e['unitID'],_0x3e121e['type'],_0x55dd13['rev']+0x1,_0x55f737),{'snapshot':_0x55dd13,'changesets':_0x1bac66['changesets'],'targetRevision':_0x55f737};}async['_getSnapshotSheetBlocks'](_0x2dd7ef,_0x1ed2ba){let _0x3b894a=T(_0x1ed2ba);return Promise['all'](_0x3b894a['map'](async _0xe2d3=>{let _0x4c1efa=await this['_database'](()=>this['_dbAdapter']['getSheetBlock'](_0x2dd7ef,_0x1ed2ba['unitID'],_0xe2d3));if(!_0x4c1efa||_0x4c1efa['id']!==_0xe2d3)throw Y('Database\x20returned\x20an\x20invalid\x20referenced\x20Sheet\x20block\x20'+_0xe2d3);return _0x4c1efa;}));}async['_createUnit'](_0x23e894,_0x1bd9dc){let _0x56ad20=Ve(_0x23e894),_0x2c6e27={..._0x1bd9dc,'request':_0x56ad20},_0x5deacc,{snapshot:_0x3c2f18}=_0x23e894;return await this['_coordinator']['runExclusive'](_0x3c2f18['unitID'],()=>this['_middleware']['run']('createUnit',_0x2c6e27,async()=>{if(V(_0x3c2f18['unitID'],_0x3c2f18['type']),_0x3c2f18['rev']!==0x1)throw J('Initial\x20snapshot\x20revision\x20must\x20be\x201');let _0x48ea84=await this['_database'](()=>this['_dbAdapter']['createUnit'](_0x2c6e27,{'record':{'unitID':_0x3c2f18['unitID'],'type':_0x3c2f18['type'],'headRevision':0x1},'snapshot':_0x3c2f18,..._0x23e894['sheetBlocks']===void 0x0?{}:{'sheetBlocks':_0x23e894['sheetBlocks']}}));if(_0x48ea84['record']['unitID']!==_0x3c2f18['unitID']||_0x48ea84['record']['type']!==_0x3c2f18['type']||!Number['isSafeInteger'](_0x48ea84['record']['headRevision'])||_0x48ea84['record']['headRevision']<0x1)throw new g('ADAPTER_FAILURE','Database\x20returned\x20an\x20invalid\x20created\x20unit\x20record',{'retryable':!0x0});_0x5deacc={'status':_0x48ea84['status'],'unitID':_0x48ea84['record']['unitID'],'headRevision':_0x48ea84['record']['headRevision']},_0x48ea84['status']==='created'&&await this['_events']['emit']('unitCreated',{'userID':_0x1bd9dc['userID'],'customData':_0x1bd9dc['customData'],'request':_0x56ad20,'record':_0x48ea84['record'],'createdAt':Date['now']()});})),_0x5deacc;}async['_requireUnit'](_0x3bb883,_0x3a9d84,_0x5acbf1){let _0x3a60f5=await this['_database'](()=>this['_dbAdapter']['getUnit'](_0x3bb883,_0x3a9d84));if(!_0x3a60f5)throw new g('UNIT_NOT_FOUND','Unit\x20'+_0x3a9d84+'\x20does\x20not\x20exist');if(_0x3a60f5['unitID']!==_0x3a9d84)throw new g('ADAPTER_FAILURE','Database\x20returned\x20Unit\x20metadata\x20for\x20a\x20different\x20identity',{'retryable':!0x0});if(_0x3a60f5['type']!==_0x5acbf1)throw J('Unit\x20type\x20does\x20not\x20match\x20the\x20stored\x20unit');if(!Number['isSafeInteger'](_0x3a60f5['headRevision'])||_0x3a60f5['headRevision']<0x1)throw new g('ADAPTER_FAILURE','Database\x20returned\x20an\x20invalid\x20unit\x20head\x20revision',{'retryable':!0x0});return _0x3a60f5;}async['_database'](_0x3b845f){try{return await _0x3b845f();}catch(_0x4ce31c){throw _0x4ce31c instanceof g?_0x4ce31c:new g('ADAPTER_FAILURE','Database\x20Adapter\x20failed',{'retryable':!0x0,'cause':_0x4ce31c});}}async['_call'](_0x3a39f3,_0x3472ab){try{return this['_metrics']['increment']('collaboration.service.call',{'operation':_0x3a39f3}),await this['_lifecycle']['run'](_0x3472ab);}catch(_0x5d2346){throw this['_normalizeError'](_0x3a39f3,_0x5d2346);}}['_normalizeError'](_0x4ff246,_0x4c7d0d){return _0x4c7d0d instanceof g?_0x4c7d0d:(this['_logger']['error']('Collaboration\x20Service\x20operation\x20failed',{'operation':_0x4ff246,'error':X(_0x4c7d0d)}),new g('INTERNAL_ERROR','Collaboration\x20Service\x20failed',{'retryable':!0x0,'cause':_0x4c7d0d}));}['_assertRunning'](){if(this['_lifecycle']['state']!=='running')throw new g('INTERNAL_ERROR','Collaboration\x20Service\x20is\x20'+this['_lifecycle']['state'],{'retryable':!0x0});}};function V(_0x4fd3fa,_0x370ca6){if(!_0x4fd3fa)throw J('unitID\x20is\x20required');if(!B['has'](_0x370ca6))throw J('Unsupported\x20unit\x20type');}function H(_0x29375b){if(!Array['isArray'](_0x29375b)||_0x29375b['length']===0x0)throw J('unitIDs\x20must\x20be\x20a\x20non-empty\x20array');if(_0x29375b['length']>0x64)throw J('unitIDs\x20cannot\x20contain\x20more\x20than\x20100\x20values');let _0x1cd1b6=[],_0x48ff27=new Set();for(let _0x4d606c of _0x29375b){if(typeof _0x4d606c!='string'||_0x4d606c['trim']()['length']===0x0)throw J('unitIDs\x20cannot\x20contain\x20empty\x20values');_0x48ff27['has'](_0x4d606c)||(_0x48ff27['add'](_0x4d606c),_0x1cd1b6['push'](_0x4d606c));}return _0x1cd1b6;}function yt(_0x4751bc,_0x11140d,_0x5901be){let _0x53e487=_0x5901be?new Set(['hard-deleted','already-hard-deleted']):new Set(['soft-deleted','already-soft-deleted']);U(_0x4751bc?.['units'],_0x11140d,_0x53e487,'delete');}function bt(_0x5162fd,_0x4123e5){let _0x48f535=new Set(['recovered','already-active']);U(_0x5162fd?.['units'],_0x4123e5,_0x48f535,'recover');}function U(_0x3b59ff,_0x5e622a,_0x457d9c,_0xba6d04){if(!Array['isArray'](_0x3b59ff)||_0x3b59ff['length']!==_0x5e622a['length'])throw Y('Database\x20returned\x20incomplete\x20'+_0xba6d04+'\x20Unit\x20results');for(let [_0x1df24d,_0x3d6d50]of _0x3b59ff['entries']())if(!_0x3d6d50||_0x3d6d50['unitID']!==_0x5e622a[_0x1df24d]||!_0x457d9c['has'](_0x3d6d50['status']))throw Y('Database\x20returned\x20invalid\x20'+_0xba6d04+'\x20Unit\x20results');}function W(_0x4afd4b,_0x229c08){if(!Number['isSafeInteger'](_0x229c08)||_0x229c08<0x0)throw J(_0x4afd4b+'\x20must\x20be\x20a\x20non-negative\x20safe\x20integer');}function G(_0x4dfd94,_0x43a935){let _0x1d229e=_0x4dfd94===0x0?_0x43a935['headRevision']:_0x4dfd94;if(_0x1d229e<0x1||_0x1d229e>_0x43a935['headRevision'])throw J('Requested\x20revision\x20is\x20outside\x20the\x20stored\x20unit\x20history');return _0x1d229e;}function K(_0x2177cd,_0x13c1f0,_0x444ce6,_0x52d500,_0x1e5e15){let _0x51e295=_0x52d500;for(let _0x15a9c8 of _0x2177cd){if(_0x15a9c8['unitID']!==_0x13c1f0||_0x15a9c8['type']!==_0x444ce6||_0x15a9c8['baseRev']!==_0x51e295-0x1||_0x15a9c8['revision']!==_0x51e295)throw new g('ADAPTER_FAILURE','Database\x20returned\x20a\x20non-contiguous\x20changeset\x20history',{'retryable':!0x0});_0x51e295+=0x1;}if(_0x51e295-0x1!==_0x1e5e15)throw new g('ADAPTER_FAILURE','Database\x20returned\x20an\x20incomplete\x20changeset\x20history',{'retryable':!0x0});}function q(_0x14eff6,_0x51d4e6){if(!Number['isSafeInteger'](_0x14eff6)||_0x14eff6<_0x51d4e6)throw new g('ADAPTER_FAILURE','Database\x20returned\x20an\x20invalid\x20latest\x20revision',{'retryable':!0x0});}function J(_0x2a336d){return new g('INVALID_REQUEST',_0x2a336d);}function Y(_0x508227){return new g('ADAPTER_FAILURE',_0x508227,{'retryable':!0x0});}function X(_0x1de113){return _0x1de113 instanceof Error?_0x1de113['message']:String(_0x1de113);}var Z=class{['_adapter']=new xt();['_runtime']=new j({'dbAdapter':this['_adapter']});['_coordinator']=new R();['_lifecycle']=new z('Unit\x20Snapshot\x20Materializer');['materializeSnapshot'](_0x2d46ef){return this['_lifecycle']['run'](async()=>{St(_0x2d46ef);let {snapshot:_0x21538d,targetRevision:_0x49276e}=_0x2d46ef;return this['_coordinator']['runExclusive'](_0x21538d['unitID'],async()=>{this['_runtime']['disposeUnit'](_0x21538d['unitID']),this['_adapter']['bind'](_0x2d46ef);let _0xb3a1ba={'userID':'unit-snapshot-materializer','customData':Object['create'](null),'request':Object['create'](null)},_0x5377b8;try{_0x5377b8=await this['_runtime']['ensureUnit'](_0xb3a1ba,_0x21538d['unitID'],_0x21538d['type']);let _0x1e6611=await this['_runtime']['createSnapshot'](_0x5377b8);if(_0x1e6611['snapshot']['unitID']!==_0x21538d['unitID']||_0x1e6611['snapshot']['type']!==_0x21538d['type']||_0x1e6611['snapshot']['rev']!==_0x49276e)throw new g('INTERNAL_ERROR','Unit\x20Runtime\x20materialized\x20an\x20unexpected\x20snapshot\x20revision',{'retryable':!0x0});return{'snapshot':_0x1e6611['snapshot'],'sheetBlocks':[..._0x1e6611['sheetBlocks']??[]]};}finally{_0x5377b8&&this['_runtime']['releaseUnit'](_0x5377b8),this['_runtime']['disposeUnit'](_0x21538d['unitID']),this['_adapter']['unbind'](_0x21538d['unitID']);}});});}['dispose'](){return this['_lifecycle']['dispose'](()=>this['_runtime']['dispose']());}},xt=class{['_bound']=new Map();['bind'](_0x1112f2){let _0x6a4a25;try{_0x6a4a25={'snapshot':structuredClone(_0x1112f2['snapshot']),'sheetBlocks':structuredClone(_0x1112f2['sheetBlocks']),'changesets':structuredClone(_0x1112f2['changesets']),'targetRevision':_0x1112f2['targetRevision']};}catch(_0x3795ce){throw new g('INVALID_REQUEST','Materialization\x20input\x20must\x20be\x20structured-cloneable',{'cause':_0x3795ce});}this['_bound']['set'](_0x6a4a25['snapshot']['unitID'],{'input':_0x6a4a25,'blocks':new Map(_0x6a4a25['sheetBlocks']['map'](_0x551921=>[_0x551921['id'],_0x551921]))});}['unbind'](_0x1338f2){this['_bound']['delete'](_0x1338f2);}async['getUnit'](_0x25834d,_0x17220c){let _0x112353=this['_bound']['get'](_0x17220c);return _0x112353?{'unitID':_0x17220c,'type':_0x112353['input']['snapshot']['type'],'headRevision':_0x112353['input']['targetRevision']}:null;}async['getSnapshot'](_0x3077,_0x12a2c5,_0x36e66a){let _0x1d709e=this['_bound']['get'](_0x12a2c5),_0x18c3fd=_0x36e66a?.['revision']??_0x1d709e?.['input']['targetRevision'];return _0x1d709e&&_0x18c3fd!==void 0x0&&_0x1d709e['input']['snapshot']['rev']<=_0x18c3fd?_0x1d709e['input']['snapshot']:null;}async['getChangesets'](_0x275254,_0x4328b0,_0x58a946){let _0x2323ef=this['_require'](_0x4328b0);return{'changesets':_0x2323ef['input']['changesets']['filter'](_0x160c3f=>_0x160c3f['revision']>_0x58a946['from']&&_0x160c3f['revision']<=_0x58a946['to']),'latestRevision':_0x2323ef['input']['targetRevision']};}['getSheetBlock'](_0x572baf,_0x10c7d6,_0x74bc41){return Promise['resolve'](this['_require'](_0x10c7d6)['blocks']['get'](_0x74bc41)??null);}['createUnit'](_0x464ea0,_0x36477a){return $('createUnit');}['deleteUnits'](_0x5747eb,_0x239c94){return $('deleteUnits');}['recoverUnits'](_0x5b5f3a,_0x17b0d1){return $('recoverUnits');}['commitChangeset'](_0x4b9320,_0x4f0a19){return $('commitChangeset');}['saveSnapshot'](_0x3aca46,_0x37e400){return $('saveSnapshot');}['_require'](_0x3e2fd7){let _0x6e8a91=this['_bound']['get'](_0x3e2fd7);if(!_0x6e8a91)throw new g('INTERNAL_ERROR','Materialization\x20data\x20for\x20Unit\x20'+_0x3e2fd7+'\x20is\x20unavailable',{'retryable':!0x0});return _0x6e8a91;}};function St(_0x138243){if(!_0x138243||typeof _0x138243!='object'||!_0x138243['snapshot'])throw Q('Materialization\x20input\x20requires\x20a\x20snapshot');let {snapshot:_0x30cddf,targetRevision:_0x1f8c02,changesets:_0x19f62f,sheetBlocks:_0x14ddbf}=_0x138243;if(typeof _0x30cddf['unitID']!='string'||_0x30cddf['unitID']['length']===0x0||!Number['isSafeInteger'](_0x30cddf['rev'])||_0x30cddf['rev']<0x1||!Number['isSafeInteger'](_0x1f8c02)||_0x1f8c02<_0x30cddf['rev'])throw Q('Materialization\x20revisions\x20are\x20invalid');if(!Array['isArray'](_0x19f62f)||!Array['isArray'](_0x14ddbf))throw Q('Materialization\x20changesets\x20and\x20sheetBlocks\x20must\x20be\x20arrays');let _0x5ad692=_0x30cddf['rev']+0x1;for(let _0x3238df of _0x19f62f){if(_0x3238df['unitID']!==_0x30cddf['unitID']||_0x3238df['type']!==_0x30cddf['type']||_0x3238df['baseRev']!==_0x5ad692-0x1||_0x3238df['revision']!==_0x5ad692)throw Q('Materialization\x20changesets\x20are\x20not\x20contiguous');_0x5ad692+=0x1;}if(_0x5ad692-0x1!==_0x1f8c02)throw Q('Materialization\x20changesets\x20do\x20not\x20reach\x20targetRevision');let _0x51faee=new Map();for(let _0x1977c3 of _0x14ddbf){if(!_0x1977c3||typeof _0x1977c3['id']!='string'||_0x1977c3['id']['length']===0x0||_0x51faee['has'](_0x1977c3['id']))throw Q('Materialization\x20Sheet\x20blocks\x20are\x20invalid');_0x51faee['set'](_0x1977c3['id'],_0x1977c3);}for(let _0x490df0 of T(_0x30cddf))if(!_0x51faee['has'](_0x490df0))throw Q('Materialization\x20is\x20missing\x20Sheet\x20block\x20'+_0x490df0);}function Q(_0x2f96ba){return new g('INVALID_REQUEST',_0x2f96ba);}function $(_0x4d22cd){return Promise['reject'](new g('INTERNAL_ERROR','Snapshot\x20materializer\x20Adapter\x20does\x20not\x20support\x20'+_0x4d22cd,{'retryable':!0x0}));}exports['CollabError']=g,exports['MAX_UNIT_LIFECYCLE_BATCH_SIZE']=_t,exports['UnitSnapshotMaterializer']=Z,exports['UniverCollabService']=vt,exports['UniverUnitRuntime']=j;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import { IChangeset, ISheetBlock, ISnapshot, UniverType } from "@univerjs/protocol";
|
|
2
|
+
import { IBoardData } from "@univerjs-pro/boards";
|
|
3
|
+
import { ISlideData } from "@univerjs-pro/slides";
|
|
4
|
+
import { IBaseSnapshot, IDocumentData, IWorkbookData } from "@univerjs/core";
|
|
5
|
+
import { IChangeset as IChangeset$1, ITransformService } from "@univerjs-pro/collaboration";
|
|
6
|
+
|
|
7
|
+
//#region src/common/types.d.ts
|
|
8
|
+
type JsonPrimitive = boolean | number | string | null;
|
|
9
|
+
type JsonValue = JsonPrimitive | JsonObject | readonly JsonValue[];
|
|
10
|
+
interface JsonObject {
|
|
11
|
+
readonly [key: string]: JsonValue;
|
|
12
|
+
}
|
|
13
|
+
type CustomData = Record<string, unknown>;
|
|
14
|
+
interface Disposable {
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/snapshots/types.d.ts
|
|
19
|
+
interface SaveSnapshotInput {
|
|
20
|
+
readonly snapshot: ISnapshot;
|
|
21
|
+
readonly sheetBlocks?: readonly ISheetBlock[];
|
|
22
|
+
}
|
|
23
|
+
interface UnitLoadData {
|
|
24
|
+
readonly snapshot: ISnapshot;
|
|
25
|
+
readonly changesets: readonly IChangeset[];
|
|
26
|
+
readonly targetRevision: number;
|
|
27
|
+
}
|
|
28
|
+
interface UnitLoadDataWithBlocks extends UnitLoadData {
|
|
29
|
+
readonly sheetBlocks: readonly ISheetBlock[];
|
|
30
|
+
}
|
|
31
|
+
interface ISnapshotWithBlocks {
|
|
32
|
+
snapshot: ISnapshot;
|
|
33
|
+
sheetBlocks: ISheetBlock[];
|
|
34
|
+
}
|
|
35
|
+
interface SnapshotPolicy {
|
|
36
|
+
shouldCreate(input: {
|
|
37
|
+
readonly unitID: string;
|
|
38
|
+
readonly type: UniverType;
|
|
39
|
+
readonly revision: number;
|
|
40
|
+
readonly changesetBytes: number;
|
|
41
|
+
readonly revisionsSinceLastSnapshot: number;
|
|
42
|
+
}): boolean;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/request/request.d.ts
|
|
46
|
+
interface BaseReadUnitDataRequest {
|
|
47
|
+
readonly unitID: string;
|
|
48
|
+
readonly type: UniverType;
|
|
49
|
+
}
|
|
50
|
+
interface GetUnitLoadDataRequest extends BaseReadUnitDataRequest {
|
|
51
|
+
readonly revision: number;
|
|
52
|
+
}
|
|
53
|
+
interface GetChangesetsRequest extends BaseReadUnitDataRequest {
|
|
54
|
+
readonly from: number;
|
|
55
|
+
readonly to: number;
|
|
56
|
+
}
|
|
57
|
+
interface GetSheetBlockRequest extends BaseReadUnitDataRequest {
|
|
58
|
+
readonly blockID: string;
|
|
59
|
+
}
|
|
60
|
+
type ReadUnitDataRequest = GetUnitLoadDataRequest | GetChangesetsRequest | GetSheetBlockRequest;
|
|
61
|
+
interface CreateUnitRequest {
|
|
62
|
+
readonly snapshot: ISnapshot;
|
|
63
|
+
readonly sheetBlocks?: readonly ISheetBlock[];
|
|
64
|
+
}
|
|
65
|
+
interface DeleteUnitsRequest {
|
|
66
|
+
readonly unitIDs: readonly string[];
|
|
67
|
+
readonly hardDelete: boolean;
|
|
68
|
+
}
|
|
69
|
+
interface RecoverUnitsRequest {
|
|
70
|
+
readonly unitIDs: readonly string[];
|
|
71
|
+
}
|
|
72
|
+
interface SubmitChangesetRequest {
|
|
73
|
+
readonly changeset: IChangeset;
|
|
74
|
+
}
|
|
75
|
+
type CollabRequest = ReadUnitDataRequest | CreateUnitRequest | DeleteUnitsRequest | RecoverUnitsRequest | SubmitChangesetRequest;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/database/adapter.d.ts
|
|
78
|
+
interface DatabaseContext<TRequest extends object = object> {
|
|
79
|
+
readonly userID: string;
|
|
80
|
+
readonly customData: CustomData;
|
|
81
|
+
readonly request: TRequest;
|
|
82
|
+
}
|
|
83
|
+
interface SubmitDatabaseContext extends DatabaseContext<SubmitChangesetRequest> {
|
|
84
|
+
readonly memberID: string;
|
|
85
|
+
}
|
|
86
|
+
interface UnitRecord {
|
|
87
|
+
readonly unitID: string;
|
|
88
|
+
readonly type: UniverType;
|
|
89
|
+
readonly headRevision: number;
|
|
90
|
+
}
|
|
91
|
+
interface ChangesetRange {
|
|
92
|
+
readonly changesets: readonly IChangeset[];
|
|
93
|
+
readonly latestRevision: number;
|
|
94
|
+
}
|
|
95
|
+
interface CreateUnitDatabaseInput {
|
|
96
|
+
readonly record: UnitRecord;
|
|
97
|
+
readonly snapshot: ISnapshot;
|
|
98
|
+
readonly sheetBlocks?: readonly ISheetBlock[];
|
|
99
|
+
}
|
|
100
|
+
type CreateUnitDatabaseResult = {
|
|
101
|
+
readonly status: "created";
|
|
102
|
+
readonly record: UnitRecord;
|
|
103
|
+
} | {
|
|
104
|
+
readonly status: "already-exists";
|
|
105
|
+
readonly record: UnitRecord;
|
|
106
|
+
};
|
|
107
|
+
type DeleteUnitDatabaseStatus = "soft-deleted" | "already-soft-deleted" | "hard-deleted" | "already-hard-deleted";
|
|
108
|
+
interface DeleteUnitsDatabaseInput {
|
|
109
|
+
readonly unitIDs: readonly string[];
|
|
110
|
+
readonly hardDelete: boolean;
|
|
111
|
+
}
|
|
112
|
+
interface DeleteUnitsDatabaseResult {
|
|
113
|
+
readonly units: readonly {
|
|
114
|
+
readonly unitID: string;
|
|
115
|
+
readonly status: DeleteUnitDatabaseStatus;
|
|
116
|
+
}[];
|
|
117
|
+
}
|
|
118
|
+
type RecoverUnitDatabaseStatus = "recovered" | "already-active";
|
|
119
|
+
interface RecoverUnitsDatabaseInput {
|
|
120
|
+
readonly unitIDs: readonly string[];
|
|
121
|
+
}
|
|
122
|
+
interface RecoverUnitsDatabaseResult {
|
|
123
|
+
readonly units: readonly {
|
|
124
|
+
readonly unitID: string;
|
|
125
|
+
readonly status: RecoverUnitDatabaseStatus;
|
|
126
|
+
}[];
|
|
127
|
+
}
|
|
128
|
+
interface CommitChangesetInput {
|
|
129
|
+
readonly changeset: IChangeset;
|
|
130
|
+
}
|
|
131
|
+
type CommitChangesetResult = {
|
|
132
|
+
readonly status: "committed";
|
|
133
|
+
readonly changeset: IChangeset;
|
|
134
|
+
readonly headRevision: number;
|
|
135
|
+
} | {
|
|
136
|
+
readonly status: "revision-mismatch";
|
|
137
|
+
readonly actualHeadRevision: number;
|
|
138
|
+
};
|
|
139
|
+
interface IDatabaseAdapter {
|
|
140
|
+
getUnit(context: DatabaseContext<object>, unitID: string): Promise<UnitRecord | null>;
|
|
141
|
+
getSnapshot(context: DatabaseContext<object>, unitID: string, options?: {
|
|
142
|
+
readonly revision?: number;
|
|
143
|
+
}): Promise<ISnapshot | null>;
|
|
144
|
+
getChangesets(context: DatabaseContext<object>, unitID: string, range: {
|
|
145
|
+
readonly from: number;
|
|
146
|
+
readonly to: number;
|
|
147
|
+
}): Promise<ChangesetRange>;
|
|
148
|
+
createUnit(context: DatabaseContext<object>, input: CreateUnitDatabaseInput): Promise<CreateUnitDatabaseResult>;
|
|
149
|
+
deleteUnits(context: DatabaseContext<object>, input: DeleteUnitsDatabaseInput): Promise<DeleteUnitsDatabaseResult>;
|
|
150
|
+
recoverUnits(context: DatabaseContext<object>, input: RecoverUnitsDatabaseInput): Promise<RecoverUnitsDatabaseResult>;
|
|
151
|
+
commitChangeset(context: SubmitDatabaseContext, input: CommitChangesetInput): Promise<CommitChangesetResult>;
|
|
152
|
+
saveSnapshot(context: DatabaseContext<object>, input: SaveSnapshotInput): Promise<void>;
|
|
153
|
+
getSheetBlock(context: DatabaseContext<object>, unitID: string, blockID: string): Promise<ISheetBlock | null>;
|
|
154
|
+
dispose?(): Promise<void>;
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/errors/collab-error.d.ts
|
|
158
|
+
type CollabErrorCode = "UNAUTHENTICATED" | "INVALID_REQUEST" | "UNIT_NOT_FOUND" | "PERMISSION_DENIED" | "OT_CONFLICT" | "REVISION_MISMATCH" | "ADAPTER_FAILURE" | "INTERNAL_ERROR";
|
|
159
|
+
declare class CollabError extends Error {
|
|
160
|
+
readonly code: CollabErrorCode;
|
|
161
|
+
readonly retryable: boolean;
|
|
162
|
+
readonly details?: Readonly<JsonObject>;
|
|
163
|
+
constructor(code: CollabErrorCode, message: string, options?: {
|
|
164
|
+
retryable?: boolean;
|
|
165
|
+
details?: Readonly<JsonObject>;
|
|
166
|
+
cause?: unknown;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/context/context.d.ts
|
|
171
|
+
interface CollabContext {
|
|
172
|
+
readonly userID: string;
|
|
173
|
+
readonly customData?: CustomData;
|
|
174
|
+
}
|
|
175
|
+
interface CollabMemberContext extends CollabContext {
|
|
176
|
+
readonly memberID: string;
|
|
177
|
+
}
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/middleware/middleware.d.ts
|
|
180
|
+
type CollabServiceMiddlewareAction = "readUnitData" | "createUnit" | "deleteUnits" | "recoverUnits" | "submitChangeset" | "applyChangeset" | "commitChangeset";
|
|
181
|
+
type MiddlewareNext = () => Promise<void>;
|
|
182
|
+
type Middleware<TContext> = (ctx: TContext, next: MiddlewareNext) => void | Promise<void>;
|
|
183
|
+
interface BaseMiddlewareContext<TRequest extends CollabRequest> {
|
|
184
|
+
readonly userID: string;
|
|
185
|
+
readonly customData: CustomData;
|
|
186
|
+
readonly request: TRequest;
|
|
187
|
+
}
|
|
188
|
+
type ReadUnitDataMiddlewareContext = BaseMiddlewareContext<ReadUnitDataRequest>;
|
|
189
|
+
type CreateUnitMiddlewareContext = BaseMiddlewareContext<CreateUnitRequest>;
|
|
190
|
+
type DeleteUnitsMiddlewareContext = BaseMiddlewareContext<DeleteUnitsRequest>;
|
|
191
|
+
type RecoverUnitsMiddlewareContext = BaseMiddlewareContext<RecoverUnitsRequest>;
|
|
192
|
+
interface SubmitChangesetMiddlewareContext extends BaseMiddlewareContext<SubmitChangesetRequest> {
|
|
193
|
+
readonly memberID: string;
|
|
194
|
+
}
|
|
195
|
+
interface ApplyChangesetMiddlewareContext extends BaseMiddlewareContext<SubmitChangesetRequest> {
|
|
196
|
+
readonly memberID: string;
|
|
197
|
+
readonly attempt: number;
|
|
198
|
+
readonly currentRevision: number;
|
|
199
|
+
readonly changeset: Readonly<IChangeset>;
|
|
200
|
+
}
|
|
201
|
+
interface CommitChangesetMiddlewareContext extends BaseMiddlewareContext<SubmitChangesetRequest> {
|
|
202
|
+
readonly memberID: string;
|
|
203
|
+
readonly attempt: number;
|
|
204
|
+
readonly expectedHeadRevision: number;
|
|
205
|
+
readonly changeset: Readonly<IChangeset>;
|
|
206
|
+
}
|
|
207
|
+
interface CollabServiceMiddlewareMap {
|
|
208
|
+
readonly readUnitData: Middleware<ReadUnitDataMiddlewareContext>;
|
|
209
|
+
readonly createUnit: Middleware<CreateUnitMiddlewareContext>;
|
|
210
|
+
readonly deleteUnits: Middleware<DeleteUnitsMiddlewareContext>;
|
|
211
|
+
readonly recoverUnits: Middleware<RecoverUnitsMiddlewareContext>;
|
|
212
|
+
readonly submitChangeset: Middleware<SubmitChangesetMiddlewareContext>;
|
|
213
|
+
readonly applyChangeset: Middleware<ApplyChangesetMiddlewareContext>;
|
|
214
|
+
readonly commitChangeset: Middleware<CommitChangesetMiddlewareContext>;
|
|
215
|
+
}
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/observability/observability.d.ts
|
|
218
|
+
interface ILogger {
|
|
219
|
+
debug(message: string, fields?: Readonly<JsonObject>): void;
|
|
220
|
+
info(message: string, fields?: Readonly<JsonObject>): void;
|
|
221
|
+
warn(message: string, fields?: Readonly<JsonObject>): void;
|
|
222
|
+
error(message: string, fields?: Readonly<JsonObject>): void;
|
|
223
|
+
}
|
|
224
|
+
interface IMetrics {
|
|
225
|
+
increment(name: string, labels?: Readonly<Record<string, string>>): void;
|
|
226
|
+
observe(name: string, value: number, labels?: Readonly<Record<string, string>>): void;
|
|
227
|
+
}
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/operations/operations.d.ts
|
|
230
|
+
type CreateUnitFromSnapshotInput = ISnapshotWithBlocks;
|
|
231
|
+
interface CreateUnitResult {
|
|
232
|
+
readonly status: "created" | "already-exists";
|
|
233
|
+
readonly unitID: string;
|
|
234
|
+
readonly headRevision: number;
|
|
235
|
+
}
|
|
236
|
+
interface DeleteUnitsInput {
|
|
237
|
+
readonly unitIDs: readonly string[];
|
|
238
|
+
readonly hardDelete?: boolean;
|
|
239
|
+
}
|
|
240
|
+
interface DeleteUnitsResult {
|
|
241
|
+
readonly units: readonly {
|
|
242
|
+
readonly unitID: string;
|
|
243
|
+
readonly status: "soft-deleted" | "already-soft-deleted" | "hard-deleted" | "already-hard-deleted";
|
|
244
|
+
}[];
|
|
245
|
+
}
|
|
246
|
+
interface RecoverUnitsInput {
|
|
247
|
+
readonly unitIDs: readonly string[];
|
|
248
|
+
}
|
|
249
|
+
interface RecoverUnitsResult {
|
|
250
|
+
readonly units: readonly {
|
|
251
|
+
readonly unitID: string;
|
|
252
|
+
readonly status: "recovered" | "already-active";
|
|
253
|
+
}[];
|
|
254
|
+
}
|
|
255
|
+
type CreateUnitFromDataInput = {
|
|
256
|
+
readonly type: UniverType.UNIVER_SHEET;
|
|
257
|
+
readonly data: IWorkbookData;
|
|
258
|
+
} | {
|
|
259
|
+
readonly type: UniverType.UNIVER_DOC;
|
|
260
|
+
readonly data: IDocumentData;
|
|
261
|
+
} | {
|
|
262
|
+
readonly type: UniverType.UNIVER_SLIDE;
|
|
263
|
+
readonly data: ISlideData;
|
|
264
|
+
} | {
|
|
265
|
+
readonly type: UniverType.UNIVER_BOARD;
|
|
266
|
+
readonly data: IBoardData;
|
|
267
|
+
} | {
|
|
268
|
+
readonly type: UniverType.UNIVER_BASE;
|
|
269
|
+
readonly data: IBaseSnapshot;
|
|
270
|
+
};
|
|
271
|
+
interface GetUnitLoadDataInput {
|
|
272
|
+
readonly unitID: string;
|
|
273
|
+
readonly type: UniverType;
|
|
274
|
+
readonly revision: number;
|
|
275
|
+
}
|
|
276
|
+
interface GetChangesetsInput {
|
|
277
|
+
readonly unitID: string;
|
|
278
|
+
readonly type: UniverType;
|
|
279
|
+
readonly from: number;
|
|
280
|
+
readonly to: number;
|
|
281
|
+
}
|
|
282
|
+
interface GetChangesetsResult {
|
|
283
|
+
readonly changesets: readonly IChangeset[];
|
|
284
|
+
readonly latestRevision: number;
|
|
285
|
+
}
|
|
286
|
+
interface GetSheetBlockInput {
|
|
287
|
+
readonly unitID: string;
|
|
288
|
+
readonly type: UniverType;
|
|
289
|
+
readonly blockID: string;
|
|
290
|
+
}
|
|
291
|
+
interface GetSheetBlockResult {
|
|
292
|
+
readonly block: ISheetBlock | null;
|
|
293
|
+
}
|
|
294
|
+
interface SubmitChangesetInput {
|
|
295
|
+
readonly changeset: IChangeset;
|
|
296
|
+
}
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/submit/changeset.d.ts
|
|
299
|
+
type SubmitChangesetResult = {
|
|
300
|
+
readonly status: "committed" | "already-committed";
|
|
301
|
+
readonly changeset: IChangeset;
|
|
302
|
+
} | {
|
|
303
|
+
readonly status: "rejected";
|
|
304
|
+
readonly error: CollabError;
|
|
305
|
+
} | {
|
|
306
|
+
readonly status: "retry";
|
|
307
|
+
readonly error: CollabError;
|
|
308
|
+
};
|
|
309
|
+
//#endregion
|
|
310
|
+
//#region src/service/service.d.ts
|
|
311
|
+
declare const MAX_UNIT_LIFECYCLE_BATCH_SIZE = 100;
|
|
312
|
+
interface UniverCollabServiceOptions {
|
|
313
|
+
readonly dbAdapter: IDatabaseAdapter;
|
|
314
|
+
readonly snapshotPolicy?: SnapshotPolicy | false;
|
|
315
|
+
readonly runtime?: {
|
|
316
|
+
readonly maxLoadedUnits?: number;
|
|
317
|
+
readonly idleTimeoutMs?: number;
|
|
318
|
+
};
|
|
319
|
+
readonly logger?: ILogger;
|
|
320
|
+
readonly metrics?: IMetrics;
|
|
321
|
+
readonly submitChangeset?: {
|
|
322
|
+
readonly maxRevisionRetries?: number;
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
interface ChangesetCommittedEvent {
|
|
326
|
+
readonly userID: string;
|
|
327
|
+
readonly memberID: string;
|
|
328
|
+
readonly customData: Record<string, unknown>;
|
|
329
|
+
readonly request: SubmitChangesetRequest;
|
|
330
|
+
readonly changeset: IChangeset;
|
|
331
|
+
readonly committedAt: number;
|
|
332
|
+
}
|
|
333
|
+
interface UnitCreatedEvent {
|
|
334
|
+
readonly userID: string;
|
|
335
|
+
readonly customData: Record<string, unknown>;
|
|
336
|
+
readonly request: CreateUnitRequest;
|
|
337
|
+
readonly record: UnitRecord;
|
|
338
|
+
readonly createdAt: number;
|
|
339
|
+
}
|
|
340
|
+
interface UnitsDeletedEvent {
|
|
341
|
+
readonly userID: string;
|
|
342
|
+
readonly customData: Record<string, unknown>;
|
|
343
|
+
readonly request: DeleteUnitsRequest;
|
|
344
|
+
readonly result: DeleteUnitsDatabaseResult;
|
|
345
|
+
readonly deletedAt: number;
|
|
346
|
+
}
|
|
347
|
+
interface UnitsRecoveredEvent {
|
|
348
|
+
readonly userID: string;
|
|
349
|
+
readonly customData: Record<string, unknown>;
|
|
350
|
+
readonly request: RecoverUnitsRequest;
|
|
351
|
+
readonly result: RecoverUnitsDatabaseResult;
|
|
352
|
+
readonly recoveredAt: number;
|
|
353
|
+
}
|
|
354
|
+
interface CollabServiceEventMap {
|
|
355
|
+
readonly changesetCommitted: ChangesetCommittedEvent;
|
|
356
|
+
readonly unitCreated: UnitCreatedEvent;
|
|
357
|
+
readonly unitsDeleted: UnitsDeletedEvent;
|
|
358
|
+
readonly unitsRecovered: UnitsRecoveredEvent;
|
|
359
|
+
}
|
|
360
|
+
interface IUniverCollabService {
|
|
361
|
+
use<K extends CollabServiceMiddlewareAction>(action: K, middleware: CollabServiceMiddlewareMap[K]): Disposable;
|
|
362
|
+
getUnitLoadData(input: GetUnitLoadDataInput, context: CollabContext): Promise<UnitLoadData>;
|
|
363
|
+
getUnitLoadDataWithBlocks(input: GetUnitLoadDataInput, context: CollabContext): Promise<UnitLoadDataWithBlocks>;
|
|
364
|
+
getChangesets(input: GetChangesetsInput, context: CollabContext): Promise<GetChangesetsResult>;
|
|
365
|
+
getSheetBlock(input: GetSheetBlockInput, context: CollabContext): Promise<GetSheetBlockResult>;
|
|
366
|
+
createUnitFromSnapshot(input: CreateUnitFromSnapshotInput, context: CollabContext): Promise<CreateUnitResult>;
|
|
367
|
+
createUnitFromData(input: CreateUnitFromDataInput, context: CollabContext): Promise<CreateUnitResult>;
|
|
368
|
+
deleteUnits(input: DeleteUnitsInput, context: CollabContext): Promise<DeleteUnitsResult>;
|
|
369
|
+
recoverUnits(input: RecoverUnitsInput, context: CollabContext): Promise<RecoverUnitsResult>;
|
|
370
|
+
submitChangeset(input: SubmitChangesetInput, context: CollabMemberContext): Promise<SubmitChangesetResult>;
|
|
371
|
+
on<K extends keyof CollabServiceEventMap>(event: K, listener: (event: CollabServiceEventMap[K]) => void | Promise<void>): Disposable;
|
|
372
|
+
dispose(): Promise<void>;
|
|
373
|
+
}
|
|
374
|
+
declare class UniverCollabService implements IUniverCollabService {
|
|
375
|
+
private readonly _dbAdapter;
|
|
376
|
+
private readonly _middleware;
|
|
377
|
+
private readonly _lifecycle;
|
|
378
|
+
private readonly _logger;
|
|
379
|
+
private readonly _metrics;
|
|
380
|
+
private readonly _events;
|
|
381
|
+
private readonly _runtime;
|
|
382
|
+
private readonly _coordinator;
|
|
383
|
+
private readonly _submitEngine;
|
|
384
|
+
constructor(options: UniverCollabServiceOptions);
|
|
385
|
+
use<K extends CollabServiceMiddlewareAction>(action: K, middleware: CollabServiceMiddlewareMap[K]): Disposable;
|
|
386
|
+
on<K extends keyof CollabServiceEventMap>(event: K, listener: (event: CollabServiceEventMap[K]) => void | Promise<void>): Disposable;
|
|
387
|
+
getUnitLoadData(input: GetUnitLoadDataInput, context: CollabContext): Promise<UnitLoadData>;
|
|
388
|
+
getUnitLoadDataWithBlocks(input: GetUnitLoadDataInput, context: CollabContext): Promise<UnitLoadDataWithBlocks>;
|
|
389
|
+
getChangesets(input: GetChangesetsInput, context: CollabContext): Promise<GetChangesetsResult>;
|
|
390
|
+
getSheetBlock(input: GetSheetBlockInput, context: CollabContext): Promise<GetSheetBlockResult>;
|
|
391
|
+
createUnitFromSnapshot(input: CreateUnitFromSnapshotInput, context: CollabContext): Promise<CreateUnitResult>;
|
|
392
|
+
createUnitFromData(input: CreateUnitFromDataInput, context: CollabContext): Promise<CreateUnitResult>;
|
|
393
|
+
deleteUnits(input: DeleteUnitsInput, context: CollabContext): Promise<DeleteUnitsResult>;
|
|
394
|
+
recoverUnits(input: RecoverUnitsInput, context: CollabContext): Promise<RecoverUnitsResult>;
|
|
395
|
+
submitChangeset(input: SubmitChangesetInput, context: CollabMemberContext): Promise<SubmitChangesetResult>;
|
|
396
|
+
dispose(): Promise<void>;
|
|
397
|
+
private _getUnitLoadData;
|
|
398
|
+
private _getSnapshotSheetBlocks;
|
|
399
|
+
private _createUnit;
|
|
400
|
+
private _requireUnit;
|
|
401
|
+
private _database;
|
|
402
|
+
private _call;
|
|
403
|
+
private _normalizeError;
|
|
404
|
+
private _assertRunning;
|
|
405
|
+
}
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region src/snapshots/unit-snapshot-materializer.d.ts
|
|
408
|
+
interface IUnitSnapshotMaterializer {
|
|
409
|
+
materializeSnapshot(input: UnitLoadDataWithBlocks): Promise<ISnapshotWithBlocks>;
|
|
410
|
+
dispose(): Promise<void>;
|
|
411
|
+
}
|
|
412
|
+
declare class UnitSnapshotMaterializer implements IUnitSnapshotMaterializer {
|
|
413
|
+
private readonly _adapter;
|
|
414
|
+
private readonly _runtime;
|
|
415
|
+
private readonly _coordinator;
|
|
416
|
+
private readonly _lifecycle;
|
|
417
|
+
materializeSnapshot(input: UnitLoadDataWithBlocks): Promise<ISnapshotWithBlocks>;
|
|
418
|
+
dispose(): Promise<void>;
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/runtime/unit-runtime.d.ts
|
|
422
|
+
interface UnitHandle {
|
|
423
|
+
readonly unitID: string;
|
|
424
|
+
readonly type: UniverType;
|
|
425
|
+
readonly revision: number;
|
|
426
|
+
}
|
|
427
|
+
interface IUnitRuntime {
|
|
428
|
+
ensureUnit(context: DatabaseContext, unitID: string, type: UniverType): Promise<UnitHandle>;
|
|
429
|
+
releaseUnit(handle: UnitHandle): void;
|
|
430
|
+
applyChangeset(context: DatabaseContext, handle: UnitHandle, changeset: Readonly<IChangeset>): Promise<void>;
|
|
431
|
+
createSnapshot(handle: UnitHandle): Promise<SaveSnapshotInput>;
|
|
432
|
+
disposeUnit(unitID: string): void;
|
|
433
|
+
dispose(): Promise<void>;
|
|
434
|
+
}
|
|
435
|
+
interface UnitRuntimeOptions {
|
|
436
|
+
readonly dbAdapter: IDatabaseAdapter;
|
|
437
|
+
readonly maxLoadedUnits?: number;
|
|
438
|
+
readonly idleTimeoutMs?: number;
|
|
439
|
+
}
|
|
440
|
+
//#endregion
|
|
441
|
+
//#region src/submit/univer-changeset-transformer.d.ts
|
|
442
|
+
declare class UniverChangesetTransformer {
|
|
443
|
+
private readonly _transformService;
|
|
444
|
+
constructor(_transformService: ITransformService);
|
|
445
|
+
parseClient(changeset: IChangeset): IChangeset$1;
|
|
446
|
+
transform(original: IChangeset$1, history: readonly IChangeset[]): IChangeset;
|
|
447
|
+
}
|
|
448
|
+
//#endregion
|
|
449
|
+
//#region src/runtime/univer-unit-runtime.d.ts
|
|
450
|
+
declare class UniverUnitRuntime implements IUnitRuntime {
|
|
451
|
+
readonly changesetTransformer: UniverChangesetTransformer;
|
|
452
|
+
private readonly _dbAdapter;
|
|
453
|
+
private readonly _maxLoadedUnits;
|
|
454
|
+
private readonly _idleTimeoutMs;
|
|
455
|
+
private readonly _univer;
|
|
456
|
+
private readonly _instanceService;
|
|
457
|
+
private readonly _commandService;
|
|
458
|
+
private readonly _revisionService;
|
|
459
|
+
private readonly _compressMutationService;
|
|
460
|
+
private readonly _snapshotService;
|
|
461
|
+
private readonly _snapshotSaveService;
|
|
462
|
+
private readonly _formulaCalculationSessionService;
|
|
463
|
+
private readonly _snapshotBridge;
|
|
464
|
+
private readonly _entries;
|
|
465
|
+
private readonly _ensuring;
|
|
466
|
+
private _disposed;
|
|
467
|
+
constructor(options: UnitRuntimeOptions);
|
|
468
|
+
ensureUnit(context: DatabaseContext, unitID: string, type: UniverType): Promise<UnitHandle>;
|
|
469
|
+
releaseUnit(handle: UnitHandle): void;
|
|
470
|
+
applyChangeset(context: DatabaseContext, handle: UnitHandle, changeset: Readonly<IChangeset>): Promise<void>;
|
|
471
|
+
createSnapshot(handle: UnitHandle): Promise<SaveSnapshotInput>;
|
|
472
|
+
disposeUnit(unitID: string): void;
|
|
473
|
+
dispose(): Promise<void>;
|
|
474
|
+
private _ensureUnit;
|
|
475
|
+
private _loadUnit;
|
|
476
|
+
private _loadSdkUnit;
|
|
477
|
+
private _createProtocolSnapshot;
|
|
478
|
+
private _requireSdkUnit;
|
|
479
|
+
private _replayRange;
|
|
480
|
+
private _applyConfirmedChangeset;
|
|
481
|
+
private _restoreHistoricalRevision;
|
|
482
|
+
private _requireEntry;
|
|
483
|
+
private _withBusy;
|
|
484
|
+
private _retain;
|
|
485
|
+
private _adoptReservation;
|
|
486
|
+
private _touch;
|
|
487
|
+
private _evictOverCapacity;
|
|
488
|
+
private _database;
|
|
489
|
+
private _assertOpen;
|
|
490
|
+
}
|
|
491
|
+
//#endregion
|
|
492
|
+
export { type ApplyChangesetMiddlewareContext, type BaseMiddlewareContext, type ChangesetCommittedEvent, type ChangesetRange, type CollabContext, CollabError, type CollabErrorCode, type CollabMemberContext, type CollabRequest, type CollabServiceEventMap, type CollabServiceMiddlewareAction, type CollabServiceMiddlewareMap, type CommitChangesetInput, type CommitChangesetMiddlewareContext, type CommitChangesetResult, type CreateUnitDatabaseInput, type CreateUnitDatabaseResult, type CreateUnitFromDataInput, type CreateUnitFromSnapshotInput, type CreateUnitMiddlewareContext, type CreateUnitRequest, type CreateUnitResult, type CustomData, type DatabaseContext, type DeleteUnitDatabaseStatus, type DeleteUnitsDatabaseInput, type DeleteUnitsDatabaseResult, type DeleteUnitsInput, type DeleteUnitsMiddlewareContext, type DeleteUnitsRequest, type DeleteUnitsResult, type Disposable, type GetChangesetsInput, type GetChangesetsRequest, type GetChangesetsResult, type GetSheetBlockInput, type GetSheetBlockRequest, type GetSheetBlockResult, type GetUnitLoadDataInput, type GetUnitLoadDataRequest, type IDatabaseAdapter, type ILogger, type IMetrics, type ISnapshotWithBlocks, type IUnitRuntime, type IUnitSnapshotMaterializer, type IUniverCollabService, type JsonObject, type JsonPrimitive, type JsonValue, MAX_UNIT_LIFECYCLE_BATCH_SIZE, type Middleware, type MiddlewareNext, type ReadUnitDataMiddlewareContext, type ReadUnitDataRequest, type RecoverUnitDatabaseStatus, type RecoverUnitsDatabaseInput, type RecoverUnitsDatabaseResult, type RecoverUnitsInput, type RecoverUnitsMiddlewareContext, type RecoverUnitsRequest, type RecoverUnitsResult, type SaveSnapshotInput, type SnapshotPolicy, type SubmitChangesetInput, type SubmitChangesetMiddlewareContext, type SubmitChangesetRequest, type SubmitChangesetResult, type SubmitDatabaseContext, type UnitCreatedEvent, type UnitHandle, type UnitLoadData, type UnitLoadDataWithBlocks, type UnitRecord, type UnitRuntimeOptions, UnitSnapshotMaterializer, type UnitsDeletedEvent, type UnitsRecoveredEvent, UniverCollabService, type UniverCollabServiceOptions, UniverUnitRuntime };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const _0x38a242=_0x210f;(function(_0x1a0fd5,_0x2582b5){const _0x11d8e8=_0x210f,_0x47e5ee=_0x1a0fd5();while(!![]){try{const _0x48dea9=parseInt(_0x11d8e8(0xa7))/0x1+-parseInt(_0x11d8e8(0xa9))/0x2+-parseInt(_0x11d8e8(0xad))/0x3+-parseInt(_0x11d8e8(0xab))/0x4+-parseInt(_0x11d8e8(0xaa))/0x5*(parseInt(_0x11d8e8(0xae))/0x6)+parseInt(_0x11d8e8(0xa5))/0x7+parseInt(_0x11d8e8(0xa4))/0x8;if(_0x48dea9===_0x2582b5)break;else _0x47e5ee['push'](_0x47e5ee['shift']());}catch(_0x37d007){_0x47e5ee['push'](_0x47e5ee['shift']());}}}(_0x2005,0x75e1e));function _0x210f(_0x2fee85,_0x5d2de9){_0x2fee85=_0x2fee85-0xa4;const _0x2005f9=_0x2005();let _0x210f8c=_0x2005f9[_0x2fee85];return _0x210f8c;}import _0x3ca9ab from'./index.cjs';function _0x2005(){const _0x2274a9=['25465816YKMxXv','206262PQwyRC','UniverCollabService','312341Gqmwdn','UnitSnapshotMaterializer','1541020jLQdVq','30445iSAWcd','3715860UUfTrp','UniverUnitRuntime','1470759oRctwr','840wyzdgk'];_0x2005=function(){return _0x2274a9;};return _0x2005();}const facadeExport0=_0x3ca9ab['CollabError'],facadeExport1=_0x3ca9ab['MAX_UNIT_LIFECYCLE_BATCH_SIZE'],facadeExport2=_0x3ca9ab[_0x38a242(0xa8)],facadeExport3=_0x3ca9ab[_0x38a242(0xa6)],facadeExport4=_0x3ca9ab[_0x38a242(0xac)];export{facadeExport0 as CollabError,facadeExport1 as MAX_UNIT_LIFECYCLE_BATCH_SIZE,facadeExport2 as UnitSnapshotMaterializer,facadeExport3 as UniverCollabService,facadeExport4 as UniverUnitRuntime};
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@univerjs-pro/collaboration-service",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0-beta.2",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@univerjs-pro/bases": "1.0.0-beta.2",
|
|
20
|
+
"@univerjs-pro/boards": "1.0.0-beta.2",
|
|
21
|
+
"@univerjs-pro/boards-chart": "1.0.0-beta.2",
|
|
22
|
+
"@univerjs-pro/boards-mind": "1.0.0-beta.2",
|
|
23
|
+
"@univerjs-pro/boards-table": "1.0.0-beta.2",
|
|
24
|
+
"@univerjs-pro/collaboration": "1.0.0-beta.2",
|
|
25
|
+
"@univerjs-pro/docs-callout": "1.0.0-beta.2",
|
|
26
|
+
"@univerjs-pro/docs-chart": "1.0.0-beta.2",
|
|
27
|
+
"@univerjs-pro/docs-code": "1.0.0-beta.2",
|
|
28
|
+
"@univerjs-pro/docs-latex": "1.0.0-beta.2",
|
|
29
|
+
"@univerjs-pro/docs-shape": "1.0.0-beta.2",
|
|
30
|
+
"@univerjs-pro/docs-table": "1.0.0-beta.2",
|
|
31
|
+
"@univerjs-pro/embed": "1.0.0-beta.2",
|
|
32
|
+
"@univerjs-pro/engine-formula-rust": "1.0.0-beta.2",
|
|
33
|
+
"@univerjs-pro/sheets-chart": "1.0.0-beta.2",
|
|
34
|
+
"@univerjs-pro/sheets-outline": "1.0.0-beta.2",
|
|
35
|
+
"@univerjs-pro/sheets-pivot": "1.0.0-beta.2",
|
|
36
|
+
"@univerjs-pro/sheets-shape": "1.0.0-beta.2",
|
|
37
|
+
"@univerjs-pro/sheets-sparkline": "1.0.0-beta.2",
|
|
38
|
+
"@univerjs-pro/slides": "1.0.0-beta.2",
|
|
39
|
+
"@univerjs-pro/slides-chart": "1.0.0-beta.2",
|
|
40
|
+
"@univerjs-pro/slides-table": "1.0.0-beta.2",
|
|
41
|
+
"@univerjs-pro/thread-comment-resource": "1.0.0-beta.2",
|
|
42
|
+
"@univerjs/core": "1.0.0-beta.2",
|
|
43
|
+
"@univerjs/data-validation": "1.0.0-beta.2",
|
|
44
|
+
"@univerjs/docs": "1.0.0-beta.2",
|
|
45
|
+
"@univerjs/docs-drawing": "1.0.0-beta.2",
|
|
46
|
+
"@univerjs/docs-hyper-link": "1.0.0-beta.2",
|
|
47
|
+
"@univerjs/drawing": "1.0.0-beta.2",
|
|
48
|
+
"@univerjs/engine-formula": "1.0.0-beta.2",
|
|
49
|
+
"@univerjs/protocol": "1.0.0-beta.2",
|
|
50
|
+
"@univerjs/sheets": "1.0.0-beta.2",
|
|
51
|
+
"@univerjs/sheets-conditional-formatting": "1.0.0-beta.2",
|
|
52
|
+
"@univerjs/sheets-drawing": "1.0.0-beta.2",
|
|
53
|
+
"@univerjs/sheets-filter": "1.0.0-beta.2",
|
|
54
|
+
"@univerjs/sheets-formula": "1.0.0-beta.2",
|
|
55
|
+
"@univerjs/sheets-hyper-link": "1.0.0-beta.2",
|
|
56
|
+
"@univerjs/sheets-note": "1.0.0-beta.2",
|
|
57
|
+
"@univerjs/sheets-sort": "1.0.0-beta.2",
|
|
58
|
+
"@univerjs/sheets-table": "1.0.0-beta.2",
|
|
59
|
+
"@univerjs/thread-comment": "1.0.0-beta.2",
|
|
60
|
+
"rxjs": "^7.8.2"
|
|
61
|
+
}
|
|
62
|
+
}
|