web-extend-plugin-vue2 0.2.2 → 0.2.3
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/README.md +45 -192
- package/dist/index.cjs +477 -547
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +475 -546
- package/dist/index.mjs.map +1 -1
- package/index.d.ts +136 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7,107 +7,62 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
7
7
|
var Vue__default = /*#__PURE__*/_interopDefault(Vue);
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* 使用方式:`resolveRuntimeOptions({ ...defaultWebExtendPluginRuntime, manifestListPath: '/api/my-plugins' })`
|
|
12
|
-
* 或只传需要改动的字段:`resolveRuntimeOptions({ manifestListPath: '/api/my-plugins' })`。
|
|
13
|
-
*
|
|
14
|
-
* @module default-runtime-config
|
|
10
|
+
* `resolveRuntimeOptions` 的默认值来源;宿主可只覆盖部分字段。
|
|
15
11
|
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @typedef {typeof defaultWebExtendPluginRuntime} WebExtendPluginDefaultRuntime
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
12
|
const defaultWebExtendPluginRuntime = {
|
|
22
|
-
/** 清单 HTTP 服务前缀(与后端 context-path 对齐),不含尾部 `/` */
|
|
23
13
|
manifestBase: '/fp-api',
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 拉取插件清单的 **路径段**(以 `/` 开头),拼在 `manifestBase` 之后。
|
|
27
|
-
* 完整 URL:`{manifestBase}{manifestListPath}` → 默认 `/fp-api/api/frontend-plugins`
|
|
28
|
-
*/
|
|
29
14
|
manifestListPath: '/api/frontend-plugins',
|
|
30
|
-
|
|
31
|
-
/** 清单 `fetch` 的 `credentials`,需 Cookie 会话时用 `include` */
|
|
32
15
|
manifestFetchCredentials: 'include',
|
|
33
|
-
|
|
34
|
-
/** 插件 dev 服务存活探测路径(拼在 `webPluginDevOrigin` 后) */
|
|
35
16
|
devPingPath: '/__web_plugin_dev_ping',
|
|
36
|
-
|
|
37
|
-
/** 插件 dev 热更新 SSE 路径(拼在插件 dev 的 origin 后) */
|
|
38
17
|
devReloadSsePath: '/__web_plugin_reload_stream',
|
|
39
|
-
|
|
40
|
-
/** 隐式 dev 映射里,每个 id 对应的入口路径(相对插件 dev origin) */
|
|
41
18
|
webPluginDevEntryPath: '/src/plugin-entry.js',
|
|
42
|
-
|
|
43
|
-
/** `fetch(devPingUrl)` 超时毫秒数 */
|
|
44
19
|
devPingTimeoutMs: 500,
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* **隐式 dev 映射**(可选):开发模式下若 `webPluginDevOrigin` 上 ping 成功,运行时会为若干插件 id 自动生成
|
|
48
|
-
* `{ id → origin + webPluginDevEntryPath }`,从而用 dev 服务入口替代清单里的 dist,便于热更新联调。
|
|
49
|
-
*
|
|
50
|
-
* 插件 id 来源优先级:`webPluginDevIds`(或 `VITE_WEB_PLUGIN_DEV_IDS`)→ 本字段。**默认 `[]`**,
|
|
51
|
-
* 避免把仓库示例 id 写进通用宿主;联调时在 `.env` 里设 `VITE_WEB_PLUGIN_DEV_IDS=com.xxx,com.yyy`,
|
|
52
|
-
* 或 `resolveRuntimeOptions({ defaultImplicitDevPluginIds: ['com.xxx'] })` 即可。
|
|
53
|
-
*/
|
|
54
20
|
defaultImplicitDevPluginIds: [],
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 允许通过 `<script>` / 动态 `import()` 加载的插件脚本所在主机名(小写),防误配公网 URL。
|
|
58
|
-
*/
|
|
59
21
|
allowedScriptHosts: ['localhost', '127.0.0.1', '::1'],
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* `hostApi.getBridge().request(path)` 允许的 path 前缀;须以 `/` 开头。
|
|
63
|
-
* 需与后端实际 API 前缀一致。
|
|
64
|
-
*/
|
|
65
22
|
bridgeAllowedPathPrefixes: ['/api/']
|
|
66
23
|
};
|
|
67
24
|
|
|
68
25
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* - Vite:在入口调用 `setWebExtendPluginEnv(import.meta.env)`,或 `installWebExtendPluginVue2(..., { env: import.meta.env })`。
|
|
72
|
-
* - 也可在入口前设置 `globalThis.__WEP_ENV__ = import.meta.env`(与 setWebExtendPluginEnv 二选一即可)。
|
|
73
|
-
*
|
|
74
|
-
* @module bundled-env
|
|
26
|
+
* 与具体打包器解耦的运行时环境读取:优先显式注入,其次 `globalThis.__WEP_ENV__`,再读 `process.env`。
|
|
27
|
+
* Vite 宿主建议在入口调用 `setWebExtendPluginEnv(import.meta.env)`。
|
|
75
28
|
*/
|
|
76
29
|
|
|
77
30
|
/** @type {Record<string, unknown> | null} */
|
|
78
|
-
let
|
|
31
|
+
let _injected = null;
|
|
79
32
|
|
|
80
33
|
/**
|
|
81
|
-
*
|
|
34
|
+
* 注入与 `import.meta.env` 同形态的对象(键如 `VITE_*`、`DEV`)。
|
|
82
35
|
* @param {Record<string, unknown> | null | undefined} env
|
|
83
36
|
*/
|
|
84
37
|
function setWebExtendPluginEnv(env) {
|
|
85
|
-
|
|
38
|
+
_injected = env && typeof env === 'object' ? env : null;
|
|
86
39
|
}
|
|
87
40
|
|
|
88
41
|
/**
|
|
89
42
|
* @returns {Record<string, unknown> | null}
|
|
90
43
|
*/
|
|
91
|
-
function
|
|
92
|
-
if (
|
|
93
|
-
return
|
|
44
|
+
function getEnvObject() {
|
|
45
|
+
if (_injected) {
|
|
46
|
+
return _injected
|
|
94
47
|
}
|
|
95
48
|
try {
|
|
96
49
|
const g = typeof globalThis !== 'undefined' ? globalThis : undefined;
|
|
97
50
|
if (g && g.__WEP_ENV__ && typeof g.__WEP_ENV__ === 'object') {
|
|
98
51
|
return g.__WEP_ENV__
|
|
99
52
|
}
|
|
100
|
-
} catch (_) {
|
|
53
|
+
} catch (_) {
|
|
54
|
+
/* ignore */
|
|
55
|
+
}
|
|
101
56
|
return null
|
|
102
57
|
}
|
|
103
58
|
|
|
104
59
|
/**
|
|
105
|
-
*
|
|
60
|
+
* 读取注入环境中的字符串配置(`VITE_*` / `PLUGIN_*` 等价键由调用方传入)。
|
|
106
61
|
* @param {string} key
|
|
107
62
|
* @returns {string|undefined}
|
|
108
63
|
*/
|
|
109
64
|
function readInjectedEnvKey(key) {
|
|
110
|
-
const o =
|
|
65
|
+
const o = getEnvObject();
|
|
111
66
|
if (!o || !(key in o)) {
|
|
112
67
|
return undefined
|
|
113
68
|
}
|
|
@@ -118,17 +73,14 @@ function readInjectedEnvKey(key) {
|
|
|
118
73
|
return String(v)
|
|
119
74
|
}
|
|
120
75
|
|
|
121
|
-
/**
|
|
122
|
-
* @returns {boolean}
|
|
123
|
-
*/
|
|
76
|
+
/** @returns {boolean} */
|
|
124
77
|
function readInjectedEnvDev() {
|
|
125
|
-
const o =
|
|
78
|
+
const o = getEnvObject();
|
|
126
79
|
return !!(o && o.DEV === true)
|
|
127
80
|
}
|
|
128
81
|
|
|
129
82
|
/**
|
|
130
|
-
* 从注入环境与 `process.env` 解析 VITE_/PLUGIN_ 键。
|
|
131
|
-
* @module runtime/env-resolve
|
|
83
|
+
* 从注入环境与 `process.env` 解析 `VITE_*` / `PLUGIN_*` 键。
|
|
132
84
|
*/
|
|
133
85
|
|
|
134
86
|
/**
|
|
@@ -143,7 +95,9 @@ function readProcessEnv(key) {
|
|
|
143
95
|
return String(v)
|
|
144
96
|
}
|
|
145
97
|
}
|
|
146
|
-
} catch (_) {
|
|
98
|
+
} catch (_) {
|
|
99
|
+
/* ignore */
|
|
100
|
+
}
|
|
147
101
|
return undefined
|
|
148
102
|
}
|
|
149
103
|
|
|
@@ -174,20 +128,22 @@ function resolveBundledEnv(key, fallback = '') {
|
|
|
174
128
|
return first === undefined || first === null ? fallback : first
|
|
175
129
|
}
|
|
176
130
|
|
|
177
|
-
/**
|
|
178
|
-
* @returns {boolean}
|
|
179
|
-
*/
|
|
131
|
+
/** @returns {boolean} */
|
|
180
132
|
function resolveBundledIsDev() {
|
|
181
133
|
try {
|
|
182
134
|
if (readInjectedEnvDev()) {
|
|
183
135
|
return true
|
|
184
136
|
}
|
|
185
|
-
} catch (_) {
|
|
137
|
+
} catch (_) {
|
|
138
|
+
/* ignore */
|
|
139
|
+
}
|
|
186
140
|
try {
|
|
187
141
|
if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development') {
|
|
188
142
|
return true
|
|
189
143
|
}
|
|
190
|
-
} catch (_) {
|
|
144
|
+
} catch (_) {
|
|
145
|
+
/* ignore */
|
|
146
|
+
}
|
|
191
147
|
return false
|
|
192
148
|
}
|
|
193
149
|
|
|
@@ -392,39 +348,24 @@ function resolveRuntimeOptions$1(user = {}) {
|
|
|
392
348
|
allowedScriptHosts,
|
|
393
349
|
bridgeAllowedPathPrefixes,
|
|
394
350
|
bootstrapSummary: user.bootstrapSummary,
|
|
395
|
-
|
|
351
|
+
pluginRoutesParentName:
|
|
352
|
+
user.pluginRoutesParentName !== undefined && String(user.pluginRoutesParentName).trim() !== ''
|
|
353
|
+
? String(user.pluginRoutesParentName).trim()
|
|
354
|
+
: '',
|
|
355
|
+
...(typeof user.fetchManifest === 'function' ? { fetchManifest: user.fetchManifest } : {}),
|
|
356
|
+
...(typeof user.transformRoutes === 'function' ? { transformRoutes: user.transformRoutes } : {}),
|
|
357
|
+
...(typeof user.interceptRegisterRoutes === 'function'
|
|
358
|
+
? { interceptRegisterRoutes: user.interceptRegisterRoutes }
|
|
359
|
+
: {}),
|
|
360
|
+
...(typeof user.adaptRouteDeclarations === 'function'
|
|
361
|
+
? { adaptRouteDeclarations: user.adaptRouteDeclarations }
|
|
362
|
+
: {})
|
|
396
363
|
}
|
|
397
364
|
}
|
|
398
365
|
|
|
399
366
|
/**
|
|
400
|
-
*
|
|
401
|
-
* @
|
|
402
|
-
*/
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* @typedef {object} FetchWebPluginManifestContext
|
|
406
|
-
* @property {string} manifestUrl
|
|
407
|
-
* @property {RequestCredentials} credentials
|
|
408
|
-
*/
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* @typedef {object} FetchWebPluginManifestResult
|
|
412
|
-
* @property {boolean} ok
|
|
413
|
-
* @property {number} [status]
|
|
414
|
-
* @property {{ hostPluginApiVersion?: string, plugins?: object[] }|null} [data]
|
|
415
|
-
* @property {unknown} [error]
|
|
416
|
-
*/
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* @callback FetchWebPluginManifestFn
|
|
420
|
-
* @param {FetchWebPluginManifestContext} ctx
|
|
421
|
-
* @returns {Promise<FetchWebPluginManifestResult>}
|
|
422
|
-
*/
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* 默认清单请求(未配置 `fetchManifest` 时)。
|
|
426
|
-
* @param {FetchWebPluginManifestContext} ctx
|
|
427
|
-
* @returns {Promise<FetchWebPluginManifestResult>}
|
|
367
|
+
* 未配置 `fetchManifest` 时使用的清单 `fetch` 实现。
|
|
368
|
+
* @param {{ manifestUrl: string, credentials: RequestCredentials }} ctx
|
|
428
369
|
*/
|
|
429
370
|
async function defaultFetchWebPluginManifest$1(ctx) {
|
|
430
371
|
const { manifestUrl, credentials } = ctx;
|
|
@@ -3165,11 +3106,11 @@ function requireSemver () {
|
|
|
3165
3106
|
var semverExports = requireSemver();
|
|
3166
3107
|
var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
|
|
3167
3108
|
|
|
3168
|
-
/**
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
*/
|
|
3172
|
-
const
|
|
3109
|
+
/** 与清单服务 `hostPluginApiVersion` 对齐,用于 `semver` 校验。 */
|
|
3110
|
+
const HOST_PLUGIN_API_VERSION = '1.0.0';
|
|
3111
|
+
|
|
3112
|
+
/** 控制台日志与横幅使用的短名称。 */
|
|
3113
|
+
const RUNTIME_CONSOLE_LABEL = 'web-extend-plugin-vue2';
|
|
3173
3114
|
|
|
3174
3115
|
/**
|
|
3175
3116
|
* 开发模式插件 URL 映射(显式 JSON + 隐式 dev 探测)。
|
|
@@ -3191,7 +3132,7 @@ function parseWebPluginDevMapExplicit(opts) {
|
|
|
3191
3132
|
const map = JSON.parse(String(raw));
|
|
3192
3133
|
return map && typeof map === 'object' ? map : null
|
|
3193
3134
|
} catch {
|
|
3194
|
-
console.warn('[
|
|
3135
|
+
console.warn('[wep] invalid webPluginDevMapJson / VITE_WEB_PLUGIN_DEV_MAP');
|
|
3195
3136
|
return null
|
|
3196
3137
|
}
|
|
3197
3138
|
}
|
|
@@ -3273,14 +3214,7 @@ async function buildImplicitWebPluginDevMap(opts, hostSet) {
|
|
|
3273
3214
|
map[id] = `${base}${pathPart}`;
|
|
3274
3215
|
}
|
|
3275
3216
|
if (ids.length) {
|
|
3276
|
-
console.info(
|
|
3277
|
-
'[plugins] 已检测到插件 dev 服务(',
|
|
3278
|
-
base,
|
|
3279
|
-
'),下列 id 将加载隐式 dev 入口(',
|
|
3280
|
-
pathPart,
|
|
3281
|
-
')而非清单 dist:',
|
|
3282
|
-
ids.join(', ')
|
|
3283
|
-
);
|
|
3217
|
+
console.info('[wep] plugin dev server', base, '→ implicit entries', pathPart, ids.join(', '));
|
|
3284
3218
|
}
|
|
3285
3219
|
return map
|
|
3286
3220
|
}
|
|
@@ -3348,10 +3282,10 @@ function startPluginDevReloadSse(origin, isDev, hostSet, ssePath) {
|
|
|
3348
3282
|
window.location.reload();
|
|
3349
3283
|
});
|
|
3350
3284
|
es.onopen = () => {
|
|
3351
|
-
console.info('[
|
|
3285
|
+
console.info('[wep] dev reload SSE', url);
|
|
3352
3286
|
};
|
|
3353
3287
|
} catch (e) {
|
|
3354
|
-
console.warn('[
|
|
3288
|
+
console.warn('[wep] EventSource failed', url, e);
|
|
3355
3289
|
}
|
|
3356
3290
|
}
|
|
3357
3291
|
|
|
@@ -3439,9 +3373,21 @@ function loadScript(src) {
|
|
|
3439
3373
|
return p
|
|
3440
3374
|
}
|
|
3441
3375
|
|
|
3376
|
+
let _printed = false;
|
|
3377
|
+
|
|
3378
|
+
/** 在首次引导插件时打印一行运行时标识(非大块 ASCII art)。 */
|
|
3379
|
+
function printRuntimeBannerOnce() {
|
|
3380
|
+
if (_printed) {
|
|
3381
|
+
return
|
|
3382
|
+
}
|
|
3383
|
+
_printed = true;
|
|
3384
|
+
if (typeof console !== 'undefined' && typeof console.info === 'function') {
|
|
3385
|
+
console.info(`[wep] ${RUNTIME_CONSOLE_LABEL} · host API ${HOST_PLUGIN_API_VERSION}`);
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3442
3389
|
/**
|
|
3443
|
-
*
|
|
3444
|
-
* @module runtime/bootstrap-plugins
|
|
3390
|
+
* 拉取插件清单、加载入口脚本并调用各插件 `activator`。
|
|
3445
3391
|
*/
|
|
3446
3392
|
|
|
3447
3393
|
/**
|
|
@@ -3474,7 +3420,7 @@ async function loadPluginEntry(p, entryUrl, devMap, hostSet) {
|
|
|
3474
3420
|
const devEntry = devMap && typeof devMap[p.id] === 'string' ? devMap[p.id].trim() : '';
|
|
3475
3421
|
if (devEntry) {
|
|
3476
3422
|
if (!isScriptHostAllowed(devEntry, hostSet)) {
|
|
3477
|
-
console.warn('[
|
|
3423
|
+
console.warn('[wep] dev entry URL not allowed', p.id, devEntry);
|
|
3478
3424
|
return
|
|
3479
3425
|
}
|
|
3480
3426
|
try {
|
|
@@ -3484,7 +3430,7 @@ async function loadPluginEntry(p, entryUrl, devMap, hostSet) {
|
|
|
3484
3430
|
devEntry
|
|
3485
3431
|
);
|
|
3486
3432
|
} catch (e) {
|
|
3487
|
-
console.warn('[
|
|
3433
|
+
console.warn('[wep] dev import failed, trying manifest entryUrl', p.id, e);
|
|
3488
3434
|
if (entryUrl && isScriptHostAllowed(entryUrl, hostSet)) {
|
|
3489
3435
|
await loadScript(entryUrl);
|
|
3490
3436
|
}
|
|
@@ -3493,7 +3439,7 @@ async function loadPluginEntry(p, entryUrl, devMap, hostSet) {
|
|
|
3493
3439
|
return
|
|
3494
3440
|
}
|
|
3495
3441
|
if (!entryUrl || !isScriptHostAllowed(entryUrl, hostSet)) {
|
|
3496
|
-
console.warn('[
|
|
3442
|
+
console.warn('[wep] skip (entryUrl not allowed)', p.id, entryUrl);
|
|
3497
3443
|
return
|
|
3498
3444
|
}
|
|
3499
3445
|
await loadScript(entryUrl);
|
|
@@ -3501,14 +3447,15 @@ async function loadPluginEntry(p, entryUrl, devMap, hostSet) {
|
|
|
3501
3447
|
|
|
3502
3448
|
/**
|
|
3503
3449
|
* @param {import('vue-router').default} router
|
|
3504
|
-
* @param {(pluginId: string, router: import('vue-router').default, hostKit?:
|
|
3450
|
+
* @param {(pluginId: string, router: import('vue-router').default, hostKit?: object) => object} createHostApiFactory
|
|
3505
3451
|
* @param {import('./resolve-runtime-options.js').WebExtendPluginRuntimeOptions} [runtimeOptions]
|
|
3506
3452
|
*/
|
|
3507
3453
|
async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions) {
|
|
3508
3454
|
if (typeof window === 'undefined') {
|
|
3509
|
-
console.warn('[
|
|
3455
|
+
console.warn('[wep] bootstrapPlugins skipped (no window)');
|
|
3510
3456
|
return
|
|
3511
3457
|
}
|
|
3458
|
+
printRuntimeBannerOnce();
|
|
3512
3459
|
const opts = resolveRuntimeOptions$1(runtimeOptions || {});
|
|
3513
3460
|
const base = String(opts.manifestBase).replace(/\/$/, '');
|
|
3514
3461
|
const manifestUrl = `${base}${opts.manifestListPath}`;
|
|
@@ -3536,16 +3483,28 @@ async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions)
|
|
|
3536
3483
|
const devMap = mergeDevMaps(implicit, explicit);
|
|
3537
3484
|
startPluginDevSseForMap(devMap, opts.isDev, hostSet, opts.devReloadSsePath);
|
|
3538
3485
|
|
|
3539
|
-
const hostKit = {
|
|
3486
|
+
const hostKit = {
|
|
3487
|
+
bridgeAllowedPathPrefixes: opts.bridgeAllowedPathPrefixes,
|
|
3488
|
+
...(opts.pluginRoutesParentName
|
|
3489
|
+
? { pluginRoutesParentName: opts.pluginRoutesParentName }
|
|
3490
|
+
: {}),
|
|
3491
|
+
...(typeof opts.transformRoutes === 'function' ? { transformRoutes: opts.transformRoutes } : {}),
|
|
3492
|
+
...(typeof opts.interceptRegisterRoutes === 'function'
|
|
3493
|
+
? { interceptRegisterRoutes: opts.interceptRegisterRoutes }
|
|
3494
|
+
: {}),
|
|
3495
|
+
...(typeof opts.adaptRouteDeclarations === 'function'
|
|
3496
|
+
? { adaptRouteDeclarations: opts.adaptRouteDeclarations }
|
|
3497
|
+
: {})
|
|
3498
|
+
};
|
|
3540
3499
|
|
|
3541
3500
|
if (!manifestResult.ok) {
|
|
3542
3501
|
if (manifestResult.error) {
|
|
3543
|
-
console.warn('[
|
|
3502
|
+
console.warn('[wep] fetch manifest failed', manifestResult.error);
|
|
3544
3503
|
} else {
|
|
3545
|
-
console.warn('[
|
|
3504
|
+
console.warn('[wep] manifest HTTP', manifestResult.status, manifestUrl);
|
|
3546
3505
|
}
|
|
3547
3506
|
if (shouldShowBootstrapSummary(opts)) {
|
|
3548
|
-
console.info('[
|
|
3507
|
+
console.info('[wep] bootstrap_summary', { ok: false, reason: 'manifest_fetch' });
|
|
3549
3508
|
}
|
|
3550
3509
|
return
|
|
3551
3510
|
}
|
|
@@ -3553,7 +3512,7 @@ async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions)
|
|
|
3553
3512
|
const data = manifestResult.data;
|
|
3554
3513
|
if (!data) {
|
|
3555
3514
|
if (shouldShowBootstrapSummary(opts)) {
|
|
3556
|
-
console.info('[
|
|
3515
|
+
console.info('[wep] bootstrap_summary', { ok: false, reason: 'manifest_empty_body' });
|
|
3557
3516
|
}
|
|
3558
3517
|
return
|
|
3559
3518
|
}
|
|
@@ -3564,12 +3523,10 @@ async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions)
|
|
|
3564
3523
|
const maj = coerced ? coerced.major : 0;
|
|
3565
3524
|
const range = `^${maj}.0.0`;
|
|
3566
3525
|
if (!semver.satisfies(HOST_PLUGIN_API_VERSION, range, { includePrerelease: true })) {
|
|
3567
|
-
console.warn(
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
apiVer
|
|
3572
|
-
);
|
|
3526
|
+
console.warn('[wep] host API version mismatch', {
|
|
3527
|
+
host: HOST_PLUGIN_API_VERSION,
|
|
3528
|
+
manifest: apiVer
|
|
3529
|
+
});
|
|
3573
3530
|
}
|
|
3574
3531
|
}
|
|
3575
3532
|
|
|
@@ -3577,11 +3534,7 @@ async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions)
|
|
|
3577
3534
|
|
|
3578
3535
|
const plugins = data.plugins || [];
|
|
3579
3536
|
if (plugins.length === 0) {
|
|
3580
|
-
console.info(
|
|
3581
|
-
'[plugins] 清单为空。请检查:① 后端清单服务(plugin-web-starter)是否已接入;② web-plugin.web-plugins-dir 是否指向含各插件子目录及 manifest.json 的路径;③ 浏览器直接访问',
|
|
3582
|
-
manifestUrl,
|
|
3583
|
-
'是否返回 plugins 条目。'
|
|
3584
|
-
);
|
|
3537
|
+
console.info('[wep] empty plugin manifest — check backend and URL', manifestUrl);
|
|
3585
3538
|
}
|
|
3586
3539
|
|
|
3587
3540
|
const summary = {
|
|
@@ -3596,7 +3549,7 @@ async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions)
|
|
|
3596
3549
|
for (const p of plugins) {
|
|
3597
3550
|
const range = p.engines && p.engines.host;
|
|
3598
3551
|
if (range && !semver.satisfies(HOST_PLUGIN_API_VERSION, range, { includePrerelease: true })) {
|
|
3599
|
-
console.warn('[
|
|
3552
|
+
console.warn('[wep] skip plugin (engines.host)', p.id, range);
|
|
3600
3553
|
summary.skipEngines++;
|
|
3601
3554
|
continue
|
|
3602
3555
|
}
|
|
@@ -3604,39 +3557,34 @@ async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions)
|
|
|
3604
3557
|
try {
|
|
3605
3558
|
await loadPluginEntry(p, entryUrl, devMap, hostSet);
|
|
3606
3559
|
} catch (e) {
|
|
3607
|
-
console.warn('[
|
|
3560
|
+
console.warn('[wep] script load failed', p.id, e);
|
|
3608
3561
|
summary.skipLoad++;
|
|
3609
3562
|
continue
|
|
3610
3563
|
}
|
|
3611
3564
|
const activator = window.__PLUGIN_ACTIVATORS__[p.id];
|
|
3612
3565
|
if (typeof activator !== 'function') {
|
|
3613
|
-
console.warn('[
|
|
3566
|
+
console.warn('[wep] no activator for', p.id);
|
|
3614
3567
|
summary.skipNoActivator++;
|
|
3615
3568
|
continue
|
|
3616
3569
|
}
|
|
3617
3570
|
const hostApi = createHostApiFactory(p.id, router, hostKit);
|
|
3618
3571
|
try {
|
|
3619
|
-
|
|
3572
|
+
const pluginRecord = Object.freeze({ ...p });
|
|
3573
|
+
activator(hostApi, { pluginRecord });
|
|
3620
3574
|
summary.activated++;
|
|
3621
3575
|
} catch (e) {
|
|
3622
|
-
console.error('[
|
|
3576
|
+
console.error('[wep] activate failed', p.id, e);
|
|
3623
3577
|
summary.activateFail++;
|
|
3624
3578
|
}
|
|
3625
3579
|
}
|
|
3626
3580
|
|
|
3627
3581
|
if (shouldShowBootstrapSummary(opts)) {
|
|
3628
|
-
console.info('[
|
|
3582
|
+
console.info('[wep] bootstrap_summary', { ok: true, ...summary });
|
|
3629
3583
|
}
|
|
3630
3584
|
}
|
|
3631
3585
|
|
|
3632
3586
|
/**
|
|
3633
|
-
*
|
|
3634
|
-
* 实现已拆至 `src/runtime/` 下各模块;本文件保留模块说明与对外类型约定,并 re-export 稳定 API。
|
|
3635
|
-
*
|
|
3636
|
-
* **Webpack 宿主**:用 `DefinePlugin` 注入 `process.env.VITE_*` 或 **`PLUGIN_*`**(等价键),或 `resolveRuntimeOptions` 显式传参。
|
|
3637
|
-
* **Vite 宿主**:入口调用 `setWebExtendPluginEnv(import.meta.env)`,或 `installWebExtendPluginVue2(..., { env: import.meta.env })`。
|
|
3638
|
-
*
|
|
3639
|
-
* @module PluginRuntime
|
|
3587
|
+
* 运行时引导相关 API 的聚合导出(实现位于 `./runtime/`)。
|
|
3640
3588
|
*/
|
|
3641
3589
|
|
|
3642
3590
|
var pluginRuntime = /*#__PURE__*/Object.freeze({
|
|
@@ -3648,7 +3596,7 @@ var pluginRuntime = /*#__PURE__*/Object.freeze({
|
|
|
3648
3596
|
|
|
3649
3597
|
/**
|
|
3650
3598
|
* 清单拉取函数的组合工具:缓存、埋点等以**中间件**形式扩展,不侵入 `bootstrapPlugins` 核心逻辑,
|
|
3651
|
-
*
|
|
3599
|
+
* 可组合的 `fetchManifest` 包装;入参/出参与 `resolveRuntimeOptions({ fetchManifest })` 一致。
|
|
3652
3600
|
*
|
|
3653
3601
|
* @module runtime/manifest-fetch-composer
|
|
3654
3602
|
*/
|
|
@@ -3863,356 +3811,367 @@ var manifestComposer = /*#__PURE__*/Object.freeze({
|
|
|
3863
3811
|
wrapManifestFetchWithCache: wrapManifestFetchWithCache$1
|
|
3864
3812
|
});
|
|
3865
3813
|
|
|
3866
|
-
/**
|
|
3867
|
-
*
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
if (
|
|
3891
|
-
throw new Error('[bridge] path
|
|
3892
|
-
}
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
}
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
...init
|
|
3900
|
-
})
|
|
3901
|
-
}
|
|
3902
|
-
}
|
|
3814
|
+
/**
|
|
3815
|
+
* 插件访问后端的受控通道:`fetch` 仅允许落在配置的路径前缀下(默认 `/api/`),默认 `credentials: 'same-origin'`。
|
|
3816
|
+
*/
|
|
3817
|
+
|
|
3818
|
+
/**
|
|
3819
|
+
* @param {{ allowedPathPrefixes?: string[] }} [config]
|
|
3820
|
+
*/
|
|
3821
|
+
function createRequestBridge(config = {}) {
|
|
3822
|
+
const raw =
|
|
3823
|
+
Array.isArray(config.allowedPathPrefixes) && config.allowedPathPrefixes.length > 0
|
|
3824
|
+
? config.allowedPathPrefixes
|
|
3825
|
+
: defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes;
|
|
3826
|
+
const allowedPathPrefixes = raw.map((p) => ensureLeadingPath(p));
|
|
3827
|
+
|
|
3828
|
+
return {
|
|
3829
|
+
/**
|
|
3830
|
+
* @param {string} path 必须以 `/` 开头,且匹配某一白名单前缀
|
|
3831
|
+
* @param {RequestInit} [init]
|
|
3832
|
+
*/
|
|
3833
|
+
async request(path, init = {}) {
|
|
3834
|
+
if (typeof path !== 'string' || !path.startsWith('/')) {
|
|
3835
|
+
throw new Error('[wep:bridge] path must start with /')
|
|
3836
|
+
}
|
|
3837
|
+
const allowed = allowedPathPrefixes.some((p) => path.startsWith(p));
|
|
3838
|
+
if (!allowed) {
|
|
3839
|
+
throw new Error('[wep:bridge] path not allowed: ' + path)
|
|
3840
|
+
}
|
|
3841
|
+
return fetch(path, {
|
|
3842
|
+
credentials: 'same-origin',
|
|
3843
|
+
...init
|
|
3844
|
+
})
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3903
3847
|
}
|
|
3904
3848
|
|
|
3905
|
-
/**
|
|
3906
|
-
*
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
*
|
|
3913
|
-
*
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
slots: {},
|
|
3921
|
-
/**
|
|
3922
|
-
* 每次变更 slots 时递增,供 ExtensionPoint 计算属性显式依赖。
|
|
3923
|
-
* Vue 2 对「先访问不存在的 slots[key]、后 Vue.set 补 key」的依赖收集不可靠,会导致扩展点不刷新。
|
|
3924
|
-
*/
|
|
3925
|
-
slotRevision: 0
|
|
3849
|
+
/**
|
|
3850
|
+
* 宿主侧响应式注册表:插件菜单与扩展点槽位(供布局与 `ExtensionPoint` 消费)。
|
|
3851
|
+
*/
|
|
3852
|
+
|
|
3853
|
+
/**
|
|
3854
|
+
* @type {{
|
|
3855
|
+
* menus: object[],
|
|
3856
|
+
* slots: Record<string, Array<{ pluginId: string, component: import('vue').Component, priority: number, key: string }>>
|
|
3857
|
+
* }}
|
|
3858
|
+
*/
|
|
3859
|
+
const registries = Vue__default.default.observable({
|
|
3860
|
+
menus: [],
|
|
3861
|
+
slots: {},
|
|
3862
|
+
/** 槽位变更计数;缓解 Vue2 对动态 `Vue.set(slots, key)` 的依赖收集不完整。 */
|
|
3863
|
+
slotRevision: 0
|
|
3926
3864
|
});
|
|
3927
3865
|
|
|
3928
|
-
/**
|
|
3929
|
-
*
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
*/
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
byPlugin.set(pluginId, arr);
|
|
3950
|
-
}
|
|
3951
|
-
arr.push(fn);
|
|
3952
|
-
}
|
|
3953
|
-
|
|
3954
|
-
/**
|
|
3955
|
-
* 执行并清空该插件已登记的全部 teardown;调用后 Map 中不再保留该 id。
|
|
3956
|
-
* @param {string} pluginId
|
|
3957
|
-
*/
|
|
3958
|
-
function runPluginTeardowns(pluginId) {
|
|
3959
|
-
const arr = byPlugin.get(pluginId);
|
|
3960
|
-
if (!arr) {
|
|
3961
|
-
return
|
|
3962
|
-
}
|
|
3963
|
-
byPlugin.delete(pluginId);
|
|
3964
|
-
for (const fn of arr) {
|
|
3965
|
-
try {
|
|
3966
|
-
fn();
|
|
3967
|
-
} catch (e) {
|
|
3968
|
-
console.warn('[plugins] teardown failed', pluginId, e);
|
|
3969
|
-
}
|
|
3970
|
-
}
|
|
3866
|
+
/**
|
|
3867
|
+
* 按插件 id 收集 `onTeardown` 回调,供 `disposeWebPlugin` 统一执行。
|
|
3868
|
+
*/
|
|
3869
|
+
|
|
3870
|
+
/** @type {Map<string, Array<() => void>>} */
|
|
3871
|
+
const _byPlugin = new Map();
|
|
3872
|
+
|
|
3873
|
+
/**
|
|
3874
|
+
* @param {string} pluginId
|
|
3875
|
+
* @param {() => void} fn
|
|
3876
|
+
*/
|
|
3877
|
+
function registerPluginTeardown(pluginId, fn) {
|
|
3878
|
+
if (typeof fn !== 'function') {
|
|
3879
|
+
return
|
|
3880
|
+
}
|
|
3881
|
+
let list = _byPlugin.get(pluginId);
|
|
3882
|
+
if (!list) {
|
|
3883
|
+
list = [];
|
|
3884
|
+
_byPlugin.set(pluginId, list);
|
|
3885
|
+
}
|
|
3886
|
+
list.push(fn);
|
|
3971
3887
|
}
|
|
3972
3888
|
|
|
3973
|
-
/**
|
|
3974
|
-
*
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
*/
|
|
3990
|
-
|
|
3991
|
-
/**
|
|
3992
|
-
* @typedef {object} HostApi
|
|
3993
|
-
* @property {string} hostPluginApiVersion 宿主实现的协议版本
|
|
3994
|
-
* @property {(routes: import('vue-router').RouteConfig[]) => void} registerRoutes 注册路由;无 `name` 时自动生成稳定合成名;优先 `router.addRoute`
|
|
3995
|
-
* @property {(items: object[]) => void} registerMenuItems 注册菜单并按 `order` 排序
|
|
3996
|
-
* @property {(pointId: string, components: RegisterSlotEntry[]) => void} registerSlotComponents 向扩展点挂载组件
|
|
3997
|
-
* @property {(urls?: string[]) => void} registerStylesheetUrls 注入 `link[rel=stylesheet]`,带 `data-plugin-asset`
|
|
3998
|
-
* @property {(urls?: string[]) => void} registerScriptUrls 顺序注入外链脚本
|
|
3999
|
-
* @property {() => void} registerSanitizedHtmlSnippet MVP 未实现,调用即抛错
|
|
4000
|
-
* @property {() => ReturnType<typeof createRequestBridge>} getBridge 受控 `fetch` 代理
|
|
4001
|
-
* @property {(pluginId: string, fn: () => void) => void} onTeardown 注册卸载回调;由 `disposeWebPlugin(pluginId)` 触发
|
|
4002
|
-
*/
|
|
4003
|
-
|
|
4004
|
-
/**
|
|
4005
|
-
* @typedef {object} HostKitOptions
|
|
4006
|
-
* @property {string[]} [bridgeAllowedPathPrefixes] 覆盖 `getBridge().request` 允许的 URL 前缀;默认见 `defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes`
|
|
4007
|
-
*/
|
|
4008
|
-
|
|
4009
|
-
/**
|
|
4010
|
-
* 创建单个插件在宿主侧的 API 句柄,传入插件 `activator(hostApi)`。
|
|
4011
|
-
*
|
|
4012
|
-
* `bootstrapPlugins` 始终以 `(pluginId, router, hostKitOptions)` 调用工厂;请使用 `(id, r, kit) => createHostApi(id, r, kit)` 传入 `bridgeAllowedPathPrefixes`。
|
|
4013
|
-
* 单参工厂 `(id) => createHostApi(id, router)` 仍可用(忽略后两个实参),此时 bridge 仅用包内默认前缀。
|
|
4014
|
-
*
|
|
4015
|
-
* @param {string} pluginId 与 manifest.id 一致
|
|
4016
|
-
* @param {import('vue-router').default} router 宿主 Vue Router 实例(vue-router@3)
|
|
4017
|
-
* @param {HostKitOptions} [hostKitOptions]
|
|
4018
|
-
* @returns {HostApi}
|
|
4019
|
-
*/
|
|
4020
|
-
function createHostApi(pluginId, router, hostKitOptions = {}) {
|
|
4021
|
-
const bridgePrefixes =
|
|
4022
|
-
Array.isArray(hostKitOptions.bridgeAllowedPathPrefixes) &&
|
|
4023
|
-
hostKitOptions.bridgeAllowedPathPrefixes.length > 0
|
|
4024
|
-
? hostKitOptions.bridgeAllowedPathPrefixes
|
|
4025
|
-
: defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes;
|
|
4026
|
-
const bridge = createRequestBridge({ allowedPathPrefixes: bridgePrefixes });
|
|
4027
|
-
|
|
4028
|
-
/**
|
|
4029
|
-
* 注入样式表;`disposeWebPlugin` 会按 `data-plugin-asset` 移除对应节点。
|
|
4030
|
-
* @param {string} href
|
|
4031
|
-
*/
|
|
4032
|
-
function injectStylesheet(href) {
|
|
4033
|
-
const link = document.createElement('link');
|
|
4034
|
-
link.rel = 'stylesheet';
|
|
4035
|
-
link.href = href;
|
|
4036
|
-
link.setAttribute('data-plugin-asset', pluginId);
|
|
4037
|
-
document.head.appendChild(link);
|
|
4038
|
-
}
|
|
4039
|
-
|
|
4040
|
-
/**
|
|
4041
|
-
* 注入外链脚本(用于插件额外资源,非清单主入口)。
|
|
4042
|
-
* @param {string} src
|
|
4043
|
-
* @returns {Promise<void>}
|
|
4044
|
-
*/
|
|
4045
|
-
function injectScript(src) {
|
|
4046
|
-
return new Promise((resolve, reject) => {
|
|
4047
|
-
const s = document.createElement('script');
|
|
4048
|
-
s.async = true;
|
|
4049
|
-
s.src = src;
|
|
4050
|
-
s.setAttribute('data-plugin-asset', pluginId);
|
|
4051
|
-
s.onload = () => resolve();
|
|
4052
|
-
s.onerror = () => reject(new Error('script failed: ' + src));
|
|
4053
|
-
document.head.appendChild(s);
|
|
4054
|
-
})
|
|
4055
|
-
}
|
|
4056
|
-
|
|
4057
|
-
return {
|
|
4058
|
-
hostPluginApiVersion: HOST_PLUGIN_API_VERSION,
|
|
4059
|
-
|
|
4060
|
-
/**
|
|
4061
|
-
* 动态注册路由。Vue Router 3.5+ 推荐 `addRoute`;若不存在则回退已弃用的 `addRoutes`。
|
|
4062
|
-
* @param {import('vue-router').RouteConfig[]} routes
|
|
4063
|
-
*/
|
|
4064
|
-
registerRoutes(routes) {
|
|
4065
|
-
const wrapped = routes.map((r) => ({
|
|
4066
|
-
...r,
|
|
4067
|
-
name: r.name || `__wep_${pluginId}_${routeSynthSeq++}`,
|
|
4068
|
-
meta: { ...(r.meta || {}), pluginId }
|
|
4069
|
-
}));
|
|
4070
|
-
if (typeof router.addRoute === 'function') {
|
|
4071
|
-
for (const r of wrapped) {
|
|
4072
|
-
router.addRoute(r);
|
|
4073
|
-
}
|
|
4074
|
-
} else {
|
|
4075
|
-
router.addRoutes(wrapped);
|
|
4076
|
-
}
|
|
4077
|
-
},
|
|
4078
|
-
|
|
4079
|
-
/**
|
|
4080
|
-
* 写入全局菜单注册表(响应式);按 `order` 升序排列。
|
|
4081
|
-
* @param {object[]} items
|
|
4082
|
-
*/
|
|
4083
|
-
registerMenuItems(items) {
|
|
4084
|
-
for (const item of items) {
|
|
4085
|
-
registries.menus.push({ ...item, pluginId });
|
|
4086
|
-
}
|
|
4087
|
-
registries.menus.sort(
|
|
4088
|
-
(a, b) => (a.order != null ? a.order : 0) - (b.order != null ? b.order : 0)
|
|
4089
|
-
);
|
|
4090
|
-
},
|
|
4091
|
-
|
|
4092
|
-
/**
|
|
4093
|
-
* 向指定扩展点 id 注册 Vue 组件;`ExtensionPoint` 按 `priority` 降序渲染。
|
|
4094
|
-
* @param {string} pointId
|
|
4095
|
-
* @param {RegisterSlotEntry[]} components
|
|
4096
|
-
*/
|
|
4097
|
-
registerSlotComponents(pointId, components) {
|
|
4098
|
-
if (!pointId) {
|
|
4099
|
-
return
|
|
4100
|
-
}
|
|
4101
|
-
if (!registries.slots[pointId]) {
|
|
4102
|
-
Vue__default.default.set(registries.slots, pointId, []);
|
|
4103
|
-
}
|
|
4104
|
-
const list = registries.slots[pointId];
|
|
4105
|
-
for (const c of components) {
|
|
4106
|
-
list.push({
|
|
4107
|
-
pluginId,
|
|
4108
|
-
component: c.component,
|
|
4109
|
-
priority: c.priority != null ? c.priority : 0,
|
|
4110
|
-
key: `${pluginId}-${pointId}-${++slotItemKeySeq}`
|
|
4111
|
-
});
|
|
4112
|
-
}
|
|
4113
|
-
list.sort((a, b) => b.priority - a.priority);
|
|
4114
|
-
registries.slotRevision++;
|
|
4115
|
-
},
|
|
4116
|
-
|
|
4117
|
-
/**
|
|
4118
|
-
* @param {string[]|undefined} urls
|
|
4119
|
-
*/
|
|
4120
|
-
registerStylesheetUrls(urls) {
|
|
4121
|
-
for (const u of urls || []) {
|
|
4122
|
-
if (typeof u === 'string' && u) {
|
|
4123
|
-
injectStylesheet(u);
|
|
4124
|
-
}
|
|
4125
|
-
}
|
|
4126
|
-
},
|
|
4127
|
-
|
|
4128
|
-
/**
|
|
4129
|
-
* 串行加载多个脚本,失败仅告警不中断宿主。
|
|
4130
|
-
* @param {string[]|undefined} urls
|
|
4131
|
-
*/
|
|
4132
|
-
registerScriptUrls(urls) {
|
|
4133
|
-
const chain = (urls || []).filter((u) => typeof u === 'string' && u).reduce(
|
|
4134
|
-
(p, u) => p.then(() => injectScript(u)),
|
|
4135
|
-
Promise.resolve()
|
|
4136
|
-
);
|
|
4137
|
-
chain.catch((e) => console.warn('[plugins] registerScriptUrls', pluginId, e));
|
|
4138
|
-
},
|
|
4139
|
-
|
|
4140
|
-
registerSanitizedHtmlSnippet() {
|
|
4141
|
-
throw new Error('registerSanitizedHtmlSnippet is not enabled in MVP')
|
|
4142
|
-
},
|
|
4143
|
-
|
|
4144
|
-
getBridge: () => bridge,
|
|
4145
|
-
|
|
4146
|
-
/**
|
|
4147
|
-
* 插件卸载前清理逻辑;第一个参数为预留与协议对齐,实际以创建 API 时的 `pluginId` 为准。
|
|
4148
|
-
* @param {string} _pluginId 预留,与 manifest.id 一致时可传入
|
|
4149
|
-
* @param {() => void} fn
|
|
4150
|
-
*/
|
|
4151
|
-
onTeardown(_pluginId, fn) {
|
|
4152
|
-
if (typeof fn === 'function') {
|
|
4153
|
-
registerPluginTeardown(pluginId, fn);
|
|
4154
|
-
}
|
|
4155
|
-
}
|
|
4156
|
-
}
|
|
3889
|
+
/**
|
|
3890
|
+
* @param {string} pluginId
|
|
3891
|
+
*/
|
|
3892
|
+
function runPluginTeardowns(pluginId) {
|
|
3893
|
+
const list = _byPlugin.get(pluginId);
|
|
3894
|
+
if (!list) {
|
|
3895
|
+
return
|
|
3896
|
+
}
|
|
3897
|
+
_byPlugin.delete(pluginId);
|
|
3898
|
+
for (const fn of list) {
|
|
3899
|
+
try {
|
|
3900
|
+
fn();
|
|
3901
|
+
} catch (e) {
|
|
3902
|
+
console.warn('[wep] teardown failed', pluginId, e);
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
4157
3905
|
}
|
|
4158
3906
|
|
|
4159
|
-
/**
|
|
4160
|
-
*
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
*
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
if (
|
|
4181
|
-
|
|
4182
|
-
}
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
}
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
}
|
|
4197
|
-
}
|
|
4198
|
-
registries.slotRevision++;
|
|
4199
|
-
|
|
4200
|
-
if (typeof window !== 'undefined' && window.__PLUGIN_ACTIVATORS__) {
|
|
4201
|
-
delete window.__PLUGIN_ACTIVATORS__[pluginId];
|
|
4202
|
-
}
|
|
4203
|
-
|
|
4204
|
-
if (typeof document !== 'undefined') {
|
|
4205
|
-
document.querySelectorAll('[data-plugin-asset]').forEach((el) => {
|
|
4206
|
-
if (el.getAttribute('data-plugin-asset') === pluginId) {
|
|
4207
|
-
el.remove();
|
|
4208
|
-
}
|
|
4209
|
-
});
|
|
4210
|
-
}
|
|
3907
|
+
/**
|
|
3908
|
+
* 构造插件 `activator(hostApi)` 使用的宿主 API:路由、菜单、扩展点、资源与受控请求桥。
|
|
3909
|
+
*/
|
|
3910
|
+
|
|
3911
|
+
let slotItemKeySeq = 0;
|
|
3912
|
+
let routeSynthSeq = 0;
|
|
3913
|
+
|
|
3914
|
+
/**
|
|
3915
|
+
* @param {unknown[]} nodes
|
|
3916
|
+
*/
|
|
3917
|
+
function analyzeRouteInputTree(nodes) {
|
|
3918
|
+
let hasDecl = false;
|
|
3919
|
+
let hasCfg = false;
|
|
3920
|
+
/** @param {unknown} r */
|
|
3921
|
+
function walk(r) {
|
|
3922
|
+
if (!r || typeof r !== 'object') {
|
|
3923
|
+
return
|
|
3924
|
+
}
|
|
3925
|
+
const o = /** @type {Record<string, unknown>} */ (r);
|
|
3926
|
+
const cfg = o.component != null || o.components != null;
|
|
3927
|
+
const decl = typeof o.componentRef === 'string';
|
|
3928
|
+
if (cfg) {
|
|
3929
|
+
hasCfg = true;
|
|
3930
|
+
} else if (decl) {
|
|
3931
|
+
hasDecl = true;
|
|
3932
|
+
}
|
|
3933
|
+
const ch = o.children;
|
|
3934
|
+
if (Array.isArray(ch)) {
|
|
3935
|
+
for (const c of ch) {
|
|
3936
|
+
walk(c);
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
for (const n of nodes) {
|
|
3941
|
+
walk(n);
|
|
3942
|
+
}
|
|
3943
|
+
return { hasDecl, hasCfg }
|
|
4211
3944
|
}
|
|
4212
3945
|
|
|
4213
3946
|
/**
|
|
4214
|
-
*
|
|
4215
|
-
*
|
|
3947
|
+
* 单插件在宿主侧的 API 句柄。工厂请传 `(id, router, kit) => createHostApi(id, r, kit)` 以便 bridge 白名单等到位。
|
|
3948
|
+
*
|
|
3949
|
+
* @param {string} pluginId
|
|
3950
|
+
* @param {import('vue-router').default} router
|
|
3951
|
+
* @param {Record<string, unknown>} [hostKitOptions] 与 `resolveRuntimeOptions` 中路由/bridge 等字段一致
|
|
3952
|
+
*/
|
|
3953
|
+
function createHostApi(pluginId, router, hostKitOptions = {}) {
|
|
3954
|
+
const bridgePrefixes =
|
|
3955
|
+
Array.isArray(hostKitOptions.bridgeAllowedPathPrefixes) &&
|
|
3956
|
+
hostKitOptions.bridgeAllowedPathPrefixes.length > 0
|
|
3957
|
+
? hostKitOptions.bridgeAllowedPathPrefixes
|
|
3958
|
+
: defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes;
|
|
3959
|
+
const bridge = createRequestBridge({ allowedPathPrefixes: bridgePrefixes });
|
|
3960
|
+
|
|
3961
|
+
const parentName =
|
|
3962
|
+
typeof hostKitOptions.pluginRoutesParentName === 'string'
|
|
3963
|
+
? hostKitOptions.pluginRoutesParentName.trim()
|
|
3964
|
+
: '';
|
|
3965
|
+
|
|
3966
|
+
/** @param {import('vue-router').RouteConfig[]} rawRouteConfigs */
|
|
3967
|
+
function applyInternalRegister(rawRouteConfigs) {
|
|
3968
|
+
const wrapped = rawRouteConfigs.map((r) => ({
|
|
3969
|
+
...r,
|
|
3970
|
+
name: r.name || `__wep_${pluginId}_${routeSynthSeq++}`,
|
|
3971
|
+
meta: { ...(r.meta || {}), pluginId }
|
|
3972
|
+
}));
|
|
3973
|
+
if (typeof router.addRoute === 'function') {
|
|
3974
|
+
if (parentName) {
|
|
3975
|
+
for (const r of wrapped) {
|
|
3976
|
+
router.addRoute(parentName, r);
|
|
3977
|
+
}
|
|
3978
|
+
} else {
|
|
3979
|
+
for (const r of wrapped) {
|
|
3980
|
+
router.addRoute(r);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
} else {
|
|
3984
|
+
if (parentName) {
|
|
3985
|
+
console.warn(
|
|
3986
|
+
'[wep] pluginRoutesParentName requires vue-router 3.5+ addRoute; falling back to top-level addRoutes'
|
|
3987
|
+
);
|
|
3988
|
+
}
|
|
3989
|
+
router.addRoutes(wrapped);
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
function injectStylesheet(href) {
|
|
3994
|
+
const link = document.createElement('link');
|
|
3995
|
+
link.rel = 'stylesheet';
|
|
3996
|
+
link.href = href;
|
|
3997
|
+
link.setAttribute('data-plugin-asset', pluginId);
|
|
3998
|
+
document.head.appendChild(link);
|
|
3999
|
+
}
|
|
4000
|
+
|
|
4001
|
+
/** @param {string} src */
|
|
4002
|
+
function injectScript(src) {
|
|
4003
|
+
return new Promise((resolve, reject) => {
|
|
4004
|
+
const s = document.createElement('script');
|
|
4005
|
+
s.async = true;
|
|
4006
|
+
s.src = src;
|
|
4007
|
+
s.setAttribute('data-plugin-asset', pluginId);
|
|
4008
|
+
s.onload = () => resolve();
|
|
4009
|
+
s.onerror = () => reject(new Error('script failed: ' + src));
|
|
4010
|
+
document.head.appendChild(s);
|
|
4011
|
+
})
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
return {
|
|
4015
|
+
hostPluginApiVersion: HOST_PLUGIN_API_VERSION,
|
|
4016
|
+
|
|
4017
|
+
registerRoutes(routes) {
|
|
4018
|
+
const list = Array.isArray(routes) ? routes : [];
|
|
4019
|
+
if (list.length === 0) {
|
|
4020
|
+
return
|
|
4021
|
+
}
|
|
4022
|
+
const { hasDecl, hasCfg } = analyzeRouteInputTree(list);
|
|
4023
|
+
if (hasDecl && hasCfg) {
|
|
4024
|
+
throw new Error(
|
|
4025
|
+
'[wep] registerRoutes: cannot mix RouteDeclaration (componentRef) with RouteConfig (component)'
|
|
4026
|
+
)
|
|
4027
|
+
}
|
|
4028
|
+
let /** @type {import('vue-router').RouteConfig[]} */ configs;
|
|
4029
|
+
if (hasDecl) {
|
|
4030
|
+
const adapt = hostKitOptions.adaptRouteDeclarations;
|
|
4031
|
+
if (typeof adapt !== 'function') {
|
|
4032
|
+
throw new Error(
|
|
4033
|
+
'[wep] registerRoutes: RouteDeclaration (componentRef) requires adaptRouteDeclarations on the host'
|
|
4034
|
+
)
|
|
4035
|
+
}
|
|
4036
|
+
configs = adapt({
|
|
4037
|
+
pluginId,
|
|
4038
|
+
router,
|
|
4039
|
+
declarations: /** @type {unknown[]} */ (list)
|
|
4040
|
+
});
|
|
4041
|
+
} else {
|
|
4042
|
+
configs = /** @type {import('vue-router').RouteConfig[]} */ (/** @type {unknown} */ (list));
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
if (typeof hostKitOptions.transformRoutes === 'function') {
|
|
4046
|
+
configs = hostKitOptions.transformRoutes({
|
|
4047
|
+
pluginId,
|
|
4048
|
+
router,
|
|
4049
|
+
routes: configs
|
|
4050
|
+
});
|
|
4051
|
+
}
|
|
4052
|
+
|
|
4053
|
+
if (typeof hostKitOptions.interceptRegisterRoutes === 'function') {
|
|
4054
|
+
hostKitOptions.interceptRegisterRoutes({
|
|
4055
|
+
pluginId,
|
|
4056
|
+
router,
|
|
4057
|
+
routes: configs,
|
|
4058
|
+
applyInternalRegister
|
|
4059
|
+
});
|
|
4060
|
+
} else {
|
|
4061
|
+
applyInternalRegister(configs);
|
|
4062
|
+
}
|
|
4063
|
+
},
|
|
4064
|
+
|
|
4065
|
+
registerMenuItems(items) {
|
|
4066
|
+
for (const item of items) {
|
|
4067
|
+
registries.menus.push({ ...item, pluginId });
|
|
4068
|
+
}
|
|
4069
|
+
registries.menus.sort(
|
|
4070
|
+
(a, b) => (a.order != null ? a.order : 0) - (b.order != null ? b.order : 0)
|
|
4071
|
+
);
|
|
4072
|
+
},
|
|
4073
|
+
|
|
4074
|
+
registerSlotComponents(pointId, components) {
|
|
4075
|
+
if (!pointId) {
|
|
4076
|
+
return
|
|
4077
|
+
}
|
|
4078
|
+
if (!registries.slots[pointId]) {
|
|
4079
|
+
Vue__default.default.set(registries.slots, pointId, []);
|
|
4080
|
+
}
|
|
4081
|
+
const list = registries.slots[pointId];
|
|
4082
|
+
for (const c of components) {
|
|
4083
|
+
list.push({
|
|
4084
|
+
pluginId,
|
|
4085
|
+
component: c.component,
|
|
4086
|
+
priority: c.priority != null ? c.priority : 0,
|
|
4087
|
+
key: `${pluginId}-${pointId}-${++slotItemKeySeq}`
|
|
4088
|
+
});
|
|
4089
|
+
}
|
|
4090
|
+
list.sort((a, b) => b.priority - a.priority);
|
|
4091
|
+
registries.slotRevision++;
|
|
4092
|
+
},
|
|
4093
|
+
|
|
4094
|
+
registerStylesheetUrls(urls) {
|
|
4095
|
+
for (const u of urls || []) {
|
|
4096
|
+
if (typeof u === 'string' && u) {
|
|
4097
|
+
injectStylesheet(u);
|
|
4098
|
+
}
|
|
4099
|
+
}
|
|
4100
|
+
},
|
|
4101
|
+
|
|
4102
|
+
registerScriptUrls(urls) {
|
|
4103
|
+
const chain = (urls || []).filter((u) => typeof u === 'string' && u).reduce(
|
|
4104
|
+
(p, u) => p.then(() => injectScript(u)),
|
|
4105
|
+
Promise.resolve()
|
|
4106
|
+
);
|
|
4107
|
+
chain.catch((e) => console.warn('[wep] registerScriptUrls', pluginId, e));
|
|
4108
|
+
},
|
|
4109
|
+
|
|
4110
|
+
registerSanitizedHtmlSnippet() {
|
|
4111
|
+
throw new Error('registerSanitizedHtmlSnippet is not enabled')
|
|
4112
|
+
},
|
|
4113
|
+
|
|
4114
|
+
getBridge: () => bridge,
|
|
4115
|
+
|
|
4116
|
+
onTeardown(_pluginId, fn) {
|
|
4117
|
+
if (typeof fn === 'function') {
|
|
4118
|
+
registerPluginTeardown(pluginId, fn);
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
/**
|
|
4125
|
+
* 卸载单个插件:执行 teardown、清理注册表与 activator、移除带 `data-plugin-asset` 的 DOM。
|
|
4126
|
+
* 注意:Vue Router 3 无公开 `removeRoute`,动态路由通常需整页刷新或宿主自行维护。
|
|
4127
|
+
*/
|
|
4128
|
+
|
|
4129
|
+
/**
|
|
4130
|
+
* @param {string} pluginId 与 manifest `id` 一致
|
|
4131
|
+
*/
|
|
4132
|
+
function disposeWebPlugin(pluginId) {
|
|
4133
|
+
if (!pluginId || typeof pluginId !== 'string') {
|
|
4134
|
+
return
|
|
4135
|
+
}
|
|
4136
|
+
|
|
4137
|
+
runPluginTeardowns(pluginId);
|
|
4138
|
+
|
|
4139
|
+
for (let i = registries.menus.length - 1; i >= 0; i--) {
|
|
4140
|
+
if (registries.menus[i].pluginId === pluginId) {
|
|
4141
|
+
registries.menus.splice(i, 1);
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
const slots = registries.slots;
|
|
4146
|
+
for (const pointId of Object.keys(slots)) {
|
|
4147
|
+
const list = slots[pointId];
|
|
4148
|
+
if (!Array.isArray(list)) {
|
|
4149
|
+
continue
|
|
4150
|
+
}
|
|
4151
|
+
const next = list.filter((x) => x.pluginId !== pluginId);
|
|
4152
|
+
if (next.length === 0) {
|
|
4153
|
+
Vue__default.default.delete(slots, pointId);
|
|
4154
|
+
} else if (next.length !== list.length) {
|
|
4155
|
+
Vue__default.default.set(slots, pointId, next);
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
registries.slotRevision++;
|
|
4159
|
+
|
|
4160
|
+
if (typeof window !== 'undefined' && window.__PLUGIN_ACTIVATORS__) {
|
|
4161
|
+
delete window.__PLUGIN_ACTIVATORS__[pluginId];
|
|
4162
|
+
}
|
|
4163
|
+
|
|
4164
|
+
if (typeof document !== 'undefined') {
|
|
4165
|
+
document.querySelectorAll('[data-plugin-asset]').forEach((el) => {
|
|
4166
|
+
if (el.getAttribute('data-plugin-asset') === pluginId) {
|
|
4167
|
+
el.remove();
|
|
4168
|
+
}
|
|
4169
|
+
});
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
/**
|
|
4174
|
+
* 布局中的扩展点占位;插件通过 `hostApi.registerSlotComponents(pointId, ...)` 注入组件。
|
|
4216
4175
|
*/
|
|
4217
4176
|
|
|
4218
4177
|
const SlotErrorBoundary = {
|
|
@@ -4223,7 +4182,7 @@ const SlotErrorBoundary = {
|
|
|
4223
4182
|
},
|
|
4224
4183
|
errorCaptured(err) {
|
|
4225
4184
|
this.error = err && err.message ? err.message : String(err);
|
|
4226
|
-
console.error('[ExtensionPoint]
|
|
4185
|
+
console.error('[wep:ExtensionPoint]', this.label, err);
|
|
4227
4186
|
return false
|
|
4228
4187
|
},
|
|
4229
4188
|
render(h) {
|
|
@@ -4278,17 +4237,13 @@ var ExtensionPoint = {
|
|
|
4278
4237
|
};
|
|
4279
4238
|
|
|
4280
4239
|
/**
|
|
4281
|
-
*
|
|
4282
|
-
* @module install
|
|
4240
|
+
* 注册全局 `ExtensionPoint` 并异步拉取清单、激活插件。
|
|
4283
4241
|
*/
|
|
4284
4242
|
|
|
4285
4243
|
/**
|
|
4286
|
-
* 注册全局组件 `ExtensionPoint` 并异步引导插件清单。
|
|
4287
|
-
*
|
|
4288
4244
|
* @param {*} Vue
|
|
4289
|
-
* @param {*} router
|
|
4290
|
-
* @param {Record<string, unknown>} [options] 传给 `resolveRuntimeOptions
|
|
4291
|
-
* @returns {Promise<void>}
|
|
4245
|
+
* @param {*} router
|
|
4246
|
+
* @param {Record<string, unknown>} [options] 传给 `resolveRuntimeOptions`;可含 `env` 以读取 `VITE_*`
|
|
4292
4247
|
*/
|
|
4293
4248
|
function installWebExtendPluginVue2(Vue, router, options) {
|
|
4294
4249
|
const opts = options || {};
|
|
@@ -4304,23 +4259,20 @@ function installWebExtendPluginVue2(Vue, router, options) {
|
|
|
4304
4259
|
}
|
|
4305
4260
|
|
|
4306
4261
|
/**
|
|
4307
|
-
*
|
|
4308
|
-
* 对外以 {@link presetVueCliAxios} 聚合;亦保留具名函数便于 tree-shaking。
|
|
4309
|
-
*
|
|
4310
|
-
* @module presets/vue-cli-axios
|
|
4262
|
+
* Vue CLI + 统一 axios(如 RuoYi `utils/request`)场景的 `install` 预设。
|
|
4311
4263
|
*/
|
|
4312
4264
|
|
|
4313
4265
|
/**
|
|
4314
|
-
* @typedef {object}
|
|
4315
|
-
* @property {(config: { url: string, method?: string
|
|
4266
|
+
* @typedef {object} VueCliAxiosPresetDeps
|
|
4267
|
+
* @property {(config: { url: string, method?: string }) => Promise<unknown>} request
|
|
4316
4268
|
*/
|
|
4317
4269
|
|
|
4318
4270
|
/**
|
|
4319
|
-
*
|
|
4271
|
+
* 将完整 manifest URL 转为相对 `apiBase` 的请求 path,供 axios `baseURL` 拼接。
|
|
4320
4272
|
* @param {string} manifestUrl
|
|
4321
4273
|
* @param {string} [apiBase]
|
|
4322
4274
|
*/
|
|
4323
|
-
function
|
|
4275
|
+
function resolveManifestPathUnderApiBase(manifestUrl, apiBase) {
|
|
4324
4276
|
const base = String(
|
|
4325
4277
|
apiBase !== undefined
|
|
4326
4278
|
? apiBase
|
|
@@ -4338,11 +4290,11 @@ function manifestPathForVueCliApiBase(manifestUrl, apiBase) {
|
|
|
4338
4290
|
}
|
|
4339
4291
|
|
|
4340
4292
|
/**
|
|
4341
|
-
*
|
|
4293
|
+
* 将裸 `{ plugins }` 与 `{ code, data: { plugins } }` 式响应解包为清单对象。
|
|
4342
4294
|
* @param {unknown} body
|
|
4343
4295
|
* @returns {object|null}
|
|
4344
4296
|
*/
|
|
4345
|
-
function
|
|
4297
|
+
function unwrapNestedManifestBody(body) {
|
|
4346
4298
|
if (!body || typeof body !== 'object') {
|
|
4347
4299
|
return null
|
|
4348
4300
|
}
|
|
@@ -4374,15 +4326,13 @@ function bridgePrefixesFromVueCliEnv() {
|
|
|
4374
4326
|
}
|
|
4375
4327
|
|
|
4376
4328
|
/**
|
|
4377
|
-
*
|
|
4378
|
-
* @param {
|
|
4379
|
-
* @param {Record<string, unknown>} [extra] 合并覆盖,如 `manifestListPath`、`env` 等
|
|
4380
|
-
* @returns {Record<string, unknown>}
|
|
4329
|
+
* @param {VueCliAxiosPresetDeps} deps
|
|
4330
|
+
* @param {Record<string, unknown>} [extra]
|
|
4381
4331
|
*/
|
|
4382
4332
|
function createVueCliAxiosInstallOptions(deps, extra = {}) {
|
|
4383
4333
|
const { request } = deps;
|
|
4384
4334
|
if (typeof request !== 'function') {
|
|
4385
|
-
throw new Error('[
|
|
4335
|
+
throw new Error('[wep] createVueCliAxiosInstallOptions requires deps.request')
|
|
4386
4336
|
}
|
|
4387
4337
|
const envBase = (
|
|
4388
4338
|
typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API
|
|
@@ -4397,16 +4347,16 @@ function createVueCliAxiosInstallOptions(deps, extra = {}) {
|
|
|
4397
4347
|
|
|
4398
4348
|
const fetchManifest = async (ctx) => {
|
|
4399
4349
|
try {
|
|
4400
|
-
const url =
|
|
4350
|
+
const url = resolveManifestPathUnderApiBase(ctx.manifestUrl, stripBase);
|
|
4401
4351
|
const body = await request({
|
|
4402
4352
|
url,
|
|
4403
4353
|
method: 'get'
|
|
4404
4354
|
});
|
|
4405
|
-
const data =
|
|
4355
|
+
const data = unwrapNestedManifestBody(body);
|
|
4406
4356
|
if (!data || typeof data !== 'object') {
|
|
4407
4357
|
return {
|
|
4408
4358
|
ok: false,
|
|
4409
|
-
error: new Error('[
|
|
4359
|
+
error: new Error('[wep] invalid manifest response'),
|
|
4410
4360
|
data: null
|
|
4411
4361
|
}
|
|
4412
4362
|
}
|
|
@@ -4432,28 +4382,18 @@ function createVueCliAxiosInstallOptions(deps, extra = {}) {
|
|
|
4432
4382
|
return opts
|
|
4433
4383
|
}
|
|
4434
4384
|
|
|
4435
|
-
/**
|
|
4436
|
-
* Vue CLI + axios 预设的**对外聚合入口**(与具名导出函数等价,便于按需查阅与扩展多预设)。
|
|
4437
|
-
* @type {Readonly<{ id: string, description: string, createInstallOptions: typeof createVueCliAxiosInstallOptions, manifestPathForApiBase: typeof manifestPathForVueCliApiBase, unwrapManifestBody: typeof unwrapTableStyleManifestBody }>}
|
|
4438
|
-
*/
|
|
4439
4385
|
const presetVueCliAxios = Object.freeze({
|
|
4440
4386
|
id: 'vue-cli-axios',
|
|
4441
|
-
description: 'Vue CLI +
|
|
4387
|
+
description: 'Vue CLI + unified axios request; manifest uses host request()',
|
|
4442
4388
|
createInstallOptions: createVueCliAxiosInstallOptions,
|
|
4443
|
-
manifestPathForApiBase:
|
|
4444
|
-
unwrapManifestBody:
|
|
4389
|
+
manifestPathForApiBase: resolveManifestPathUnderApiBase,
|
|
4390
|
+
unwrapManifestBody: unwrapNestedManifestBody
|
|
4445
4391
|
});
|
|
4446
4392
|
|
|
4447
4393
|
/**
|
|
4448
|
-
*
|
|
4449
|
-
* 语义化版本内保持本文件导出的符号与聚合结构兼容。
|
|
4450
|
-
*
|
|
4451
|
-
* `PluginRuntime` 与 `manifest-fetch-composer` 通过 namespace 绑定到 `WebExtendPluginVue2.runtime`,避免具名导出与聚合对象重复列举。
|
|
4452
|
-
*
|
|
4453
|
-
* @module public
|
|
4394
|
+
* 包对外稳定导出与 `WebExtendPluginVue2` 命名空间。
|
|
4454
4395
|
*/
|
|
4455
4396
|
|
|
4456
|
-
|
|
4457
4397
|
const {
|
|
4458
4398
|
bootstrapPlugins,
|
|
4459
4399
|
defaultFetchWebPluginManifest,
|
|
@@ -4466,18 +4406,6 @@ const {
|
|
|
4466
4406
|
wrapManifestFetchWithCache
|
|
4467
4407
|
} = manifestComposer;
|
|
4468
4408
|
|
|
4469
|
-
/**
|
|
4470
|
-
* 根命名空间:宿主可通过 `WebExtendPluginVue2.presets.vueCliAxios` 等路径发现能力,避免仅依赖散落的具名导出。
|
|
4471
|
-
* @type {Readonly<{
|
|
4472
|
-
* install: typeof installWebExtendPluginVue2,
|
|
4473
|
-
* runtime: Readonly<{ bootstrapPlugins: typeof pluginRuntime.bootstrapPlugins, resolveRuntimeOptions: typeof pluginRuntime.resolveRuntimeOptions, defaultFetchWebPluginManifest: typeof pluginRuntime.defaultFetchWebPluginManifest, composeManifestFetch: typeof manifestComposer.composeManifestFetch, manifestFetchCacheMiddleware: typeof manifestComposer.manifestFetchCacheMiddleware, wrapManifestFetchWithCache: typeof manifestComposer.wrapManifestFetchWithCache }>,
|
|
4474
|
-
* host: Readonly<{ createHostApi: typeof createHostApi, disposeWebPlugin: typeof disposeWebPlugin, createRequestBridge: typeof createRequestBridge, registries: typeof registries }>,
|
|
4475
|
-
* config: Readonly<{ defaultWebExtendPluginRuntime: typeof defaultWebExtendPluginRuntime, setWebExtendPluginEnv: typeof setWebExtendPluginEnv }>,
|
|
4476
|
-
* constants: Readonly<{ HOST_PLUGIN_API_VERSION: typeof HOST_PLUGIN_API_VERSION }>,
|
|
4477
|
-
* components: Readonly<{ ExtensionPoint: typeof ExtensionPoint }>,
|
|
4478
|
-
* presets: Readonly<{ vueCliAxios: typeof presetVueCliAxios }>
|
|
4479
|
-
* }>}
|
|
4480
|
-
*/
|
|
4481
4409
|
const WebExtendPluginVue2 = Object.freeze({
|
|
4482
4410
|
install: installWebExtendPluginVue2,
|
|
4483
4411
|
runtime: Object.freeze({
|
|
@@ -4499,7 +4427,8 @@ const WebExtendPluginVue2 = Object.freeze({
|
|
|
4499
4427
|
setWebExtendPluginEnv
|
|
4500
4428
|
}),
|
|
4501
4429
|
constants: Object.freeze({
|
|
4502
|
-
HOST_PLUGIN_API_VERSION
|
|
4430
|
+
HOST_PLUGIN_API_VERSION,
|
|
4431
|
+
RUNTIME_CONSOLE_LABEL
|
|
4503
4432
|
}),
|
|
4504
4433
|
components: Object.freeze({
|
|
4505
4434
|
ExtensionPoint
|
|
@@ -4511,6 +4440,7 @@ const WebExtendPluginVue2 = Object.freeze({
|
|
|
4511
4440
|
|
|
4512
4441
|
exports.ExtensionPoint = ExtensionPoint;
|
|
4513
4442
|
exports.HOST_PLUGIN_API_VERSION = HOST_PLUGIN_API_VERSION;
|
|
4443
|
+
exports.RUNTIME_CONSOLE_LABEL = RUNTIME_CONSOLE_LABEL;
|
|
4514
4444
|
exports.WebExtendPluginVue2 = WebExtendPluginVue2;
|
|
4515
4445
|
exports.bootstrapPlugins = bootstrapPlugins;
|
|
4516
4446
|
exports.composeManifestFetch = composeManifestFetch;
|
|
@@ -4522,11 +4452,11 @@ exports.defaultWebExtendPluginRuntime = defaultWebExtendPluginRuntime;
|
|
|
4522
4452
|
exports.disposeWebPlugin = disposeWebPlugin;
|
|
4523
4453
|
exports.installWebExtendPluginVue2 = installWebExtendPluginVue2;
|
|
4524
4454
|
exports.manifestFetchCacheMiddleware = manifestFetchCacheMiddleware;
|
|
4525
|
-
exports.manifestPathForVueCliApiBase = manifestPathForVueCliApiBase;
|
|
4526
4455
|
exports.presetVueCliAxios = presetVueCliAxios;
|
|
4527
4456
|
exports.registries = registries;
|
|
4457
|
+
exports.resolveManifestPathUnderApiBase = resolveManifestPathUnderApiBase;
|
|
4528
4458
|
exports.resolveRuntimeOptions = resolveRuntimeOptions;
|
|
4529
4459
|
exports.setWebExtendPluginEnv = setWebExtendPluginEnv;
|
|
4530
|
-
exports.
|
|
4460
|
+
exports.unwrapNestedManifestBody = unwrapNestedManifestBody;
|
|
4531
4461
|
exports.wrapManifestFetchWithCache = wrapManifestFetchWithCache;
|
|
4532
4462
|
//# sourceMappingURL=index.cjs.map
|