@hydranium/client-browser 1.0.0-next.303 → 1.0.0-next.305
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 +63 -14
- package/lib/language-client.d.ts +1 -1
- package/lib/language-client.d.ts.map +1 -1
- package/lib/language-client.js +6 -2
- package/lib/language-client.js.map +1 -1
- package/lib/monaco/index.d.ts +10 -0
- package/lib/monaco/index.d.ts.map +1 -0
- package/lib/monaco/index.js +29 -0
- package/lib/monaco/index.js.map +1 -0
- package/lib/monaco/monaco-lsp-client.d.ts +495 -0
- package/lib/monaco/monaco-lsp-client.d.ts.map +1 -0
- package/lib/monaco/monaco-lsp-client.js +1277 -0
- package/lib/monaco/monaco-lsp-client.js.map +1 -0
- package/package.json +17 -4
- package/src/language-client.ts +6 -3
- package/src/monaco/index.ts +13 -0
- package/src/monaco/monaco-lsp-client.ts +1462 -0
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,
|
|
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
|
-
| `
|
|
32
|
-
| `vscode-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
89
|
-
|
|
|
90
|
-
| `.`
|
|
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
|
|
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
|
|
package/lib/language-client.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
|
-
import type
|
|
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,
|
|
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"}
|
package/lib/language-client.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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;;;
|
|
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"}
|