@hydranium/protocol 1.0.0-next.63 → 1.0.0-next.66
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/client/data-connection.d.ts +30 -3
- package/lib/client/data-connection.d.ts.map +1 -1
- package/lib/client/data-connection.js +45 -4
- package/lib/client/data-connection.js.map +1 -1
- package/lib/client/index.d.ts +5 -5
- package/lib/client/index.js +5 -5
- package/lib/client/rpc-connection.d.ts +18 -3
- package/lib/client/rpc-connection.d.ts.map +1 -1
- package/lib/client/rpc-connection.js +18 -2
- package/lib/client/rpc-connection.js.map +1 -1
- package/lib/client-ids.d.ts +41 -0
- package/lib/client-ids.d.ts.map +1 -0
- package/lib/client-ids.js +44 -0
- package/lib/client-ids.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/data-connection.ts +49 -3
- package/src/client/index.ts +5 -5
- package/src/client/rpc-connection.ts +21 -4
- package/src/client-ids.ts +45 -0
- package/src/index.ts +1 -0
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
import { type DataClientProtocol, type DataServerProtocol } from '../data';
|
|
10
10
|
import type { TransferElement } from '../transfer-element';
|
|
11
|
+
import { DataEvents } from './data-events';
|
|
11
12
|
import type { DataPort } from './data-port';
|
|
12
13
|
import { DataSession } from './data-session';
|
|
13
14
|
import { RpcConnection, type RpcConnectionLifecycle } from './rpc-connection';
|
|
@@ -61,9 +62,13 @@ export declare class DataConnection<TTransfer extends TransferElement, TServer e
|
|
|
61
62
|
*
|
|
62
63
|
* `clientId` must be distinct per participant and stable for its lifetime:
|
|
63
64
|
* it keys the server's per-`(uri, clientId)` hold and watch, and it is the
|
|
64
|
-
* echo key an inbound `onDocumentUpdated` is matched against.
|
|
65
|
-
*
|
|
66
|
-
*
|
|
65
|
+
* echo key an inbound `onDocumentUpdated` is matched against.
|
|
66
|
+
*
|
|
67
|
+
* Throws for an id in {@link FRAMEWORK_CLIENT_IDS} — those are authors the
|
|
68
|
+
* SERVER emits rather than participants, so a session holding one would read
|
|
69
|
+
* the framework's own broadcasts as its own echoes and drop them. Nothing
|
|
70
|
+
* about that fails on its own: the document simply stops following, which
|
|
71
|
+
* looks like a dead connection.
|
|
67
72
|
*/
|
|
68
73
|
createSession(clientId: string): DataSession<TTransfer, TServer>;
|
|
69
74
|
/**
|
|
@@ -73,4 +78,26 @@ export declare class DataConnection<TTransfer extends TransferElement, TServer e
|
|
|
73
78
|
*/
|
|
74
79
|
dispose(): void;
|
|
75
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* A {@link DataConnection} that brings its own {@link DataEvents}, so a host
|
|
83
|
+
* with several interested parties does not have to supply one.
|
|
84
|
+
*
|
|
85
|
+
* **The client slot holds exactly one object, and that is why this exists.**
|
|
86
|
+
* `createRpcProxy` binds a single `localTarget`, and underneath a method name
|
|
87
|
+
* maps to one handler — a second registration replaces the first silently. So a
|
|
88
|
+
* properties panel and a tree cannot both be the client; one fan-out sits in the
|
|
89
|
+
* slot and both subscribe to it.
|
|
90
|
+
*
|
|
91
|
+
* Use {@link DataConnection} directly instead when the client is yours: an
|
|
92
|
+
* adopter service that implements the protocol plus its own methods, a single
|
|
93
|
+
* consumer that IS the client, or a request/response-only client that binds
|
|
94
|
+
* nothing.
|
|
95
|
+
*/
|
|
96
|
+
export declare class DataConnectionWithEvents<TTransfer extends TransferElement, TServer extends DataServerProtocol<TTransfer> = DataServerProtocol<TTransfer>> extends DataConnection<TTransfer, TServer, DataEvents<TTransfer>> {
|
|
97
|
+
/** Server pushes, fanned out to as many local listeners as the host has. */
|
|
98
|
+
readonly events: DataEvents<TTransfer>;
|
|
99
|
+
constructor(port: DataPort, options?: DataConnectionOptions);
|
|
100
|
+
/** Disposes the fan-out it created, which no caller else holds. */
|
|
101
|
+
dispose(): void;
|
|
102
|
+
}
|
|
76
103
|
//# sourceMappingURL=data-connection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-connection.d.ts","sourceRoot":"","sources":["../../src/client/data-connection.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;
|
|
1
|
+
{"version":3,"file":"data-connection.d.ts","sourceRoot":"","sources":["../../src/client/data-connection.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAyD,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClI,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE9E,0CAA0C;AAC1C,MAAM,WAAW,qBAAsB,SAAQ,sBAAsB;IAClE;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,iGAAiG;AACjG,MAAM,WAAW,gCAAgC,CAAC,OAAO,SAAS,MAAM,CAAE,SAAQ,qBAAqB;IACpG;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;CAC9D;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,CAAC,SAAS,SAAS,eAAe,EAAE,OAAO,SAAS,MAAM,IACrF,OAAO,SAAS,kBAAkB,CAAC,SAAS,CAAC,GACxC,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,gCAAgC,CAAC,OAAO,CAAC,CAAC,CAAC,GACtF,CAAC,OAAO,EAAE,gCAAgC,CAAC,OAAO,CAAC,CAAC,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc,CACxB,SAAS,SAAS,eAAe,EACjC,OAAO,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,kBAAkB,CAAC,SAAS,CAAC,EAC7E,OAAO,SAAS,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,CACvD,SAAQ,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC;IACtC,SAAS,CAAC,QAAQ,CAAC,QAAQ,uCAA8C;gBAE7D,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC;IAY5F;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;IAahE;;;;OAIG;IACM,OAAO,IAAI,IAAI;CAO1B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,wBAAwB,CAClC,SAAS,SAAS,eAAe,EACjC,OAAO,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAC9E,SAAQ,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChE,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;gBAE3B,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAQ3D,mEAAmE;IAC1D,OAAO,IAAI,IAAI;CAI1B"}
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
* SPDX-License-Identifier: MIT
|
|
9
9
|
********************************************************************************/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.DataConnection = void 0;
|
|
11
|
+
exports.DataConnectionWithEvents = exports.DataConnection = void 0;
|
|
12
|
+
const client_ids_1 = require("../client-ids");
|
|
12
13
|
const data_1 = require("../data");
|
|
14
|
+
const data_events_1 = require("./data-events");
|
|
13
15
|
const data_session_1 = require("./data-session");
|
|
14
16
|
const rpc_connection_1 = require("./rpc-connection");
|
|
15
17
|
/**
|
|
@@ -43,12 +45,19 @@ class DataConnection extends rpc_connection_1.RpcConnection {
|
|
|
43
45
|
*
|
|
44
46
|
* `clientId` must be distinct per participant and stable for its lifetime:
|
|
45
47
|
* it keys the server's per-`(uri, clientId)` hold and watch, and it is the
|
|
46
|
-
* echo key an inbound `onDocumentUpdated` is matched against.
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* echo key an inbound `onDocumentUpdated` is matched against.
|
|
49
|
+
*
|
|
50
|
+
* Throws for an id in {@link FRAMEWORK_CLIENT_IDS} — those are authors the
|
|
51
|
+
* SERVER emits rather than participants, so a session holding one would read
|
|
52
|
+
* the framework's own broadcasts as its own echoes and drop them. Nothing
|
|
53
|
+
* about that fails on its own: the document simply stops following, which
|
|
54
|
+
* looks like a dead connection.
|
|
49
55
|
*/
|
|
50
56
|
createSession(clientId) {
|
|
51
57
|
this.assertLive();
|
|
58
|
+
if (client_ids_1.FRAMEWORK_CLIENT_IDS.includes(clientId)) {
|
|
59
|
+
throw new Error(`clientId '${clientId}' is reserved by the framework and cannot identify a participant`);
|
|
60
|
+
}
|
|
52
61
|
const session = new data_session_1.DataSession(clientId, {
|
|
53
62
|
connected: () => this.connected(),
|
|
54
63
|
releaseSession: released => this.sessions.delete(released)
|
|
@@ -70,4 +79,36 @@ class DataConnection extends rpc_connection_1.RpcConnection {
|
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
81
|
exports.DataConnection = DataConnection;
|
|
82
|
+
/**
|
|
83
|
+
* A {@link DataConnection} that brings its own {@link DataEvents}, so a host
|
|
84
|
+
* with several interested parties does not have to supply one.
|
|
85
|
+
*
|
|
86
|
+
* **The client slot holds exactly one object, and that is why this exists.**
|
|
87
|
+
* `createRpcProxy` binds a single `localTarget`, and underneath a method name
|
|
88
|
+
* maps to one handler — a second registration replaces the first silently. So a
|
|
89
|
+
* properties panel and a tree cannot both be the client; one fan-out sits in the
|
|
90
|
+
* slot and both subscribe to it.
|
|
91
|
+
*
|
|
92
|
+
* Use {@link DataConnection} directly instead when the client is yours: an
|
|
93
|
+
* adopter service that implements the protocol plus its own methods, a single
|
|
94
|
+
* consumer that IS the client, or a request/response-only client that binds
|
|
95
|
+
* nothing.
|
|
96
|
+
*/
|
|
97
|
+
class DataConnectionWithEvents extends DataConnection {
|
|
98
|
+
/** Server pushes, fanned out to as many local listeners as the host has. */
|
|
99
|
+
events;
|
|
100
|
+
constructor(port, options) {
|
|
101
|
+
// Built as a local because `this` is unavailable before `super`, then
|
|
102
|
+
// read back onto the field.
|
|
103
|
+
const events = new data_events_1.DataEvents();
|
|
104
|
+
super(port, events, options);
|
|
105
|
+
this.events = events;
|
|
106
|
+
}
|
|
107
|
+
/** Disposes the fan-out it created, which no caller else holds. */
|
|
108
|
+
dispose() {
|
|
109
|
+
super.dispose();
|
|
110
|
+
this.events.dispose();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.DataConnectionWithEvents = DataConnectionWithEvents;
|
|
73
114
|
//# sourceMappingURL=data-connection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-connection.js","sourceRoot":"","sources":["../../src/client/data-connection.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,kCAAkI;
|
|
1
|
+
{"version":3,"file":"data-connection.js","sourceRoot":"","sources":["../../src/client/data-connection.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,8CAAqD;AACrD,kCAAkI;AAElI,+CAA2C;AAE3C,iDAA6C;AAC7C,qDAA8E;AAqC9E;;;;;;;;;;;;GAYG;AACH,MAAa,cAIX,SAAQ,8BAA+B;IACnB,QAAQ,GAAG,IAAI,GAAG,EAAmC,CAAC;IAEzE,YAAY,IAAc,EAAE,MAAe,EAAE,GAAG,IAA4C;QACzF,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,IAAuF,CAAC;QAC/G,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE;YACjB,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,8BAAuB;YACnE,0DAA0D;YAC1D,sEAAsE;YACtE,mEAAmE;YACnE,aAAa,EAAE,OAAO,CAAC,aAAa,IAAK,mCAA+E;YACxH,SAAS,EAAE,OAAO;SACpB,CAAC,CAAC;IACN,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,QAAgB;QAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,iCAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,aAAa,QAAQ,kEAAkE,CAAC,CAAC;QAC5G,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,0BAAW,CAAqB,QAAQ,EAAE;YAC3D,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE;YACjC,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;SAC5D,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,OAAO,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACM,OAAO;QACb,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,KAAK,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;CACH;AAzDD,wCAyDC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAa,wBAGX,SAAQ,cAAyD;IAChE,4EAA4E;IACnE,MAAM,CAAwB;IAEvC,YAAY,IAAc,EAAE,OAA+B;QACxD,sEAAsE;QACtE,4BAA4B;QAC5B,MAAM,MAAM,GAAG,IAAI,wBAAU,EAAa,CAAC;QAC3C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,mEAAmE;IAC1D,OAAO;QACb,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;CACH;AApBD,4DAoBC"}
|
package/lib/client/index.d.ts
CHANGED
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
* carries the entries.
|
|
27
27
|
*
|
|
28
28
|
* The Theia-specific mounting of the same contract lives in
|
|
29
|
-
* `@hydranium/data-client-theia
|
|
30
|
-
*
|
|
31
|
-
* is the Theia-bound counterpart of `DataEvents`.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
29
|
+
* `@hydranium/data-client-theia`, and is now only the TRANSPORT: its
|
|
30
|
+
* `ChannelDataPort` fills the `DataPort` seam over a Theia channel, and its
|
|
31
|
+
* `EmitterDataClient` is the Theia-bound counterpart of `DataEvents`.
|
|
32
|
+
* Everything above the port is here, so a Theia frontend and a browser page
|
|
33
|
+
* differ by which port they construct and nothing else.
|
|
34
34
|
*/
|
|
35
35
|
export * from './data-connection';
|
|
36
36
|
export * from './data-events';
|
package/lib/client/index.js
CHANGED
|
@@ -42,11 +42,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
42
42
|
* carries the entries.
|
|
43
43
|
*
|
|
44
44
|
* The Theia-specific mounting of the same contract lives in
|
|
45
|
-
* `@hydranium/data-client-theia
|
|
46
|
-
*
|
|
47
|
-
* is the Theia-bound counterpart of `DataEvents`.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
45
|
+
* `@hydranium/data-client-theia`, and is now only the TRANSPORT: its
|
|
46
|
+
* `ChannelDataPort` fills the `DataPort` seam over a Theia channel, and its
|
|
47
|
+
* `EmitterDataClient` is the Theia-bound counterpart of `DataEvents`.
|
|
48
|
+
* Everything above the port is here, so a Theia frontend and a browser page
|
|
49
|
+
* differ by which port they construct and nothing else.
|
|
50
50
|
*/
|
|
51
51
|
__exportStar(require("./data-connection"), exports);
|
|
52
52
|
__exportStar(require("./data-events"), exports);
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
import type { MessageConnection } from 'vscode-jsonrpc';
|
|
10
|
+
import { type ResolvedMessage } from '../messages/primitives';
|
|
10
11
|
import { type RpcProxy } from '../rpc';
|
|
11
12
|
import type { DataPort } from './data-port';
|
|
12
13
|
/**
|
|
@@ -94,11 +95,25 @@ export declare class RpcConnection<TServer extends ReadyServer, TClient extends
|
|
|
94
95
|
* The current generation's proxy WITHOUT awaiting readiness — calls queue
|
|
95
96
|
* against the connection promise.
|
|
96
97
|
*
|
|
98
|
+
* **Protected, and that is the point.** An early request is answered
|
|
99
|
+
* correctly from a registry the workspace walk has not filled yet, which
|
|
100
|
+
* reads as a broken project tier rather than as a race — so every caller has
|
|
101
|
+
* to interpose the gate, and every caller forgetting to is a silent bug.
|
|
102
|
+
* {@link connected} is the public route and returns this same proxy once the
|
|
103
|
+
* gate has settled, which leaves nothing to forget. The one caller that
|
|
104
|
+
* cannot use it is {@link awaitReady}, whose whole job is running the gate.
|
|
105
|
+
*
|
|
97
106
|
* Read per access, never cached: a reconnect replaces the generation, and a
|
|
98
|
-
* held reference would address the dead one.
|
|
99
|
-
|
|
107
|
+
* held reference would address the dead one.
|
|
108
|
+
*/
|
|
109
|
+
protected get server(): RpcProxy<TServer>;
|
|
110
|
+
/**
|
|
111
|
+
* Surface a failure the way this host does, through the port's sink.
|
|
112
|
+
*
|
|
113
|
+
* Here rather than only on the port so every participant sharing the
|
|
114
|
+
* connection reports through one route without being handed the transport.
|
|
100
115
|
*/
|
|
101
|
-
|
|
116
|
+
reportError(error: unknown, reported: ResolvedMessage): void;
|
|
102
117
|
/** Tear down the current connection and stop tracking the port. Idempotent. */
|
|
103
118
|
dispose(): void;
|
|
104
119
|
/** The live generation, building one if there is none. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-connection.d.ts","sourceRoot":"","sources":["../../src/client/rpc-connection.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"rpc-connection.d.ts","sourceRoot":"","sources":["../../src/client/rpc-connection.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,KAAK,eAAe,EAAyC,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,QAAQ,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,sGAGtC,CAAC;AAEF,eAAO,MAAM,qBAAqB,sGAGjC,CAAC;AAEF,yEAAyE;AACzE,MAAM,WAAW,WAAW;IACzB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,mFAAmF;AACnF,MAAM,WAAW,sBAAsB;IACpC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,gEAAgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED,wFAAwF;AACxF,MAAM,WAAW,4BAA4B,CAAC,OAAO,SAAS,MAAM;IACjE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5D,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;CAC7C;AAED,+EAA+E;AAC/E,UAAU,UAAU,CAAC,OAAO,SAAS,MAAM;IACxC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAa,CAAC,OAAO,SAAS,WAAW,EAAE,OAAO,SAAS,MAAM;IAUxE,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ;IACjC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;IAVrC,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAC3C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;IACtE,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;IACrD,0FAA0F;IAC1F,SAAS,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAC3C,SAAS,CAAC,QAAQ,UAAS;IAC3B,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAC;gBAGtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,EAClC,OAAO,EAAE,4BAA4B,CAAC,OAAO,CAAC;IAQjD;;;;;;;;;;OAUG;IACG,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAU7C;;;;;;;;;;;;;;OAcG;IACH,SAAS,KAAK,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,CAGxC;IAED;;;;;OAKG;IACH,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI5D,+EAA+E;IAC/E,OAAO,IAAI,IAAI;IASf,0DAA0D;IAC1D,SAAS,CAAC,iBAAiB,IAAI,UAAU,CAAC,OAAO,CAAC;IAqBlD,6EAA6E;cAC7D,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB1E;;;OAGG;IACH,SAAS,CAAC,cAAc,IAAI,IAAI;IAShC,SAAS,CAAC,UAAU,IAAI,IAAI;CAK9B"}
|
|
@@ -79,14 +79,30 @@ class RpcConnection {
|
|
|
79
79
|
* The current generation's proxy WITHOUT awaiting readiness — calls queue
|
|
80
80
|
* against the connection promise.
|
|
81
81
|
*
|
|
82
|
+
* **Protected, and that is the point.** An early request is answered
|
|
83
|
+
* correctly from a registry the workspace walk has not filled yet, which
|
|
84
|
+
* reads as a broken project tier rather than as a race — so every caller has
|
|
85
|
+
* to interpose the gate, and every caller forgetting to is a silent bug.
|
|
86
|
+
* {@link connected} is the public route and returns this same proxy once the
|
|
87
|
+
* gate has settled, which leaves nothing to forget. The one caller that
|
|
88
|
+
* cannot use it is {@link awaitReady}, whose whole job is running the gate.
|
|
89
|
+
*
|
|
82
90
|
* Read per access, never cached: a reconnect replaces the generation, and a
|
|
83
|
-
* held reference would address the dead one.
|
|
84
|
-
* also waits for the server's startup gate.
|
|
91
|
+
* held reference would address the dead one.
|
|
85
92
|
*/
|
|
86
93
|
get server() {
|
|
87
94
|
this.assertLive();
|
|
88
95
|
return this.currentGeneration().server;
|
|
89
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Surface a failure the way this host does, through the port's sink.
|
|
99
|
+
*
|
|
100
|
+
* Here rather than only on the port so every participant sharing the
|
|
101
|
+
* connection reports through one route without being handed the transport.
|
|
102
|
+
*/
|
|
103
|
+
reportError(error, reported) {
|
|
104
|
+
this.port.reportError(error, reported);
|
|
105
|
+
}
|
|
90
106
|
/** Tear down the current connection and stop tracking the port. Idempotent. */
|
|
91
107
|
dispose() {
|
|
92
108
|
if (this.disposed) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-connection.js","sourceRoot":"","sources":["../../src/client/rpc-connection.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAGlF,
|
|
1
|
+
{"version":3,"file":"rpc-connection.js","sourceRoot":"","sources":["../../src/client/rpc-connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
/**
|
|
10
|
+
* Well-known values of the wire's `clientId` / `sourceClientId` field.
|
|
11
|
+
*
|
|
12
|
+
* The framework tracks each document as belonging to one or more "clients" —
|
|
13
|
+
* typically an LSP-text client (Monaco, VS Code, …), a GLSP diagram client,
|
|
14
|
+
* and/or a structured-form client — and keys its holds and watches per
|
|
15
|
+
* `(uri, clientId)`. These three values are not real participants, so a client
|
|
16
|
+
* minting its own id must avoid them.
|
|
17
|
+
*
|
|
18
|
+
* **Here rather than in the server package, because the side that has to
|
|
19
|
+
* RECOGNISE them is the client.** An inbound `onDocumentUpdated` carries
|
|
20
|
+
* `sourceClientId`, and a consumer deciding what to do with it is asking which
|
|
21
|
+
* of these it is — so a frontend would otherwise have to depend on the server
|
|
22
|
+
* tier to name three strings, and in practice retypes the literal instead.
|
|
23
|
+
*/
|
|
24
|
+
/** Identifier for an LSP-text client (Monaco, VS Code, …). */
|
|
25
|
+
export declare const LANGUAGE_CLIENT_ID = "language-client";
|
|
26
|
+
/** Fallback identifier when a document's author is unknown (e.g. cold workspace-init load). */
|
|
27
|
+
export declare const UNKNOWN_CLIENT_ID = "unknown";
|
|
28
|
+
/**
|
|
29
|
+
* Synthetic author id on the `onDocumentUpdated` broadcast a data-server
|
|
30
|
+
* emits after the LAST client closed a document and the framework rebuilt it
|
|
31
|
+
* from its disk content (discarding unsaved in-session edits). Not a real
|
|
32
|
+
* client: it lets consumers distinguish the revert broadcast from
|
|
33
|
+
* client-authored updates.
|
|
34
|
+
*/
|
|
35
|
+
export declare const REVERT_ON_CLOSE_CLIENT_ID = "revert-on-close";
|
|
36
|
+
/**
|
|
37
|
+
* Every id the framework reserves, for a client checking that the identity it
|
|
38
|
+
* is about to mint collides with none of them.
|
|
39
|
+
*/
|
|
40
|
+
export declare const FRAMEWORK_CLIENT_IDS: readonly string[];
|
|
41
|
+
//# sourceMappingURL=client-ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-ids.d.ts","sourceRoot":"","sources":["../src/client-ids.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;GAcG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AAEpD,+FAA+F;AAC/F,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAuE,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.FRAMEWORK_CLIENT_IDS = exports.REVERT_ON_CLOSE_CLIENT_ID = exports.UNKNOWN_CLIENT_ID = exports.LANGUAGE_CLIENT_ID = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* Well-known values of the wire's `clientId` / `sourceClientId` field.
|
|
14
|
+
*
|
|
15
|
+
* The framework tracks each document as belonging to one or more "clients" —
|
|
16
|
+
* typically an LSP-text client (Monaco, VS Code, …), a GLSP diagram client,
|
|
17
|
+
* and/or a structured-form client — and keys its holds and watches per
|
|
18
|
+
* `(uri, clientId)`. These three values are not real participants, so a client
|
|
19
|
+
* minting its own id must avoid them.
|
|
20
|
+
*
|
|
21
|
+
* **Here rather than in the server package, because the side that has to
|
|
22
|
+
* RECOGNISE them is the client.** An inbound `onDocumentUpdated` carries
|
|
23
|
+
* `sourceClientId`, and a consumer deciding what to do with it is asking which
|
|
24
|
+
* of these it is — so a frontend would otherwise have to depend on the server
|
|
25
|
+
* tier to name three strings, and in practice retypes the literal instead.
|
|
26
|
+
*/
|
|
27
|
+
/** Identifier for an LSP-text client (Monaco, VS Code, …). */
|
|
28
|
+
exports.LANGUAGE_CLIENT_ID = 'language-client';
|
|
29
|
+
/** Fallback identifier when a document's author is unknown (e.g. cold workspace-init load). */
|
|
30
|
+
exports.UNKNOWN_CLIENT_ID = 'unknown';
|
|
31
|
+
/**
|
|
32
|
+
* Synthetic author id on the `onDocumentUpdated` broadcast a data-server
|
|
33
|
+
* emits after the LAST client closed a document and the framework rebuilt it
|
|
34
|
+
* from its disk content (discarding unsaved in-session edits). Not a real
|
|
35
|
+
* client: it lets consumers distinguish the revert broadcast from
|
|
36
|
+
* client-authored updates.
|
|
37
|
+
*/
|
|
38
|
+
exports.REVERT_ON_CLOSE_CLIENT_ID = 'revert-on-close';
|
|
39
|
+
/**
|
|
40
|
+
* Every id the framework reserves, for a client checking that the identity it
|
|
41
|
+
* is about to mint collides with none of them.
|
|
42
|
+
*/
|
|
43
|
+
exports.FRAMEWORK_CLIENT_IDS = [exports.LANGUAGE_CLIENT_ID, exports.UNKNOWN_CLIENT_ID, exports.REVERT_ON_CLOSE_CLIENT_ID];
|
|
44
|
+
//# sourceMappingURL=client-ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-ids.js","sourceRoot":"","sources":["../src/client-ids.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF;;;;;;;;;;;;;;GAcG;AAEH,8DAA8D;AACjD,QAAA,kBAAkB,GAAG,iBAAiB,CAAC;AAEpD,+FAA+F;AAClF,QAAA,iBAAiB,GAAG,SAAS,CAAC;AAE3C;;;;;;GAMG;AACU,QAAA,yBAAyB,GAAG,iBAAiB,CAAC;AAE3D;;;GAGG;AACU,QAAA,oBAAoB,GAAsB,CAAC,0BAAkB,EAAE,yBAAiB,EAAE,iCAAyB,CAAC,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
export * from './abstract-logger';
|
|
10
10
|
export * from './client';
|
|
11
|
+
export * from './client-ids';
|
|
11
12
|
export * from './clock';
|
|
12
13
|
export * from './data';
|
|
13
14
|
export * from './browser-runtime';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AASlF,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AAIpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AASlF,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AAIpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
// every production bundle that imports the root.
|
|
31
31
|
__exportStar(require("./abstract-logger"), exports);
|
|
32
32
|
__exportStar(require("./client"), exports);
|
|
33
|
+
__exportStar(require("./client-ids"), exports);
|
|
33
34
|
__exportStar(require("./clock"), exports);
|
|
34
35
|
__exportStar(require("./data"), exports);
|
|
35
36
|
__exportStar(require("./browser-runtime"), exports);
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,kFAAkF;AAClF,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,iDAAiD;AAEjD,oDAAkC;AAClC,2CAAyB;AACzB,0CAAwB;AACxB,yCAAuB;AACvB,oDAAkC;AAClC,8CAA4B;AAC5B,2CAAyB;AACzB,qDAAmC;AACnC,2CAAyB;AACzB,sDAAoC;AACpC,6EAA6E;AAC7E,+EAA+E;AAC/E,+BAA+B;AAC/B,wDAAsC;AACtC,gDAA8B;AAC9B,gDAA8B;AAC9B,qDAAmC;AACnC,oDAAkC;AAClC,8CAA4B;AAC5B,2CAAyB;AACzB,wDAAsC;AACtC,qDAAmC;AACnC,kDAAgC;AAChC,sDAAoC;AACpC,iDAA+B;AAC/B,4CAA0B;AAC1B,wCAAsB;AACtB,wCAAsB;AACtB,yCAAuB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,kFAAkF;AAClF,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,iDAAiD;AAEjD,oDAAkC;AAClC,2CAAyB;AACzB,+CAA6B;AAC7B,0CAAwB;AACxB,yCAAuB;AACvB,oDAAkC;AAClC,8CAA4B;AAC5B,2CAAyB;AACzB,qDAAmC;AACnC,2CAAyB;AACzB,sDAAoC;AACpC,6EAA6E;AAC7E,+EAA+E;AAC/E,+BAA+B;AAC/B,wDAAsC;AACtC,gDAA8B;AAC9B,gDAA8B;AAC9B,qDAAmC;AACnC,oDAAkC;AAClC,8CAA4B;AAC5B,2CAAyB;AACzB,wDAAsC;AACtC,qDAAmC;AACnC,kDAAgC;AAChC,sDAAoC;AACpC,iDAA+B;AAC/B,4CAA0B;AAC1B,wCAAsB;AACtB,wCAAsB;AACtB,yCAAuB"}
|
package/package.json
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
+
import { FRAMEWORK_CLIENT_IDS } from '../client-ids';
|
|
10
11
|
import { DATA_CLIENT_PROTOCOL_METHODS, DATA_SERVER_WIRE_PREFIX, type DataClientProtocol, type DataServerProtocol } from '../data';
|
|
11
12
|
import type { TransferElement } from '../transfer-element';
|
|
13
|
+
import { DataEvents } from './data-events';
|
|
12
14
|
import type { DataPort } from './data-port';
|
|
13
15
|
import { DataSession } from './data-session';
|
|
14
16
|
import { RpcConnection, type RpcConnectionLifecycle } from './rpc-connection';
|
|
@@ -85,12 +87,19 @@ export class DataConnection<
|
|
|
85
87
|
*
|
|
86
88
|
* `clientId` must be distinct per participant and stable for its lifetime:
|
|
87
89
|
* it keys the server's per-`(uri, clientId)` hold and watch, and it is the
|
|
88
|
-
* echo key an inbound `onDocumentUpdated` is matched against.
|
|
89
|
-
*
|
|
90
|
-
*
|
|
90
|
+
* echo key an inbound `onDocumentUpdated` is matched against.
|
|
91
|
+
*
|
|
92
|
+
* Throws for an id in {@link FRAMEWORK_CLIENT_IDS} — those are authors the
|
|
93
|
+
* SERVER emits rather than participants, so a session holding one would read
|
|
94
|
+
* the framework's own broadcasts as its own echoes and drop them. Nothing
|
|
95
|
+
* about that fails on its own: the document simply stops following, which
|
|
96
|
+
* looks like a dead connection.
|
|
91
97
|
*/
|
|
92
98
|
createSession(clientId: string): DataSession<TTransfer, TServer> {
|
|
93
99
|
this.assertLive();
|
|
100
|
+
if (FRAMEWORK_CLIENT_IDS.includes(clientId)) {
|
|
101
|
+
throw new Error(`clientId '${clientId}' is reserved by the framework and cannot identify a participant`);
|
|
102
|
+
}
|
|
94
103
|
const session = new DataSession<TTransfer, TServer>(clientId, {
|
|
95
104
|
connected: () => this.connected(),
|
|
96
105
|
releaseSession: released => this.sessions.delete(released)
|
|
@@ -112,3 +121,40 @@ export class DataConnection<
|
|
|
112
121
|
super.dispose();
|
|
113
122
|
}
|
|
114
123
|
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A {@link DataConnection} that brings its own {@link DataEvents}, so a host
|
|
127
|
+
* with several interested parties does not have to supply one.
|
|
128
|
+
*
|
|
129
|
+
* **The client slot holds exactly one object, and that is why this exists.**
|
|
130
|
+
* `createRpcProxy` binds a single `localTarget`, and underneath a method name
|
|
131
|
+
* maps to one handler — a second registration replaces the first silently. So a
|
|
132
|
+
* properties panel and a tree cannot both be the client; one fan-out sits in the
|
|
133
|
+
* slot and both subscribe to it.
|
|
134
|
+
*
|
|
135
|
+
* Use {@link DataConnection} directly instead when the client is yours: an
|
|
136
|
+
* adopter service that implements the protocol plus its own methods, a single
|
|
137
|
+
* consumer that IS the client, or a request/response-only client that binds
|
|
138
|
+
* nothing.
|
|
139
|
+
*/
|
|
140
|
+
export class DataConnectionWithEvents<
|
|
141
|
+
TTransfer extends TransferElement,
|
|
142
|
+
TServer extends DataServerProtocol<TTransfer> = DataServerProtocol<TTransfer>
|
|
143
|
+
> extends DataConnection<TTransfer, TServer, DataEvents<TTransfer>> {
|
|
144
|
+
/** Server pushes, fanned out to as many local listeners as the host has. */
|
|
145
|
+
readonly events: DataEvents<TTransfer>;
|
|
146
|
+
|
|
147
|
+
constructor(port: DataPort, options?: DataConnectionOptions) {
|
|
148
|
+
// Built as a local because `this` is unavailable before `super`, then
|
|
149
|
+
// read back onto the field.
|
|
150
|
+
const events = new DataEvents<TTransfer>();
|
|
151
|
+
super(port, events, options);
|
|
152
|
+
this.events = events;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Disposes the fan-out it created, which no caller else holds. */
|
|
156
|
+
override dispose(): void {
|
|
157
|
+
super.dispose();
|
|
158
|
+
this.events.dispose();
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
* carries the entries.
|
|
28
28
|
*
|
|
29
29
|
* The Theia-specific mounting of the same contract lives in
|
|
30
|
-
* `@hydranium/data-client-theia
|
|
31
|
-
*
|
|
32
|
-
* is the Theia-bound counterpart of `DataEvents`.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
30
|
+
* `@hydranium/data-client-theia`, and is now only the TRANSPORT: its
|
|
31
|
+
* `ChannelDataPort` fills the `DataPort` seam over a Theia channel, and its
|
|
32
|
+
* `EmitterDataClient` is the Theia-bound counterpart of `DataEvents`.
|
|
33
|
+
* Everything above the port is here, so a Theia frontend and a browser page
|
|
34
|
+
* differ by which port they construct and nothing else.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
export * from './data-connection';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
10
|
import type { MessageConnection } from 'vscode-jsonrpc';
|
|
11
|
-
import { defineMessage, describeError, resolve } from '../messages/primitives';
|
|
11
|
+
import { type ResolvedMessage, defineMessage, describeError, resolve } from '../messages/primitives';
|
|
12
12
|
import { type RpcProxy, createRpcProxy } from '../rpc';
|
|
13
13
|
import type { DataPort } from './data-port';
|
|
14
14
|
|
|
@@ -125,15 +125,32 @@ export class RpcConnection<TServer extends ReadyServer, TClient extends object>
|
|
|
125
125
|
* The current generation's proxy WITHOUT awaiting readiness — calls queue
|
|
126
126
|
* against the connection promise.
|
|
127
127
|
*
|
|
128
|
+
* **Protected, and that is the point.** An early request is answered
|
|
129
|
+
* correctly from a registry the workspace walk has not filled yet, which
|
|
130
|
+
* reads as a broken project tier rather than as a race — so every caller has
|
|
131
|
+
* to interpose the gate, and every caller forgetting to is a silent bug.
|
|
132
|
+
* {@link connected} is the public route and returns this same proxy once the
|
|
133
|
+
* gate has settled, which leaves nothing to forget. The one caller that
|
|
134
|
+
* cannot use it is {@link awaitReady}, whose whole job is running the gate.
|
|
135
|
+
*
|
|
128
136
|
* Read per access, never cached: a reconnect replaces the generation, and a
|
|
129
|
-
* held reference would address the dead one.
|
|
130
|
-
* also waits for the server's startup gate.
|
|
137
|
+
* held reference would address the dead one.
|
|
131
138
|
*/
|
|
132
|
-
get server(): RpcProxy<TServer> {
|
|
139
|
+
protected get server(): RpcProxy<TServer> {
|
|
133
140
|
this.assertLive();
|
|
134
141
|
return this.currentGeneration().server;
|
|
135
142
|
}
|
|
136
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Surface a failure the way this host does, through the port's sink.
|
|
146
|
+
*
|
|
147
|
+
* Here rather than only on the port so every participant sharing the
|
|
148
|
+
* connection reports through one route without being handed the transport.
|
|
149
|
+
*/
|
|
150
|
+
reportError(error: unknown, reported: ResolvedMessage): void {
|
|
151
|
+
this.port.reportError(error, reported);
|
|
152
|
+
}
|
|
153
|
+
|
|
137
154
|
/** Tear down the current connection and stop tracking the port. Idempotent. */
|
|
138
155
|
dispose(): void {
|
|
139
156
|
if (this.disposed) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Well-known values of the wire's `clientId` / `sourceClientId` field.
|
|
12
|
+
*
|
|
13
|
+
* The framework tracks each document as belonging to one or more "clients" —
|
|
14
|
+
* typically an LSP-text client (Monaco, VS Code, …), a GLSP diagram client,
|
|
15
|
+
* and/or a structured-form client — and keys its holds and watches per
|
|
16
|
+
* `(uri, clientId)`. These three values are not real participants, so a client
|
|
17
|
+
* minting its own id must avoid them.
|
|
18
|
+
*
|
|
19
|
+
* **Here rather than in the server package, because the side that has to
|
|
20
|
+
* RECOGNISE them is the client.** An inbound `onDocumentUpdated` carries
|
|
21
|
+
* `sourceClientId`, and a consumer deciding what to do with it is asking which
|
|
22
|
+
* of these it is — so a frontend would otherwise have to depend on the server
|
|
23
|
+
* tier to name three strings, and in practice retypes the literal instead.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** Identifier for an LSP-text client (Monaco, VS Code, …). */
|
|
27
|
+
export const LANGUAGE_CLIENT_ID = 'language-client';
|
|
28
|
+
|
|
29
|
+
/** Fallback identifier when a document's author is unknown (e.g. cold workspace-init load). */
|
|
30
|
+
export const UNKNOWN_CLIENT_ID = 'unknown';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Synthetic author id on the `onDocumentUpdated` broadcast a data-server
|
|
34
|
+
* emits after the LAST client closed a document and the framework rebuilt it
|
|
35
|
+
* from its disk content (discarding unsaved in-session edits). Not a real
|
|
36
|
+
* client: it lets consumers distinguish the revert broadcast from
|
|
37
|
+
* client-authored updates.
|
|
38
|
+
*/
|
|
39
|
+
export const REVERT_ON_CLOSE_CLIENT_ID = 'revert-on-close';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Every id the framework reserves, for a client checking that the identity it
|
|
43
|
+
* is about to mint collides with none of them.
|
|
44
|
+
*/
|
|
45
|
+
export const FRAMEWORK_CLIENT_IDS: readonly string[] = [LANGUAGE_CLIENT_ID, UNKNOWN_CLIENT_ID, REVERT_ON_CLOSE_CLIENT_ID];
|