web-extend-plugin-vue2 0.3.6 → 0.3.8

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/dist/index.mjs CHANGED
@@ -39,8 +39,8 @@ const defaultManifestFetchCache = {
39
39
  };
40
40
  const routeSynthNamePrefix = '__wep_';
41
41
  const defaultWebExtendPluginRuntime = {
42
- manifestBase: '/fp-api',
43
- manifestListPath: '/api/frontend-plugins',
42
+ manifestBase: '/dev-api',
43
+ manifestListPath: '/web-plugin',
44
44
  manifestFetchCredentials: 'include',
45
45
  devPingPath: '/__web_plugin_dev_ping',
46
46
  devReloadSsePath: '/__web_plugin_reload_stream',
@@ -50,7 +50,7 @@ const defaultWebExtendPluginRuntime = {
50
50
  allowedScriptHosts: ['localhost', '127.0.0.1', '::1'],
51
51
  bridgeAllowedPathPrefixes: ['/api/'],
52
52
  pluginMountPath: '/plugin',
53
- devFallbackStaticManifestUrl: '/web-plugins/plugins.manifest.json'
53
+ devFallbackStaticManifestUrl: ''
54
54
  };
55
55
 
56
56
  /**
@@ -225,21 +225,35 @@ function isScriptHostAllowed(url, hostSet) {
225
225
  }
226
226
  }
227
227
 
228
- /**
229
- * 合并用户、环境与默认配置得到运行时选项。
230
- */
231
228
  const DEF = defaultWebExtendPluginRuntime;
232
229
  const EK = webExtendPluginEnvKeys;
230
+ function asRecord$1(value) {
231
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
232
+ }
233
+ function normalizeHostBridge(userVal) {
234
+ const raw = asRecord$1(userVal);
235
+ if (!raw) {
236
+ return undefined;
237
+ }
238
+ const normalized = {};
239
+ if (raw.modules && typeof raw.modules === 'object' && !Array.isArray(raw.modules)) {
240
+ normalized.modules = { ...raw.modules };
241
+ }
242
+ if (raw.components && typeof raw.components === 'object' && !Array.isArray(raw.components)) {
243
+ normalized.components = { ...raw.components };
244
+ }
245
+ return normalized.modules || normalized.components ? normalized : undefined;
246
+ }
233
247
  function resolveManifestCredentials(userVal, envKey, fallback) {
234
248
  if (userVal !== undefined) {
235
- const s = String(userVal);
236
- if (s === 'include' || s === 'omit' || s === 'same-origin') {
237
- return s;
249
+ const normalized = String(userVal);
250
+ if (normalized === 'include' || normalized === 'omit' || normalized === 'same-origin') {
251
+ return normalized;
238
252
  }
239
253
  }
240
- const e = resolveBundledEnv(envKey, '');
241
- if (e === 'include' || e === 'omit' || e === 'same-origin') {
242
- return e;
254
+ const envValue = resolveBundledEnv(envKey, '');
255
+ if (envValue === 'include' || envValue === 'omit' || envValue === 'same-origin') {
256
+ return envValue;
243
257
  }
244
258
  return fallback;
245
259
  }
@@ -248,167 +262,184 @@ function resolvePositiveInt(userVal, envKey, fallback) {
248
262
  return Math.floor(userVal);
249
263
  }
250
264
  const raw = resolveBundledEnv(envKey, '');
251
- const n = raw ? parseInt(raw, 10) : NaN;
252
- if (Number.isFinite(n) && n > 0) {
253
- return n;
265
+ const parsed = raw ? parseInt(raw, 10) : NaN;
266
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
267
+ }
268
+ function normalizeStringList$1(value) {
269
+ if (Array.isArray(value)) {
270
+ return value.map(String).map((item) => item.trim()).filter(Boolean);
254
271
  }
255
- return fallback;
272
+ if (typeof value === 'string' && value.trim()) {
273
+ return value
274
+ .split(',')
275
+ .map((item) => item.trim())
276
+ .filter(Boolean);
277
+ }
278
+ return [];
279
+ }
280
+ function resolveAllowedScriptHosts(value) {
281
+ const raw = normalizeStringList$1(value);
282
+ return raw.length > 0 ? raw.map(normalizeHost).filter(Boolean) : [];
283
+ }
284
+ function resolvePathPrefixes(value) {
285
+ const raw = normalizeStringList$1(value);
286
+ return raw.length > 0 ? raw.map((item) => ensureLeadingPath(item)).filter(Boolean) : [];
287
+ }
288
+ function resolveBoolean(value) {
289
+ if (value === true || value === false) {
290
+ return value;
291
+ }
292
+ return undefined;
293
+ }
294
+ function resolveManifestInput(user) {
295
+ return asRecord$1(user.manifest) || {};
296
+ }
297
+ function resolveHostInput(user) {
298
+ return asRecord$1(user.host) || {};
299
+ }
300
+ function resolveDevInput(user) {
301
+ return asRecord$1(user.dev) || {};
302
+ }
303
+ function resolveHooksInput(user) {
304
+ return asRecord$1(user.hooks) || {};
305
+ }
306
+ function resolveDevPluginIds(dev) {
307
+ const explicit = normalizeStringList$1(dev.pluginIds);
308
+ if (explicit.length > 0) {
309
+ return explicit;
310
+ }
311
+ const fromEnv = normalizeStringList$1(resolveBundledEnv(EK.webPluginDevIds, ''));
312
+ if (fromEnv.length > 0) {
313
+ return fromEnv;
314
+ }
315
+ const implicit = normalizeStringList$1(resolveBundledEnv(EK.implicitDevIds, ''));
316
+ return implicit.length > 0 ? implicit : [...DEF.defaultImplicitDevPluginIds];
317
+ }
318
+ function resolveDevManifestFallback(dev, manifestMode, isDev) {
319
+ if (manifestMode === 'static') {
320
+ return false;
321
+ }
322
+ const direct = resolveBoolean(dev.manifestFallback && dev.manifestFallback.enabled);
323
+ if (direct !== undefined) {
324
+ return direct;
325
+ }
326
+ const envFlag = resolveBundledEnv(EK.devManifestFallback, '');
327
+ if (envFlag === '0' || envFlag === 'false') {
328
+ return false;
329
+ }
330
+ if (envFlag === '1' || envFlag === 'true') {
331
+ return true;
332
+ }
333
+ return false;
256
334
  }
257
- /** 合并用户、环境变量与 `defaultWebExtendPluginRuntime`,得到完整运行时选项(宿主可只传需要覆盖的字段)。 */
258
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
259
335
  function resolveRuntimeOptions$1(user = {}) {
260
- const manifestBaseRaw = user.manifestBase !== undefined && user.manifestBase !== ''
261
- ? String(user.manifestBase)
336
+ const manifest = resolveManifestInput(user);
337
+ const host = resolveHostInput(user);
338
+ const hostRoute = asRecord$1(host.route) || {};
339
+ const dev = resolveDevInput(user);
340
+ const devFallback = asRecord$1(dev.manifestFallback) || {};
341
+ const hooks = resolveHooksInput(user);
342
+ const normalizedHostBridge = normalizeHostBridge(host.bridge);
343
+ const manifestBaseRaw = manifest.baseUrl !== undefined && String(manifest.baseUrl).trim() !== ''
344
+ ? String(manifest.baseUrl)
262
345
  : resolveBundledEnv(EK.manifestBase, DEF.manifestBase) || DEF.manifestBase;
263
- const manifestListPath = ensureLeadingPath(user.manifestListPath !== undefined && user.manifestListPath !== ''
264
- ? user.manifestListPath
346
+ const manifestListPath = ensureLeadingPath(manifest.listPath !== undefined && String(manifest.listPath).trim() !== ''
347
+ ? manifest.listPath
265
348
  : resolveBundledEnv(EK.manifestListPath, DEF.manifestListPath));
266
- const defaultImplicitDevPluginIds = Array.isArray(user.defaultImplicitDevPluginIds)
267
- ? user.defaultImplicitDevPluginIds.map(String).filter(Boolean)
268
- : (() => {
269
- const e = resolveBundledEnv(EK.implicitDevIds, '');
270
- if (e) {
271
- return e
272
- .split(',')
273
- .map((s) => s.trim())
274
- .filter(Boolean);
275
- }
276
- return [...DEF.defaultImplicitDevPluginIds];
277
- })();
278
- const allowedScriptHosts = Array.isArray(user.allowedScriptHosts) && user.allowedScriptHosts.length > 0
279
- ? user.allowedScriptHosts.map((h) => normalizeHost(String(h))).filter(Boolean)
280
- : (() => {
281
- const e = resolveBundledEnv(EK.allowedScriptHosts, '');
282
- if (e) {
283
- return e
284
- .split(',')
285
- .map((s) => normalizeHost(s.trim()))
286
- .filter(Boolean);
287
- }
288
- return [...DEF.allowedScriptHosts];
289
- })();
290
- const bridgeAllowedPathPrefixes = Array.isArray(user.bridgeAllowedPathPrefixes) && user.bridgeAllowedPathPrefixes.length > 0
291
- ? user.bridgeAllowedPathPrefixes.map((p) => ensureLeadingPath(p)).filter(Boolean)
292
- : (() => {
293
- const e = resolveBundledEnv(EK.bridgePrefixes, '');
294
- if (e) {
295
- return e
296
- .split(',')
297
- .map((s) => ensureLeadingPath(s.trim()))
298
- .filter(Boolean);
299
- }
300
- return [...DEF.bridgeAllowedPathPrefixes];
301
- })();
302
- const manifestMode = resolveManifestModeFromInputs(user.manifestMode);
303
- const staticManifestUrl = resolveStaticManifestUrlFromInputs(user.staticManifestUrl);
304
- const isDevResolved = user.isDev !== undefined ? user.isDev : resolveBundledIsDev();
305
- const devFallbackStaticManifestUrl = (() => {
306
- if (user.devFallbackStaticManifestUrl !== undefined && String(user.devFallbackStaticManifestUrl).trim() !== '') {
307
- return String(user.devFallbackStaticManifestUrl).trim();
349
+ const allowedScriptHosts = (() => {
350
+ const explicit = resolveAllowedScriptHosts(host.scriptHosts);
351
+ if (explicit.length > 0) {
352
+ return explicit;
308
353
  }
309
- const e = resolveBundledEnv(EK.devFallbackManifestUrl, '');
310
- if (e) {
311
- return e.trim();
354
+ const fromEnv = resolveAllowedScriptHosts(resolveBundledEnv(EK.allowedScriptHosts, ''));
355
+ return fromEnv.length > 0 ? fromEnv : [...DEF.allowedScriptHosts];
356
+ })();
357
+ const bridgeAllowedPathPrefixes = (() => {
358
+ const explicit = resolvePathPrefixes(host.requestPathPrefixes);
359
+ if (explicit.length > 0) {
360
+ return explicit;
361
+ }
362
+ const fromEnv = resolvePathPrefixes(resolveBundledEnv(EK.bridgePrefixes, ''));
363
+ return fromEnv.length > 0 ? fromEnv : [...DEF.bridgeAllowedPathPrefixes];
364
+ })();
365
+ const manifestMode = resolveManifestModeFromInputs(manifest.source);
366
+ const staticManifestUrl = resolveStaticManifestUrlFromInputs(manifest.staticUrl);
367
+ const isDev = resolveBoolean(dev.enabled) !== undefined ? Boolean(dev.enabled) : resolveBundledIsDev();
368
+ const devFallbackStaticManifestUrl = (() => {
369
+ if (devFallback.staticUrl !== undefined && String(devFallback.staticUrl).trim() !== '') {
370
+ return String(devFallback.staticUrl).trim();
312
371
  }
313
- return String(DEF.devFallbackStaticManifestUrl).trim();
372
+ const envValue = resolveBundledEnv(EK.devFallbackManifestUrl, '');
373
+ return envValue ? envValue.trim() : String(DEF.devFallbackStaticManifestUrl).trim();
314
374
  })();
315
- const hostLayoutComponent = user.hostLayoutComponent;
316
- const pluginRoutesParentName = user.pluginRoutesParentName !== undefined && String(user.pluginRoutesParentName).trim() !== ''
317
- ? String(user.pluginRoutesParentName).trim()
375
+ const pluginRoutesParentName = hostRoute.parentName !== undefined && String(hostRoute.parentName).trim() !== ''
376
+ ? String(hostRoute.parentName).trim()
318
377
  : '';
319
- const pluginMountRaw = user.pluginMountPath !== undefined && String(user.pluginMountPath).trim() !== ''
320
- ? String(user.pluginMountPath).trim()
378
+ const pluginMountRaw = hostRoute.mountPath !== undefined && String(hostRoute.mountPath).trim() !== ''
379
+ ? String(hostRoute.mountPath).trim()
321
380
  : String(resolveBundledEnv(EK.mountPath, '') || DEF.pluginMountPath).trim();
322
381
  const pluginMountPath = ensureLeadingPath(pluginMountRaw || DEF.pluginMountPath);
323
- const pluginHostRouteMeta = user.pluginHostRouteMeta !== undefined && user.pluginHostRouteMeta !== null
324
- ? user.pluginHostRouteMeta
325
- : undefined;
326
- const ensurePluginHostRoute = user.ensurePluginHostRoute === true;
327
- const devManifestFallback = (() => {
328
- if (manifestMode === 'static') {
329
- return false;
382
+ const pluginHostRouteMeta = asRecord$1(hostRoute.meta);
383
+ const ensurePluginHostRoute = resolveBoolean(hostRoute.enabled) === true;
384
+ const webPluginDevMapJson = (() => {
385
+ if (dev.pluginMap && typeof dev.pluginMap === 'object' && !Array.isArray(dev.pluginMap)) {
386
+ return JSON.stringify(dev.pluginMap);
330
387
  }
331
- if (user.devManifestFallback === false) {
332
- return false;
333
- }
334
- if (user.devManifestFallback === true) {
335
- return true;
336
- }
337
- const envFlag = resolveBundledEnv(EK.devManifestFallback, '');
338
- if (envFlag === '0' || envFlag === 'false') {
339
- return false;
340
- }
341
- if (envFlag === '1' || envFlag === 'true') {
342
- return true;
343
- }
344
- return !!isDevResolved;
388
+ return dev.pluginMap !== undefined ? String(dev.pluginMap || '') : resolveBundledEnv(EK.webPluginDevMap, '');
345
389
  })();
346
390
  return {
347
391
  manifestBase: manifestBaseRaw.replace(/\/$/, '') || DEF.manifestBase.replace(/\/$/, ''),
348
392
  manifestListPath,
349
393
  manifestMode,
350
394
  staticManifestUrl,
351
- devManifestFallback,
395
+ devManifestFallback: resolveDevManifestFallback(dev, manifestMode),
352
396
  devFallbackStaticManifestUrl,
353
- manifestFetchCredentials: resolveManifestCredentials(user.manifestFetchCredentials, EK.manifestCredentials, DEF.manifestFetchCredentials),
354
- isDev: isDevResolved,
355
- webPluginDevOrigin: user.webPluginDevOrigin !== undefined
356
- ? user.webPluginDevOrigin
357
- : resolveBundledEnv(EK.webPluginDevOrigin, ''),
358
- webPluginDevIds: user.webPluginDevIds !== undefined ? user.webPluginDevIds : resolveBundledEnv(EK.webPluginDevIds, ''),
359
- webPluginDevMapJson: user.webPluginDevMapJson !== undefined
360
- ? user.webPluginDevMapJson
361
- : resolveBundledEnv(EK.webPluginDevMap, ''),
362
- webPluginDevEntryPath: ensureLeadingPath(user.webPluginDevEntryPath !== undefined && user.webPluginDevEntryPath !== ''
363
- ? user.webPluginDevEntryPath
397
+ manifestFetchCredentials: resolveManifestCredentials(manifest.credentials, EK.manifestCredentials, DEF.manifestFetchCredentials),
398
+ isDev,
399
+ webPluginDevOrigin: dev.origin !== undefined ? String(dev.origin || '').trim() : resolveBundledEnv(EK.webPluginDevOrigin, ''),
400
+ webPluginDevIds: resolveDevPluginIds(dev),
401
+ webPluginDevMapJson,
402
+ webPluginDevEntryPath: ensureLeadingPath(dev.entryPath !== undefined && String(dev.entryPath).trim() !== ''
403
+ ? String(dev.entryPath)
364
404
  : resolveBundledEnv(EK.devEntry, DEF.webPluginDevEntryPath)),
365
- devPingPath: ensureLeadingPath(user.devPingPath !== undefined && user.devPingPath !== ''
366
- ? user.devPingPath
405
+ devPingPath: ensureLeadingPath(dev.pingPath !== undefined && String(dev.pingPath).trim() !== ''
406
+ ? String(dev.pingPath)
367
407
  : resolveBundledEnv(EK.devPing, DEF.devPingPath)),
368
- devReloadSsePath: ensureLeadingPath(user.devReloadSsePath !== undefined && user.devReloadSsePath !== ''
369
- ? user.devReloadSsePath
408
+ devReloadSsePath: ensureLeadingPath(dev.reloadSsePath !== undefined && String(dev.reloadSsePath).trim() !== ''
409
+ ? String(dev.reloadSsePath)
370
410
  : resolveBundledEnv(EK.devSse, DEF.devReloadSsePath)),
371
- devPingTimeoutMs: resolvePositiveInt(user.devPingTimeoutMs, EK.devPingTimeout, DEF.devPingTimeoutMs),
372
- defaultImplicitDevPluginIds,
411
+ devPingTimeoutMs: resolvePositiveInt(dev.pingTimeoutMs, EK.devPingTimeout, DEF.devPingTimeoutMs),
412
+ defaultImplicitDevPluginIds: [...DEF.defaultImplicitDevPluginIds],
373
413
  allowedScriptHosts,
374
414
  bridgeAllowedPathPrefixes,
375
- bootstrapSummary: user.bootstrapSummary,
376
- hostLayoutComponent,
415
+ bootstrapSummary: resolveBoolean(dev.bootstrapSummary),
416
+ hostLayoutComponent: hostRoute.layout,
377
417
  pluginMountPath,
378
418
  pluginHostRouteMeta,
379
419
  ensurePluginHostRoute,
380
420
  pluginRoutesParentName,
381
- ...(typeof user.fetchManifest === 'function' ? { fetchManifest: user.fetchManifest } : {}),
382
- ...(typeof user.transformRoutes === 'function' ? { transformRoutes: user.transformRoutes } : {}),
383
- ...(typeof user.interceptRegisterRoutes === 'function'
384
- ? { interceptRegisterRoutes: user.interceptRegisterRoutes }
385
- : {}),
386
- ...(typeof user.adaptRouteDeclarations === 'function'
387
- ? { adaptRouteDeclarations: user.adaptRouteDeclarations }
421
+ ...(typeof manifest.fetch === 'function' ? { fetchManifest: manifest.fetch } : {}),
422
+ ...(typeof hooks.transformRoutes === 'function' ? { transformRoutes: hooks.transformRoutes } : {}),
423
+ ...(typeof hooks.interceptRegisterRoutes === 'function'
424
+ ? { interceptRegisterRoutes: hooks.interceptRegisterRoutes }
388
425
  : {}),
389
- ...(typeof user.onPluginRoutesContributed === 'function'
390
- ? { onPluginRoutesContributed: user.onPluginRoutesContributed }
426
+ ...(typeof hooks.adaptRouteDeclarations === 'function'
427
+ ? { adaptRouteDeclarations: hooks.adaptRouteDeclarations }
391
428
  : {}),
392
- ...(user.hostContext !== undefined &&
393
- user.hostContext !== null &&
394
- typeof user.hostContext === 'object' &&
395
- !Array.isArray(user.hostContext)
396
- ? { hostContext: user.hostContext }
429
+ ...(typeof hooks.onRoutesContributed === 'function'
430
+ ? { onPluginRoutesContributed: hooks.onRoutesContributed }
397
431
  : {}),
398
- ...(user.hostCapabilities !== undefined &&
399
- user.hostCapabilities !== null &&
400
- typeof user.hostCapabilities === 'object' &&
401
- !Array.isArray(user.hostCapabilities)
402
- ? { hostCapabilities: user.hostCapabilities }
432
+ ...(asRecord$1(host.context) ? { hostContext: asRecord$1(host.context) } : {}),
433
+ ...(asRecord$1(host.capabilities) ? { hostCapabilities: asRecord$1(host.capabilities) } : {}),
434
+ ...(normalizedHostBridge ? { hostBridge: normalizedHostBridge } : {}),
435
+ ...(typeof hooks.beforeActivate === 'function'
436
+ ? { onBeforePluginActivate: hooks.beforeActivate }
403
437
  : {}),
404
- ...(typeof user.onBeforePluginActivate === 'function'
405
- ? { onBeforePluginActivate: user.onBeforePluginActivate }
438
+ ...(typeof hooks.afterActivate === 'function'
439
+ ? { onAfterPluginActivate: hooks.afterActivate }
406
440
  : {}),
407
- ...(typeof user.onAfterPluginActivate === 'function'
408
- ? { onAfterPluginActivate: user.onAfterPluginActivate }
409
- : {}),
410
- ...(typeof user.onPluginActivateError === 'function'
411
- ? { onPluginActivateError: user.onPluginActivateError }
441
+ ...(typeof hooks.onActivateError === 'function'
442
+ ? { onPluginActivateError: hooks.onActivateError }
412
443
  : {})
413
444
  };
414
445
  }
@@ -3418,18 +3449,31 @@ function disposeWebPlugin(pluginId) {
3418
3449
  }
3419
3450
 
3420
3451
  /**
3421
- * 开发模式插件 URL 映射(显式 JSON + 隐式 dev 探测)。
3452
+ * 开发模式插件 URL 映射。
3422
3453
  */
3454
+ function normalizeStringValue(value) {
3455
+ return value == null ? '' : String(value).trim();
3456
+ }
3457
+ function normalizeStringList(value, fallback = []) {
3458
+ const raw = normalizeStringValue(value);
3459
+ if (!raw) {
3460
+ return [...fallback];
3461
+ }
3462
+ return raw
3463
+ .split(',')
3464
+ .map((item) => item.trim())
3465
+ .filter(Boolean);
3466
+ }
3423
3467
  function parseWebPluginDevMapExplicit(opts) {
3424
3468
  if (!opts.isDev) {
3425
3469
  return null;
3426
3470
  }
3427
- const raw = opts.webPluginDevMapJson;
3428
- if (raw === undefined || raw === null || String(raw).trim() === '') {
3471
+ const raw = normalizeStringValue(opts.webPluginDevMapJson);
3472
+ if (!raw) {
3429
3473
  return null;
3430
3474
  }
3431
3475
  try {
3432
- const map = JSON.parse(String(raw));
3476
+ const map = JSON.parse(raw);
3433
3477
  return map && typeof map === 'object' ? map : null;
3434
3478
  }
3435
3479
  catch (_a) {
@@ -3446,22 +3490,11 @@ async function buildImplicitWebPluginDevMap(opts, hostSet) {
3446
3490
  if (!opts.isDev) {
3447
3491
  return {};
3448
3492
  }
3449
- const origin = opts.webPluginDevOrigin === undefined || opts.webPluginDevOrigin === null
3450
- ? ''
3451
- : String(opts.webPluginDevOrigin).trim();
3452
- if (!origin) {
3493
+ const origin = normalizeStringValue(opts.webPluginDevOrigin);
3494
+ if (!origin || !isScriptHostAllowed(`${origin}/`, hostSet)) {
3453
3495
  return {};
3454
3496
  }
3455
- if (!isScriptHostAllowed(`${origin}/`, hostSet)) {
3456
- return {};
3457
- }
3458
- const idsRaw = opts.webPluginDevIds;
3459
- const ids = idsRaw !== undefined && idsRaw !== null && String(idsRaw).trim() !== ''
3460
- ? String(idsRaw)
3461
- .split(',')
3462
- .map((s) => s.trim())
3463
- .filter(Boolean)
3464
- : [...opts.defaultImplicitDevPluginIds];
3497
+ const ids = normalizeStringList(opts.webPluginDevIds, opts.defaultImplicitDevPluginIds);
3465
3498
  if (ids.length === 0) {
3466
3499
  return {};
3467
3500
  }
@@ -3470,31 +3503,28 @@ async function buildImplicitWebPluginDevMap(opts, hostSet) {
3470
3503
  try {
3471
3504
  const ctrl = new AbortController();
3472
3505
  const timer = setTimeout(() => ctrl.abort(), opts.devPingTimeoutMs);
3473
- const r = await fetch(pingUrl, {
3506
+ const response = await fetch(pingUrl, {
3474
3507
  mode: 'cors',
3475
3508
  cache: 'no-store',
3476
3509
  signal: ctrl.signal
3477
3510
  });
3478
3511
  clearTimeout(timer);
3479
- if (!r.ok) {
3512
+ if (!response.ok) {
3480
3513
  return {};
3481
3514
  }
3482
- const body = (await r.text()).trim();
3483
- if (body !== 'ok') {
3515
+ if ((await response.text()).trim() !== 'ok') {
3484
3516
  return {};
3485
3517
  }
3486
3518
  }
3487
3519
  catch (_a) {
3488
3520
  return {};
3489
3521
  }
3490
- const pathPart = opts.webPluginDevEntryPath;
3522
+ const entryUrl = `${base}${opts.webPluginDevEntryPath}`;
3491
3523
  const map = {};
3492
3524
  for (const id of ids) {
3493
- map[id] = `${base}${pathPart}`;
3494
- }
3495
- if (ids.length) {
3496
- console.info('[wep] plugin dev server', base, '→ implicit entries', pathPart, ids.join(', '));
3525
+ map[id] = entryUrl;
3497
3526
  }
3527
+ console.info('[wep] plugin dev server', base, '-> implicit entries', opts.webPluginDevEntryPath, ids.join(', '));
3498
3528
  return map;
3499
3529
  }
3500
3530
 
@@ -3628,15 +3658,14 @@ async function fetchStaticManifestViaHttp(ctx) {
3628
3658
  }
3629
3659
 
3630
3660
  /**
3631
- * 当 `ensurePluginHostRoute === true` 且提供 `pluginRoutesParentName` + `hostLayoutComponent` 时,
3632
- * 注册 `pluginMountPath` + Layout 的命名父路由,供 `router.addRoute(parentName, child)` 挂载插件页。
3661
+ * 在需要时补注册插件宿主父路由。
3633
3662
  */
3634
3663
  function routeNameExists(router, name) {
3635
3664
  if (!name) {
3636
3665
  return false;
3637
3666
  }
3638
3667
  if (typeof router.getRoutes === 'function') {
3639
- return router.getRoutes().some((r) => r.name === name);
3668
+ return router.getRoutes().some((route) => route.name === name);
3640
3669
  }
3641
3670
  return walkRouteNames(router.options && router.options.routes, name);
3642
3671
  }
@@ -3644,50 +3673,49 @@ function walkRouteNames(routes, name) {
3644
3673
  if (!Array.isArray(routes)) {
3645
3674
  return false;
3646
3675
  }
3647
- for (const r of routes) {
3648
- if (r && typeof r === 'object' && r.name === name) {
3676
+ for (const route of routes) {
3677
+ if (route && typeof route === 'object' && route.name === name) {
3649
3678
  return true;
3650
3679
  }
3651
- const ch = r && typeof r === 'object' ? r.children : null;
3652
- if (walkRouteNames(ch, name)) {
3680
+ const children = route && typeof route === 'object' ? route.children : undefined;
3681
+ if (walkRouteNames(children, name)) {
3653
3682
  return true;
3654
3683
  }
3655
3684
  }
3656
3685
  return false;
3657
3686
  }
3658
- function ensurePluginHostRoute$1(router, opts) {
3659
- if (opts.ensurePluginHostRoute !== true) {
3660
- return;
3661
- }
3662
- if (!router || typeof router.addRoute !== 'function') {
3687
+ function normalizeMountPath(value) {
3688
+ const mountDefault = defaultWebExtendPluginRuntime.pluginMountPath;
3689
+ const raw = String(value || mountDefault).trim().replace(/\/$/, '') || mountDefault;
3690
+ return raw.startsWith('/') ? raw : `/${raw}`;
3691
+ }
3692
+ function resolveRouteMeta(value) {
3693
+ return value && typeof value === 'object' && !Array.isArray(value)
3694
+ ? { ...value }
3695
+ : { requiresConfig: true, hidden: true };
3696
+ }
3697
+ function ensurePluginHostRoute$1(router, options) {
3698
+ const opts = options && typeof options === 'object' && ('manifestBase' in options || 'ensurePluginHostRoute' in options)
3699
+ ? options
3700
+ : resolveRuntimeOptions$1(options);
3701
+ if (opts.ensurePluginHostRoute !== true || !router || typeof router.addRoute !== 'function') {
3663
3702
  return;
3664
3703
  }
3665
3704
  const parentName = String(opts.pluginRoutesParentName || '').trim();
3666
- if (!parentName) {
3667
- return;
3668
- }
3669
- if (routeNameExists(router, parentName)) {
3705
+ if (!parentName || routeNameExists(router, parentName)) {
3670
3706
  return;
3671
3707
  }
3672
3708
  const Layout = opts.hostLayoutComponent;
3673
3709
  if (!Layout) {
3674
- console.warn('[wep] 缺少 hostLayoutComponent,未自动注册插件壳路由;请传入宿主 Layout,或在路由表中自行配置与 pluginRoutesParentName 一致的父路由');
3710
+ console.warn('[wep] missing hostLayoutComponent; plugin host route was not auto-registered');
3675
3711
  return;
3676
3712
  }
3677
- const mountDefault = defaultWebExtendPluginRuntime.pluginMountPath;
3678
- let pathRaw = String(opts.pluginMountPath || mountDefault).trim().replace(/\/$/, '') || mountDefault;
3679
- if (!pathRaw.startsWith('/')) {
3680
- pathRaw = `/${pathRaw}`;
3681
- }
3682
- const meta = opts.pluginHostRouteMeta && typeof opts.pluginHostRouteMeta === 'object'
3683
- ? { ...opts.pluginHostRouteMeta }
3684
- : { requiresConfig: true, hidden: true };
3685
3713
  router.addRoute({
3686
- path: pathRaw,
3714
+ path: normalizeMountPath(opts.pluginMountPath),
3687
3715
  name: parentName,
3688
3716
  component: Layout,
3689
3717
  redirect: 'noredirect',
3690
- meta,
3718
+ meta: resolveRouteMeta(opts.pluginHostRouteMeta),
3691
3719
  children: []
3692
3720
  });
3693
3721
  }
@@ -4069,6 +4097,73 @@ function sortByPriority(plugins) {
4069
4097
  })
4070
4098
  .map((decorated) => decorated.entry);
4071
4099
  }
4100
+ function logBootstrapSummary(enabled, payload) {
4101
+ if (enabled) {
4102
+ console.info('[wep] bootstrap_summary', payload);
4103
+ }
4104
+ }
4105
+ function getManifestBody(result) {
4106
+ return result.ok && result.data && typeof result.data === 'object' ? result.data : null;
4107
+ }
4108
+ function getManifestPluginCount(result) {
4109
+ const body = getManifestBody(result);
4110
+ return body && Array.isArray(body.plugins) ? body.plugins.length : 0;
4111
+ }
4112
+ async function fetchManifestSafely(fetchManifest, manifestCtx) {
4113
+ try {
4114
+ if (typeof fetchManifest === 'function') {
4115
+ return await fetchManifest(manifestCtx);
4116
+ }
4117
+ return await defaultFetchWebPluginManifest$1(manifestCtx);
4118
+ }
4119
+ catch (error) {
4120
+ return { ok: false, error, data: null };
4121
+ }
4122
+ }
4123
+ function buildHostKit(opts) {
4124
+ const frozenHostContext = freezeShallowHostContext(opts.hostContext !== undefined ? opts.hostContext : undefined, opts.hostCapabilities && typeof opts.hostCapabilities === 'object' ? opts.hostCapabilities : undefined);
4125
+ return {
4126
+ hostContext: frozenHostContext,
4127
+ bridgeAllowedPathPrefixes: opts.bridgeAllowedPathPrefixes,
4128
+ ...(opts.pluginRoutesParentName ? { pluginRoutesParentName: opts.pluginRoutesParentName } : {}),
4129
+ ...(typeof opts.transformRoutes === 'function' ? { transformRoutes: opts.transformRoutes } : {}),
4130
+ ...(typeof opts.interceptRegisterRoutes === 'function'
4131
+ ? { interceptRegisterRoutes: opts.interceptRegisterRoutes }
4132
+ : {}),
4133
+ ...(typeof opts.adaptRouteDeclarations === 'function'
4134
+ ? { adaptRouteDeclarations: opts.adaptRouteDeclarations }
4135
+ : {}),
4136
+ ...(typeof opts.onPluginRoutesContributed === 'function'
4137
+ ? { onPluginRoutesContributed: opts.onPluginRoutesContributed }
4138
+ : {})
4139
+ };
4140
+ }
4141
+ function resolveManifestRequest(opts) {
4142
+ const isStatic = opts.manifestMode === 'static';
4143
+ if (isStatic) {
4144
+ const raw = String(opts.staticManifestUrl || '').trim();
4145
+ if (!raw) {
4146
+ return null;
4147
+ }
4148
+ return {
4149
+ isStatic,
4150
+ manifestUrl: resolveStaticManifestUrlForFetch(raw, window.location.origin)
4151
+ };
4152
+ }
4153
+ const base = String(opts.manifestBase).replace(/\/$/, '');
4154
+ return {
4155
+ isStatic,
4156
+ manifestUrl: `${base}${opts.manifestListPath}`
4157
+ };
4158
+ }
4159
+ function isResolvedRuntimeOptions(input) {
4160
+ return !!(input &&
4161
+ typeof input === 'object' &&
4162
+ !Array.isArray(input) &&
4163
+ ('manifestBase' in input ||
4164
+ 'manifestListPath' in input ||
4165
+ 'fetchManifest' in input));
4166
+ }
4072
4167
  async function bootstrapPlugins$1(
4073
4168
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4074
4169
  router,
@@ -4080,26 +4175,17 @@ createHostApiFactory, runtimeOptions) {
4080
4175
  }
4081
4176
  printRuntimeBannerOnce();
4082
4177
  clearActivatedPluginIds();
4083
- const opts = resolveRuntimeOptions$1(runtimeOptions || {});
4178
+ const opts = isResolvedRuntimeOptions(runtimeOptions) ? runtimeOptions : resolveRuntimeOptions$1(runtimeOptions);
4179
+ const showBootstrapSummary = shouldShowBootstrapSummary(opts);
4084
4180
  setPluginBootstrapRouter(router);
4085
4181
  ensurePluginHostRoute$1(router, opts);
4086
- const base = String(opts.manifestBase).replace(/\/$/, '');
4087
- const isStatic = opts.manifestMode === 'static';
4088
- let manifestUrl;
4089
- if (isStatic) {
4090
- const raw = String(opts.staticManifestUrl || '').trim();
4091
- if (!raw) {
4092
- console.warn('[wep] manifestMode=static requires non-empty staticManifestUrl (or env VITE_WEB_PLUGIN_STATIC_MANIFEST_URL)');
4093
- if (shouldShowBootstrapSummary(opts)) {
4094
- console.info('[wep] bootstrap_summary', { ok: false, reason: 'static_manifest_url_missing' });
4095
- }
4096
- return;
4097
- }
4098
- manifestUrl = resolveStaticManifestUrlForFetch(raw, window.location.origin);
4099
- }
4100
- else {
4101
- manifestUrl = `${base}${opts.manifestListPath}`;
4182
+ const manifestRequest = resolveManifestRequest(opts);
4183
+ if (!manifestRequest) {
4184
+ console.warn('[wep] manifestMode=static requires non-empty staticManifestUrl (or env VITE_WEB_PLUGIN_STATIC_MANIFEST_URL)');
4185
+ logBootstrapSummary(showBootstrapSummary, { ok: false, reason: 'static_manifest_url_missing' });
4186
+ return;
4102
4187
  }
4188
+ const { isStatic, manifestUrl } = manifestRequest;
4103
4189
  const hostSet = buildAllowedScriptHostsSet(opts.allowedScriptHosts);
4104
4190
  const explicit = parseWebPluginDevMapExplicit(opts);
4105
4191
  const manifestCtx = {
@@ -4107,27 +4193,15 @@ createHostApiFactory, runtimeOptions) {
4107
4193
  credentials: opts.manifestFetchCredentials
4108
4194
  };
4109
4195
  const [primaryResult, implicit] = await Promise.all([
4110
- (async () => {
4111
- try {
4112
- if (typeof opts.fetchManifest === 'function') {
4113
- return await opts.fetchManifest(manifestCtx);
4114
- }
4115
- return await defaultFetchWebPluginManifest$1(manifestCtx);
4116
- }
4117
- catch (e) {
4118
- return { ok: false, error: e, data: null };
4119
- }
4120
- })(),
4196
+ fetchManifestSafely(typeof opts.fetchManifest === 'function'
4197
+ ? opts.fetchManifest
4198
+ : undefined, manifestCtx),
4121
4199
  buildImplicitWebPluginDevMap(opts, hostSet)
4122
4200
  ]);
4123
4201
  let manifestResult = primaryResult;
4124
4202
  let manifestUrlUsed = manifestUrl;
4125
4203
  if (!isStatic && opts.devManifestFallback && opts.isDev) {
4126
- const dataObj = primaryResult.ok && primaryResult.data && typeof primaryResult.data === 'object'
4127
- ? primaryResult.data
4128
- : null;
4129
- const plen = dataObj && Array.isArray(dataObj.plugins) ? dataObj.plugins.length : 0;
4130
- const needFallback = !primaryResult.ok || plen === 0;
4204
+ const needFallback = !primaryResult.ok || getManifestPluginCount(primaryResult) === 0;
4131
4205
  const fallbackRaw = String(opts.devFallbackStaticManifestUrl || '').trim();
4132
4206
  if (needFallback && fallbackRaw) {
4133
4207
  const fallbackUrl = resolveStaticManifestUrlForFetch(fallbackRaw, window.location.origin);
@@ -4136,8 +4210,7 @@ createHostApiFactory, runtimeOptions) {
4136
4210
  credentials: opts.manifestFetchCredentials
4137
4211
  };
4138
4212
  const fr = await fetchStaticManifestViaHttp(fallbackCtx);
4139
- const fdata = fr.ok && fr.data && typeof fr.data === 'object' ? fr.data : null;
4140
- const flen = fdata && Array.isArray(fdata.plugins) ? fdata.plugins.length : 0;
4213
+ const flen = getManifestPluginCount(fr);
4141
4214
  if (fr.ok && flen > 0) {
4142
4215
  manifestResult = fr;
4143
4216
  manifestUrlUsed = fallbackUrl;
@@ -4147,22 +4220,7 @@ createHostApiFactory, runtimeOptions) {
4147
4220
  }
4148
4221
  const devMap = mergeDevMaps(implicit, explicit);
4149
4222
  startPluginDevSseForMap(devMap, opts.isDev, hostSet, opts.devReloadSsePath);
4150
- const frozenHostContext = freezeShallowHostContext(opts.hostContext !== undefined ? opts.hostContext : undefined, opts.hostCapabilities && typeof opts.hostCapabilities === 'object' ? opts.hostCapabilities : undefined);
4151
- const hostKit = {
4152
- hostContext: frozenHostContext,
4153
- bridgeAllowedPathPrefixes: opts.bridgeAllowedPathPrefixes,
4154
- ...(opts.pluginRoutesParentName ? { pluginRoutesParentName: opts.pluginRoutesParentName } : {}),
4155
- ...(typeof opts.transformRoutes === 'function' ? { transformRoutes: opts.transformRoutes } : {}),
4156
- ...(typeof opts.interceptRegisterRoutes === 'function'
4157
- ? { interceptRegisterRoutes: opts.interceptRegisterRoutes }
4158
- : {}),
4159
- ...(typeof opts.adaptRouteDeclarations === 'function'
4160
- ? { adaptRouteDeclarations: opts.adaptRouteDeclarations }
4161
- : {}),
4162
- ...(typeof opts.onPluginRoutesContributed === 'function'
4163
- ? { onPluginRoutesContributed: opts.onPluginRoutesContributed }
4164
- : {})
4165
- };
4223
+ const hostKit = buildHostKit(opts);
4166
4224
  if (!manifestResult.ok) {
4167
4225
  if (manifestResult.error) {
4168
4226
  console.warn('[wep] fetch manifest failed', manifestResult.error);
@@ -4171,16 +4229,12 @@ createHostApiFactory, runtimeOptions) {
4171
4229
  const label = isStatic ? 'static manifest' : 'manifest HTTP';
4172
4230
  console.warn(`[wep] ${label}`, manifestResult.status, manifestUrlUsed);
4173
4231
  }
4174
- if (shouldShowBootstrapSummary(opts)) {
4175
- console.info('[wep] bootstrap_summary', { ok: false, reason: 'manifest_fetch' });
4176
- }
4232
+ logBootstrapSummary(showBootstrapSummary, { ok: false, reason: 'manifest_fetch' });
4177
4233
  return;
4178
4234
  }
4179
- const data = manifestResult.data;
4235
+ const data = getManifestBody(manifestResult);
4180
4236
  if (!data) {
4181
- if (shouldShowBootstrapSummary(opts)) {
4182
- console.info('[wep] bootstrap_summary', { ok: false, reason: 'manifest_empty_body' });
4183
- }
4237
+ logBootstrapSummary(showBootstrapSummary, { ok: false, reason: 'manifest_empty_body' });
4184
4238
  return;
4185
4239
  }
4186
4240
  const apiVer = data.hostPluginApiVersion;
@@ -4193,12 +4247,10 @@ createHostApiFactory, runtimeOptions) {
4193
4247
  host: HOST_PLUGIN_API_VERSION,
4194
4248
  manifest: apiVer
4195
4249
  });
4196
- if (shouldShowBootstrapSummary(opts)) {
4197
- console.info('[wep] bootstrap_summary', {
4198
- ok: false,
4199
- reason: 'manifest_host_api_version_mismatch'
4200
- });
4201
- }
4250
+ logBootstrapSummary(showBootstrapSummary, {
4251
+ ok: false,
4252
+ reason: 'manifest_host_api_version_mismatch'
4253
+ });
4202
4254
  return;
4203
4255
  }
4204
4256
  }
@@ -4298,9 +4350,7 @@ createHostApiFactory, runtimeOptions) {
4298
4350
  }
4299
4351
  }
4300
4352
  }
4301
- if (shouldShowBootstrapSummary(opts)) {
4302
- console.info('[wep] bootstrap_summary', { ok: true, ...summary });
4303
- }
4353
+ logBootstrapSummary(showBootstrapSummary, { ok: true, ...summary });
4304
4354
  }
4305
4355
 
4306
4356
  /**
@@ -4578,10 +4628,39 @@ function clearContributedRoutesForPlugin(pluginId) {
4578
4628
  }
4579
4629
 
4580
4630
  /**
4581
- * 构造插件 `activator(hostApi)` 使用的宿主 API:路由、扩展点、资源与受控请求桥。
4631
+ * 构造插件 `activator(hostApi)` 使用的宿主 API
4582
4632
  */
4583
4633
  let slotItemKeySeq = 0;
4584
4634
  let routeSynthSeq = 0;
4635
+ function getBridgePrefixes(hostKitOptions) {
4636
+ return Array.isArray(hostKitOptions.bridgeAllowedPathPrefixes) &&
4637
+ hostKitOptions.bridgeAllowedPathPrefixes.length > 0
4638
+ ? hostKitOptions.bridgeAllowedPathPrefixes
4639
+ : defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes;
4640
+ }
4641
+ function resolveHostRuntime(hostKitOptions) {
4642
+ const hostContext = hostKitOptions.hostContext != null && typeof hostKitOptions.hostContext === 'object'
4643
+ ? hostKitOptions.hostContext
4644
+ : Object.freeze({});
4645
+ const hostVue = hostContext.Vue;
4646
+ return {
4647
+ hostContext,
4648
+ VueRuntime: hostVue || Vue
4649
+ };
4650
+ }
4651
+ function normalizeParentRouteName(hostKitOptions) {
4652
+ return typeof hostKitOptions.pluginRoutesParentName === 'string'
4653
+ ? hostKitOptions.pluginRoutesParentName.trim()
4654
+ : '';
4655
+ }
4656
+ function normalizeUrls(urls) {
4657
+ return Array.isArray(urls)
4658
+ ? urls
4659
+ .filter((url) => typeof url === 'string')
4660
+ .map((url) => url.trim())
4661
+ .filter(Boolean)
4662
+ : [];
4663
+ }
4585
4664
  function decorateRouteTreeWithPluginMeta(pluginId, route) {
4586
4665
  const meta = route.meta && typeof route.meta === 'object' && !Array.isArray(route.meta)
4587
4666
  ? route.meta
@@ -4607,97 +4686,81 @@ function decorateRouteTreeWithPluginMeta(pluginId, route) {
4607
4686
  function analyzeRouteInputTree(nodes) {
4608
4687
  let hasDecl = false;
4609
4688
  let hasCfg = false;
4610
- function walk(r) {
4611
- if (!r || typeof r !== 'object') {
4689
+ function walk(node) {
4690
+ if (!node || typeof node !== 'object') {
4612
4691
  return;
4613
4692
  }
4614
- const o = r;
4615
- const cfg = o.component != null || o.components != null;
4616
- const decl = typeof o.componentRef === 'string';
4617
- if (cfg) {
4693
+ const record = node;
4694
+ const hasRouteConfig = record.component != null || record.components != null;
4695
+ const hasRouteDecl = typeof record.componentRef === 'string';
4696
+ if (hasRouteConfig) {
4618
4697
  hasCfg = true;
4619
4698
  }
4620
- else if (decl) {
4699
+ else if (hasRouteDecl) {
4621
4700
  hasDecl = true;
4622
4701
  }
4623
- const ch = o.children;
4624
- if (Array.isArray(ch)) {
4625
- for (const c of ch) {
4626
- walk(c);
4702
+ if (Array.isArray(record.children)) {
4703
+ for (const child of record.children) {
4704
+ walk(child);
4627
4705
  }
4628
4706
  }
4629
4707
  }
4630
- for (const n of nodes) {
4631
- walk(n);
4708
+ for (const node of nodes) {
4709
+ walk(node);
4632
4710
  }
4633
4711
  return { hasDecl, hasCfg };
4634
4712
  }
4635
- /**
4636
- * 单插件在宿主侧的 API 句柄。工厂请传 `(id, router, kit) => createHostApi(id, r, kit)` 以便 bridge 白名单等到位。
4637
- */
4713
+ function rollbackRegisteredTopRoutes(
4638
4714
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4639
- function createHostApi(pluginId, router, hostKitOptions = {}) {
4640
- const bridgePrefixes = Array.isArray(hostKitOptions.bridgeAllowedPathPrefixes) &&
4641
- hostKitOptions.bridgeAllowedPathPrefixes.length > 0
4642
- ? hostKitOptions.bridgeAllowedPathPrefixes
4643
- : defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes;
4644
- const bridge = createRequestBridge({ allowedPathPrefixes: bridgePrefixes });
4645
- const parentName = typeof hostKitOptions.pluginRoutesParentName === 'string'
4646
- ? hostKitOptions.pluginRoutesParentName.trim()
4647
- : '';
4648
- function rollbackRegisteredTopRoutes(routes) {
4649
- for (let i = routes.length - 1; i >= 0; i--) {
4650
- const route = routes[i];
4651
- if (typeof route.dispose === 'function') {
4652
- try {
4653
- route.dispose();
4654
- continue;
4655
- }
4656
- catch (e) {
4657
- console.warn('[wep] rollback route disposer failed', route.name, e);
4658
- }
4715
+ router, routes) {
4716
+ for (let i = routes.length - 1; i >= 0; i--) {
4717
+ const route = routes[i];
4718
+ if (typeof route.dispose === 'function') {
4719
+ try {
4720
+ route.dispose();
4721
+ continue;
4659
4722
  }
4660
- if (typeof router.removeRoute === 'function') {
4661
- try {
4662
- router.removeRoute(route.name);
4663
- }
4664
- catch (e) {
4665
- console.warn('[wep] rollback removeRoute failed', route.name, e);
4666
- }
4723
+ catch (e) {
4724
+ console.warn('[wep] rollback route disposer failed', route.name, e);
4725
+ }
4726
+ }
4727
+ if (typeof router.removeRoute === 'function') {
4728
+ try {
4729
+ router.removeRoute(route.name);
4730
+ }
4731
+ catch (e) {
4732
+ console.warn('[wep] rollback removeRoute failed', route.name, e);
4667
4733
  }
4668
4734
  }
4669
4735
  }
4670
- function applyInternalRegister(rawRouteConfigs) {
4671
- const wrapped = rawRouteConfigs.map((r) => ({
4672
- ...decorateRouteTreeWithPluginMeta(pluginId, r),
4673
- name: r.name || `${routeSynthNamePrefix}${pluginId}_${routeSynthSeq++}`
4674
- }));
4736
+ }
4737
+ function decorateTopRoutes(pluginId, rawRouteConfigs) {
4738
+ return rawRouteConfigs.map((route) => ({
4739
+ ...decorateRouteTreeWithPluginMeta(pluginId, route),
4740
+ name: route.name || `${routeSynthNamePrefix}${pluginId}_${routeSynthSeq++}`
4741
+ }));
4742
+ }
4743
+ function createRouteRegistrar({ pluginId, router, parentName, hostKitOptions }) {
4744
+ function addTopRoute(route) {
4745
+ const dispose = parentName ? router.addRoute(parentName, route) : router.addRoute(route);
4746
+ return {
4747
+ name: String(route.name),
4748
+ dispose: typeof dispose === 'function' ? dispose : undefined
4749
+ };
4750
+ }
4751
+ return function applyInternalRegister(rawRouteConfigs) {
4675
4752
  if (typeof router.addRoute !== 'function') {
4676
- throw new Error('[wep] vue-router 3.5+ 必需:请使用 router.addRoute(不再支持 addRoutes)');
4753
+ throw new Error('[wep] vue-router 3.5+ required: please use router.addRoute');
4677
4754
  }
4755
+ const wrapped = decorateTopRoutes(pluginId, rawRouteConfigs);
4678
4756
  const registeredTopRoutes = [];
4679
4757
  try {
4680
- if (parentName) {
4681
- for (const r of wrapped) {
4682
- const dispose = router.addRoute(parentName, r);
4683
- registeredTopRoutes.push({
4684
- name: String(r.name),
4685
- dispose: typeof dispose === 'function' ? dispose : undefined
4686
- });
4687
- }
4688
- }
4689
- else {
4690
- for (const r of wrapped) {
4691
- const dispose = router.addRoute(r);
4692
- registeredTopRoutes.push({
4693
- name: String(r.name),
4694
- dispose: typeof dispose === 'function' ? dispose : undefined
4695
- });
4696
- }
4758
+ for (const route of wrapped) {
4759
+ registeredTopRoutes.push(addTopRoute(route));
4697
4760
  }
4698
4761
  }
4699
4762
  catch (e) {
4700
- rollbackRegisteredTopRoutes(registeredTopRoutes);
4763
+ rollbackRegisteredTopRoutes(router, registeredTopRoutes);
4701
4764
  throw e;
4702
4765
  }
4703
4766
  recordPluginTopRoutes(pluginId, registeredTopRoutes);
@@ -4710,69 +4773,80 @@ function createHostApi(pluginId, router, hostKitOptions = {}) {
4710
4773
  contributedRoutes
4711
4774
  });
4712
4775
  }
4713
- }
4714
- function injectStylesheet(href) {
4715
- const link = document.createElement('link');
4716
- link.rel = 'stylesheet';
4717
- link.href = href;
4718
- link.setAttribute('data-plugin-asset', pluginId);
4719
- document.head.appendChild(link);
4720
- }
4721
- function injectScript(src) {
4722
- return new Promise((resolve, reject) => {
4723
- const s = document.createElement('script');
4724
- s.async = true;
4725
- s.src = src;
4726
- s.setAttribute('data-plugin-asset', pluginId);
4727
- s.onload = () => resolve();
4728
- s.onerror = () => reject(new Error('script failed: ' + src));
4729
- document.head.appendChild(s);
4776
+ };
4777
+ }
4778
+ function injectStylesheet(pluginId, href) {
4779
+ const link = document.createElement('link');
4780
+ link.rel = 'stylesheet';
4781
+ link.href = href;
4782
+ link.setAttribute('data-plugin-asset', pluginId);
4783
+ document.head.appendChild(link);
4784
+ }
4785
+ function injectScript(pluginId, src) {
4786
+ return new Promise((resolve, reject) => {
4787
+ const script = document.createElement('script');
4788
+ script.async = true;
4789
+ script.src = src;
4790
+ script.setAttribute('data-plugin-asset', pluginId);
4791
+ script.onload = () => resolve();
4792
+ script.onerror = () => reject(new Error('script failed: ' + src));
4793
+ document.head.appendChild(script);
4794
+ });
4795
+ }
4796
+ function resolveRouteConfigs(pluginId,
4797
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4798
+ router, hostKitOptions, routes) {
4799
+ const { hasDecl, hasCfg } = analyzeRouteInputTree(routes);
4800
+ if (hasDecl && hasCfg) {
4801
+ throw new Error('[wep] registerRoutes: cannot mix RouteDeclaration (componentRef) with RouteConfig (component)');
4802
+ }
4803
+ let configs;
4804
+ if (hasDecl) {
4805
+ const adapt = hostKitOptions.adaptRouteDeclarations;
4806
+ if (typeof adapt !== 'function') {
4807
+ throw new Error('[wep] registerRoutes: RouteDeclaration (componentRef) requires adaptRouteDeclarations on the host');
4808
+ }
4809
+ configs = adapt({
4810
+ pluginId,
4811
+ router,
4812
+ declarations: routes
4730
4813
  });
4731
4814
  }
4732
- const hostContext = hostKitOptions.hostContext != null && typeof hostKitOptions.hostContext === 'object'
4733
- ? hostKitOptions.hostContext
4734
- : Object.freeze({});
4735
- const hostVue = hostContext && hostContext.Vue;
4736
- const VueRuntime = hostVue || Vue;
4815
+ else {
4816
+ configs = routes;
4817
+ }
4818
+ return typeof hostKitOptions.transformRoutes === 'function'
4819
+ ? hostKitOptions.transformRoutes({
4820
+ pluginId,
4821
+ router,
4822
+ routes: configs
4823
+ })
4824
+ : configs;
4825
+ }
4826
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4827
+ function createHostApi(pluginId, router, hostKitOptions = {}) {
4828
+ const bridge = createRequestBridge({ allowedPathPrefixes: getBridgePrefixes(hostKitOptions) });
4829
+ const parentName = normalizeParentRouteName(hostKitOptions);
4830
+ const applyInternalRegister = createRouteRegistrar({
4831
+ pluginId,
4832
+ router,
4833
+ parentName,
4834
+ hostKitOptions
4835
+ });
4836
+ const { hostContext, VueRuntime } = resolveHostRuntime(hostKitOptions);
4737
4837
  ensureRegistriesReactive(VueRuntime);
4738
4838
  registerPluginTeardown(pluginId, () => {
4739
4839
  clearContributedRoutesForPlugin(pluginId);
4740
4840
  });
4741
4841
  return {
4742
4842
  hostPluginApiVersion: HOST_PLUGIN_API_VERSION,
4743
- /** 宿主注入的只读依赖(store、router、开放能力等),见 `resolveRuntimeOptions.hostContext` */
4744
4843
  hostContext,
4745
4844
  registerRoutes(routes) {
4746
4845
  const list = Array.isArray(routes) ? routes : [];
4747
4846
  if (list.length === 0) {
4748
4847
  return;
4749
4848
  }
4750
- const { hasDecl, hasCfg } = analyzeRouteInputTree(list);
4751
- if (hasDecl && hasCfg) {
4752
- throw new Error('[wep] registerRoutes: cannot mix RouteDeclaration (componentRef) with RouteConfig (component)');
4753
- }
4754
- let configs;
4755
- if (hasDecl) {
4756
- const adapt = hostKitOptions.adaptRouteDeclarations;
4757
- if (typeof adapt !== 'function') {
4758
- throw new Error('[wep] registerRoutes: RouteDeclaration (componentRef) requires adaptRouteDeclarations on the host');
4759
- }
4760
- configs = adapt({
4761
- pluginId,
4762
- router,
4763
- declarations: list
4764
- });
4765
- }
4766
- else {
4767
- configs = list;
4768
- }
4769
- if (typeof hostKitOptions.transformRoutes === 'function') {
4770
- configs = hostKitOptions.transformRoutes({
4771
- pluginId,
4772
- router,
4773
- routes: configs
4774
- });
4775
- }
4849
+ const configs = resolveRouteConfigs(pluginId, router, hostKitOptions, list);
4776
4850
  if (typeof hostKitOptions.interceptRegisterRoutes === 'function') {
4777
4851
  hostKitOptions.interceptRegisterRoutes({
4778
4852
  pluginId,
@@ -4793,11 +4867,11 @@ function createHostApi(pluginId, router, hostKitOptions = {}) {
4793
4867
  VueRuntime.set(registries.slots, pointId, []);
4794
4868
  }
4795
4869
  const list = registries.slots[pointId];
4796
- for (const c of components) {
4870
+ for (const componentEntry of components) {
4797
4871
  list.push({
4798
4872
  pluginId,
4799
- component: c.component,
4800
- priority: c.priority != null ? c.priority : 0,
4873
+ component: componentEntry.component,
4874
+ priority: componentEntry.priority != null ? componentEntry.priority : 0,
4801
4875
  key: `${pluginId}-${pointId}-${++slotItemKeySeq}`
4802
4876
  });
4803
4877
  }
@@ -4805,14 +4879,12 @@ function createHostApi(pluginId, router, hostKitOptions = {}) {
4805
4879
  registries.slotRevision++;
4806
4880
  },
4807
4881
  registerStylesheetUrls(urls) {
4808
- for (const u of urls || []) {
4809
- if (typeof u === 'string' && u) {
4810
- injectStylesheet(u);
4811
- }
4882
+ for (const url of normalizeUrls(urls)) {
4883
+ injectStylesheet(pluginId, url);
4812
4884
  }
4813
4885
  },
4814
4886
  registerScriptUrls(urls) {
4815
- const chain = (urls || []).filter((u) => typeof u === 'string' && u).reduce((p, u) => p.then(() => injectScript(u)), Promise.resolve());
4887
+ const chain = normalizeUrls(urls).reduce((promise, url) => promise.then(() => injectScript(pluginId, url)), Promise.resolve());
4816
4888
  chain.catch((e) => console.warn('[wep] registerScriptUrls', pluginId, e));
4817
4889
  },
4818
4890
  registerSanitizedHtmlSnippet() {
@@ -4885,16 +4957,6 @@ function createExtensionPointComponent(VueLike = Vue) {
4885
4957
  }
4886
4958
  var ExtensionPoint = createExtensionPointComponent();
4887
4959
 
4888
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4889
- function installWebExtendPluginVue2(Vue, router, options) {
4890
- if (Vue) {
4891
- ensureRegistriesReactive(Vue);
4892
- Vue.component('ExtensionPoint', createExtensionPointComponent(Vue));
4893
- }
4894
- const runtime = resolveRuntimeOptions$1(options || {});
4895
- return bootstrapPlugins$1(router, (id, r, kit) => createHostApi(id, r, kit || {}), runtime);
4896
- }
4897
-
4898
4960
  function isRecord(input) {
4899
4961
  return !!input && typeof input === 'object' && !Array.isArray(input);
4900
4962
  }
@@ -4932,22 +4994,19 @@ VueRuntime, options = {}) {
4932
4994
  return modules;
4933
4995
  }
4934
4996
 
4935
- function resolveManifestPathUnderApiBase(manifestUrl, apiBase) {
4936
- const base = String(apiBase !== undefined
4937
- ? apiBase
4938
- : typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API
4939
- ? String(process.env.VUE_APP_BASE_API)
4940
- : '').replace(/\/$/, '');
4941
- if (typeof window === 'undefined') {
4942
- return '/api/frontend-plugins';
4943
- }
4944
- const url = new URL(manifestUrl, window.location.origin);
4945
- let path = url.pathname + url.search;
4946
- if (base && path.startsWith(base)) {
4947
- path = path.slice(base.length) || '/';
4997
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4998
+ function installWebExtendPluginVue2(Vue, router, options) {
4999
+ const runtime = resolveRuntimeOptions$1(options);
5000
+ if (Vue) {
5001
+ ensureRegistriesReactive(Vue);
5002
+ Vue.component('ExtensionPoint', createExtensionPointComponent(Vue));
5003
+ if (runtime.hostBridge && typeof runtime.hostBridge === 'object') {
5004
+ installHostBridge(Vue, runtime.hostBridge);
5005
+ }
4948
5006
  }
4949
- return path;
5007
+ return bootstrapPlugins$1(router, createHostApi, runtime);
4950
5008
  }
5009
+
4951
5010
  function bridgePrefixesFromVueCliEnv() {
4952
5011
  const base = (typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API
4953
5012
  ? String(process.env.VUE_APP_BASE_API)
@@ -4955,32 +5014,29 @@ function bridgePrefixesFromVueCliEnv() {
4955
5014
  const raw = [base ? `${base}/` : '', '/api/', '/dev-api/'].filter(Boolean);
4956
5015
  return [...new Set(raw)];
4957
5016
  }
5017
+ function asRecord(value) {
5018
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
5019
+ }
4958
5020
  function createVueCliAxiosInstallOptions(deps, extra = {}) {
4959
5021
  const { request } = deps;
4960
5022
  if (typeof request !== 'function') {
4961
5023
  throw new Error('[wep] createVueCliAxiosInstallOptions requires deps.request');
4962
5024
  }
4963
- const { fetchManifest: userFetchManifest, manifestMode: extraManifestMode, staticManifestUrl: extraStaticManifestUrl, ...restExtra } = extra;
4964
- const envBase = (typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API
4965
- ? String(process.env.VUE_APP_BASE_API)
4966
- : '').replace(/\/$/, '');
4967
- const userBase = extra.manifestBase !== undefined && String(extra.manifestBase).trim() !== ''
4968
- ? String(extra.manifestBase).replace(/\/$/, '')
4969
- : '';
4970
- const stripBase = userBase || envBase;
5025
+ const manifest = asRecord(extra.manifest) || {};
5026
+ const host = asRecord(extra.host) || {};
5027
+ const mergedHost = { ...host };
4971
5028
  const fetchManifestApi = async (ctx) => {
4972
5029
  try {
5030
+ const manifestRequestUrl = typeof window !== 'undefined'
5031
+ ? new URL(String(ctx.manifestUrl), window.location.origin).toString()
5032
+ : String(ctx.manifestUrl);
4973
5033
  const body = await request({
4974
- url: resolveManifestPathUnderApiBase(ctx.manifestUrl, stripBase),
5034
+ url: manifestRequestUrl,
4975
5035
  method: 'get'
4976
5036
  });
4977
5037
  const data = unwrapNestedManifestBody(body);
4978
5038
  if (!data || typeof data !== 'object') {
4979
- return {
4980
- ok: false,
4981
- error: new Error('[wep] invalid manifest response'),
4982
- data: null
4983
- };
5039
+ return { ok: false, error: new Error('[wep] invalid manifest response'), data: null };
4984
5040
  }
4985
5041
  return { ok: true, data };
4986
5042
  }
@@ -4988,28 +5044,35 @@ function createVueCliAxiosInstallOptions(deps, extra = {}) {
4988
5044
  return { ok: false, error, data: null };
4989
5045
  }
4990
5046
  };
4991
- const manifestMode = resolveManifestModeFromInputs(extraManifestMode);
4992
- const staticManifestUrl = resolveStaticManifestUrlFromInputs(extraStaticManifestUrl);
4993
- const fetchManifest = typeof userFetchManifest === 'function'
4994
- ? userFetchManifest
4995
- : manifestMode === 'static'
5047
+ const manifestSource = resolveManifestModeFromInputs(manifest.source);
5048
+ const staticUrl = resolveStaticManifestUrlFromInputs(manifest.staticUrl);
5049
+ const fetchManifest = typeof manifest.fetch === 'function'
5050
+ ? manifest.fetch
5051
+ : manifestSource === 'static'
4996
5052
  ? fetchStaticManifestViaHttp
4997
5053
  : fetchManifestApi;
4998
- const options = {
4999
- manifestBase: stripBase || undefined,
5000
- bridgeAllowedPathPrefixes: bridgePrefixesFromVueCliEnv(),
5001
- manifestMode,
5002
- staticManifestUrl,
5003
- ...restExtra,
5004
- fetchManifest
5005
- };
5006
5054
  const listPath = typeof process !== 'undefined' &&
5007
5055
  process.env &&
5008
- process.env[webExtendPluginEnvKeys.manifestPathAlt];
5009
- if (listPath && options.manifestListPath === undefined && extra.manifestListPath === undefined) {
5010
- options.manifestListPath = String(process.env[webExtendPluginEnvKeys.manifestPathAlt]);
5056
+ process.env[webExtendPluginEnvKeys.manifestPathAlt]
5057
+ ? String(process.env[webExtendPluginEnvKeys.manifestPathAlt])
5058
+ : undefined;
5059
+ if (mergedHost.requestPathPrefixes === undefined) {
5060
+ mergedHost.requestPathPrefixes = bridgePrefixesFromVueCliEnv();
5011
5061
  }
5012
- return options;
5062
+ return {
5063
+ ...extra,
5064
+ manifest: {
5065
+ ...manifest,
5066
+ baseUrl: manifest.baseUrl !== undefined && String(manifest.baseUrl).trim() !== ''
5067
+ ? String(manifest.baseUrl).replace(/\/$/, '')
5068
+ : undefined,
5069
+ listPath: manifest.listPath !== undefined ? manifest.listPath : listPath,
5070
+ source: manifestSource,
5071
+ staticUrl,
5072
+ fetch: fetchManifest
5073
+ },
5074
+ host: mergedHost
5075
+ };
5013
5076
  }
5014
5077
 
5015
5078
  const { bootstrapPlugins, defaultFetchWebPluginManifest, resolveRuntimeOptions, ensurePluginHostRoute, getActivatedPluginIds } = pluginRuntime;