@hydranium/data-client-vscode 0.0.0-stage → 1.0.0-next

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -2
  3. package/lib/browser/index.d.ts +10 -0
  4. package/lib/browser/index.d.ts.map +1 -0
  5. package/lib/browser/index.js +26 -0
  6. package/lib/browser/index.js.map +1 -0
  7. package/lib/browser/webview-data-port.d.ts +64 -0
  8. package/lib/browser/webview-data-port.d.ts.map +1 -0
  9. package/lib/browser/webview-data-port.js +97 -0
  10. package/lib/browser/webview-data-port.js.map +1 -0
  11. package/lib/index.d.ts +10 -0
  12. package/lib/index.d.ts.map +1 -0
  13. package/lib/index.js +29 -0
  14. package/lib/index.js.map +1 -0
  15. package/lib/messenger-channel.d.ts +155 -0
  16. package/lib/messenger-channel.d.ts.map +1 -0
  17. package/lib/messenger-channel.js +106 -0
  18. package/lib/messenger-channel.js.map +1 -0
  19. package/lib/node/data-server-connection.d.ts +57 -0
  20. package/lib/node/data-server-connection.d.ts.map +1 -0
  21. package/lib/node/data-server-connection.js +92 -0
  22. package/lib/node/data-server-connection.js.map +1 -0
  23. package/lib/node/index.d.ts +10 -0
  24. package/lib/node/index.d.ts.map +1 -0
  25. package/lib/node/index.js +26 -0
  26. package/lib/node/index.js.map +1 -0
  27. package/lib/testing/index.d.ts +10 -0
  28. package/lib/testing/index.d.ts.map +1 -0
  29. package/lib/testing/index.js +26 -0
  30. package/lib/testing/index.js.map +1 -0
  31. package/lib/testing/messenger-harness.d.ts +48 -0
  32. package/lib/testing/messenger-harness.d.ts.map +1 -0
  33. package/lib/testing/messenger-harness.js +91 -0
  34. package/lib/testing/messenger-harness.js.map +1 -0
  35. package/package.json +99 -4
  36. package/src/browser/index.ts +10 -0
  37. package/src/browser/webview-data-port.ts +115 -0
  38. package/src/index.ts +13 -0
  39. package/src/messenger-channel.ts +224 -0
  40. package/src/node/data-server-connection.ts +85 -0
  41. package/src/node/index.ts +10 -0
  42. package/src/testing/index.ts +10 -0
  43. package/src/testing/messenger-harness.ts +121 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,111 @@
1
- # Temporary Holding Version
1
+ # `@hydranium/data-client-vscode`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The data head's client side in a VS Code extension built on
4
+ [Hydranium](https://github.com/eclipse-emfcloud/hydranium). Install it when a
5
+ webview of your extension reads or writes models through the data head: a
6
+ webview has no sockets, so the extension host relays the data-server's socket
7
+ to it over a `vscode-messenger` hop, and the webview's data port reads it.
8
+
9
+ ## What it gives you
10
+
11
+ - The extension host's relay from the data-server's socket to one webview,
12
+ with the port looked up again for every connection, so a restarted server
13
+ is found.
14
+ - A channel over the messenger for each end of the hop, filtered to the one
15
+ webview it serves, so the hop can be shared with GLSP's diagram webviews.
16
+ - The webview's `DataPort`, for the connection and sessions from
17
+ `@hydranium/protocol`, which rejects pending requests when the extension host
18
+ reports the relay lost.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install @hydranium/data-client-vscode
24
+ ```
25
+
26
+ | Peer | Range |
27
+ | -------------------------- | ------------- |
28
+ | `@hydranium/protocol` | `^1.0.0-next` |
29
+ | `vscode-jsonrpc` | `^9.0.0` |
30
+ | `vscode-messenger` | `^0.4.5` |
31
+ | `vscode-messenger-common` | `^0.4.5` |
32
+ | `vscode-messenger-webview` | `^0.4.5` |
33
+
34
+ The `vscode-messenger` packages are optional; only `./testing` loads them.
35
+ Your extension and webview use the copies GLSP's VS Code integration brings,
36
+ or their own.
37
+
38
+ ## Wiring
39
+
40
+ In the extension host, connect each webview to the data head over a messenger
41
+ constructed with `ignoreHiddenViews: false`, as `GlspVscodeConnector`'s is, or
42
+ a hidden webview misses every answer. Tell the webview when the relay closes,
43
+ since nothing else reaches it:
44
+
45
+ <!-- snippet-preamble
46
+ import type { MessageParticipant } from 'vscode-messenger-common';
47
+ import type { Messenger } from 'vscode-messenger';
48
+ declare const messenger: Messenger;
49
+ declare const webview: MessageParticipant;
50
+ declare function findDataServerPort(): Promise<number>;
51
+ declare function tellWebviewConnectionLost(): void;
52
+ -->
53
+
54
+ ```ts
55
+ import { connectDataServer } from '@hydranium/data-client-vscode/node';
56
+
57
+ const relay = connectDataServer({ messenger, webview, findPort: findDataServerPort });
58
+ relay.onClose(() => tellWebviewConnectionLost());
59
+ ```
60
+
61
+ In the webview, build the port over the mirror channel, start the messenger,
62
+ and hand the port to a data connection; call `connectionLost` on the port
63
+ when the extension host says the relay closed:
64
+
65
+ ```ts
66
+ import { createWebviewSideChannel } from '@hydranium/data-client-vscode';
67
+ import { WebviewDataPort } from '@hydranium/data-client-vscode/browser';
68
+ import { DataConnectionWithEvents } from '@hydranium/protocol';
69
+ import { HOST_EXTENSION } from 'vscode-messenger-common';
70
+ import { Messenger, type VsCodeApi } from 'vscode-messenger-webview';
71
+
72
+ // VS Code injects it into the webview; there is nothing to import.
73
+ declare function acquireVsCodeApi(): VsCodeApi;
74
+
75
+ const messenger = new Messenger(acquireVsCodeApi());
76
+ const port = new WebviewDataPort(createWebviewSideChannel(messenger, HOST_EXTENSION));
77
+ messenger.start();
78
+ const connection = new DataConnectionWithEvents(port);
79
+ ```
80
+
81
+ To test a webview's data path in Node, `makeMessengerHarness` from `./testing`
82
+ joins the real extension-side and webview-side messengers through a fake
83
+ panel and a fake `window`, so the test runs their real routing.
84
+
85
+ For the whole setup, see *Host in VS Code* in
86
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
87
+
88
+ ## Entry points
89
+
90
+ | Subpath | Use it for | Runs in |
91
+ | ----------- | --------------------------------------------- | -------------------------- |
92
+ | `.` | The messenger channel both ends build on | anywhere |
93
+ | `./node` | The relay from the data-server's socket | the VS Code extension host |
94
+ | `./browser` | The webview's data port | a webview |
95
+ | `./testing` | The real messenger pair joined in a Node test | a test |
96
+
97
+ The subpaths need a TypeScript `moduleResolution` that reads `exports`
98
+ (`NodeNext` or `Bundler`); see *Requirements* in
99
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
100
+
101
+ ## Status
102
+
103
+ Alpha: every release is a prerelease that may break the API, so pin an exact
104
+ version. Guides and known limitations:
105
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
106
+
107
+ ## License
108
+
109
+ `MIT` — see this package's [`LICENSE`](./LICENSE), and the repository
110
+ [`NOTICE.md`](https://github.com/eclipse-emfcloud/hydranium/blob/main/NOTICE.md)
111
+ for third-party notices.
@@ -0,0 +1,10 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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
+ export * from './webview-data-port';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 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
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
22
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ __exportStar(require("./webview-data-port"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,sDAAoC"}
@@ -0,0 +1,64 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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
+ import { type DataPort, type Logger, type PostMessageChannel, type ResolvedMessage } from '@hydranium/protocol';
10
+ import { Emitter, type Event, type MessageConnection } from 'vscode-jsonrpc';
11
+ /** Options for {@link WebviewDataPort}. */
12
+ export interface WebviewDataPortOptions {
13
+ /**
14
+ * Surface a data-head failure. Without one it goes to the webview's console;
15
+ * a webview whose extension shows notifications forwards it there instead.
16
+ */
17
+ readonly reportError?: (error: unknown, reported: ResolvedMessage) => void;
18
+ /** Where the connection logs its protocol faults, and what it does on its own. */
19
+ readonly logger?: Logger;
20
+ }
21
+ /**
22
+ * The webview's {@link DataPort}: the sandbox side of the data head, over the
23
+ * extension host's messenger hop.
24
+ *
25
+ * `vscode-jsonrpc/browser`, not the package root, which installs no runtime
26
+ * abstraction layer and throws on the first message rather than at wire-up.
27
+ */
28
+ export declare class WebviewDataPort implements DataPort {
29
+ protected readonly channel: PostMessageChannel;
30
+ protected readonly options: WebviewDataPortOptions;
31
+ protected readonly disposeEmitter: Emitter<void>;
32
+ readonly onDispose: Event<void>;
33
+ readonly logger?: Logger;
34
+ protected disposed: boolean;
35
+ /** The connection every generation gets until it is disposed. */
36
+ protected connection?: MessageConnection;
37
+ constructor(channel: PostMessageChannel, options?: WebviewDataPortOptions);
38
+ /**
39
+ * Hand back a listening connection over the hop: the same one until it is
40
+ * disposed, and then a fresh transport, so a disposed connection leaves no
41
+ * second reader on the pipe.
42
+ *
43
+ * Every connection reaches the one relay behind the pipe, and each numbers
44
+ * its requests from zero, so a second live one would take answers meant for
45
+ * the first. A retry after a failed readiness check therefore gets the
46
+ * connection the check used.
47
+ */
48
+ connect(): Promise<MessageConnection>;
49
+ reportError(error: unknown, reported: ResolvedMessage): void;
50
+ /**
51
+ * The extension host reports the relay's framed side died.
52
+ *
53
+ * A `PostMessageChannel` has no `close()`, so the pipe still looks open from
54
+ * here: firing `onDispose` makes `DataConnection` drop its generation, and
55
+ * disposing the connection rejects everything in flight, also when no
56
+ * generation holds it. The connection is forgotten before the event, so a
57
+ * listener that connects gets a fresh one rather than the one about to be
58
+ * disposed.
59
+ */
60
+ connectionLost(): void;
61
+ /** Refuses to connect afterwards: the consumer's reconnect would otherwise open a reader nothing releases. */
62
+ dispose(): void;
63
+ }
64
+ //# sourceMappingURL=webview-data-port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webview-data-port.d.ts","sourceRoot":"","sources":["../../src/browser/webview-data-port.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAGJ,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG7E,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACpC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3E,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAS1C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB;IAC9C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,sBAAsB;IATrD,SAAS,CAAC,QAAQ,CAAC,cAAc,gBAAuB;IACxD,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAA6B;IAC5D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,QAAQ,UAAS;IAC3B,iEAAiE;IACjE,SAAS,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAEzC,YACsB,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,sBAA2B,EAGzD;IAED;;;;;;;;;OASG;IACG,OAAO,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAiB1C;IAED,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAM3D;IAED;;;;;;;;;OASG;IACH,cAAc,IAAI,IAAI,CAKrB;IAED,8GAA8G;IAC9G,OAAO,IAAI,IAAI,CAKd;CACH"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 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.WebviewDataPort = void 0;
12
+ const protocol_1 = require("@hydranium/protocol");
13
+ const vscode_jsonrpc_1 = require("vscode-jsonrpc");
14
+ const browser_1 = require("vscode-jsonrpc/browser");
15
+ /**
16
+ * The webview's {@link DataPort}: the sandbox side of the data head, over the
17
+ * extension host's messenger hop.
18
+ *
19
+ * `vscode-jsonrpc/browser`, not the package root, which installs no runtime
20
+ * abstraction layer and throws on the first message rather than at wire-up.
21
+ */
22
+ class WebviewDataPort {
23
+ channel;
24
+ options;
25
+ disposeEmitter = new vscode_jsonrpc_1.Emitter();
26
+ onDispose = this.disposeEmitter.event;
27
+ logger;
28
+ disposed = false;
29
+ /** The connection every generation gets until it is disposed. */
30
+ connection;
31
+ constructor(channel, options = {}) {
32
+ this.channel = channel;
33
+ this.options = options;
34
+ this.logger = options.logger;
35
+ }
36
+ /**
37
+ * Hand back a listening connection over the hop: the same one until it is
38
+ * disposed, and then a fresh transport, so a disposed connection leaves no
39
+ * second reader on the pipe.
40
+ *
41
+ * Every connection reaches the one relay behind the pipe, and each numbers
42
+ * its requests from zero, so a second live one would take answers meant for
43
+ * the first. A retry after a failed readiness check therefore gets the
44
+ * connection the check used.
45
+ */
46
+ async connect() {
47
+ if (this.disposed) {
48
+ throw new Error('WebviewDataPort: the port is disposed');
49
+ }
50
+ if (!this.connection) {
51
+ const transport = (0, protocol_1.createPostMessageTransport)(this.channel);
52
+ const connection = (0, browser_1.createMessageConnection)(transport.reader, transport.writer, this.logger);
53
+ connection.onDispose(() => {
54
+ transport.dispose();
55
+ if (this.connection === connection) {
56
+ this.connection = undefined;
57
+ }
58
+ });
59
+ connection.listen();
60
+ this.connection = connection;
61
+ }
62
+ return this.connection;
63
+ }
64
+ reportError(error, reported) {
65
+ if (this.options.reportError) {
66
+ this.options.reportError(error, reported);
67
+ }
68
+ else {
69
+ console.error(`[data head] ${(0, protocol_1.renderFrameworkMessage)(reported)}`, error);
70
+ }
71
+ }
72
+ /**
73
+ * The extension host reports the relay's framed side died.
74
+ *
75
+ * A `PostMessageChannel` has no `close()`, so the pipe still looks open from
76
+ * here: firing `onDispose` makes `DataConnection` drop its generation, and
77
+ * disposing the connection rejects everything in flight, also when no
78
+ * generation holds it. The connection is forgotten before the event, so a
79
+ * listener that connects gets a fresh one rather than the one about to be
80
+ * disposed.
81
+ */
82
+ connectionLost() {
83
+ const lost = this.connection;
84
+ this.connection = undefined;
85
+ this.disposeEmitter.fire();
86
+ lost?.dispose();
87
+ }
88
+ /** Refuses to connect afterwards: the consumer's reconnect would otherwise open a reader nothing releases. */
89
+ dispose() {
90
+ this.disposed = true;
91
+ this.disposeEmitter.fire();
92
+ this.disposeEmitter.dispose();
93
+ this.connection?.dispose();
94
+ }
95
+ }
96
+ exports.WebviewDataPort = WebviewDataPort;
97
+ //# sourceMappingURL=webview-data-port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webview-data-port.js","sourceRoot":"","sources":["../../src/browser/webview-data-port.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,kDAO6B;AAC7B,mDAA6E;AAC7E,oDAAiE;AAajE;;;;;;GAMG;AACH;IASyB,OAAO;IACP,OAAO;IATV,cAAc,GAAG,IAAI,wBAAO,EAAQ,CAAC;IAC/C,SAAS,GAAgB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;IACnD,MAAM,CAAU;IACf,QAAQ,GAAG,KAAK,CAAC;IAC3B,iEAAiE;IACvD,UAAU,CAAqB;IAEzC,YACsB,OAA2B,EAC3B,OAAO,GAA2B,EAAE;uBADpC,OAAO;uBACP,OAAO;QAE1B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAChC,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,OAAO;QACV,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,SAAS,GAAG,IAAA,qCAA0B,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAA,iCAAuB,EAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5F,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE;gBACvB,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;oBAClC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;gBAC/B,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,UAAU,CAAC,MAAM,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;IAC1B,CAAC;IAED,WAAW,CAAC,KAAc,EAAE,QAAyB;QAClD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACL,OAAO,CAAC,KAAK,CAAC,eAAe,IAAA,iCAAsB,EAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC3E,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,cAAc;QACX,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,EAAE,OAAO,EAAE,CAAC;IACnB,CAAC;IAED,8GAA8G;IAC9G,OAAO;QACJ,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QAC9B,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;CACH"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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
+ export * from './messenger-channel';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAKlF,cAAc,qBAAqB,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 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
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
22
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ // Neutral: the messenger channel both ends of the hop build on, free of
26
+ // `vscode`, Node and the DOM. The extension host's end is `./node`, the
27
+ // webview's `./browser`.
28
+ __exportStar(require("./messenger-channel"), exports);
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,wEAAwE;AACxE,wEAAwE;AACxE,yBAAyB;AACzB,sDAAoC"}
@@ -0,0 +1,155 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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
+ import type { PostMessageChannel } from '@hydranium/protocol';
10
+ import type { Disposable, Message } from 'vscode-jsonrpc';
11
+ /**
12
+ * A notification type as `vscode-messenger` defines it: a method name, with the
13
+ * payload type carried only in the generic parameter.
14
+ *
15
+ * Restated rather than imported: `vscode-messenger-common`'s
16
+ * `NotificationType<P>` is `{ method: string }` with `P` phantom, and the import
17
+ * would pin the adopter's messenger copy, which GLSP's VS Code integration
18
+ * chooses.
19
+ */
20
+ export interface NotificationTypeLike {
21
+ readonly method: string;
22
+ }
23
+ /**
24
+ * The one method both ends of the hop share: hand a message to a participant.
25
+ *
26
+ * `TParticipant` stays generic because the two ends address different things,
27
+ * the extension side a registered webview and the webview side
28
+ * `HOST_EXTENSION`.
29
+ */
30
+ export interface MessengerSendLike<TParticipant> {
31
+ sendNotification(type: NotificationTypeLike, receiver: TParticipant, params?: Message): void;
32
+ }
33
+ /**
34
+ * The two methods the channel needs from the **extension-side** messenger.
35
+ *
36
+ * Two methods rather than the class, so any messenger with them fits, GLSP's
37
+ * included, without pinning a `vscode-messenger` copy.
38
+ */
39
+ export interface MessengerLike<TParticipant> extends MessengerSendLike<TParticipant> {
40
+ onNotification(type: NotificationTypeLike, handler: (params: Message, sender: TParticipant) => void, options?: {
41
+ sender?: TParticipant;
42
+ }): Disposable;
43
+ }
44
+ /**
45
+ * The **webview-side** messenger, which differs from the extension side in
46
+ * every point the channel depends on:
47
+ *
48
+ * - **`onNotification` returns the messenger itself**, not a `Disposable`, and
49
+ * there is no unregister API, so a registration lasts as long as the webview.
50
+ * {@link createMessengerChannel} therefore stops delivering through a flag.
51
+ * - **There is no `sender` option**: a webview has one peer.
52
+ * - **`start()` must be called** before anything arrives, since it attaches the
53
+ * `window` listener. It is absent here because the channel does not call it;
54
+ * the webview's bootstrap does.
55
+ *
56
+ * A separate interface rather than a wider {@link MessengerLike}: one shape for
57
+ * both ends would promise a webview an unregisterable handler and a sender
58
+ * filter it cannot honour.
59
+ */
60
+ export interface WebviewMessengerLike<TParticipant> extends MessengerSendLike<TParticipant> {
61
+ onNotification(type: NotificationTypeLike, handler: (params: Message, sender: TParticipant) => void): unknown;
62
+ }
63
+ /**
64
+ * The data head's two notification types, one per direction.
65
+ *
66
+ * `vscode-messenger` addresses a notification to its receiver, so one method
67
+ * for both directions would also deliver correctly. Two keep the direction
68
+ * readable on the wire and in a messenger trace, and keep a delivery that
69
+ * routes by method alone, such as `BROADCAST`, from reaching the sender's own
70
+ * handler.
71
+ */
72
+ export declare const DATA_TO_WEBVIEW: NotificationTypeLike;
73
+ export declare const DATA_TO_EXTENSION: NotificationTypeLike;
74
+ /**
75
+ * Options for {@link createMessengerChannel}.
76
+ *
77
+ * Generic over the registration type as well as the participant, because the two
78
+ * sides disagree on what `onNotification` hands back: a `Disposable` on the
79
+ * extension side, the messenger itself on the webview side. The type parameter
80
+ * keeps {@link releaseRegistration} typed; probing an `unknown` for a `dispose`
81
+ * method would dispose the whole webview messenger if it ever gained one.
82
+ */
83
+ export interface MessengerChannelOptions<TParticipant, TRegistration> {
84
+ readonly messenger: {
85
+ sendNotification(type: NotificationTypeLike, receiver: TParticipant, params?: Message): void;
86
+ onNotification(type: NotificationTypeLike, handler: (params: Message, sender: TParticipant) => void, options?: {
87
+ sender?: TParticipant;
88
+ }): TRegistration;
89
+ };
90
+ /** Where this side's outbound messages are addressed. */
91
+ readonly receiver: TParticipant;
92
+ /** The notification type this side SENDS on. */
93
+ readonly outbound: NotificationTypeLike;
94
+ /** The notification type this side LISTENS on. */
95
+ readonly inbound: NotificationTypeLike;
96
+ /**
97
+ * Accept inbound notifications only from this participant. Supply it
98
+ * whenever the messenger is shared, as GLSP's is with every diagram
99
+ * webview, so a second webview cannot inject traffic into this connection.
100
+ *
101
+ * Extension side only: the webview-side messenger ignores it.
102
+ */
103
+ readonly sender?: TParticipant;
104
+ /**
105
+ * Observe the hop going away, the webview being disposed. Passed through to
106
+ * {@link PostMessageChannel.onClose}, whose reader and writer use it to fire
107
+ * their own close.
108
+ */
109
+ readonly onClose?: (listener: () => void) => Disposable;
110
+ /**
111
+ * Release what `onNotification` returned, where the messenger hands back
112
+ * something releasable: on the extension side, whose registrations would
113
+ * otherwise accumulate on a hop that outlives every webview on it.
114
+ */
115
+ readonly releaseRegistration?: (registration: TRegistration) => void;
116
+ }
117
+ /**
118
+ * Present a messenger as a {@link PostMessageChannel}, so the data head's
119
+ * transport rides a host's existing notification hop.
120
+ *
121
+ * `createPostMessageTransport` turns the channel into a reader and writer,
122
+ * `relayToPostMessageChannel` pumps the extension host's socket onto it from
123
+ * the other side, and everything above, `createRpcProxy` and `DataSession`
124
+ * included, is host-invariant. Sharing GLSP's `Messenger` rather than opening a
125
+ * second hop gives a diagram and a data webview one lifecycle and one dispose.
126
+ *
127
+ * **`onMessage`'s `Disposable` means "stop delivering", not necessarily
128
+ * "unregister".** The webview-side messenger cannot unregister, so a flag keeps
129
+ * the promise on both sides. Where unregistering is possible,
130
+ * {@link MessengerChannelOptions.releaseRegistration} does it too, or every
131
+ * disposed webview would leave a handler on a shared hop.
132
+ */
133
+ export declare function createMessengerChannel<TParticipant, TRegistration>(options: MessengerChannelOptions<TParticipant, TRegistration>): PostMessageChannel;
134
+ /**
135
+ * The extension host's end: posts toward the webview, listens for what the
136
+ * webview sends.
137
+ */
138
+ export declare function createExtensionSideChannel<TParticipant>(messenger: MessengerLike<TParticipant>, webview: TParticipant, onClose?: (listener: () => void) => Disposable): PostMessageChannel;
139
+ /**
140
+ * The webview's end: the mirror image, addressed at the extension host.
141
+ *
142
+ * Two preconditions the webview's bootstrap owns, both of which present as "no
143
+ * data ever arrives" when missed:
144
+ *
145
+ * - **Read the channel through `WebviewDataPort`**, or build its connection
146
+ * with `createMessageConnection` from `vscode-jsonrpc/browser`: the package
147
+ * root installs no runtime abstraction layer and throws on the first
148
+ * message.
149
+ * - **Call the messenger's own `start()`**, which attaches the `window`
150
+ * listener.
151
+ *
152
+ * No `sender` filter: a webview has one peer.
153
+ */
154
+ export declare function createWebviewSideChannel<TParticipant>(messenger: WebviewMessengerLike<TParticipant>, hostExtension: TParticipant, onClose?: (listener: () => void) => Disposable): PostMessageChannel;
155
+ //# sourceMappingURL=messenger-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messenger-channel.d.ts","sourceRoot":"","sources":["../src/messenger-channel.ts"],"names":[],"mappings":"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"}