@eclipse-glsp/protocol 2.7.0-next.24 → 2.7.0-next.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/action-protocol/model-saving.d.ts +140 -5
- package/lib/action-protocol/model-saving.d.ts.map +1 -1
- package/lib/action-protocol/model-saving.js +40 -1
- package/lib/action-protocol/model-saving.js.map +1 -1
- package/lib/action-protocol/viewport.d.ts +22 -1
- package/lib/action-protocol/viewport.d.ts.map +1 -1
- package/lib/action-protocol/viewport.js +17 -1
- package/lib/action-protocol/viewport.js.map +1 -1
- package/lib/client-server-protocol/base-glsp-client.d.ts +2 -2
- package/lib/client-server-protocol/base-glsp-client.d.ts.map +1 -1
- package/lib/client-server-protocol/base-glsp-client.js +3 -2
- package/lib/client-server-protocol/base-glsp-client.js.map +1 -1
- package/lib/client-server-protocol/glsp-client.d.ts +7 -2
- package/lib/client-server-protocol/glsp-client.d.ts.map +1 -1
- package/lib/client-server-protocol/glsp-client.js.map +1 -1
- package/lib/client-server-protocol/glsp-server.d.ts +18 -1
- package/lib/client-server-protocol/glsp-server.d.ts.map +1 -1
- package/lib/client-server-protocol/glsp-server.js +3 -2
- package/lib/client-server-protocol/glsp-server.js.map +1 -1
- package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.d.ts +1 -1
- package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.d.ts.map +1 -1
- package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.js +4 -3
- package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.js.map +1 -1
- package/lib/client-server-protocol/mcp.d.ts +225 -0
- package/lib/client-server-protocol/mcp.d.ts.map +1 -0
- package/lib/client-server-protocol/mcp.js +75 -0
- package/lib/client-server-protocol/mcp.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/action-protocol/model-saving.spec.ts +126 -1
- package/src/action-protocol/model-saving.ts +170 -6
- package/src/action-protocol/viewport.spec.ts +37 -1
- package/src/action-protocol/viewport.ts +33 -1
- package/src/client-server-protocol/base-glsp-client.spec.ts +21 -6
- package/src/client-server-protocol/base-glsp-client.ts +3 -2
- package/src/client-server-protocol/glsp-client.ts +7 -3
- package/src/client-server-protocol/glsp-server.ts +19 -1
- package/src/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.spec.ts +10 -1
- package/src/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.ts +4 -3
- package/src/client-server-protocol/mcp.ts +256 -0
- package/src/index.ts +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2021-
|
|
2
|
+
* Copyright (c) 2021-2026 STMicroelectronics and others.
|
|
3
3
|
*
|
|
4
4
|
* This program and the accompanying materials are made available under the
|
|
5
5
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
16
|
import * as sprotty from 'sprotty-protocol/lib/actions';
|
|
17
|
-
import { hasBooleanProp, hasStringProp } from '../utils/type-util';
|
|
17
|
+
import { ProposalString, hasBooleanProp, hasStringProp } from '../utils/type-util';
|
|
18
18
|
import { Action, RequestAction, ResponseAction } from './base-protocol';
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -84,9 +84,12 @@ export namespace SetDirtyStateAction {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
|
-
* A
|
|
87
|
+
* A {@link RequestExportSvgAction} is sent by the client (or the server) to initiate the SVG export of the current diagram.
|
|
88
88
|
* The handler of this action is expected to retrieve the diagram SVG and should send a {@link ExportSvgAction} as response.
|
|
89
89
|
* Typically the {@link ExportSvgAction} is handled directly on client side.
|
|
90
|
+
*
|
|
91
|
+
* @deprecated Use the unified {@link RequestExportAction} (with `format: 'svg'`) and
|
|
92
|
+
* {@link ExportResultAction} pair instead.
|
|
90
93
|
*/
|
|
91
94
|
export interface RequestExportSvgAction extends RequestAction<ExportSvgAction>, sprotty.RequestExportSvgAction {
|
|
92
95
|
kind: typeof RequestExportSvgAction.KIND;
|
|
@@ -108,18 +111,21 @@ export namespace RequestExportSvgAction {
|
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
/** Configuration options for the {@link RequestExportSvgAction */
|
|
114
|
+
/** Configuration options for the {@link RequestExportSvgAction} */
|
|
112
115
|
export interface ExportSvgOptions extends sprotty.ExportSvgOptions {
|
|
113
116
|
// If set to false applied diagram styles will not be copied to the exported SVG
|
|
114
117
|
skipCopyStyles?: boolean;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
/**
|
|
118
|
-
* The client sends an
|
|
121
|
+
* The client sends an {@link ExportSvgAction} to indicate that the diagram, which represents the current model state,
|
|
119
122
|
* should be exported in SVG format. The action only provides the diagram SVG as plain string. The expected result of executing
|
|
120
|
-
* an
|
|
123
|
+
* an {@link ExportSvgAction} is a new file in SVG-format on the underlying filesystem. However, other details like the target destination,
|
|
121
124
|
* concrete file name, file extension etc. are not specified in the protocol. So it is the responsibility of the action handler to
|
|
122
125
|
* process this information accordingly and export the result to the underlying filesystem.
|
|
126
|
+
*
|
|
127
|
+
* @deprecated Use {@link ExportResultAction} as the response to a unified
|
|
128
|
+
* {@link RequestExportAction} instead.
|
|
123
129
|
*/
|
|
124
130
|
export interface ExportSvgAction extends ResponseAction, sprotty.ExportSvgAction {
|
|
125
131
|
kind: typeof ExportSvgAction.KIND;
|
|
@@ -143,3 +149,161 @@ export namespace ExportSvgAction {
|
|
|
143
149
|
};
|
|
144
150
|
}
|
|
145
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Format identifier for a diagram export. The package ships `'svg'` and `'png'`;
|
|
155
|
+
* adopters add formats by registering a `DiagramExporter` strategy keyed on any string.
|
|
156
|
+
*/
|
|
157
|
+
export type ExportFormat = ProposalString<'svg' | 'png'>;
|
|
158
|
+
|
|
159
|
+
/** MIME type returned alongside an export. */
|
|
160
|
+
export type ExportMimeType = ProposalString<'image/svg+xml' | 'image/png'>;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Encoding of the bytes carried in {@link ExportResultAction.data}. The package ships
|
|
164
|
+
* `'text'` (UTF-8 markup, e.g. SVG) and `'base64'` (binary blobs, e.g. PNG); adopters
|
|
165
|
+
* registering a strategy with a different runtime declare their own encoding tag.
|
|
166
|
+
* Receivers must reject encodings they don't understand explicitly; silently treating an
|
|
167
|
+
* unknown value as one of the shipped ones corrupts payloads.
|
|
168
|
+
*/
|
|
169
|
+
export type ExportEncoding = ProposalString<'text' | 'base64'>;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Options shared by every export strategy that renders through sprotty's SVG export pipeline.
|
|
173
|
+
* Today honoured by SVG output and the canvas-based PNG rasteriser; future strategies that
|
|
174
|
+
* also raster from SVG (PDF, PPTX, ...) would extend this interface for the same knob.
|
|
175
|
+
*/
|
|
176
|
+
export interface SvgRenderOptions {
|
|
177
|
+
/**
|
|
178
|
+
* Skip the per-element style-copy step. The default copy walk is expensive on large
|
|
179
|
+
* diagrams; setting this flag skips it at the cost of losing CSS-driven styling in the
|
|
180
|
+
* exported output.
|
|
181
|
+
*/
|
|
182
|
+
skipCopyStyles?: boolean;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* SVG-specific options carried inside {@link RequestExportAction.formatOptions} for the SVG
|
|
187
|
+
* export strategy. Mirrors {@link ExportSvgOptions} so callers migrating from the legacy
|
|
188
|
+
* {@link RequestExportSvgAction} retain feature parity.
|
|
189
|
+
*/
|
|
190
|
+
export interface SvgExportOptions extends SvgRenderOptions {}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* PNG-specific options carried inside {@link RequestExportAction.formatOptions} for the PNG
|
|
194
|
+
* export strategy. All fields optional — strategies fall back to sensible defaults. Inherits
|
|
195
|
+
* `skipCopyStyles` from {@link SvgRenderOptions} since PNG rasterises from SVG.
|
|
196
|
+
*/
|
|
197
|
+
export interface PngExportOptions extends SvgRenderOptions {
|
|
198
|
+
/** Output width in px. */
|
|
199
|
+
width?: number;
|
|
200
|
+
/** Output height in px. If omitted, height is derived to preserve the rendered aspect ratio. */
|
|
201
|
+
height?: number;
|
|
202
|
+
/** CSS colour painted as the canvas background before drawing the SVG. */
|
|
203
|
+
background?: string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Generic, format-agnostic export request. Sent client-to-self for UI-driven export
|
|
208
|
+
* flows, or server-to-client for server-orchestrated flows (e.g. an MCP tool requesting
|
|
209
|
+
* a PNG snapshot of the active diagram). The expected response is an
|
|
210
|
+
* {@link ExportResultAction} carrying the rendered bytes.
|
|
211
|
+
*
|
|
212
|
+
* `formatOptions` is opaque to the protocol — typed as `unknown` so the format-specific
|
|
213
|
+
* overloads of {@link RequestExportAction.create} can narrow it to {@link SvgExportOptions},
|
|
214
|
+
* {@link PngExportOptions}, or an adopter's own shape without an index-signature dance. The
|
|
215
|
+
* `DiagramExporter` for the given `format` validates the value at the strategy boundary.
|
|
216
|
+
*
|
|
217
|
+
* Coexists with the legacy {@link RequestExportSvgAction} under strict separation:
|
|
218
|
+
* legacy kind (`requestExportSvg`) → legacy action ({@link ExportSvgAction}) only; new kind
|
|
219
|
+
* (`requestExport`) → new action ({@link ExportResultAction}) only; never crossed.
|
|
220
|
+
*/
|
|
221
|
+
export interface RequestExportAction extends RequestAction<ExportResultAction> {
|
|
222
|
+
kind: typeof RequestExportAction.KIND;
|
|
223
|
+
format: ExportFormat;
|
|
224
|
+
formatOptions?: unknown;
|
|
225
|
+
}
|
|
226
|
+
export namespace RequestExportAction {
|
|
227
|
+
export const KIND = 'requestExport';
|
|
228
|
+
|
|
229
|
+
export function is(object: unknown): object is RequestExportAction {
|
|
230
|
+
return RequestAction.hasKind(object, KIND) && hasStringProp(object, 'format');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Typed overload for the shipped `'svg'` format — autocomplete on `formatOptions`. */
|
|
234
|
+
export function create(format: 'svg', options?: { formatOptions?: SvgExportOptions; requestId?: string }): RequestExportAction;
|
|
235
|
+
/** Typed overload for the shipped `'png'` format — autocomplete on `formatOptions`. */
|
|
236
|
+
export function create(format: 'png', options?: { formatOptions?: PngExportOptions; requestId?: string }): RequestExportAction;
|
|
237
|
+
/** General overload for adopter-registered formats; `formatOptions` is opaque. */
|
|
238
|
+
export function create(format: ExportFormat, options?: { formatOptions?: unknown; requestId?: string }): RequestExportAction;
|
|
239
|
+
export function create(format: ExportFormat, options: { formatOptions?: unknown; requestId?: string } = {}): RequestExportAction {
|
|
240
|
+
return {
|
|
241
|
+
kind: KIND,
|
|
242
|
+
format,
|
|
243
|
+
requestId: '',
|
|
244
|
+
...options
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Response to a {@link RequestExportAction} carrying the rendered diagram. Text-encoded
|
|
251
|
+
* payloads (e.g. SVG markup) ride in `data` directly; binary payloads (e.g. PNG) are
|
|
252
|
+
* base64-encoded with `encoding: 'base64'` so the action stays JSON-safe.
|
|
253
|
+
*/
|
|
254
|
+
export interface ExportResultAction extends ResponseAction {
|
|
255
|
+
kind: typeof ExportResultAction.KIND;
|
|
256
|
+
/** Echoes the requested format. */
|
|
257
|
+
format: ExportFormat;
|
|
258
|
+
mimeType: ExportMimeType;
|
|
259
|
+
encoding: ExportEncoding;
|
|
260
|
+
/** SVG markup (`encoding: 'text'`) or base64-encoded bytes (`encoding: 'base64'`). */
|
|
261
|
+
data: string;
|
|
262
|
+
/** Echoes the request's `formatOptions` so receivers can correlate result fields back to the request. */
|
|
263
|
+
formatOptions?: unknown;
|
|
264
|
+
}
|
|
265
|
+
export namespace ExportResultAction {
|
|
266
|
+
export const KIND = 'exportResult';
|
|
267
|
+
|
|
268
|
+
export function is(object: unknown): object is ExportResultAction {
|
|
269
|
+
return (
|
|
270
|
+
Action.hasKind(object, KIND) &&
|
|
271
|
+
hasStringProp(object, 'format') &&
|
|
272
|
+
hasStringProp(object, 'data') &&
|
|
273
|
+
hasStringProp(object, 'mimeType') &&
|
|
274
|
+
hasStringProp(object, 'encoding')
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Typed overload for the shipped `'svg'` format — typed echoed `formatOptions`. */
|
|
279
|
+
export function create(
|
|
280
|
+
format: 'svg',
|
|
281
|
+
data: string,
|
|
282
|
+
options: { mimeType: ExportMimeType; encoding: ExportEncoding; responseId?: string; formatOptions?: SvgExportOptions }
|
|
283
|
+
): ExportResultAction;
|
|
284
|
+
/** Typed overload for the shipped `'png'` format — typed echoed `formatOptions`. */
|
|
285
|
+
export function create(
|
|
286
|
+
format: 'png',
|
|
287
|
+
data: string,
|
|
288
|
+
options: { mimeType: ExportMimeType; encoding: ExportEncoding; responseId?: string; formatOptions?: PngExportOptions }
|
|
289
|
+
): ExportResultAction;
|
|
290
|
+
/** General overload for adopter-registered formats; echoed `formatOptions` is opaque. */
|
|
291
|
+
export function create(
|
|
292
|
+
format: ExportFormat,
|
|
293
|
+
data: string,
|
|
294
|
+
options: { mimeType: ExportMimeType; encoding: ExportEncoding; responseId?: string; formatOptions?: unknown }
|
|
295
|
+
): ExportResultAction;
|
|
296
|
+
export function create(
|
|
297
|
+
format: ExportFormat,
|
|
298
|
+
data: string,
|
|
299
|
+
options: { mimeType: ExportMimeType; encoding: ExportEncoding; responseId?: string; formatOptions?: unknown }
|
|
300
|
+
): ExportResultAction {
|
|
301
|
+
return {
|
|
302
|
+
kind: KIND,
|
|
303
|
+
format,
|
|
304
|
+
data,
|
|
305
|
+
responseId: '',
|
|
306
|
+
...options
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
********************************************************************************/
|
|
16
16
|
|
|
17
17
|
import { expect } from 'chai';
|
|
18
|
-
import { CenterAction, FitToScreenAction, MoveViewportAction } from './viewport';
|
|
18
|
+
import { CenterAction, FitToScreenAction, MoveViewportAction, OriginViewportAction } from './viewport';
|
|
19
19
|
|
|
20
20
|
describe('Viewport Actions', () => {
|
|
21
21
|
describe('CenterAction', () => {
|
|
@@ -133,4 +133,40 @@ describe('Viewport Actions', () => {
|
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
135
|
});
|
|
136
|
+
|
|
137
|
+
describe('OriginViewportAction', () => {
|
|
138
|
+
describe('is', () => {
|
|
139
|
+
it('should return true for an object having the correct type and a value for all required interface properties', () => {
|
|
140
|
+
const action: OriginViewportAction = {
|
|
141
|
+
kind: 'originViewport',
|
|
142
|
+
animate: true
|
|
143
|
+
};
|
|
144
|
+
expect(OriginViewportAction.is(action)).to.be.true;
|
|
145
|
+
});
|
|
146
|
+
it('should return false for `undefined`', () => {
|
|
147
|
+
expect(OriginViewportAction.is(undefined)).to.be.false;
|
|
148
|
+
});
|
|
149
|
+
it('should return false for an object that does not have all required interface properties', () => {
|
|
150
|
+
expect(OriginViewportAction.is({ kind: 'notTheRightOne' })).to.be.false;
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('create', () => {
|
|
155
|
+
it('should return an object conforming to the interface with default values for the optional arguments', () => {
|
|
156
|
+
const expected: OriginViewportAction = {
|
|
157
|
+
kind: 'originViewport',
|
|
158
|
+
animate: true
|
|
159
|
+
};
|
|
160
|
+
expect(OriginViewportAction.create()).to.deep.equals(expected);
|
|
161
|
+
});
|
|
162
|
+
it('should return an object conforming to the interface with matching properties for the given optional arguments', () => {
|
|
163
|
+
const expected: OriginViewportAction = {
|
|
164
|
+
kind: 'originViewport',
|
|
165
|
+
animate: false
|
|
166
|
+
};
|
|
167
|
+
const { animate } = expected;
|
|
168
|
+
expect(OriginViewportAction.create({ animate })).to.deep.equals(expected);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
});
|
|
136
172
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2021-
|
|
2
|
+
* Copyright (c) 2021-2026 STMicroelectronics and others.
|
|
3
3
|
*
|
|
4
4
|
* This program and the accompanying materials are made available under the
|
|
5
5
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
@@ -111,6 +111,38 @@ export namespace FitToScreenAction {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Resets the viewport to its origin (zoom 1, scroll 0). This is typically dispatched by the
|
|
116
|
+
* client (e.g., from the tool palette) but can also be sent by the server to reset the viewport
|
|
117
|
+
* remotely.
|
|
118
|
+
* The corresponding namespace declares the action kind as constant and offers helper functions for type guard checks
|
|
119
|
+
* and creating new `OriginViewportActions`.
|
|
120
|
+
*/
|
|
121
|
+
export interface OriginViewportAction extends Action {
|
|
122
|
+
kind: typeof OriginViewportAction.KIND;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Indicate if the modification of the viewport should be realized with or without support of animations.
|
|
126
|
+
*/
|
|
127
|
+
animate: boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export namespace OriginViewportAction {
|
|
131
|
+
export const KIND = 'originViewport';
|
|
132
|
+
|
|
133
|
+
export function is(object: unknown): object is OriginViewportAction {
|
|
134
|
+
return Action.hasKind(object, KIND) && hasBooleanProp(object, 'animate');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function create(options: { animate?: boolean } = {}): OriginViewportAction {
|
|
138
|
+
return {
|
|
139
|
+
kind: KIND,
|
|
140
|
+
animate: true,
|
|
141
|
+
...options
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
114
146
|
/**
|
|
115
147
|
* Moves the diagram canvas.
|
|
116
148
|
* The corresponding namespace declares the action kind as constant and offers helper functions for type guard checks
|
|
@@ -220,20 +220,35 @@ describe('Node GLSP Client', () => {
|
|
|
220
220
|
});
|
|
221
221
|
|
|
222
222
|
describe('shutdownServer', () => {
|
|
223
|
-
it('should fail if server is not configured', () => {
|
|
223
|
+
it('should fail if server is not configured', async () => {
|
|
224
224
|
resetClient(false);
|
|
225
|
-
|
|
225
|
+
// `shutdownServer` is now async; guard failures surface as a rejected promise.
|
|
226
|
+
let rejection: unknown;
|
|
227
|
+
try {
|
|
228
|
+
await client.shutdownServer();
|
|
229
|
+
} catch (err) {
|
|
230
|
+
rejection = err;
|
|
231
|
+
}
|
|
232
|
+
expect(rejection).to.be.instanceOf(Error);
|
|
233
|
+
expect((rejection as Error).message).to.match(/not in 'Running' state/);
|
|
226
234
|
expect(server.shutdown.called).to.be.false;
|
|
227
235
|
});
|
|
228
|
-
it('should fail if client is not running', () => {
|
|
236
|
+
it('should fail if client is not running', async () => {
|
|
229
237
|
resetClient(false);
|
|
230
238
|
client.configureServer(server);
|
|
231
|
-
|
|
239
|
+
let rejection: unknown;
|
|
240
|
+
try {
|
|
241
|
+
await client.shutdownServer();
|
|
242
|
+
} catch (err) {
|
|
243
|
+
rejection = err;
|
|
244
|
+
}
|
|
245
|
+
expect(rejection).to.be.instanceOf(Error);
|
|
246
|
+
expect((rejection as Error).message).to.match(/not in 'Running' state/);
|
|
232
247
|
expect(server.shutdown.called).to.be.false;
|
|
233
248
|
});
|
|
234
|
-
it('should invoke the corresponding server method', () => {
|
|
249
|
+
it('should invoke the corresponding server method', async () => {
|
|
235
250
|
resetClient();
|
|
236
|
-
client.shutdownServer();
|
|
251
|
+
await client.shutdownServer();
|
|
237
252
|
expect(server.shutdown.calledOnce).to.be.true;
|
|
238
253
|
});
|
|
239
254
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2023-
|
|
2
|
+
* Copyright (c) 2023-2026 EclipseSource and others.
|
|
3
3
|
*
|
|
4
4
|
* This program and the accompanying materials are made available under the
|
|
5
5
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
@@ -153,7 +153,8 @@ export class BaseGLSPClient implements GLSPClient {
|
|
|
153
153
|
return this.checkedServer.disposeClientSession(params);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
shutdownServer(): void {
|
|
156
|
+
async shutdownServer(): Promise<void> {
|
|
157
|
+
// Fire-and-forget at the proxy boundary; subclasses with a flushable send override.
|
|
157
158
|
this.checkedServer.shutdown();
|
|
158
159
|
}
|
|
159
160
|
|
|
@@ -18,7 +18,7 @@ import { v4 as uuid } from 'uuid';
|
|
|
18
18
|
import { ActionMessage } from '../action-protocol/base-protocol';
|
|
19
19
|
import { Disposable } from '../utils/disposable';
|
|
20
20
|
import { Event } from '../utils/event';
|
|
21
|
-
import { AnyObject, hasStringProp } from '../utils/type-util';
|
|
21
|
+
import { AnyObject, MaybePromise, hasStringProp } from '../utils/type-util';
|
|
22
22
|
import { DisposeClientSessionParameters, InitializeClientSessionParameters, InitializeParameters, InitializeResult } from './types';
|
|
23
23
|
|
|
24
24
|
export class ApplicationIdProvider {
|
|
@@ -131,9 +131,13 @@ export interface GLSPClient {
|
|
|
131
131
|
disposeClientSession(params: DisposeClientSessionParameters): Promise<void>;
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
|
-
* Send a `shutdown` notification to the server.
|
|
134
|
+
* Send a `shutdown` notification to the server. The return type is {@link MaybePromise} so
|
|
135
|
+
* pre-existing synchronous adopter implementations remain valid; new implementations should
|
|
136
|
+
* return a `Promise<void>` that resolves once the notification has been flushed to the wire,
|
|
137
|
+
* otherwise callers that dispose the connection immediately afterwards may race the pending
|
|
138
|
+
* notification and the server never sees the shutdown signal.
|
|
135
139
|
*/
|
|
136
|
-
shutdownServer(): void
|
|
140
|
+
shutdownServer(): MaybePromise<void>;
|
|
137
141
|
|
|
138
142
|
/**
|
|
139
143
|
* Stops the client and disposes unknown resources. During the stop procedure the client is in the `Stopping` state and will
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2022-
|
|
2
|
+
* Copyright (c) 2022-2026 STMicroelectronics and others.
|
|
3
3
|
*
|
|
4
4
|
* This program and the accompanying materials are made available under the
|
|
5
5
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
********************************************************************************/
|
|
16
16
|
|
|
17
17
|
import { ActionMessage } from '../action-protocol/base-protocol';
|
|
18
|
+
import { MaybePromise } from '../utils/type-util';
|
|
18
19
|
import { DisposeClientSessionParameters, InitializeClientSessionParameters, InitializeParameters, InitializeResult } from './types';
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -131,6 +132,23 @@ export interface GLSPServerListener {
|
|
|
131
132
|
}
|
|
132
133
|
export const GLSPServerListener = Symbol('GLSPServerListener');
|
|
133
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Contribution interface for extending the server initialization process.
|
|
137
|
+
* Implementations can modify the {@link InitializeResult} based on the provided {@link InitializeParameters}.
|
|
138
|
+
*/
|
|
139
|
+
export interface GLSPServerInitializer {
|
|
140
|
+
/**
|
|
141
|
+
* Handles the server initialization with the given parameters and allows to modify the initialization result.
|
|
142
|
+
*
|
|
143
|
+
* @param server The {@link GLSPServer} instance that is being initialized.
|
|
144
|
+
* @param params The {@link InitializeParameters} provided by the client.
|
|
145
|
+
* @param result The current {@link InitializeResult} that can be modified by the contribution.
|
|
146
|
+
* @returns The (possibly modified) {@link InitializeResult}.
|
|
147
|
+
*/
|
|
148
|
+
initializeServer(server: GLSPServer, params: InitializeParameters, result: InitializeResult): MaybePromise<InitializeResult>;
|
|
149
|
+
}
|
|
150
|
+
export const GLSPServerInitializer = Symbol('GLSPServerInitializer');
|
|
151
|
+
|
|
134
152
|
/**
|
|
135
153
|
* Communication proxy interface used by the GLSP servers to send action messages to clients.
|
|
136
154
|
* The default `JsonrpcClientProxy` used an underlying jsonrpc message connection for sending the action messages.
|
|
@@ -262,7 +262,16 @@ describe('Base JSON-RPC GLSP Client', () => {
|
|
|
262
262
|
await resetClient(false);
|
|
263
263
|
const stateChangeHandler = sinon.spy();
|
|
264
264
|
client.onCurrentStateChanged(stateChangeHandler);
|
|
265
|
-
|
|
265
|
+
// `shutdownServer` is now async; the connection-state guard rejects the returned
|
|
266
|
+
// promise rather than throwing synchronously.
|
|
267
|
+
let rejection: unknown;
|
|
268
|
+
try {
|
|
269
|
+
await client.shutdownServer();
|
|
270
|
+
} catch (err) {
|
|
271
|
+
rejection = err;
|
|
272
|
+
}
|
|
273
|
+
expect(rejection).to.be.instanceOf(Error);
|
|
274
|
+
expect((rejection as Error).message).to.equal(JsonrpcGLSPClient.ClientNotReadyMsg);
|
|
266
275
|
expect(connection.sendNotification.called).to.be.false;
|
|
267
276
|
expect(stateChangeHandler.called).to.be.false;
|
|
268
277
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2019-
|
|
2
|
+
* Copyright (c) 2019-2026 EclipseSource and others.
|
|
3
3
|
*
|
|
4
4
|
* This program and the accompanying materials are made available under the
|
|
5
5
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
@@ -125,8 +125,9 @@ export class BaseJsonrpcGLSPClient implements GLSPClient {
|
|
|
125
125
|
this.checkedConnection.sendNotification(JsonrpcGLSPClient.ActionMessageNotification, message);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
shutdownServer(): void {
|
|
129
|
-
|
|
128
|
+
async shutdownServer(): Promise<void> {
|
|
129
|
+
// Await the send so callers can dispose the connection without racing the wire flush.
|
|
130
|
+
await this.checkedConnection.sendNotification(JsonrpcGLSPClient.ShutdownNotification);
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
stop(): Promise<void> {
|