@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.
- package/LICENSE.txt +27 -0
- package/README.md +269 -0
- package/dist/WebVisualizationEngine.d.ts +165 -0
- package/dist/WebVisualizationEngine.d.ts.map +1 -0
- package/dist/WebVisualizationEngine.js +284 -0
- package/dist/WebVisualizationEngine.js.map +1 -0
- package/dist/createWebVisualizationEngine.d.ts +27 -0
- package/dist/createWebVisualizationEngine.d.ts.map +1 -0
- package/dist/createWebVisualizationEngine.js +91 -0
- package/dist/createWebVisualizationEngine.js.map +1 -0
- package/dist/design-system/platform.css +623 -0
- package/dist/errors/index.d.ts +25 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +31 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/CompositeFileSystem.d.ts +28 -0
- package/dist/internal/CompositeFileSystem.d.ts.map +1 -0
- package/dist/internal/CompositeFileSystem.js +82 -0
- package/dist/internal/CompositeFileSystem.js.map +1 -0
- package/dist/internal/assetInliner.d.ts +30 -0
- package/dist/internal/assetInliner.d.ts.map +1 -0
- package/dist/internal/assetInliner.js +126 -0
- package/dist/internal/assetInliner.js.map +1 -0
- package/dist/internal/constants.d.ts +20 -0
- package/dist/internal/constants.d.ts.map +1 -0
- package/dist/internal/constants.js +34 -0
- package/dist/internal/constants.js.map +1 -0
- package/dist/internal/htmlPipeline.d.ts +50 -0
- package/dist/internal/htmlPipeline.d.ts.map +1 -0
- package/dist/internal/htmlPipeline.js +86 -0
- package/dist/internal/htmlPipeline.js.map +1 -0
- package/dist/pluginAssets/BundledPluginAssetReader.d.ts +34 -0
- package/dist/pluginAssets/BundledPluginAssetReader.d.ts.map +1 -0
- package/dist/pluginAssets/BundledPluginAssetReader.js +77 -0
- package/dist/pluginAssets/BundledPluginAssetReader.js.map +1 -0
- package/dist/plugins/flexipage/ui/assets/index-BAFqMU7k.js +48 -0
- package/dist/plugins/flexipage/ui/assets/index-U3SB2gLS.css +1 -0
- package/dist/plugins/flexipage/ui/index.html +16 -0
- package/dist/plugins/schema/ui/assets/index-DCLgZby3.css +1 -0
- package/dist/plugins/schema/ui/assets/index-Ho7jg9o_.js +70 -0
- package/dist/plugins/schema/ui/index.html +14 -0
- package/dist/types/HttpAsset.d.ts +18 -0
- package/dist/types/HttpAsset.d.ts.map +1 -0
- package/dist/types/HttpAsset.js +8 -0
- package/dist/types/HttpAsset.js.map +1 -0
- package/dist/types/PluginDataUpdateMessage.d.ts +24 -0
- package/dist/types/PluginDataUpdateMessage.d.ts.map +1 -0
- package/dist/types/PluginDataUpdateMessage.js +8 -0
- package/dist/types/PluginDataUpdateMessage.js.map +1 -0
- package/dist/types/PluginInfo.d.ts +20 -0
- package/dist/types/PluginInfo.d.ts.map +1 -0
- package/dist/types/PluginInfo.js +8 -0
- package/dist/types/PluginInfo.js.map +1 -0
- package/dist/types/VisualizeOutcome.d.ts +19 -0
- package/dist/types/VisualizeOutcome.d.ts.map +1 -0
- package/dist/types/VisualizeOutcome.js +8 -0
- package/dist/types/VisualizeOutcome.js.map +1 -0
- package/dist/types/WebAdapterOptions.d.ts +22 -0
- package/dist/types/WebAdapterOptions.d.ts.map +1 -0
- package/dist/types/WebAdapterOptions.js +8 -0
- package/dist/types/WebAdapterOptions.js.map +1 -0
- 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"}
|