@univerjs/rpc 0.20.1 → 0.21.0
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/lib/cjs/index.js +776 -1
- package/lib/es/index.js +728 -1
- package/lib/index.js +728 -1
- package/lib/umd/index.js +1 -1
- package/package.json +4 -4
package/lib/es/index.js
CHANGED
|
@@ -1 +1,728 @@
|
|
|
1
|
-
import{CommandType as e,Disposable as t,ICommandService as n,IConfigService as r,ILogService as i,IUniverInstanceService as a,Inject as o,Injector as s,Plugin as c,RxDisposable as l,UniverInstanceType as u,createIdentifier as d,merge as f,toDisposable as p}from"@univerjs/core";import{filter as m,take as ee,takeUntil as h}from"rxjs/operators";import{BehaviorSubject as g,Observable as _,firstValueFrom as v,isObservable as te,of as y,shareReplay as b}from"rxjs";const x=`rpc.main-thread.config`;Symbol(x);const S={},C=`rpc.worker-thread.config`;Symbol(C);const w={};function T(e,t){return function(n,r){t(n,r,e)}}function E(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}const D=`rpc.remote-sync.service`,O=d(D);let k=class{constructor(e){this._commandService=e}async syncMutation(e,t){let{fromCollab:n,...r}=t||{};return this._commandService.syncExecuteCommand(e.mutationInfo.id,e.mutationInfo.params,{...r,onlyLocal:!0,fromSync:!0})}};k=E([T(0,n)],k);const A=`univer.remote-instance-service`,j=d(A);let M=class{constructor(e,t,n){this._univerInstanceService=e,this._commandService=t,this._logService=n}whenReady(){return Promise.resolve(!0)}async syncMutation(e,t){return this._applyMutation(e.mutationInfo,t)}async createInstance(e){this._logService.debug(`[WebWorkerRemoteInstanceService]: Creating instance with id ${e.unitID}`);let{type:t,snapshot:n}=e;try{switch(t){case u.UNIVER_SHEET:return this._univerInstanceService.createUnit(u.UNIVER_SHEET,n),!0;default:throw Error(`[WebWorkerRemoteInstanceService]: cannot create replica for document type: ${t}.`)}}catch(e){throw e instanceof Error?e:TypeError(`${e}`)}}async disposeInstance(e){return this._logService.debug(`[WebWorkerRemoteInstanceService]: Disposing instance with id ${e.unitID}`),this._univerInstanceService.disposeUnit(e.unitID)}_applyMutation(e,t){let{id:n,params:r}=e,{fromCollab:i,...a}=t||{};return this._commandService.syncExecuteCommand(n,r,{...a,onlyLocal:!0,fromSync:!0})}};M=E([T(0,a),T(1,n),T(2,i)],M);function N(e){"@babel/helpers - typeof";return N=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},N(e)}function P(e,t){if(N(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(N(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function F(e){var t=P(e,`string`);return N(t)==`symbol`?t:t+``}function I(e,t,n){return(t=F(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function L(e){let t=e;return new class{call(e,n){let r=t[e];if(typeof r==`function`){let e=n?r.apply(t,n):r.call(t);return e instanceof Promise||(e=Promise.resolve(e)),e}throw Error(`[RPC]: method not found for ${e}!`)}subscribe(e,n){let r=t[e];if(typeof r==`function`){let e=n?r.apply(t,n):r.call(t);return te(e)?e:y(e)}throw Error(`[RPC]: observable method not found for ${e}!`)}}}function R(e){return new Proxy({},{get(t,n){if(n!==`dispose`)return function(...t){return z(n)?e.subscribe(n,t):e.call(n,t)}}})}function z(e){return e.endsWith(`$`)}var B=function(e){return e[e.REQUEST_INITIALIZATION=50]=`REQUEST_INITIALIZATION`,e[e.CALL=100]=`CALL`,e[e.SUBSCRIBE=101]=`SUBSCRIBE`,e[e.UNSUBSCRIBE=102]=`UNSUBSCRIBE`,e}(B||{}),V=function(e){return e[e.INITIALIZE=0]=`INITIALIZE`,e[e.CALL_SUCCESS=201]=`CALL_SUCCESS`,e[e.CALL_FAILURE=202]=`CALL_FAILURE`,e[e.SUBSCRIBE_NEXT=300]=`SUBSCRIBE_NEXT`,e[e.SUBSCRIBE_ERROR=301]=`SUBSCRIBE_ERROR`,e[e.SUBSCRIBE_COMPLETE=302]=`SUBSCRIBE_COMPLETE`,e}(V||{}),H=class extends l{constructor(e){super(),this._protocol=e,I(this,`_initialized`,new g(!1)),I(this,`_lastRequestCounter`,0),I(this,`_pendingRequests`,new Map),this._protocol.send({type:B.REQUEST_INITIALIZATION}),this._protocol.onMessage.pipe(h(this.dispose$)).subscribe(e=>this._onMessage(e))}dispose(){this._pendingRequests.clear()}getChannel(e){return{call:(t,n)=>this._disposed?Promise.reject(Error(`[ChannelClient]: client is disposed!`)):this._remoteCall(e,t,n),subscribe:(t,n)=>{if(this._disposed)throw Error(`[ChannelClient]: client is disposed!`);return this._remoteSubscribe(e,t,n)}}}_whenReady(){return v(this._initialized.pipe(m(e=>e),ee(1)))}_remoteCall(e,t,n){return this._initialized.getValue()?this._doRemoteCall(e,t,n):this._whenReady().then(()=>this._doRemoteCall(e,t,n))}_doRemoteCall(e,t,n){let r=++this._lastRequestCounter,i={seq:r,type:B.CALL,channelName:e,method:t,args:n},a=this._pendingRequests;return new Promise((e,t)=>{this._pendingRequests.set(r,{handle(n){switch(n.type){case V.CALL_SUCCESS:a.delete(r),e(n.data);break;case V.CALL_FAILURE:a.delete(r),t(n.data);break;default:throw Error(`[ChannelClient]: unknown response type!`)}}}),this._sendRequest(i)})}_remoteSubscribe(e,t,n){return new _(r=>{let i=-1,a=()=>{i=++this._lastRequestCounter;let a=B.SUBSCRIBE,o={seq:i,type:a,channelName:e,method:t,args:n};this._pendingRequests.set(i,{handle(e){switch(e.type){case V.SUBSCRIBE_NEXT:r.next(e.data);break;case V.SUBSCRIBE_ERROR:r.error(e.data);break;case V.SUBSCRIBE_COMPLETE:r.complete();break;default:throw Error(`[ChannelClient]: unknown response type!`)}}}),this._sendRequest(o)};return this._initialized.getValue()?a():this._whenReady().then(a),()=>{if(i===-1)return;let n={type:B.UNSUBSCRIBE,seq:i,channelName:e,method:t};this._sendRequest(n)}})}_sendRequest(e){this._protocol.send(e)}_onMessage(e){let{type:t,seq:n}=e;switch(t){case V.INITIALIZE:this._initialized.next(!0);break;case V.CALL_SUCCESS:case V.CALL_FAILURE:case V.SUBSCRIBE_NEXT:case V.SUBSCRIBE_COMPLETE:case V.SUBSCRIBE_ERROR:{var r;let{_pendingRequests:i}=this;(r=i.get(n))==null||r.handle(e),t!==V.SUBSCRIBE_NEXT&&i.delete(n);break}}}},U=class extends l{constructor(e){super(),this._protocol=e,I(this,`_channels`,new Map),I(this,`_subscriptions`,new Map),this._protocol.onMessage.pipe(h(this.dispose$)).subscribe(e=>this._onRequest(e)),this._sendInitialize()}dispose(){super.dispose(),this._subscriptions.clear(),this._channels.clear()}registerChannel(e,t){this._channels.set(e,t)}_onRequest(e){switch(e.type){case B.REQUEST_INITIALIZATION:this._sendInitialize();break;case B.CALL:this._onMethodCall(e);break;case B.SUBSCRIBE:this._onSubscribe(e);break;case B.UNSUBSCRIBE:this._onUnsubscribe(e);break;default:break}}_sendInitialize(){this._sendResponse({seq:-1,type:V.INITIALIZE})}_onMethodCall(e){let{channelName:t,method:n,args:r}=e,i=this._channels.get(t),a;try{if(!i)throw Error(`[ChannelServer]: Channel ${t} not found!`);a=r?i.call(n,r):i.call(n)}catch(e){a=Promise.reject(e instanceof Error?e:Error(String(e)))}a.then(t=>{this._sendResponse({seq:e.seq,type:V.CALL_SUCCESS,data:t})}).catch(t=>{t instanceof Error?this._sendResponse({seq:e.seq,type:V.CALL_FAILURE,data:t.message}):this._sendResponse({seq:e.seq,type:V.CALL_FAILURE,data:String(t)})})}_onSubscribe(e){let{channelName:t,seq:n}=e,r=this._channels.get(t);try{if(!r)throw Error(`[ChannelServer]: Channel ${t} not found!`);let i=r.subscribe(e.method,e.args).subscribe({next:e=>{this._sendResponse({seq:n,type:V.SUBSCRIBE_NEXT,data:e})},error:e=>{this._sendResponse({seq:n,type:V.SUBSCRIBE_ERROR,data:e.message}),this._sendResponse({seq:n,type:V.SUBSCRIBE_COMPLETE})},complete:()=>{this._sendResponse({seq:n,type:V.SUBSCRIBE_COMPLETE})}});this._subscriptions.set(e.seq,i)}catch(t){t instanceof Error?this._sendResponse({seq:e.seq,type:V.SUBSCRIBE_ERROR,data:t.message}):this._sendResponse({seq:e.seq,type:V.SUBSCRIBE_ERROR,data:String(t)})}}_onUnsubscribe(e){let t=this._subscriptions.get(e.seq);t&&(t.unsubscribe(),this._subscriptions.delete(e.seq))}_sendResponse(e){this._protocol.send(e)}};const W=d(`IRPCChannelService`);var G=class{constructor(e){I(this,`_client`,void 0),I(this,`_server`,void 0),this._client=new H(e),this._server=new U(e)}dispose(){this._client.dispose(),this._server.dispose()}requestChannel(e){return this._client.getChannel(e)}registerChannel(e,t){this._server.registerChannel(e,t)}};let K=class extends l{constructor(e,t,n,r,i){super(),this._injector=e,this._commandService=t,this._univerInstanceService=n,this._rpcChannelService=r,this._remoteSyncService=i,I(this,`_remoteInstanceService`,void 0),I(this,`_syncingUnits`,new Set),I(this,`_syncingMutations`,new Set),this._initRPCChannels(),this._init()}registerSyncingMutations(e){this._syncingMutations.add(e.id)}syncUnit(e){return this._syncingUnits.add(e),p(()=>this._syncingUnits.delete(e))}_initRPCChannels(){this._rpcChannelService.registerChannel(D,L(this._remoteSyncService)),this._injector.add([j,{useFactory:()=>R(this._rpcChannelService.requestChannel(A))}]),this._remoteInstanceService=this._injector.get(j)}_init(){this._univerInstanceService.getTypeOfUnitAdded$(u.UNIVER_SHEET).pipe(h(this.dispose$)).subscribe(e=>{this._syncingUnits.add(e.getUnitId()),this._remoteInstanceService.createInstance({unitID:e.getUnitId(),type:u.UNIVER_SHEET,snapshot:e.getSnapshot()})}),this._univerInstanceService.getTypeOfUnitDisposed$(u.UNIVER_SHEET).pipe(h(this.dispose$)).subscribe(e=>{this._syncingUnits.delete(e.getUnitId()),this._remoteInstanceService.disposeInstance({unitID:e.getUnitId()})}),this.disposeWithMe(this._commandService.onCommandExecuted((t,n)=>{let{type:r,params:i,id:a}=t,o=(i==null?void 0:i.unitId)||``;r===e.MUTATION&&(!o||this._syncingUnits.has(o))&&!(n!=null&&n.fromSync)&&this._syncingMutations.has(a)&&this._remoteInstanceService.syncMutation({mutationInfo:t},n)}))}};K=E([T(0,o(s)),T(1,n),T(2,a),T(3,W),T(4,O)],K);let q=class extends t{constructor(e,t,n,r){super(),this._injector=e,this._remoteInstanceService=t,this._commandService=n,this._rpcChannelService=r,I(this,`_remoteSyncService`,void 0),this._initRPCChannels(),this._init()}_initRPCChannels(){this._rpcChannelService.registerChannel(A,L(this._remoteInstanceService)),this._injector.add([O,{useFactory:()=>R(this._rpcChannelService.requestChannel(D))}]),this._remoteSyncService=this._injector.get(O)}_init(){this.disposeWithMe(this._commandService.onCommandExecuted((t,n)=>{t.type===e.MUTATION&&!(n!=null&&n.fromSync)&&this._remoteSyncService.syncMutation({mutationInfo:t},n)}))}};q=E([T(0,o(s)),T(1,j),T(2,n),T(3,W)],q);var J=`@univerjs/rpc`,Y=`0.20.1`;function X(){return{send(e){postMessage(e)},onMessage:new _(e=>{let t=t=>{e.next(t.data)};return addEventListener(`message`,t),()=>removeEventListener(`message`,t)}).pipe(b(1))}}function Z(e){return{send(t){e.postMessage(t)},onMessage:new _(t=>{let n=e=>{t.next(e.data)};return e.addEventListener(`message`,n),()=>e.removeEventListener(`message`,n)}).pipe(b(1))}}let Q=class extends c{constructor(e=S,t,n){super(),this._config=e,this._injector=t,this._configService=n,I(this,`_internalWorker`,null);let{...r}=f({},S,this._config);this._configService.setConfig(x,r)}dispose(){super.dispose(),this._internalWorker&&(this._internalWorker.terminate(),this._internalWorker=null)}onStarting(){let{workerURL:e}=this._config;if(!e)throw Error(`[UniverRPCMainThreadPlugin]: The workerURL is required for the RPC main thread plugin.`);let t=e instanceof Worker?e:new Worker(e);this._internalWorker=e instanceof Worker?null:t;let n=Z(t);[[W,{useFactory:()=>new G(n)}],[K],[O,{useClass:k}]].forEach(e=>this._injector.add(e)),this._injector.get(K)}};I(Q,`pluginName`,`UNIVER_RPC_MAIN_THREAD_PLUGIN`),I(Q,`packageName`,J),I(Q,`version`,Y),Q=E([T(1,o(s)),T(2,r)],Q);let $=class extends c{constructor(e=w,t,n){super(),this._config=e,this._injector=t,this._configService=n;let{...r}=f({},w,this._config);this._configService.setConfig(C,r)}onStarting(){[[q],[W,{useFactory:()=>new G(X())}],[j,{useClass:M}]].forEach(e=>this._injector.add(e)),this._injector.get(q)}};I($,`pluginName`,`UNIVER_RPC_WORKER_THREAD_PLUGIN`),I($,`packageName`,J),I($,`version`,Y),$=E([T(1,o(s)),T(2,r)],$);export{H as ChannelClient,U as ChannelServer,G as ChannelService,K as DataSyncPrimaryController,q as DataSyncReplicaController,W as IRPCChannelService,j as IRemoteInstanceService,O as IRemoteSyncService,x as PLUGIN_CONFIG_KEY_MAIN_THREAD,C as PLUGIN_CONFIG_KEY_WORKER_THREAD,A as RemoteInstanceServiceName,k as RemoteSyncPrimaryService,D as RemoteSyncServiceName,Q as UniverRPCMainThreadPlugin,$ as UniverRPCWorkerThreadPlugin,M as WebWorkerRemoteInstanceService,L as fromModule,R as toModule};
|
|
1
|
+
import { CommandType, Disposable, ICommandService, IConfigService, ILogService, IUniverInstanceService, Inject, Injector, Plugin, RxDisposable, UniverInstanceType, createIdentifier, merge, toDisposable } from "@univerjs/core";
|
|
2
|
+
import { filter, take, takeUntil } from "rxjs/operators";
|
|
3
|
+
import { BehaviorSubject, Observable, firstValueFrom, isObservable, of, shareReplay } from "rxjs";
|
|
4
|
+
|
|
5
|
+
//#region src/config/config.ts
|
|
6
|
+
/**
|
|
7
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
* you may not use this file except in compliance with the License.
|
|
11
|
+
* You may obtain a copy of the License at
|
|
12
|
+
*
|
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
*
|
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
* See the License for the specific language governing permissions and
|
|
19
|
+
* limitations under the License.
|
|
20
|
+
*/
|
|
21
|
+
const PLUGIN_CONFIG_KEY_MAIN_THREAD = "rpc.main-thread.config";
|
|
22
|
+
const configSymbolMainThread = Symbol(PLUGIN_CONFIG_KEY_MAIN_THREAD);
|
|
23
|
+
const defaultPluginMainThreadConfig = {};
|
|
24
|
+
const PLUGIN_CONFIG_KEY_WORKER_THREAD = "rpc.worker-thread.config";
|
|
25
|
+
const configSymbolWorkerThread = Symbol(PLUGIN_CONFIG_KEY_WORKER_THREAD);
|
|
26
|
+
const defaultPluginWorkerThreadConfig = {};
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region \0@oxc-project+runtime@0.124.0/helpers/decorateParam.js
|
|
30
|
+
function __decorateParam(paramIndex, decorator) {
|
|
31
|
+
return function(target, key) {
|
|
32
|
+
decorator(target, key, paramIndex);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region \0@oxc-project+runtime@0.124.0/helpers/decorate.js
|
|
38
|
+
function __decorate(decorators, target, key, desc) {
|
|
39
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
40
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
41
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
42
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/services/remote-instance/remote-instance.service.ts
|
|
47
|
+
const RemoteSyncServiceName = "rpc.remote-sync.service";
|
|
48
|
+
/**
|
|
49
|
+
* This service is provided by the primary Univer.
|
|
50
|
+
*
|
|
51
|
+
* Replica Univer could call this service to update mutations back to the primary Univer.
|
|
52
|
+
*/
|
|
53
|
+
const IRemoteSyncService = createIdentifier(RemoteSyncServiceName);
|
|
54
|
+
let RemoteSyncPrimaryService = class RemoteSyncPrimaryService {
|
|
55
|
+
constructor(_commandService) {
|
|
56
|
+
this._commandService = _commandService;
|
|
57
|
+
}
|
|
58
|
+
async syncMutation(params, options) {
|
|
59
|
+
const { fromCollab, ...restOptions } = options || {};
|
|
60
|
+
return this._commandService.syncExecuteCommand(params.mutationInfo.id, params.mutationInfo.params, {
|
|
61
|
+
...restOptions,
|
|
62
|
+
onlyLocal: true,
|
|
63
|
+
fromSync: true
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
RemoteSyncPrimaryService = __decorate([__decorateParam(0, ICommandService)], RemoteSyncPrimaryService);
|
|
68
|
+
const RemoteInstanceServiceName = "univer.remote-instance-service";
|
|
69
|
+
/**
|
|
70
|
+
* This service is provided by the replica Univer.
|
|
71
|
+
*
|
|
72
|
+
* Primary univer could call this service to init and dispose univer business instances
|
|
73
|
+
* and sync mutations to replica univer.
|
|
74
|
+
*/
|
|
75
|
+
const IRemoteInstanceService = createIdentifier(RemoteInstanceServiceName);
|
|
76
|
+
let WebWorkerRemoteInstanceService = class WebWorkerRemoteInstanceService {
|
|
77
|
+
constructor(_univerInstanceService, _commandService, _logService) {
|
|
78
|
+
this._univerInstanceService = _univerInstanceService;
|
|
79
|
+
this._commandService = _commandService;
|
|
80
|
+
this._logService = _logService;
|
|
81
|
+
}
|
|
82
|
+
whenReady() {
|
|
83
|
+
return Promise.resolve(true);
|
|
84
|
+
}
|
|
85
|
+
async syncMutation(params, options) {
|
|
86
|
+
return this._applyMutation(params.mutationInfo, options);
|
|
87
|
+
}
|
|
88
|
+
async createInstance(params) {
|
|
89
|
+
this._logService.debug(`[WebWorkerRemoteInstanceService]: Creating instance with id ${params.unitID}`);
|
|
90
|
+
const { type, snapshot } = params;
|
|
91
|
+
try {
|
|
92
|
+
switch (type) {
|
|
93
|
+
case UniverInstanceType.UNIVER_SHEET:
|
|
94
|
+
this._univerInstanceService.createUnit(UniverInstanceType.UNIVER_SHEET, snapshot);
|
|
95
|
+
return true;
|
|
96
|
+
default: throw new Error(`[WebWorkerRemoteInstanceService]: cannot create replica for document type: ${type}.`);
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
if (err instanceof Error) throw err;
|
|
100
|
+
else throw new TypeError(`${err}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async disposeInstance(params) {
|
|
104
|
+
this._logService.debug(`[WebWorkerRemoteInstanceService]: Disposing instance with id ${params.unitID}`);
|
|
105
|
+
return this._univerInstanceService.disposeUnit(params.unitID);
|
|
106
|
+
}
|
|
107
|
+
_applyMutation(mutationInfo, options) {
|
|
108
|
+
const { id, params: mutationParams } = mutationInfo;
|
|
109
|
+
const { fromCollab, ...restOptions } = options || {};
|
|
110
|
+
return this._commandService.syncExecuteCommand(id, mutationParams, {
|
|
111
|
+
...restOptions,
|
|
112
|
+
onlyLocal: true,
|
|
113
|
+
fromSync: true
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
WebWorkerRemoteInstanceService = __decorate([
|
|
118
|
+
__decorateParam(0, IUniverInstanceService),
|
|
119
|
+
__decorateParam(1, ICommandService),
|
|
120
|
+
__decorateParam(2, ILogService)
|
|
121
|
+
], WebWorkerRemoteInstanceService);
|
|
122
|
+
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region \0@oxc-project+runtime@0.124.0/helpers/typeof.js
|
|
125
|
+
function _typeof(o) {
|
|
126
|
+
"@babel/helpers - typeof";
|
|
127
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
128
|
+
return typeof o;
|
|
129
|
+
} : function(o) {
|
|
130
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
131
|
+
}, _typeof(o);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region \0@oxc-project+runtime@0.124.0/helpers/toPrimitive.js
|
|
136
|
+
function toPrimitive(t, r) {
|
|
137
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
138
|
+
var e = t[Symbol.toPrimitive];
|
|
139
|
+
if (void 0 !== e) {
|
|
140
|
+
var i = e.call(t, r || "default");
|
|
141
|
+
if ("object" != _typeof(i)) return i;
|
|
142
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
143
|
+
}
|
|
144
|
+
return ("string" === r ? String : Number)(t);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//#endregion
|
|
148
|
+
//#region \0@oxc-project+runtime@0.124.0/helpers/toPropertyKey.js
|
|
149
|
+
function toPropertyKey(t) {
|
|
150
|
+
var i = toPrimitive(t, "string");
|
|
151
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region \0@oxc-project+runtime@0.124.0/helpers/defineProperty.js
|
|
156
|
+
function _defineProperty(e, r, t) {
|
|
157
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
158
|
+
value: t,
|
|
159
|
+
enumerable: !0,
|
|
160
|
+
configurable: !0,
|
|
161
|
+
writable: !0
|
|
162
|
+
}) : e[r] = t, e;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/services/rpc/rpc.service.ts
|
|
167
|
+
/**
|
|
168
|
+
* Wrapper a service or a controller into a channel so it could be invoked by
|
|
169
|
+
* a remote client. When the protocol is called, it would forward to the
|
|
170
|
+
* underlying service or controller.
|
|
171
|
+
*
|
|
172
|
+
* @param module the wrapper service or controller
|
|
173
|
+
* @returns the channel instance
|
|
174
|
+
*/
|
|
175
|
+
function fromModule(module) {
|
|
176
|
+
const handler = module;
|
|
177
|
+
return new class {
|
|
178
|
+
call(method, args) {
|
|
179
|
+
const target = handler[method];
|
|
180
|
+
if (typeof target === "function") {
|
|
181
|
+
let res = args ? target.apply(handler, args) : target.call(handler);
|
|
182
|
+
if (!(res instanceof Promise)) res = Promise.resolve(res);
|
|
183
|
+
return res;
|
|
184
|
+
}
|
|
185
|
+
throw new Error(`[RPC]: method not found for ${method}!`);
|
|
186
|
+
}
|
|
187
|
+
subscribe(eventMethod, args) {
|
|
188
|
+
const target = handler[eventMethod];
|
|
189
|
+
if (typeof target === "function") {
|
|
190
|
+
const res = args ? target.apply(handler, args) : target.call(handler);
|
|
191
|
+
if (!isObservable(res)) return of(res);
|
|
192
|
+
return res;
|
|
193
|
+
}
|
|
194
|
+
throw new Error(`[RPC]: observable method not found for ${eventMethod}!`);
|
|
195
|
+
}
|
|
196
|
+
}();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Wrap a channel into a service or a controller so it could be invoked by
|
|
200
|
+
* the upper layer modules. When the service or controller is called, it would
|
|
201
|
+
* request the remote server by calling the channel.
|
|
202
|
+
*
|
|
203
|
+
* @param channel
|
|
204
|
+
* @returns A proxy object that forwards calls/subscriptions to the remote channel.
|
|
205
|
+
*/
|
|
206
|
+
function toModule(channel) {
|
|
207
|
+
return new Proxy({}, { get(_, propKey) {
|
|
208
|
+
if (propKey === "dispose") return;
|
|
209
|
+
return function(...args) {
|
|
210
|
+
if (propertyIsEventSource(propKey)) return channel.subscribe(propKey, args);
|
|
211
|
+
return channel.call(propKey, args);
|
|
212
|
+
};
|
|
213
|
+
} });
|
|
214
|
+
}
|
|
215
|
+
function propertyIsEventSource(name) {
|
|
216
|
+
return name.endsWith("$");
|
|
217
|
+
}
|
|
218
|
+
var RequestType = /* @__PURE__ */ function(RequestType) {
|
|
219
|
+
/**
|
|
220
|
+
* In Univer, we cannot make sure that when IPCServer constructs, the process (or thread)
|
|
221
|
+
* where the corresponding IPCClient residents has bootstrapped and been ready to recieve messages.
|
|
222
|
+
* This may result in the IPCClient hanging there, waiting for the `INITIALIZE` message that it has
|
|
223
|
+
* already missed. So the client should send a REQUEST_INITIALIZATION in case of that.
|
|
224
|
+
*
|
|
225
|
+
* Later, we may want a more sophisticated RPC system where the server can serve more than
|
|
226
|
+
* one clients, and this event may be removed.
|
|
227
|
+
*/
|
|
228
|
+
RequestType[RequestType["REQUEST_INITIALIZATION"] = 50] = "REQUEST_INITIALIZATION";
|
|
229
|
+
/** A simple remote calling wrapper in a Promise. */
|
|
230
|
+
RequestType[RequestType["CALL"] = 100] = "CALL";
|
|
231
|
+
/** Subscribe to a remote Observable. */
|
|
232
|
+
RequestType[RequestType["SUBSCRIBE"] = 101] = "SUBSCRIBE";
|
|
233
|
+
/** Cancel subscription to that remove Observable. */
|
|
234
|
+
RequestType[RequestType["UNSUBSCRIBE"] = 102] = "UNSUBSCRIBE";
|
|
235
|
+
return RequestType;
|
|
236
|
+
}(RequestType || {});
|
|
237
|
+
var ResponseType = /* @__PURE__ */ function(ResponseType) {
|
|
238
|
+
/**
|
|
239
|
+
* When underlying protocol is established. The server should send the
|
|
240
|
+
* client an `INITIALIZE` response to indicate that the server is up
|
|
241
|
+
* and ready to provide services.
|
|
242
|
+
*/
|
|
243
|
+
ResponseType[ResponseType["INITIALIZE"] = 0] = "INITIALIZE";
|
|
244
|
+
ResponseType[ResponseType["CALL_SUCCESS"] = 201] = "CALL_SUCCESS";
|
|
245
|
+
ResponseType[ResponseType["CALL_FAILURE"] = 202] = "CALL_FAILURE";
|
|
246
|
+
ResponseType[ResponseType["SUBSCRIBE_NEXT"] = 300] = "SUBSCRIBE_NEXT";
|
|
247
|
+
ResponseType[ResponseType["SUBSCRIBE_ERROR"] = 301] = "SUBSCRIBE_ERROR";
|
|
248
|
+
ResponseType[ResponseType["SUBSCRIBE_COMPLETE"] = 302] = "SUBSCRIBE_COMPLETE";
|
|
249
|
+
return ResponseType;
|
|
250
|
+
}(ResponseType || {});
|
|
251
|
+
/**
|
|
252
|
+
* This method provides implementation for `IChannel` and is responsible for
|
|
253
|
+
* transforming a local calling to a RPC calling.
|
|
254
|
+
*/
|
|
255
|
+
var ChannelClient = class extends RxDisposable {
|
|
256
|
+
constructor(_protocol) {
|
|
257
|
+
super();
|
|
258
|
+
this._protocol = _protocol;
|
|
259
|
+
_defineProperty(this, "_initialized", new BehaviorSubject(false));
|
|
260
|
+
_defineProperty(this, "_lastRequestCounter", 0);
|
|
261
|
+
_defineProperty(this, "_pendingRequests", /* @__PURE__ */ new Map());
|
|
262
|
+
this._protocol.send({ type: RequestType.REQUEST_INITIALIZATION });
|
|
263
|
+
this._protocol.onMessage.pipe(takeUntil(this.dispose$)).subscribe((message) => this._onMessage(message));
|
|
264
|
+
}
|
|
265
|
+
dispose() {
|
|
266
|
+
this._pendingRequests.clear();
|
|
267
|
+
}
|
|
268
|
+
getChannel(channelName) {
|
|
269
|
+
return {
|
|
270
|
+
call: (method, args) => {
|
|
271
|
+
if (this._disposed) return Promise.reject(/* @__PURE__ */ new Error("[ChannelClient]: client is disposed!"));
|
|
272
|
+
return this._remoteCall(channelName, method, args);
|
|
273
|
+
},
|
|
274
|
+
subscribe: (eventMethod, args) => {
|
|
275
|
+
if (this._disposed) throw new Error("[ChannelClient]: client is disposed!");
|
|
276
|
+
return this._remoteSubscribe(channelName, eventMethod, args);
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
_whenReady() {
|
|
281
|
+
return firstValueFrom(this._initialized.pipe(filter((v) => v), take(1)));
|
|
282
|
+
}
|
|
283
|
+
_remoteCall(channelName, method, args) {
|
|
284
|
+
if (this._initialized.getValue()) return this._doRemoteCall(channelName, method, args);
|
|
285
|
+
return this._whenReady().then(() => this._doRemoteCall(channelName, method, args));
|
|
286
|
+
}
|
|
287
|
+
_doRemoteCall(channelName, method, args) {
|
|
288
|
+
const sequence = ++this._lastRequestCounter;
|
|
289
|
+
const request = {
|
|
290
|
+
seq: sequence,
|
|
291
|
+
type: RequestType.CALL,
|
|
292
|
+
channelName,
|
|
293
|
+
method,
|
|
294
|
+
args
|
|
295
|
+
};
|
|
296
|
+
const pendingRequests = this._pendingRequests;
|
|
297
|
+
return new Promise((resolve, reject) => {
|
|
298
|
+
this._pendingRequests.set(sequence, { handle(response) {
|
|
299
|
+
switch (response.type) {
|
|
300
|
+
case ResponseType.CALL_SUCCESS:
|
|
301
|
+
pendingRequests.delete(sequence);
|
|
302
|
+
resolve(response.data);
|
|
303
|
+
break;
|
|
304
|
+
case ResponseType.CALL_FAILURE:
|
|
305
|
+
pendingRequests.delete(sequence);
|
|
306
|
+
reject(response.data);
|
|
307
|
+
break;
|
|
308
|
+
default: throw new Error("[ChannelClient]: unknown response type!");
|
|
309
|
+
}
|
|
310
|
+
} });
|
|
311
|
+
this._sendRequest(request);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
_remoteSubscribe(channelName, method, args) {
|
|
315
|
+
return new Observable((subscriber) => {
|
|
316
|
+
let sequence = -1;
|
|
317
|
+
const doSubscribe = () => {
|
|
318
|
+
sequence = ++this._lastRequestCounter;
|
|
319
|
+
const type = RequestType.SUBSCRIBE;
|
|
320
|
+
const request = {
|
|
321
|
+
seq: sequence,
|
|
322
|
+
type,
|
|
323
|
+
channelName,
|
|
324
|
+
method,
|
|
325
|
+
args
|
|
326
|
+
};
|
|
327
|
+
this._pendingRequests.set(sequence, { handle(response) {
|
|
328
|
+
switch (response.type) {
|
|
329
|
+
case ResponseType.SUBSCRIBE_NEXT:
|
|
330
|
+
subscriber.next(response.data);
|
|
331
|
+
break;
|
|
332
|
+
case ResponseType.SUBSCRIBE_ERROR:
|
|
333
|
+
subscriber.error(response.data);
|
|
334
|
+
break;
|
|
335
|
+
case ResponseType.SUBSCRIBE_COMPLETE:
|
|
336
|
+
subscriber.complete();
|
|
337
|
+
break;
|
|
338
|
+
default: throw new Error("[ChannelClient]: unknown response type!");
|
|
339
|
+
}
|
|
340
|
+
} });
|
|
341
|
+
this._sendRequest(request);
|
|
342
|
+
};
|
|
343
|
+
if (this._initialized.getValue()) doSubscribe();
|
|
344
|
+
else this._whenReady().then(doSubscribe);
|
|
345
|
+
return () => {
|
|
346
|
+
if (sequence === -1) return;
|
|
347
|
+
const cancelSubscriptionRequest = {
|
|
348
|
+
type: RequestType.UNSUBSCRIBE,
|
|
349
|
+
seq: sequence,
|
|
350
|
+
channelName,
|
|
351
|
+
method
|
|
352
|
+
};
|
|
353
|
+
this._sendRequest(cancelSubscriptionRequest);
|
|
354
|
+
};
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
_sendRequest(request) {
|
|
358
|
+
this._protocol.send(request);
|
|
359
|
+
}
|
|
360
|
+
_onMessage(response) {
|
|
361
|
+
const { type: responseType, seq } = response;
|
|
362
|
+
switch (responseType) {
|
|
363
|
+
case ResponseType.INITIALIZE:
|
|
364
|
+
this._initialized.next(true);
|
|
365
|
+
break;
|
|
366
|
+
case ResponseType.CALL_SUCCESS:
|
|
367
|
+
case ResponseType.CALL_FAILURE:
|
|
368
|
+
case ResponseType.SUBSCRIBE_NEXT:
|
|
369
|
+
case ResponseType.SUBSCRIBE_COMPLETE:
|
|
370
|
+
case ResponseType.SUBSCRIBE_ERROR: {
|
|
371
|
+
var _pendingRequests$get;
|
|
372
|
+
const { _pendingRequests } = this;
|
|
373
|
+
(_pendingRequests$get = _pendingRequests.get(seq)) === null || _pendingRequests$get === void 0 || _pendingRequests$get.handle(response);
|
|
374
|
+
responseType !== ResponseType.SUBSCRIBE_NEXT && _pendingRequests.delete(seq);
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
var ChannelServer = class extends RxDisposable {
|
|
381
|
+
constructor(_protocol) {
|
|
382
|
+
super();
|
|
383
|
+
this._protocol = _protocol;
|
|
384
|
+
_defineProperty(this, "_channels", /* @__PURE__ */ new Map());
|
|
385
|
+
_defineProperty(this, "_subscriptions", /* @__PURE__ */ new Map());
|
|
386
|
+
this._protocol.onMessage.pipe(takeUntil(this.dispose$)).subscribe((message) => this._onRequest(message));
|
|
387
|
+
this._sendInitialize();
|
|
388
|
+
}
|
|
389
|
+
dispose() {
|
|
390
|
+
super.dispose();
|
|
391
|
+
this._subscriptions.clear();
|
|
392
|
+
this._channels.clear();
|
|
393
|
+
}
|
|
394
|
+
registerChannel(channelName, channel) {
|
|
395
|
+
this._channels.set(channelName, channel);
|
|
396
|
+
}
|
|
397
|
+
_onRequest(request) {
|
|
398
|
+
switch (request.type) {
|
|
399
|
+
case RequestType.REQUEST_INITIALIZATION:
|
|
400
|
+
this._sendInitialize();
|
|
401
|
+
break;
|
|
402
|
+
case RequestType.CALL:
|
|
403
|
+
this._onMethodCall(request);
|
|
404
|
+
break;
|
|
405
|
+
case RequestType.SUBSCRIBE:
|
|
406
|
+
this._onSubscribe(request);
|
|
407
|
+
break;
|
|
408
|
+
case RequestType.UNSUBSCRIBE:
|
|
409
|
+
this._onUnsubscribe(request);
|
|
410
|
+
break;
|
|
411
|
+
default: break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
_sendInitialize() {
|
|
415
|
+
this._sendResponse({
|
|
416
|
+
seq: -1,
|
|
417
|
+
type: ResponseType.INITIALIZE
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
_onMethodCall(request) {
|
|
421
|
+
const { channelName, method, args } = request;
|
|
422
|
+
const channel = this._channels.get(channelName);
|
|
423
|
+
let promise;
|
|
424
|
+
try {
|
|
425
|
+
if (!channel) throw new Error(`[ChannelServer]: Channel ${channelName} not found!`);
|
|
426
|
+
promise = args ? channel.call(method, args) : channel.call(method);
|
|
427
|
+
} catch (err) {
|
|
428
|
+
promise = Promise.reject(err instanceof Error ? err : new Error(String(err)));
|
|
429
|
+
}
|
|
430
|
+
promise.then((data) => {
|
|
431
|
+
this._sendResponse({
|
|
432
|
+
seq: request.seq,
|
|
433
|
+
type: ResponseType.CALL_SUCCESS,
|
|
434
|
+
data
|
|
435
|
+
});
|
|
436
|
+
}).catch((err) => {
|
|
437
|
+
if (err instanceof Error) this._sendResponse({
|
|
438
|
+
seq: request.seq,
|
|
439
|
+
type: ResponseType.CALL_FAILURE,
|
|
440
|
+
data: err.message
|
|
441
|
+
});
|
|
442
|
+
else this._sendResponse({
|
|
443
|
+
seq: request.seq,
|
|
444
|
+
type: ResponseType.CALL_FAILURE,
|
|
445
|
+
data: String(err)
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
_onSubscribe(request) {
|
|
450
|
+
const { channelName, seq } = request;
|
|
451
|
+
const channel = this._channels.get(channelName);
|
|
452
|
+
try {
|
|
453
|
+
if (!channel) throw new Error(`[ChannelServer]: Channel ${channelName} not found!`);
|
|
454
|
+
const subscription = channel.subscribe(request.method, request.args).subscribe({
|
|
455
|
+
next: (data) => {
|
|
456
|
+
this._sendResponse({
|
|
457
|
+
seq,
|
|
458
|
+
type: ResponseType.SUBSCRIBE_NEXT,
|
|
459
|
+
data
|
|
460
|
+
});
|
|
461
|
+
},
|
|
462
|
+
error: (err) => {
|
|
463
|
+
this._sendResponse({
|
|
464
|
+
seq,
|
|
465
|
+
type: ResponseType.SUBSCRIBE_ERROR,
|
|
466
|
+
data: err.message
|
|
467
|
+
});
|
|
468
|
+
this._sendResponse({
|
|
469
|
+
seq,
|
|
470
|
+
type: ResponseType.SUBSCRIBE_COMPLETE
|
|
471
|
+
});
|
|
472
|
+
},
|
|
473
|
+
complete: () => {
|
|
474
|
+
this._sendResponse({
|
|
475
|
+
seq,
|
|
476
|
+
type: ResponseType.SUBSCRIBE_COMPLETE
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
this._subscriptions.set(request.seq, subscription);
|
|
481
|
+
} catch (err) {
|
|
482
|
+
if (err instanceof Error) this._sendResponse({
|
|
483
|
+
seq: request.seq,
|
|
484
|
+
type: ResponseType.SUBSCRIBE_ERROR,
|
|
485
|
+
data: err.message
|
|
486
|
+
});
|
|
487
|
+
else this._sendResponse({
|
|
488
|
+
seq: request.seq,
|
|
489
|
+
type: ResponseType.SUBSCRIBE_ERROR,
|
|
490
|
+
data: String(err)
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
_onUnsubscribe(request) {
|
|
495
|
+
const subscription = this._subscriptions.get(request.seq);
|
|
496
|
+
if (subscription) {
|
|
497
|
+
subscription.unsubscribe();
|
|
498
|
+
this._subscriptions.delete(request.seq);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
_sendResponse(response) {
|
|
502
|
+
this._protocol.send(response);
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
//#endregion
|
|
507
|
+
//#region src/services/rpc/channel.service.ts
|
|
508
|
+
const IRPCChannelService = createIdentifier("IRPCChannelService");
|
|
509
|
+
/**
|
|
510
|
+
* This service is responsible for managing the RPC channels.
|
|
511
|
+
*/
|
|
512
|
+
var ChannelService = class {
|
|
513
|
+
constructor(_messageProtocol) {
|
|
514
|
+
_defineProperty(this, "_client", void 0);
|
|
515
|
+
_defineProperty(this, "_server", void 0);
|
|
516
|
+
this._client = new ChannelClient(_messageProtocol);
|
|
517
|
+
this._server = new ChannelServer(_messageProtocol);
|
|
518
|
+
}
|
|
519
|
+
dispose() {
|
|
520
|
+
this._client.dispose();
|
|
521
|
+
this._server.dispose();
|
|
522
|
+
}
|
|
523
|
+
requestChannel(name) {
|
|
524
|
+
return this._client.getChannel(name);
|
|
525
|
+
}
|
|
526
|
+
registerChannel(name, channel) {
|
|
527
|
+
this._server.registerChannel(name, channel);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/controllers/data-sync/data-sync-primary.controller.ts
|
|
533
|
+
let DataSyncPrimaryController = class DataSyncPrimaryController extends RxDisposable {
|
|
534
|
+
constructor(_injector, _commandService, _univerInstanceService, _rpcChannelService, _remoteSyncService) {
|
|
535
|
+
super();
|
|
536
|
+
this._injector = _injector;
|
|
537
|
+
this._commandService = _commandService;
|
|
538
|
+
this._univerInstanceService = _univerInstanceService;
|
|
539
|
+
this._rpcChannelService = _rpcChannelService;
|
|
540
|
+
this._remoteSyncService = _remoteSyncService;
|
|
541
|
+
_defineProperty(this, "_remoteInstanceService", void 0);
|
|
542
|
+
_defineProperty(this, "_syncingUnits", /* @__PURE__ */ new Set());
|
|
543
|
+
_defineProperty(this, "_syncingMutations", /* @__PURE__ */ new Set());
|
|
544
|
+
this._initRPCChannels();
|
|
545
|
+
this._init();
|
|
546
|
+
}
|
|
547
|
+
registerSyncingMutations(mutation) {
|
|
548
|
+
this._syncingMutations.add(mutation.id);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Only spreadsheets would be synced to the web worker in normal situations. If you would like to
|
|
552
|
+
* sync other types of documents, you should manually call this method with that document's id.
|
|
553
|
+
*/
|
|
554
|
+
syncUnit(unitId) {
|
|
555
|
+
this._syncingUnits.add(unitId);
|
|
556
|
+
return toDisposable(() => this._syncingUnits.delete(unitId));
|
|
557
|
+
}
|
|
558
|
+
_initRPCChannels() {
|
|
559
|
+
this._rpcChannelService.registerChannel(RemoteSyncServiceName, fromModule(this._remoteSyncService));
|
|
560
|
+
this._injector.add([IRemoteInstanceService, { useFactory: () => toModule(this._rpcChannelService.requestChannel(RemoteInstanceServiceName)) }]);
|
|
561
|
+
this._remoteInstanceService = this._injector.get(IRemoteInstanceService);
|
|
562
|
+
}
|
|
563
|
+
_init() {
|
|
564
|
+
this._univerInstanceService.getTypeOfUnitAdded$(UniverInstanceType.UNIVER_SHEET).pipe(takeUntil(this.dispose$)).subscribe((sheet) => {
|
|
565
|
+
this._syncingUnits.add(sheet.getUnitId());
|
|
566
|
+
this._remoteInstanceService.createInstance({
|
|
567
|
+
unitID: sheet.getUnitId(),
|
|
568
|
+
type: UniverInstanceType.UNIVER_SHEET,
|
|
569
|
+
snapshot: sheet.getSnapshot()
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
this._univerInstanceService.getTypeOfUnitDisposed$(UniverInstanceType.UNIVER_SHEET).pipe(takeUntil(this.dispose$)).subscribe((workbook) => {
|
|
573
|
+
this._syncingUnits.delete(workbook.getUnitId());
|
|
574
|
+
this._remoteInstanceService.disposeInstance({ unitID: workbook.getUnitId() });
|
|
575
|
+
});
|
|
576
|
+
this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo, options) => {
|
|
577
|
+
const { type, params, id } = commandInfo;
|
|
578
|
+
const unitId = (params === null || params === void 0 ? void 0 : params.unitId) || "";
|
|
579
|
+
if (type === CommandType.MUTATION && (!unitId || this._syncingUnits.has(unitId)) && !(options === null || options === void 0 ? void 0 : options.fromSync) && this._syncingMutations.has(id)) this._remoteInstanceService.syncMutation({ mutationInfo: commandInfo }, options);
|
|
580
|
+
}));
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
DataSyncPrimaryController = __decorate([
|
|
584
|
+
__decorateParam(0, Inject(Injector)),
|
|
585
|
+
__decorateParam(1, ICommandService),
|
|
586
|
+
__decorateParam(2, IUniverInstanceService),
|
|
587
|
+
__decorateParam(3, IRPCChannelService),
|
|
588
|
+
__decorateParam(4, IRemoteSyncService)
|
|
589
|
+
], DataSyncPrimaryController);
|
|
590
|
+
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region src/controllers/data-sync/data-sync-replica.controller.ts
|
|
593
|
+
let DataSyncReplicaController = class DataSyncReplicaController extends Disposable {
|
|
594
|
+
constructor(_injector, _remoteInstanceService, _commandService, _rpcChannelService) {
|
|
595
|
+
super();
|
|
596
|
+
this._injector = _injector;
|
|
597
|
+
this._remoteInstanceService = _remoteInstanceService;
|
|
598
|
+
this._commandService = _commandService;
|
|
599
|
+
this._rpcChannelService = _rpcChannelService;
|
|
600
|
+
_defineProperty(this, "_remoteSyncService", void 0);
|
|
601
|
+
this._initRPCChannels();
|
|
602
|
+
this._init();
|
|
603
|
+
}
|
|
604
|
+
_initRPCChannels() {
|
|
605
|
+
this._rpcChannelService.registerChannel(RemoteInstanceServiceName, fromModule(this._remoteInstanceService));
|
|
606
|
+
this._injector.add([IRemoteSyncService, { useFactory: () => toModule(this._rpcChannelService.requestChannel(RemoteSyncServiceName)) }]);
|
|
607
|
+
this._remoteSyncService = this._injector.get(IRemoteSyncService);
|
|
608
|
+
}
|
|
609
|
+
_init() {
|
|
610
|
+
this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo, options) => {
|
|
611
|
+
if (commandInfo.type === CommandType.MUTATION && !(options === null || options === void 0 ? void 0 : options.fromSync)) this._remoteSyncService.syncMutation({ mutationInfo: commandInfo }, options);
|
|
612
|
+
}));
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
DataSyncReplicaController = __decorate([
|
|
616
|
+
__decorateParam(0, Inject(Injector)),
|
|
617
|
+
__decorateParam(1, IRemoteInstanceService),
|
|
618
|
+
__decorateParam(2, ICommandService),
|
|
619
|
+
__decorateParam(3, IRPCChannelService)
|
|
620
|
+
], DataSyncReplicaController);
|
|
621
|
+
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region package.json
|
|
624
|
+
var name = "@univerjs/rpc";
|
|
625
|
+
var version = "0.21.0";
|
|
626
|
+
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region src/services/rpc/implementations/web-worker-rpc.service.ts
|
|
629
|
+
/**
|
|
630
|
+
* Generate an `IMessageProtocol` on the web worker.
|
|
631
|
+
* @returns A protocol wrapper around worker global messaging APIs.
|
|
632
|
+
*/
|
|
633
|
+
function createWebWorkerMessagePortOnWorker() {
|
|
634
|
+
return {
|
|
635
|
+
send(message) {
|
|
636
|
+
postMessage(message);
|
|
637
|
+
},
|
|
638
|
+
onMessage: new Observable((subscriber) => {
|
|
639
|
+
const handler = (event) => {
|
|
640
|
+
subscriber.next(event.data);
|
|
641
|
+
};
|
|
642
|
+
addEventListener("message", handler);
|
|
643
|
+
return () => removeEventListener("message", handler);
|
|
644
|
+
}).pipe(shareReplay(1))
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Generate an `IMessageProtocol` on the main thread side.
|
|
649
|
+
* @param worker The Web Worker object
|
|
650
|
+
* @returns A protocol wrapper around the given worker messaging APIs.
|
|
651
|
+
*/
|
|
652
|
+
function createWebWorkerMessagePortOnMain(worker) {
|
|
653
|
+
return {
|
|
654
|
+
send(message) {
|
|
655
|
+
worker.postMessage(message);
|
|
656
|
+
},
|
|
657
|
+
onMessage: new Observable((subscriber) => {
|
|
658
|
+
const handler = (event) => {
|
|
659
|
+
subscriber.next(event.data);
|
|
660
|
+
};
|
|
661
|
+
worker.addEventListener("message", handler);
|
|
662
|
+
return () => worker.removeEventListener("message", handler);
|
|
663
|
+
}).pipe(shareReplay(1))
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
//#endregion
|
|
668
|
+
//#region src/plugin.ts
|
|
669
|
+
let UniverRPCMainThreadPlugin = class UniverRPCMainThreadPlugin extends Plugin {
|
|
670
|
+
constructor(_config = defaultPluginMainThreadConfig, _injector, _configService) {
|
|
671
|
+
super();
|
|
672
|
+
this._config = _config;
|
|
673
|
+
this._injector = _injector;
|
|
674
|
+
this._configService = _configService;
|
|
675
|
+
_defineProperty(this, "_internalWorker", null);
|
|
676
|
+
const { ...rest } = merge({}, defaultPluginMainThreadConfig, this._config);
|
|
677
|
+
this._configService.setConfig(PLUGIN_CONFIG_KEY_MAIN_THREAD, rest);
|
|
678
|
+
}
|
|
679
|
+
dispose() {
|
|
680
|
+
super.dispose();
|
|
681
|
+
if (this._internalWorker) {
|
|
682
|
+
this._internalWorker.terminate();
|
|
683
|
+
this._internalWorker = null;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
onStarting() {
|
|
687
|
+
const { workerURL } = this._config;
|
|
688
|
+
if (!workerURL) throw new Error("[UniverRPCMainThreadPlugin]: The workerURL is required for the RPC main thread plugin.");
|
|
689
|
+
const worker = workerURL instanceof Worker ? workerURL : new Worker(workerURL);
|
|
690
|
+
this._internalWorker = workerURL instanceof Worker ? null : worker;
|
|
691
|
+
const messageProtocol = createWebWorkerMessagePortOnMain(worker);
|
|
692
|
+
[
|
|
693
|
+
[IRPCChannelService, { useFactory: () => new ChannelService(messageProtocol) }],
|
|
694
|
+
[DataSyncPrimaryController],
|
|
695
|
+
[IRemoteSyncService, { useClass: RemoteSyncPrimaryService }]
|
|
696
|
+
].forEach((dependency) => this._injector.add(dependency));
|
|
697
|
+
this._injector.get(DataSyncPrimaryController);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
_defineProperty(UniverRPCMainThreadPlugin, "pluginName", "UNIVER_RPC_MAIN_THREAD_PLUGIN");
|
|
701
|
+
_defineProperty(UniverRPCMainThreadPlugin, "packageName", name);
|
|
702
|
+
_defineProperty(UniverRPCMainThreadPlugin, "version", version);
|
|
703
|
+
UniverRPCMainThreadPlugin = __decorate([__decorateParam(1, Inject(Injector)), __decorateParam(2, IConfigService)], UniverRPCMainThreadPlugin);
|
|
704
|
+
let UniverRPCWorkerThreadPlugin = class UniverRPCWorkerThreadPlugin extends Plugin {
|
|
705
|
+
constructor(_config = defaultPluginWorkerThreadConfig, _injector, _configService) {
|
|
706
|
+
super();
|
|
707
|
+
this._config = _config;
|
|
708
|
+
this._injector = _injector;
|
|
709
|
+
this._configService = _configService;
|
|
710
|
+
const { ...rest } = merge({}, defaultPluginWorkerThreadConfig, this._config);
|
|
711
|
+
this._configService.setConfig(PLUGIN_CONFIG_KEY_WORKER_THREAD, rest);
|
|
712
|
+
}
|
|
713
|
+
onStarting() {
|
|
714
|
+
[
|
|
715
|
+
[DataSyncReplicaController],
|
|
716
|
+
[IRPCChannelService, { useFactory: () => new ChannelService(createWebWorkerMessagePortOnWorker()) }],
|
|
717
|
+
[IRemoteInstanceService, { useClass: WebWorkerRemoteInstanceService }]
|
|
718
|
+
].forEach((dependency) => this._injector.add(dependency));
|
|
719
|
+
this._injector.get(DataSyncReplicaController);
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
_defineProperty(UniverRPCWorkerThreadPlugin, "pluginName", "UNIVER_RPC_WORKER_THREAD_PLUGIN");
|
|
723
|
+
_defineProperty(UniverRPCWorkerThreadPlugin, "packageName", name);
|
|
724
|
+
_defineProperty(UniverRPCWorkerThreadPlugin, "version", version);
|
|
725
|
+
UniverRPCWorkerThreadPlugin = __decorate([__decorateParam(1, Inject(Injector)), __decorateParam(2, IConfigService)], UniverRPCWorkerThreadPlugin);
|
|
726
|
+
|
|
727
|
+
//#endregion
|
|
728
|
+
export { ChannelClient, ChannelServer, ChannelService, DataSyncPrimaryController, DataSyncReplicaController, IRPCChannelService, IRemoteInstanceService, IRemoteSyncService, PLUGIN_CONFIG_KEY_MAIN_THREAD, PLUGIN_CONFIG_KEY_WORKER_THREAD, RemoteInstanceServiceName, RemoteSyncPrimaryService, RemoteSyncServiceName, UniverRPCMainThreadPlugin, UniverRPCWorkerThreadPlugin, WebWorkerRemoteInstanceService, fromModule, toModule };
|