@hydranium/protocol 1.0.0-next.63 → 1.0.0-next.67

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.
@@ -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. Avoid the
65
- * three values the framework uses as sentinels — `'language-client'`,
66
- * `'unknown'` and `'revert-on-close'`.
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;AAElF,OAAO,EAAyD,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClI,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,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;;;;;;;;OAQG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;IAUhE;;;;OAIG;IACM,OAAO,IAAI,IAAI;CAO1B"}
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. Avoid the
47
- * three values the framework uses as sentinels — `'language-client'`,
48
- * `'unknown'` and `'revert-on-close'`.
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;AAGlI,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;;;;;;;;OAQG;IACH,aAAa,CAAC,QAAgB;QAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,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;AAlDD,wCAkDC"}
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"}
@@ -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`: its `AbstractDataServiceFrontend` solves the
30
- * same problem against Theia's channel transport, and its `EmitterDataClient`
31
- * is the Theia-bound counterpart of `DataEvents`. Prefer this tier for
32
- * anything new, and reach for the Theia package only for what genuinely needs
33
- * Theia DI.
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';
@@ -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`: its `AbstractDataServiceFrontend` solves the
46
- * same problem against Theia's channel transport, and its `EmitterDataClient`
47
- * is the Theia-bound counterpart of `DataEvents`. Prefer this tier for
48
- * anything new, and reach for the Theia package only for what genuinely needs
49
- * Theia DI.
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. Prefer {@link connected}, which
99
- * also waits for the server's startup gate.
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
- get server(): RpcProxy<TServer>;
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;AAExD,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;;;;;;;OAOG;IACH,IAAI,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,CAG9B;IAED,+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"}
1
+ {"version":3,"file":"rpc-connection.d.ts","sourceRoot":"","sources":["../../src/client/rpc-connection.ts"],"names":[],"mappings":"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"}
@@ -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. Prefer {@link connected}, which
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":"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"}
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';
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydranium/protocol",
3
- "version": "1.0.0-next.63",
3
+ "version": "1.0.0-next.67",
4
4
  "description": "Generic, language-agnostic types, constants, and pure utilities for the hydranium framework.",
5
5
  "keywords": [
6
6
  "hydranium",
@@ -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. Avoid the
89
- * three values the framework uses as sentinels — `'language-client'`,
90
- * `'unknown'` and `'revert-on-close'`.
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
+ }
@@ -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`: its `AbstractDataServiceFrontend` solves the
31
- * same problem against Theia's channel transport, and its `EmitterDataClient`
32
- * is the Theia-bound counterpart of `DataEvents`. Prefer this tier for
33
- * anything new, and reach for the Theia package only for what genuinely needs
34
- * Theia DI.
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. Prefer {@link connected}, which
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];
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@
16
16
 
17
17
  export * from './abstract-logger';
18
18
  export * from './client';
19
+ export * from './client-ids';
19
20
  export * from './clock';
20
21
  export * from './data';
21
22
  export * from './browser-runtime';