@univerjs-pro/collaboration-history-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 ADDED
@@ -0,0 +1,88 @@
1
+ # @univerjs-pro/collaboration-history-service
2
+
3
+ English | [简体中文](./README.zh-CN.md)
4
+
5
+ An optional Univer version-history Service. It groups confirmed collaboration revisions into user-facing history entries, enriches creator profiles, and provides the service contract used by History Endpoint.
6
+
7
+ History is a derived index. Confirmed changesets stored by the collaboration Service remain the authoritative source of Unit state.
8
+
9
+ ```text
10
+ Transport
11
+ → UniverHistoryEndpoint
12
+ → UniverHistoryService
13
+ → History Database Adapter
14
+ ```
15
+
16
+ ## Installation and creation
17
+
18
+ ```bash
19
+ pnpm add \
20
+ @univerjs-pro/collaboration-service \
21
+ @univerjs-pro/collaboration-history-service \
22
+ @univerjs-pro/collaboration-history-endpoint \
23
+ @univerjs-pro/collaboration-history-database-sqlite
24
+ ```
25
+
26
+ ```ts
27
+ import { SQLiteHistoryDatabaseAdapter } from '@univerjs-pro/collaboration-history-database-sqlite';
28
+ import {
29
+ DefaultHistoryPolicy,
30
+ UniverHistoryService,
31
+ } from '@univerjs-pro/collaboration-history-service';
32
+
33
+ const historyDatabase = new SQLiteHistoryDatabaseAdapter({
34
+ filename: './data/collaboration.sqlite',
35
+ });
36
+ const historyService = new UniverHistoryService({
37
+ collabService,
38
+ dbAdapter: historyDatabase,
39
+ policy: new DefaultHistoryPolicy({ timeIntervalMs: 60_000 }),
40
+ userProvider: {
41
+ async getUsers(userIDs) {
42
+ return applicationUsers.findMany(userIDs);
43
+ },
44
+ },
45
+ });
46
+
47
+ const attachment = historyService.attach(collabService);
48
+ ```
49
+
50
+ `attach()` listens for Unit creation and confirmed changesets. The default policy segments history at roughly 60-second intervals and around special mutations such as restore, rather than creating one entry per changeset. If `dbAdapter` is omitted, the Service owns an in-memory Adapter suitable only for tests and temporary environments.
51
+
52
+ ## History middleware
53
+
54
+ History does not inherit middleware from the main Collaboration Service. Five actions independently protect reads and indexing:
55
+
56
+ | Action | When it runs | Visible fields | Retry semantics | Typical uses |
57
+ | --- | --- | --- | --- | --- |
58
+ | `getHistoryList` | After Request creation, before reading History Adapter | `userID`, `customData`, `request` | Once per API call | Unit read ACL, pagination audit |
59
+ | `listHistoryCreators` | After Request creation, before reading creator index | `userID`, `customData`, `request` | Once per API call | Unit read ACL |
60
+ | `getHistoryChangesets` | After Request creation, before reading index and core changesets | `userID`, `customData`, `request` | Once per API call | Unit read ACL, revision-range limits |
61
+ | `indexUnitCreated` | After index Request creation, before writing revision-1 index data | `userID`, `customData`, `request` | Once per logical index; not repeated on collaboration database revision conflicts | Index scope, tenant, audit |
62
+ | `indexChangeset` | After changeset index Request creation, before writing index data | `userID`, `customData`, `request` | Once per logical index; not repeated on collaboration database revision conflicts | Index filtering, tenant, audit |
63
+
64
+ ```ts
65
+ historyService.use('getHistoryList', async (ctx, next) => {
66
+ if (!await acl.canRead(ctx.userID, ctx.request.unitID)) {
67
+ throw new CollabError('PERMISSION_DENIED', 'History is not accessible');
68
+ }
69
+ await next();
70
+ });
71
+ ```
72
+
73
+ User Provider only enriches display users and is not an authorization boundary.
74
+
75
+ When an application reads History Service directly, SDK result fields use `userID/userIDs/unitID`. `UniverHistoryEndpoint` maps them at the HTTP protocol boundary to the `userId/userIds/unitId` fields required by the frontend protocol. No manual conversion is needed when using History Client.
76
+
77
+ ## Reliability and disposal
78
+
79
+ The convenient `attach()` updates the index in-process but does not guarantee that every update completes. Failure does not affect already committed collaboration data. For strictly lossless indexing, write a transactional outbox in the collaboration commit transaction and have a retryable background worker call `indexUnitCreated()` or `indexChangeset()`.
80
+
81
+ ```ts
82
+ attachment.dispose();
83
+ await historyService.dispose();
84
+ await collabService.dispose();
85
+ await historyDatabase.dispose();
86
+ ```
87
+
88
+ History Service does not dispose a Database Adapter injected by the application.
@@ -0,0 +1,96 @@
1
+ # @univerjs-pro/collaboration-history-service
2
+
3
+ [English](./README.md) | [简体中文](./README.zh-CN.md)
4
+
5
+ 可选的 Univer 版本历史 Service,负责把 confirmed collaboration revisions 分组为面向
6
+ 用户的历史条目、补全创建者资料,并提供 History Endpoint 使用的服务契约。
7
+
8
+ History 是派生索引;协同 Service 保存的 confirmed changesets 才是 Unit 状态的权威来源。
9
+
10
+ ```text
11
+ Transport
12
+ → UniverHistoryEndpoint
13
+ → UniverHistoryService
14
+ → History Database Adapter
15
+ ```
16
+
17
+ ## 安装与创建
18
+
19
+ ```bash
20
+ pnpm add \
21
+ @univerjs-pro/collaboration-service \
22
+ @univerjs-pro/collaboration-history-service \
23
+ @univerjs-pro/collaboration-history-endpoint \
24
+ @univerjs-pro/collaboration-history-database-sqlite
25
+ ```
26
+
27
+ ```ts
28
+ import { SQLiteHistoryDatabaseAdapter } from '@univerjs-pro/collaboration-history-database-sqlite';
29
+ import {
30
+ DefaultHistoryPolicy,
31
+ UniverHistoryService,
32
+ } from '@univerjs-pro/collaboration-history-service';
33
+
34
+ const historyDatabase = new SQLiteHistoryDatabaseAdapter({
35
+ filename: './data/collaboration.sqlite',
36
+ });
37
+ const historyService = new UniverHistoryService({
38
+ collabService,
39
+ dbAdapter: historyDatabase,
40
+ policy: new DefaultHistoryPolicy({ timeIntervalMs: 60_000 }),
41
+ userProvider: {
42
+ async getUsers(userIDs) {
43
+ return applicationUsers.findMany(userIDs);
44
+ },
45
+ },
46
+ });
47
+
48
+ const attachment = historyService.attach(collabService);
49
+ ```
50
+
51
+ `attach()` 监听 Unit 创建和 confirmed changeset。默认策略按约 60 秒和 restore 等特殊
52
+ mutation 分段,而不是每条 changeset 生成一个历史项。未传 `dbAdapter` 时 Service 会拥有
53
+ 一个内存 Adapter,只适合测试或临时环境。
54
+
55
+ ## History middleware
56
+
57
+ History 不继承主 Collaboration Service 的 middleware。五个 action 分别保护读取和索引:
58
+
59
+ | Action | 触发时机 | 可见字段 | 重试语义 | 典型用途 |
60
+ | --- | --- | --- | --- | --- |
61
+ | `getHistoryList` | Request 创建后、读取 History Adapter 前 | `userID`、`customData`、`request` | 每次 API 调用一次 | Unit 读取 ACL、分页审计 |
62
+ | `listHistoryCreators` | Request 创建后、读取创建者索引前 | `userID`、`customData`、`request` | 每次 API 调用一次 | Unit 读取 ACL |
63
+ | `getHistoryChangesets` | Request 创建后、读取索引和 core changesets 前 | `userID`、`customData`、`request` | 每次 API 调用一次 | Unit 读取 ACL、revision 范围限制 |
64
+ | `indexUnitCreated` | 创建索引 Request 后、写 revision 1 索引数据前 | `userID`、`customData`、`request` | 每次逻辑索引一次;协同数据库 revision 冲突重试时不重复 | 索引范围、tenant 和审计 |
65
+ | `indexChangeset` | changeset 索引 Request 创建后、写索引数据前 | `userID`、`customData`、`request` | 每次逻辑索引一次;协同数据库 revision 冲突重试时不重复 | 索引过滤、tenant 和审计 |
66
+
67
+ ```ts
68
+ historyService.use('getHistoryList', async (ctx, next) => {
69
+ if (!await acl.canRead(ctx.userID, ctx.request.unitID)) {
70
+ throw new CollabError('PERMISSION_DENIED', 'History is not accessible');
71
+ }
72
+ await next();
73
+ });
74
+ ```
75
+
76
+ User Provider 只补全展示用户,不是鉴权边界。
77
+
78
+ 应用直接读取 History Service 时,SDK 自有结果字段使用 `userID/userIDs/unitID`;
79
+ `UniverHistoryEndpoint` 会在 HTTP 协议边界自动映射为前端协议所需的
80
+ `userId/userIds/unitId`。使用 History Client 时无需手动转换。
81
+
82
+ ## 可靠性与资源释放
83
+
84
+ 便捷的 `attach()` 在进程内更新索引,但不保证每次更新都完成;失败不影响已提交的协同
85
+ 数据。若应用要求索引严格不丢失,应在协同提交事务中写 transactional outbox,再由可重复
86
+ 执行的后台任务调用 `indexUnitCreated()` 或
87
+ `indexChangeset()`。
88
+
89
+ ```ts
90
+ attachment.dispose();
91
+ await historyService.dispose();
92
+ await collabService.dispose();
93
+ await historyDatabase.dispose();
94
+ ```
95
+
96
+ History Service 不会释放应用注入的 Database Adapter。
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object['defineProperty'](exports,Symbol['toStringTag'],{'value':'Module'});let e=require('@univerjs-pro/collaboration'),t=require('@univerjs-pro/collaboration-service');function n(_0x123786){let _0x25b388=[..._0x123786]['sort']((_0x428067,_0x52af06)=>_0x428067['revision']-_0x52af06['revision']),_0x44e531=new Map();for(let _0x419cac of _0x25b388){let _0x27cbe2=_0x44e531['get'](_0x419cac['historyRevision'])??[];_0x27cbe2['push'](_0x419cac),_0x44e531['set'](_0x419cac['historyRevision'],_0x27cbe2);}return[..._0x44e531['values']()]['map'](_0xd4bfc8=>{let _0x1b0a85=_0xd4bfc8[0x0],_0x588907=_0xd4bfc8['at'](-0x1),_0x2fb366=i(_0xd4bfc8['map'](_0x37da49=>_0x37da49['userID'])),_0x50ac47=i(_0xd4bfc8['flatMap'](_0x3f17b9=>_0x3f17b9['commands'])),_0x530531=_0xd4bfc8['find'](_0x45718c=>_0x45718c['restoredRevision']!==void 0x0)?.['restoredRevision'];return{'historyId':_0x1b0a85['unitID']+':'+_0x1b0a85['historyRevision'],'unitID':_0x1b0a85['unitID'],'type':_0x1b0a85['type'],'startRevision':_0x1b0a85['revision'],'endRevision':_0x588907['revision'],'userID':_0x1b0a85['userID'],'userIDs':_0x2fb366,'commands':_0x50ac47,'createdAt':_0x1b0a85['committedAt'],'startRevisionCreatedAt':_0x1b0a85['committedAt'],'endRevisionCreatedAt':_0x588907['committedAt'],..._0x1b0a85['additionalFields']===void 0x0?{}:{'additionalFields':_0x1b0a85['additionalFields']},'origin':_0x1b0a85['origin'],..._0x530531===void 0x0?{}:{'restoredRevision':_0x530531}};});}function r(_0x1f4dc9,_0x57b76d){let _0x4f4484=new Set(_0x57b76d['userIDs']??[]),_0x4c8592=_0x1f4dc9['filter'](_0x411525=>(_0x57b76d['beforeRevision']===void 0x0||_0x411525['startRevision']<_0x57b76d['beforeRevision'])&&(_0x57b76d['origin']===void 0x0||_0x57b76d['origin']===0x0||_0x411525['origin']===_0x57b76d['origin'])&&(_0x4f4484['size']===0x0||_0x411525['userIDs']['some'](_0x53a1d2=>_0x4f4484['has'](_0x53a1d2))))['sort']((_0x1bdf33,_0x21c6fe)=>_0x21c6fe['startRevision']-_0x1bdf33['startRevision']);return{'records':_0x4c8592['slice'](0x0,_0x57b76d['length']),'hasMore':_0x4c8592['length']>_0x57b76d['length']};}function i(_0x586018){return[...new Set(_0x586018)];}var a=class{['_entries']=new Map();['_disposed']=!0x1;async['getIndexState'](_0x1d52d6){this['_assertOpen']();let _0x47456e=o(this['_entries']['get'](_0x1d52d6));if(!_0x47456e)return null;let _0x4ef293=this['_entries']['get'](_0x1d52d6)?.['get'](_0x47456e['historyRevision']);if(!_0x4ef293)throw Error('History\x20Database\x20Adapter\x20contains\x20an\x20invalid\x20history\x20revision');return{'unitID':_0x1d52d6,'type':_0x47456e['type'],'latestRevision':_0x47456e['revision'],'currentHistoryRevision':_0x47456e['historyRevision'],'currentHistoryCreatedAt':_0x4ef293['committedAt'],'forceNextHistory':_0x47456e['forceNextHistory']};}async['getRevision'](_0xf38df2,_0x18046b){return this['_assertOpen'](),this['_entries']['get'](_0xf38df2)?.['get'](_0x18046b)??null;}async['appendRevision'](_0x1df27d,_0x14cb27){this['_assertOpen']();let _0x3337e2=this['_entries']['get'](_0x1df27d['unitID'])??new Map();if(_0x3337e2['has'](_0x1df27d['revision']))return{'status':'already-indexed'};let _0x834b6a=o(_0x3337e2)?.['revision']??0x0;return _0x834b6a!==_0x14cb27['expectedLatestRevision']||_0x1df27d['revision']!==_0x834b6a+0x1?{'status':'revision-conflict','actualLatestRevision':_0x834b6a}:(_0x3337e2['set'](_0x1df27d['revision'],structuredClone(_0x1df27d)),this['_entries']['set'](_0x1df27d['unitID'],_0x3337e2),{'status':'appended'});}async['listRecords'](_0x76c761,_0x504f04){return this['_assertOpen'](),r(n([...this['_entries']['get'](_0x76c761)?.['values']()??[]]),_0x504f04);}async['listCreators'](_0x207e28){this['_assertOpen']();let _0x358006=new Map();for(let _0x4ea54e of this['_entries']['get'](_0x207e28)?.['values']()??[]){let _0x4d73ed=_0x358006['get'](_0x4ea54e['userID'])??new Set();_0x4d73ed['add'](_0x4ea54e['origin']),_0x358006['set'](_0x4ea54e['userID'],_0x4d73ed);}return[..._0x358006]['map'](([_0x4439d5,_0xd36add])=>({'userID':_0x4439d5,'origins':[..._0xd36add]}));}async['dispose'](){this['_disposed']||(this['_disposed']=!0x0,this['_entries']['clear']());}['_assertOpen'](){if(this['_disposed'])throw Error('History\x20Database\x20Adapter\x20is\x20disposed');}};function o(_0x3242cf){if(!_0x3242cf?.['size'])return;let _0x123aae;for(let _0x16cc7f of _0x3242cf['values']())(!_0x123aae||_0x16cc7f['revision']>_0x123aae['revision'])&&(_0x123aae=_0x16cc7f);return _0x123aae;}var s=class{['_timeIntervalMs'];['_singleHistoryMutationIds'];constructor(_0x223c6b={}){if(this['_timeIntervalMs']=_0x223c6b['timeIntervalMs']??0xea60,!Number['isSafeInteger'](this['_timeIntervalMs'])||this['_timeIntervalMs']<0x0)throw TypeError('timeIntervalMs\x20must\x20be\x20a\x20non-negative\x20safe\x20integer');this['_singleHistoryMutationIds']=_0x223c6b['singleHistoryMutationIds']??e['SINGLE_HISTORY_MUTATIONS'];}['evaluate'](_0x41cb11){if(!_0x41cb11['state']||_0x41cb11['revision']===0x1)return{'startsNewHistory':!0x0,'forceNextHistory':!0x1};let _0x104515=!!_0x41cb11['changeset']?.['mutations']['some'](_0x5e01ba=>this['_singleHistoryMutationIds']['has'](_0x5e01ba['id']));return{'startsNewHistory':_0x41cb11['state']['forceNextHistory']||_0x104515||_0x41cb11['committedAt']-_0x41cb11['state']['currentHistoryCreatedAt']>=this['_timeIntervalMs'],'forceNextHistory':_0x104515};}},c=class{['_middlewares']=new Map();['use'](_0x217a3a,_0x44f039){let _0x3ff2a0=this['_middlewares']['get'](_0x217a3a)??[],_0x402316=_0x44f039;_0x3ff2a0['push'](_0x402316),this['_middlewares']['set'](_0x217a3a,_0x3ff2a0);let _0x909679=!0x1;return{'dispose':()=>{if(_0x909679)return;_0x909679=!0x0;let _0x57009a=_0x3ff2a0['indexOf'](_0x402316);_0x57009a>=0x0&&_0x3ff2a0['splice'](_0x57009a,0x1);}};}async['run'](_0x179534,_0x3cc0c1,_0x32589a){let _0xee9fab=[...this['_middlewares']['get'](_0x179534)??[]],_0x1421e8=async _0x193b00=>{let _0xc7623e=_0xee9fab[_0x193b00];if(!_0xc7623e){await _0x32589a();return;}let _0x28b6ca=!0x1,_0x274ed7,_0x4eebb6=()=>{if(_0x28b6ca)throw Error('Middleware\x20for\x20action\x20'+_0x179534+'\x20called\x20next()\x20more\x20than\x20once');return _0x28b6ca=!0x0,_0x274ed7=_0x1421e8(_0x193b00+0x1),_0x274ed7;};try{await _0xc7623e(_0x3cc0c1,_0x4eebb6);}catch(_0x1eb667){if(_0x274ed7)try{await _0x274ed7;}catch{}throw _0x1eb667;}if(!_0x28b6ca)throw Error('Middleware\x20for\x20action\x20'+_0x179534+'\x20completed\x20without\x20calling\x20next()');await _0x274ed7;};await _0x1421e8(0x0);}['clear'](){this['_middlewares']['clear']();}},l='univer.mutation.create-unit',u='univer.mutation.revert-version',d=class{['_collabService'];['_dbAdapter'];['_ownsDbAdapter'];['_policy'];['_userProvider'];['_logger'];['_maxIndexRetries'];['_middleware']=new c();['_attachments']=new Set();['_calls']=new Set();['_indexQueues']=new Map();['_state']='running';constructor(_0x5b0f2b){if(!_0x5b0f2b?.['collabService'])throw TypeError('UniverHistoryService\x20requires\x20a\x20collabService');if(this['_collabService']=_0x5b0f2b['collabService'],this['_dbAdapter']=_0x5b0f2b['dbAdapter']??new a(),this['_ownsDbAdapter']=_0x5b0f2b['dbAdapter']===void 0x0,this['_policy']=_0x5b0f2b['policy']??new s(),this['_userProvider']=_0x5b0f2b['userProvider'],this['_logger']=_0x5b0f2b['logger'],this['_maxIndexRetries']=_0x5b0f2b['maxIndexRetries']??0x3,!Number['isSafeInteger'](this['_maxIndexRetries'])||this['_maxIndexRetries']<0x0)throw TypeError('maxIndexRetries\x20must\x20be\x20a\x20non-negative\x20safe\x20integer');}['use'](_0x58c29e,_0x31372b){return this['_assertRunning'](),this['_middleware']['use'](_0x58c29e,_0x31372b);}['getHistoryList'](_0x49a44c,_0x5d4f52){return this['_call'](async()=>{let _0x4f0ce1=p(_0x5d4f52),_0x1b1420=f(_0x49a44c),_0x3ecc1b={..._0x4f0ce1,'request':_0x1b1420},_0x3b4a2a;return await this['_middleware']['run']('getHistoryList',_0x3ecc1b,async()=>{if(m(_0x49a44c['unitID']),!Number['isSafeInteger'](_0x49a44c['length'])||_0x49a44c['length']<0x1||_0x49a44c['length']>0x64)throw C('length\x20must\x20be\x20an\x20integer\x20from\x201\x20to\x20100');let _0x2e91d9=_(_0x49a44c['lastLabel']),_0x5abc14=await this['_databaseCall'](()=>this['_dbAdapter']['listRecords'](_0x49a44c['unitID'],{'length':_0x49a44c['length'],..._0x2e91d9===void 0x0?{}:{'beforeRevision':_0x2e91d9},..._0x49a44c['origin']===void 0x0?{}:{'origin':_0x49a44c['origin']},..._0x49a44c['userIDs']===void 0x0?{}:{'userIDs':_0x49a44c['userIDs']}})),_0x2bd06a=await this['_resolveUsers'](w(_0x5abc14['records']['flatMap'](_0x21a991=>_0x21a991['userIDs'])),_0x4f0ce1,_0x1b1420),_0x47d4dc={};for(let _0x803b52 of _0x5abc14['records'])_0x47d4dc[_0x803b52['historyId']]=await this['_historyData'](_0x803b52);_0x3b4a2a={'hasMore':_0x5abc14['hasMore'],'lastLabel':_0x5abc14['records']['at'](-0x1)?.['startRevision']['toString']()??'','entities':{'datas':_0x47d4dc,'users':_0x2bd06a},'historyIds':_0x5abc14['records']['map'](_0x38f006=>_0x38f006['historyId'])};}),_0x3b4a2a;});}['listHistoryCreators'](_0x48b041,_0x2fd695){return this['_call'](async()=>{let _0x1ef00c=p(_0x2fd695),_0x464081=f(_0x48b041),_0x66fa1d={..._0x1ef00c,'request':_0x464081},_0xbe48ae;return await this['_middleware']['run']('listHistoryCreators',_0x66fa1d,async()=>{m(_0x48b041['unitID']);let _0xa385c1=await this['_databaseCall'](()=>this['_dbAdapter']['listCreators'](_0x48b041['unitID'])),_0x36382d=await this['_resolveUsers'](_0xa385c1['map'](_0x10fe9f=>_0x10fe9f['userID']),_0x1ef00c,_0x464081);_0xbe48ae={'creators':_0xa385c1['map'](_0x45a111=>{let _0x59bc87=_0x36382d[_0x45a111['userID']]??x(_0x45a111['userID']);return{'userID':_0x45a111['userID'],'name':_0x59bc87['name'],'avatar':_0x59bc87['avatar'],'origins':_0x45a111['origins']};})};}),_0xbe48ae;});}['getHistoryChangesets'](_0x347113,_0x51635c){return this['_call'](async()=>{let _0x4a3587=p(_0x51635c),_0x484339=f(_0x347113),_0x551526={..._0x4a3587,'request':_0x484339},_0x3058da;return await this['_middleware']['run']('getHistoryChangesets',_0x551526,async()=>{if(m(_0x347113['unitID']),h('startRevision',_0x347113['startRevision']),h('endRevision',_0x347113['endRevision']),_0x347113['endRevision']<_0x347113['startRevision'])throw C('endRevision\x20must\x20not\x20precede\x20startRevision');let _0x2e76e7=await this['_databaseCall'](()=>this['_dbAdapter']['getIndexState'](_0x347113['unitID']));if(!_0x2e76e7)throw new t['CollabError']('UNIT_NOT_FOUND','History\x20for\x20Unit\x20'+_0x347113['unitID']+'\x20does\x20not\x20exist');if(_0x347113['endRevision']>_0x2e76e7['latestRevision'])throw C('endRevision\x20exceeds\x20the\x20latest\x20indexed\x20revision');let _0x3963b4=await this['_collabService']['getChangesets']({'unitID':_0x347113['unitID'],'type':_0x2e76e7['type'],'from':_0x347113['startRevision']-0x1,'to':_0x347113['endRevision']},_0x4a3587),_0xc6cd8a=new Set(_0x3963b4['changesets']['map'](_0x371c68=>_0x371c68['userID']));for(let _0x3fc6ad=_0x347113['startRevision'];_0x3fc6ad<=_0x347113['endRevision'];_0x3fc6ad+=0x1){let _0x24b2e9=await this['_databaseCall'](()=>this['_dbAdapter']['getRevision'](_0x347113['unitID'],_0x3fc6ad));_0x24b2e9&&_0xc6cd8a['add'](_0x24b2e9['userID']);}_0x3058da={'changesets':_0x3963b4['changesets'],'users':await this['_resolveUsers']([..._0xc6cd8a],_0x4a3587,_0x484339)};}),_0x3058da;});}['indexUnitCreated'](_0x32fe11,_0x5c0eff){return this['_call'](()=>this['_executeIndexUnitCreated'](_0x32fe11,p(_0x5c0eff)));}['indexChangeset'](_0x48f10a,_0x24d658){return this['_call'](()=>this['_executeIndexChangeset'](_0x48f10a,p(_0x24d658)));}['attach'](_0x1c9da2=this['_collabService']){this['_assertRunning']();let _0x547211=[_0x1c9da2['on']('unitCreated',_0x2019b1=>{this['_enqueue'](_0x2019b1['record']['unitID'],()=>this['_executeIndexUnitCreated']({'unitID':_0x2019b1['record']['unitID'],'type':_0x2019b1['record']['type'],'createdAt':_0x2019b1['createdAt']},{'userID':_0x2019b1['userID'],'customData':_0x2019b1['customData']}));}),_0x1c9da2['on']('changesetCommitted',_0x436384=>{this['_enqueue'](_0x436384['changeset']['unitID'],()=>this['_executeIndexChangeset']({'changeset':_0x436384['changeset'],'committedAt':_0x436384['committedAt']},{'userID':_0x436384['userID'],'customData':_0x436384['customData']}));})],_0x2049bc=!0x1,_0x2aae0e={'dispose':()=>{if(!_0x2049bc){_0x2049bc=!0x0;for(let _0xd3343f of _0x547211)_0xd3343f['dispose']();this['_attachments']['delete'](_0x2aae0e);}}};return this['_attachments']['add'](_0x2aae0e),_0x2aae0e;}async['dispose'](){if(this['_state']!=='disposed'){if(this['_state']==='disposing'){await Promise['allSettled']([...this['_calls'],...this['_indexQueues']['values']()]);return;}this['_state']='disposing';for(let _0x3dd0e9 of[...this['_attachments']])_0x3dd0e9['dispose']();await Promise['allSettled']([...this['_calls'],...this['_indexQueues']['values']()]),this['_middleware']['clear'](),this['_indexQueues']['clear'](),this['_ownsDbAdapter']&&await this['_dbAdapter']['dispose']?.(),this['_state']='disposed';}}async['_executeIndexUnitCreated'](_0x5b1bfa,_0x1e755d){let _0x3a3c92=f(_0x5b1bfa),_0x196d54={..._0x1e755d,'request':_0x3a3c92},_0x5103d5;return await this['_middleware']['run']('indexUnitCreated',_0x196d54,async()=>{g(_0x5b1bfa['unitID'],_0x5b1bfa['type'],0x1,_0x5b1bfa['createdAt']);let _0x34a9b4={'unitID':_0x5b1bfa['unitID'],'type':_0x5b1bfa['type'],'revision':0x1,'userID':_0x1e755d['userID'],'commands':[l],'committedAt':_0x5b1bfa['createdAt'],'origin':0x1,'historyRevision':0x1,'forceNextHistory':!0x1};_0x5103d5=await this['_appendWithRetry'](_0x34a9b4,()=>_0x34a9b4);}),_0x5103d5;}async['_executeIndexChangeset'](_0x3bc11b,_0xb3fa30){let _0x5ee33b=f(_0x3bc11b),_0x4fc64c={..._0xb3fa30,'request':_0x5ee33b},_0x1ad3c8;return await this['_middleware']['run']('indexChangeset',_0x4fc64c,async()=>{let {changeset:_0x26b11f}=_0x3bc11b;if(g(_0x26b11f['unitID'],_0x26b11f['type'],_0x26b11f['revision'],_0x3bc11b['committedAt']),_0x26b11f['revision']<0x2)throw C('Confirmed\x20changeset\x20revision\x20must\x20be\x20at\x20least\x202');if(!_0x26b11f['userID'])throw C('changeset.userID\x20is\x20required');_0x1ad3c8=await this['_appendWithRetry']({'unitID':_0x26b11f['unitID'],'type':_0x26b11f['type'],'revision':_0x26b11f['revision'],'userID':_0x26b11f['userID'],'commands':w(_0x26b11f['mutations']['map'](_0x28c8b6=>_0x28c8b6['id'])),'committedAt':_0x3bc11b['committedAt'],..._0x26b11f['additionalFields']===void 0x0?{}:{'additionalFields':_0x26b11f['additionalFields']},'origin':v(_0x26b11f['additionalFields']),'historyRevision':_0x26b11f['revision'],'forceNextHistory':!0x1,...y(_0x26b11f)},_0x4f884e=>{if(!_0x4f884e)throw S(_0x26b11f['unitID'],_0x26b11f['revision'],0x0);if(_0x4f884e['type']!==_0x26b11f['type'])throw C('Changeset\x20type\x20does\x20not\x20match\x20indexed\x20Unit\x20type');if(_0x26b11f['revision']!==_0x4f884e['latestRevision']+0x1)throw S(_0x26b11f['unitID'],_0x26b11f['revision'],_0x4f884e['latestRevision']);let _0x42ddc5=this['_policy']['evaluate']({'state':_0x4f884e,'unitID':_0x26b11f['unitID'],'type':_0x26b11f['type'],'revision':_0x26b11f['revision'],'committedAt':_0x3bc11b['committedAt'],'changeset':_0x26b11f});return{'unitID':_0x26b11f['unitID'],'type':_0x26b11f['type'],'revision':_0x26b11f['revision'],'userID':_0x26b11f['userID'],'commands':w(_0x26b11f['mutations']['map'](_0x4fae51=>_0x4fae51['id'])),'committedAt':_0x3bc11b['committedAt'],..._0x26b11f['additionalFields']===void 0x0?{}:{'additionalFields':_0x26b11f['additionalFields']},'origin':v(_0x26b11f['additionalFields']),'historyRevision':_0x42ddc5['startsNewHistory']?_0x26b11f['revision']:_0x4f884e['currentHistoryRevision'],'forceNextHistory':_0x42ddc5['forceNextHistory'],...y(_0x26b11f)};});}),_0x1ad3c8;}async['_appendWithRetry'](_0x29935c,_0x1f7f12){for(let _0x587c99=0x0;_0x587c99<=this['_maxIndexRetries'];_0x587c99+=0x1){let _0x4640df=await this['_databaseCall'](()=>this['_dbAdapter']['getIndexState'](_0x29935c['unitID']));if(await this['_databaseCall'](()=>this['_dbAdapter']['getRevision'](_0x29935c['unitID'],_0x29935c['revision'])))return{'status':'already-indexed','revision':_0x29935c['revision']};let _0x2c943a=_0x1f7f12(_0x4640df),_0x34c702=await this['_databaseCall'](()=>this['_dbAdapter']['appendRevision'](_0x2c943a,{'expectedLatestRevision':_0x4640df?.['latestRevision']??0x0}));if(_0x34c702['status']==='appended')return{'status':'indexed','revision':_0x2c943a['revision']};if(_0x34c702['status']==='already-indexed')return{'status':'already-indexed','revision':_0x2c943a['revision']};}throw new t['CollabError']('ADAPTER_FAILURE','History\x20Database\x20Adapter\x20CAS\x20retries\x20were\x20exhausted',{'retryable':!0x0});}async['_historyData'](_0x30a582){let _0x3914e1='';if(_0x30a582['restoredRevision']!==void 0x0){let _0x22b2af=await this['_databaseCall'](()=>this['_dbAdapter']['getRevision'](_0x30a582['unitID'],_0x30a582['restoredRevision']));_0x3914e1=_0x22b2af?String(_0x22b2af['committedAt']):'';}return{'userID':_0x30a582['userID'],'unitID':_0x30a582['unitID'],'command':_0x30a582['commands'],'createTime':String(_0x30a582['createdAt']),'recoverTime':_0x3914e1,'startRevision':_0x30a582['startRevision'],'endRevision':_0x30a582['endRevision'],...b(_0x30a582),'origin':_0x30a582['origin'],'startRevCreateTime':_0x30a582['startRevisionCreatedAt'],'endRevCreateTime':_0x30a582['endRevisionCreatedAt'],'userIDs':_0x30a582['userIDs']};}async['_resolveUsers'](_0x161a27,_0xd97f73,_0x3869dd){let _0x1d61e4=w(_0x161a27['filter'](Boolean)),_0x445f75=[];if(this['_userProvider']&&_0x1d61e4['length'])try{_0x445f75=await this['_userProvider']['getUsers'](_0x1d61e4,{..._0xd97f73,'request':_0x3869dd});}catch(_0x11781b){this['_logError']('History\x20user\x20lookup\x20failed',_0x11781b);}let _0x595720={};for(let _0x192d6e of _0x445f75)_0x192d6e?.['userID']&&_0x1d61e4['includes'](_0x192d6e['userID'])&&(_0x595720[_0x192d6e['userID']]=_0x192d6e);for(let _0x3ba859 of _0x1d61e4)_0x595720[_0x3ba859]??=x(_0x3ba859);return _0x595720;}['_enqueue'](_0x30a3e2,_0xa4b87b){if(this['_state']!=='running')return;let _0xe8fa6=(this['_indexQueues']['get'](_0x30a3e2)??Promise['resolve']())['catch'](()=>void 0x0)['then'](_0xa4b87b)['then'](()=>void 0x0)['catch'](_0x1a172b=>{this['_logError']('History\x20background\x20indexing\x20failed',_0x1a172b);})['finally'](()=>{this['_indexQueues']['get'](_0x30a3e2)===_0xe8fa6&&this['_indexQueues']['delete'](_0x30a3e2);});this['_indexQueues']['set'](_0x30a3e2,_0xe8fa6);}['_call'](_0x4cd511){this['_assertRunning']();let _0x23e31d=_0x4cd511();return this['_calls']['add'](_0x23e31d),_0x23e31d['then'](()=>this['_calls']['delete'](_0x23e31d),()=>this['_calls']['delete'](_0x23e31d)),_0x23e31d;}async['_databaseCall'](_0x3441f1){try{return await _0x3441f1();}catch(_0x39525f){throw _0x39525f instanceof t['CollabError']?_0x39525f:new t['CollabError']('ADAPTER_FAILURE','History\x20Database\x20Adapter\x20failed',{'retryable':!0x0,'cause':_0x39525f});}}['_assertRunning'](){if(this['_state']!=='running')throw new t['CollabError']('INTERNAL_ERROR','History\x20Service\x20is\x20'+this['_state'],{'retryable':!0x0});}['_logError'](_0x4917f0,_0x19767b){try{this['_logger']?.['error'](_0x4917f0,{'error':_0x19767b instanceof Error?_0x19767b['message']:String(_0x19767b)});}catch{}}};function f(_0x494e64){return{..._0x494e64};}function p(_0x577a44){if(!_0x577a44||typeof _0x577a44!='object')throw C('context\x20must\x20be\x20an\x20object');if(typeof _0x577a44['userID']!='string'||_0x577a44['userID']['length']===0x0)throw C('userID\x20must\x20be\x20a\x20non-empty\x20string');if(_0x577a44['customData']!==void 0x0&&(_0x577a44['customData']===null||typeof _0x577a44['customData']!='object'||Array['isArray'](_0x577a44['customData'])))throw C('customData\x20must\x20be\x20an\x20object');return{'userID':_0x577a44['userID'],'customData':_0x577a44['customData']??Object['create'](null)};}function m(_0x510374){if(!_0x510374)throw C('unitID\x20is\x20required');}function h(_0x40e477,_0x4f12e2){if(!Number['isSafeInteger'](_0x4f12e2)||_0x4f12e2<0x1)throw C(_0x40e477+'\x20must\x20be\x20a\x20positive\x20safe\x20integer');}function g(_0x33738f,_0x5a1f74,_0x456368,_0x16d090){if(m(_0x33738f),h('revision',_0x456368),!Number['isSafeInteger'](_0x16d090)||_0x16d090<0x0)throw C('History\x20timestamp\x20must\x20be\x20a\x20non-negative\x20safe\x20integer');}function _(_0xca489c){if(!_0xca489c)return;let _0x1c9400=Number(_0xca489c);return h('lastLabel',_0x1c9400),_0x1c9400;}function v(_0x4696b3){if(!_0x4696b3)return 0x1;try{let _0x2aba29=JSON['parse'](_0x4696b3);return _0x2aba29['origin']===0x2?0x2:(_0x2aba29['origin'],0x1);}catch{return 0x1;}}function y(_0x2f9957){let _0x544e05=_0x2f9957['mutations']['find'](_0x3a5a48=>_0x3a5a48['id']===u);if(!_0x544e05)return{};try{let _0x1f6f59=JSON['parse'](_0x544e05['data']);return Number['isSafeInteger'](_0x1f6f59['revision'])&&_0x1f6f59['revision']>=0x1?{'restoredRevision':_0x1f6f59['revision']}:{};}catch{return{};}}function b(_0x1bbb51){return _0x1bbb51['additionalFields']===void 0x0?_0x1bbb51['restoredRevision']===void 0x0?{}:{'additionalFields':JSON['stringify']({'restoredRevision':_0x1bbb51['restoredRevision']})}:{'additionalFields':_0x1bbb51['additionalFields']};}function x(_0x11fe19){return{'userID':_0x11fe19,'name':_0x11fe19,'avatar':'','anonymous':!0x0,'canBindAnonymous':!0x1,'phone':'','email':'','createTimestamp':0x0};}function S(_0x1a39a1,_0x4149f3,_0x3194d1){return new t['CollabError']('ADAPTER_FAILURE','History\x20for\x20Unit\x20'+_0x1a39a1+'\x20cannot\x20index\x20revision\x20'+_0x4149f3+'\x20after\x20'+_0x3194d1,{'retryable':!0x0});}function C(_0x2ff5b0){return new t['CollabError']('INVALID_REQUEST',_0x2ff5b0);}function w(_0x18f815){return[...new Set(_0x18f815)];}exports['DefaultHistoryPolicy']=s,exports['MemoryHistoryDatabaseAdapter']=a,exports['UniverHistoryService']=d,exports['buildHistoryRecords']=n,exports['selectHistoryRecords']=r;
@@ -0,0 +1,287 @@
1
+ import { IChangeset, IUser, UniverType } from "@univerjs/protocol";
2
+ import { CollabContext, CustomData, Disposable, ILogger, IUniverCollabService } from "@univerjs-pro/collaboration-service";
3
+
4
+ //#region src/types.d.ts
5
+ type HistoryOrigin = 0 | 1 | 2;
6
+ interface GetHistoryListInput {
7
+ readonly unitID: string;
8
+ readonly length: number;
9
+ readonly lastLabel?: string;
10
+ readonly origin?: HistoryOrigin;
11
+ readonly userIDs?: readonly string[];
12
+ }
13
+ interface ListHistoryCreatorsInput {
14
+ readonly unitID: string;
15
+ }
16
+ interface GetHistoryChangesetsInput {
17
+ readonly unitID: string;
18
+ readonly startRevision: number;
19
+ readonly endRevision: number;
20
+ }
21
+ interface IndexUnitCreatedInput {
22
+ readonly unitID: string;
23
+ readonly type: UniverType;
24
+ readonly createdAt: number;
25
+ }
26
+ interface IndexChangesetInput {
27
+ readonly changeset: IChangeset;
28
+ readonly committedAt: number;
29
+ }
30
+ interface HistoryData {
31
+ readonly userID: string;
32
+ readonly unitID: string;
33
+ readonly command: readonly string[];
34
+ readonly createTime: string;
35
+ readonly recoverTime: string;
36
+ readonly startRevision: number;
37
+ readonly endRevision: number;
38
+ readonly additionalFields?: string;
39
+ readonly origin?: HistoryOrigin;
40
+ readonly startRevCreateTime: number;
41
+ readonly endRevCreateTime: number;
42
+ readonly userIDs: readonly string[];
43
+ }
44
+ interface GetHistoryListResult {
45
+ readonly hasMore: boolean;
46
+ readonly lastLabel: string;
47
+ readonly entities: {
48
+ readonly datas: Readonly<Record<string, HistoryData>>;
49
+ readonly users: Readonly<Record<string, IUser>>;
50
+ };
51
+ readonly historyIds: readonly string[];
52
+ }
53
+ interface HistoryCreator {
54
+ readonly userID: string;
55
+ readonly name: string;
56
+ readonly avatar: string;
57
+ readonly origins: readonly HistoryOrigin[];
58
+ }
59
+ interface ListHistoryCreatorsResult {
60
+ readonly creators: readonly HistoryCreator[];
61
+ }
62
+ interface GetHistoryChangesetsResult {
63
+ readonly changesets: readonly IChangeset[];
64
+ readonly users: Readonly<Record<string, IUser>>;
65
+ }
66
+ type IndexHistoryResult = {
67
+ readonly status: "indexed";
68
+ readonly revision: number;
69
+ } | {
70
+ readonly status: "already-indexed";
71
+ readonly revision: number;
72
+ };
73
+ interface GetHistoryListRequest extends GetHistoryListInput {}
74
+ interface ListHistoryCreatorsRequest extends ListHistoryCreatorsInput {}
75
+ interface GetHistoryChangesetsRequest extends GetHistoryChangesetsInput {}
76
+ interface IndexUnitCreatedRequest extends IndexUnitCreatedInput {}
77
+ interface IndexChangesetRequest extends IndexChangesetInput {}
78
+ type HistoryRequest = GetHistoryListRequest | ListHistoryCreatorsRequest | GetHistoryChangesetsRequest | IndexUnitCreatedRequest | IndexChangesetRequest;
79
+ interface HistoryUserProviderContext {
80
+ readonly userID: string;
81
+ readonly customData: CustomData;
82
+ readonly request: HistoryRequest;
83
+ }
84
+ interface IHistoryUserProvider {
85
+ getUsers(userIDs: readonly string[], context: HistoryUserProviderContext): Promise<readonly IUser[]>;
86
+ }
87
+ //#endregion
88
+ //#region src/database-adapter.d.ts
89
+ interface HistoryRevision {
90
+ readonly unitID: string;
91
+ readonly type: UniverType;
92
+ readonly revision: number;
93
+ readonly userID: string;
94
+ readonly commands: readonly string[];
95
+ readonly committedAt: number;
96
+ readonly additionalFields?: string;
97
+ readonly origin: HistoryOrigin;
98
+ readonly historyRevision: number;
99
+ readonly forceNextHistory: boolean;
100
+ readonly restoredRevision?: number;
101
+ }
102
+ interface HistoryIndexState {
103
+ readonly unitID: string;
104
+ readonly type: UniverType;
105
+ readonly latestRevision: number;
106
+ readonly currentHistoryRevision: number;
107
+ readonly currentHistoryCreatedAt: number;
108
+ readonly forceNextHistory: boolean;
109
+ }
110
+ interface HistoryRecord {
111
+ readonly historyId: string;
112
+ readonly unitID: string;
113
+ readonly type: UniverType;
114
+ readonly startRevision: number;
115
+ readonly endRevision: number;
116
+ readonly userID: string;
117
+ readonly userIDs: readonly string[];
118
+ readonly commands: readonly string[];
119
+ readonly createdAt: number;
120
+ readonly startRevisionCreatedAt: number;
121
+ readonly endRevisionCreatedAt: number;
122
+ readonly additionalFields?: string;
123
+ readonly origin: HistoryOrigin;
124
+ readonly restoredRevision?: number;
125
+ }
126
+ interface ListHistoryRecordsOptions {
127
+ readonly length: number;
128
+ readonly beforeRevision?: number;
129
+ readonly origin?: HistoryOrigin;
130
+ readonly userIDs?: readonly string[];
131
+ }
132
+ interface ListHistoryRecordsResult {
133
+ readonly records: readonly HistoryRecord[];
134
+ readonly hasMore: boolean;
135
+ }
136
+ interface HistoryCreatorIndex {
137
+ readonly userID: string;
138
+ readonly origins: readonly HistoryOrigin[];
139
+ }
140
+ type AppendHistoryRevisionResult = {
141
+ readonly status: "appended";
142
+ } | {
143
+ readonly status: "already-indexed";
144
+ } | {
145
+ readonly status: "revision-conflict";
146
+ readonly actualLatestRevision: number;
147
+ };
148
+ interface IHistoryDatabaseAdapter {
149
+ getIndexState(unitID: string): Promise<HistoryIndexState | null>;
150
+ getRevision(unitID: string, revision: number): Promise<HistoryRevision | null>;
151
+ appendRevision(entry: HistoryRevision, options: {
152
+ readonly expectedLatestRevision: number;
153
+ }): Promise<AppendHistoryRevisionResult>;
154
+ listRecords(unitID: string, options: ListHistoryRecordsOptions): Promise<ListHistoryRecordsResult>;
155
+ listCreators(unitID: string): Promise<readonly HistoryCreatorIndex[]>;
156
+ dispose?(): Promise<void>;
157
+ }
158
+ declare function buildHistoryRecords(entries: readonly HistoryRevision[]): readonly HistoryRecord[];
159
+ declare function selectHistoryRecords(records: readonly HistoryRecord[], options: ListHistoryRecordsOptions): ListHistoryRecordsResult;
160
+ //#endregion
161
+ //#region src/memory-history-database-adapter.d.ts
162
+ declare class MemoryHistoryDatabaseAdapter implements IHistoryDatabaseAdapter {
163
+ private readonly _entries;
164
+ private _disposed;
165
+ getIndexState(unitID: string): Promise<HistoryIndexState | null>;
166
+ getRevision(unitID: string, revision: number): Promise<HistoryRevision | null>;
167
+ appendRevision(entry: HistoryRevision, options: {
168
+ readonly expectedLatestRevision: number;
169
+ }): Promise<AppendHistoryRevisionResult>;
170
+ listRecords(unitID: string, options: ListHistoryRecordsOptions): Promise<ListHistoryRecordsResult>;
171
+ listCreators(unitID: string): Promise<readonly HistoryCreatorIndex[]>;
172
+ dispose(): Promise<void>;
173
+ private _assertOpen;
174
+ }
175
+ //#endregion
176
+ //#region src/policy.d.ts
177
+ interface HistoryPolicyInput {
178
+ readonly state: HistoryIndexState | null;
179
+ readonly unitID: string;
180
+ readonly type: UniverType;
181
+ readonly revision: number;
182
+ readonly committedAt: number;
183
+ readonly changeset?: IChangeset;
184
+ }
185
+ interface HistoryPolicyDecision {
186
+ readonly startsNewHistory: boolean;
187
+ readonly forceNextHistory: boolean;
188
+ }
189
+ interface IHistoryPolicy {
190
+ evaluate(input: HistoryPolicyInput): HistoryPolicyDecision;
191
+ }
192
+ interface DefaultHistoryPolicyOptions {
193
+ readonly timeIntervalMs?: number;
194
+ readonly singleHistoryMutationIds?: ReadonlySet<string>;
195
+ }
196
+ declare class DefaultHistoryPolicy implements IHistoryPolicy {
197
+ private readonly _timeIntervalMs;
198
+ private readonly _singleHistoryMutationIds;
199
+ constructor(options?: DefaultHistoryPolicyOptions);
200
+ evaluate(input: HistoryPolicyInput): HistoryPolicyDecision;
201
+ }
202
+ //#endregion
203
+ //#region src/middleware.d.ts
204
+ type HistoryMiddlewareAction = "getHistoryList" | "listHistoryCreators" | "getHistoryChangesets" | "indexUnitCreated" | "indexChangeset";
205
+ type HistoryMiddlewareNext = () => Promise<void>;
206
+ type HistoryMiddleware<TContext> = (context: TContext, next: HistoryMiddlewareNext) => void | Promise<void>;
207
+ interface BaseHistoryMiddlewareContext {
208
+ readonly userID: string;
209
+ readonly customData: CustomData;
210
+ }
211
+ interface GetHistoryListMiddlewareContext extends BaseHistoryMiddlewareContext {
212
+ readonly request: GetHistoryListRequest;
213
+ }
214
+ interface ListHistoryCreatorsMiddlewareContext extends BaseHistoryMiddlewareContext {
215
+ readonly request: ListHistoryCreatorsRequest;
216
+ }
217
+ interface GetHistoryChangesetsMiddlewareContext extends BaseHistoryMiddlewareContext {
218
+ readonly request: GetHistoryChangesetsRequest;
219
+ }
220
+ interface IndexUnitCreatedMiddlewareContext extends BaseHistoryMiddlewareContext {
221
+ readonly request: IndexUnitCreatedRequest;
222
+ }
223
+ interface IndexChangesetMiddlewareContext extends BaseHistoryMiddlewareContext {
224
+ readonly request: IndexChangesetRequest;
225
+ }
226
+ interface HistoryMiddlewareMap {
227
+ readonly getHistoryList: HistoryMiddleware<GetHistoryListMiddlewareContext>;
228
+ readonly listHistoryCreators: HistoryMiddleware<ListHistoryCreatorsMiddlewareContext>;
229
+ readonly getHistoryChangesets: HistoryMiddleware<GetHistoryChangesetsMiddlewareContext>;
230
+ readonly indexUnitCreated: HistoryMiddleware<IndexUnitCreatedMiddlewareContext>;
231
+ readonly indexChangeset: HistoryMiddleware<IndexChangesetMiddlewareContext>;
232
+ }
233
+ //#endregion
234
+ //#region src/service.d.ts
235
+ interface UniverHistoryServiceOptions {
236
+ readonly collabService: IUniverCollabService;
237
+ readonly dbAdapter?: IHistoryDatabaseAdapter;
238
+ readonly policy?: IHistoryPolicy;
239
+ readonly userProvider?: IHistoryUserProvider;
240
+ readonly logger?: ILogger;
241
+ readonly maxIndexRetries?: number;
242
+ }
243
+ interface IUniverHistoryService {
244
+ use<K extends HistoryMiddlewareAction>(action: K, middleware: HistoryMiddlewareMap[K]): Disposable;
245
+ getHistoryList(input: GetHistoryListInput, context: CollabContext): Promise<GetHistoryListResult>;
246
+ listHistoryCreators(input: ListHistoryCreatorsInput, context: CollabContext): Promise<ListHistoryCreatorsResult>;
247
+ getHistoryChangesets(input: GetHistoryChangesetsInput, context: CollabContext): Promise<GetHistoryChangesetsResult>;
248
+ indexUnitCreated(input: IndexUnitCreatedInput, context: CollabContext): Promise<IndexHistoryResult>;
249
+ indexChangeset(input: IndexChangesetInput, context: CollabContext): Promise<IndexHistoryResult>;
250
+ attach(collabService?: IUniverCollabService): Disposable;
251
+ dispose(): Promise<void>;
252
+ }
253
+ declare class UniverHistoryService implements IUniverHistoryService {
254
+ private readonly _collabService;
255
+ private readonly _dbAdapter;
256
+ private readonly _ownsDbAdapter;
257
+ private readonly _policy;
258
+ private readonly _userProvider;
259
+ private readonly _logger;
260
+ private readonly _maxIndexRetries;
261
+ private readonly _middleware;
262
+ private readonly _attachments;
263
+ private readonly _calls;
264
+ private readonly _indexQueues;
265
+ private _state;
266
+ constructor(options: UniverHistoryServiceOptions);
267
+ use<K extends HistoryMiddlewareAction>(action: K, middleware: HistoryMiddlewareMap[K]): Disposable;
268
+ getHistoryList(input: GetHistoryListInput, context: CollabContext): Promise<GetHistoryListResult>;
269
+ listHistoryCreators(input: ListHistoryCreatorsInput, context: CollabContext): Promise<ListHistoryCreatorsResult>;
270
+ getHistoryChangesets(input: GetHistoryChangesetsInput, context: CollabContext): Promise<GetHistoryChangesetsResult>;
271
+ indexUnitCreated(input: IndexUnitCreatedInput, context: CollabContext): Promise<IndexHistoryResult>;
272
+ indexChangeset(input: IndexChangesetInput, context: CollabContext): Promise<IndexHistoryResult>;
273
+ attach(collabService?: IUniverCollabService): Disposable;
274
+ dispose(): Promise<void>;
275
+ private _executeIndexUnitCreated;
276
+ private _executeIndexChangeset;
277
+ private _appendWithRetry;
278
+ private _historyData;
279
+ private _resolveUsers;
280
+ private _enqueue;
281
+ private _call;
282
+ private _databaseCall;
283
+ private _assertRunning;
284
+ private _logError;
285
+ }
286
+ //#endregion
287
+ export { type AppendHistoryRevisionResult, type BaseHistoryMiddlewareContext, DefaultHistoryPolicy, type DefaultHistoryPolicyOptions, type GetHistoryChangesetsInput, type GetHistoryChangesetsMiddlewareContext, type GetHistoryChangesetsRequest, type GetHistoryChangesetsResult, type GetHistoryListInput, type GetHistoryListMiddlewareContext, type GetHistoryListRequest, type GetHistoryListResult, type HistoryCreator, type HistoryCreatorIndex, type HistoryData, type HistoryIndexState, type HistoryMiddleware, type HistoryMiddlewareAction, type HistoryMiddlewareMap, type HistoryMiddlewareNext, type HistoryOrigin, type HistoryPolicyDecision, type HistoryPolicyInput, type HistoryRecord, type HistoryRequest, type HistoryRevision, type HistoryUserProviderContext, type IHistoryDatabaseAdapter, type IHistoryPolicy, type IHistoryUserProvider, type IUniverHistoryService, type IndexChangesetInput, type IndexChangesetMiddlewareContext, type IndexChangesetRequest, type IndexHistoryResult, type IndexUnitCreatedInput, type IndexUnitCreatedMiddlewareContext, type IndexUnitCreatedRequest, type ListHistoryCreatorsInput, type ListHistoryCreatorsMiddlewareContext, type ListHistoryCreatorsRequest, type ListHistoryCreatorsResult, type ListHistoryRecordsOptions, type ListHistoryRecordsResult, MemoryHistoryDatabaseAdapter, UniverHistoryService, type UniverHistoryServiceOptions, buildHistoryRecords, selectHistoryRecords };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ const _0x4de5bd=_0x53a1;(function(_0x2acce2,_0x3bac2c){const _0x2df8da=_0x53a1,_0x18c705=_0x2acce2();while(!![]){try{const _0x4b9091=parseInt(_0x2df8da(0x150))/0x1*(parseInt(_0x2df8da(0x153))/0x2)+-parseInt(_0x2df8da(0x15e))/0x3+parseInt(_0x2df8da(0x157))/0x4*(-parseInt(_0x2df8da(0x15d))/0x5)+-parseInt(_0x2df8da(0x152))/0x6*(parseInt(_0x2df8da(0x155))/0x7)+-parseInt(_0x2df8da(0x15b))/0x8*(parseInt(_0x2df8da(0x151))/0x9)+parseInt(_0x2df8da(0x15a))/0xa*(-parseInt(_0x2df8da(0x15c))/0xb)+parseInt(_0x2df8da(0x154))/0xc;if(_0x4b9091===_0x3bac2c)break;else _0x18c705['push'](_0x18c705['shift']());}catch(_0x489c6e){_0x18c705['push'](_0x18c705['shift']());}}}(_0x1261,0x5e1e3));function _0x53a1(_0x343040,_0x2dd396){_0x343040=_0x343040-0x14f;const _0x126148=_0x1261();let _0x53a10a=_0x126148[_0x343040];return _0x53a10a;}import _0x4585e4 from'./index.cjs';const facadeExport0=_0x4585e4[_0x4de5bd(0x14f)],facadeExport1=_0x4585e4[_0x4de5bd(0x159)],facadeExport2=_0x4585e4[_0x4de5bd(0x156)],facadeExport3=_0x4585e4['buildHistoryRecords'],facadeExport4=_0x4585e4[_0x4de5bd(0x158)];export{facadeExport0 as DefaultHistoryPolicy,facadeExport1 as MemoryHistoryDatabaseAdapter,facadeExport2 as UniverHistoryService,facadeExport3 as buildHistoryRecords,facadeExport4 as selectHistoryRecords};function _0x1261(){const _0x55e0c6=['3523528MyZpKI','1144NkfhZm','3005enxXWZ','1059990ZCIzVE','DefaultHistoryPolicy','387CZZPRX','9LVXASg','6wQiAaq','2082oiFKcT','21627072SeFpaI','4583838uyVFvC','UniverHistoryService','1964MUiQro','selectHistoryRecords','MemoryHistoryDatabaseAdapter','7300uLNgTP'];_0x1261=function(){return _0x55e0c6;};return _0x1261();}
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@univerjs-pro/collaboration-history-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/collaboration": "1.0.0-beta.2",
20
+ "@univerjs-pro/collaboration-service": "1.0.0-beta.2",
21
+ "@univerjs/protocol": "1.0.0-beta.2"
22
+ }
23
+ }