@nbreak/runtime-loader 0.1.0

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 ADDED
@@ -0,0 +1,34 @@
1
+ Data Screen License
2
+ ===================
3
+
4
+ Copyright (c) 2026 NBreak. All rights reserved.
5
+
6
+ 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
7
+ This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
8
+
9
+ 您可以自由地:
10
+ ------------------
11
+ * **分享** — 在任何媒介以任何形式复制、发行本作品
12
+ * **演绎** — 修改、转换或以本作品为基础进行创作
13
+
14
+ 惟须遵守下列条件:
15
+ ------------------
16
+ * **署名** — 您必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书。
17
+ * **非商业性使用** — 您不得将本作品用于商业目的。
18
+
19
+ **商业使用需获得商业授权。** 请参阅项目根目录下的 LICENSE-COMMERCIAL 文件了解商业授权详情。
20
+
21
+ 没有附加限制 — 您不得适用法律限制或技术措施从而限制他人做本许可协议允许的事情。
22
+
23
+ 完整协议文本请访问:
24
+ https://creativecommons.org/licenses/by-nc/4.0/legalcode
25
+
26
+ ---
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @datascreen/runtime-loader
2
+
3
+ DataScreen 运行时扩展加载器:Module Federation + UMD fallback。
@@ -0,0 +1,463 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _nbreak_core = require("@nbreak/core");
3
+ let _nbreak_shared = require("@nbreak/shared");
4
+ //#region src/strategies/federation.js
5
+ /**
6
+ * @nbreak/runtime-loader - Module Federation 加载策略
7
+ *
8
+ * 通过 __federation__ 或 __webpack_init_sharing__ 加载联邦模块
9
+ * 优先级高于 UMD,但需要宿主构建时配置 Module Federation
10
+ */
11
+ /**
12
+ * 是否支持 Module Federation
13
+ * @returns {boolean}
14
+ */
15
+ function isFederationSupported() {
16
+ return typeof __webpack_init_sharing__ === "function" || typeof __federation__ !== "undefined" || typeof window !== "undefined" && typeof window.__federation__ !== "undefined";
17
+ }
18
+ /**
19
+ * 加载联邦模块
20
+ * @param {string} remoteName - 远程模块名
21
+ * @param {string} modulePath - 模块路径(如 './index')
22
+ * @param {string} remoteUrl - 远程入口 URL(如需动态注入)
23
+ * @returns {Promise<*>}
24
+ */
25
+ async function loadFederation(remoteName, modulePath, remoteUrl) {
26
+ if (remoteUrl && !isRemoteLoaded(remoteName)) await injectRemoteEntry(remoteName, remoteUrl);
27
+ if (typeof __webpack_init_sharing__ === "function") await __webpack_init_sharing__("default");
28
+ const container = await getRemoteContainer(remoteName);
29
+ if (!container) throw new Error(`联邦模块 "${remoteName}" 未找到`);
30
+ if (container.init) await container.init(__webpack_share_scopes__ || { default: {} });
31
+ const factory = await container.get(modulePath);
32
+ if (!factory) throw new Error(`联邦模块 "${remoteName}" 中未找到 "${modulePath}"`);
33
+ return factory();
34
+ }
35
+ /**
36
+ * 检查远程模块是否已注入
37
+ */
38
+ function isRemoteLoaded(remoteName) {
39
+ if (typeof window === "undefined") return false;
40
+ return !!(window[remoteName] || window.__federation__?.[remoteName]);
41
+ }
42
+ /**
43
+ * 注入远程入口脚本
44
+ */
45
+ async function injectRemoteEntry(remoteName, remoteUrl) {
46
+ return new Promise((resolve, reject) => {
47
+ const script = document.createElement("script");
48
+ script.src = remoteUrl;
49
+ script.crossOrigin = "anonymous";
50
+ script.onload = () => resolve();
51
+ script.onerror = () => reject(/* @__PURE__ */ new Error(`联邦入口加载失败: ${remoteUrl}`));
52
+ document.head.appendChild(script);
53
+ });
54
+ }
55
+ /**
56
+ * 获取远程容器
57
+ */
58
+ async function getRemoteContainer(remoteName) {
59
+ if (typeof window === "undefined") return null;
60
+ let attempts = 0;
61
+ const maxAttempts = 50;
62
+ while (attempts < maxAttempts) {
63
+ const container = window[remoteName] || window.__federation__?.[remoteName];
64
+ if (container) return container;
65
+ await new Promise((r) => setTimeout(r, 100));
66
+ attempts++;
67
+ }
68
+ return null;
69
+ }
70
+ //#endregion
71
+ //#region src/strategies/esm.js
72
+ /**
73
+ * @nbreak/runtime-loader - ESM 动态 import 加载策略
74
+ *
75
+ * 通过 dynamic import() 加载 ESM 格式扩展
76
+ * 需要浏览器支持 import maps 或服务端允许 CORS
77
+ */
78
+ var loadedModules = /* @__PURE__ */ new Map();
79
+ /**
80
+ * 动态加载 ESM 扩展
81
+ * @param {string} url - 模块 URL
82
+ * @returns {Promise<*>}
83
+ */
84
+ async function loadEsm(url) {
85
+ if (loadedModules.has(url)) return loadedModules.get(url);
86
+ try {
87
+ const mod = await import(
88
+ /* @vite-ignore */
89
+ url
90
+ );
91
+ const extension = mod.default || mod;
92
+ loadedModules.set(url, extension);
93
+ return extension;
94
+ } catch (e) {
95
+ throw new Error(`ESM 动态加载失败: ${url} - ${e.message}`);
96
+ }
97
+ }
98
+ /**
99
+ * 通过 import maps 注册扩展
100
+ * @param {Object} imports - { "包名": "URL" }
101
+ */
102
+ function registerImportMap(imports = {}) {
103
+ if (typeof document === "undefined") return;
104
+ const existingMaps = document.querySelectorAll("script[type=\"importmap\"]");
105
+ let existingImports = {};
106
+ existingMaps.forEach((s) => {
107
+ try {
108
+ const data = JSON.parse(s.textContent);
109
+ if (data.imports) existingImports = {
110
+ ...existingImports,
111
+ ...data.imports
112
+ };
113
+ } catch (e) {}
114
+ });
115
+ const merged = {
116
+ ...existingImports,
117
+ ...imports
118
+ };
119
+ const script = document.createElement("script");
120
+ script.type = "importmap";
121
+ script.textContent = JSON.stringify({ imports: merged });
122
+ document.head.appendChild(script);
123
+ }
124
+ /**
125
+ * 清除已加载的 ESM 模块缓存
126
+ */
127
+ function clearEsmCache() {
128
+ loadedModules.clear();
129
+ }
130
+ //#endregion
131
+ //#region src/strategies/umd.js
132
+ /**
133
+ * @nbreak/runtime-loader - UMD 加载策略
134
+ *
135
+ * 通过动态 <script> 标签加载 UMD 格式的扩展包
136
+ * 适用于无 Module Federation 环境的 fallback
137
+ */
138
+ var scriptCounter = 0;
139
+ /**
140
+ * 加载 UMD 扩展
141
+ * @param {string} url - 扩展包 URL
142
+ * @param {string} globalName - UMD 全局变量名
143
+ * @param {Object} [options]
144
+ * @param {number} [options.timeout=10000] - 加载超时(毫秒)
145
+ * @returns {Promise<*>} 扩展模块导出
146
+ */
147
+ function loadUmd(url, globalName, options = {}) {
148
+ const timeout = options.timeout || 1e4;
149
+ return new Promise((resolve, reject) => {
150
+ if (globalName && typeof window !== "undefined" && window[globalName]) {
151
+ resolve(window[globalName]);
152
+ return;
153
+ }
154
+ const scriptId = `ds-ext-${++scriptCounter}`;
155
+ const script = document.createElement("script");
156
+ script.src = url;
157
+ script.id = scriptId;
158
+ script.crossOrigin = "anonymous";
159
+ const timer = setTimeout(() => {
160
+ cleanup();
161
+ reject(/* @__PURE__ */ new Error(`加载超时: ${url} (${timeout}ms)`));
162
+ }, timeout);
163
+ function cleanup() {
164
+ clearTimeout(timer);
165
+ script.onload = null;
166
+ script.onerror = null;
167
+ }
168
+ script.onload = () => {
169
+ cleanup();
170
+ if (globalName && typeof window !== "undefined") {
171
+ const mod = window[globalName];
172
+ if (mod) resolve(mod);
173
+ else reject(/* @__PURE__ */ new Error(`UMD 全局变量 "${globalName}" 未找到`));
174
+ } else {
175
+ if (typeof window !== "undefined" && window.__ds_extensions__) {
176
+ const ext = window.__ds_extensions__[scriptId];
177
+ if (ext) {
178
+ resolve(ext);
179
+ return;
180
+ }
181
+ }
182
+ resolve(null);
183
+ }
184
+ };
185
+ script.onerror = (e) => {
186
+ cleanup();
187
+ reject(/* @__PURE__ */ new Error(`加载失败: ${url}`));
188
+ };
189
+ document.head.appendChild(script);
190
+ });
191
+ }
192
+ /**
193
+ * 移除已加载的 UMD 脚本
194
+ * @param {string} globalName
195
+ */
196
+ function unloadUmd(globalName) {
197
+ if (typeof window !== "undefined" && window[globalName]) delete window[globalName];
198
+ }
199
+ /**
200
+ * 预加载 UMD 扩展(不等待)
201
+ */
202
+ function preloadUmd(url, globalName) {
203
+ const link = document.createElement("link");
204
+ link.rel = "preload";
205
+ link.as = "script";
206
+ link.href = url;
207
+ document.head.appendChild(link);
208
+ }
209
+ //#endregion
210
+ //#region src/loadExtension.js
211
+ /**
212
+ * @nbreak/runtime-loader - 扩展加载主入口
213
+ *
214
+ * 提供 loadExtension() API,自动选择最优加载策略:
215
+ * 1. Module Federation(如果可用)
216
+ * 2. ESM dynamic import(如果浏览器支持)
217
+ * 3. UMD script fallback
218
+ *
219
+ * 加载完成后自动注册到 extensionRegistry
220
+ */
221
+ /**
222
+ * 当前宿主版本
223
+ */
224
+ var HOST_VERSION = "0.1.0";
225
+ /**
226
+ * 设置宿主版本(用于兼容性检查)
227
+ */
228
+ function setHostVersion(version) {
229
+ HOST_VERSION = version;
230
+ }
231
+ /**
232
+ * 加载扩展
233
+ *
234
+ * @param {string|Object} manifestInput - manifest URL 或 manifest 对象
235
+ * @param {Object} [options]
236
+ * @param {string} [options.strategy] - 强制使用策略(federation/esm/umd)
237
+ * @param {boolean} [options.autoRegister=true] - 加载后自动注册
238
+ * @param {number} [options.timeout=15000] - 总超时
239
+ * @returns {Promise<Object>} 加载的 Extension 对象
240
+ */
241
+ async function loadExtension(manifestInput, options = {}) {
242
+ const { autoRegister = true, timeout = 15e3 } = options;
243
+ const manifest = await resolveManifest(manifestInput);
244
+ if (!manifest) throw new Error("无法获取 manifest");
245
+ const { valid, errors } = (0, _nbreak_shared.validateManifest)(manifest);
246
+ if (!valid) throw new Error(`manifest 校验失败: ${errors.join("; ")}`);
247
+ if (manifest.datascreenVersion && !(0, _nbreak_shared.isVersionCompatible)(manifest.datascreenVersion, HOST_VERSION)) throw new Error(`版本不兼容: 扩展要求 ${manifest.datascreenVersion},当前 ${HOST_VERSION}`);
248
+ if (_nbreak_core.extensionRegistry.has(manifest.name)) {
249
+ console.warn(`[DataScreen Runtime] 扩展 "${manifest.name}" 已注册,跳过加载`);
250
+ return _nbreak_core.extensionRegistry.getByName(manifest.name);
251
+ }
252
+ const strategy = options.strategy || selectStrategy(manifest);
253
+ console.log(`[DataScreen Runtime] 加载扩展 "${manifest.name}" (策略: ${strategy})`);
254
+ const extension = await loadWithTimeout(() => loadWithStrategy(manifest, strategy, options), timeout, `加载扩展 "${manifest.name}" 超时`);
255
+ if (!extension) throw new Error(`扩展 "${manifest.name}" 加载后未返回有效内容`);
256
+ extension.manifest = manifest;
257
+ if (autoRegister) {
258
+ extension.status = _nbreak_shared.EXTENSION_STATUS.LOADING;
259
+ if (!await _nbreak_core.extensionRegistry.register(extension)) console.warn(`[DataScreen Runtime] 扩展 "${manifest.name}" 注册失败`);
260
+ }
261
+ return extension;
262
+ }
263
+ /**
264
+ * 批量加载扩展
265
+ */
266
+ async function loadExtensions(manifestInputs, options = {}) {
267
+ const results = [];
268
+ for (const input of manifestInputs) try {
269
+ const ext = await loadExtension(input, options);
270
+ results.push({
271
+ success: true,
272
+ extension: ext
273
+ });
274
+ } catch (e) {
275
+ console.error(`[DataScreen Runtime] 加载失败:`, e);
276
+ results.push({
277
+ success: false,
278
+ error: e.message
279
+ });
280
+ }
281
+ return results;
282
+ }
283
+ /**
284
+ * 解析 manifest(URL 或对象)
285
+ */
286
+ async function resolveManifest(input) {
287
+ if (typeof input === "object" && input !== null) return input;
288
+ if (typeof input === "string") {
289
+ const response = await fetch(input);
290
+ if (!response.ok) throw new Error(`获取 manifest 失败: ${response.status} ${input}`);
291
+ return await response.json();
292
+ }
293
+ return null;
294
+ }
295
+ /**
296
+ * 自动选择加载策略
297
+ */
298
+ function selectStrategy(manifest) {
299
+ if (manifest.strategy) return manifest.strategy;
300
+ if (manifest.federation && manifest.federation.remoteName) return _nbreak_shared.LOAD_STRATEGIES.FEDERATION;
301
+ if (manifest.globalName) return _nbreak_shared.LOAD_STRATEGIES.UMD;
302
+ if (isFederationSupported()) return _nbreak_shared.LOAD_STRATEGIES.FEDERATION;
303
+ return _nbreak_shared.LOAD_STRATEGIES.ESM;
304
+ }
305
+ /**
306
+ * 按策略加载
307
+ */
308
+ async function loadWithStrategy(manifest, strategy, options) {
309
+ const baseUrl = manifest.baseUrl || "";
310
+ switch (strategy) {
311
+ case _nbreak_shared.LOAD_STRATEGIES.FEDERATION: {
312
+ const fed = manifest.federation || {};
313
+ return await loadFederation(fed.remoteName || manifest.name, fed.modulePath || "./index", fed.remoteUrl || baseUrl + manifest.entry);
314
+ }
315
+ case _nbreak_shared.LOAD_STRATEGIES.ESM: return await loadEsm(baseUrl + (manifest.module || manifest.entry));
316
+ case _nbreak_shared.LOAD_STRATEGIES.UMD: return await loadUmd(baseUrl + manifest.entry, manifest.globalName || toGlobalName(manifest.name), options);
317
+ default: throw new Error(`未知加载策略: ${strategy}`);
318
+ }
319
+ }
320
+ /**
321
+ * 带超时的加载
322
+ */
323
+ async function loadWithTimeout(loader, timeout, errorMessage) {
324
+ return Promise.race([loader(), new Promise((_, reject) => setTimeout(() => reject(new Error(errorMessage)), timeout))]);
325
+ }
326
+ /**
327
+ * 包名转全局变量名
328
+ */
329
+ function toGlobalName(name) {
330
+ return name.replace(/^@/, "").replace(/[/-]/g, "_").replace(/\.js$/, "");
331
+ }
332
+ /**
333
+ * 卸载扩展
334
+ */
335
+ async function unloadExtension(name) {
336
+ const ext = _nbreak_core.extensionRegistry.getByName(name);
337
+ if (!ext) return false;
338
+ await _nbreak_core.extensionRegistry.unregister(name);
339
+ if (ext.manifest) {
340
+ const { globalName } = ext.manifest;
341
+ if (globalName && typeof window !== "undefined" && window[globalName]) delete window[globalName];
342
+ }
343
+ return true;
344
+ }
345
+ //#endregion
346
+ //#region src/registry.js
347
+ /**
348
+ * @nbreak/runtime-loader - 扩展注册表服务
349
+ *
350
+ * 管理可用的扩展清单(manifest registry)
351
+ * 应用可从远程 API 拉取可用扩展列表,或本地配置
352
+ */
353
+ var ExtensionManifestRegistry = class {
354
+ constructor() {
355
+ this.manifests = /* @__PURE__ */ new Map();
356
+ this.sources = [];
357
+ }
358
+ /**
359
+ * 添加本地 manifest
360
+ */
361
+ add(manifest) {
362
+ const { valid, errors } = (0, _nbreak_shared.validateManifest)(manifest);
363
+ if (!valid) {
364
+ console.warn(`[DataScreen Manifest Registry] manifest 校验失败:`, errors);
365
+ return false;
366
+ }
367
+ this.manifests.set(manifest.name, manifest);
368
+ return true;
369
+ }
370
+ /**
371
+ * 批量添加
372
+ */
373
+ addAll(manifests) {
374
+ return manifests.map((m) => this.add(m));
375
+ }
376
+ /**
377
+ * 获取 manifest
378
+ */
379
+ get(name) {
380
+ return this.manifests.get(name) || null;
381
+ }
382
+ /**
383
+ * 获取所有 manifest
384
+ */
385
+ getAll() {
386
+ return Array.from(this.manifests.values());
387
+ }
388
+ /**
389
+ * 按 type 筛选
390
+ */
391
+ getByType(type) {
392
+ return this.getAll().filter((m) => m.type === type);
393
+ }
394
+ /**
395
+ * 添加远程源
396
+ * @param {string} sourceUrl - 返回 manifest 数组的 API URL
397
+ */
398
+ addSource(sourceUrl) {
399
+ this.sources.push(sourceUrl);
400
+ }
401
+ /**
402
+ * 从远程源同步 manifest
403
+ */
404
+ async sync() {
405
+ for (const sourceUrl of this.sources) try {
406
+ const response = await fetch(sourceUrl);
407
+ if (!response.ok) continue;
408
+ const data = await response.json();
409
+ (Array.isArray(data) ? data : data.manifests || data.extensions || []).forEach((m) => this.add(m));
410
+ } catch (e) {
411
+ console.warn(`[DataScreen Manifest Registry] 同步源失败: ${sourceUrl}`, e);
412
+ }
413
+ }
414
+ /**
415
+ * 移除 manifest
416
+ */
417
+ remove(name) {
418
+ return this.manifests.delete(name);
419
+ }
420
+ /**
421
+ * 清空
422
+ */
423
+ clear() {
424
+ this.manifests.clear();
425
+ this.sources = [];
426
+ }
427
+ /**
428
+ * 数量
429
+ */
430
+ size() {
431
+ return this.manifests.size;
432
+ }
433
+ };
434
+ var manifestRegistry = new ExtensionManifestRegistry();
435
+ //#endregion
436
+ //#region src/index.js
437
+ var VERSION = "0.1.0";
438
+ var PACKAGE_NAME = "@nbreak/runtime-loader";
439
+ //#endregion
440
+ exports.ExtensionManifestRegistry = ExtensionManifestRegistry;
441
+ Object.defineProperty(exports, "LOAD_STRATEGIES", {
442
+ enumerable: true,
443
+ get: function() {
444
+ return _nbreak_shared.LOAD_STRATEGIES;
445
+ }
446
+ });
447
+ exports.PACKAGE_NAME = PACKAGE_NAME;
448
+ exports.VERSION = VERSION;
449
+ exports.clearEsmCache = clearEsmCache;
450
+ exports.isFederationSupported = isFederationSupported;
451
+ exports.loadEsm = loadEsm;
452
+ exports.loadExtension = loadExtension;
453
+ exports.loadExtensions = loadExtensions;
454
+ exports.loadFederation = loadFederation;
455
+ exports.loadUmd = loadUmd;
456
+ exports.manifestRegistry = manifestRegistry;
457
+ exports.preloadUmd = preloadUmd;
458
+ exports.registerImportMap = registerImportMap;
459
+ exports.setHostVersion = setHostVersion;
460
+ exports.unloadExtension = unloadExtension;
461
+ exports.unloadUmd = unloadUmd;
462
+
463
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["extensionRegistry","EXTENSION_STATUS","LOAD_STRATEGIES"],"sources":["../../src/strategies/federation.js","../../src/strategies/esm.js","../../src/strategies/umd.js","../../src/loadExtension.js","../../src/registry.js","../../src/index.js"],"sourcesContent":["/**\n * @nbreak/runtime-loader - Module Federation 加载策略\n *\n * 通过 __federation__ 或 __webpack_init_sharing__ 加载联邦模块\n * 优先级高于 UMD,但需要宿主构建时配置 Module Federation\n */\n\n/**\n * 是否支持 Module Federation\n * @returns {boolean}\n */\nexport function isFederationSupported() {\n return typeof __webpack_init_sharing__ === 'function' ||\n typeof __federation__ !== 'undefined' ||\n (typeof window !== 'undefined' && typeof window.__federation__ !== 'undefined');\n}\n\n/**\n * 加载联邦模块\n * @param {string} remoteName - 远程模块名\n * @param {string} modulePath - 模块路径(如 './index')\n * @param {string} remoteUrl - 远程入口 URL(如需动态注入)\n * @returns {Promise<*>}\n */\nexport async function loadFederation(remoteName, modulePath, remoteUrl) {\n // 注入远程入口(如果未加载)\n if (remoteUrl && !isRemoteLoaded(remoteName)) {\n await injectRemoteEntry(remoteName, remoteUrl);\n }\n\n // 初始化共享作用域\n if (typeof __webpack_init_sharing__ === 'function') {\n await __webpack_init_sharing__('default');\n }\n\n const container = await getRemoteContainer(remoteName);\n if (!container) {\n throw new Error(`联邦模块 \"${remoteName}\" 未找到`);\n }\n\n // 初始化容器\n if (container.init) {\n await container.init(__webpack_share_scopes__ || { default: {} });\n }\n\n // 获取模块\n const factory = await container.get(modulePath);\n if (!factory) {\n throw new Error(`联邦模块 \"${remoteName}\" 中未找到 \"${modulePath}\"`);\n }\n\n return factory();\n}\n\n/**\n * 检查远程模块是否已注入\n */\nfunction isRemoteLoaded(remoteName) {\n if (typeof window === 'undefined') return false;\n return !!(window[remoteName] || window.__federation__?.[remoteName]);\n}\n\n/**\n * 注入远程入口脚本\n */\nasync function injectRemoteEntry(remoteName, remoteUrl) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = remoteUrl;\n script.crossOrigin = 'anonymous';\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`联邦入口加载失败: ${remoteUrl}`));\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * 获取远程容器\n */\nasync function getRemoteContainer(remoteName) {\n if (typeof window === 'undefined') return null;\n\n // 等待容器可用(给 script 一些时间)\n let attempts = 0;\n const maxAttempts = 50;\n\n while (attempts < maxAttempts) {\n const container = window[remoteName] || window.__federation__?.[remoteName];\n if (container) return container;\n await new Promise(r => setTimeout(r, 100));\n attempts++;\n }\n\n return null;\n}\n","/**\n * @nbreak/runtime-loader - ESM 动态 import 加载策略\n *\n * 通过 dynamic import() 加载 ESM 格式扩展\n * 需要浏览器支持 import maps 或服务端允许 CORS\n */\n\nconst loadedModules = new Map();\n\n/**\n * 动态加载 ESM 扩展\n * @param {string} url - 模块 URL\n * @returns {Promise<*>}\n */\nexport async function loadEsm(url) {\n if (loadedModules.has(url)) {\n return loadedModules.get(url);\n }\n\n try {\n const mod = await import(/* @vite-ignore */ url);\n const extension = mod.default || mod;\n loadedModules.set(url, extension);\n return extension;\n } catch (e) {\n throw new Error(`ESM 动态加载失败: ${url} - ${e.message}`);\n }\n}\n\n/**\n * 通过 import maps 注册扩展\n * @param {Object} imports - { \"包名\": \"URL\" }\n */\nexport function registerImportMap(imports = {}) {\n if (typeof document === 'undefined') return;\n\n const existingMaps = document.querySelectorAll('script[type=\"importmap\"]');\n let existingImports = {};\n existingMaps.forEach(s => {\n try {\n const data = JSON.parse(s.textContent);\n if (data.imports) {\n existingImports = { ...existingImports, ...data.imports };\n }\n } catch (e) {\n // ignore\n }\n });\n\n const merged = { ...existingImports, ...imports };\n const script = document.createElement('script');\n script.type = 'importmap';\n script.textContent = JSON.stringify({ imports: merged });\n document.head.appendChild(script);\n}\n\n/**\n * 清除已加载的 ESM 模块缓存\n */\nexport function clearEsmCache() {\n loadedModules.clear();\n}\n","/**\n * @nbreak/runtime-loader - UMD 加载策略\n *\n * 通过动态 <script> 标签加载 UMD 格式的扩展包\n * 适用于无 Module Federation 环境的 fallback\n */\n\nlet scriptCounter = 0;\n\n/**\n * 加载 UMD 扩展\n * @param {string} url - 扩展包 URL\n * @param {string} globalName - UMD 全局变量名\n * @param {Object} [options]\n * @param {number} [options.timeout=10000] - 加载超时(毫秒)\n * @returns {Promise<*>} 扩展模块导出\n */\nexport function loadUmd(url, globalName, options = {}) {\n const timeout = options.timeout || 10000;\n\n return new Promise((resolve, reject) => {\n // 如果全局变量已存在,直接返回\n if (globalName && typeof window !== 'undefined' && window[globalName]) {\n resolve(window[globalName]);\n return;\n }\n\n const scriptId = `ds-ext-${++scriptCounter}`;\n const script = document.createElement('script');\n script.src = url;\n script.id = scriptId;\n script.crossOrigin = 'anonymous';\n\n const timer = setTimeout(() => {\n cleanup();\n reject(new Error(`加载超时: ${url} (${timeout}ms)`));\n }, timeout);\n\n function cleanup() {\n clearTimeout(timer);\n script.onload = null;\n script.onerror = null;\n }\n\n script.onload = () => {\n cleanup();\n if (globalName && typeof window !== 'undefined') {\n const mod = window[globalName];\n if (mod) {\n resolve(mod);\n } else {\n reject(new Error(`UMD 全局变量 \"${globalName}\" 未找到`));\n }\n } else {\n // 尝试从 __ds_extensions__ 注册表获取\n if (typeof window !== 'undefined' && window.__ds_extensions__) {\n const ext = window.__ds_extensions__[scriptId];\n if (ext) {\n resolve(ext);\n return;\n }\n }\n resolve(null);\n }\n };\n\n script.onerror = (e) => {\n cleanup();\n reject(new Error(`加载失败: ${url}`));\n };\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * 移除已加载的 UMD 脚本\n * @param {string} globalName\n */\nexport function unloadUmd(globalName) {\n if (typeof window !== 'undefined' && window[globalName]) {\n delete window[globalName];\n }\n}\n\n/**\n * 预加载 UMD 扩展(不等待)\n */\nexport function preloadUmd(url, globalName) {\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'script';\n link.href = url;\n document.head.appendChild(link);\n}\n","/**\n * @nbreak/runtime-loader - 扩展加载主入口\n *\n * 提供 loadExtension() API,自动选择最优加载策略:\n * 1. Module Federation(如果可用)\n * 2. ESM dynamic import(如果浏览器支持)\n * 3. UMD script fallback\n *\n * 加载完成后自动注册到 extensionRegistry\n */\n\nimport { extensionRegistry } from '@nbreak/core';\nimport {\n validateManifest,\n isVersionCompatible,\n LOAD_STRATEGIES,\n EXTENSION_STATUS,\n} from '@nbreak/shared';\nimport { isFederationSupported, loadFederation } from './strategies/federation.js';\nimport { loadEsm } from './strategies/esm.js';\nimport { loadUmd } from './strategies/umd.js';\n\n/**\n * 当前宿主版本\n */\nlet HOST_VERSION = '0.1.0';\n\n/**\n * 设置宿主版本(用于兼容性检查)\n */\nexport function setHostVersion(version) {\n HOST_VERSION = version;\n}\n\n/**\n * 加载扩展\n *\n * @param {string|Object} manifestInput - manifest URL 或 manifest 对象\n * @param {Object} [options]\n * @param {string} [options.strategy] - 强制使用策略(federation/esm/umd)\n * @param {boolean} [options.autoRegister=true] - 加载后自动注册\n * @param {number} [options.timeout=15000] - 总超时\n * @returns {Promise<Object>} 加载的 Extension 对象\n */\nexport async function loadExtension(manifestInput, options = {}) {\n const { autoRegister = true, timeout = 15000 } = options;\n\n // 1. 获取 manifest\n const manifest = await resolveManifest(manifestInput);\n if (!manifest) {\n throw new Error('无法获取 manifest');\n }\n\n // 2. 校验 manifest\n const { valid, errors } = validateManifest(manifest);\n if (!valid) {\n throw new Error(`manifest 校验失败: ${errors.join('; ')}`);\n }\n\n // 3. 版本兼容性检查\n if (manifest.datascreenVersion && !isVersionCompatible(manifest.datascreenVersion, HOST_VERSION)) {\n throw new Error(`版本不兼容: 扩展要求 ${manifest.datascreenVersion},当前 ${HOST_VERSION}`);\n }\n\n // 4. 检查是否已注册\n if (extensionRegistry.has(manifest.name)) {\n console.warn(`[DataScreen Runtime] 扩展 \"${manifest.name}\" 已注册,跳过加载`);\n return extensionRegistry.getByName(manifest.name);\n }\n\n // 5. 选择策略并加载\n const strategy = options.strategy || selectStrategy(manifest);\n console.log(`[DataScreen Runtime] 加载扩展 \"${manifest.name}\" (策略: ${strategy})`);\n\n const extension = await loadWithTimeout(\n () => loadWithStrategy(manifest, strategy, options),\n timeout,\n `加载扩展 \"${manifest.name}\" 超时`\n );\n\n if (!extension) {\n throw new Error(`扩展 \"${manifest.name}\" 加载后未返回有效内容`);\n }\n\n // 6. 关联 manifest 并注册\n extension.manifest = manifest;\n\n if (autoRegister) {\n extension.status = EXTENSION_STATUS.LOADING;\n const success = await extensionRegistry.register(extension);\n if (!success) {\n console.warn(`[DataScreen Runtime] 扩展 \"${manifest.name}\" 注册失败`);\n }\n }\n\n return extension;\n}\n\n/**\n * 批量加载扩展\n */\nexport async function loadExtensions(manifestInputs, options = {}) {\n const results = [];\n for (const input of manifestInputs) {\n try {\n const ext = await loadExtension(input, options);\n results.push({ success: true, extension: ext });\n } catch (e) {\n console.error(`[DataScreen Runtime] 加载失败:`, e);\n results.push({ success: false, error: e.message });\n }\n }\n return results;\n}\n\n/**\n * 解析 manifest(URL 或对象)\n */\nasync function resolveManifest(input) {\n if (typeof input === 'object' && input !== null) {\n return input;\n }\n\n if (typeof input === 'string') {\n const response = await fetch(input);\n if (!response.ok) {\n throw new Error(`获取 manifest 失败: ${response.status} ${input}`);\n }\n return await response.json();\n }\n\n return null;\n}\n\n/**\n * 自动选择加载策略\n */\nfunction selectStrategy(manifest) {\n // 1. 如果 manifest 指定了 strategy\n if (manifest.strategy) {\n return manifest.strategy;\n }\n\n // 2. 如果 manifest 有 federation 配置\n if (manifest.federation && manifest.federation.remoteName) {\n return LOAD_STRATEGIES.FEDERATION;\n }\n\n // 3. 如果 manifest 有 globalName(UMD 标识)\n if (manifest.globalName) {\n return LOAD_STRATEGIES.UMD;\n }\n\n // 4. 默认:Federation > ESM\n if (isFederationSupported()) {\n return LOAD_STRATEGIES.FEDERATION;\n }\n\n return LOAD_STRATEGIES.ESM;\n}\n\n/**\n * 按策略加载\n */\nasync function loadWithStrategy(manifest, strategy, options) {\n const baseUrl = manifest.baseUrl || '';\n\n switch (strategy) {\n case LOAD_STRATEGIES.FEDERATION: {\n const fed = manifest.federation || {};\n const remoteName = fed.remoteName || manifest.name;\n const modulePath = fed.modulePath || './index';\n const remoteUrl = fed.remoteUrl || (baseUrl + manifest.entry);\n return await loadFederation(remoteName, modulePath, remoteUrl);\n }\n\n case LOAD_STRATEGIES.ESM: {\n const url = baseUrl + (manifest.module || manifest.entry);\n return await loadEsm(url);\n }\n\n case LOAD_STRATEGIES.UMD: {\n const url = baseUrl + manifest.entry;\n const globalName = manifest.globalName || toGlobalName(manifest.name);\n return await loadUmd(url, globalName, options);\n }\n\n default:\n throw new Error(`未知加载策略: ${strategy}`);\n }\n}\n\n/**\n * 带超时的加载\n */\nasync function loadWithTimeout(loader, timeout, errorMessage) {\n return Promise.race([\n loader(),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error(errorMessage)), timeout)\n ),\n ]);\n}\n\n/**\n * 包名转全局变量名\n */\nfunction toGlobalName(name) {\n return name\n .replace(/^@/, '')\n .replace(/[/-]/g, '_')\n .replace(/\\.js$/, '');\n}\n\n/**\n * 卸载扩展\n */\nexport async function unloadExtension(name) {\n const ext = extensionRegistry.getByName(name);\n if (!ext) return false;\n\n await extensionRegistry.unregister(name);\n\n // 清理脚本/模块缓存\n if (ext.manifest) {\n const { globalName } = ext.manifest;\n if (globalName && typeof window !== 'undefined' && window[globalName]) {\n delete window[globalName];\n }\n }\n\n return true;\n}\n","/**\n * @nbreak/runtime-loader - 扩展注册表服务\n *\n * 管理可用的扩展清单(manifest registry)\n * 应用可从远程 API 拉取可用扩展列表,或本地配置\n */\n\nimport { validateManifest } from '@nbreak/shared';\n\nclass ExtensionManifestRegistry {\n constructor() {\n this.manifests = new Map(); // name -> manifest\n this.sources = []; // 远程源\n }\n\n /**\n * 添加本地 manifest\n */\n add(manifest) {\n const { valid, errors } = validateManifest(manifest);\n if (!valid) {\n console.warn(`[DataScreen Manifest Registry] manifest 校验失败:`, errors);\n return false;\n }\n this.manifests.set(manifest.name, manifest);\n return true;\n }\n\n /**\n * 批量添加\n */\n addAll(manifests) {\n return manifests.map(m => this.add(m));\n }\n\n /**\n * 获取 manifest\n */\n get(name) {\n return this.manifests.get(name) || null;\n }\n\n /**\n * 获取所有 manifest\n */\n getAll() {\n return Array.from(this.manifests.values());\n }\n\n /**\n * 按 type 筛选\n */\n getByType(type) {\n return this.getAll().filter(m => m.type === type);\n }\n\n /**\n * 添加远程源\n * @param {string} sourceUrl - 返回 manifest 数组的 API URL\n */\n addSource(sourceUrl) {\n this.sources.push(sourceUrl);\n }\n\n /**\n * 从远程源同步 manifest\n */\n async sync() {\n for (const sourceUrl of this.sources) {\n try {\n const response = await fetch(sourceUrl);\n if (!response.ok) continue;\n const data = await response.json();\n const manifests = Array.isArray(data) ? data : (data.manifests || data.extensions || []);\n manifests.forEach(m => this.add(m));\n } catch (e) {\n console.warn(`[DataScreen Manifest Registry] 同步源失败: ${sourceUrl}`, e);\n }\n }\n }\n\n /**\n * 移除 manifest\n */\n remove(name) {\n return this.manifests.delete(name);\n }\n\n /**\n * 清空\n */\n clear() {\n this.manifests.clear();\n this.sources = [];\n }\n\n /**\n * 数量\n */\n size() {\n return this.manifests.size;\n }\n}\n\nexport { ExtensionManifestRegistry };\nexport const manifestRegistry = new ExtensionManifestRegistry();\nexport default ExtensionManifestRegistry;\n","/**\n * @nbreak/runtime-loader - 入口\n *\n * 运行时扩展加载器,提供:\n * - loadExtension(): 从 manifest URL 或对象加载单个扩展\n * - loadExtensions(): 批量加载\n * - unloadExtension(): 卸载\n * - manifestRegistry: 扩展清单管理\n * - 各加载策略(federation/esm/umd)单独导出\n */\n\nexport {\n loadExtension,\n loadExtensions,\n unloadExtension,\n setHostVersion,\n} from './loadExtension.js';\n\nexport { ExtensionManifestRegistry, manifestRegistry } from './registry.js';\n\n// 加载策略\nexport { isFederationSupported, loadFederation } from './strategies/federation.js';\nexport { loadEsm, registerImportMap, clearEsmCache } from './strategies/esm.js';\nexport { loadUmd, unloadUmd, preloadUmd } from './strategies/umd.js';\n\n// 常量\nexport { LOAD_STRATEGIES } from '@nbreak/shared';\n\n// 版本信息\nexport const VERSION = '0.1.0';\nexport const PACKAGE_NAME = '@nbreak/runtime-loader';\n"],"mappings":"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"}
@@ -0,0 +1,441 @@
1
+ import { extensionRegistry } from "@nbreak/core";
2
+ import { EXTENSION_STATUS, LOAD_STRATEGIES, LOAD_STRATEGIES as LOAD_STRATEGIES$1, isVersionCompatible, validateManifest } from "@nbreak/shared";
3
+ //#region src/strategies/federation.js
4
+ /**
5
+ * @nbreak/runtime-loader - Module Federation 加载策略
6
+ *
7
+ * 通过 __federation__ 或 __webpack_init_sharing__ 加载联邦模块
8
+ * 优先级高于 UMD,但需要宿主构建时配置 Module Federation
9
+ */
10
+ /**
11
+ * 是否支持 Module Federation
12
+ * @returns {boolean}
13
+ */
14
+ function isFederationSupported() {
15
+ return typeof __webpack_init_sharing__ === "function" || typeof __federation__ !== "undefined" || typeof window !== "undefined" && typeof window.__federation__ !== "undefined";
16
+ }
17
+ /**
18
+ * 加载联邦模块
19
+ * @param {string} remoteName - 远程模块名
20
+ * @param {string} modulePath - 模块路径(如 './index')
21
+ * @param {string} remoteUrl - 远程入口 URL(如需动态注入)
22
+ * @returns {Promise<*>}
23
+ */
24
+ async function loadFederation(remoteName, modulePath, remoteUrl) {
25
+ if (remoteUrl && !isRemoteLoaded(remoteName)) await injectRemoteEntry(remoteName, remoteUrl);
26
+ if (typeof __webpack_init_sharing__ === "function") await __webpack_init_sharing__("default");
27
+ const container = await getRemoteContainer(remoteName);
28
+ if (!container) throw new Error(`联邦模块 "${remoteName}" 未找到`);
29
+ if (container.init) await container.init(__webpack_share_scopes__ || { default: {} });
30
+ const factory = await container.get(modulePath);
31
+ if (!factory) throw new Error(`联邦模块 "${remoteName}" 中未找到 "${modulePath}"`);
32
+ return factory();
33
+ }
34
+ /**
35
+ * 检查远程模块是否已注入
36
+ */
37
+ function isRemoteLoaded(remoteName) {
38
+ if (typeof window === "undefined") return false;
39
+ return !!(window[remoteName] || window.__federation__?.[remoteName]);
40
+ }
41
+ /**
42
+ * 注入远程入口脚本
43
+ */
44
+ async function injectRemoteEntry(remoteName, remoteUrl) {
45
+ return new Promise((resolve, reject) => {
46
+ const script = document.createElement("script");
47
+ script.src = remoteUrl;
48
+ script.crossOrigin = "anonymous";
49
+ script.onload = () => resolve();
50
+ script.onerror = () => reject(/* @__PURE__ */ new Error(`联邦入口加载失败: ${remoteUrl}`));
51
+ document.head.appendChild(script);
52
+ });
53
+ }
54
+ /**
55
+ * 获取远程容器
56
+ */
57
+ async function getRemoteContainer(remoteName) {
58
+ if (typeof window === "undefined") return null;
59
+ let attempts = 0;
60
+ const maxAttempts = 50;
61
+ while (attempts < maxAttempts) {
62
+ const container = window[remoteName] || window.__federation__?.[remoteName];
63
+ if (container) return container;
64
+ await new Promise((r) => setTimeout(r, 100));
65
+ attempts++;
66
+ }
67
+ return null;
68
+ }
69
+ //#endregion
70
+ //#region src/strategies/esm.js
71
+ /**
72
+ * @nbreak/runtime-loader - ESM 动态 import 加载策略
73
+ *
74
+ * 通过 dynamic import() 加载 ESM 格式扩展
75
+ * 需要浏览器支持 import maps 或服务端允许 CORS
76
+ */
77
+ var loadedModules = /* @__PURE__ */ new Map();
78
+ /**
79
+ * 动态加载 ESM 扩展
80
+ * @param {string} url - 模块 URL
81
+ * @returns {Promise<*>}
82
+ */
83
+ async function loadEsm(url) {
84
+ if (loadedModules.has(url)) return loadedModules.get(url);
85
+ try {
86
+ const mod = await import(
87
+ /* @vite-ignore */
88
+ url
89
+ );
90
+ const extension = mod.default || mod;
91
+ loadedModules.set(url, extension);
92
+ return extension;
93
+ } catch (e) {
94
+ throw new Error(`ESM 动态加载失败: ${url} - ${e.message}`);
95
+ }
96
+ }
97
+ /**
98
+ * 通过 import maps 注册扩展
99
+ * @param {Object} imports - { "包名": "URL" }
100
+ */
101
+ function registerImportMap(imports = {}) {
102
+ if (typeof document === "undefined") return;
103
+ const existingMaps = document.querySelectorAll("script[type=\"importmap\"]");
104
+ let existingImports = {};
105
+ existingMaps.forEach((s) => {
106
+ try {
107
+ const data = JSON.parse(s.textContent);
108
+ if (data.imports) existingImports = {
109
+ ...existingImports,
110
+ ...data.imports
111
+ };
112
+ } catch (e) {}
113
+ });
114
+ const merged = {
115
+ ...existingImports,
116
+ ...imports
117
+ };
118
+ const script = document.createElement("script");
119
+ script.type = "importmap";
120
+ script.textContent = JSON.stringify({ imports: merged });
121
+ document.head.appendChild(script);
122
+ }
123
+ /**
124
+ * 清除已加载的 ESM 模块缓存
125
+ */
126
+ function clearEsmCache() {
127
+ loadedModules.clear();
128
+ }
129
+ //#endregion
130
+ //#region src/strategies/umd.js
131
+ /**
132
+ * @nbreak/runtime-loader - UMD 加载策略
133
+ *
134
+ * 通过动态 <script> 标签加载 UMD 格式的扩展包
135
+ * 适用于无 Module Federation 环境的 fallback
136
+ */
137
+ var scriptCounter = 0;
138
+ /**
139
+ * 加载 UMD 扩展
140
+ * @param {string} url - 扩展包 URL
141
+ * @param {string} globalName - UMD 全局变量名
142
+ * @param {Object} [options]
143
+ * @param {number} [options.timeout=10000] - 加载超时(毫秒)
144
+ * @returns {Promise<*>} 扩展模块导出
145
+ */
146
+ function loadUmd(url, globalName, options = {}) {
147
+ const timeout = options.timeout || 1e4;
148
+ return new Promise((resolve, reject) => {
149
+ if (globalName && typeof window !== "undefined" && window[globalName]) {
150
+ resolve(window[globalName]);
151
+ return;
152
+ }
153
+ const scriptId = `ds-ext-${++scriptCounter}`;
154
+ const script = document.createElement("script");
155
+ script.src = url;
156
+ script.id = scriptId;
157
+ script.crossOrigin = "anonymous";
158
+ const timer = setTimeout(() => {
159
+ cleanup();
160
+ reject(/* @__PURE__ */ new Error(`加载超时: ${url} (${timeout}ms)`));
161
+ }, timeout);
162
+ function cleanup() {
163
+ clearTimeout(timer);
164
+ script.onload = null;
165
+ script.onerror = null;
166
+ }
167
+ script.onload = () => {
168
+ cleanup();
169
+ if (globalName && typeof window !== "undefined") {
170
+ const mod = window[globalName];
171
+ if (mod) resolve(mod);
172
+ else reject(/* @__PURE__ */ new Error(`UMD 全局变量 "${globalName}" 未找到`));
173
+ } else {
174
+ if (typeof window !== "undefined" && window.__ds_extensions__) {
175
+ const ext = window.__ds_extensions__[scriptId];
176
+ if (ext) {
177
+ resolve(ext);
178
+ return;
179
+ }
180
+ }
181
+ resolve(null);
182
+ }
183
+ };
184
+ script.onerror = (e) => {
185
+ cleanup();
186
+ reject(/* @__PURE__ */ new Error(`加载失败: ${url}`));
187
+ };
188
+ document.head.appendChild(script);
189
+ });
190
+ }
191
+ /**
192
+ * 移除已加载的 UMD 脚本
193
+ * @param {string} globalName
194
+ */
195
+ function unloadUmd(globalName) {
196
+ if (typeof window !== "undefined" && window[globalName]) delete window[globalName];
197
+ }
198
+ /**
199
+ * 预加载 UMD 扩展(不等待)
200
+ */
201
+ function preloadUmd(url, globalName) {
202
+ const link = document.createElement("link");
203
+ link.rel = "preload";
204
+ link.as = "script";
205
+ link.href = url;
206
+ document.head.appendChild(link);
207
+ }
208
+ //#endregion
209
+ //#region src/loadExtension.js
210
+ /**
211
+ * @nbreak/runtime-loader - 扩展加载主入口
212
+ *
213
+ * 提供 loadExtension() API,自动选择最优加载策略:
214
+ * 1. Module Federation(如果可用)
215
+ * 2. ESM dynamic import(如果浏览器支持)
216
+ * 3. UMD script fallback
217
+ *
218
+ * 加载完成后自动注册到 extensionRegistry
219
+ */
220
+ /**
221
+ * 当前宿主版本
222
+ */
223
+ var HOST_VERSION = "0.1.0";
224
+ /**
225
+ * 设置宿主版本(用于兼容性检查)
226
+ */
227
+ function setHostVersion(version) {
228
+ HOST_VERSION = version;
229
+ }
230
+ /**
231
+ * 加载扩展
232
+ *
233
+ * @param {string|Object} manifestInput - manifest URL 或 manifest 对象
234
+ * @param {Object} [options]
235
+ * @param {string} [options.strategy] - 强制使用策略(federation/esm/umd)
236
+ * @param {boolean} [options.autoRegister=true] - 加载后自动注册
237
+ * @param {number} [options.timeout=15000] - 总超时
238
+ * @returns {Promise<Object>} 加载的 Extension 对象
239
+ */
240
+ async function loadExtension(manifestInput, options = {}) {
241
+ const { autoRegister = true, timeout = 15e3 } = options;
242
+ const manifest = await resolveManifest(manifestInput);
243
+ if (!manifest) throw new Error("无法获取 manifest");
244
+ const { valid, errors } = validateManifest(manifest);
245
+ if (!valid) throw new Error(`manifest 校验失败: ${errors.join("; ")}`);
246
+ if (manifest.datascreenVersion && !isVersionCompatible(manifest.datascreenVersion, HOST_VERSION)) throw new Error(`版本不兼容: 扩展要求 ${manifest.datascreenVersion},当前 ${HOST_VERSION}`);
247
+ if (extensionRegistry.has(manifest.name)) {
248
+ console.warn(`[DataScreen Runtime] 扩展 "${manifest.name}" 已注册,跳过加载`);
249
+ return extensionRegistry.getByName(manifest.name);
250
+ }
251
+ const strategy = options.strategy || selectStrategy(manifest);
252
+ console.log(`[DataScreen Runtime] 加载扩展 "${manifest.name}" (策略: ${strategy})`);
253
+ const extension = await loadWithTimeout(() => loadWithStrategy(manifest, strategy, options), timeout, `加载扩展 "${manifest.name}" 超时`);
254
+ if (!extension) throw new Error(`扩展 "${manifest.name}" 加载后未返回有效内容`);
255
+ extension.manifest = manifest;
256
+ if (autoRegister) {
257
+ extension.status = EXTENSION_STATUS.LOADING;
258
+ if (!await extensionRegistry.register(extension)) console.warn(`[DataScreen Runtime] 扩展 "${manifest.name}" 注册失败`);
259
+ }
260
+ return extension;
261
+ }
262
+ /**
263
+ * 批量加载扩展
264
+ */
265
+ async function loadExtensions(manifestInputs, options = {}) {
266
+ const results = [];
267
+ for (const input of manifestInputs) try {
268
+ const ext = await loadExtension(input, options);
269
+ results.push({
270
+ success: true,
271
+ extension: ext
272
+ });
273
+ } catch (e) {
274
+ console.error(`[DataScreen Runtime] 加载失败:`, e);
275
+ results.push({
276
+ success: false,
277
+ error: e.message
278
+ });
279
+ }
280
+ return results;
281
+ }
282
+ /**
283
+ * 解析 manifest(URL 或对象)
284
+ */
285
+ async function resolveManifest(input) {
286
+ if (typeof input === "object" && input !== null) return input;
287
+ if (typeof input === "string") {
288
+ const response = await fetch(input);
289
+ if (!response.ok) throw new Error(`获取 manifest 失败: ${response.status} ${input}`);
290
+ return await response.json();
291
+ }
292
+ return null;
293
+ }
294
+ /**
295
+ * 自动选择加载策略
296
+ */
297
+ function selectStrategy(manifest) {
298
+ if (manifest.strategy) return manifest.strategy;
299
+ if (manifest.federation && manifest.federation.remoteName) return LOAD_STRATEGIES$1.FEDERATION;
300
+ if (manifest.globalName) return LOAD_STRATEGIES$1.UMD;
301
+ if (isFederationSupported()) return LOAD_STRATEGIES$1.FEDERATION;
302
+ return LOAD_STRATEGIES$1.ESM;
303
+ }
304
+ /**
305
+ * 按策略加载
306
+ */
307
+ async function loadWithStrategy(manifest, strategy, options) {
308
+ const baseUrl = manifest.baseUrl || "";
309
+ switch (strategy) {
310
+ case LOAD_STRATEGIES$1.FEDERATION: {
311
+ const fed = manifest.federation || {};
312
+ return await loadFederation(fed.remoteName || manifest.name, fed.modulePath || "./index", fed.remoteUrl || baseUrl + manifest.entry);
313
+ }
314
+ case LOAD_STRATEGIES$1.ESM: return await loadEsm(baseUrl + (manifest.module || manifest.entry));
315
+ case LOAD_STRATEGIES$1.UMD: return await loadUmd(baseUrl + manifest.entry, manifest.globalName || toGlobalName(manifest.name), options);
316
+ default: throw new Error(`未知加载策略: ${strategy}`);
317
+ }
318
+ }
319
+ /**
320
+ * 带超时的加载
321
+ */
322
+ async function loadWithTimeout(loader, timeout, errorMessage) {
323
+ return Promise.race([loader(), new Promise((_, reject) => setTimeout(() => reject(new Error(errorMessage)), timeout))]);
324
+ }
325
+ /**
326
+ * 包名转全局变量名
327
+ */
328
+ function toGlobalName(name) {
329
+ return name.replace(/^@/, "").replace(/[/-]/g, "_").replace(/\.js$/, "");
330
+ }
331
+ /**
332
+ * 卸载扩展
333
+ */
334
+ async function unloadExtension(name) {
335
+ const ext = extensionRegistry.getByName(name);
336
+ if (!ext) return false;
337
+ await extensionRegistry.unregister(name);
338
+ if (ext.manifest) {
339
+ const { globalName } = ext.manifest;
340
+ if (globalName && typeof window !== "undefined" && window[globalName]) delete window[globalName];
341
+ }
342
+ return true;
343
+ }
344
+ //#endregion
345
+ //#region src/registry.js
346
+ /**
347
+ * @nbreak/runtime-loader - 扩展注册表服务
348
+ *
349
+ * 管理可用的扩展清单(manifest registry)
350
+ * 应用可从远程 API 拉取可用扩展列表,或本地配置
351
+ */
352
+ var ExtensionManifestRegistry = class {
353
+ constructor() {
354
+ this.manifests = /* @__PURE__ */ new Map();
355
+ this.sources = [];
356
+ }
357
+ /**
358
+ * 添加本地 manifest
359
+ */
360
+ add(manifest) {
361
+ const { valid, errors } = validateManifest(manifest);
362
+ if (!valid) {
363
+ console.warn(`[DataScreen Manifest Registry] manifest 校验失败:`, errors);
364
+ return false;
365
+ }
366
+ this.manifests.set(manifest.name, manifest);
367
+ return true;
368
+ }
369
+ /**
370
+ * 批量添加
371
+ */
372
+ addAll(manifests) {
373
+ return manifests.map((m) => this.add(m));
374
+ }
375
+ /**
376
+ * 获取 manifest
377
+ */
378
+ get(name) {
379
+ return this.manifests.get(name) || null;
380
+ }
381
+ /**
382
+ * 获取所有 manifest
383
+ */
384
+ getAll() {
385
+ return Array.from(this.manifests.values());
386
+ }
387
+ /**
388
+ * 按 type 筛选
389
+ */
390
+ getByType(type) {
391
+ return this.getAll().filter((m) => m.type === type);
392
+ }
393
+ /**
394
+ * 添加远程源
395
+ * @param {string} sourceUrl - 返回 manifest 数组的 API URL
396
+ */
397
+ addSource(sourceUrl) {
398
+ this.sources.push(sourceUrl);
399
+ }
400
+ /**
401
+ * 从远程源同步 manifest
402
+ */
403
+ async sync() {
404
+ for (const sourceUrl of this.sources) try {
405
+ const response = await fetch(sourceUrl);
406
+ if (!response.ok) continue;
407
+ const data = await response.json();
408
+ (Array.isArray(data) ? data : data.manifests || data.extensions || []).forEach((m) => this.add(m));
409
+ } catch (e) {
410
+ console.warn(`[DataScreen Manifest Registry] 同步源失败: ${sourceUrl}`, e);
411
+ }
412
+ }
413
+ /**
414
+ * 移除 manifest
415
+ */
416
+ remove(name) {
417
+ return this.manifests.delete(name);
418
+ }
419
+ /**
420
+ * 清空
421
+ */
422
+ clear() {
423
+ this.manifests.clear();
424
+ this.sources = [];
425
+ }
426
+ /**
427
+ * 数量
428
+ */
429
+ size() {
430
+ return this.manifests.size;
431
+ }
432
+ };
433
+ var manifestRegistry = new ExtensionManifestRegistry();
434
+ //#endregion
435
+ //#region src/index.js
436
+ var VERSION = "0.1.0";
437
+ var PACKAGE_NAME = "@nbreak/runtime-loader";
438
+ //#endregion
439
+ export { ExtensionManifestRegistry, LOAD_STRATEGIES, PACKAGE_NAME, VERSION, clearEsmCache, isFederationSupported, loadEsm, loadExtension, loadExtensions, loadFederation, loadUmd, manifestRegistry, preloadUmd, registerImportMap, setHostVersion, unloadExtension, unloadUmd };
440
+
441
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["LOAD_STRATEGIES"],"sources":["../../src/strategies/federation.js","../../src/strategies/esm.js","../../src/strategies/umd.js","../../src/loadExtension.js","../../src/registry.js","../../src/index.js"],"sourcesContent":["/**\n * @nbreak/runtime-loader - Module Federation 加载策略\n *\n * 通过 __federation__ 或 __webpack_init_sharing__ 加载联邦模块\n * 优先级高于 UMD,但需要宿主构建时配置 Module Federation\n */\n\n/**\n * 是否支持 Module Federation\n * @returns {boolean}\n */\nexport function isFederationSupported() {\n return typeof __webpack_init_sharing__ === 'function' ||\n typeof __federation__ !== 'undefined' ||\n (typeof window !== 'undefined' && typeof window.__federation__ !== 'undefined');\n}\n\n/**\n * 加载联邦模块\n * @param {string} remoteName - 远程模块名\n * @param {string} modulePath - 模块路径(如 './index')\n * @param {string} remoteUrl - 远程入口 URL(如需动态注入)\n * @returns {Promise<*>}\n */\nexport async function loadFederation(remoteName, modulePath, remoteUrl) {\n // 注入远程入口(如果未加载)\n if (remoteUrl && !isRemoteLoaded(remoteName)) {\n await injectRemoteEntry(remoteName, remoteUrl);\n }\n\n // 初始化共享作用域\n if (typeof __webpack_init_sharing__ === 'function') {\n await __webpack_init_sharing__('default');\n }\n\n const container = await getRemoteContainer(remoteName);\n if (!container) {\n throw new Error(`联邦模块 \"${remoteName}\" 未找到`);\n }\n\n // 初始化容器\n if (container.init) {\n await container.init(__webpack_share_scopes__ || { default: {} });\n }\n\n // 获取模块\n const factory = await container.get(modulePath);\n if (!factory) {\n throw new Error(`联邦模块 \"${remoteName}\" 中未找到 \"${modulePath}\"`);\n }\n\n return factory();\n}\n\n/**\n * 检查远程模块是否已注入\n */\nfunction isRemoteLoaded(remoteName) {\n if (typeof window === 'undefined') return false;\n return !!(window[remoteName] || window.__federation__?.[remoteName]);\n}\n\n/**\n * 注入远程入口脚本\n */\nasync function injectRemoteEntry(remoteName, remoteUrl) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = remoteUrl;\n script.crossOrigin = 'anonymous';\n\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`联邦入口加载失败: ${remoteUrl}`));\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * 获取远程容器\n */\nasync function getRemoteContainer(remoteName) {\n if (typeof window === 'undefined') return null;\n\n // 等待容器可用(给 script 一些时间)\n let attempts = 0;\n const maxAttempts = 50;\n\n while (attempts < maxAttempts) {\n const container = window[remoteName] || window.__federation__?.[remoteName];\n if (container) return container;\n await new Promise(r => setTimeout(r, 100));\n attempts++;\n }\n\n return null;\n}\n","/**\n * @nbreak/runtime-loader - ESM 动态 import 加载策略\n *\n * 通过 dynamic import() 加载 ESM 格式扩展\n * 需要浏览器支持 import maps 或服务端允许 CORS\n */\n\nconst loadedModules = new Map();\n\n/**\n * 动态加载 ESM 扩展\n * @param {string} url - 模块 URL\n * @returns {Promise<*>}\n */\nexport async function loadEsm(url) {\n if (loadedModules.has(url)) {\n return loadedModules.get(url);\n }\n\n try {\n const mod = await import(/* @vite-ignore */ url);\n const extension = mod.default || mod;\n loadedModules.set(url, extension);\n return extension;\n } catch (e) {\n throw new Error(`ESM 动态加载失败: ${url} - ${e.message}`);\n }\n}\n\n/**\n * 通过 import maps 注册扩展\n * @param {Object} imports - { \"包名\": \"URL\" }\n */\nexport function registerImportMap(imports = {}) {\n if (typeof document === 'undefined') return;\n\n const existingMaps = document.querySelectorAll('script[type=\"importmap\"]');\n let existingImports = {};\n existingMaps.forEach(s => {\n try {\n const data = JSON.parse(s.textContent);\n if (data.imports) {\n existingImports = { ...existingImports, ...data.imports };\n }\n } catch (e) {\n // ignore\n }\n });\n\n const merged = { ...existingImports, ...imports };\n const script = document.createElement('script');\n script.type = 'importmap';\n script.textContent = JSON.stringify({ imports: merged });\n document.head.appendChild(script);\n}\n\n/**\n * 清除已加载的 ESM 模块缓存\n */\nexport function clearEsmCache() {\n loadedModules.clear();\n}\n","/**\n * @nbreak/runtime-loader - UMD 加载策略\n *\n * 通过动态 <script> 标签加载 UMD 格式的扩展包\n * 适用于无 Module Federation 环境的 fallback\n */\n\nlet scriptCounter = 0;\n\n/**\n * 加载 UMD 扩展\n * @param {string} url - 扩展包 URL\n * @param {string} globalName - UMD 全局变量名\n * @param {Object} [options]\n * @param {number} [options.timeout=10000] - 加载超时(毫秒)\n * @returns {Promise<*>} 扩展模块导出\n */\nexport function loadUmd(url, globalName, options = {}) {\n const timeout = options.timeout || 10000;\n\n return new Promise((resolve, reject) => {\n // 如果全局变量已存在,直接返回\n if (globalName && typeof window !== 'undefined' && window[globalName]) {\n resolve(window[globalName]);\n return;\n }\n\n const scriptId = `ds-ext-${++scriptCounter}`;\n const script = document.createElement('script');\n script.src = url;\n script.id = scriptId;\n script.crossOrigin = 'anonymous';\n\n const timer = setTimeout(() => {\n cleanup();\n reject(new Error(`加载超时: ${url} (${timeout}ms)`));\n }, timeout);\n\n function cleanup() {\n clearTimeout(timer);\n script.onload = null;\n script.onerror = null;\n }\n\n script.onload = () => {\n cleanup();\n if (globalName && typeof window !== 'undefined') {\n const mod = window[globalName];\n if (mod) {\n resolve(mod);\n } else {\n reject(new Error(`UMD 全局变量 \"${globalName}\" 未找到`));\n }\n } else {\n // 尝试从 __ds_extensions__ 注册表获取\n if (typeof window !== 'undefined' && window.__ds_extensions__) {\n const ext = window.__ds_extensions__[scriptId];\n if (ext) {\n resolve(ext);\n return;\n }\n }\n resolve(null);\n }\n };\n\n script.onerror = (e) => {\n cleanup();\n reject(new Error(`加载失败: ${url}`));\n };\n\n document.head.appendChild(script);\n });\n}\n\n/**\n * 移除已加载的 UMD 脚本\n * @param {string} globalName\n */\nexport function unloadUmd(globalName) {\n if (typeof window !== 'undefined' && window[globalName]) {\n delete window[globalName];\n }\n}\n\n/**\n * 预加载 UMD 扩展(不等待)\n */\nexport function preloadUmd(url, globalName) {\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'script';\n link.href = url;\n document.head.appendChild(link);\n}\n","/**\n * @nbreak/runtime-loader - 扩展加载主入口\n *\n * 提供 loadExtension() API,自动选择最优加载策略:\n * 1. Module Federation(如果可用)\n * 2. ESM dynamic import(如果浏览器支持)\n * 3. UMD script fallback\n *\n * 加载完成后自动注册到 extensionRegistry\n */\n\nimport { extensionRegistry } from '@nbreak/core';\nimport {\n validateManifest,\n isVersionCompatible,\n LOAD_STRATEGIES,\n EXTENSION_STATUS,\n} from '@nbreak/shared';\nimport { isFederationSupported, loadFederation } from './strategies/federation.js';\nimport { loadEsm } from './strategies/esm.js';\nimport { loadUmd } from './strategies/umd.js';\n\n/**\n * 当前宿主版本\n */\nlet HOST_VERSION = '0.1.0';\n\n/**\n * 设置宿主版本(用于兼容性检查)\n */\nexport function setHostVersion(version) {\n HOST_VERSION = version;\n}\n\n/**\n * 加载扩展\n *\n * @param {string|Object} manifestInput - manifest URL 或 manifest 对象\n * @param {Object} [options]\n * @param {string} [options.strategy] - 强制使用策略(federation/esm/umd)\n * @param {boolean} [options.autoRegister=true] - 加载后自动注册\n * @param {number} [options.timeout=15000] - 总超时\n * @returns {Promise<Object>} 加载的 Extension 对象\n */\nexport async function loadExtension(manifestInput, options = {}) {\n const { autoRegister = true, timeout = 15000 } = options;\n\n // 1. 获取 manifest\n const manifest = await resolveManifest(manifestInput);\n if (!manifest) {\n throw new Error('无法获取 manifest');\n }\n\n // 2. 校验 manifest\n const { valid, errors } = validateManifest(manifest);\n if (!valid) {\n throw new Error(`manifest 校验失败: ${errors.join('; ')}`);\n }\n\n // 3. 版本兼容性检查\n if (manifest.datascreenVersion && !isVersionCompatible(manifest.datascreenVersion, HOST_VERSION)) {\n throw new Error(`版本不兼容: 扩展要求 ${manifest.datascreenVersion},当前 ${HOST_VERSION}`);\n }\n\n // 4. 检查是否已注册\n if (extensionRegistry.has(manifest.name)) {\n console.warn(`[DataScreen Runtime] 扩展 \"${manifest.name}\" 已注册,跳过加载`);\n return extensionRegistry.getByName(manifest.name);\n }\n\n // 5. 选择策略并加载\n const strategy = options.strategy || selectStrategy(manifest);\n console.log(`[DataScreen Runtime] 加载扩展 \"${manifest.name}\" (策略: ${strategy})`);\n\n const extension = await loadWithTimeout(\n () => loadWithStrategy(manifest, strategy, options),\n timeout,\n `加载扩展 \"${manifest.name}\" 超时`\n );\n\n if (!extension) {\n throw new Error(`扩展 \"${manifest.name}\" 加载后未返回有效内容`);\n }\n\n // 6. 关联 manifest 并注册\n extension.manifest = manifest;\n\n if (autoRegister) {\n extension.status = EXTENSION_STATUS.LOADING;\n const success = await extensionRegistry.register(extension);\n if (!success) {\n console.warn(`[DataScreen Runtime] 扩展 \"${manifest.name}\" 注册失败`);\n }\n }\n\n return extension;\n}\n\n/**\n * 批量加载扩展\n */\nexport async function loadExtensions(manifestInputs, options = {}) {\n const results = [];\n for (const input of manifestInputs) {\n try {\n const ext = await loadExtension(input, options);\n results.push({ success: true, extension: ext });\n } catch (e) {\n console.error(`[DataScreen Runtime] 加载失败:`, e);\n results.push({ success: false, error: e.message });\n }\n }\n return results;\n}\n\n/**\n * 解析 manifest(URL 或对象)\n */\nasync function resolveManifest(input) {\n if (typeof input === 'object' && input !== null) {\n return input;\n }\n\n if (typeof input === 'string') {\n const response = await fetch(input);\n if (!response.ok) {\n throw new Error(`获取 manifest 失败: ${response.status} ${input}`);\n }\n return await response.json();\n }\n\n return null;\n}\n\n/**\n * 自动选择加载策略\n */\nfunction selectStrategy(manifest) {\n // 1. 如果 manifest 指定了 strategy\n if (manifest.strategy) {\n return manifest.strategy;\n }\n\n // 2. 如果 manifest 有 federation 配置\n if (manifest.federation && manifest.federation.remoteName) {\n return LOAD_STRATEGIES.FEDERATION;\n }\n\n // 3. 如果 manifest 有 globalName(UMD 标识)\n if (manifest.globalName) {\n return LOAD_STRATEGIES.UMD;\n }\n\n // 4. 默认:Federation > ESM\n if (isFederationSupported()) {\n return LOAD_STRATEGIES.FEDERATION;\n }\n\n return LOAD_STRATEGIES.ESM;\n}\n\n/**\n * 按策略加载\n */\nasync function loadWithStrategy(manifest, strategy, options) {\n const baseUrl = manifest.baseUrl || '';\n\n switch (strategy) {\n case LOAD_STRATEGIES.FEDERATION: {\n const fed = manifest.federation || {};\n const remoteName = fed.remoteName || manifest.name;\n const modulePath = fed.modulePath || './index';\n const remoteUrl = fed.remoteUrl || (baseUrl + manifest.entry);\n return await loadFederation(remoteName, modulePath, remoteUrl);\n }\n\n case LOAD_STRATEGIES.ESM: {\n const url = baseUrl + (manifest.module || manifest.entry);\n return await loadEsm(url);\n }\n\n case LOAD_STRATEGIES.UMD: {\n const url = baseUrl + manifest.entry;\n const globalName = manifest.globalName || toGlobalName(manifest.name);\n return await loadUmd(url, globalName, options);\n }\n\n default:\n throw new Error(`未知加载策略: ${strategy}`);\n }\n}\n\n/**\n * 带超时的加载\n */\nasync function loadWithTimeout(loader, timeout, errorMessage) {\n return Promise.race([\n loader(),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error(errorMessage)), timeout)\n ),\n ]);\n}\n\n/**\n * 包名转全局变量名\n */\nfunction toGlobalName(name) {\n return name\n .replace(/^@/, '')\n .replace(/[/-]/g, '_')\n .replace(/\\.js$/, '');\n}\n\n/**\n * 卸载扩展\n */\nexport async function unloadExtension(name) {\n const ext = extensionRegistry.getByName(name);\n if (!ext) return false;\n\n await extensionRegistry.unregister(name);\n\n // 清理脚本/模块缓存\n if (ext.manifest) {\n const { globalName } = ext.manifest;\n if (globalName && typeof window !== 'undefined' && window[globalName]) {\n delete window[globalName];\n }\n }\n\n return true;\n}\n","/**\n * @nbreak/runtime-loader - 扩展注册表服务\n *\n * 管理可用的扩展清单(manifest registry)\n * 应用可从远程 API 拉取可用扩展列表,或本地配置\n */\n\nimport { validateManifest } from '@nbreak/shared';\n\nclass ExtensionManifestRegistry {\n constructor() {\n this.manifests = new Map(); // name -> manifest\n this.sources = []; // 远程源\n }\n\n /**\n * 添加本地 manifest\n */\n add(manifest) {\n const { valid, errors } = validateManifest(manifest);\n if (!valid) {\n console.warn(`[DataScreen Manifest Registry] manifest 校验失败:`, errors);\n return false;\n }\n this.manifests.set(manifest.name, manifest);\n return true;\n }\n\n /**\n * 批量添加\n */\n addAll(manifests) {\n return manifests.map(m => this.add(m));\n }\n\n /**\n * 获取 manifest\n */\n get(name) {\n return this.manifests.get(name) || null;\n }\n\n /**\n * 获取所有 manifest\n */\n getAll() {\n return Array.from(this.manifests.values());\n }\n\n /**\n * 按 type 筛选\n */\n getByType(type) {\n return this.getAll().filter(m => m.type === type);\n }\n\n /**\n * 添加远程源\n * @param {string} sourceUrl - 返回 manifest 数组的 API URL\n */\n addSource(sourceUrl) {\n this.sources.push(sourceUrl);\n }\n\n /**\n * 从远程源同步 manifest\n */\n async sync() {\n for (const sourceUrl of this.sources) {\n try {\n const response = await fetch(sourceUrl);\n if (!response.ok) continue;\n const data = await response.json();\n const manifests = Array.isArray(data) ? data : (data.manifests || data.extensions || []);\n manifests.forEach(m => this.add(m));\n } catch (e) {\n console.warn(`[DataScreen Manifest Registry] 同步源失败: ${sourceUrl}`, e);\n }\n }\n }\n\n /**\n * 移除 manifest\n */\n remove(name) {\n return this.manifests.delete(name);\n }\n\n /**\n * 清空\n */\n clear() {\n this.manifests.clear();\n this.sources = [];\n }\n\n /**\n * 数量\n */\n size() {\n return this.manifests.size;\n }\n}\n\nexport { ExtensionManifestRegistry };\nexport const manifestRegistry = new ExtensionManifestRegistry();\nexport default ExtensionManifestRegistry;\n","/**\n * @nbreak/runtime-loader - 入口\n *\n * 运行时扩展加载器,提供:\n * - loadExtension(): 从 manifest URL 或对象加载单个扩展\n * - loadExtensions(): 批量加载\n * - unloadExtension(): 卸载\n * - manifestRegistry: 扩展清单管理\n * - 各加载策略(federation/esm/umd)单独导出\n */\n\nexport {\n loadExtension,\n loadExtensions,\n unloadExtension,\n setHostVersion,\n} from './loadExtension.js';\n\nexport { ExtensionManifestRegistry, manifestRegistry } from './registry.js';\n\n// 加载策略\nexport { isFederationSupported, loadFederation } from './strategies/federation.js';\nexport { loadEsm, registerImportMap, clearEsmCache } from './strategies/esm.js';\nexport { loadUmd, unloadUmd, preloadUmd } from './strategies/umd.js';\n\n// 常量\nexport { LOAD_STRATEGIES } from '@nbreak/shared';\n\n// 版本信息\nexport const VERSION = '0.1.0';\nexport const PACKAGE_NAME = '@nbreak/runtime-loader';\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@nbreak/runtime-loader",
3
+ "version": "0.1.0",
4
+ "description": "DataScreen 运行时扩展加载器:Module Federation + UMD fallback",
5
+ "type": "module",
6
+ "main": "./dist/cjs/index.cjs",
7
+ "module": "./dist/esm/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/cjs/index.cjs"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "dependencies": {
19
+ "@nbreak/shared": "0.1.0",
20
+ "@nbreak/core": "0.1.0"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "license": "SEE LICENSE IN LICENSE",
26
+ "scripts": {
27
+ "build": "rm -rf dist && BUILD_FORMAT=es vite build && BUILD_FORMAT=cjs vite build",
28
+ "dev": "vite build --watch"
29
+ }
30
+ }