@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# `@hydranium/glsp-client-theia`
|
|
2
|
+
|
|
3
|
+
Theia client primitives for the hydranium **GLSP head** — the companion of
|
|
4
|
+
`@hydranium/glsp-server` in the
|
|
5
|
+
[Hydranium](https://github.com/eclipse-emfcloud/hydranium) framework.
|
|
6
|
+
|
|
7
|
+
It sits between `@eclipse-glsp/theia-integration` and an adopter's diagram: the
|
|
8
|
+
module composition, the instrumented dispatcher and bounds updater, the loading
|
|
9
|
+
overlay, the marker-propagation switch, and the backend socket bridge. Install it
|
|
10
|
+
if you are mounting a hydranium GLSP diagram in a Theia application.
|
|
11
|
+
|
|
12
|
+
## What it gives you
|
|
13
|
+
|
|
14
|
+
- **`AbstractHydraniumGlspTheiaFrontendModule`** — a `GLSPTheiaFrontendModule`
|
|
15
|
+
subclass that absorbs the overrides every adopter otherwise writes verbatim.
|
|
16
|
+
You declare `diagramLanguage`, `diagramConfiguration` and `diagramManager`;
|
|
17
|
+
optionally set `logLevelPreference` (the base then binds the log-threshold
|
|
18
|
+
contribution for you) and override `bindClientContribution()` — returning
|
|
19
|
+
`SkipClientContribution` for a secondary diagram type that shares a server with
|
|
20
|
+
a primary one.
|
|
21
|
+
- **`createGlspClientTheiaModule(context, options)`** — the standard per-diagram
|
|
22
|
+
bindings, all unconditional: the cross-head `ChannelLogger`,
|
|
23
|
+
`HydraniumGlspActionDispatcher`, `HydraniumDiagramLoader`,
|
|
24
|
+
`HydraniumHiddenBoundsUpdater`, and `HydraniumGlspMessageService`. Each
|
|
25
|
+
replaces a GLSP default with a strict superset of its behaviour, so a head that
|
|
26
|
+
wants the original rebinds that one token back.
|
|
27
|
+
- **Loading feedback that cannot silently vanish.** `HydraniumDiagramLoader`
|
|
28
|
+
catches every load failure — the dispatcher-init, connect and first
|
|
29
|
+
`RequestModelAction` steps upstream leaves unwrapped — routes it to the Output
|
|
30
|
+
channel, and reports it as an error `StatusAction`. It publishes a terminal
|
|
31
|
+
`DiagramLoadOutcome`, which `HydraniumGlspDiagramWidget` keys its opaque canvas
|
|
32
|
+
overlay on (`DIAGRAM_LOADING_CLASS`, `DIAGRAM_LOADING_FAILED_CLASS`).
|
|
33
|
+
`HydraniumGlspMessageService` then drops the now-redundant "Model loading in
|
|
34
|
+
progress" toast (`MODEL_LOADING_PROGRESS_TITLE`) and forwards every other
|
|
35
|
+
progress report untouched.
|
|
36
|
+
- **Instrumentation.** `HydraniumGlspActionDispatcher` logs action traffic into
|
|
37
|
+
the shared Output channel and pairs requests with responses — by id, or by kind
|
|
38
|
+
for the GLSP flow actions that carry none (`HYDRANIUM_DEFAULT_LOGGED_KINDS`,
|
|
39
|
+
`HYDRANIUM_DEFAULT_KIND_PAIRS`, extensible via
|
|
40
|
+
`HydraniumGlspActionDispatcherOptions`). `HydraniumHiddenBoundsUpdater` emits
|
|
41
|
+
one trace line per bounds request with the measured element count and the raw
|
|
42
|
+
`getBBox` cost — the client-side phase that scales with rendered elements
|
|
43
|
+
rather than model size.
|
|
44
|
+
- **`AbstractHydraniumGlspDiagramConfiguration`** with
|
|
45
|
+
`propagateMarkersToProblemsView` — set it `false` for a head whose co-resident
|
|
46
|
+
LSP already publishes the same diagnostics, and the per-diagram container binds
|
|
47
|
+
`NoOpExternalMarkerManager` instead: markers still decorate the diagram, but
|
|
48
|
+
Theia's Problems view stops double-listing them.
|
|
49
|
+
**`AbstractHydraniumGlspDiagramManager`** derives the language-correlated
|
|
50
|
+
getters from one descriptor plus a label.
|
|
51
|
+
- **`HydraniumGlspClientContribution`** — for a server that starts late: it tails
|
|
52
|
+
the Output channel for a server-printed ready marker and defers `start` until a
|
|
53
|
+
workspace is open.
|
|
54
|
+
- **Backend (`./node`)** — `GlspServerConnectionHandler` (the socket bridge,
|
|
55
|
+
plugging in `@eclipse-glsp/theia-integration`'s `SocketConnectionForwarder`) and
|
|
56
|
+
`createGlspConnectionContainerModule(handler)` for the frontend-scoped module
|
|
57
|
+
boilerplate.
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install @hydranium/glsp-client-theia
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
You must already have a Theia application wired for GLSP — `@eclipse-glsp/client`
|
|
66
|
+
and `@eclipse-glsp/theia-integration` are peers, not bundled — and a running
|
|
67
|
+
hydranium GLSP server. The declared peer dependencies are:
|
|
68
|
+
|
|
69
|
+
| Peer | Range |
|
|
70
|
+
| --------------------------------- | ------------- |
|
|
71
|
+
| `@eclipse-glsp/client` | `^2.6.0` |
|
|
72
|
+
| `@eclipse-glsp/theia-integration` | `^2.6.0` |
|
|
73
|
+
| `@hydranium/client-theia` | `^1.0.0-next` |
|
|
74
|
+
| `@hydranium/protocol` | `^1.0.0-next` |
|
|
75
|
+
| `@theia/core` | `^1.71.0` |
|
|
76
|
+
| `@theia/output` | `^1.71.0` |
|
|
77
|
+
| `@theia/process` | `^1.71.0` |
|
|
78
|
+
| `@theia/workspace` | `^1.71.0` |
|
|
79
|
+
| `inversify` | `^6.0.0` |
|
|
80
|
+
| `snabbdom` | `^3.5.1` |
|
|
81
|
+
|
|
82
|
+
## Wiring
|
|
83
|
+
|
|
84
|
+
This package declares no `theiaExtensions` — it is a library your own Theia
|
|
85
|
+
extension builds on. That extension declares the entries; a diagram is one
|
|
86
|
+
frontend/backend pair:
|
|
87
|
+
|
|
88
|
+
- the **frontend** entry points at a module that
|
|
89
|
+
`export default new MyDiagramModule()`, where `MyDiagramModule` extends
|
|
90
|
+
`AbstractHydraniumGlspTheiaFrontendModule`. Your `DiagramConfiguration`
|
|
91
|
+
subclass calls `createGlspClientTheiaModule` in its container initialisation,
|
|
92
|
+
passing the `channelLogger` name;
|
|
93
|
+
- the **backend** entry is typically
|
|
94
|
+
`export default createGlspConnectionContainerModule(MyHandler)`, where
|
|
95
|
+
`MyHandler` extends `GlspServerConnectionHandler`. The handler's
|
|
96
|
+
`languageContributionId` decides the per-language service path Theia routes
|
|
97
|
+
frontend connections to.
|
|
98
|
+
|
|
99
|
+
**The `style/` directory needs no action from you.** It holds one stylesheet,
|
|
100
|
+
`diagram-loading.css`, for the widget's loading overlay, and the widget module
|
|
101
|
+
imports it itself — precisely so an adopter cannot ship an unstyled `div` in
|
|
102
|
+
normal flow by forgetting it. It is listed in `files` because it must be present
|
|
103
|
+
in the published tarball for that import to resolve; your bundler needs a CSS
|
|
104
|
+
loader, which a Theia application's webpack configuration already has. Colours
|
|
105
|
+
come from `--theia-*` theme variables, and every rule is overridable from a
|
|
106
|
+
stylesheet loaded afterwards.
|
|
107
|
+
|
|
108
|
+
## Entry points
|
|
109
|
+
|
|
110
|
+
| Subpath | Holds | Environment |
|
|
111
|
+
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
112
|
+
| `.` | Re-exports `./browser` — the larger of the two tiers and safe to load anywhere. | browser-neutral (gated) |
|
|
113
|
+
| `./browser` | The frontend module bases, `createGlspClientTheiaModule`, the dispatcher, loader, widget, bounds updater, message service, diagram manager and configuration bases, `NoOpExternalMarkerManager` | browser / Theia frontend (gated) |
|
|
114
|
+
| `./node` | `GlspServerConnectionHandler`, `createGlspConnectionContainerModule` | Node / Theia backend |
|
|
115
|
+
| `./testing` | `makeBindRecorder`, the GLSP-module-specific Inversify double (the cross-head doubles live in `@hydranium/client-theia/testing`) | browser-neutral (gated) |
|
|
116
|
+
|
|
117
|
+
Every subpath also has a `./lib/<name>` twin for consumers on
|
|
118
|
+
`moduleResolution: "Node"`. "Gated" means the repository's neutral-bundle check
|
|
119
|
+
enforces that the entry bundles for the browser with no `node:*` import,
|
|
120
|
+
transitive ones included; `./node` is deliberately outside that gate. Also
|
|
121
|
+
worth reading: [what "gated neutral" does and does not promise](../../docs/concepts/browser-hosting.md#a-note-on-what-gated-neutral-does-and-does-not-promise).
|
|
122
|
+
|
|
123
|
+
## Status
|
|
124
|
+
|
|
125
|
+
Alpha — pre-v0, not yet published. The API is not stable and may change without a
|
|
126
|
+
deprecation cycle. See [`docs/concepts/architecture.md`](../../docs/concepts/architecture.md) for
|
|
127
|
+
the GLSP head's place among the heads, and the
|
|
128
|
+
[repository README](../../README.md) for current status and known limitations.
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
`MIT` — see this package's [`LICENSE`](./LICENSE). Third-party notices for the
|
|
133
|
+
runtime dependency closure are collected in the repository
|
|
134
|
+
[`NOTICE.md`](../../NOTICE.md).
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
import { type Action, GLSPActionDispatcher } from '@eclipse-glsp/client';
|
|
10
|
+
import { ChannelLogger } from '@hydranium/client-theia/lib/browser';
|
|
11
|
+
import { type Tracer } from '@hydranium/protocol';
|
|
12
|
+
/** Default subset of action kinds the framework dispatcher will log: the GLSP
|
|
13
|
+
* traffic an observer reading the Output channel typically wants to see. All
|
|
14
|
+
* are standard `@eclipse-glsp/client` kinds; adopters with custom action kinds
|
|
15
|
+
* extend via `extraLoggedKinds`. */
|
|
16
|
+
export declare const HYDRANIUM_DEFAULT_LOGGED_KINDS: ReadonlySet<string>;
|
|
17
|
+
/** Default request → response kind pairs for GLSP 'flow' actions that do NOT
|
|
18
|
+
* carry a requestId/responseId — so the dispatcher matches by kind (FIFO).
|
|
19
|
+
* Id-based matching still wins when a requestId is present. */
|
|
20
|
+
export declare const HYDRANIUM_DEFAULT_KIND_PAIRS: ReadonlyMap<string, string>;
|
|
21
|
+
/** Additive options. Adopters with custom action kinds pass extras here; the
|
|
22
|
+
* framework defaults always apply (you cannot un-log a kind the framework
|
|
23
|
+
* considers worth logging — subclass + override `dispatch` if you must). */
|
|
24
|
+
export interface HydraniumGlspActionDispatcherOptions {
|
|
25
|
+
readonly extraLoggedKinds?: Iterable<string>;
|
|
26
|
+
readonly extraKindPairs?: Iterable<readonly [string, string]>;
|
|
27
|
+
/** Replaces the default `summarize` body entirely. Use for adopter-domain
|
|
28
|
+
* action kinds where the framework default returns ''. */
|
|
29
|
+
readonly summarize?: (action: Action) => string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Wraps every dispatch so action traffic appears in the framework Output
|
|
33
|
+
* channel, interleaved with server log lines. Instrumenting the dispatcher
|
|
34
|
+
* (rather than per-kind handlers) catches ResponseActions that bypass the
|
|
35
|
+
* handler pipeline.
|
|
36
|
+
*
|
|
37
|
+
* The framework defaults cover the standard GLSP kinds worth logging, not every
|
|
38
|
+
* kind the protocol defines. Adopters with custom kinds either pass
|
|
39
|
+
* `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
|
|
40
|
+
* `toDynamicValue` binding) or subclass and override.
|
|
41
|
+
*/
|
|
42
|
+
export declare class HydraniumGlspActionDispatcher extends GLSPActionDispatcher {
|
|
43
|
+
protected readonly channel: ChannelLogger;
|
|
44
|
+
protected readonly tracer: Tracer;
|
|
45
|
+
protected readonly loggedKinds: ReadonlySet<string>;
|
|
46
|
+
protected readonly kindPairs: ReadonlyMap<string, string>;
|
|
47
|
+
protected readonly kindPairsReverse: ReadonlyMap<string, string>;
|
|
48
|
+
protected pairCounter: number;
|
|
49
|
+
/** Pending requests keyed by requestId (for actions that carry one). */
|
|
50
|
+
protected pendingById: Map<string, {
|
|
51
|
+
id: number;
|
|
52
|
+
start: number;
|
|
53
|
+
}>;
|
|
54
|
+
/** FIFO queue per response kind, used for `flow` pairs without requestId/responseId. */
|
|
55
|
+
protected pendingByKind: Map<string, {
|
|
56
|
+
id: number;
|
|
57
|
+
start: number;
|
|
58
|
+
}[]>;
|
|
59
|
+
constructor(options?: HydraniumGlspActionDispatcherOptions);
|
|
60
|
+
initialize(): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Register the one-shot 'model initialized' timing line. Instrumentation
|
|
63
|
+
* only — guarded so a tracer failure degrades logging rather than aborting
|
|
64
|
+
* diagram init. `initialize()` runs inside `DiagramLoader.load()`, whose
|
|
65
|
+
* caller (`GLSPDiagramWidget.onAfterAttach`) neither awaits nor catches the
|
|
66
|
+
* returned promise; an error thrown here would therefore escape as an
|
|
67
|
+
* uncaught rejection that blanks the diagram with no server-side signal.
|
|
68
|
+
*/
|
|
69
|
+
protected registerInitTiming(): void;
|
|
70
|
+
dispatch(action: Action): Promise<void>;
|
|
71
|
+
protected logAction(action: Action): void;
|
|
72
|
+
protected classify(action: Action): {
|
|
73
|
+
verb: string;
|
|
74
|
+
direction: string;
|
|
75
|
+
};
|
|
76
|
+
/** Emit `[request #N]` on the request side, `[response #N, Xms]` on the matching response side.
|
|
77
|
+
* Match first by requestId/responseId, then by known kind pairs (FIFO). */
|
|
78
|
+
protected trackPair(action: Action): string;
|
|
79
|
+
protected formatResponse(entry: {
|
|
80
|
+
id: number;
|
|
81
|
+
start: number;
|
|
82
|
+
}): string;
|
|
83
|
+
protected summarize(action: Action): string;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=action-dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-dispatcher.d.ts","sourceRoot":"","sources":["../../src/browser/action-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,MAAM,EAEX,oBAAoB,EAmBtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAiB,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD;;;qCAGqC;AACrC,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAe7D,CAAC;AAEH;;gEAEgE;AAChE,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAInE,CAAC;AAEH;;6EAE6E;AAC7E,MAAM,WAAW,oCAAoC;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D;+DAC2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAClD;AAED;;;;;;;;;;GAUG;AACH,qBACa,6BAA8B,SAAQ,oBAAoB;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAC3C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAG,MAAM,CAAC;IAE1D,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjE,SAAS,CAAC,WAAW,SAAK;IAC1B,wEAAwE;IACxE,SAAS,CAAC,WAAW;YAAyB,MAAM;eAAS,MAAM;OAAM;IACzE,wFAAwF;IACxF,SAAS,CAAC,aAAa;YAA+B,MAAM;eAAS,MAAM;SAAO;gBAEzD,OAAO,CAAC,EAAE,oCAAoC;IAa9D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAQ3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAczC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAkBvE;gFAC4E;IAC5E,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAiC3C,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAKtE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAoC7C"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, 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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
11
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
12
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
13
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
18
|
+
};
|
|
19
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
20
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.HydraniumGlspActionDispatcher = exports.HYDRANIUM_DEFAULT_KIND_PAIRS = exports.HYDRANIUM_DEFAULT_LOGGED_KINDS = void 0;
|
|
24
|
+
const client_1 = require("@eclipse-glsp/client");
|
|
25
|
+
const browser_1 = require("@hydranium/client-theia/lib/browser");
|
|
26
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
27
|
+
/** Default subset of action kinds the framework dispatcher will log: the GLSP
|
|
28
|
+
* traffic an observer reading the Output channel typically wants to see. All
|
|
29
|
+
* are standard `@eclipse-glsp/client` kinds; adopters with custom action kinds
|
|
30
|
+
* extend via `extraLoggedKinds`. */
|
|
31
|
+
exports.HYDRANIUM_DEFAULT_LOGGED_KINDS = new Set([
|
|
32
|
+
client_1.SetModelAction.KIND,
|
|
33
|
+
client_1.UpdateModelAction.KIND,
|
|
34
|
+
client_1.RequestBoundsAction.KIND,
|
|
35
|
+
client_1.ComputedBoundsAction.KIND,
|
|
36
|
+
client_1.SetDirtyStateAction.KIND,
|
|
37
|
+
client_1.SetEditModeAction.KIND,
|
|
38
|
+
client_1.SetMarkersAction.KIND,
|
|
39
|
+
client_1.SetTypeHintsAction.KIND,
|
|
40
|
+
client_1.StatusAction.KIND,
|
|
41
|
+
client_1.MessageAction.KIND,
|
|
42
|
+
client_1.RejectAction.KIND,
|
|
43
|
+
client_1.RequestContextActions.KIND,
|
|
44
|
+
client_1.RequestModelAction.KIND,
|
|
45
|
+
client_1.RequestTypeHintsAction.KIND
|
|
46
|
+
]);
|
|
47
|
+
/** Default request → response kind pairs for GLSP 'flow' actions that do NOT
|
|
48
|
+
* carry a requestId/responseId — so the dispatcher matches by kind (FIFO).
|
|
49
|
+
* Id-based matching still wins when a requestId is present. */
|
|
50
|
+
exports.HYDRANIUM_DEFAULT_KIND_PAIRS = new Map([
|
|
51
|
+
[client_1.RequestModelAction.KIND, client_1.SetModelAction.KIND],
|
|
52
|
+
[client_1.RequestTypeHintsAction.KIND, client_1.SetTypeHintsAction.KIND],
|
|
53
|
+
[client_1.RequestBoundsAction.KIND, client_1.ComputedBoundsAction.KIND]
|
|
54
|
+
]);
|
|
55
|
+
/**
|
|
56
|
+
* Wraps every dispatch so action traffic appears in the framework Output
|
|
57
|
+
* channel, interleaved with server log lines. Instrumenting the dispatcher
|
|
58
|
+
* (rather than per-kind handlers) catches ResponseActions that bypass the
|
|
59
|
+
* handler pipeline.
|
|
60
|
+
*
|
|
61
|
+
* The framework defaults cover the standard GLSP kinds worth logging, not every
|
|
62
|
+
* kind the protocol defines. Adopters with custom kinds either pass
|
|
63
|
+
* `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
|
|
64
|
+
* `toDynamicValue` binding) or subclass and override.
|
|
65
|
+
*/
|
|
66
|
+
let HydraniumGlspActionDispatcher = class HydraniumGlspActionDispatcher extends client_1.GLSPActionDispatcher {
|
|
67
|
+
channel;
|
|
68
|
+
tracer;
|
|
69
|
+
loggedKinds;
|
|
70
|
+
kindPairs;
|
|
71
|
+
kindPairsReverse;
|
|
72
|
+
pairCounter = 0;
|
|
73
|
+
/** Pending requests keyed by requestId (for actions that carry one). */
|
|
74
|
+
pendingById = new Map();
|
|
75
|
+
/** FIFO queue per response kind, used for `flow` pairs without requestId/responseId. */
|
|
76
|
+
pendingByKind = new Map();
|
|
77
|
+
constructor(options) {
|
|
78
|
+
super();
|
|
79
|
+
const extraLogged = options?.extraLoggedKinds ? Array.from(options.extraLoggedKinds) : [];
|
|
80
|
+
this.loggedKinds = new Set([...exports.HYDRANIUM_DEFAULT_LOGGED_KINDS, ...extraLogged]);
|
|
81
|
+
const extraPairs = options?.extraKindPairs ? Array.from(options.extraKindPairs) : [];
|
|
82
|
+
const pairs = new Map([...exports.HYDRANIUM_DEFAULT_KIND_PAIRS, ...extraPairs]);
|
|
83
|
+
this.kindPairs = pairs;
|
|
84
|
+
this.kindPairsReverse = new Map(Array.from(pairs, ([req, res]) => [res, req]));
|
|
85
|
+
if (options?.summarize) {
|
|
86
|
+
this.summarize = options.summarize;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
initialize() {
|
|
90
|
+
// `initialize()` is called many times; super is idempotent, but our callback registration
|
|
91
|
+
// isn't. Register the timing log only on the first call (when super.initialized is unset).
|
|
92
|
+
if (!this.initialized) {
|
|
93
|
+
this.registerInitTiming();
|
|
94
|
+
}
|
|
95
|
+
return super.initialize();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Register the one-shot 'model initialized' timing line. Instrumentation
|
|
99
|
+
* only — guarded so a tracer failure degrades logging rather than aborting
|
|
100
|
+
* diagram init. `initialize()` runs inside `DiagramLoader.load()`, whose
|
|
101
|
+
* caller (`GLSPDiagramWidget.onAfterAttach`) neither awaits nor catches the
|
|
102
|
+
* returned promise; an error thrown here would therefore escape as an
|
|
103
|
+
* uncaught rejection that blanks the diagram with no server-side signal.
|
|
104
|
+
*/
|
|
105
|
+
registerInitTiming() {
|
|
106
|
+
try {
|
|
107
|
+
this.tracer.time('Model initialized', () => this.onceModelInitialized(), 'info', { logAfterMs: 0 });
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
this.channel.error('Failed to register model-initialized timing instrumentation', err);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
dispatch(action) {
|
|
114
|
+
if (this.loggedKinds.has(action.kind)) {
|
|
115
|
+
this.logAction(action);
|
|
116
|
+
}
|
|
117
|
+
return super.dispatch(action);
|
|
118
|
+
}
|
|
119
|
+
logAction(action) {
|
|
120
|
+
const { verb, direction } = this.classify(action);
|
|
121
|
+
const summary = this.summarize(action);
|
|
122
|
+
const timing = this.trackPair(action);
|
|
123
|
+
const parts = [`${verb} action '${action.kind}'`, `[${direction}]`];
|
|
124
|
+
if (summary) {
|
|
125
|
+
parts.push(`[${summary}]`);
|
|
126
|
+
}
|
|
127
|
+
if (timing) {
|
|
128
|
+
parts.push(timing);
|
|
129
|
+
}
|
|
130
|
+
this.channel.trace(parts.join(' '));
|
|
131
|
+
}
|
|
132
|
+
classify(action) {
|
|
133
|
+
// GLSP marks client-produced computedBounds as ServerAction to suppress forwarding; stays local.
|
|
134
|
+
if (client_1.LocalComputedBoundsAction.is(action)) {
|
|
135
|
+
return { verb: 'Process', direction: 'client → client' };
|
|
136
|
+
}
|
|
137
|
+
// Marked by GLSPModelSource.messageReceived — arrived from the server.
|
|
138
|
+
if (client_1.ServerAction.is(action)) {
|
|
139
|
+
return { verb: 'Receive', direction: 'server → client' };
|
|
140
|
+
}
|
|
141
|
+
// GLSPModelSource is registered as handler for every server-handled kind (configureServeActions),
|
|
142
|
+
// so its presence means the action will be forwarded to the server.
|
|
143
|
+
const handlers = this.actionHandlerRegistry.get(action.kind);
|
|
144
|
+
if (handlers.some(handler => handler instanceof client_1.GLSPModelSource)) {
|
|
145
|
+
return { verb: 'Send', direction: 'client → server' };
|
|
146
|
+
}
|
|
147
|
+
return { verb: 'Process', direction: 'client → client' };
|
|
148
|
+
}
|
|
149
|
+
/** Emit `[request #N]` on the request side, `[response #N, Xms]` on the matching response side.
|
|
150
|
+
* Match first by requestId/responseId, then by known kind pairs (FIFO). */
|
|
151
|
+
trackPair(action) {
|
|
152
|
+
// Response side.
|
|
153
|
+
if (client_1.ResponseAction.hasValidResponseId(action)) {
|
|
154
|
+
const entry = this.pendingById.get(action.responseId);
|
|
155
|
+
if (entry) {
|
|
156
|
+
this.pendingById.delete(action.responseId);
|
|
157
|
+
return this.formatResponse(entry);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (this.kindPairsReverse.has(action.kind)) {
|
|
161
|
+
const queue = this.pendingByKind.get(action.kind);
|
|
162
|
+
const entry = queue?.shift();
|
|
163
|
+
if (entry) {
|
|
164
|
+
return this.formatResponse(entry);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Request side.
|
|
168
|
+
if (client_1.RequestAction.is(action) && action.requestId) {
|
|
169
|
+
const entry = { id: ++this.pairCounter, start: performance.now() };
|
|
170
|
+
this.pendingById.set(action.requestId, entry);
|
|
171
|
+
return `[request #${entry.id}]`;
|
|
172
|
+
}
|
|
173
|
+
if (this.kindPairs.has(action.kind)) {
|
|
174
|
+
const responseKind = this.kindPairs.get(action.kind);
|
|
175
|
+
const entry = { id: ++this.pairCounter, start: performance.now() };
|
|
176
|
+
const queue = this.pendingByKind.get(responseKind) ?? [];
|
|
177
|
+
queue.push(entry);
|
|
178
|
+
this.pendingByKind.set(responseKind, queue);
|
|
179
|
+
return `[request #${entry.id}]`;
|
|
180
|
+
}
|
|
181
|
+
return '';
|
|
182
|
+
}
|
|
183
|
+
formatResponse(entry) {
|
|
184
|
+
const elapsed = Math.round(performance.now() - entry.start);
|
|
185
|
+
return `[response #${entry.id}, ${elapsed}ms]`;
|
|
186
|
+
}
|
|
187
|
+
summarize(action) {
|
|
188
|
+
if (client_1.SetModelAction.is(action) || client_1.UpdateModelAction.is(action)) {
|
|
189
|
+
const root = action.newRoot;
|
|
190
|
+
return `rootType=${root?.type ?? 'none'} children=${root?.children?.length ?? 0}`;
|
|
191
|
+
}
|
|
192
|
+
if (client_1.RequestBoundsAction.is(action)) {
|
|
193
|
+
return `rootType=${action.newRoot.type} children=${action.newRoot.children?.length ?? 0}`;
|
|
194
|
+
}
|
|
195
|
+
if (client_1.ComputedBoundsAction.is(action)) {
|
|
196
|
+
return `bounds=${action.bounds.length}`;
|
|
197
|
+
}
|
|
198
|
+
if (client_1.SetDirtyStateAction.is(action)) {
|
|
199
|
+
return `isDirty=${action.isDirty} reason=${action.reason ?? 'n/a'}`;
|
|
200
|
+
}
|
|
201
|
+
if (client_1.SetEditModeAction.is(action)) {
|
|
202
|
+
return `editMode=${action.editMode}`;
|
|
203
|
+
}
|
|
204
|
+
if (client_1.SetMarkersAction.is(action)) {
|
|
205
|
+
return `markers=${action.markers.length}`;
|
|
206
|
+
}
|
|
207
|
+
if (client_1.StatusAction.is(action) || client_1.MessageAction.is(action)) {
|
|
208
|
+
// severity=NONE with empty message is the conventional 'clear' signal.
|
|
209
|
+
const clear = action.severity === 'NONE' && !action.message ? ' (clear)' : '';
|
|
210
|
+
return `severity=${action.severity} message="${action.message.slice(0, 160)}"${clear}`;
|
|
211
|
+
}
|
|
212
|
+
if (client_1.RejectAction.is(action)) {
|
|
213
|
+
return `reason="${action.message.slice(0, 160)}"`;
|
|
214
|
+
}
|
|
215
|
+
if (client_1.SetTypeHintsAction.is(action)) {
|
|
216
|
+
return `shapes=${action.shapeHints.length} edges=${action.edgeHints.length}`;
|
|
217
|
+
}
|
|
218
|
+
if (client_1.RequestContextActions.is(action)) {
|
|
219
|
+
return `contextId=${action.contextId}`;
|
|
220
|
+
}
|
|
221
|
+
return '';
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
exports.HydraniumGlspActionDispatcher = HydraniumGlspActionDispatcher;
|
|
225
|
+
__decorate([
|
|
226
|
+
(0, inversify_1.inject)(browser_1.ChannelLogger),
|
|
227
|
+
__metadata("design:type", browser_1.ChannelLogger)
|
|
228
|
+
], HydraniumGlspActionDispatcher.prototype, "channel", void 0);
|
|
229
|
+
__decorate([
|
|
230
|
+
(0, inversify_1.inject)(browser_1.ChannelTracer),
|
|
231
|
+
__metadata("design:type", Object)
|
|
232
|
+
], HydraniumGlspActionDispatcher.prototype, "tracer", void 0);
|
|
233
|
+
exports.HydraniumGlspActionDispatcher = HydraniumGlspActionDispatcher = __decorate([
|
|
234
|
+
(0, inversify_1.injectable)(),
|
|
235
|
+
__param(0, (0, inversify_1.unmanaged)()),
|
|
236
|
+
__metadata("design:paramtypes", [Object])
|
|
237
|
+
], HydraniumGlspActionDispatcher);
|
|
238
|
+
//# sourceMappingURL=action-dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-dispatcher.js","sourceRoot":"","sources":["../../src/browser/action-dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
import { type GLSPClient } from '@eclipse-glsp/client';
|
|
10
|
+
import { BaseGLSPClientContribution } from '@eclipse-glsp/theia-integration';
|
|
11
|
+
import { OutputChannelManager } from '@theia/output/lib/browser/output-channel';
|
|
12
|
+
import { WorkspaceService } from '@theia/workspace/lib/browser';
|
|
13
|
+
/** Options for `HydraniumGlspClientContribution`. The channel name is the
|
|
14
|
+
* Theia Output channel both the LSP and GLSP sides write to (so log lines
|
|
15
|
+
* interleave); the ready marker is a server-printed substring that signals
|
|
16
|
+
* "the GLSP server is accepting client connections". */
|
|
17
|
+
export interface ClientContributionOptions {
|
|
18
|
+
readonly languageContributionId: string;
|
|
19
|
+
readonly channelName: string;
|
|
20
|
+
readonly readyMarker: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Theia GLSP client contribution for adopters whose GLSP server runs in a
|
|
24
|
+
* sideloaded VS Code extension process (or any other deferred-start setup).
|
|
25
|
+
* The behaviours adopters reliably need are lifted:
|
|
26
|
+
*
|
|
27
|
+
* 1. `waitForBackendConnected`: tail the OutputChannel for a server-printed
|
|
28
|
+
* ready marker. While a socket connection might open earlier, the GLSP
|
|
29
|
+
* server typically does internal initialisation before it can accept
|
|
30
|
+
* client connections — we wait for it to say so.
|
|
31
|
+
* 2. `start`: defer until a workspace is opened. If Theia starts without a
|
|
32
|
+
* workspace, this prevents the frontend-backend connection (and its
|
|
33
|
+
* "connecting" progress spinner) from firing prematurely.
|
|
34
|
+
*
|
|
35
|
+
* A `GLSPClient` override filtering inbound messages by clientId is
|
|
36
|
+
* deliberately NOT provided: upstream's `BaseJsonrpcGLSPClient.onActionMessage`
|
|
37
|
+
* already filters by clientId, so the `TheiaJsonrpcGLSPClient` returned by
|
|
38
|
+
* `BaseGLSPClientContribution.createGLSPClient` is correct as-is.
|
|
39
|
+
*/
|
|
40
|
+
export declare class HydraniumGlspClientContribution extends BaseGLSPClientContribution {
|
|
41
|
+
protected outputChannelManager: OutputChannelManager;
|
|
42
|
+
protected readonly workspaceService: WorkspaceService;
|
|
43
|
+
readonly id: string;
|
|
44
|
+
protected readonly channelName: string;
|
|
45
|
+
protected readonly readyMarker: string;
|
|
46
|
+
constructor(options: ClientContributionOptions);
|
|
47
|
+
/** Wait for the server to print its ready marker into the OutputChannel.
|
|
48
|
+
* Resolves immediately if the marker is already present (server started
|
|
49
|
+
* before the client contribution mounted). */
|
|
50
|
+
protected waitForBackendConnected(): Promise<void>;
|
|
51
|
+
protected start(glspClient: GLSPClient): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=client-contribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-contribution.d.ts","sourceRoot":"","sources":["../../src/browser/client-contribution.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAG7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE;;;yDAGyD;AACzD,MAAM,WAAW,yBAAyB;IACvC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,+BAAgC,SAAQ,0BAA0B;IAC9C,SAAS,CAAC,oBAAoB,EAAG,oBAAoB,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAG,gBAAgB,CAAC;IAEjF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,yBAAyB;IAO3D;;mDAE+C;cAC/B,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC;cAkB/B,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAkBvE"}
|