@univerjs-pro/collaboration-worktree-endpoint 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,102 @@
1
+ # @univerjs-pro/collaboration-worktree-endpoint
2
+
3
+ English | [简体中文](./README.zh-CN.md)
4
+
5
+ Provides Worktree management APIs and accepts Univer collaboration requests scoped to a specific Worktree. It uses `UniverCollabWorktreeService` APIs for Worktree management and collaboration-data operations.
6
+
7
+ ## Installation and registration
8
+
9
+ ```bash
10
+ pnpm add \
11
+ @univerjs-pro/collaboration-worktree-service \
12
+ @univerjs-pro/collaboration-worktree-endpoint \
13
+ @univerjs-pro/collaboration-endpoint \
14
+ @univerjs-pro/collaboration-transport-node
15
+ ```
16
+
17
+ Worktree Endpoint and trunk Endpoint must share the same `ticketStore`:
18
+
19
+ ```ts
20
+ const ticketStore = new MemorySessionTicketStore();
21
+ const trunkEndpoint = new UniverCollabEndpoint(collabService, { ticketStore });
22
+ const worktreeEndpoint = new UniverCollabWorktreeEndpoint(
23
+ worktreeService,
24
+ { ticketStore }
25
+ );
26
+
27
+ transport.use(authenticationMiddleware);
28
+ transport.register(trunkEndpoint);
29
+ transport.register(worktreeEndpoint);
30
+ ```
31
+
32
+ Authentication middleware must first set `ctx.userID` for HTTP requests. Apart from sharing the same `ticketStore` instance, no extra association between Endpoints is needed. Every WebSocket connection still uses its own one-time ticket.
33
+
34
+ ## What the frontend receives
35
+
36
+ - Worktree HTTP APIs for create, read, ready, reopen, discard, merge, and preview.
37
+ - Separate snapshot, changeset, ACK, broadcast, and Presence channels for each Worktree.
38
+ - A `/events` WebSocket for Worktree state changes, allowing product UI to refresh ready/merged state.
39
+
40
+ Applications do not place `worktreeID` into changesets or room IDs themselves. The browser configures the target Worktree, Endpoint reads `worktreeID` from the URL, and data and realtime rooms remain isolated between Worktrees.
41
+
42
+ ## Worktree protocol paths
43
+
44
+ The protocol is rooted at `/universer-api/worktrees/:worktreeID`. One collaboration WebSocket belongs to one Worktree. Even with the same `unitID`, edits and online members in different Worktrees are isolated. Worktree state changes use a separate `/events` WebSocket instead of injecting unknown events into the collaboration WebSocket.
45
+
46
+ Management APIs:
47
+
48
+ | Method | Path | Purpose |
49
+ | --- | --- | --- |
50
+ | `POST` | `/universer-api/worktrees` | Create Worktree |
51
+ | `GET` | `/universer-api/worktrees/:worktreeID` | Read complete Worktree state |
52
+ | `POST` | `/universer-api/worktrees/:worktreeID/units` | Add an existing trunk Unit |
53
+ | `POST` | `/universer-api/worktrees/:worktreeID/units/from-snapshot` | Create draft Unit from protocol snapshot |
54
+ | `POST` | `/universer-api/worktrees/:worktreeID/units/from-data` | Create draft Unit from Univer Unit data |
55
+ | `GET` | `/universer-api/worktrees/:worktreeID/units/:unitID/merge-preview` | Evaluate one Unit merge |
56
+ | `POST` | `/universer-api/worktrees/:worktreeID/ready` | Freeze each Unit's current draft revision |
57
+ | `POST` | `/universer-api/worktrees/:worktreeID/reopen` | Return to draft |
58
+ | `POST` | `/universer-api/worktrees/:worktreeID/merge` | Merge Units into trunk one by one |
59
+ | `POST` | `/universer-api/worktrees/:worktreeID/discard` | Discard Worktree |
60
+
61
+ Realtime and collaboration channels:
62
+
63
+ | Channel | Path | Purpose |
64
+ | --- | --- | --- |
65
+ | HTTP | `/universer-api/worktrees/:worktreeID/snapshot/...` | Read this Worktree's snapshot, blocks, and missing changesets |
66
+ | HTTP | `/universer-api/worktrees/:worktreeID/comb/...` | Submit a changeset to this Worktree |
67
+ | WebSocket | `/universer-api/worktrees/:worktreeID/comb/connect` | Worktree Sessions, rooms, Presence, ACKs, broadcasts |
68
+ | WebSocket | `/universer-api/worktrees/:worktreeID/events` | Push complete `WorktreeData` state |
69
+
70
+ The URL is authoritative for `worktreeID`. `merge-preview` evaluates one Unit only in `ready`, uses `Cache-Control: no-store`, and does not perform a formal merge.
71
+
72
+ ## Middleware
73
+
74
+ Worktree Endpoint middleware controls only the current Worktree's Sessions and realtime rooms:
75
+
76
+ | Action | When it runs | Visible fields | Retry semantics | Typical uses |
77
+ | --- | --- | --- | --- | --- |
78
+ | `connect` | After consuming ticket and creating Worktree Session, before registering collaboration or `/events` connection | `worktreeID`, `session`, `connection`, `member` | Once per connection; reconnect runs again | Member display, connection policy |
79
+ | `joinUnit` | After `JOIN`, before Session joins current Worktree room | `worktreeID`, `session`, `unitID` | Once for Session's first JOIN; Endpoint does not retry | Worktree and Unit read ACL |
80
+ | `receivePresence` | After joined Session sends Presence, before room broadcast | `worktreeID`, `session`, `unitID`, `payload`, event-scoped `customData` | Once per Presence; Endpoint does not retry | Validation, rate limits, filtering |
81
+ | `sendPresence` | Before sending Presence to one current-Worktree room member | `worktreeID`, `session`, `unitID`, `payload`, event-scoped `customData`, `targetMemberID` | Once per target; send failure not retried | Per-recipient display-data filtering |
82
+
83
+ ```ts
84
+ worktreeEndpoint.use('joinUnit', async (ctx, next) => {
85
+ if (!await acl.canReadWorktreeUnit(
86
+ ctx.session.userID,
87
+ ctx.worktreeID,
88
+ ctx.unitID
89
+ )) {
90
+ throw new CollabError('PERMISSION_DENIED', 'Cannot join this Worktree Unit');
91
+ }
92
+ await next();
93
+ });
94
+ ```
95
+
96
+ `joinUnit` protects only realtime rooms. Worktree data reads, submissions, and merge must be protected by Worktree Service middleware. Service middleware receives `ctx.userID/customData` attached to the current HTTP request by Transport.
97
+
98
+ ## Deployment and disposal
99
+
100
+ Realtime rooms, state events, and broadcasts are currently guaranteed only within one Endpoint process.
101
+
102
+ Transport disposes registered Endpoints. Endpoint does not dispose Worktree Service, trunk Service, or the application-provided `ticketStore`.
@@ -0,0 +1,111 @@
1
+ # @univerjs-pro/collaboration-worktree-endpoint
2
+
3
+ [English](./README.md) | [简体中文](./README.zh-CN.md)
4
+
5
+ 提供 Worktree 管理 API,并接收限定到具体 Worktree 的 Univer 协同请求。它使用
6
+ `UniverCollabWorktreeService` API 处理 Worktree 管理和协同数据操作。
7
+
8
+ ## 安装与注册
9
+
10
+ ```bash
11
+ pnpm add \
12
+ @univerjs-pro/collaboration-worktree-service \
13
+ @univerjs-pro/collaboration-worktree-endpoint \
14
+ @univerjs-pro/collaboration-endpoint \
15
+ @univerjs-pro/collaboration-transport-node
16
+ ```
17
+
18
+ Worktree Endpoint 和 trunk Endpoint 需要共享同一个 `ticketStore`:
19
+
20
+ ```ts
21
+ const ticketStore = new MemorySessionTicketStore();
22
+ const trunkEndpoint = new UniverCollabEndpoint(collabService, { ticketStore });
23
+ const worktreeEndpoint = new UniverCollabWorktreeEndpoint(
24
+ worktreeService,
25
+ { ticketStore }
26
+ );
27
+
28
+ transport.use(authenticationMiddleware);
29
+ transport.register(trunkEndpoint);
30
+ transport.register(worktreeEndpoint);
31
+ ```
32
+
33
+ 认证 middleware 必须先为 HTTP 请求设置 `ctx.userID`。除共享同一个 `ticketStore` 实例外,
34
+ 无需额外关联两个 Endpoint;每条 WebSocket 连接仍使用独立的一次性 ticket。
35
+
36
+ ## 前端会获得什么
37
+
38
+ - 一组用于创建、读取、ready、reopen、discard、merge 和预览的 Worktree HTTP API。
39
+ - 每个 Worktree 独立的 snapshot、changeset、ACK、广播和 Presence 通道。
40
+ - Worktree 状态变化的 `/events` WebSocket,便于产品 UI 刷新 ready/merged 等状态。
41
+
42
+ 应用不需要自己把 `worktreeID` 塞进 changeset 或 room ID。浏览器只配置目标 Worktree,
43
+ Endpoint 从 URL 取得 `worktreeID` 并保持不同 Worktree 之间的数据和实时房间隔离。
44
+
45
+ ## Worktree 协议路径
46
+
47
+ 协议位于 `/universer-api/worktrees/:worktreeID`。一条协同 WebSocket 只属于一个
48
+ Worktree;即使 `unitID` 相同,不同 Worktree 的编辑和在线成员也彼此隔离。Worktree 状态
49
+ 变化通过独立 `/events` WebSocket 发送,不向协同 WebSocket 注入未知事件。
50
+
51
+ 管理 API:
52
+
53
+ | Method | Path | 用途 |
54
+ | --- | --- | --- |
55
+ | `POST` | `/universer-api/worktrees` | 创建 Worktree |
56
+ | `GET` | `/universer-api/worktrees/:worktreeID` | 读取完整 Worktree 状态 |
57
+ | `POST` | `/universer-api/worktrees/:worktreeID/units` | 加入已有 trunk Unit |
58
+ | `POST` | `/universer-api/worktrees/:worktreeID/units/from-snapshot` | 从 protocol snapshot 创建 draft Unit |
59
+ | `POST` | `/universer-api/worktrees/:worktreeID/units/from-data` | 从 Univer Unit data 创建 draft Unit |
60
+ | `GET` | `/universer-api/worktrees/:worktreeID/units/:unitID/merge-preview` | 评估单 Unit 合入 |
61
+ | `POST` | `/universer-api/worktrees/:worktreeID/ready` | 冻结各 Unit 当前的 draft revision |
62
+ | `POST` | `/universer-api/worktrees/:worktreeID/reopen` | 重新进入 draft |
63
+ | `POST` | `/universer-api/worktrees/:worktreeID/merge` | 逐 Unit 合入 trunk |
64
+ | `POST` | `/universer-api/worktrees/:worktreeID/discard` | 丢弃 Worktree |
65
+
66
+ 实时和协同通道:
67
+
68
+ | 通道 | Path | 用途 |
69
+ | --- | --- | --- |
70
+ | HTTP | `/universer-api/worktrees/:worktreeID/snapshot/...` | 读取该 Worktree 的 snapshot、blocks 和缺失 changesets |
71
+ | HTTP | `/universer-api/worktrees/:worktreeID/comb/...` | 向该 Worktree 提交 changeset |
72
+ | WebSocket | `/universer-api/worktrees/:worktreeID/comb/connect` | 该 Worktree 的 Session、房间、Presence、ACK 和广播 |
73
+ | WebSocket | `/universer-api/worktrees/:worktreeID/events` | 推送完整 `WorktreeData` 状态 |
74
+
75
+ URL 是 `worktreeID` 的权威来源。`merge-preview` 只在 `ready` 状态评估一个 Unit,使用
76
+ `Cache-Control: no-store`,不执行正式 merge。
77
+
78
+ ## Middleware
79
+
80
+ Worktree Endpoint middleware 只控制当前 Worktree 的 Session 和实时房间:
81
+
82
+ | Action | 触发时机 | 可见字段 | 重试语义 | 典型用途 |
83
+ | --- | --- | --- | --- | --- |
84
+ | `connect` | ticket 已消费并创建 Worktree Session,注册协同或 `/events` 连接前 | `worktreeID`、`session`、`connection`、`member` | 每次建连一次;重连再次执行 | 成员展示和连接策略 |
85
+ | `joinUnit` | 收到 `JOIN`,Session 加入当前 Worktree 房间前 | `worktreeID`、`session`、`unitID` | 当前 Session 首次 JOIN 时一次;Endpoint 不重试 | Worktree 与 Unit 读取 ACL |
86
+ | `receivePresence` | 已 JOIN 的 Session 发送 Presence、向房间广播前 | `worktreeID`、`session`、`unitID`、`payload`、事件级 `customData` | 每条 Presence 一次;Endpoint 不重试 | 校验、限流和过滤 |
87
+ | `sendPresence` | Presence 即将发送给当前 Worktree 的一个房间成员 | `worktreeID`、`session`、`unitID`、`payload`、事件级 `customData`、`targetMemberID` | 每个目标成员一次;发送失败不重试 | 按接收者过滤展示数据 |
88
+
89
+ ```ts
90
+ worktreeEndpoint.use('joinUnit', async (ctx, next) => {
91
+ if (!await acl.canReadWorktreeUnit(
92
+ ctx.session.userID,
93
+ ctx.worktreeID,
94
+ ctx.unitID
95
+ )) {
96
+ throw new CollabError('PERMISSION_DENIED', 'Cannot join this Worktree Unit');
97
+ }
98
+ await next();
99
+ });
100
+ ```
101
+
102
+ `joinUnit` 只保护实时房间。Worktree 数据读取、提交和 merge 必须由 Worktree Service
103
+ middleware 保护;Service middleware 获取当前 HTTP 请求由 Transport 挂载的
104
+ `ctx.userID/customData`。
105
+
106
+ ## 部署与资源释放
107
+
108
+ 实时房间、状态事件和广播当前只保证单 Endpoint 进程。
109
+
110
+ Transport 释放已注册 Endpoint;Endpoint 不释放 Worktree Service、trunk Service 或
111
+ 应用传入的 `ticketStore`。
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object['defineProperty'](exports,Symbol['toStringTag'],{'value':'Module'});let e=require('node:crypto'),t=require('@univerjs-pro/collaboration-endpoint'),n=require('@univerjs-pro/collaboration-service'),r=require('@univerjs-pro/collaboration-transport-node'),i=require('@univerjs-pro/collaboration-worktree-service'),a=require('@univerjs/protocol');var o=class{['_middlewares']=new Map();['use'](_0x4e4668,_0x275927){let _0x481b9f=this['_middlewares']['get'](_0x4e4668)??[],_0x4659d9=_0x275927;_0x481b9f['push'](_0x4659d9),this['_middlewares']['set'](_0x4e4668,_0x481b9f);let _0x4a432d=!0x1;return{'dispose':()=>{if(_0x4a432d)return;_0x4a432d=!0x0;let _0x212f25=_0x481b9f['indexOf'](_0x4659d9);_0x212f25>=0x0&&_0x481b9f['splice'](_0x212f25,0x1);}};}async['run'](_0x2f7d8a,_0xfc21b6,_0x2a9ce0){let _0x7baee7=[...this['_middlewares']['get'](_0x2f7d8a)??[]],_0x2462ca=async _0x3ca4da=>{let _0x2f3fb2=_0x7baee7[_0x3ca4da];if(!_0x2f3fb2){await _0x2a9ce0();return;}let _0xc550e8=!0x1,_0x36a818;if(await _0x2f3fb2(_0xfc21b6,()=>{if(_0xc550e8)throw Error('Middleware\x20for\x20action\x20'+String(_0x2f7d8a)+'\x20called\x20next()\x20twice');return _0xc550e8=!0x0,_0x36a818=_0x2462ca(_0x3ca4da+0x1),_0x36a818;}),!_0xc550e8)throw Error('Middleware\x20for\x20action\x20'+String(_0x2f7d8a)+'\x20did\x20not\x20call\x20next()');await _0x36a818;};await _0x2462ca(0x0);}['clear'](){this['_middlewares']['clear']();}},s=0x5*0xea60,c='/universer-api/worktrees',l='/universer-api/user/session-ticket',u=class{['_service'];['_options'];['_middleware']=new o();['_listeners']=new Map();['_scopedEndpoints']=new Map();['_eventBindings']=new Map();['_eventRooms']=new Map();['_eventQueues']=new Map();['_subscriptions'];['_ticketTtlMs'];['_disposed']=!0x1;constructor(_0x270c02,_0xc2afb4){if(this['_service']=_0x270c02,this['_options']=_0xc2afb4,!_0x270c02)throw TypeError('UniverCollabWorktreeEndpoint\x20requires\x20a\x20Worktree\x20Service');if(!_0xc2afb4?.['ticketStore'])throw TypeError('UniverCollabWorktreeEndpoint\x20requires\x20the\x20shared\x20ticketStore');if(this['_ticketTtlMs']=_0xc2afb4['sessionTicketTtlMs']??s,!Number['isSafeInteger'](this['_ticketTtlMs'])||this['_ticketTtlMs']<=0x0)throw TypeError('sessionTicketTtlMs\x20must\x20be\x20a\x20positive\x20safe\x20integer');this['_subscriptions']=[this['_service']['on']('worktreeCreated',_0xf79609=>this['_enqueueWorktreeChanged'](_0xf79609['worktree'])),this['_service']['on']('worktreeUnitAdded',_0x44513a=>this['_enqueueWorktreeChanged'](_0x44513a['worktree'])),this['_service']['on']('worktreeUnitCreated',_0x515959=>this['_enqueueWorktreeChanged'](_0x515959['worktree'])),this['_service']['on']('worktreeStatusChanged',_0x4ce12e=>this['_enqueueWorktreeChanged'](_0x4ce12e['worktree'])),this['_service']['on']('worktreeUnitMergeResultRecorded',_0x2793c3=>this['_enqueueWorktreeChanged'](_0x2793c3['worktree']))];}['use'](_0x423b6c,_0x9483bc){return this['_assertRunning'](),this['_middleware']['use'](_0x423b6c,_0x9483bc);}['on'](_0xa1147b,_0x55fc51){this['_assertRunning']();let _0x4459ad=this['_listeners']['get'](_0xa1147b)??new Set(),_0x2a79c5=_0x55fc51;_0x4459ad['add'](_0x2a79c5),this['_listeners']['set'](_0xa1147b,_0x4459ad);let _0x377147=!0x1;return{'dispose':()=>{_0x377147||(_0x377147=!0x0,_0x4459ad['delete'](_0x2a79c5));}};}async['handleHttp'](_0x185b28,_0x4ae53d){if(this['_disposed']){await _0x4ae53d();return;}await this['_handleHttp'](_0x185b28,_0x4ae53d);}async['handleUpgrade'](_0x12f94a,_0x140ba8){if(this['_disposed']){await _0x140ba8();return;}let _0x36d2d3,_0x6a4a3c;try{_0x36d2d3=new URL(_0x12f94a['incomingMessage']['url']??'/','http://localhost'),_0x6a4a3c=p(_0x36d2d3['pathname']);}catch{_0x12f94a['reject'](0x190,'Invalid\x20Worktree\x20WebSocket\x20URL');return;}if(!_0x6a4a3c){await _0x140ba8();return;}if(_0x6a4a3c['suffix']==='/events'){let _0xa7c96a=await this['_options']['ticketStore']['consume'](_0x36d2d3['searchParams']['get']('sessionTicket')??'');if(!_0xa7c96a){_0x12f94a['reject'](0x191,'Invalid\x20or\x20expired\x20session\x20ticket');return;}let _0x1c2737=_0x6a4a3c['worktreeID'];_0x12f94a['accept']({'open':({connection:_0x54f06f})=>this['_openEventConnection'](_0x54f06f,_0xa7c96a,_0x1c2737),'message':({connection:_0xa24ae6})=>_0xa24ae6['close'](0x3eb,'Worktree\x20event\x20connection\x20is\x20server-only'),'close':({connection:_0x54bc66})=>this['_removeEventBinding'](_0x54bc66['id'])});return;}if(_0x6a4a3c['suffix']==='/comb/connect'){await this['_scopedEndpoint'](_0x6a4a3c['worktreeID'],_0x6a4a3c['protocolBasePath'])['handleUpgrade'](_0x12f94a,_0x140ba8);return;}await _0x140ba8();}async['dispose'](){if(this['_disposed'])return;this['_disposed']=!0x0,this['_subscriptions']['forEach'](_0x4eb16b=>_0x4eb16b['dispose']()),await Promise['allSettled']([...this['_eventQueues']['values']()]);for(let _0x25a049 of this['_eventBindings']['values']())_0x25a049['connection']['close'](0x3e9,'Endpoint\x20disposed');this['_eventBindings']['clear'](),this['_eventRooms']['clear'](),this['_eventQueues']['clear']();let _0x580e28=[...this['_scopedEndpoints']['values']()];this['_scopedEndpoints']['clear'](),await Promise['all'](_0x580e28['map'](_0x2b641c=>_0x2b641c['dispose']())),this['_middleware']['clear'](),this['_listeners']['clear']();}async['_handleHttp'](_0x544fd7,_0x27082c){let _0x1d1d7a;try{_0x1d1d7a=new URL(_0x544fd7['incomingMessage']['url']??'/','http://localhost');}catch(_0x729849){this['_writeFailure'](_0x544fd7,_0x729849);return;}if(_0x544fd7['incomingMessage']['method']==='GET'&&_0x1d1d7a['pathname']===l){try{this['_requireUser'](_0x544fd7);let _0x5b5e7a=await this['_options']['ticketStore']['issue']({'userID':_0x544fd7['userID'],'customData':_0x544fd7['customData']},this['_ticketTtlMs']);w(_0x544fd7,0xc8,{'error':{'code':a['ErrorCode']['OK'],'message':''},'ticket':_0x5b5e7a});}catch(_0x40382a){this['_writeFailure'](_0x544fd7,_0x40382a);}return;}let _0x53c11b,_0x22c222;try{_0x53c11b=f(_0x544fd7['incomingMessage']['method'],_0x1d1d7a['pathname']),_0x22c222=p(_0x1d1d7a['pathname']);}catch(_0x5e9919){this['_writeFailure'](_0x544fd7,_0x5e9919);return;}if(_0x53c11b){await this['_handleManagement'](_0x544fd7,_0x53c11b);return;}if(_0x22c222&&m(_0x22c222['suffix'])){await this['_scopedEndpoint'](_0x22c222['worktreeID'],_0x22c222['protocolBasePath'])['handleHttp'](_0x544fd7,_0x27082c);return;}await _0x27082c();}async['_handleManagement'](_0x1d2c28,_0x4b6105){try{this['_requireUser'](_0x1d2c28);let _0x4eaa8e={'userID':_0x1d2c28['userID'],'customData':_0x1d2c28['customData']};if(_0x4b6105['action']==='evaluateUnitMerge'){let _0x109dcc=await this['_service']['evaluateWorktreeUnitMerge']({'worktreeID':_0x4b6105['worktreeID'],'unitID':_0x4b6105['unitID']},_0x4eaa8e);_0x1d2c28['response']['setHeader']('cache-control','no-store'),w(_0x1d2c28,0xc8,{'evaluation':_0x109dcc});return;}let _0x5f0ef9;switch(_0x4b6105['action']){case'create':{let _0x28eafa=await _0x1d2c28['readJson']();g(_0x28eafa),_0x5f0ef9=await this['_service']['createWorktree'](_0x28eafa,_0x4eaa8e);break;}case'get':_0x5f0ef9=await this['_service']['getWorktree']({'worktreeID':_0x4b6105['worktreeID']},_0x4eaa8e);break;case'addUnit':{let _0x46fb7f=await _0x1d2c28['readJson']();_(_0x46fb7f),_0x5f0ef9=await this['_service']['addUnit']({'worktreeID':_0x4b6105['worktreeID'],'unitID':_0x46fb7f['unitID']},_0x4eaa8e);break;}case'createUnitFromSnapshot':{let _0x241f4d=v(await _0x1d2c28['readJson']());_0x5f0ef9=await this['_service']['createUnitFromSnapshot']({'worktreeID':_0x4b6105['worktreeID'],..._0x241f4d},_0x4eaa8e);break;}case'createUnitFromData':{let _0x4727c5=y(await _0x1d2c28['readJson']());_0x5f0ef9=await this['_service']['createUnitFromData']({'worktreeID':_0x4b6105['worktreeID'],..._0x4727c5},_0x4eaa8e);break;}case'ready':_0x5f0ef9=await this['_service']['markReady']({'worktreeID':_0x4b6105['worktreeID']},_0x4eaa8e);break;case'reopen':_0x5f0ef9=await this['_service']['reopenWorktree']({'worktreeID':_0x4b6105['worktreeID']},_0x4eaa8e);break;case'discard':_0x5f0ef9=await this['_service']['discardWorktree']({'worktreeID':_0x4b6105['worktreeID']},_0x4eaa8e);break;case'merge':_0x5f0ef9=await this['_service']['mergeWorktree']({'worktreeID':_0x4b6105['worktreeID']},{..._0x4eaa8e,'memberID':'http-'+(0x0,e['randomUUID'])()});break;}w(_0x1d2c28,0xc8,{'worktree':_0x5f0ef9['worktree']});}catch(_0x2a5dc8){this['_writeFailure'](_0x1d2c28,_0x2a5dc8);}}async['_openEventConnection'](_0x16c319,_0x355b84,_0xa86173){try{let _0x4f5221=(0x0,e['randomUUID'])(),_0x3bf832={'memberID':_0x4f5221,'userID':_0x355b84['userID'],'customData':_0x355b84['customData']},_0x2568d5={'memberID':_0x4f5221,'userID':_0x355b84['userID'],'name':_0x355b84['userID']};await this['_middleware']['run']('connect',{'worktreeID':_0xa86173,'session':_0x3bf832,'connection':_0x16c319,'member':_0x2568d5},async()=>void 0x0);let _0x58f20a={'worktreeID':_0xa86173,'connection':_0x16c319,'session':_0x3bf832,'ready':!0x1};this['_eventBindings']['set'](_0x16c319['id'],_0x58f20a);let _0x503359=this['_eventRooms']['get'](_0xa86173)??new Map();_0x503359['set'](_0x16c319['id'],_0x58f20a),this['_eventRooms']['set'](_0xa86173,_0x503359);try{let {worktree:_0xd985c9}=await this['_service']['getWorktree']({'worktreeID':_0xa86173},{'userID':_0x3bf832['userID'],'customData':_0x16c319['customData']});if(await this['_sendChanged'](_0x58f20a,_0xd985c9),_0x58f20a['ready']=!0x0,_0x58f20a['pending']){let _0x40d4bd=_0x58f20a['pending'];delete _0x58f20a['pending'],await this['_sendChanged'](_0x58f20a,_0x40d4bd);}}catch(_0x1a8a23){throw this['_removeEventBinding'](_0x16c319['id']),_0x1a8a23;}}catch(_0xc5d080){_0x16c319['close'](_0xc5d080 instanceof n['CollabError']||_0xc5d080 instanceof i['WorktreeError']?0x3f0:0x3f3,'Worktree\x20event\x20connection\x20rejected');}}['_scopedEndpoint'](_0x5a52d1,_0x56a166){let _0x3830e7=this['_scopedEndpoints']['get'](_0x5a52d1);if(_0x3830e7)return _0x3830e7;let _0x54d113=new t['UniverCollabEndpoint'](new d(this['_service'],_0x5a52d1),{'ticketStore':this['_options']['ticketStore'],'protocolBasePath':_0x56a166});return _0x54d113['use']('connect',(_0x467d0b,_0x58043d)=>this['_middleware']['run']('connect',{..._0x467d0b,'worktreeID':_0x5a52d1},_0x58043d)),_0x54d113['use']('joinUnit',async(_0xb49527,_0x6a0f75)=>{let {worktree:_0xa4b106}=await this['_getJoinableWorktree'](_0x5a52d1,_0xb49527['session']);if(!_0xa4b106['units']['some'](({unitID:_0x517d23})=>_0x517d23===_0xb49527['unitID']))throw new n['CollabError']('UNIT_NOT_FOUND','Unit\x20'+_0xb49527['unitID']+'\x20is\x20not\x20in\x20Worktree\x20'+_0x5a52d1);await this['_middleware']['run']('joinUnit',{..._0xb49527,'worktreeID':_0x5a52d1},_0x6a0f75);}),_0x54d113['use']('receivePresence',(_0x51c13f,_0x79640a)=>this['_middleware']['run']('receivePresence',{..._0x51c13f,'worktreeID':_0x5a52d1},_0x79640a)),_0x54d113['use']('sendPresence',(_0x1a14c6,_0x28bf87)=>this['_middleware']['run']('sendPresence',{..._0x1a14c6,'worktreeID':_0x5a52d1},_0x28bf87)),_0x54d113['on']('memberLeftUnit',_0x3bffd9=>this['_emit']('memberLeftUnit',{..._0x3bffd9,'worktreeID':_0x5a52d1})),this['_scopedEndpoints']['set'](_0x5a52d1,_0x54d113),_0x54d113;}async['_getJoinableWorktree'](_0x22f301,_0x373afd){try{let _0xb783fe=await this['_service']['getWorktree']({'worktreeID':_0x22f301},{'userID':_0x373afd['userID']});if(_0xb783fe['worktree']['status']==='discarded')throw new n['CollabError']('PERMISSION_DENIED','Discarded\x20Worktree\x20cannot\x20be\x20joined');return _0xb783fe;}catch(_0x40e994){throw _0x40e994 instanceof i['WorktreeError']&&_0x40e994['code']==='WORKTREE_NOT_FOUND'?new n['CollabError']('UNIT_NOT_FOUND',_0x40e994['message']):_0x40e994;}}['_enqueueWorktreeChanged'](_0x43d404){if(this['_disposed'])return;let _0xb373d4=_0x43d404['worktreeID'],_0x400137=(this['_eventQueues']['get'](_0xb373d4)??Promise['resolve']())['catch'](()=>void 0x0)['then'](async()=>{let _0x107b7b=[...this['_eventRooms']['get'](_0xb373d4)?.['values']()??[]];for(let _0x467dfc of _0x107b7b){if(!_0x467dfc['ready']){_0x467dfc['pending']=_0x43d404;continue;}await this['_sendChanged'](_0x467dfc,_0x43d404);}});this['_eventQueues']['set'](_0xb373d4,_0x400137),_0x400137['finally'](()=>{this['_eventQueues']['get'](_0xb373d4)===_0x400137&&this['_eventQueues']['delete'](_0xb373d4);});}['_sendChanged'](_0x34ce7b,_0x15183f){let _0x125404={'event':'worktreeChanged','worktree':_0x15183f};return Promise['resolve'](_0x34ce7b['connection']['send'](JSON['stringify'](_0x125404)));}['_removeEventBinding'](_0x3cd8ce){let _0x4afbc3=this['_eventBindings']['get'](_0x3cd8ce);if(!_0x4afbc3)return;this['_eventBindings']['delete'](_0x3cd8ce);let _0x536ba2=this['_eventRooms']['get'](_0x4afbc3['worktreeID']);_0x536ba2?.['delete'](_0x3cd8ce),_0x536ba2?.['size']===0x0&&this['_eventRooms']['delete'](_0x4afbc3['worktreeID']);}async['_emit'](_0x2d07cc,_0xb6d632){for(let _0x300be0 of[...this['_listeners']['get'](_0x2d07cc)??[]])try{await _0x300be0(_0xb6d632);}catch{}}['_requireUser'](_0x1565e2){if(!_0x1565e2['userID'])throw new n['CollabError']('UNAUTHENTICATED','HTTP\x20user\x20is\x20not\x20authenticated');}['_writeFailure'](_0x25199e,_0x10a8fe){let _0x5538ae=T(_0x10a8fe);w(_0x25199e,_0x5538ae['status'],{'error':_0x5538ae['error']});}['_assertRunning'](){if(this['_disposed'])throw new n['CollabError']('INTERNAL_ERROR','Worktree\x20Endpoint\x20is\x20disposed');}},d=class{['_service'];['_worktreeID'];constructor(_0x537c68,_0x3c01da){this['_service']=_0x537c68,this['_worktreeID']=_0x3c01da;}['use'](){return{'dispose':()=>void 0x0};}['getUnitLoadData'](_0x295fca,_0x10432e){return this['_service']['getUnitLoadData']({..._0x295fca,'worktreeID':this['_worktreeID']},_0x10432e);}['getUnitLoadDataWithBlocks'](_0x8b7cbb,_0x4efa54){return Promise['reject'](new n['CollabError']('INVALID_REQUEST','Cannot\x20read\x20Unit\x20blocks\x20through\x20a\x20Worktree\x20Endpoint'));}['getChangesets'](_0x39b116,_0x280db3){return this['_service']['getChangesets']({..._0x39b116,'worktreeID':this['_worktreeID']},_0x280db3);}['getSheetBlock'](_0x304e0f,_0x48aa76){return this['_service']['getSheetBlock']({..._0x304e0f,'worktreeID':this['_worktreeID']},_0x48aa76);}['createUnitFromSnapshot'](_0x1e9e1f,_0xd2b29c){return Promise['reject'](new n['CollabError']('INVALID_REQUEST','Cannot\x20create\x20a\x20Unit\x20through\x20a\x20Worktree\x20Endpoint'));}['createUnitFromData'](_0x2a4c4b,_0x15430c){return Promise['reject'](new n['CollabError']('INVALID_REQUEST','Cannot\x20create\x20a\x20Unit\x20through\x20a\x20Worktree\x20Endpoint'));}['deleteUnits'](_0x1a0ce8,_0x10ba4d){return Promise['reject'](new n['CollabError']('INVALID_REQUEST','Cannot\x20delete\x20Units\x20through\x20a\x20Worktree\x20Endpoint'));}['recoverUnits'](_0x436493,_0x2cc755){return Promise['reject'](new n['CollabError']('INVALID_REQUEST','Cannot\x20recover\x20Units\x20through\x20a\x20Worktree\x20Endpoint'));}['submitChangeset'](_0x301f67,_0x55cbec){return this['_service']['submitChangeset']({..._0x301f67,'worktreeID':this['_worktreeID']},_0x55cbec);}['on'](_0x4b0764,_0x131735){return _0x4b0764==='changesetCommitted'?this['_service']['on']('changesetCommitted',_0x389020=>{if(_0x389020['request']['worktreeID']===this['_worktreeID'])return _0x131735(_0x389020);}):{'dispose':()=>void 0x0};}['dispose'](){return Promise['resolve']();}};function f(_0x1ff135,_0x2608fd){if(_0x1ff135==='POST'&&_0x2608fd===c)return{'action':'create'};let _0x5b7332=_0x2608fd['split']('/')['filter'](Boolean);if(_0x5b7332['length']<0x3||_0x5b7332[0x0]!=='universer-api'||_0x5b7332[0x1]!=='worktrees')return null;let _0xbda0e6=h(_0x5b7332[0x2]);if(_0x1ff135==='GET'&&_0x5b7332['length']===0x3)return{'action':'get','worktreeID':_0xbda0e6};if(_0x1ff135==='GET'&&_0x5b7332['length']===0x6&&_0x5b7332[0x3]==='units'&&_0x5b7332[0x5]==='merge-preview')return{'action':'evaluateUnitMerge','worktreeID':_0xbda0e6,'unitID':h(_0x5b7332[0x4])};if(_0x1ff135==='POST'&&_0x5b7332['length']===0x5&&_0x5b7332[0x3]==='units'){let _0x27b99f={'from-snapshot':'createUnitFromSnapshot','from-data':'createUnitFromData'}[_0x5b7332[0x4]];return _0x27b99f?{'action':_0x27b99f,'worktreeID':_0xbda0e6}:null;}if(_0x1ff135!=='POST'||_0x5b7332['length']!==0x4)return null;let _0xce5dd9={'units':'addUnit','ready':'ready','reopen':'reopen','discard':'discard','merge':'merge'}[_0x5b7332[0x3]];return _0xce5dd9?{'action':_0xce5dd9,'worktreeID':_0xbda0e6}:null;}function p(_0x23e23f){let _0x4c84c1=_0x23e23f['split']('/')['filter'](Boolean);if(_0x4c84c1['length']<0x4||_0x4c84c1[0x0]!=='universer-api'||_0x4c84c1[0x1]!=='worktrees')return null;let _0x4f8e88=_0x4c84c1[0x2],_0x441427=h(_0x4f8e88),_0x7b6378=c+'/'+encodeURIComponent(_0x441427);return _0x23e23f['startsWith'](_0x7b6378+'/')?{'worktreeID':_0x441427,'protocolBasePath':_0x7b6378,'suffix':_0x23e23f['slice'](_0x7b6378['length'])}:null;}function m(_0x5c2582){return _0x5c2582['startsWith']('/snapshot/')||_0x5c2582['startsWith']('/comb/');}function h(_0x4d06b8){try{let _0x43df32=decodeURIComponent(_0x4d06b8);if(!_0x43df32)throw Error('empty');return _0x43df32;}catch{throw new n['CollabError']('INVALID_REQUEST','Route\x20contains\x20invalid\x20encoding');}}function g(_0x27426c){if(!_0x27426c||typeof _0x27426c!='object'||typeof _0x27426c['worktreeID']!='string')throw new n['CollabError']('INVALID_REQUEST','worktreeID\x20must\x20be\x20a\x20string');let _0x4136b5=_0x27426c['units'];if(_0x4136b5!==void 0x0&&(!Array['isArray'](_0x4136b5)||_0x4136b5['some'](_0x1a7981=>typeof _0x1a7981!='string')))throw new n['CollabError']('INVALID_REQUEST','units\x20must\x20be\x20a\x20string\x20array');}function _(_0x34378c){if(!_0x34378c||typeof _0x34378c!='object'||typeof _0x34378c['unitID']!='string')throw new n['CollabError']('INVALID_REQUEST','unitID\x20must\x20be\x20a\x20string');}function v(_0x28c662){if(!S(_0x28c662)||!S(_0x28c662['snapshot']))throw new n['CollabError']('INVALID_REQUEST','snapshot\x20must\x20be\x20an\x20object');let _0x21f83e=_0x28c662['snapshot'];b(_0x21f83e);let _0x3b788a=_0x28c662['sheetBlocks'];if(_0x3b788a!==void 0x0&&(!Array['isArray'](_0x3b788a)||_0x3b788a['some'](_0x51ecd6=>!S(_0x51ecd6))))throw new n['CollabError']('INVALID_REQUEST','sheetBlocks\x20must\x20be\x20an\x20object\x20array');for(let _0x1742df of _0x3b788a??[])_0x1742df['data']=x(_0x1742df['data'],'sheetBlocks[].data');return{'snapshot':_0x21f83e,'sheetBlocks':_0x3b788a??[]};}function y(_0x165717){if(!S(_0x165717)||!C['has'](_0x165717['type'])||!S(_0x165717['data']))throw new n['CollabError']('INVALID_REQUEST','type\x20and\x20data\x20must\x20describe\x20a\x20supported\x20Unit');return _0x165717;}function b(_0x5dc603){let _0x1d293d=_0x5dc603['workbook']??_0x5dc603['doc']??_0x5dc603['slide']??_0x5dc603['board'];if(_0x1d293d&&(_0x1d293d['originalMeta']=x(_0x1d293d['originalMeta'],'snapshot\x20originalMeta'),_0x5dc603['workbook'])){for(let _0x597038 of Object['values'](_0x5dc603['workbook']['sheets']))_0x597038['originalMeta']=x(_0x597038['originalMeta'],'snapshot\x20sheet\x20originalMeta');}}function x(_0x32416d,_0x3c6f0d){if(_0x32416d instanceof Uint8Array)return _0x32416d;if(typeof _0x32416d!='string')throw new n['CollabError']('INVALID_REQUEST',_0x3c6f0d+'\x20must\x20be\x20a\x20base64\x20string');try{return new Uint8Array(Buffer['from'](_0x32416d,'base64'));}catch{throw new n['CollabError']('INVALID_REQUEST',_0x3c6f0d+'\x20must\x20be\x20valid\x20base64');}}function S(_0x259cce){return!!_0x259cce&&typeof _0x259cce=='object'&&!Array['isArray'](_0x259cce);}var C=new Set([a['UniverType']['UNIVER_SHEET'],a['UniverType']['UNIVER_DOC'],a['UniverType']['UNIVER_SLIDE'],a['UniverType']['UNIVER_BOARD'],a['UniverType']['UNIVER_BASE']]);function w(_0x15d6e6,_0x414b96,_0x5c718a){let _0x5333d7=_0x15d6e6['response'];_0x5333d7['writableEnded']||_0x5333d7['destroyed']||(_0x5333d7['statusCode']=_0x414b96,_0x5333d7['setHeader']('content-type','application/json;\x20charset=utf-8'),_0x5333d7['end'](JSON['stringify'](_0x5c718a,(_0x40ad11,_0x9867f6)=>_0x9867f6 instanceof Uint8Array?Buffer['from'](_0x9867f6)['toString']('base64'):_0x9867f6)));}function T(_0x44722c){return _0x44722c instanceof r['NodeTransportError']?{'status':_0x44722c['code']==='REQUEST_BODY_TOO_LARGE'?0x19d:_0x44722c['code']==='INVALID_JSON'||_0x44722c['code']==='REQUEST_ABORTED'?0x190:0x1f7,'error':{'code':_0x44722c['code'],'message':_0x44722c['message']}}:_0x44722c instanceof i['WorktreeError']?{'status':_0x44722c['code']==='WORKTREE_NOT_FOUND'||_0x44722c['code']==='WORKTREE_UNIT_NOT_FOUND'?0x194:0x199,'error':{'code':_0x44722c['code'],'message':_0x44722c['message'],'retryable':_0x44722c['retryable']}}:_0x44722c instanceof n['CollabError']?{'status':{'UNAUTHENTICATED':0x191,'INVALID_REQUEST':0x190,'UNIT_NOT_FOUND':0x194,'PERMISSION_DENIED':0x193,'OT_CONFLICT':0x199,'REVISION_MISMATCH':0x199,'ADAPTER_FAILURE':0x1f7,'INTERNAL_ERROR':0x1f4}[_0x44722c['code']],'error':{'code':_0x44722c['code'],'message':_0x44722c['message'],'retryable':_0x44722c['retryable']}}:{'status':0x1f4,'error':{'code':'INTERNAL_ERROR','message':'Internal\x20server\x20error'}};}exports['UniverCollabWorktreeEndpoint']=u;
@@ -0,0 +1,84 @@
1
+ import { EndpointMember, EndpointSession, ISessionTicketStore } from "@univerjs-pro/collaboration-endpoint";
2
+ import { Disposable } from "@univerjs-pro/collaboration-service";
3
+ import { NodeHttpTransportContext, NodeTransportConnection, NodeTransportEndpoint, NodeTransportNext, NodeWebSocketEndpointContext } from "@univerjs-pro/collaboration-transport-node";
4
+ import { IUniverCollabWorktreeService, WorktreeData } from "@univerjs-pro/collaboration-worktree-service";
5
+
6
+ //#region src/worktree-endpoint.d.ts
7
+ interface UniverCollabWorktreeEndpointOptions {
8
+ readonly ticketStore: ISessionTicketStore;
9
+ readonly sessionTicketTtlMs?: number;
10
+ }
11
+ interface BaseWorktreeEndpointMiddlewareContext {
12
+ readonly worktreeID: string;
13
+ readonly session: EndpointSession;
14
+ }
15
+ interface ConnectWorktreeEndpointMiddlewareContext extends BaseWorktreeEndpointMiddlewareContext {
16
+ readonly connection: NodeTransportConnection;
17
+ readonly member: EndpointMember;
18
+ }
19
+ interface JoinWorktreeUnitEndpointMiddlewareContext extends BaseWorktreeEndpointMiddlewareContext {
20
+ readonly unitID: string;
21
+ }
22
+ interface ReceiveWorktreePresenceEndpointMiddlewareContext extends JoinWorktreeUnitEndpointMiddlewareContext {
23
+ readonly payload: unknown;
24
+ readonly customData: Record<string, unknown>;
25
+ }
26
+ interface SendWorktreePresenceEndpointMiddlewareContext extends ReceiveWorktreePresenceEndpointMiddlewareContext {
27
+ readonly targetMemberID: string;
28
+ }
29
+ type WorktreeEndpointMiddlewareAction = "connect" | "joinUnit" | "receivePresence" | "sendPresence";
30
+ type WorktreeEndpointMiddlewareNext = () => Promise<void>;
31
+ type WorktreeEndpointMiddleware<TContext> = (context: TContext, next: WorktreeEndpointMiddlewareNext) => void | Promise<void>;
32
+ interface WorktreeEndpointMiddlewareMap {
33
+ readonly connect: WorktreeEndpointMiddleware<ConnectWorktreeEndpointMiddlewareContext>;
34
+ readonly joinUnit: WorktreeEndpointMiddleware<JoinWorktreeUnitEndpointMiddlewareContext>;
35
+ readonly receivePresence: WorktreeEndpointMiddleware<ReceiveWorktreePresenceEndpointMiddlewareContext>;
36
+ readonly sendPresence: WorktreeEndpointMiddleware<SendWorktreePresenceEndpointMiddlewareContext>;
37
+ }
38
+ interface MemberLeftWorktreeUnitEvent {
39
+ readonly worktreeID: string;
40
+ readonly session: EndpointSession;
41
+ readonly unitID: string;
42
+ readonly reason: "explicit" | "disconnect" | "endpoint-dispose";
43
+ }
44
+ interface WorktreeEndpointEventMap {
45
+ readonly memberLeftUnit: MemberLeftWorktreeUnitEvent;
46
+ }
47
+ interface WorktreeChangedMessage {
48
+ readonly event: "worktreeChanged";
49
+ readonly worktree: WorktreeData;
50
+ }
51
+ type EndpointListener<K extends keyof WorktreeEndpointEventMap> = (event: WorktreeEndpointEventMap[K]) => void | Promise<void>;
52
+ declare class UniverCollabWorktreeEndpoint implements NodeTransportEndpoint {
53
+ private readonly _service;
54
+ private readonly _options;
55
+ private readonly _middleware;
56
+ private readonly _listeners;
57
+ private readonly _scopedEndpoints;
58
+ private readonly _eventBindings;
59
+ private readonly _eventRooms;
60
+ private readonly _eventQueues;
61
+ private readonly _subscriptions;
62
+ private readonly _ticketTtlMs;
63
+ private _disposed;
64
+ constructor(_service: IUniverCollabWorktreeService, _options: UniverCollabWorktreeEndpointOptions);
65
+ use<K extends WorktreeEndpointMiddlewareAction>(action: K, middleware: WorktreeEndpointMiddlewareMap[K]): Disposable;
66
+ on<K extends keyof WorktreeEndpointEventMap>(event: K, listener: EndpointListener<K>): Disposable;
67
+ handleHttp(context: NodeHttpTransportContext, next: NodeTransportNext): Promise<void>;
68
+ handleUpgrade(context: NodeWebSocketEndpointContext, next: NodeTransportNext): Promise<void>;
69
+ dispose(): Promise<void>;
70
+ private _handleHttp;
71
+ private _handleManagement;
72
+ private _openEventConnection;
73
+ private _scopedEndpoint;
74
+ private _getJoinableWorktree;
75
+ private _enqueueWorktreeChanged;
76
+ private _sendChanged;
77
+ private _removeEventBinding;
78
+ private _emit;
79
+ private _requireUser;
80
+ private _writeFailure;
81
+ private _assertRunning;
82
+ }
83
+ //#endregion
84
+ export { type BaseWorktreeEndpointMiddlewareContext, type ConnectWorktreeEndpointMiddlewareContext, type JoinWorktreeUnitEndpointMiddlewareContext, type MemberLeftWorktreeUnitEvent, type ReceiveWorktreePresenceEndpointMiddlewareContext, type SendWorktreePresenceEndpointMiddlewareContext, UniverCollabWorktreeEndpoint, type UniverCollabWorktreeEndpointOptions, type WorktreeChangedMessage, type WorktreeEndpointEventMap, type WorktreeEndpointMiddleware, type WorktreeEndpointMiddlewareAction, type WorktreeEndpointMiddlewareMap, type WorktreeEndpointMiddlewareNext };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ const _0x9d398c=_0x192b;(function(_0x2f5ca4,_0x41d9ab){const _0x166e10=_0x192b,_0x36afa5=_0x2f5ca4();while(!![]){try{const _0x4f0f33=parseInt(_0x166e10(0xd9))/0x1*(parseInt(_0x166e10(0xda))/0x2)+-parseInt(_0x166e10(0xd8))/0x3*(-parseInt(_0x166e10(0xdd))/0x4)+parseInt(_0x166e10(0xe0))/0x5+parseInt(_0x166e10(0xdf))/0x6+parseInt(_0x166e10(0xdc))/0x7*(-parseInt(_0x166e10(0xd6))/0x8)+parseInt(_0x166e10(0xe1))/0x9+parseInt(_0x166e10(0xde))/0xa*(-parseInt(_0x166e10(0xdb))/0xb);if(_0x4f0f33===_0x41d9ab)break;else _0x36afa5['push'](_0x36afa5['shift']());}catch(_0x1708a1){_0x36afa5['push'](_0x36afa5['shift']());}}}(_0x4668,0x9f98f));import _0x1766c4 from'./index.cjs';function _0x192b(_0x2958ca,_0x2942cb){_0x2958ca=_0x2958ca-0xd6;const _0x46680b=_0x4668();let _0x192bbd=_0x46680b[_0x2958ca];return _0x192bbd;}const facadeExport0=_0x1766c4[_0x9d398c(0xd7)];function _0x4668(){const _0x5b07d2=['11eZLAFi','1526jXUkUe','33420qUiGsy','23422340MuxxGK','7008006YtCAfa','4667425akwIOY','8526375NlEzBD','11056KunWHq','UniverCollabWorktreeEndpoint','51wRzeYq','106325bbqLWV','2UJoiue'];_0x4668=function(){return _0x5b07d2;};return _0x4668();}export{facadeExport0 as UniverCollabWorktreeEndpoint};
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@univerjs-pro/collaboration-worktree-endpoint",
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-endpoint": "1.0.0-beta.2",
20
+ "@univerjs-pro/collaboration-service": "1.0.0-beta.2",
21
+ "@univerjs-pro/collaboration-transport-node": "1.0.0-beta.2",
22
+ "@univerjs-pro/collaboration-worktree-service": "1.0.0-beta.2",
23
+ "@univerjs/protocol": "1.0.0-beta.2"
24
+ }
25
+ }