@hydranium/client-browser 1.0.0-next.303 → 1.0.0-next.304

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,8 @@
3
3
  The page side of a [Hydranium](https://github.com/eclipse-emfcloud/hydranium)
4
4
  host that runs its heads in a web worker, with no backend. Install it when
5
5
  your language runs in a plain web page: it hands each head its own
6
- `MessagePort`, runs the page's LSP handshake, and gives the data head its port.
6
+ `MessagePort`, runs the page's LSP handshake, makes a Monaco editor the LSP
7
+ head's client, and gives the data head its port.
7
8
 
8
9
  ## What it gives you
9
10
 
@@ -12,6 +13,10 @@ your language runs in a plain web page: it hands each head its own
12
13
  - The LSP head's connection with the server's own requests answered: the
13
14
  capability registrations and the configuration section it reads while the
14
15
  workspace comes up.
16
+ - A Monaco editor as the LSP head's client, from `./monaco`: the languages and
17
+ providers registered, `workspace/applyEdit` answered, `didOpen`, `didChange`
18
+ and `didClose` sent for the documents you open, and a save of the unsaved
19
+ ones through the data head.
15
20
  - A `DataPort` over the data head's port, for the connection and sessions from
16
21
  `@hydranium/protocol`.
17
22
  - The GLSP head's connection, for GLSP's own client.
@@ -25,11 +30,14 @@ your language runs in a plain web page: it hands each head its own
25
30
  npm install @hydranium/client-browser
26
31
  ```
27
32
 
28
- | Peer | Range |
29
- | -------------------------------- | ------------- |
30
- | `@hydranium/protocol` | `^1.0.0-next` |
31
- | `vscode-jsonrpc` | `^9.0.0` |
32
- | `vscode-languageserver-protocol` | `~3.18.1` |
33
+ | Peer | Range |
34
+ | -------------------------------- | ----------------- |
35
+ | `@hydranium/protocol` | `^1.0.0-next` |
36
+ | `monaco-editor-core` | `>=0.56.0 <1.0.0` |
37
+ | `vscode-jsonrpc` | `^9.0.0` |
38
+ | `vscode-languageserver-protocol` | `~3.18.1` |
39
+
40
+ `monaco-editor-core` is optional; only `./monaco` needs it.
33
41
 
34
42
  ## Wiring
35
43
 
@@ -75,21 +83,62 @@ The data port reports a data-head failure to the console. A host with a
75
83
  surface of its own subclasses `WorkerDataPort` and passes it as
76
84
  `createDataPort`.
77
85
 
78
- The default capabilities declare `workspace.applyEdit`, which the handshake
79
- does not answer: register a `workspace/applyEdit` handler on the connection
80
- before you open a document, as any LSP client does, or the server's writes
81
- to that document are lost.
86
+ Build the Monaco client, from `./monaco`, in `beforeInitialized` too, from the
87
+ server's capabilities and your language table, and hand it each diagnostics
88
+ notification. Open a document on the text the worker holds, never on a copy
89
+ in your bundle, and create editors through the client, which keeps the
90
+ settings a server-driven language needs under your own. Save through a data
91
+ session: the server already holds every edit, so the save persists and
92
+ authors nothing.
93
+
94
+ <!-- snippet-preamble
95
+ import { connectWorkerHeads } from '@hydranium/client-browser';
96
+ import { DataConnectionWithEvents } from '@hydranium/protocol';
97
+ declare const worker: Parameters<typeof connectWorkerHeads>[0];
98
+ declare const container: HTMLElement;
99
+ declare const textFromTheWorker: string;
100
+ const heads = connectWorkerHeads(worker);
101
+ const data = new DataConnectionWithEvents(heads.data);
102
+ -->
103
+
104
+ ```ts
105
+ import { initializeLanguageClient } from '@hydranium/client-browser';
106
+ import { MONACO_CLIENT_CAPABILITIES, MonacoLspClient, saveDirtyDocuments } from '@hydranium/client-browser/monaco';
107
+ import { PublishDiagnosticsNotification } from 'vscode-languageserver-protocol';
108
+
109
+ let client!: MonacoLspClient;
110
+ await initializeLanguageClient(heads.lsp, {
111
+ rootUri: 'file:///workspace',
112
+ capabilities: MONACO_CLIENT_CAPABILITIES,
113
+ beforeInitialized: result => {
114
+ client = new MonacoLspClient(heads.lsp, result.capabilities, {
115
+ languages: [{ id: 'my-language', extensions: ['.my'] }]
116
+ });
117
+ heads.lsp.onNotification(PublishDiagnosticsNotification.type, params => client.applyDiagnostics(params));
118
+ }
119
+ });
120
+ const model = client.openDocument('file:///workspace/a.my', textFromTheWorker);
121
+ client.createEditor(container, model, { theme: 'vs' });
122
+ await saveDirtyDocuments(client, data.createSession('editors'));
123
+ ```
124
+
125
+ `MONACO_CLIENT_CAPABILITIES` declares `workspace.applyEdit`, which the Monaco
126
+ client answers, and every form it renders, so a server that gates a form on
127
+ its capability sends it. A host with another editor declares its own, and
128
+ registers its own `workspace/applyEdit` handler before it opens a document,
129
+ as any LSP client does, or the server's writes to that document are lost.
82
130
 
83
131
  For the whole setup, see *Host in a browser* in
84
132
  [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
85
133
 
86
134
  ## Entry points
87
135
 
88
- | Subpath | Use it for | Runs in |
89
- | ------- | --------------------------------------------------------- | ---------- |
90
- | `.` | The worker bootstrap, the LSP handshake and the data port | a web page |
136
+ | Subpath | Use it for | Runs in |
137
+ | ---------- | --------------------------------------------------------- | ---------- |
138
+ | `.` | The worker bootstrap, the LSP handshake and the data port | a web page |
139
+ | `./monaco` | The Monaco editor as the LSP head's client, and its save | a web page |
91
140
 
92
- The package needs a TypeScript `moduleResolution` that reads `exports`
141
+ The subpaths need a TypeScript `moduleResolution` that reads `exports`
93
142
  (`NodeNext` or `Bundler`); see *Requirements* in
94
143
  [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
95
144
 
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
- import type { Locale } from '@hydranium/protocol';
9
+ import { type Locale } from '@hydranium/protocol';
10
10
  import type { MessageConnection } from 'vscode-jsonrpc/browser';
11
11
  import { type ClientCapabilities, type InitializeResult, type LogMessageParams } from 'vscode-languageserver-protocol';
12
12
  /** The one configuration section the server reads, and what it reads there. */
@@ -1 +1 @@
1
- {"version":3,"file":"language-client.d.ts","sourceRoot":"","sources":["../src/language-client.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAOJ,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACvB,MAAM,gCAAgC,CAAC;AAExC,+EAA+E;AAC/E,MAAM,WAAW,2BAA2B;IACzC,kHAAkH;IAClH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oJAAoJ;IACpJ,QAAQ,IAAI,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACnC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,oGAAoG;IACpG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C,uFAAuF;IACvF,QAAQ,CAAC,aAAa,CAAC,EAAE,2BAA2B,CAAC;IACrD,8IAA8I;IAC9I,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC3D;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAClE;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,iBAAiB,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyBvI"}
1
+ {"version":3,"file":"language-client.d.ts","sourceRoot":"","sources":["../src/language-client.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAOJ,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACvB,MAAM,gCAAgC,CAAC;AAExC,+EAA+E;AAC/E,MAAM,WAAW,2BAA2B;IACzC,kHAAkH;IAClH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oJAAoJ;IACpJ,QAAQ,IAAI,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACnC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,oGAAoG;IACpG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C,uFAAuF;IACvF,QAAQ,CAAC,aAAa,CAAC,EAAE,2BAA2B,CAAC;IACrD,8IAA8I;IAC9I,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC3D;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAClE;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,iBAAiB,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4BvI"}
@@ -9,6 +9,7 @@
9
9
  ********************************************************************************/
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.initializeLanguageClient = initializeLanguageClient;
12
+ const protocol_1 = require("@hydranium/protocol");
12
13
  const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
13
14
  /** The capabilities the server's inbound requests rely on, declared unless the host declares its own. */
14
15
  const DEFAULT_CAPABILITIES = { workspace: { applyEdit: true, configuration: true } };
@@ -38,7 +39,10 @@ async function initializeLanguageClient(connection, options) {
38
39
  connection.onNotification(vscode_languageserver_protocol_1.LogMessageNotification.type, options.onLogMessage);
39
40
  }
40
41
  connection.listen();
41
- const result = await connection.sendRequest(vscode_languageserver_protocol_1.InitializeRequest.type, {
42
+ // By method name: these types come from `vscode-languageserver-protocol`'s
43
+ // copy of `vscode-jsonrpc`, which need not be the connection's.
44
+ const sender = (0, protocol_1.sendByMethodName)(connection);
45
+ const result = await sender.sendRequest(vscode_languageserver_protocol_1.InitializeRequest.type, {
42
46
  processId: null,
43
47
  rootUri: options.rootUri,
44
48
  locale: options.locale,
@@ -46,7 +50,7 @@ async function initializeLanguageClient(connection, options) {
46
50
  workspaceFolders: [{ uri: options.rootUri, name: workspaceName }]
47
51
  });
48
52
  options.beforeInitialized?.(result);
49
- await connection.sendNotification(vscode_languageserver_protocol_1.InitializedNotification.type, {});
53
+ await sender.sendNotification(vscode_languageserver_protocol_1.InitializedNotification.type, {});
50
54
  return result;
51
55
  }
52
56
  /** The root's last path segment, decoded, or the root itself for one with no path. */
@@ -1 +1 @@
1
- {"version":3,"file":"language-client.js","sourceRoot":"","sources":["../src/language-client.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAIlF,mFAUwC;AAyCxC,yGAAyG;AACzG,MAAM,oBAAoB,GAAuB,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;AAEzG;;;;;;;;;;;;;GAaG;AACI,KAAK,mCAAmC,UAA6B,EAAE,OAA8B;IACzG,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,UAAU,CAAC,SAAS,CAAC,oDAAmB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAChE,UAAU,CAAC,SAAS,CAAC,sDAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC5C,UAAU,CAAC,SAAS,CAAC,qDAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CACtD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CACrI,CAAC;IACF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACxB,UAAU,CAAC,cAAc,CAAC,uDAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IACD,UAAU,CAAC,MAAM,EAAE,CAAC;IAEpB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,kDAAiB,CAAC,IAAI,EAAE;QACjE,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,oBAAoB;QAC1D,gBAAgB,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;KACnE,CAAC,CAAC;IACH,OAAO,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,UAAU,CAAC,gBAAgB,CAAC,wDAAuB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AACjB,CAAC;AAED,sFAAsF;AACtF,SAAS,eAAe,CAAC,OAAe;IACrC,OAAO,kBAAkB,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC;AAC9G,CAAC"}
1
+ {"version":3,"file":"language-client.js","sourceRoot":"","sources":["../src/language-client.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,kDAAoE;AAEpE,mFAUwC;AAyCxC,yGAAyG;AACzG,MAAM,oBAAoB,GAAuB,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;AAEzG;;;;;;;;;;;;;GAaG;AACI,KAAK,mCAAmC,UAA6B,EAAE,OAA8B;IACzG,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,UAAU,CAAC,SAAS,CAAC,oDAAmB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAChE,UAAU,CAAC,SAAS,CAAC,sDAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC5C,UAAU,CAAC,SAAS,CAAC,qDAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CACtD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CACrI,CAAC;IACF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACxB,UAAU,CAAC,cAAc,CAAC,uDAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IACD,UAAU,CAAC,MAAM,EAAE,CAAC;IAEpB,2EAA2E;IAC3E,gEAAgE;IAChE,MAAM,MAAM,GAAG,IAAA,2BAAgB,EAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,kDAAiB,CAAC,IAAI,EAAE;QAC7D,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,oBAAoB;QAC1D,gBAAgB,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;KACnE,CAAC,CAAC;IACH,OAAO,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,CAAC,gBAAgB,CAAC,wDAAuB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC;AACjB,CAAC;AAED,sFAAsF;AACtF,SAAS,eAAe,CAAC,OAAe;IACrC,OAAO,kBAAkB,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC;AAC9G,CAAC"}
@@ -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 './monaco-lsp-client';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/monaco/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAKlF,cAAc,qBAAqB,CAAC"}
@@ -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
+ // The Monaco entry (`@hydranium/client-browser/monaco`). Behind a subpath because
26
+ // `monaco-editor-core` touches the DOM at load and has no Node entry, so the `.`
27
+ // barrel stays loadable by a host's Node tests and a page without Monaco.
28
+ __exportStar(require("./monaco-lsp-client"), exports);
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/monaco/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,kFAAkF;AAClF,iFAAiF;AACjF,0EAA0E;AAC1E,sDAAoC"}