@salesforce/metadata-visualizer-web 1.0.1

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.
Files changed (66) hide show
  1. package/LICENSE.txt +27 -0
  2. package/README.md +269 -0
  3. package/dist/WebVisualizationEngine.d.ts +165 -0
  4. package/dist/WebVisualizationEngine.d.ts.map +1 -0
  5. package/dist/WebVisualizationEngine.js +284 -0
  6. package/dist/WebVisualizationEngine.js.map +1 -0
  7. package/dist/createWebVisualizationEngine.d.ts +27 -0
  8. package/dist/createWebVisualizationEngine.d.ts.map +1 -0
  9. package/dist/createWebVisualizationEngine.js +91 -0
  10. package/dist/createWebVisualizationEngine.js.map +1 -0
  11. package/dist/design-system/platform.css +623 -0
  12. package/dist/errors/index.d.ts +25 -0
  13. package/dist/errors/index.d.ts.map +1 -0
  14. package/dist/errors/index.js +31 -0
  15. package/dist/errors/index.js.map +1 -0
  16. package/dist/index.d.ts +22 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +18 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/internal/CompositeFileSystem.d.ts +28 -0
  21. package/dist/internal/CompositeFileSystem.d.ts.map +1 -0
  22. package/dist/internal/CompositeFileSystem.js +82 -0
  23. package/dist/internal/CompositeFileSystem.js.map +1 -0
  24. package/dist/internal/assetInliner.d.ts +30 -0
  25. package/dist/internal/assetInliner.d.ts.map +1 -0
  26. package/dist/internal/assetInliner.js +126 -0
  27. package/dist/internal/assetInliner.js.map +1 -0
  28. package/dist/internal/constants.d.ts +20 -0
  29. package/dist/internal/constants.d.ts.map +1 -0
  30. package/dist/internal/constants.js +34 -0
  31. package/dist/internal/constants.js.map +1 -0
  32. package/dist/internal/htmlPipeline.d.ts +50 -0
  33. package/dist/internal/htmlPipeline.d.ts.map +1 -0
  34. package/dist/internal/htmlPipeline.js +86 -0
  35. package/dist/internal/htmlPipeline.js.map +1 -0
  36. package/dist/pluginAssets/BundledPluginAssetReader.d.ts +34 -0
  37. package/dist/pluginAssets/BundledPluginAssetReader.d.ts.map +1 -0
  38. package/dist/pluginAssets/BundledPluginAssetReader.js +77 -0
  39. package/dist/pluginAssets/BundledPluginAssetReader.js.map +1 -0
  40. package/dist/plugins/flexipage/ui/assets/index-BAFqMU7k.js +48 -0
  41. package/dist/plugins/flexipage/ui/assets/index-U3SB2gLS.css +1 -0
  42. package/dist/plugins/flexipage/ui/index.html +16 -0
  43. package/dist/plugins/schema/ui/assets/index-DCLgZby3.css +1 -0
  44. package/dist/plugins/schema/ui/assets/index-Ho7jg9o_.js +70 -0
  45. package/dist/plugins/schema/ui/index.html +14 -0
  46. package/dist/types/HttpAsset.d.ts +18 -0
  47. package/dist/types/HttpAsset.d.ts.map +1 -0
  48. package/dist/types/HttpAsset.js +8 -0
  49. package/dist/types/HttpAsset.js.map +1 -0
  50. package/dist/types/PluginDataUpdateMessage.d.ts +24 -0
  51. package/dist/types/PluginDataUpdateMessage.d.ts.map +1 -0
  52. package/dist/types/PluginDataUpdateMessage.js +8 -0
  53. package/dist/types/PluginDataUpdateMessage.js.map +1 -0
  54. package/dist/types/PluginInfo.d.ts +20 -0
  55. package/dist/types/PluginInfo.d.ts.map +1 -0
  56. package/dist/types/PluginInfo.js +8 -0
  57. package/dist/types/PluginInfo.js.map +1 -0
  58. package/dist/types/VisualizeOutcome.d.ts +19 -0
  59. package/dist/types/VisualizeOutcome.d.ts.map +1 -0
  60. package/dist/types/VisualizeOutcome.js +8 -0
  61. package/dist/types/VisualizeOutcome.js.map +1 -0
  62. package/dist/types/WebAdapterOptions.d.ts +22 -0
  63. package/dist/types/WebAdapterOptions.d.ts.map +1 -0
  64. package/dist/types/WebAdapterOptions.js +8 -0
  65. package/dist/types/WebAdapterOptions.js.map +1 -0
  66. package/package.json +77 -0
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ **/
7
+ import { WebviewMessageType, ErrorCategory } from '@salesforce/metadata-core-sdk';
8
+ import { injectBootstrap } from './internal/htmlPipeline.js';
9
+ import { inlineAssets } from './internal/assetInliner.js';
10
+ import { BROWSER_IFRAME_BOOTSTRAP } from './internal/constants.js';
11
+ /**
12
+ * Browser/HTTP platform adapter for the visualization framework.
13
+ * Provides methods to generate self-contained HTML bundles and parse metadata
14
+ * for embedding in iframes. All methods are safe to call concurrently.
15
+ */
16
+ export class WebVisualizationEngine {
17
+ /**
18
+ * Construct an engine.
19
+ *
20
+ * **Use `createWebVisualizationEngine()` instead.** This constructor is exposed
21
+ * only for the factory and internal tests, and it asserts an ownership contract
22
+ * that is easy to misuse:
23
+ *
24
+ * - The injected `framework` (and its `ErrorManager`) is **owned** by the
25
+ * resulting engine. Calling `dispose()` tears it down — including any error
26
+ * listeners registered by other code on the same instance.
27
+ * - Therefore the framework must be dedicated to this engine. Sharing one
28
+ * `VisualizationEngine` between a `WebVisualizationEngine` and another
29
+ * adapter (e.g. the VS Code adapter) will break the other adapter when this
30
+ * engine is disposed.
31
+ *
32
+ * @internal
33
+ */
34
+ constructor(deps) {
35
+ /** Tracks whether dispose() has been called to prevent use-after-dispose */
36
+ this.disposed = false;
37
+ /** Per-file monotonic counter for fileId. Date.now() collides under sub-ms concurrent calls. */
38
+ this.fileIdCounters = new Map();
39
+ this.framework = deps.framework;
40
+ this.pluginManager = deps.pluginManager;
41
+ this.assetReader = deps.pluginAssetReader;
42
+ }
43
+ /**
44
+ * Generate a complete HTML bundle for a plugin's visualization UI.
45
+ * Returns a self-contained HTML file with all assets (JS, CSS, platform styles) inlined,
46
+ * ready to be embedded in an iframe. No metadata parsing occurs — this generates the static UI shell.
47
+ *
48
+ * @param pluginId - ID of the registered plugin to generate bundle for
49
+ * @returns Object containing the bundle (null if failed) and error (null if successful)
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const { bundle, error } = await engine.visualizeMetadata('flexipage-visualizer');
54
+ * if (error) {
55
+ * console.error('Bundle generation failed:', error.message);
56
+ * res.status(error.category === 'Configuration' ? 404 : 500).json({ error: error.message });
57
+ * } else if (bundle) {
58
+ * res.type(bundle.contentType).send(bundle.body);
59
+ * }
60
+ * ```
61
+ */
62
+ async visualizeMetadata(pluginId) {
63
+ this.assertNotDisposed();
64
+ // Fail fast on invalid plugin IDs to avoid downstream errors
65
+ if (!pluginId || pluginId.trim().length === 0) {
66
+ return {
67
+ bundle: null,
68
+ error: {
69
+ message: 'pluginId is null or empty',
70
+ category: ErrorCategory.Validation,
71
+ },
72
+ };
73
+ }
74
+ // Verify plugin is registered before attempting asset read
75
+ if (!this.requireKnownPlugin(pluginId)) {
76
+ return {
77
+ bundle: null,
78
+ error: {
79
+ message: `No plugin found for pluginId: ${pluginId}`,
80
+ category: ErrorCategory.Configuration,
81
+ },
82
+ };
83
+ }
84
+ try {
85
+ // Build self-contained HTML bundle: inline all assets to eliminate external requests
86
+ let html = await this.assetReader.readPluginIndexHtml(pluginId);
87
+ const platformCss = await this.assetReader.readDesignSystemCss();
88
+ html = await inlineAssets(html, pluginId, this.assetReader, platformCss);
89
+ // Bootstrap script enables host-plugin postMessage communication
90
+ html = injectBootstrap(html, BROWSER_IFRAME_BOOTSTRAP);
91
+ return {
92
+ bundle: {
93
+ contentType: 'text/html; charset=utf-8',
94
+ body: html,
95
+ // Bundle is the static plugin UI shell only (no per-user / per-org data —
96
+ // that flows separately via getParsedMetadata + postMessage). The shell is
97
+ // an immutable build artifact keyed by pluginId, safe to share across users
98
+ // and cache for a day. `immutable` lets clients skip revalidation entirely.
99
+ cacheControl: 'public, max-age=86400, immutable',
100
+ },
101
+ error: null,
102
+ };
103
+ }
104
+ catch (err) {
105
+ // Asset reading or inlining failed (missing plugin files, corrupt assets, etc.)
106
+ return {
107
+ bundle: null,
108
+ error: {
109
+ message: err instanceof Error ? err.message : 'Failed to generate bundle',
110
+ category: ErrorCategory.Runtime,
111
+ context: { pluginId: pluginId },
112
+ stackTrace: err instanceof Error ? err.stack : undefined,
113
+ },
114
+ };
115
+ }
116
+ }
117
+ /**
118
+ * Parse a metadata file and return the visualization outcome.
119
+ * Finds the appropriate plugin by file pattern, parses the file, and returns structured data.
120
+ * Handles error capturing for concurrent-safe execution (multiple calls won't interfere).
121
+ *
122
+ * @param metadataFilePath - Path to the metadata file to parse
123
+ * @returns VisualizeOutcome containing either parsed result or error
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * const outcome = await engine.getParsedMetadata('force-app/main/default/flexipages/Home.flexipage');
128
+ * if (outcome.error) {
129
+ * console.error('Parse failed:', outcome.error.message);
130
+ * } else {
131
+ * console.log('Parsed data:', outcome.result.data);
132
+ * }
133
+ * ```
134
+ */
135
+ async getParsedMetadata(metadataFilePath) {
136
+ this.assertNotDisposed();
137
+ // Fail fast on invalid paths to avoid downstream parsing errors
138
+ if (!metadataFilePath || metadataFilePath.trim().length === 0) {
139
+ return {
140
+ result: null,
141
+ error: {
142
+ message: 'Invalid file path',
143
+ category: ErrorCategory.Validation,
144
+ },
145
+ };
146
+ }
147
+ const errorManager = this.framework.getErrorManager();
148
+ const invocationId = globalThis.crypto.randomUUID();
149
+ let captured = null;
150
+ // Per-invocation filter ensures this listener only sees errors reported by
151
+ // our own visualize() call, even when other requests run concurrently.
152
+ const unsubscribe = errorManager.onErrorReported((err) => {
153
+ captured = err;
154
+ }, { invocationId });
155
+ try {
156
+ const result = await this.framework.visualize(metadataFilePath, invocationId);
157
+ return {
158
+ result,
159
+ error: result ? null : captured,
160
+ };
161
+ }
162
+ finally {
163
+ unsubscribe();
164
+ }
165
+ }
166
+ /**
167
+ * Parse metadata and generate an update message for posting to an existing plugin iframe.
168
+ * Use this when file content changes and you need to push updates to a loaded iframe
169
+ * without regenerating the entire bundle. Plugins receive updates via onDataUpdate().
170
+ *
171
+ * @param metadataFilePath - Path to the metadata file to parse
172
+ * @returns Object containing error (if any) and pluginDataUpdateMessage (null if parsing failed)
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * // File watcher integration
177
+ * watcher.on('change', async (filePath) => {
178
+ * const { error, pluginDataUpdateMessage } = await engine.getUpdatedParsedMetadata(filePath);
179
+ * if (pluginDataUpdateMessage) {
180
+ * iframeWindow.postMessage(pluginDataUpdateMessage, '*');
181
+ * }
182
+ * });
183
+ * ```
184
+ */
185
+ async getUpdatedParsedMetadata(metadataFilePath) {
186
+ this.assertNotDisposed();
187
+ // Delegates to getParsedMetadata for validation and parsing, then wraps result as update message
188
+ const outcome = await this.getParsedMetadata(metadataFilePath);
189
+ const pluginDataUpdateMessage = this.createDataUpdateMessage(outcome);
190
+ return { error: outcome.error, pluginDataUpdateMessage };
191
+ }
192
+ /**
193
+ * Release all resources held by the engine.
194
+ * After calling this method, the engine instance should not be used.
195
+ * Safe to call multiple times (idempotent).
196
+ *
197
+ * **Disposes the underlying framework.** The engine takes ownership of the
198
+ * `VisualizationEngine` passed to its constructor (or built by the factory),
199
+ * including its `ErrorManager`. Do not share that framework with another
200
+ * adapter — it will be torn down here.
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * process.on('SIGTERM', () => {
205
+ * engine.dispose();
206
+ * process.exit(0);
207
+ * });
208
+ * ```
209
+ */
210
+ dispose() {
211
+ if (this.disposed) {
212
+ return;
213
+ }
214
+ this.disposed = true;
215
+ this.fileIdCounters.clear();
216
+ // Framework owns the ErrorManager and disposes it as part of framework.dispose().
217
+ this.framework.dispose();
218
+ }
219
+ /**
220
+ * Create a PLUGIN_DATA_UPDATE message for posting to a loaded plugin iframe.
221
+ * Per-file monotonic counter guarantees a unique, ordered fileId per update,
222
+ * even under sub-millisecond concurrent calls (Date.now() can collide).
223
+ *
224
+ * @param outcome - Visualization outcome with parsed data
225
+ * @returns Message ready to be posted via iframe.contentWindow.postMessage(), or null if parsing failed
226
+ */
227
+ createDataUpdateMessage(outcome) {
228
+ if (!outcome.result) {
229
+ return null;
230
+ }
231
+ // Extract filename from full path (plugins often display just the filename, not full path)
232
+ const fileName = outcome.result.filePath.split('/').pop() || outcome.result.filePath;
233
+ const nextSeq = (this.fileIdCounters.get(outcome.result.filePath) ?? 0) + 1;
234
+ this.fileIdCounters.set(outcome.result.filePath, nextSeq);
235
+ return {
236
+ type: WebviewMessageType.PLUGIN_DATA_UPDATE,
237
+ payload: {
238
+ data: outcome.result.data,
239
+ context: {
240
+ filePath: outcome.result.filePath,
241
+ fileName: fileName,
242
+ },
243
+ fileId: `${outcome.result.filePath}@${nextSeq}`,
244
+ },
245
+ };
246
+ }
247
+ /**
248
+ * Find the registered plugin that handles a given file.
249
+ * Matches file against plugin patterns (e.g., *.flexipage, *.object, *-meta.xml).
250
+ *
251
+ * @param metadataFile - Filename (e.g., 'Home.flexipage') or full path to match
252
+ * @returns PluginInfo if a matching plugin is found, null otherwise
253
+ */
254
+ getPlugin(metadataFile) {
255
+ const match = this.pluginManager.findVisualizerPluginForFile(metadataFile);
256
+ return match ? toPluginInfo(match.metadata) : null;
257
+ }
258
+ /**
259
+ * Verify a plugin is registered before attempting to use it.
260
+ * Prevents asset read failures for non-existent plugins.
261
+ */
262
+ requireKnownPlugin(pluginId) {
263
+ return this.pluginManager.getAllVisualizerPlugins().some((p) => p.metadata.id === pluginId);
264
+ }
265
+ /** Guards against use-after-dispose by throwing an error */
266
+ assertNotDisposed() {
267
+ if (this.disposed) {
268
+ throw new Error('WebVisualizationEngine has been disposed');
269
+ }
270
+ }
271
+ }
272
+ /**
273
+ * Convert framework plugin metadata to web adapter's PluginInfo format.
274
+ * Renames 'name' to 'displayName' for consistency with HTTP API conventions.
275
+ */
276
+ function toPluginInfo(meta) {
277
+ return {
278
+ id: meta.id,
279
+ displayName: meta.name,
280
+ filePatterns: meta.filePatterns ?? [],
281
+ priority: meta.priority,
282
+ };
283
+ }
284
+ //# sourceMappingURL=WebVisualizationEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebVisualizationEngine.js","sourceRoot":"","sources":["../src/WebVisualizationEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ **/
7
+ import { WebVisualizationEngine } from './WebVisualizationEngine.js';
8
+ import type { WebAdapterOptions } from './types/WebAdapterOptions.js';
9
+ /**
10
+ * Build a fully-initialized `WebVisualizationEngine`. This is the only
11
+ * public construction path — `WebVisualizationEngine`'s own constructor
12
+ * is internal so we can ensure plugin loading completes before the engine
13
+ * is handed to the consumer.
14
+ *
15
+ * Wiring details (host-invisible):
16
+ * - The host's `IFileSystem` is wrapped in a `CompositeFileSystem` that
17
+ * routes paths under the adapter's bundled-plugins root to a Node fs
18
+ * reader, and everything else to the host. This lets the framework's
19
+ * existing `visualize(filePath)` HTML render reach plugin index.html
20
+ * without ever asking the host's filesystem for paths the host
21
+ * doesn't know about.
22
+ * - Plugin assets are read via `BundledPluginAssetReader` — used by
23
+ * `getPluginIndexHtml` and `getPluginAsset`. The composite filesystem
24
+ * covers the framework's internal flow.
25
+ */
26
+ export declare function createWebVisualizationEngine(opts: WebAdapterOptions): Promise<WebVisualizationEngine>;
27
+ //# sourceMappingURL=createWebVisualizationEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createWebVisualizationEngine.d.ts","sourceRoot":"","sources":["../src/createWebVisualizationEngine.ts"],"names":[],"mappings":"AAAA;;;;;IAKI;AAaJ,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,sBAAsB,CAAC,CA2BjC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ **/
7
+ import * as path from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { LogLevel, NoOpTelemetry, } from '@salesforce/metadata-core-sdk';
10
+ import { PluginManager, VisualizationEngine } from '@salesforce/metadata-visualizer-core';
11
+ import { BundledPluginAssetReader } from './pluginAssets/BundledPluginAssetReader.js';
12
+ import { createCompositeFileSystem } from './internal/CompositeFileSystem.js';
13
+ import { WebVisualizationEngine } from './WebVisualizationEngine.js';
14
+ /**
15
+ * Build a fully-initialized `WebVisualizationEngine`. This is the only
16
+ * public construction path — `WebVisualizationEngine`'s own constructor
17
+ * is internal so we can ensure plugin loading completes before the engine
18
+ * is handed to the consumer.
19
+ *
20
+ * Wiring details (host-invisible):
21
+ * - The host's `IFileSystem` is wrapped in a `CompositeFileSystem` that
22
+ * routes paths under the adapter's bundled-plugins root to a Node fs
23
+ * reader, and everything else to the host. This lets the framework's
24
+ * existing `visualize(filePath)` HTML render reach plugin index.html
25
+ * without ever asking the host's filesystem for paths the host
26
+ * doesn't know about.
27
+ * - Plugin assets are read via `BundledPluginAssetReader` — used by
28
+ * `getPluginIndexHtml` and `getPluginAsset`. The composite filesystem
29
+ * covers the framework's internal flow.
30
+ */
31
+ export async function createWebVisualizationEngine(opts) {
32
+ const bundledPluginsRoot = resolveBundledPluginsRoot();
33
+ const composite = createCompositeFileSystem(opts.fileSystem, resolveBundledRoot());
34
+ const platformContext = {
35
+ fileSystem: composite,
36
+ logger: new NoOpLogger(),
37
+ telemetry: opts.telemetry ?? new NoOpTelemetry(),
38
+ // Framework constructs `<reactBuildsBasePath>/<pluginId>/ui/index.html`
39
+ // and reads through `fileSystem`. With the composite in place, those
40
+ // reads land on the adapter's bundled assets without the host's IFS
41
+ // ever seeing them.
42
+ reactBuildsBasePath: bundledPluginsRoot,
43
+ };
44
+ const pluginManager = new PluginManager(platformContext);
45
+ await pluginManager.loadPlugins();
46
+ const framework = new VisualizationEngine(platformContext, pluginManager);
47
+ const pluginAssetReader = new BundledPluginAssetReader(resolveBundledRoot());
48
+ return new WebVisualizationEngine({
49
+ framework,
50
+ pluginManager,
51
+ pluginAssetReader,
52
+ });
53
+ }
54
+ /**
55
+ * Resolve the adapter's own `dist/` directory at runtime. After the build
56
+ * step, this is `<package>/dist/`, which contains `plugins/...` and
57
+ * `design-system/platform.css`.
58
+ */
59
+ function resolveBundledRoot() {
60
+ return path.dirname(fileURLToPath(import.meta.url));
61
+ }
62
+ /** Resolve the bundled plugins root (`<dist>/plugins`). */
63
+ function resolveBundledPluginsRoot() {
64
+ return path.join(resolveBundledRoot(), 'plugins');
65
+ }
66
+ /**
67
+ * Default no-op `ILogger` for when the consumer doesn't supply one. Kept
68
+ * inline rather than re-exported from the package surface — consumers
69
+ * either provide their own logger or get silence.
70
+ */
71
+ class NoOpLogger {
72
+ constructor() {
73
+ this.level = LogLevel.Info;
74
+ }
75
+ debug() { }
76
+ info() { }
77
+ warn() { }
78
+ error() { }
79
+ success() { }
80
+ log() { }
81
+ setLevel(level) {
82
+ this.level = level;
83
+ }
84
+ getLevel() {
85
+ return this.level;
86
+ }
87
+ createChild() {
88
+ return this;
89
+ }
90
+ }
91
+ //# sourceMappingURL=createWebVisualizationEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createWebVisualizationEngine.js","sourceRoot":"","sources":["../src/createWebVisualizationEngine.ts"],"names":[],"mappings":"AAAA;;;;;IAKI;AAEJ,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAEL,QAAQ,EAER,aAAa,GACd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AACtF,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,IAAuB;IAEvB,MAAM,kBAAkB,GAAG,yBAAyB,EAAE,CAAC;IAEvD,MAAM,SAAS,GAAG,yBAAyB,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAEnF,MAAM,eAAe,GAAqB;QACxC,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,IAAI,UAAU,EAAE;QACxB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,aAAa,EAAE;QAChD,wEAAwE;QACxE,qEAAqE;QACrE,oEAAoE;QACpE,oBAAoB;QACpB,mBAAmB,EAAE,kBAAkB;KACxC,CAAC;IAEF,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,eAAe,CAAC,CAAC;IACzD,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC;IAElC,MAAM,SAAS,GAAG,IAAI,mBAAmB,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IAC1E,MAAM,iBAAiB,GAAG,IAAI,wBAAwB,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAE7E,OAAO,IAAI,sBAAsB,CAAC;QAChC,SAAS;QACT,aAAa;QACb,iBAAiB;KAClB,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB;IACzB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,2DAA2D;AAC3D,SAAS,yBAAyB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,SAAS,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU;IAAhB;QACU,UAAK,GAAa,QAAQ,CAAC,IAAI,CAAC;IAgB1C,CAAC;IAfC,KAAK,KAAU,CAAC;IAChB,IAAI,KAAU,CAAC;IACf,IAAI,KAAU,CAAC;IACf,KAAK,KAAU,CAAC;IAChB,OAAO,KAAU,CAAC;IAClB,GAAG,KAAU,CAAC;IACd,QAAQ,CAAC,KAAe;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IACD,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IACD,WAAW;QACT,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}