@hydranium/glsp-client-theia 1.0.0-next.10
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/LICENSE +21 -0
- package/README.md +134 -0
- package/lib/browser/action-dispatcher.d.ts +85 -0
- package/lib/browser/action-dispatcher.d.ts.map +1 -0
- package/lib/browser/action-dispatcher.js +238 -0
- package/lib/browser/action-dispatcher.js.map +1 -0
- package/lib/browser/client-contribution.d.ts +53 -0
- package/lib/browser/client-contribution.d.ts.map +1 -0
- package/lib/browser/client-contribution.js +111 -0
- package/lib/browser/client-contribution.js.map +1 -0
- package/lib/browser/diagram-loader.d.ts +123 -0
- package/lib/browser/diagram-loader.d.ts.map +1 -0
- package/lib/browser/diagram-loader.js +153 -0
- package/lib/browser/diagram-loader.js.map +1 -0
- package/lib/browser/diagram-only-marker-manager.d.ts +28 -0
- package/lib/browser/diagram-only-marker-manager.d.ts.map +1 -0
- package/lib/browser/diagram-only-marker-manager.js +44 -0
- package/lib/browser/diagram-only-marker-manager.js.map +1 -0
- package/lib/browser/diagram-widget.d.ts +97 -0
- package/lib/browser/diagram-widget.d.ts.map +1 -0
- package/lib/browser/diagram-widget.js +172 -0
- package/lib/browser/diagram-widget.js.map +1 -0
- package/lib/browser/glsp-client-theia-module.d.ts +40 -0
- package/lib/browser/glsp-client-theia-module.d.ts.map +1 -0
- package/lib/browser/glsp-client-theia-module.js +46 -0
- package/lib/browser/glsp-client-theia-module.js.map +1 -0
- package/lib/browser/glsp-diagram-manager.d.ts +46 -0
- package/lib/browser/glsp-diagram-manager.d.ts.map +1 -0
- package/lib/browser/glsp-diagram-manager.js +66 -0
- package/lib/browser/glsp-diagram-manager.js.map +1 -0
- package/lib/browser/glsp-message-service.d.ts +59 -0
- package/lib/browser/glsp-message-service.d.ts.map +1 -0
- package/lib/browser/glsp-message-service.js +97 -0
- package/lib/browser/glsp-message-service.js.map +1 -0
- package/lib/browser/glsp-theia-frontend-module.d.ts +110 -0
- package/lib/browser/glsp-theia-frontend-module.d.ts.map +1 -0
- package/lib/browser/glsp-theia-frontend-module.js +133 -0
- package/lib/browser/glsp-theia-frontend-module.js.map +1 -0
- package/lib/browser/hidden-bounds-updater.d.ts +122 -0
- package/lib/browser/hidden-bounds-updater.d.ts.map +1 -0
- package/lib/browser/hidden-bounds-updater.js +207 -0
- package/lib/browser/hidden-bounds-updater.js.map +1 -0
- package/lib/browser/hydranium-glsp-diagram-configuration.d.ts +52 -0
- package/lib/browser/hydranium-glsp-diagram-configuration.d.ts.map +1 -0
- package/lib/browser/hydranium-glsp-diagram-configuration.js +72 -0
- package/lib/browser/hydranium-glsp-diagram-configuration.js.map +1 -0
- package/lib/browser/index.d.ts +20 -0
- package/lib/browser/index.d.ts.map +1 -0
- package/lib/browser/index.js +38 -0
- package/lib/browser/index.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +39 -0
- package/lib/index.js.map +1 -0
- package/lib/node/connection-container-module.d.ts +22 -0
- package/lib/node/connection-container-module.d.ts.map +1 -0
- package/lib/node/connection-container-module.js +36 -0
- package/lib/node/connection-container-module.js.map +1 -0
- package/lib/node/glsp-server-connection-handler.d.ts +49 -0
- package/lib/node/glsp-server-connection-handler.d.ts.map +1 -0
- package/lib/node/glsp-server-connection-handler.js +64 -0
- package/lib/node/glsp-server-connection-handler.js.map +1 -0
- package/lib/node/index.d.ts +11 -0
- package/lib/node/index.d.ts.map +1 -0
- package/lib/node/index.js +28 -0
- package/lib/node/index.js.map +1 -0
- package/lib/testing/bind-recorder.d.ts +67 -0
- package/lib/testing/bind-recorder.d.ts.map +1 -0
- package/lib/testing/bind-recorder.js +72 -0
- package/lib/testing/bind-recorder.js.map +1 -0
- package/lib/testing/index.d.ts +10 -0
- package/lib/testing/index.d.ts.map +1 -0
- package/lib/testing/index.js +30 -0
- package/lib/testing/index.js.map +1 -0
- package/package.json +114 -0
- package/src/browser/action-dispatcher.ts +257 -0
- package/src/browser/client-contribution.ts +100 -0
- package/src/browser/diagram-loader.ts +173 -0
- package/src/browser/diagram-only-marker-manager.ts +33 -0
- package/src/browser/diagram-widget.ts +178 -0
- package/src/browser/glsp-client-theia-module.ts +54 -0
- package/src/browser/glsp-diagram-manager.ts +67 -0
- package/src/browser/glsp-message-service.ts +90 -0
- package/src/browser/glsp-theia-frontend-module.ts +157 -0
- package/src/browser/hidden-bounds-updater.ts +212 -0
- package/src/browser/hydranium-glsp-diagram-configuration.ts +63 -0
- package/src/browser/index.ts +22 -0
- package/src/index.ts +23 -0
- package/src/node/connection-container-module.ts +34 -0
- package/src/node/glsp-server-connection-handler.ts +69 -0
- package/src/node/index.ts +12 -0
- package/src/testing/bind-recorder.ts +126 -0
- package/src/testing/index.ts +15 -0
- package/style/diagram-loading.css +67 -0
|
@@ -0,0 +1,126 @@
|
|
|
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
|
+
import type { interfaces } from 'inversify';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* One captured `bind(...)` or `rebind(...)` call on a {@link BindRecorder}.
|
|
14
|
+
*
|
|
15
|
+
* `chain` holds the follow-up methods in invocation order, one string per call,
|
|
16
|
+
* rendered as `name(arg, …)`. Arguments are stringified inline so assertions
|
|
17
|
+
* can compare structure without re-resolving service identifiers.
|
|
18
|
+
*/
|
|
19
|
+
export interface BindRecorderEntry {
|
|
20
|
+
readonly kind: 'bind' | 'rebind';
|
|
21
|
+
readonly token: unknown;
|
|
22
|
+
readonly chain: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A spy set of Inversify binding hooks that records every call and its chain.
|
|
27
|
+
* Hand them to a module-factory under test — they satisfy Inversify's
|
|
28
|
+
* `interfaces.Bind` / `interfaces.Rebind` / `interfaces.Unbind` /
|
|
29
|
+
* `interfaces.IsBound` shapes at the call site but never resolve real services.
|
|
30
|
+
*
|
|
31
|
+
* Together they match GLSP's `BindingContext`, so a factory taking the whole
|
|
32
|
+
* context is called as `factory(recorder, options)` — the recorder *is*
|
|
33
|
+
* structurally a context.
|
|
34
|
+
*
|
|
35
|
+
* Use {@link captured} to assert which tokens were touched and with what
|
|
36
|
+
* fluent chain. {@link find} is a small ergonomic helper for the common
|
|
37
|
+
* lookup pattern.
|
|
38
|
+
*/
|
|
39
|
+
export interface BindRecorder {
|
|
40
|
+
readonly bind: interfaces.Bind;
|
|
41
|
+
readonly rebind: interfaces.Rebind;
|
|
42
|
+
readonly unbind: interfaces.Unbind;
|
|
43
|
+
readonly isBound: interfaces.IsBound;
|
|
44
|
+
readonly captured: readonly BindRecorderEntry[];
|
|
45
|
+
/** Convenience lookup — returns the first entry matching both `kind` and `token`, or `undefined`. */
|
|
46
|
+
find(kind: 'bind' | 'rebind', token: unknown): BindRecorderEntry | undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Options for {@link makeBindRecorder}. */
|
|
50
|
+
export interface BindRecorderOptions {
|
|
51
|
+
/**
|
|
52
|
+
* What `isBound` answers. Defaults to `true` for every token, matching
|
|
53
|
+
* production: a head registers its own module *after* the GLSP default
|
|
54
|
+
* modules, so the tokens a framework module rebinds are already bound. Pass a
|
|
55
|
+
* list to model a container where only those tokens are bound — e.g. to
|
|
56
|
+
* exercise a factory's bind-instead-of-rebind fallback.
|
|
57
|
+
*/
|
|
58
|
+
readonly boundTokens?: readonly unknown[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Methods on Inversify's binding builder that the recorder traps verbatim. */
|
|
62
|
+
const RECORDED_CHAIN_METHODS = [
|
|
63
|
+
'toSelf',
|
|
64
|
+
'to',
|
|
65
|
+
'toService',
|
|
66
|
+
'toConstantValue',
|
|
67
|
+
'toDynamicValue',
|
|
68
|
+
'toFactory',
|
|
69
|
+
'toFunction',
|
|
70
|
+
'toAutoFactory',
|
|
71
|
+
'toProvider',
|
|
72
|
+
'inSingletonScope',
|
|
73
|
+
'inTransientScope',
|
|
74
|
+
'inRequestScope',
|
|
75
|
+
'whenTargetNamed',
|
|
76
|
+
'whenTargetTagged',
|
|
77
|
+
'whenInjectedInto',
|
|
78
|
+
'onActivation',
|
|
79
|
+
'onDeactivation'
|
|
80
|
+
] as const;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Build a {@link BindRecorder} for testing Inversify module factories without a
|
|
84
|
+
* real container: hand it to the factory, then assert over {@link BindRecorder.find}.
|
|
85
|
+
*
|
|
86
|
+
* The `bind` / `rebind` functions return a chained proxy that ignores its
|
|
87
|
+
* arguments structurally but records every method invocation as a string.
|
|
88
|
+
* Stringification: functions → `<className>`, symbols → `Symbol(desc).toString()`,
|
|
89
|
+
* everything else → `String(value)`. This is enough to assert which tokens are
|
|
90
|
+
* involved without dragging real service resolution into the test.
|
|
91
|
+
*/
|
|
92
|
+
export function makeBindRecorder(options: BindRecorderOptions = {}): BindRecorder {
|
|
93
|
+
const captured: BindRecorderEntry[] = [];
|
|
94
|
+
|
|
95
|
+
const stringifyArg = (value: unknown): string => {
|
|
96
|
+
if (typeof value === 'function') {
|
|
97
|
+
return `<${value.name || 'fn'}>`;
|
|
98
|
+
}
|
|
99
|
+
if (typeof value === 'symbol') {
|
|
100
|
+
return value.toString();
|
|
101
|
+
}
|
|
102
|
+
return String(value);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const beginEntry = (kind: 'bind' | 'rebind', token: unknown): unknown => {
|
|
106
|
+
const entry: BindRecorderEntry = { kind, token, chain: [] };
|
|
107
|
+
captured.push(entry);
|
|
108
|
+
const proxy: Record<string, (...args: unknown[]) => unknown> = {};
|
|
109
|
+
for (const method of RECORDED_CHAIN_METHODS) {
|
|
110
|
+
proxy[method] = (...args: unknown[]): unknown => {
|
|
111
|
+
entry.chain.push(`${method}(${args.map(stringifyArg).join(', ')})`);
|
|
112
|
+
return proxy;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return proxy;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const bind = ((token: unknown) => beginEntry('bind', token)) as interfaces.Bind;
|
|
119
|
+
const rebind = ((token: unknown) => beginEntry('rebind', token)) as interfaces.Rebind;
|
|
120
|
+
const unbind = (() => undefined) as unknown as interfaces.Unbind;
|
|
121
|
+
const isBound = ((token: unknown) => options.boundTokens?.includes(token) ?? true) as interfaces.IsBound;
|
|
122
|
+
const find = (kind: 'bind' | 'rebind', token: unknown): BindRecorderEntry | undefined =>
|
|
123
|
+
captured.find(entry => entry.kind === kind && entry.token === token);
|
|
124
|
+
|
|
125
|
+
return { bind, rebind, unbind, isBound, captured, find };
|
|
126
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
// Subpath barrel for `@hydranium/glsp-client-theia/testing` — the
|
|
11
|
+
// GLSP-module-specific Inversify test double. The cross-head doubles
|
|
12
|
+
// (`makeStubOutputChannelManager`, `makeStubInversifyContext`) live in
|
|
13
|
+
// `@hydranium/client-theia/testing`, alongside the logger they double for.
|
|
14
|
+
|
|
15
|
+
export * from './bind-recorder';
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
/* Loading overlay shown by HydraniumGlspDiagramWidget until the diagram load
|
|
11
|
+
settles. Imported by the widget module itself, so an adopter cannot forget it;
|
|
12
|
+
every rule is overridable from an adopter stylesheet loaded afterwards.
|
|
13
|
+
Colours come from Theia theme variables, so light/dark follow the workbench. */
|
|
14
|
+
|
|
15
|
+
.hydranium-diagram-loading {
|
|
16
|
+
position: absolute;
|
|
17
|
+
inset: 0;
|
|
18
|
+
z-index: 10;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
gap: 12px;
|
|
24
|
+
background: var(--theia-editor-background);
|
|
25
|
+
color: var(--theia-descriptionForeground);
|
|
26
|
+
font-size: var(--theia-ui-font-size1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.hydranium-diagram-loading-spinner {
|
|
30
|
+
width: 40px;
|
|
31
|
+
height: 40px;
|
|
32
|
+
border: 4px solid var(--theia-editorWidget-border);
|
|
33
|
+
border-top-color: var(--theia-button-background);
|
|
34
|
+
border-radius: 50%;
|
|
35
|
+
/* transform-only, so the animation runs on the compositor and keeps turning
|
|
36
|
+
through a synchronous phase that blocks the main thread — which is exactly
|
|
37
|
+
when the user most needs to see that something is still happening. */
|
|
38
|
+
animation: hydranium-diagram-loading-spin 0.9s linear infinite;
|
|
39
|
+
will-change: transform;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@keyframes hydranium-diagram-loading-spin {
|
|
43
|
+
from {
|
|
44
|
+
transform: rotate(0deg);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
to {
|
|
48
|
+
transform: rotate(360deg);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Failure state: set only when the loader could NOT dispatch its error
|
|
53
|
+
StatusAction, so this overlay is the single remaining surface for the message.
|
|
54
|
+
The spinner goes (nothing is pending any more) and the text takes the error
|
|
55
|
+
colour. A load that failed and WAS reported never reaches this state — the
|
|
56
|
+
overlay is removed and GLSP's own status overlay shows it instead. */
|
|
57
|
+
.hydranium-diagram-loading-failed .hydranium-diagram-loading-spinner {
|
|
58
|
+
display: none;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.hydranium-diagram-loading-failed .hydranium-diagram-loading-label {
|
|
62
|
+
/* Wrap rather than clip: a load failure message can be long (a connection
|
|
63
|
+
error carries a URI), and it is the only copy the user gets here. */
|
|
64
|
+
max-width: 80%;
|
|
65
|
+
text-align: center;
|
|
66
|
+
color: var(--theia-errorForeground);
|
|
67
|
+
}
|