@hydranium/glsp-server 1.0.0-next.16 → 1.0.0-next.160
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 +20 -5
- package/lib/browser/start-glsp-server-in-worker.d.ts +30 -39
- package/lib/browser/start-glsp-server-in-worker.d.ts.map +1 -1
- package/lib/browser/start-glsp-server-in-worker.js +45 -11
- package/lib/browser/start-glsp-server-in-worker.js.map +1 -1
- package/lib/command/hydranium-glsp-command-stack.d.ts +27 -0
- package/lib/command/hydranium-glsp-command-stack.d.ts.map +1 -0
- package/lib/command/hydranium-glsp-command-stack.js +53 -0
- package/lib/command/hydranium-glsp-command-stack.js.map +1 -0
- package/lib/command/hydranium-glsp-recording-command.d.ts +22 -22
- package/lib/command/hydranium-glsp-recording-command.d.ts.map +1 -1
- package/lib/command/hydranium-glsp-recording-command.js +25 -26
- package/lib/command/hydranium-glsp-recording-command.js.map +1 -1
- package/lib/command/index.d.ts +1 -0
- package/lib/command/index.d.ts.map +1 -1
- package/lib/command/index.js +1 -0
- package/lib/command/index.js.map +1 -1
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.d.ts +12 -3
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.d.ts.map +1 -1
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.js +18 -2
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.js.map +1 -1
- package/lib/launcher/glsp-server-overrides.d.ts +10 -8
- package/lib/launcher/glsp-server-overrides.d.ts.map +1 -1
- package/lib/launcher/glsp-server-overrides.js +25 -11
- package/lib/launcher/glsp-server-overrides.js.map +1 -1
- package/lib/launcher/hydranium-glsp-server.d.ts +14 -10
- package/lib/launcher/hydranium-glsp-server.d.ts.map +1 -1
- package/lib/launcher/hydranium-glsp-server.js +20 -10
- package/lib/launcher/hydranium-glsp-server.js.map +1 -1
- package/lib/messages/index.d.ts +24 -0
- package/lib/messages/index.d.ts.map +1 -0
- package/lib/messages/index.js +24 -0
- package/lib/messages/index.js.map +1 -0
- package/lib/node/start-glsp-server.d.ts +1 -1
- package/lib/node/start-glsp-server.d.ts.map +1 -1
- package/lib/node/start-glsp-server.js +3 -4
- package/lib/node/start-glsp-server.js.map +1 -1
- package/lib/state/abstract-hydranium-glsp-state.d.ts +110 -43
- package/lib/state/abstract-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/abstract-hydranium-glsp-state.js +139 -60
- package/lib/state/abstract-hydranium-glsp-state.js.map +1 -1
- package/lib/state/full-text-hydranium-glsp-state.d.ts +6 -6
- package/lib/state/full-text-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/full-text-hydranium-glsp-state.js +6 -10
- package/lib/state/full-text-hydranium-glsp-state.js.map +1 -1
- package/lib/state/reconcile-source-model-write.d.ts +9 -8
- package/lib/state/reconcile-source-model-write.d.ts.map +1 -1
- package/lib/state/reconcile-source-model-write.js +8 -8
- package/lib/state/reconcile-source-model-write.js.map +1 -1
- package/lib/state/reconciling-multi-document-glsp-state.d.ts +59 -59
- package/lib/state/reconciling-multi-document-glsp-state.d.ts.map +1 -1
- package/lib/state/reconciling-multi-document-glsp-state.js +84 -82
- package/lib/state/reconciling-multi-document-glsp-state.js.map +1 -1
- package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts +19 -18
- package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/reconciling-transfer-hydranium-glsp-state.js +26 -30
- package/lib/state/reconciling-transfer-hydranium-glsp-state.js.map +1 -1
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.d.ts +30 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.d.ts.map +1 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.js +47 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.js.map +1 -0
- package/lib/storage/hydranium-glsp-storage.d.ts +313 -86
- package/lib/storage/hydranium-glsp-storage.d.ts.map +1 -1
- package/lib/storage/hydranium-glsp-storage.js +456 -104
- package/lib/storage/hydranium-glsp-storage.js.map +1 -1
- package/lib/storage/index.d.ts +2 -1
- package/lib/storage/index.d.ts.map +1 -1
- package/lib/storage/index.js +2 -1
- package/lib/storage/index.js.map +1 -1
- package/lib/storage/save-delivery-policy.d.ts +46 -0
- package/lib/storage/save-delivery-policy.d.ts.map +1 -0
- package/lib/storage/{save-conflict-policy.js → save-delivery-policy.js} +7 -8
- package/lib/storage/save-delivery-policy.js.map +1 -0
- package/lib/testing/glsp-harness.js +4 -4
- package/lib/testing/glsp-harness.js.map +1 -1
- package/lib/validation/diagnostic-markers.d.ts +2 -2
- package/lib/validation/diagnostic-markers.d.ts.map +1 -1
- package/lib/validation/diagnostic-markers.js +7 -0
- package/lib/validation/diagnostic-markers.js.map +1 -1
- package/lib/validation/hydranium-glsp-model-validator.d.ts.map +1 -1
- package/lib/validation/hydranium-glsp-model-validator.js +1 -1
- package/lib/validation/hydranium-glsp-model-validator.js.map +1 -1
- package/package.json +17 -8
- package/src/browser/start-glsp-server-in-worker.ts +43 -47
- package/src/command/hydranium-glsp-command-stack.ts +36 -0
- package/src/command/hydranium-glsp-recording-command.ts +26 -26
- package/src/command/index.ts +1 -0
- package/src/launcher/abstract-hydranium-glsp-diagram-module.ts +27 -3
- package/src/launcher/glsp-server-overrides.ts +27 -11
- package/src/launcher/hydranium-glsp-server.ts +20 -10
- package/src/messages/index.ts +30 -0
- package/src/node/start-glsp-server.ts +3 -5
- package/src/state/abstract-hydranium-glsp-state.ts +174 -73
- package/src/state/full-text-hydranium-glsp-state.ts +7 -11
- package/src/state/reconcile-source-model-write.ts +18 -15
- package/src/state/reconciling-multi-document-glsp-state.ts +86 -83
- package/src/state/reconciling-transfer-hydranium-glsp-state.ts +27 -31
- package/src/storage/hydranium-glsp-request-save-model-action-handler.ts +40 -0
- package/src/storage/hydranium-glsp-storage.ts +520 -113
- package/src/storage/index.ts +2 -1
- package/src/storage/save-delivery-policy.ts +44 -0
- package/src/testing/glsp-harness.ts +4 -4
- package/src/validation/diagnostic-markers.ts +10 -3
- package/src/validation/hydranium-glsp-model-validator.ts +3 -3
- package/lib/storage/save-conflict-policy.d.ts +0 -56
- package/lib/storage/save-conflict-policy.d.ts.map +0 -1
- package/lib/storage/save-conflict-policy.js.map +0 -1
- package/src/storage/save-conflict-policy.ts +0 -52
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { type AnyObject, type JsonModelState, JsonRecordingCommand, type MaybePromise } from '@eclipse-glsp/server';
|
|
11
11
|
import { type AstNode } from '@hydranium/langium';
|
|
12
12
|
import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
|
|
13
|
+
import { type BasedOn } from '@hydranium/protocol';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Source-model state shape consumed by {@link HydraniumGlspRecordingCommand}.
|
|
@@ -46,25 +47,25 @@ export type HydraniumGlspRecordingState<TSourceModel extends AnyObject> = Abstra
|
|
|
46
47
|
*
|
|
47
48
|
* **postChange semantics.** GLSP's `JsonRecordingCommand.postChange` calls
|
|
48
49
|
* `modelState.updateSourceModel(newModel)` with the model only. The
|
|
49
|
-
* framework lift overrides `postChange` so it also threads the
|
|
50
|
-
* version
|
|
51
|
-
* `
|
|
52
|
-
* postChange calls
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
50
|
+
* framework lift overrides `postChange` so it also threads the snapshot
|
|
51
|
+
* version taken at command start — letting the downstream
|
|
52
|
+
* session `update` opt into the `ConflictError` gate. Undo / redo
|
|
53
|
+
* postChange calls pass `'anything'`: the user authored against the recorded
|
|
54
|
+
* patch, not against a specific server version, so re-applying it should
|
|
55
|
+
* succeed regardless of intervening edits. The recorded patch itself encodes
|
|
56
|
+
* the semantic intent.
|
|
56
57
|
*/
|
|
57
58
|
export class HydraniumGlspRecordingCommand<TSourceModel extends AnyObject> extends JsonRecordingCommand<TSourceModel> {
|
|
58
59
|
declare protected modelState: HydraniumGlspRecordingState<TSourceModel>;
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
|
-
*
|
|
62
|
-
* {@link postChange} so
|
|
63
|
-
*
|
|
64
|
-
* returns so undo / redo paths fall through
|
|
65
|
-
*
|
|
62
|
+
* What the command was authored against, taken at {@link execute} start and
|
|
63
|
+
* threaded into {@link postChange} so
|
|
64
|
+
* {@link AbstractHydraniumGlspState.updateSourceModel} gates on it. Reset to
|
|
65
|
+
* `'anything'` after `execute` returns so undo / redo paths fall through
|
|
66
|
+
* ungated.
|
|
66
67
|
*/
|
|
67
|
-
protected
|
|
68
|
+
protected activeBasedOn: BasedOn = 'anything';
|
|
68
69
|
|
|
69
70
|
/**
|
|
70
71
|
* Source-model snapshots captured at {@link execute} — the state the
|
|
@@ -98,20 +99,19 @@ export class HydraniumGlspRecordingCommand<TSourceModel extends AnyObject> exten
|
|
|
98
99
|
* via {@link AbstractHydraniumGlspState.updateSourceModel}). The label combines
|
|
99
100
|
* the operation name with the source-uri-stamped logger.
|
|
100
101
|
*
|
|
101
|
-
*
|
|
102
|
-
* can thread
|
|
103
|
-
*
|
|
104
|
-
* see a stale captured version.
|
|
102
|
+
* Takes {@link AbstractHydraniumGlspState.basedOn} at start so {@link postChange}
|
|
103
|
+
* can thread it into `updateSourceModel`. Scoped with `try`/`finally` so undo
|
|
104
|
+
* / redo paths invoked later do not see a stale value.
|
|
105
105
|
*/
|
|
106
106
|
override async execute(): Promise<void> {
|
|
107
107
|
const logger = this.modelState.logger.for('HydraniumGlspRecordingCommand');
|
|
108
|
-
this.
|
|
109
|
-
logger.debug(`Executing '${this.label}' (based-on doc.version=v${this.
|
|
108
|
+
this.activeBasedOn = this.modelState.basedOn;
|
|
109
|
+
logger.debug(`Executing '${this.label}' (based-on doc.version=v${this.modelState.version})`);
|
|
110
110
|
this.beforeSnapshot = this.deepClone(await this.getJsonObject());
|
|
111
111
|
try {
|
|
112
112
|
await this.modelState.tracer.for('HydraniumGlspRecordingCommand').time(`Execute command '${this.label}'`, () => super.execute());
|
|
113
113
|
} finally {
|
|
114
|
-
this.
|
|
114
|
+
this.activeBasedOn = 'anything';
|
|
115
115
|
}
|
|
116
116
|
this.afterSnapshot = this.deepClone(await this.getJsonObject());
|
|
117
117
|
}
|
|
@@ -119,15 +119,15 @@ export class HydraniumGlspRecordingCommand<TSourceModel extends AnyObject> exten
|
|
|
119
119
|
/**
|
|
120
120
|
* Override of GLSP's {@link JsonRecordingCommand.postChange} so the
|
|
121
121
|
* call to {@link AbstractHydraniumGlspState.updateSourceModel} threads the
|
|
122
|
-
*
|
|
122
|
+
* based-on version alongside the new model.
|
|
123
123
|
*
|
|
124
|
-
* During {@link execute}
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
124
|
+
* During {@link execute} it is the snapshot version taken at command start;
|
|
125
|
+
* during {@link undo} / {@link redo} it is `'anything'` — replaying a
|
|
126
|
+
* recorded patch does not author against a specific server version, so no
|
|
127
|
+
* gate applies.
|
|
128
128
|
*/
|
|
129
129
|
protected override postChange(newModel: TSourceModel): MaybePromise<void> {
|
|
130
|
-
return this.modelState.updateSourceModel(newModel, this.
|
|
130
|
+
return this.modelState.updateSourceModel(newModel, this.activeBasedOn);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
package/src/command/index.ts
CHANGED
|
@@ -7,11 +7,19 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type ActionHandlerConstructor,
|
|
12
|
+
type BindingTarget,
|
|
13
|
+
type CommandStack,
|
|
14
|
+
DiagramModule,
|
|
15
|
+
type InstanceMultiBinding
|
|
16
|
+
} from '@eclipse-glsp/server';
|
|
11
17
|
import { injectable, type interfaces } from 'inversify';
|
|
12
18
|
import type { LanguageMetaData } from '@hydranium/langium';
|
|
13
19
|
import { type ServerLanguageServices, type ServerSharedServices, typedMetadata } from '@hydranium/core';
|
|
14
20
|
import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
|
|
21
|
+
import { HydraniumGlspRequestSaveModelActionHandler } from '../storage/hydranium-glsp-request-save-model-action-handler.js';
|
|
22
|
+
import { HydraniumGlspCommandStack } from '../command/hydranium-glsp-command-stack.js';
|
|
15
23
|
|
|
16
24
|
/**
|
|
17
25
|
* Bind {@link HydraniumTypes}.DiagramLanguage on a GLSP **session** container
|
|
@@ -20,8 +28,10 @@ import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
|
|
|
20
28
|
* Exported separately from {@link AbstractHydraniumGlspDiagramModule} for adopters
|
|
21
29
|
* whose diagram module already extends an intermediate base of their own and
|
|
22
30
|
* cannot take the framework base class; call it from `configure` after
|
|
23
|
-
* `super.configure(...)
|
|
24
|
-
*
|
|
31
|
+
* `super.configure(...)`, add {@link HydraniumGlspRequestSaveModelActionHandler}
|
|
32
|
+
* in `configureActionHandlers`, and return {@link HydraniumGlspCommandStack} from
|
|
33
|
+
* `bindCommandStack`, all of which the base also does. The base class is the
|
|
34
|
+
* preferred entry point because it makes the declaration non-optional.
|
|
25
35
|
*
|
|
26
36
|
* **Why the session tier.** GLSP builds its app container once per process,
|
|
27
37
|
* before any document exists, so a per-language service bound there can only
|
|
@@ -114,4 +124,18 @@ export abstract class AbstractHydraniumGlspDiagramModule extends DiagramModule {
|
|
|
114
124
|
super.configure(bind, unbind, isBound, rebind);
|
|
115
125
|
bindDiagramLanguage(bind, this.declareLanguage());
|
|
116
126
|
}
|
|
127
|
+
|
|
128
|
+
/** {@link HydraniumGlspCommandStack}, so the diagram is dirty exactly while a document it has open is. */
|
|
129
|
+
protected override bindCommandStack(): BindingTarget<CommandStack> {
|
|
130
|
+
return HydraniumGlspCommandStack;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Adds {@link HydraniumGlspRequestSaveModelActionHandler}, the save the
|
|
135
|
+
* Theia client sends, beside GLSP's own save handler.
|
|
136
|
+
*/
|
|
137
|
+
protected override configureActionHandlers(binding: InstanceMultiBinding<ActionHandlerConstructor>): void {
|
|
138
|
+
super.configureActionHandlers(binding);
|
|
139
|
+
binding.add(HydraniumGlspRequestSaveModelActionHandler);
|
|
140
|
+
}
|
|
117
141
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import { GLSPServer } from '@eclipse-glsp/server';
|
|
10
|
+
import { DefaultGLSPServer, GLSPServer, LoggerFactory } from '@eclipse-glsp/server';
|
|
11
11
|
import { ContainerModule } from 'inversify';
|
|
12
12
|
import { HydraniumGlspServer } from './hydranium-glsp-server.js';
|
|
13
13
|
|
|
@@ -18,15 +18,17 @@ import { HydraniumGlspServer } from './hydranium-glsp-server.js';
|
|
|
18
18
|
*
|
|
19
19
|
* **The tier matters, and the app container cannot stand in for it.** GLSP's
|
|
20
20
|
* launcher creates the server container as a child and loads the adopter's
|
|
21
|
-
* `ServerModule` into it
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* reach this symbol.
|
|
21
|
+
* `ServerModule` into it. The framework's server is a singleton of that
|
|
22
|
+
* container; bound in the app container, every connected application would
|
|
23
|
+
* share one server.
|
|
25
24
|
*
|
|
26
|
-
* **
|
|
27
|
-
* `GLSPServer
|
|
28
|
-
*
|
|
29
|
-
*
|
|
25
|
+
* **An adopter's server is kept when it extends {@link HydraniumGlspServer}.**
|
|
26
|
+
* Any other `GLSPServer` the adopter's `ServerModule` binds, upstream's default
|
|
27
|
+
* included, is replaced when the container first creates it, so a server that
|
|
28
|
+
* extends upstream's directly is discarded, with a warning naming its class.
|
|
29
|
+
* The replacement happens on activation because `rebind` would replace an
|
|
30
|
+
* adopter's subclass as well; the discarded server is constructed once and
|
|
31
|
+
* never used.
|
|
30
32
|
*
|
|
31
33
|
* Keeping this out of the adopter's hands is the point: an adopter passes their
|
|
32
34
|
* own `ServerModule` in, so anything they must add themselves is a fix the
|
|
@@ -40,7 +42,21 @@ import { HydraniumGlspServer } from './hydranium-glsp-server.js';
|
|
|
40
42
|
* a further adopter subclass moves it again.
|
|
41
43
|
*/
|
|
42
44
|
export function createGlspServerOverrides(): ContainerModule {
|
|
43
|
-
return new ContainerModule((
|
|
44
|
-
|
|
45
|
+
return new ContainerModule((bind, _unbind, _isBound, _rebind, _unbindAsync, onActivation) => {
|
|
46
|
+
bind(HydraniumGlspServer).toSelf().inSingletonScope();
|
|
47
|
+
onActivation<GLSPServer>(GLSPServer, (context, server) => {
|
|
48
|
+
if (server instanceof HydraniumGlspServer) {
|
|
49
|
+
return server;
|
|
50
|
+
}
|
|
51
|
+
if (server.constructor !== DefaultGLSPServer) {
|
|
52
|
+
context.container
|
|
53
|
+
.get<LoggerFactory>(LoggerFactory)('HydraniumGlspServer')
|
|
54
|
+
.warn(
|
|
55
|
+
`Replacing the bound GLSP server ${server.constructor.name} with HydraniumGlspServer; ` +
|
|
56
|
+
'extend HydraniumGlspServer to keep its behaviour.'
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return context.container.get(HydraniumGlspServer);
|
|
60
|
+
});
|
|
45
61
|
});
|
|
46
62
|
}
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type RequestAction,
|
|
16
16
|
type ResponseAction
|
|
17
17
|
} from '@eclipse-glsp/server';
|
|
18
|
+
import { RequestSaveModelAction } from '@hydranium/protocol';
|
|
18
19
|
import { injectable } from 'inversify';
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -26,9 +27,10 @@ import { injectable } from 'inversify';
|
|
|
26
27
|
* `error.cause?.toString()` whenever the error is a {@link GLSPServerError},
|
|
27
28
|
* and that one value feeds both the server log and the client's
|
|
28
29
|
* {@link RejectAction}. A {@link GLSPServerError} carrying no `cause` therefore
|
|
29
|
-
* reaches
|
|
30
|
-
* while a plain `Error` survives,
|
|
31
|
-
* itself. The typed error is the trap,
|
|
30
|
+
* reaches its readers as `undefined` — the log line and the client's
|
|
31
|
+
* action-dispatcher warning both print it — while a plain `Error` survives,
|
|
32
|
+
* because the other branch reads the error itself. The typed error is the trap,
|
|
33
|
+
* and it is the one upstream's own
|
|
32
34
|
* `getOrThrow` helper raises: that helper's signature cannot pass a `cause`, so
|
|
33
35
|
* an adopter using the sanctioned helper has no fix available on their side.
|
|
34
36
|
* Restating the cause at each throw site is the alternative, and it costs
|
|
@@ -37,10 +39,10 @@ import { injectable } from 'inversify';
|
|
|
37
39
|
* Only the REQUEST path needs this. Non-request actions fail through
|
|
38
40
|
* upstream's `handleProcessError`, which reads `message` directly.
|
|
39
41
|
*
|
|
40
|
-
*
|
|
41
|
-
* {@link DefaultGLSPServer}
|
|
42
|
-
*
|
|
43
|
-
* server
|
|
42
|
+
* An adopter who binds their own GLSP server extends this class rather than
|
|
43
|
+
* {@link DefaultGLSPServer}: the framework's server-container override keeps a
|
|
44
|
+
* server that extends this one and replaces any other, so a subclass of
|
|
45
|
+
* upstream's server is discarded.
|
|
44
46
|
*/
|
|
45
47
|
@injectable()
|
|
46
48
|
export class HydraniumGlspServer extends DefaultGLSPServer {
|
|
@@ -63,9 +65,12 @@ export class HydraniumGlspServer extends DefaultGLSPServer {
|
|
|
63
65
|
/**
|
|
64
66
|
* Lifted verbatim from `@eclipse-glsp/server` 2.7.0's
|
|
65
67
|
* {@link DefaultGLSPServer.handleClientRequest}, with the detail computation
|
|
66
|
-
* delegated to {@link requestFailureDetail}
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* delegated to {@link requestFailureDetail}, and one addition: a failed
|
|
69
|
+
* {@link RequestSaveModelAction} also raises the error notification a failed
|
|
70
|
+
* `SaveModelAction` raises. A rejection reaches only the client's log, and a
|
|
71
|
+
* Theia host only logs a rejected save, so without it a save that failed
|
|
72
|
+
* would tell the user nothing. Nothing else here — the timeout branch, the
|
|
73
|
+
* response dispatch, the nested send-failure handling — relates to either.
|
|
69
74
|
*
|
|
70
75
|
* **This body does not track upstream.** A release that changes request
|
|
71
76
|
* handling would silently not apply, on the path every request takes. There
|
|
@@ -96,6 +101,11 @@ export class HydraniumGlspServer extends DefaultGLSPServer {
|
|
|
96
101
|
detail
|
|
97
102
|
});
|
|
98
103
|
this.sendResponseToClient(clientId, reject);
|
|
104
|
+
// Inside the guard: `process` does not await this method, so a
|
|
105
|
+
// closed connection throwing here would be an unhandled rejection.
|
|
106
|
+
if (action.kind === RequestSaveModelAction.KIND) {
|
|
107
|
+
this.handleProcessError({ clientId, action }, error);
|
|
108
|
+
}
|
|
99
109
|
} catch (sendError: unknown) {
|
|
100
110
|
this.logger.error(`Failed to send rejection for request '${action.requestId}':`, sendError);
|
|
101
111
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
* Every user-facing message `@hydranium/glsp-server` raises.
|
|
12
|
+
*
|
|
13
|
+
* **Each one is rendered AT ITS RAISE SITE**, through the shared
|
|
14
|
+
* `MessageRenderer`, because GLSP's action protocol carries no slot for an
|
|
15
|
+
* identity on any of its actions — so the identity is gone the moment a raise
|
|
16
|
+
* site formats its text, and there is nothing at the error boundary to render
|
|
17
|
+
* from. That makes this head the one place where a new message can ship
|
|
18
|
+
* unrendered without any single chokepoint noticing, which is why the package's
|
|
19
|
+
* own test suite scans for a declaration reached by `.format()` instead.
|
|
20
|
+
*
|
|
21
|
+
* The barrel is also how an adopter rendering their own diagram chrome
|
|
22
|
+
* discovers the codes exist.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
DIAGRAM_READONLY_PARSE_ERROR,
|
|
27
|
+
DIAGRAM_SESSION_REFUSED,
|
|
28
|
+
SAVE_TARGET_UNKNOWN,
|
|
29
|
+
SOURCE_URI_MISSING
|
|
30
|
+
} from '../storage/hydranium-glsp-storage.js';
|
|
@@ -16,8 +16,7 @@ import {
|
|
|
16
16
|
defaultSocketLaunchOptions
|
|
17
17
|
} from '@eclipse-glsp/server/node.js';
|
|
18
18
|
import { Container, type ContainerModule } from 'inversify';
|
|
19
|
-
import type
|
|
20
|
-
import { Deferred } from '@hydranium/langium';
|
|
19
|
+
import { Deferred, type Logger } from '@hydranium/protocol';
|
|
21
20
|
import type * as net from 'node:net';
|
|
22
21
|
import type { IntegratedServer } from '@hydranium/core';
|
|
23
22
|
import { createGlspFrameworkOverrides } from '../launcher/glsp-framework-overrides.js';
|
|
@@ -155,8 +154,7 @@ export function startGlspServer(options: GlspServerOptions): StartedGlspServer {
|
|
|
155
154
|
const launcher = appContainer.resolve<SocketServerLauncher>(SocketServerLauncher);
|
|
156
155
|
// Passed as an additional module rather than folded into the app container:
|
|
157
156
|
// the launcher loads these into the per-connection SERVER container, which is
|
|
158
|
-
// the
|
|
159
|
-
// can be rebound.
|
|
157
|
+
// the tier where each connection gets a server of its own.
|
|
160
158
|
launcher.configure(options.serverModule, createGlspServerOverrides());
|
|
161
159
|
|
|
162
160
|
const started = new Deferred<void>();
|
|
@@ -177,7 +175,7 @@ export function startGlspServer(options: GlspServerOptions): StartedGlspServer {
|
|
|
177
175
|
if (options.lspConnection && options.portCommand) {
|
|
178
176
|
options.lspConnection.onRequest(options.portCommand, () => portHandle.port);
|
|
179
177
|
}
|
|
180
|
-
lifecycle?.info(`[GlspServer] Ready to accept new client requests on port: ${address.port}`);
|
|
178
|
+
lifecycle?.info(`[GlspServer] Ready to accept new client requests on ${address.address} port: ${address.port}`);
|
|
181
179
|
started.resolve();
|
|
182
180
|
} else {
|
|
183
181
|
const message = address === null ? 'address is null' : `bound to non-TCP "${String(address)}"`;
|