web-extend-plugin-vue2 0.2.1 → 0.2.2
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 +111 -0
- package/dist/index.cjs +996 -500
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +988 -501
- package/dist/index.mjs.map +1 -1
- package/index.d.ts +126 -0
- package/package.json +5 -2
package/dist/index.cjs
CHANGED
|
@@ -65,115 +65,490 @@ const defaultWebExtendPluginRuntime = {
|
|
|
65
65
|
bridgeAllowedPathPrefixes: ['/api/']
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
/**
|
|
69
|
+
* 不依赖 `import.meta`,兼容 Webpack 4/5、Vue CLI、Vite、Rspack 等宿主。
|
|
70
|
+
* - Webpack / Vue CLI:依赖构建时注入的 `process.env`(如 `VUE_APP_*`、`DefinePlugin` 注入的 `VITE_*`)。
|
|
71
|
+
* - Vite:在入口调用 `setWebExtendPluginEnv(import.meta.env)`,或 `installWebExtendPluginVue2(..., { env: import.meta.env })`。
|
|
72
|
+
* - 也可在入口前设置 `globalThis.__WEP_ENV__ = import.meta.env`(与 setWebExtendPluginEnv 二选一即可)。
|
|
73
|
+
*
|
|
74
|
+
* @module bundled-env
|
|
75
|
+
*/
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
/** @type {Record<string, unknown> | null} */
|
|
78
|
+
let _explicitEnv = null;
|
|
76
79
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
/**
|
|
81
|
+
* 显式注入与 `import.meta.env` 同形态的对象(推荐 Vite 宿主在入口调用一次)。
|
|
82
|
+
* @param {Record<string, unknown> | null | undefined} env
|
|
83
|
+
*/
|
|
84
|
+
function setWebExtendPluginEnv(env) {
|
|
85
|
+
_explicitEnv = env && typeof env === 'object' ? env : null;
|
|
86
|
+
}
|
|
80
87
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
/**
|
|
89
|
+
* @returns {Record<string, unknown> | null}
|
|
90
|
+
*/
|
|
91
|
+
function getInjectedEnvObject() {
|
|
92
|
+
if (_explicitEnv) {
|
|
93
|
+
return _explicitEnv
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const g = typeof globalThis !== 'undefined' ? globalThis : undefined;
|
|
97
|
+
if (g && g.__WEP_ENV__ && typeof g.__WEP_ENV__ === 'object') {
|
|
98
|
+
return g.__WEP_ENV__
|
|
99
|
+
}
|
|
100
|
+
} catch (_) {}
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
84
103
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
/**
|
|
105
|
+
* 从注入环境读取字符串配置键(`VITE_*` / `PLUGIN_*` 等)。
|
|
106
|
+
* @param {string} key
|
|
107
|
+
* @returns {string|undefined}
|
|
108
|
+
*/
|
|
109
|
+
function readInjectedEnvKey(key) {
|
|
110
|
+
const o = getInjectedEnvObject();
|
|
111
|
+
if (!o || !(key in o)) {
|
|
112
|
+
return undefined
|
|
113
|
+
}
|
|
114
|
+
const v = o[key];
|
|
115
|
+
if (v === undefined || v === '') {
|
|
116
|
+
return undefined
|
|
117
|
+
}
|
|
118
|
+
return String(v)
|
|
119
|
+
}
|
|
88
120
|
|
|
89
|
-
|
|
90
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @returns {boolean}
|
|
123
|
+
*/
|
|
124
|
+
function readInjectedEnvDev() {
|
|
125
|
+
const o = getInjectedEnvObject();
|
|
126
|
+
return !!(o && o.DEV === true)
|
|
127
|
+
}
|
|
91
128
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
129
|
+
/**
|
|
130
|
+
* 从注入环境与 `process.env` 解析 VITE_/PLUGIN_ 键。
|
|
131
|
+
* @module runtime/env-resolve
|
|
132
|
+
*/
|
|
95
133
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
134
|
+
/**
|
|
135
|
+
* @param {string} key
|
|
136
|
+
* @returns {string|undefined}
|
|
137
|
+
*/
|
|
138
|
+
function readProcessEnv(key) {
|
|
139
|
+
try {
|
|
140
|
+
if (typeof process !== 'undefined' && process.env && key in process.env) {
|
|
141
|
+
const v = process.env[key];
|
|
142
|
+
if (v !== undefined && v !== '') {
|
|
143
|
+
return String(v)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch (_) {}
|
|
147
|
+
return undefined
|
|
148
|
+
}
|
|
105
149
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
};
|
|
116
|
-
return constants;
|
|
150
|
+
/**
|
|
151
|
+
* @param {string} viteStyleKey
|
|
152
|
+
* @returns {string|null}
|
|
153
|
+
*/
|
|
154
|
+
function viteKeyToPluginAlternate(viteStyleKey) {
|
|
155
|
+
if (typeof viteStyleKey !== 'string' || !viteStyleKey.startsWith('VITE_')) {
|
|
156
|
+
return null
|
|
157
|
+
}
|
|
158
|
+
return `PLUGIN_${viteStyleKey.slice(5)}`
|
|
117
159
|
}
|
|
118
160
|
|
|
119
|
-
|
|
120
|
-
|
|
161
|
+
/**
|
|
162
|
+
* @param {string} key
|
|
163
|
+
* @param {string} [fallback='']
|
|
164
|
+
*/
|
|
165
|
+
function resolveBundledEnv(key, fallback = '') {
|
|
166
|
+
const alt = viteKeyToPluginAlternate(key);
|
|
167
|
+
const inj = readInjectedEnvKey(key);
|
|
168
|
+
const fromInjected =
|
|
169
|
+
inj === undefined || inj === null ? (alt ? readInjectedEnvKey(alt) : undefined) : inj;
|
|
170
|
+
const proc = readProcessEnv(key);
|
|
171
|
+
const fromProcess =
|
|
172
|
+
proc === undefined || proc === null ? (alt ? readProcessEnv(alt) : undefined) : proc;
|
|
173
|
+
const first = fromInjected === undefined || fromInjected === null ? fromProcess : fromInjected;
|
|
174
|
+
return first === undefined || first === null ? fallback : first
|
|
175
|
+
}
|
|
121
176
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
177
|
+
/**
|
|
178
|
+
* @returns {boolean}
|
|
179
|
+
*/
|
|
180
|
+
function resolveBundledIsDev() {
|
|
181
|
+
try {
|
|
182
|
+
if (readInjectedEnvDev()) {
|
|
183
|
+
return true
|
|
184
|
+
}
|
|
185
|
+
} catch (_) {}
|
|
186
|
+
try {
|
|
187
|
+
if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development') {
|
|
188
|
+
return true
|
|
189
|
+
}
|
|
190
|
+
} catch (_) {}
|
|
191
|
+
return false
|
|
192
|
+
}
|
|
125
193
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
/\bsemver\b/i.test(process.env.NODE_DEBUG)
|
|
131
|
-
) ? (...args) => console.error('SEMVER', ...args)
|
|
132
|
-
: () => {};
|
|
194
|
+
/**
|
|
195
|
+
* 路径与脚本主机名校验工具。
|
|
196
|
+
* @module runtime/path-host-utils
|
|
197
|
+
*/
|
|
133
198
|
|
|
134
|
-
|
|
135
|
-
|
|
199
|
+
/**
|
|
200
|
+
* @param {string} p
|
|
201
|
+
*/
|
|
202
|
+
function ensureLeadingPath(p) {
|
|
203
|
+
const t = String(p || '').trim();
|
|
204
|
+
if (!t) {
|
|
205
|
+
return '/'
|
|
206
|
+
}
|
|
207
|
+
return t.startsWith('/') ? t : `/${t}`
|
|
136
208
|
}
|
|
137
209
|
|
|
138
|
-
|
|
210
|
+
/**
|
|
211
|
+
* @param {string} hostname
|
|
212
|
+
*/
|
|
213
|
+
function normalizeHost(hostname) {
|
|
214
|
+
if (!hostname) {
|
|
215
|
+
return ''
|
|
216
|
+
}
|
|
217
|
+
const h = hostname.toLowerCase();
|
|
218
|
+
if (h.startsWith('[') && h.endsWith(']')) {
|
|
219
|
+
return h.slice(1, -1)
|
|
220
|
+
}
|
|
221
|
+
return h
|
|
222
|
+
}
|
|
139
223
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
224
|
+
/**
|
|
225
|
+
* @param {string[]} hostnames
|
|
226
|
+
* @returns {Set<string>}
|
|
227
|
+
*/
|
|
228
|
+
function buildAllowedScriptHostsSet(hostnames) {
|
|
229
|
+
const s = new Set();
|
|
230
|
+
for (const h of hostnames) {
|
|
231
|
+
const n = normalizeHost(h);
|
|
232
|
+
if (n) {
|
|
233
|
+
s.add(n);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return s
|
|
237
|
+
}
|
|
144
238
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
239
|
+
/**
|
|
240
|
+
* @param {string} url
|
|
241
|
+
* @param {Set<string>} hostSet
|
|
242
|
+
*/
|
|
243
|
+
function isScriptHostAllowed(url, hostSet) {
|
|
244
|
+
if (typeof window === 'undefined') {
|
|
245
|
+
return false
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
const u = new URL(url, window.location.origin);
|
|
249
|
+
const h = normalizeHost(u.hostname);
|
|
250
|
+
return hostSet.has(h)
|
|
251
|
+
} catch {
|
|
252
|
+
return false
|
|
253
|
+
}
|
|
254
|
+
}
|
|
152
255
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const safeSrc = exports$1.safeSrc = [];
|
|
158
|
-
const t = exports$1.t = {};
|
|
159
|
-
let R = 0;
|
|
256
|
+
/**
|
|
257
|
+
* 合并用户、环境与默认配置得到运行时选项。
|
|
258
|
+
* @module runtime/resolve-runtime-options
|
|
259
|
+
*/
|
|
160
260
|
|
|
161
|
-
const LETTERDASHNUMBER = '[a-zA-Z0-9-]';
|
|
162
261
|
|
|
163
|
-
|
|
164
|
-
// used internally via the safeRe object since all inputs in this library get
|
|
165
|
-
// normalized first to trim and collapse all extra whitespace. The original
|
|
166
|
-
// regexes are exported for userland consumption and lower level usage. A
|
|
167
|
-
// future breaking change could export the safer regex only with a note that
|
|
168
|
-
// all input should have extra whitespace removed.
|
|
169
|
-
const safeRegexReplacements = [
|
|
170
|
-
['\\s', 1],
|
|
171
|
-
['\\d', MAX_LENGTH],
|
|
172
|
-
[LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
|
|
173
|
-
];
|
|
262
|
+
const DEF = defaultWebExtendPluginRuntime;
|
|
174
263
|
|
|
175
|
-
|
|
176
|
-
|
|
264
|
+
/**
|
|
265
|
+
* @param {string|undefined} userVal
|
|
266
|
+
* @param {string} envKey
|
|
267
|
+
* @param {RequestCredentials} fallback
|
|
268
|
+
*/
|
|
269
|
+
function resolveManifestCredentials(userVal, envKey, fallback) {
|
|
270
|
+
if (userVal !== undefined && userVal !== '') {
|
|
271
|
+
const s = String(userVal);
|
|
272
|
+
if (s === 'include' || s === 'omit' || s === 'same-origin') {
|
|
273
|
+
return s
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const e = resolveBundledEnv(envKey, '');
|
|
277
|
+
if (e === 'include' || e === 'omit' || e === 'same-origin') {
|
|
278
|
+
return e
|
|
279
|
+
}
|
|
280
|
+
return fallback
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @param {number|undefined} userVal
|
|
285
|
+
* @param {string} envKey
|
|
286
|
+
* @param {number} fallback
|
|
287
|
+
*/
|
|
288
|
+
function resolvePositiveInt(userVal, envKey, fallback) {
|
|
289
|
+
if (typeof userVal === 'number' && Number.isFinite(userVal) && userVal > 0) {
|
|
290
|
+
return Math.floor(userVal)
|
|
291
|
+
}
|
|
292
|
+
const raw = resolveBundledEnv(envKey, '');
|
|
293
|
+
const n = raw ? parseInt(raw, 10) : NaN;
|
|
294
|
+
if (Number.isFinite(n) && n > 0) {
|
|
295
|
+
return n
|
|
296
|
+
}
|
|
297
|
+
return fallback
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* 合并用户、环境变量与 `defaultWebExtendPluginRuntime`,得到完整运行时选项(宿主可只传需要覆盖的字段)。
|
|
302
|
+
* @param {WebExtendPluginRuntimeOptions} [user]
|
|
303
|
+
* @returns {object}
|
|
304
|
+
*/
|
|
305
|
+
function resolveRuntimeOptions$1(user = {}) {
|
|
306
|
+
const manifestBaseRaw =
|
|
307
|
+
user.manifestBase !== undefined && user.manifestBase !== ''
|
|
308
|
+
? String(user.manifestBase)
|
|
309
|
+
: resolveBundledEnv('VITE_FRONTEND_PLUGIN_BASE', DEF.manifestBase) || DEF.manifestBase;
|
|
310
|
+
|
|
311
|
+
const manifestListPath = ensureLeadingPath(
|
|
312
|
+
user.manifestListPath !== undefined && user.manifestListPath !== ''
|
|
313
|
+
? user.manifestListPath
|
|
314
|
+
: resolveBundledEnv('VITE_WEB_PLUGIN_MANIFEST_PATH', DEF.manifestListPath)
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const defaultImplicitDevPluginIds = Array.isArray(user.defaultImplicitDevPluginIds)
|
|
318
|
+
? user.defaultImplicitDevPluginIds.map(String).filter(Boolean)
|
|
319
|
+
: (() => {
|
|
320
|
+
const e = resolveBundledEnv('VITE_WEB_PLUGIN_IMPLICIT_DEV_IDS', '');
|
|
321
|
+
if (e) {
|
|
322
|
+
return e
|
|
323
|
+
.split(',')
|
|
324
|
+
.map((s) => s.trim())
|
|
325
|
+
.filter(Boolean)
|
|
326
|
+
}
|
|
327
|
+
return [...DEF.defaultImplicitDevPluginIds]
|
|
328
|
+
})();
|
|
329
|
+
|
|
330
|
+
const allowedScriptHosts =
|
|
331
|
+
Array.isArray(user.allowedScriptHosts) && user.allowedScriptHosts.length > 0
|
|
332
|
+
? user.allowedScriptHosts.map((h) => normalizeHost(String(h))).filter(Boolean)
|
|
333
|
+
: (() => {
|
|
334
|
+
const e = resolveBundledEnv('VITE_WEB_PLUGIN_ALLOWED_SCRIPT_HOSTS', '');
|
|
335
|
+
if (e) {
|
|
336
|
+
return e
|
|
337
|
+
.split(',')
|
|
338
|
+
.map((s) => normalizeHost(s.trim()))
|
|
339
|
+
.filter(Boolean)
|
|
340
|
+
}
|
|
341
|
+
return [...DEF.allowedScriptHosts]
|
|
342
|
+
})();
|
|
343
|
+
|
|
344
|
+
const bridgeAllowedPathPrefixes =
|
|
345
|
+
Array.isArray(user.bridgeAllowedPathPrefixes) && user.bridgeAllowedPathPrefixes.length > 0
|
|
346
|
+
? user.bridgeAllowedPathPrefixes.map((p) => ensureLeadingPath(p)).filter(Boolean)
|
|
347
|
+
: (() => {
|
|
348
|
+
const e = resolveBundledEnv('VITE_WEB_PLUGIN_BRIDGE_PREFIXES', '');
|
|
349
|
+
if (e) {
|
|
350
|
+
return e
|
|
351
|
+
.split(',')
|
|
352
|
+
.map((s) => ensureLeadingPath(s.trim()))
|
|
353
|
+
.filter(Boolean)
|
|
354
|
+
}
|
|
355
|
+
return [...DEF.bridgeAllowedPathPrefixes]
|
|
356
|
+
})();
|
|
357
|
+
|
|
358
|
+
return {
|
|
359
|
+
manifestBase: manifestBaseRaw.replace(/\/$/, '') || DEF.manifestBase.replace(/\/$/, ''),
|
|
360
|
+
manifestListPath,
|
|
361
|
+
manifestFetchCredentials: resolveManifestCredentials(
|
|
362
|
+
user.manifestFetchCredentials,
|
|
363
|
+
'VITE_WEB_PLUGIN_MANIFEST_CREDENTIALS',
|
|
364
|
+
DEF.manifestFetchCredentials
|
|
365
|
+
),
|
|
366
|
+
isDev: user.isDev !== undefined ? user.isDev : resolveBundledIsDev(),
|
|
367
|
+
webPluginDevOrigin:
|
|
368
|
+
user.webPluginDevOrigin !== undefined ? user.webPluginDevOrigin : resolveBundledEnv('VITE_WEB_PLUGIN_DEV_ORIGIN', ''),
|
|
369
|
+
webPluginDevIds:
|
|
370
|
+
user.webPluginDevIds !== undefined ? user.webPluginDevIds : resolveBundledEnv('VITE_WEB_PLUGIN_DEV_IDS', ''),
|
|
371
|
+
webPluginDevMapJson:
|
|
372
|
+
user.webPluginDevMapJson !== undefined
|
|
373
|
+
? user.webPluginDevMapJson
|
|
374
|
+
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_MAP', ''),
|
|
375
|
+
webPluginDevEntryPath: ensureLeadingPath(
|
|
376
|
+
user.webPluginDevEntryPath !== undefined && user.webPluginDevEntryPath !== ''
|
|
377
|
+
? user.webPluginDevEntryPath
|
|
378
|
+
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_ENTRY', DEF.webPluginDevEntryPath)
|
|
379
|
+
),
|
|
380
|
+
devPingPath: ensureLeadingPath(
|
|
381
|
+
user.devPingPath !== undefined && user.devPingPath !== ''
|
|
382
|
+
? user.devPingPath
|
|
383
|
+
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_PING_PATH', DEF.devPingPath)
|
|
384
|
+
),
|
|
385
|
+
devReloadSsePath: ensureLeadingPath(
|
|
386
|
+
user.devReloadSsePath !== undefined && user.devReloadSsePath !== ''
|
|
387
|
+
? user.devReloadSsePath
|
|
388
|
+
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_SSE_PATH', DEF.devReloadSsePath)
|
|
389
|
+
),
|
|
390
|
+
devPingTimeoutMs: resolvePositiveInt(user.devPingTimeoutMs, 'VITE_WEB_PLUGIN_DEV_PING_TIMEOUT_MS', DEF.devPingTimeoutMs),
|
|
391
|
+
defaultImplicitDevPluginIds,
|
|
392
|
+
allowedScriptHosts,
|
|
393
|
+
bridgeAllowedPathPrefixes,
|
|
394
|
+
bootstrapSummary: user.bootstrapSummary,
|
|
395
|
+
...(typeof user.fetchManifest === 'function' ? { fetchManifest: user.fetchManifest } : {})
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* 默认清单 HTTP 拉取(未配置 `fetchManifest` 时)。
|
|
401
|
+
* @module runtime/default-fetch-manifest
|
|
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>}
|
|
428
|
+
*/
|
|
429
|
+
async function defaultFetchWebPluginManifest$1(ctx) {
|
|
430
|
+
const { manifestUrl, credentials } = ctx;
|
|
431
|
+
try {
|
|
432
|
+
const res = await fetch(manifestUrl, { credentials });
|
|
433
|
+
if (!res.ok) {
|
|
434
|
+
return { ok: false, status: res.status, data: null }
|
|
435
|
+
}
|
|
436
|
+
const data = await res.json();
|
|
437
|
+
return { ok: true, data }
|
|
438
|
+
} catch (e) {
|
|
439
|
+
return { ok: false, error: e, data: null }
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function getDefaultExportFromCjs (x) {
|
|
444
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
var re = {exports: {}};
|
|
448
|
+
|
|
449
|
+
var constants;
|
|
450
|
+
var hasRequiredConstants;
|
|
451
|
+
|
|
452
|
+
function requireConstants () {
|
|
453
|
+
if (hasRequiredConstants) return constants;
|
|
454
|
+
hasRequiredConstants = 1;
|
|
455
|
+
|
|
456
|
+
// Note: this is the semver.org version of the spec that it implements
|
|
457
|
+
// Not necessarily the package version of this code.
|
|
458
|
+
const SEMVER_SPEC_VERSION = '2.0.0';
|
|
459
|
+
|
|
460
|
+
const MAX_LENGTH = 256;
|
|
461
|
+
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
|
|
462
|
+
/* istanbul ignore next */ 9007199254740991;
|
|
463
|
+
|
|
464
|
+
// Max safe segment length for coercion.
|
|
465
|
+
const MAX_SAFE_COMPONENT_LENGTH = 16;
|
|
466
|
+
|
|
467
|
+
// Max safe length for a build identifier. The max length minus 6 characters for
|
|
468
|
+
// the shortest version with a build 0.0.0+BUILD.
|
|
469
|
+
const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6;
|
|
470
|
+
|
|
471
|
+
const RELEASE_TYPES = [
|
|
472
|
+
'major',
|
|
473
|
+
'premajor',
|
|
474
|
+
'minor',
|
|
475
|
+
'preminor',
|
|
476
|
+
'patch',
|
|
477
|
+
'prepatch',
|
|
478
|
+
'prerelease',
|
|
479
|
+
];
|
|
480
|
+
|
|
481
|
+
constants = {
|
|
482
|
+
MAX_LENGTH,
|
|
483
|
+
MAX_SAFE_COMPONENT_LENGTH,
|
|
484
|
+
MAX_SAFE_BUILD_LENGTH,
|
|
485
|
+
MAX_SAFE_INTEGER,
|
|
486
|
+
RELEASE_TYPES,
|
|
487
|
+
SEMVER_SPEC_VERSION,
|
|
488
|
+
FLAG_INCLUDE_PRERELEASE: 0b001,
|
|
489
|
+
FLAG_LOOSE: 0b010,
|
|
490
|
+
};
|
|
491
|
+
return constants;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
var debug_1;
|
|
495
|
+
var hasRequiredDebug;
|
|
496
|
+
|
|
497
|
+
function requireDebug () {
|
|
498
|
+
if (hasRequiredDebug) return debug_1;
|
|
499
|
+
hasRequiredDebug = 1;
|
|
500
|
+
|
|
501
|
+
const debug = (
|
|
502
|
+
typeof process === 'object' &&
|
|
503
|
+
process.env &&
|
|
504
|
+
process.env.NODE_DEBUG &&
|
|
505
|
+
/\bsemver\b/i.test(process.env.NODE_DEBUG)
|
|
506
|
+
) ? (...args) => console.error('SEMVER', ...args)
|
|
507
|
+
: () => {};
|
|
508
|
+
|
|
509
|
+
debug_1 = debug;
|
|
510
|
+
return debug_1;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
var hasRequiredRe;
|
|
514
|
+
|
|
515
|
+
function requireRe () {
|
|
516
|
+
if (hasRequiredRe) return re.exports;
|
|
517
|
+
hasRequiredRe = 1;
|
|
518
|
+
(function (module, exports$1) {
|
|
519
|
+
|
|
520
|
+
const {
|
|
521
|
+
MAX_SAFE_COMPONENT_LENGTH,
|
|
522
|
+
MAX_SAFE_BUILD_LENGTH,
|
|
523
|
+
MAX_LENGTH,
|
|
524
|
+
} = requireConstants();
|
|
525
|
+
const debug = requireDebug();
|
|
526
|
+
exports$1 = module.exports = {};
|
|
527
|
+
|
|
528
|
+
// The actual regexps go on exports.re
|
|
529
|
+
const re = exports$1.re = [];
|
|
530
|
+
const safeRe = exports$1.safeRe = [];
|
|
531
|
+
const src = exports$1.src = [];
|
|
532
|
+
const safeSrc = exports$1.safeSrc = [];
|
|
533
|
+
const t = exports$1.t = {};
|
|
534
|
+
let R = 0;
|
|
535
|
+
|
|
536
|
+
const LETTERDASHNUMBER = '[a-zA-Z0-9-]';
|
|
537
|
+
|
|
538
|
+
// Replace some greedy regex tokens to prevent regex dos issues. These regex are
|
|
539
|
+
// used internally via the safeRe object since all inputs in this library get
|
|
540
|
+
// normalized first to trim and collapse all extra whitespace. The original
|
|
541
|
+
// regexes are exported for userland consumption and lower level usage. A
|
|
542
|
+
// future breaking change could export the safer regex only with a note that
|
|
543
|
+
// all input should have extra whitespace removed.
|
|
544
|
+
const safeRegexReplacements = [
|
|
545
|
+
['\\s', 1],
|
|
546
|
+
['\\d', MAX_LENGTH],
|
|
547
|
+
[LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
|
|
548
|
+
];
|
|
549
|
+
|
|
550
|
+
const makeSafeRegex = (value) => {
|
|
551
|
+
for (const [token, max] of safeRegexReplacements) {
|
|
177
552
|
value = value
|
|
178
553
|
.split(`${token}*`).join(`${token}{0,${max}}`)
|
|
179
554
|
.split(`${token}+`).join(`${token}{1,${max}}`);
|
|
@@ -2778,395 +3153,31 @@ function requireSemver () {
|
|
|
2778
3153
|
SemVer,
|
|
2779
3154
|
re: internalRe.re,
|
|
2780
3155
|
src: internalRe.src,
|
|
2781
|
-
tokens: internalRe.t,
|
|
2782
|
-
SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
|
|
2783
|
-
RELEASE_TYPES: constants.RELEASE_TYPES,
|
|
2784
|
-
compareIdentifiers: identifiers.compareIdentifiers,
|
|
2785
|
-
rcompareIdentifiers: identifiers.rcompareIdentifiers,
|
|
2786
|
-
};
|
|
2787
|
-
return semver$1;
|
|
2788
|
-
}
|
|
2789
|
-
|
|
2790
|
-
var semverExports = requireSemver();
|
|
2791
|
-
var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
|
|
2792
|
-
|
|
2793
|
-
/**
|
|
2794
|
-
* 不依赖 `import.meta`,兼容 Webpack 4/5、Vue CLI、Vite、Rspack 等宿主。
|
|
2795
|
-
* - Webpack / Vue CLI:依赖构建时注入的 `process.env`(如 `VUE_APP_*`、`DefinePlugin` 注入的 `VITE_*`)。
|
|
2796
|
-
* - Vite:在入口调用 `setWebExtendPluginEnv(import.meta.env)`,或 `installWebExtendPluginVue2(..., { env: import.meta.env })`。
|
|
2797
|
-
* - 也可在入口前设置 `globalThis.__WEP_ENV__ = import.meta.env`(与 setWebExtendPluginEnv 二选一即可)。
|
|
2798
|
-
*
|
|
2799
|
-
* @module bundled-env
|
|
2800
|
-
*/
|
|
2801
|
-
|
|
2802
|
-
/** @type {Record<string, unknown> | null} */
|
|
2803
|
-
let _explicitEnv = null;
|
|
2804
|
-
|
|
2805
|
-
/**
|
|
2806
|
-
* 显式注入与 `import.meta.env` 同形态的对象(推荐 Vite 宿主在入口调用一次)。
|
|
2807
|
-
* @param {Record<string, unknown> | null | undefined} env
|
|
2808
|
-
*/
|
|
2809
|
-
function setWebExtendPluginEnv(env) {
|
|
2810
|
-
_explicitEnv = env && typeof env === 'object' ? env : null;
|
|
2811
|
-
}
|
|
2812
|
-
|
|
2813
|
-
/**
|
|
2814
|
-
* @returns {Record<string, unknown> | null}
|
|
2815
|
-
*/
|
|
2816
|
-
function getInjectedEnvObject() {
|
|
2817
|
-
if (_explicitEnv) {
|
|
2818
|
-
return _explicitEnv
|
|
2819
|
-
}
|
|
2820
|
-
try {
|
|
2821
|
-
const g = typeof globalThis !== 'undefined' ? globalThis : undefined;
|
|
2822
|
-
if (g && g.__WEP_ENV__ && typeof g.__WEP_ENV__ === 'object') {
|
|
2823
|
-
return g.__WEP_ENV__
|
|
2824
|
-
}
|
|
2825
|
-
} catch (_) {}
|
|
2826
|
-
return null
|
|
2827
|
-
}
|
|
2828
|
-
|
|
2829
|
-
/**
|
|
2830
|
-
* 从注入环境读取字符串配置键(`VITE_*` / `PLUGIN_*` 等)。
|
|
2831
|
-
* @param {string} key
|
|
2832
|
-
* @returns {string|undefined}
|
|
2833
|
-
*/
|
|
2834
|
-
function readInjectedEnvKey(key) {
|
|
2835
|
-
const o = getInjectedEnvObject();
|
|
2836
|
-
if (!o || !(key in o)) {
|
|
2837
|
-
return undefined
|
|
2838
|
-
}
|
|
2839
|
-
const v = o[key];
|
|
2840
|
-
if (v === undefined || v === '') {
|
|
2841
|
-
return undefined
|
|
2842
|
-
}
|
|
2843
|
-
return String(v)
|
|
2844
|
-
}
|
|
2845
|
-
|
|
2846
|
-
/**
|
|
2847
|
-
* @returns {boolean}
|
|
2848
|
-
*/
|
|
2849
|
-
function readInjectedEnvDev() {
|
|
2850
|
-
const o = getInjectedEnvObject();
|
|
2851
|
-
return !!(o && o.DEV === true)
|
|
2852
|
-
}
|
|
2853
|
-
|
|
2854
|
-
/**
|
|
2855
|
-
* 与 `plugin-web-starter`(WebPluginsResponse)返回的 `hostPluginApiVersion` 保持一致,用于契约校验。
|
|
2856
|
-
* @type {string}
|
|
2857
|
-
*/
|
|
2858
|
-
const HOST_PLUGIN_API_VERSION = '1.0.0';
|
|
2859
|
-
|
|
2860
|
-
/**
|
|
2861
|
-
* 宿主侧插件引导:拉取清单、dev 映射、加载入口脚本、调用 activator。
|
|
2862
|
-
* 路径与白名单等默认值见 `defaultWebExtendPluginRuntime`,可通过 `resolveRuntimeOptions` / 环境变量覆盖。
|
|
2863
|
-
*
|
|
2864
|
-
* **Webpack 宿主**:用 `DefinePlugin` 注入 `process.env.VITE_*` 或 **`PLUGIN_*`**(等价键),或 `resolveRuntimeOptions` 显式传参。
|
|
2865
|
-
* **Vite 宿主**:入口调用 `setWebExtendPluginEnv(import.meta.env)`,或 `installWebExtendPluginVue2(..., { env: import.meta.env })`。
|
|
2866
|
-
*
|
|
2867
|
-
* @module PluginRuntime
|
|
2868
|
-
*/
|
|
2869
|
-
|
|
2870
|
-
const DEF = defaultWebExtendPluginRuntime;
|
|
2871
|
-
|
|
2872
|
-
/**
|
|
2873
|
-
* @typedef {object} WebExtendPluginRuntimeOptions
|
|
2874
|
-
* @property {string} [manifestBase] 清单服务 URL 前缀
|
|
2875
|
-
* @property {string} [manifestListPath] 清单接口路径(以 `/` 开头),拼在 manifestBase 后
|
|
2876
|
-
* @property {RequestCredentials} [manifestFetchCredentials] 清单 fetch 的 credentials
|
|
2877
|
-
* @property {boolean} [isDev] 开发模式
|
|
2878
|
-
* @property {string} [webPluginDevOrigin] 插件 dev origin
|
|
2879
|
-
* @property {string} [webPluginDevIds] 逗号分隔 id,隐式 dev 映射
|
|
2880
|
-
* @property {string} [webPluginDevMapJson] 显式 dev 映射 JSON
|
|
2881
|
-
* @property {string} [webPluginDevEntryPath] 隐式 dev 入口路径(相对插件 dev origin)
|
|
2882
|
-
* @property {string} [devPingPath] dev 存活探测路径
|
|
2883
|
-
* @property {string} [devReloadSsePath] dev 热更新 SSE 路径
|
|
2884
|
-
* @property {number} [devPingTimeoutMs] 探测超时
|
|
2885
|
-
* @property {string[]} [defaultImplicitDevPluginIds] 无 `webPluginDevIds`/env 时用于隐式 dev 的 id;包内默认 `[]`
|
|
2886
|
-
* @property {string[]} [allowedScriptHosts] 允许加载脚本的主机名
|
|
2887
|
-
* @property {string[]} [bridgeAllowedPathPrefixes] bridge.request 白名单前缀
|
|
2888
|
-
* @property {boolean} [bootstrapSummary] bootstrap 结束是否打印摘要
|
|
2889
|
-
*/
|
|
2890
|
-
|
|
2891
|
-
/**
|
|
2892
|
-
* 从 Webpack `DefinePlugin` 等注入的 `process.env` 读取。
|
|
2893
|
-
* @param {string} key
|
|
2894
|
-
* @returns {string|undefined}
|
|
2895
|
-
*/
|
|
2896
|
-
function readProcessEnv(key) {
|
|
2897
|
-
try {
|
|
2898
|
-
if (typeof process !== 'undefined' && process.env && key in process.env) {
|
|
2899
|
-
const v = process.env[key];
|
|
2900
|
-
if (v !== undefined && v !== '') {
|
|
2901
|
-
return String(v)
|
|
2902
|
-
}
|
|
2903
|
-
}
|
|
2904
|
-
} catch (_) {}
|
|
2905
|
-
return undefined
|
|
2906
|
-
}
|
|
2907
|
-
|
|
2908
|
-
/**
|
|
2909
|
-
* `VITE_*` 的并列命名:同值可读 `PLUGIN_*`(`VITE_WEB_PLUGIN_X` → `PLUGIN_WEB_PLUGIN_X`)。
|
|
2910
|
-
* Vite 需在 `defineConfig({ envPrefix: ['VITE_', 'PLUGIN_'] })` 中暴露 `PLUGIN_`;Webpack 用 DefinePlugin 注入即可。
|
|
2911
|
-
* @param {string} viteStyleKey 以 `VITE_` 开头的键名
|
|
2912
|
-
* @returns {string|null}
|
|
2913
|
-
*/
|
|
2914
|
-
function viteKeyToPluginAlternate(viteStyleKey) {
|
|
2915
|
-
if (typeof viteStyleKey !== 'string' || !viteStyleKey.startsWith('VITE_')) {
|
|
2916
|
-
return null
|
|
2917
|
-
}
|
|
2918
|
-
return `PLUGIN_${viteStyleKey.slice(5)}`
|
|
2919
|
-
}
|
|
2920
|
-
|
|
2921
|
-
/**
|
|
2922
|
-
* 先读注入环境(`setWebExtendPluginEnv` / `__WEP_ENV__`)中的 `VITE_*` 与并列 `PLUGIN_*`,再读 `process.env`,最后 `fallback`。
|
|
2923
|
-
* @param {string} key 仍以 `VITE_*` 为逻辑名(与文档一致)
|
|
2924
|
-
* @param {string} [fallback='']
|
|
2925
|
-
*/
|
|
2926
|
-
function resolveBundledEnv(key, fallback = '') {
|
|
2927
|
-
const alt = viteKeyToPluginAlternate(key);
|
|
2928
|
-
const inj = readInjectedEnvKey(key);
|
|
2929
|
-
const fromInjected =
|
|
2930
|
-
inj === undefined || inj === null ? (alt ? readInjectedEnvKey(alt) : undefined) : inj;
|
|
2931
|
-
const proc = readProcessEnv(key);
|
|
2932
|
-
const fromProcess =
|
|
2933
|
-
proc === undefined || proc === null ? (alt ? readProcessEnv(alt) : undefined) : proc;
|
|
2934
|
-
const first = fromInjected === undefined || fromInjected === null ? fromProcess : fromInjected;
|
|
2935
|
-
return first === undefined || first === null ? fallback : first
|
|
2936
|
-
}
|
|
2937
|
-
|
|
2938
|
-
/**
|
|
2939
|
-
* @returns {boolean}
|
|
2940
|
-
*/
|
|
2941
|
-
function resolveBundledIsDev() {
|
|
2942
|
-
try {
|
|
2943
|
-
if (readInjectedEnvDev()) {
|
|
2944
|
-
return true
|
|
2945
|
-
}
|
|
2946
|
-
} catch (_) {}
|
|
2947
|
-
try {
|
|
2948
|
-
if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development') {
|
|
2949
|
-
return true
|
|
2950
|
-
}
|
|
2951
|
-
} catch (_) {}
|
|
2952
|
-
return false
|
|
2953
|
-
}
|
|
2954
|
-
|
|
2955
|
-
/**
|
|
2956
|
-
* @param {string} p
|
|
2957
|
-
*/
|
|
2958
|
-
function ensureLeadingPath(p) {
|
|
2959
|
-
const t = String(p || '').trim();
|
|
2960
|
-
if (!t) {
|
|
2961
|
-
return '/'
|
|
2962
|
-
}
|
|
2963
|
-
return t.startsWith('/') ? t : `/${t}`
|
|
2964
|
-
}
|
|
2965
|
-
|
|
2966
|
-
/**
|
|
2967
|
-
* 解析 `include` | `omit` | `same-origin`,非法时回退默认值。
|
|
2968
|
-
* @param {string|undefined} userVal
|
|
2969
|
-
* @param {string} envKey
|
|
2970
|
-
* @param {RequestCredentials} fallback
|
|
2971
|
-
*/
|
|
2972
|
-
function resolveManifestCredentials(userVal, envKey, fallback) {
|
|
2973
|
-
if (userVal !== undefined && userVal !== '') {
|
|
2974
|
-
const s = String(userVal);
|
|
2975
|
-
if (s === 'include' || s === 'omit' || s === 'same-origin') {
|
|
2976
|
-
return s
|
|
2977
|
-
}
|
|
2978
|
-
}
|
|
2979
|
-
const e = resolveBundledEnv(envKey, '');
|
|
2980
|
-
if (e === 'include' || e === 'omit' || e === 'same-origin') {
|
|
2981
|
-
return e
|
|
2982
|
-
}
|
|
2983
|
-
return fallback
|
|
2984
|
-
}
|
|
2985
|
-
|
|
2986
|
-
/**
|
|
2987
|
-
* @param {number|undefined} userVal
|
|
2988
|
-
* @param {string} envKey
|
|
2989
|
-
* @param {number} fallback
|
|
2990
|
-
*/
|
|
2991
|
-
function resolvePositiveInt(userVal, envKey, fallback) {
|
|
2992
|
-
if (typeof userVal === 'number' && Number.isFinite(userVal) && userVal > 0) {
|
|
2993
|
-
return Math.floor(userVal)
|
|
2994
|
-
}
|
|
2995
|
-
const raw = resolveBundledEnv(envKey, '');
|
|
2996
|
-
const n = raw ? parseInt(raw, 10) : NaN;
|
|
2997
|
-
if (Number.isFinite(n) && n > 0) {
|
|
2998
|
-
return n
|
|
2999
|
-
}
|
|
3000
|
-
return fallback
|
|
3001
|
-
}
|
|
3002
|
-
|
|
3003
|
-
/**
|
|
3004
|
-
* 合并用户、环境变量与 `defaultWebExtendPluginRuntime`,得到完整运行时选项(宿主可只传需要覆盖的字段)。
|
|
3005
|
-
* @param {WebExtendPluginRuntimeOptions} [user]
|
|
3006
|
-
* @returns {object}
|
|
3007
|
-
*/
|
|
3008
|
-
function resolveRuntimeOptions(user = {}) {
|
|
3009
|
-
const manifestBaseRaw =
|
|
3010
|
-
user.manifestBase !== undefined && user.manifestBase !== ''
|
|
3011
|
-
? String(user.manifestBase)
|
|
3012
|
-
: resolveBundledEnv('VITE_FRONTEND_PLUGIN_BASE', DEF.manifestBase) || DEF.manifestBase;
|
|
3013
|
-
|
|
3014
|
-
const manifestListPath = ensureLeadingPath(
|
|
3015
|
-
user.manifestListPath !== undefined && user.manifestListPath !== ''
|
|
3016
|
-
? user.manifestListPath
|
|
3017
|
-
: resolveBundledEnv('VITE_WEB_PLUGIN_MANIFEST_PATH', DEF.manifestListPath)
|
|
3018
|
-
);
|
|
3019
|
-
|
|
3020
|
-
const defaultImplicitDevPluginIds =
|
|
3021
|
-
Array.isArray(user.defaultImplicitDevPluginIds)
|
|
3022
|
-
? user.defaultImplicitDevPluginIds.map(String).filter(Boolean)
|
|
3023
|
-
: (() => {
|
|
3024
|
-
const e = resolveBundledEnv('VITE_WEB_PLUGIN_IMPLICIT_DEV_IDS', '');
|
|
3025
|
-
if (e) {
|
|
3026
|
-
return e
|
|
3027
|
-
.split(',')
|
|
3028
|
-
.map((s) => s.trim())
|
|
3029
|
-
.filter(Boolean)
|
|
3030
|
-
}
|
|
3031
|
-
return [...DEF.defaultImplicitDevPluginIds]
|
|
3032
|
-
})();
|
|
3033
|
-
|
|
3034
|
-
const allowedScriptHosts =
|
|
3035
|
-
Array.isArray(user.allowedScriptHosts) && user.allowedScriptHosts.length > 0
|
|
3036
|
-
? user.allowedScriptHosts.map((h) => normalizeHost(String(h))).filter(Boolean)
|
|
3037
|
-
: (() => {
|
|
3038
|
-
const e = resolveBundledEnv('VITE_WEB_PLUGIN_ALLOWED_SCRIPT_HOSTS', '');
|
|
3039
|
-
if (e) {
|
|
3040
|
-
return e
|
|
3041
|
-
.split(',')
|
|
3042
|
-
.map((s) => normalizeHost(s.trim()))
|
|
3043
|
-
.filter(Boolean)
|
|
3044
|
-
}
|
|
3045
|
-
return [...DEF.allowedScriptHosts]
|
|
3046
|
-
})();
|
|
3047
|
-
|
|
3048
|
-
const bridgeAllowedPathPrefixes =
|
|
3049
|
-
Array.isArray(user.bridgeAllowedPathPrefixes) && user.bridgeAllowedPathPrefixes.length > 0
|
|
3050
|
-
? user.bridgeAllowedPathPrefixes.map((p) => ensureLeadingPath(p)).filter(Boolean)
|
|
3051
|
-
: (() => {
|
|
3052
|
-
const e = resolveBundledEnv('VITE_WEB_PLUGIN_BRIDGE_PREFIXES', '');
|
|
3053
|
-
if (e) {
|
|
3054
|
-
return e
|
|
3055
|
-
.split(',')
|
|
3056
|
-
.map((s) => ensureLeadingPath(s.trim()))
|
|
3057
|
-
.filter(Boolean)
|
|
3058
|
-
}
|
|
3059
|
-
return [...DEF.bridgeAllowedPathPrefixes]
|
|
3060
|
-
})();
|
|
3061
|
-
|
|
3062
|
-
return {
|
|
3063
|
-
manifestBase: manifestBaseRaw.replace(/\/$/, '') || DEF.manifestBase.replace(/\/$/, ''),
|
|
3064
|
-
manifestListPath,
|
|
3065
|
-
manifestFetchCredentials: resolveManifestCredentials(
|
|
3066
|
-
user.manifestFetchCredentials,
|
|
3067
|
-
'VITE_WEB_PLUGIN_MANIFEST_CREDENTIALS',
|
|
3068
|
-
DEF.manifestFetchCredentials
|
|
3069
|
-
),
|
|
3070
|
-
isDev: user.isDev !== undefined ? user.isDev : resolveBundledIsDev(),
|
|
3071
|
-
webPluginDevOrigin:
|
|
3072
|
-
user.webPluginDevOrigin !== undefined ? user.webPluginDevOrigin : resolveBundledEnv('VITE_WEB_PLUGIN_DEV_ORIGIN', ''),
|
|
3073
|
-
webPluginDevIds:
|
|
3074
|
-
user.webPluginDevIds !== undefined ? user.webPluginDevIds : resolveBundledEnv('VITE_WEB_PLUGIN_DEV_IDS', ''),
|
|
3075
|
-
webPluginDevMapJson:
|
|
3076
|
-
user.webPluginDevMapJson !== undefined
|
|
3077
|
-
? user.webPluginDevMapJson
|
|
3078
|
-
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_MAP', ''),
|
|
3079
|
-
webPluginDevEntryPath: ensureLeadingPath(
|
|
3080
|
-
user.webPluginDevEntryPath !== undefined && user.webPluginDevEntryPath !== ''
|
|
3081
|
-
? user.webPluginDevEntryPath
|
|
3082
|
-
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_ENTRY', DEF.webPluginDevEntryPath)
|
|
3083
|
-
),
|
|
3084
|
-
devPingPath: ensureLeadingPath(
|
|
3085
|
-
user.devPingPath !== undefined && user.devPingPath !== ''
|
|
3086
|
-
? user.devPingPath
|
|
3087
|
-
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_PING_PATH', DEF.devPingPath)
|
|
3088
|
-
),
|
|
3089
|
-
devReloadSsePath: ensureLeadingPath(
|
|
3090
|
-
user.devReloadSsePath !== undefined && user.devReloadSsePath !== ''
|
|
3091
|
-
? user.devReloadSsePath
|
|
3092
|
-
: resolveBundledEnv('VITE_WEB_PLUGIN_DEV_SSE_PATH', DEF.devReloadSsePath)
|
|
3093
|
-
),
|
|
3094
|
-
devPingTimeoutMs: resolvePositiveInt(user.devPingTimeoutMs, 'VITE_WEB_PLUGIN_DEV_PING_TIMEOUT_MS', DEF.devPingTimeoutMs),
|
|
3095
|
-
defaultImplicitDevPluginIds,
|
|
3096
|
-
allowedScriptHosts,
|
|
3097
|
-
bridgeAllowedPathPrefixes,
|
|
3098
|
-
bootstrapSummary: user.bootstrapSummary
|
|
3099
|
-
}
|
|
3100
|
-
}
|
|
3101
|
-
|
|
3102
|
-
/**
|
|
3103
|
-
* @param {ReturnType<typeof resolveRuntimeOptions>} opts
|
|
3104
|
-
*/
|
|
3105
|
-
function shouldShowBootstrapSummary(opts) {
|
|
3106
|
-
if (opts.bootstrapSummary === true) {
|
|
3107
|
-
return true
|
|
3108
|
-
}
|
|
3109
|
-
if (opts.bootstrapSummary === false) {
|
|
3110
|
-
return false
|
|
3111
|
-
}
|
|
3112
|
-
const env = resolveBundledEnv('VITE_PLUGINS_BOOTSTRAP_SUMMARY', '');
|
|
3113
|
-
if (env === '0' || env === 'false') {
|
|
3114
|
-
return false
|
|
3115
|
-
}
|
|
3116
|
-
if (env === '1' || env === 'true') {
|
|
3117
|
-
return true
|
|
3118
|
-
}
|
|
3119
|
-
return resolveBundledIsDev()
|
|
3156
|
+
tokens: internalRe.t,
|
|
3157
|
+
SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
|
|
3158
|
+
RELEASE_TYPES: constants.RELEASE_TYPES,
|
|
3159
|
+
compareIdentifiers: identifiers.compareIdentifiers,
|
|
3160
|
+
rcompareIdentifiers: identifiers.rcompareIdentifiers,
|
|
3161
|
+
};
|
|
3162
|
+
return semver$1;
|
|
3120
3163
|
}
|
|
3121
3164
|
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
*/
|
|
3125
|
-
function normalizeHost(hostname) {
|
|
3126
|
-
if (!hostname) {
|
|
3127
|
-
return ''
|
|
3128
|
-
}
|
|
3129
|
-
const h = hostname.toLowerCase();
|
|
3130
|
-
if (h.startsWith('[') && h.endsWith(']')) {
|
|
3131
|
-
return h.slice(1, -1)
|
|
3132
|
-
}
|
|
3133
|
-
return h
|
|
3134
|
-
}
|
|
3165
|
+
var semverExports = requireSemver();
|
|
3166
|
+
var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
|
|
3135
3167
|
|
|
3136
|
-
/**
|
|
3137
|
-
*
|
|
3138
|
-
* @
|
|
3139
|
-
*/
|
|
3140
|
-
|
|
3141
|
-
const s = new Set();
|
|
3142
|
-
for (const h of hostnames) {
|
|
3143
|
-
const n = normalizeHost(h);
|
|
3144
|
-
if (n) {
|
|
3145
|
-
s.add(n);
|
|
3146
|
-
}
|
|
3147
|
-
}
|
|
3148
|
-
return s
|
|
3149
|
-
}
|
|
3168
|
+
/**
|
|
3169
|
+
* 与 `plugin-web-starter`(WebPluginsResponse)返回的 `hostPluginApiVersion` 保持一致,用于契约校验。
|
|
3170
|
+
* @type {string}
|
|
3171
|
+
*/
|
|
3172
|
+
const HOST_PLUGIN_API_VERSION = '1.0.0';
|
|
3150
3173
|
|
|
3151
3174
|
/**
|
|
3152
|
-
*
|
|
3153
|
-
* @
|
|
3175
|
+
* 开发模式插件 URL 映射(显式 JSON + 隐式 dev 探测)。
|
|
3176
|
+
* @module runtime/dev-map
|
|
3154
3177
|
*/
|
|
3155
|
-
function isScriptHostAllowed(url, hostSet) {
|
|
3156
|
-
if (typeof window === 'undefined') {
|
|
3157
|
-
return false
|
|
3158
|
-
}
|
|
3159
|
-
try {
|
|
3160
|
-
const u = new URL(url, window.location.origin);
|
|
3161
|
-
const h = normalizeHost(u.hostname);
|
|
3162
|
-
return hostSet.has(h)
|
|
3163
|
-
} catch {
|
|
3164
|
-
return false
|
|
3165
|
-
}
|
|
3166
|
-
}
|
|
3167
3178
|
|
|
3168
3179
|
/**
|
|
3169
|
-
* @param {
|
|
3180
|
+
* @param {{ isDev: boolean, webPluginDevMapJson?: string|null }} opts
|
|
3170
3181
|
*/
|
|
3171
3182
|
function parseWebPluginDevMapExplicit(opts) {
|
|
3172
3183
|
if (!opts.isDev) {
|
|
@@ -3186,7 +3197,24 @@ function parseWebPluginDevMapExplicit(opts) {
|
|
|
3186
3197
|
}
|
|
3187
3198
|
|
|
3188
3199
|
/**
|
|
3189
|
-
* @param {
|
|
3200
|
+
* @param {Record<string, string>} implicit
|
|
3201
|
+
* @param {Record<string, string>|null} explicit
|
|
3202
|
+
*/
|
|
3203
|
+
function mergeDevMaps(implicit, explicit) {
|
|
3204
|
+
const i = implicit && typeof implicit === 'object' ? implicit : {};
|
|
3205
|
+
const e = explicit && typeof explicit === 'object' ? explicit : {};
|
|
3206
|
+
return { ...i, ...e }
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
/**
|
|
3210
|
+
* @param {object} opts
|
|
3211
|
+
* @param {boolean} opts.isDev
|
|
3212
|
+
* @param {string|undefined|null} opts.webPluginDevOrigin
|
|
3213
|
+
* @param {string|undefined|null} opts.webPluginDevIds
|
|
3214
|
+
* @param {string[]} opts.defaultImplicitDevPluginIds
|
|
3215
|
+
* @param {string} opts.devPingPath
|
|
3216
|
+
* @param {number} opts.devPingTimeoutMs
|
|
3217
|
+
* @param {string} opts.webPluginDevEntryPath
|
|
3190
3218
|
* @param {Set<string>} hostSet
|
|
3191
3219
|
*/
|
|
3192
3220
|
async function buildImplicitWebPluginDevMap(opts, hostSet) {
|
|
@@ -3258,14 +3286,9 @@ async function buildImplicitWebPluginDevMap(opts, hostSet) {
|
|
|
3258
3286
|
}
|
|
3259
3287
|
|
|
3260
3288
|
/**
|
|
3261
|
-
*
|
|
3262
|
-
* @
|
|
3289
|
+
* 开发模式下插件热更新 SSE(按 dev 映射中的 origin 连接)。
|
|
3290
|
+
* @module runtime/dev-reload-sse
|
|
3263
3291
|
*/
|
|
3264
|
-
function mergeDevMaps(implicit, explicit) {
|
|
3265
|
-
const i = implicit && typeof implicit === 'object' ? implicit : {};
|
|
3266
|
-
const e = explicit && typeof explicit === 'object' ? explicit : {};
|
|
3267
|
-
return { ...i, ...e }
|
|
3268
|
-
}
|
|
3269
3292
|
|
|
3270
3293
|
/** @type {Map<string, EventSource>} */
|
|
3271
3294
|
const pluginDevEventSources = new Map();
|
|
@@ -3362,8 +3385,17 @@ function startPluginDevSseForMap(devMap, isDev, hostSet, ssePath) {
|
|
|
3362
3385
|
}
|
|
3363
3386
|
}
|
|
3364
3387
|
|
|
3388
|
+
/**
|
|
3389
|
+
* 动态加载脚本(去重与并发合并)。
|
|
3390
|
+
* @module runtime/load-script
|
|
3391
|
+
*/
|
|
3392
|
+
|
|
3365
3393
|
const loadScriptMemo = new Map();
|
|
3366
3394
|
|
|
3395
|
+
/**
|
|
3396
|
+
* @param {string} src
|
|
3397
|
+
* @returns {Promise<void>}
|
|
3398
|
+
*/
|
|
3367
3399
|
function loadScript(src) {
|
|
3368
3400
|
if (typeof document === 'undefined') {
|
|
3369
3401
|
return Promise.reject(new Error('loadScript: no document'))
|
|
@@ -3407,6 +3439,31 @@ function loadScript(src) {
|
|
|
3407
3439
|
return p
|
|
3408
3440
|
}
|
|
3409
3441
|
|
|
3442
|
+
/**
|
|
3443
|
+
* 拉取清单、合并 dev 映射、加载入口并执行 activator。
|
|
3444
|
+
* @module runtime/bootstrap-plugins
|
|
3445
|
+
*/
|
|
3446
|
+
|
|
3447
|
+
/**
|
|
3448
|
+
* @param {import('./resolve-runtime-options.js').WebExtendPluginRuntimeOptions|object} opts
|
|
3449
|
+
*/
|
|
3450
|
+
function shouldShowBootstrapSummary(opts) {
|
|
3451
|
+
if (opts.bootstrapSummary === true) {
|
|
3452
|
+
return true
|
|
3453
|
+
}
|
|
3454
|
+
if (opts.bootstrapSummary === false) {
|
|
3455
|
+
return false
|
|
3456
|
+
}
|
|
3457
|
+
const env = resolveBundledEnv('VITE_PLUGINS_BOOTSTRAP_SUMMARY', '');
|
|
3458
|
+
if (env === '0' || env === 'false') {
|
|
3459
|
+
return false
|
|
3460
|
+
}
|
|
3461
|
+
if (env === '1' || env === 'true') {
|
|
3462
|
+
return true
|
|
3463
|
+
}
|
|
3464
|
+
return resolveBundledIsDev()
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3410
3467
|
/**
|
|
3411
3468
|
* @param {{ id: string }} p
|
|
3412
3469
|
* @param {string} [entryUrl]
|
|
@@ -3445,29 +3502,30 @@ async function loadPluginEntry(p, entryUrl, devMap, hostSet) {
|
|
|
3445
3502
|
/**
|
|
3446
3503
|
* @param {import('vue-router').default} router
|
|
3447
3504
|
* @param {(pluginId: string, router: import('vue-router').default, hostKit?: { bridgeAllowedPathPrefixes: string[] }) => object} createHostApiFactory
|
|
3448
|
-
*
|
|
3449
|
-
* @param {WebExtendPluginRuntimeOptions} [runtimeOptions]
|
|
3505
|
+
* @param {import('./resolve-runtime-options.js').WebExtendPluginRuntimeOptions} [runtimeOptions]
|
|
3450
3506
|
*/
|
|
3451
|
-
async function bootstrapPlugins(router, createHostApiFactory, runtimeOptions) {
|
|
3507
|
+
async function bootstrapPlugins$1(router, createHostApiFactory, runtimeOptions) {
|
|
3452
3508
|
if (typeof window === 'undefined') {
|
|
3453
3509
|
console.warn('[plugins] bootstrapPlugins skipped: requires browser (window)');
|
|
3454
3510
|
return
|
|
3455
3511
|
}
|
|
3456
|
-
const opts = resolveRuntimeOptions(runtimeOptions || {});
|
|
3512
|
+
const opts = resolveRuntimeOptions$1(runtimeOptions || {});
|
|
3457
3513
|
const base = String(opts.manifestBase).replace(/\/$/, '');
|
|
3458
3514
|
const manifestUrl = `${base}${opts.manifestListPath}`;
|
|
3459
3515
|
const hostSet = buildAllowedScriptHostsSet(opts.allowedScriptHosts);
|
|
3460
3516
|
const explicit = parseWebPluginDevMapExplicit(opts);
|
|
3461
3517
|
|
|
3518
|
+
const manifestCtx = {
|
|
3519
|
+
manifestUrl,
|
|
3520
|
+
credentials: opts.manifestFetchCredentials
|
|
3521
|
+
};
|
|
3462
3522
|
const [manifestResult, implicit] = await Promise.all([
|
|
3463
3523
|
(async () => {
|
|
3464
3524
|
try {
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
return { ok: false, status: res.status, data: null }
|
|
3525
|
+
if (typeof opts.fetchManifest === 'function') {
|
|
3526
|
+
return await opts.fetchManifest(manifestCtx)
|
|
3468
3527
|
}
|
|
3469
|
-
|
|
3470
|
-
return { ok: true, data }
|
|
3528
|
+
return await defaultFetchWebPluginManifest$1(manifestCtx)
|
|
3471
3529
|
} catch (e) {
|
|
3472
3530
|
return { ok: false, error: e, data: null }
|
|
3473
3531
|
}
|
|
@@ -3571,6 +3629,240 @@ async function bootstrapPlugins(router, createHostApiFactory, runtimeOptions) {
|
|
|
3571
3629
|
}
|
|
3572
3630
|
}
|
|
3573
3631
|
|
|
3632
|
+
/**
|
|
3633
|
+
* 宿主侧插件引导:拉取清单、dev 映射、加载入口脚本、调用 activator。
|
|
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
|
|
3640
|
+
*/
|
|
3641
|
+
|
|
3642
|
+
var pluginRuntime = /*#__PURE__*/Object.freeze({
|
|
3643
|
+
__proto__: null,
|
|
3644
|
+
bootstrapPlugins: bootstrapPlugins$1,
|
|
3645
|
+
defaultFetchWebPluginManifest: defaultFetchWebPluginManifest$1,
|
|
3646
|
+
resolveRuntimeOptions: resolveRuntimeOptions$1
|
|
3647
|
+
});
|
|
3648
|
+
|
|
3649
|
+
/**
|
|
3650
|
+
* 清单拉取函数的组合工具:缓存、埋点等以**中间件**形式扩展,不侵入 `bootstrapPlugins` 核心逻辑,
|
|
3651
|
+
* 符合第三方依赖「可组合、可替换」约定。契约与 `PluginRuntime` 中 `fetchManifest` 一致。
|
|
3652
|
+
*
|
|
3653
|
+
* @module runtime/manifest-fetch-composer
|
|
3654
|
+
*/
|
|
3655
|
+
|
|
3656
|
+
/**
|
|
3657
|
+
* @typedef {object} FetchWebPluginManifestContext
|
|
3658
|
+
* @property {string} manifestUrl
|
|
3659
|
+
* @property {RequestCredentials} credentials
|
|
3660
|
+
*/
|
|
3661
|
+
|
|
3662
|
+
/**
|
|
3663
|
+
* @typedef {object} FetchWebPluginManifestResult
|
|
3664
|
+
* @property {boolean} ok
|
|
3665
|
+
* @property {number} [status]
|
|
3666
|
+
* @property {{ hostPluginApiVersion?: string, plugins?: object[] }|null} [data]
|
|
3667
|
+
* @property {unknown} [error]
|
|
3668
|
+
*/
|
|
3669
|
+
|
|
3670
|
+
/**
|
|
3671
|
+
* @callback FetchWebPluginManifestFn
|
|
3672
|
+
* @param {FetchWebPluginManifestContext} ctx
|
|
3673
|
+
* @returns {Promise<FetchWebPluginManifestResult>}
|
|
3674
|
+
*/
|
|
3675
|
+
|
|
3676
|
+
/**
|
|
3677
|
+
* 将内层 `fetchManifest` 包装为带缓存的版本。等价于
|
|
3678
|
+
* `composeManifestFetch(inner, manifestFetchCacheMiddleware(options))`。
|
|
3679
|
+
*
|
|
3680
|
+
* @param {FetchWebPluginManifestFn} inner 内层实现(如预设生成的 `fetchManifest` 或 `defaultFetchWebPluginManifest`)
|
|
3681
|
+
* @param {ManifestFetchCacheOptions} [options]
|
|
3682
|
+
* @returns {FetchWebPluginManifestFn}
|
|
3683
|
+
*/
|
|
3684
|
+
function wrapManifestFetchWithCache$1(inner, options = {}) {
|
|
3685
|
+
return composeManifestFetch$1(inner, manifestFetchCacheMiddleware$1(options))
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
/**
|
|
3689
|
+
* @typedef {object} ManifestFetchCacheOptions
|
|
3690
|
+
* @property {number} [ttlMs] 缓存时长(毫秒)。`<= 0` 或未传时**不缓存**(直接透传 `inner`)。
|
|
3691
|
+
* @property {'memory'|'session'|'local'} [storage='memory'] `session`/`local` 依赖 `JSON.stringify`,仅适合可序列化的 `data`。
|
|
3692
|
+
* @property {string} [storageKeyPrefix='wep.manifestFetch.v1'] Web Storage 键前缀(仅 storage 非 memory 时生效)。
|
|
3693
|
+
* @property {(ctx: FetchWebPluginManifestContext) => string} [cacheKey] 默认 `manifestUrl + '\0' + credentials`。
|
|
3694
|
+
* @property {(result: FetchWebPluginManifestResult) => boolean} [shouldCache] 默认:`ok === true` 且 `data` 非空。
|
|
3695
|
+
* @property {number} [maxEntries=50] 仅 `memory`:超过条数时淘汰最久未读条目。
|
|
3696
|
+
* @property {() => number} [now] 测试注入时间戳。
|
|
3697
|
+
*/
|
|
3698
|
+
|
|
3699
|
+
/**
|
|
3700
|
+
* 清单拉取**中间件工厂**:`next` 为内层 `fetchManifest`。
|
|
3701
|
+
*
|
|
3702
|
+
* @param {ManifestFetchCacheOptions} options
|
|
3703
|
+
* @returns {(next: FetchWebPluginManifestFn) => FetchWebPluginManifestFn}
|
|
3704
|
+
*/
|
|
3705
|
+
function manifestFetchCacheMiddleware$1(options = {}) {
|
|
3706
|
+
const ttlMs = typeof options.ttlMs === 'number' && Number.isFinite(options.ttlMs) ? options.ttlMs : 0;
|
|
3707
|
+
if (ttlMs <= 0) {
|
|
3708
|
+
return (next) => next
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
const storage = options.storage || 'memory';
|
|
3712
|
+
const prefix = options.storageKeyPrefix || 'wep.manifestFetch.v1';
|
|
3713
|
+
const maxEntries = typeof options.maxEntries === 'number' && options.maxEntries > 0 ? options.maxEntries : 50;
|
|
3714
|
+
const getNow = typeof options.now === 'function' ? options.now : () => Date.now();
|
|
3715
|
+
const cacheKeyFn =
|
|
3716
|
+
typeof options.cacheKey === 'function'
|
|
3717
|
+
? options.cacheKey
|
|
3718
|
+
: (ctx) => `${String(ctx.manifestUrl)}\0${String(ctx.credentials)}`;
|
|
3719
|
+
|
|
3720
|
+
const shouldCache =
|
|
3721
|
+
typeof options.shouldCache === 'function'
|
|
3722
|
+
? options.shouldCache
|
|
3723
|
+
: (r) => !!(r && r.ok === true && r.data != null);
|
|
3724
|
+
|
|
3725
|
+
/** @type {Map<string, { expiresAt: number, result: FetchWebPluginManifestResult, lastRead: number }>} */
|
|
3726
|
+
const memory = new Map();
|
|
3727
|
+
|
|
3728
|
+
function cloneResult(r) {
|
|
3729
|
+
try {
|
|
3730
|
+
if (typeof structuredClone === 'function') {
|
|
3731
|
+
return structuredClone(r)
|
|
3732
|
+
}
|
|
3733
|
+
} catch (_) {}
|
|
3734
|
+
try {
|
|
3735
|
+
return JSON.parse(JSON.stringify(r))
|
|
3736
|
+
} catch (_) {
|
|
3737
|
+
return { ...r, data: r.data }
|
|
3738
|
+
}
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3741
|
+
function touchMemory(key) {
|
|
3742
|
+
const e = memory.get(key);
|
|
3743
|
+
if (e) {
|
|
3744
|
+
e.lastRead = getNow();
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
function pruneMemory() {
|
|
3749
|
+
if (memory.size <= maxEntries) {
|
|
3750
|
+
return
|
|
3751
|
+
}
|
|
3752
|
+
const entries = [...memory.entries()].sort((a, b) => a[1].lastRead - b[1].lastRead);
|
|
3753
|
+
const drop = memory.size - maxEntries;
|
|
3754
|
+
for (let i = 0; i < drop; i++) {
|
|
3755
|
+
memory.delete(entries[i][0]);
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
function readWebStorage(store, key) {
|
|
3760
|
+
try {
|
|
3761
|
+
const raw = store.getItem(key);
|
|
3762
|
+
if (!raw) {
|
|
3763
|
+
return null
|
|
3764
|
+
}
|
|
3765
|
+
const o = JSON.parse(raw);
|
|
3766
|
+
if (!o || typeof o !== 'object') {
|
|
3767
|
+
return null
|
|
3768
|
+
}
|
|
3769
|
+
const exp = o.expiresAt;
|
|
3770
|
+
const res = o.result;
|
|
3771
|
+
if (typeof exp !== 'number' || getNow() > exp) {
|
|
3772
|
+
store.removeItem(key);
|
|
3773
|
+
return null
|
|
3774
|
+
}
|
|
3775
|
+
return /** @type {FetchWebPluginManifestResult} */ (res)
|
|
3776
|
+
} catch (_) {
|
|
3777
|
+
return null
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
|
|
3781
|
+
function writeWebStorage(store, key, result, expiresAt) {
|
|
3782
|
+
try {
|
|
3783
|
+
store.setItem(key, JSON.stringify({ expiresAt, result }));
|
|
3784
|
+
} catch (_) {
|
|
3785
|
+
/* Quota / 不可序列化 */
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
|
|
3789
|
+
return (next) => {
|
|
3790
|
+
return async (ctx) => {
|
|
3791
|
+
const key = cacheKeyFn(ctx);
|
|
3792
|
+
const now = getNow();
|
|
3793
|
+
|
|
3794
|
+
if (storage === 'memory') {
|
|
3795
|
+
const hit = memory.get(key);
|
|
3796
|
+
if (hit && hit.expiresAt > now) {
|
|
3797
|
+
touchMemory(key);
|
|
3798
|
+
return cloneResult(hit.result)
|
|
3799
|
+
}
|
|
3800
|
+
} else if (storage === 'session' && typeof sessionStorage !== 'undefined') {
|
|
3801
|
+
const sk = `${prefix}:${key}`;
|
|
3802
|
+
const hit = readWebStorage(sessionStorage, sk);
|
|
3803
|
+
if (hit) {
|
|
3804
|
+
return cloneResult(hit)
|
|
3805
|
+
}
|
|
3806
|
+
} else if (storage === 'local' && typeof localStorage !== 'undefined') {
|
|
3807
|
+
const sk = `${prefix}:${key}`;
|
|
3808
|
+
const hit = readWebStorage(localStorage, sk);
|
|
3809
|
+
if (hit) {
|
|
3810
|
+
return cloneResult(hit)
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
const result = await next(ctx);
|
|
3815
|
+
|
|
3816
|
+
if (!shouldCache(result)) {
|
|
3817
|
+
return result
|
|
3818
|
+
}
|
|
3819
|
+
|
|
3820
|
+
const expiresAt = now + ttlMs;
|
|
3821
|
+
const frozen = cloneResult(result);
|
|
3822
|
+
|
|
3823
|
+
if (storage === 'memory') {
|
|
3824
|
+
memory.set(key, { expiresAt, result: frozen, lastRead: now });
|
|
3825
|
+
pruneMemory();
|
|
3826
|
+
} else if (storage === 'session' && typeof sessionStorage !== 'undefined') {
|
|
3827
|
+
writeWebStorage(sessionStorage, `${prefix}:${key}`, frozen, expiresAt);
|
|
3828
|
+
} else if (storage === 'local' && typeof localStorage !== 'undefined') {
|
|
3829
|
+
writeWebStorage(localStorage, `${prefix}:${key}`, frozen, expiresAt);
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
return result
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3837
|
+
/**
|
|
3838
|
+
* 自右向左组合中间件(与 Koa/Redux 习惯一致:`compose(f,g,h)(inner)` = f(g(h(inner))))。
|
|
3839
|
+
*
|
|
3840
|
+
* @param {FetchWebPluginManifestFn} inner 最内层拉取实现
|
|
3841
|
+
* @param {...function(FetchWebPluginManifestFn): FetchWebPluginManifestFn} middlewares 每个元素签名 `(next) => async (ctx) => result`
|
|
3842
|
+
* @returns {FetchWebPluginManifestFn}
|
|
3843
|
+
*/
|
|
3844
|
+
function composeManifestFetch$1(inner, ...middlewares) {
|
|
3845
|
+
if (typeof inner !== 'function') {
|
|
3846
|
+
throw new Error('[web-extend-plugin-vue2] composeManifestFetch 需要 inner 为函数')
|
|
3847
|
+
}
|
|
3848
|
+
let f = inner;
|
|
3849
|
+
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
3850
|
+
const mw = middlewares[i];
|
|
3851
|
+
if (typeof mw !== 'function') {
|
|
3852
|
+
throw new Error('[web-extend-plugin-vue2] composeManifestFetch 中间件须为函数')
|
|
3853
|
+
}
|
|
3854
|
+
f = mw(f);
|
|
3855
|
+
}
|
|
3856
|
+
return f
|
|
3857
|
+
}
|
|
3858
|
+
|
|
3859
|
+
var manifestComposer = /*#__PURE__*/Object.freeze({
|
|
3860
|
+
__proto__: null,
|
|
3861
|
+
composeManifestFetch: composeManifestFetch$1,
|
|
3862
|
+
manifestFetchCacheMiddleware: manifestFetchCacheMiddleware$1,
|
|
3863
|
+
wrapManifestFetchWithCache: wrapManifestFetchWithCache$1
|
|
3864
|
+
});
|
|
3865
|
+
|
|
3574
3866
|
/**
|
|
3575
3867
|
* 插件通过宿主访问后端的受控通道:仅允许配置的前缀路径,默认 `/api/`;强制默认 `same-origin` 携带 Cookie。
|
|
3576
3868
|
* 前缀列表由 `createRequestBridge({ allowedPathPrefixes })` 传入,与 `defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes` 对齐。
|
|
@@ -3578,17 +3870,6 @@ async function bootstrapPlugins(router, createHostApiFactory, runtimeOptions) {
|
|
|
3578
3870
|
* @module bridge
|
|
3579
3871
|
*/
|
|
3580
3872
|
|
|
3581
|
-
/**
|
|
3582
|
-
* @param {string} p
|
|
3583
|
-
*/
|
|
3584
|
-
function ensureLeadingSlash(p) {
|
|
3585
|
-
const t = String(p || '').trim();
|
|
3586
|
-
if (!t) {
|
|
3587
|
-
return '/'
|
|
3588
|
-
}
|
|
3589
|
-
return t.startsWith('/') ? t : `/${t}`
|
|
3590
|
-
}
|
|
3591
|
-
|
|
3592
3873
|
/**
|
|
3593
3874
|
* @param {{ allowedPathPrefixes?: string[] }} [config]
|
|
3594
3875
|
*/
|
|
@@ -3597,7 +3878,7 @@ function createRequestBridge(config = {}) {
|
|
|
3597
3878
|
Array.isArray(config.allowedPathPrefixes) && config.allowedPathPrefixes.length > 0
|
|
3598
3879
|
? config.allowedPathPrefixes
|
|
3599
3880
|
: defaultWebExtendPluginRuntime.bridgeAllowedPathPrefixes;
|
|
3600
|
-
const allowedPathPrefixes = raw.map((p) =>
|
|
3881
|
+
const allowedPathPrefixes = raw.map((p) => ensureLeadingPath(p));
|
|
3601
3882
|
|
|
3602
3883
|
return {
|
|
3603
3884
|
/**
|
|
@@ -4018,19 +4299,234 @@ function installWebExtendPluginVue2(Vue, router, options) {
|
|
|
4018
4299
|
if (Vue && ExtensionPoint) {
|
|
4019
4300
|
Vue.component('ExtensionPoint', ExtensionPoint);
|
|
4020
4301
|
}
|
|
4021
|
-
const runtime = resolveRuntimeOptions(runtimeUser);
|
|
4022
|
-
return bootstrapPlugins(router, (id, r, kit) => createHostApi(id, r, kit), runtime)
|
|
4302
|
+
const runtime = resolveRuntimeOptions$1(runtimeUser);
|
|
4303
|
+
return bootstrapPlugins$1(router, (id, r, kit) => createHostApi(id, r, kit), runtime)
|
|
4304
|
+
}
|
|
4305
|
+
|
|
4306
|
+
/**
|
|
4307
|
+
* 预设:Vue CLI + 统一 axios(如若依 `utils/request`)。
|
|
4308
|
+
* 对外以 {@link presetVueCliAxios} 聚合;亦保留具名函数便于 tree-shaking。
|
|
4309
|
+
*
|
|
4310
|
+
* @module presets/vue-cli-axios
|
|
4311
|
+
*/
|
|
4312
|
+
|
|
4313
|
+
/**
|
|
4314
|
+
* @typedef {object} VueCliAxiosInstallPresetDeps
|
|
4315
|
+
* @property {(config: { url: string, method?: string, [key: string]: unknown }) => Promise<unknown>} request 宿主 axios 封装(已含 baseURL、Token 等)
|
|
4316
|
+
*/
|
|
4317
|
+
|
|
4318
|
+
/**
|
|
4319
|
+
* 将 `manifestBase + manifestListPath` 转为相对 `VUE_APP_BASE_API` 的路径(供 axios baseURL 拼接)。
|
|
4320
|
+
* @param {string} manifestUrl
|
|
4321
|
+
* @param {string} [apiBase]
|
|
4322
|
+
*/
|
|
4323
|
+
function manifestPathForVueCliApiBase(manifestUrl, apiBase) {
|
|
4324
|
+
const base = String(
|
|
4325
|
+
apiBase !== undefined
|
|
4326
|
+
? apiBase
|
|
4327
|
+
: (typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API) || ''
|
|
4328
|
+
).replace(/\/$/, '');
|
|
4329
|
+
if (typeof window === 'undefined') {
|
|
4330
|
+
return '/api/frontend-plugins'
|
|
4331
|
+
}
|
|
4332
|
+
const u = new URL(manifestUrl, window.location.origin);
|
|
4333
|
+
let path = u.pathname + u.search;
|
|
4334
|
+
if (base && path.startsWith(base)) {
|
|
4335
|
+
path = path.slice(base.length) || '/';
|
|
4336
|
+
}
|
|
4337
|
+
return path
|
|
4338
|
+
}
|
|
4339
|
+
|
|
4340
|
+
/**
|
|
4341
|
+
* 兼容裸清单 JSON 与常见 `{ code, data: { plugins } }` 包装。
|
|
4342
|
+
* @param {unknown} body
|
|
4343
|
+
* @returns {object|null}
|
|
4344
|
+
*/
|
|
4345
|
+
function unwrapTableStyleManifestBody(body) {
|
|
4346
|
+
if (!body || typeof body !== 'object') {
|
|
4347
|
+
return null
|
|
4348
|
+
}
|
|
4349
|
+
const o = /** @type {Record<string, unknown>} */ (body);
|
|
4350
|
+
if (Array.isArray(o.plugins)) {
|
|
4351
|
+
return o
|
|
4352
|
+
}
|
|
4353
|
+
const d = o.data;
|
|
4354
|
+
if (d && typeof d === 'object') {
|
|
4355
|
+
const inner = /** @type {Record<string, unknown>} */ (d);
|
|
4356
|
+
if (Array.isArray(inner.plugins)) {
|
|
4357
|
+
return inner
|
|
4358
|
+
}
|
|
4359
|
+
if ('plugins' in inner) {
|
|
4360
|
+
return inner
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
return d !== undefined && d !== null && typeof d === 'object' ? /** @type {object} */ (d) : o
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
function bridgePrefixesFromVueCliEnv() {
|
|
4367
|
+
const base = (
|
|
4368
|
+
typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API
|
|
4369
|
+
? String(process.env.VUE_APP_BASE_API)
|
|
4370
|
+
: ''
|
|
4371
|
+
).replace(/\/$/, '');
|
|
4372
|
+
const raw = [base ? `${base}/` : '', '/api/', '/dev-api/'].filter(Boolean);
|
|
4373
|
+
return [...new Set(raw)]
|
|
4374
|
+
}
|
|
4375
|
+
|
|
4376
|
+
/**
|
|
4377
|
+
* 生成可直接传给 `installWebExtendPluginVue2` 的 options(含 fetchManifest、manifestBase、bridge 前缀)。
|
|
4378
|
+
* @param {VueCliAxiosInstallPresetDeps} deps
|
|
4379
|
+
* @param {Record<string, unknown>} [extra] 合并覆盖,如 `manifestListPath`、`env` 等
|
|
4380
|
+
* @returns {Record<string, unknown>}
|
|
4381
|
+
*/
|
|
4382
|
+
function createVueCliAxiosInstallOptions(deps, extra = {}) {
|
|
4383
|
+
const { request } = deps;
|
|
4384
|
+
if (typeof request !== 'function') {
|
|
4385
|
+
throw new Error('[web-extend-plugin-vue2] createVueCliAxiosInstallOptions({ request }) 需要宿主 request 函数')
|
|
4386
|
+
}
|
|
4387
|
+
const envBase = (
|
|
4388
|
+
typeof process !== 'undefined' && process.env && process.env.VUE_APP_BASE_API
|
|
4389
|
+
? String(process.env.VUE_APP_BASE_API)
|
|
4390
|
+
: ''
|
|
4391
|
+
).replace(/\/$/, '');
|
|
4392
|
+
const userBase =
|
|
4393
|
+
extra.manifestBase !== undefined && String(extra.manifestBase).trim() !== ''
|
|
4394
|
+
? String(extra.manifestBase).replace(/\/$/, '')
|
|
4395
|
+
: '';
|
|
4396
|
+
const stripBase = userBase || envBase;
|
|
4397
|
+
|
|
4398
|
+
const fetchManifest = async (ctx) => {
|
|
4399
|
+
try {
|
|
4400
|
+
const url = manifestPathForVueCliApiBase(ctx.manifestUrl, stripBase);
|
|
4401
|
+
const body = await request({
|
|
4402
|
+
url,
|
|
4403
|
+
method: 'get'
|
|
4404
|
+
});
|
|
4405
|
+
const data = unwrapTableStyleManifestBody(body);
|
|
4406
|
+
if (!data || typeof data !== 'object') {
|
|
4407
|
+
return {
|
|
4408
|
+
ok: false,
|
|
4409
|
+
error: new Error('[web-plugin] 清单响应格式无效'),
|
|
4410
|
+
data: null
|
|
4411
|
+
}
|
|
4412
|
+
}
|
|
4413
|
+
return { ok: true, data }
|
|
4414
|
+
} catch (e) {
|
|
4415
|
+
return { ok: false, error: e, data: null }
|
|
4416
|
+
}
|
|
4417
|
+
};
|
|
4418
|
+
|
|
4419
|
+
const opts = {
|
|
4420
|
+
manifestBase: stripBase || undefined,
|
|
4421
|
+
bridgeAllowedPathPrefixes: bridgePrefixesFromVueCliEnv(),
|
|
4422
|
+
fetchManifest,
|
|
4423
|
+
...extra
|
|
4424
|
+
};
|
|
4425
|
+
|
|
4426
|
+
const listPath =
|
|
4427
|
+
typeof process !== 'undefined' && process.env && process.env.VUE_APP_WEB_PLUGIN_MANIFEST_PATH;
|
|
4428
|
+
if (listPath && opts.manifestListPath === undefined && extra.manifestListPath === undefined) {
|
|
4429
|
+
opts.manifestListPath = String(listPath);
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
return opts
|
|
4023
4433
|
}
|
|
4024
4434
|
|
|
4435
|
+
/**
|
|
4436
|
+
* Vue CLI + axios 预设的**对外聚合入口**(与具名导出函数等价,便于按需查阅与扩展多预设)。
|
|
4437
|
+
* @type {Readonly<{ id: string, description: string, createInstallOptions: typeof createVueCliAxiosInstallOptions, manifestPathForApiBase: typeof manifestPathForVueCliApiBase, unwrapManifestBody: typeof unwrapTableStyleManifestBody }>}
|
|
4438
|
+
*/
|
|
4439
|
+
const presetVueCliAxios = Object.freeze({
|
|
4440
|
+
id: 'vue-cli-axios',
|
|
4441
|
+
description: 'Vue CLI + 统一 axios 实例(如若依 utils/request),清单走宿主 request',
|
|
4442
|
+
createInstallOptions: createVueCliAxiosInstallOptions,
|
|
4443
|
+
manifestPathForApiBase: manifestPathForVueCliApiBase,
|
|
4444
|
+
unwrapManifestBody: unwrapTableStyleManifestBody
|
|
4445
|
+
});
|
|
4446
|
+
|
|
4447
|
+
/**
|
|
4448
|
+
* 稳定对外 API:具名导出 + {@link WebExtendPluginVue2} 聚合对象。
|
|
4449
|
+
* 语义化版本内保持本文件导出的符号与聚合结构兼容。
|
|
4450
|
+
*
|
|
4451
|
+
* `PluginRuntime` 与 `manifest-fetch-composer` 通过 namespace 绑定到 `WebExtendPluginVue2.runtime`,避免具名导出与聚合对象重复列举。
|
|
4452
|
+
*
|
|
4453
|
+
* @module public
|
|
4454
|
+
*/
|
|
4455
|
+
|
|
4456
|
+
|
|
4457
|
+
const {
|
|
4458
|
+
bootstrapPlugins,
|
|
4459
|
+
defaultFetchWebPluginManifest,
|
|
4460
|
+
resolveRuntimeOptions
|
|
4461
|
+
} = pluginRuntime;
|
|
4462
|
+
|
|
4463
|
+
const {
|
|
4464
|
+
composeManifestFetch,
|
|
4465
|
+
manifestFetchCacheMiddleware,
|
|
4466
|
+
wrapManifestFetchWithCache
|
|
4467
|
+
} = manifestComposer;
|
|
4468
|
+
|
|
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
|
+
const WebExtendPluginVue2 = Object.freeze({
|
|
4482
|
+
install: installWebExtendPluginVue2,
|
|
4483
|
+
runtime: Object.freeze({
|
|
4484
|
+
bootstrapPlugins: bootstrapPlugins$1,
|
|
4485
|
+
resolveRuntimeOptions: resolveRuntimeOptions$1,
|
|
4486
|
+
defaultFetchWebPluginManifest: defaultFetchWebPluginManifest$1,
|
|
4487
|
+
composeManifestFetch: composeManifestFetch$1,
|
|
4488
|
+
manifestFetchCacheMiddleware: manifestFetchCacheMiddleware$1,
|
|
4489
|
+
wrapManifestFetchWithCache: wrapManifestFetchWithCache$1
|
|
4490
|
+
}),
|
|
4491
|
+
host: Object.freeze({
|
|
4492
|
+
createHostApi,
|
|
4493
|
+
disposeWebPlugin,
|
|
4494
|
+
createRequestBridge,
|
|
4495
|
+
registries
|
|
4496
|
+
}),
|
|
4497
|
+
config: Object.freeze({
|
|
4498
|
+
defaultWebExtendPluginRuntime,
|
|
4499
|
+
setWebExtendPluginEnv
|
|
4500
|
+
}),
|
|
4501
|
+
constants: Object.freeze({
|
|
4502
|
+
HOST_PLUGIN_API_VERSION
|
|
4503
|
+
}),
|
|
4504
|
+
components: Object.freeze({
|
|
4505
|
+
ExtensionPoint
|
|
4506
|
+
}),
|
|
4507
|
+
presets: Object.freeze({
|
|
4508
|
+
vueCliAxios: presetVueCliAxios
|
|
4509
|
+
})
|
|
4510
|
+
});
|
|
4511
|
+
|
|
4025
4512
|
exports.ExtensionPoint = ExtensionPoint;
|
|
4026
4513
|
exports.HOST_PLUGIN_API_VERSION = HOST_PLUGIN_API_VERSION;
|
|
4514
|
+
exports.WebExtendPluginVue2 = WebExtendPluginVue2;
|
|
4027
4515
|
exports.bootstrapPlugins = bootstrapPlugins;
|
|
4516
|
+
exports.composeManifestFetch = composeManifestFetch;
|
|
4028
4517
|
exports.createHostApi = createHostApi;
|
|
4029
4518
|
exports.createRequestBridge = createRequestBridge;
|
|
4519
|
+
exports.createVueCliAxiosInstallOptions = createVueCliAxiosInstallOptions;
|
|
4520
|
+
exports.defaultFetchWebPluginManifest = defaultFetchWebPluginManifest;
|
|
4030
4521
|
exports.defaultWebExtendPluginRuntime = defaultWebExtendPluginRuntime;
|
|
4031
4522
|
exports.disposeWebPlugin = disposeWebPlugin;
|
|
4032
4523
|
exports.installWebExtendPluginVue2 = installWebExtendPluginVue2;
|
|
4524
|
+
exports.manifestFetchCacheMiddleware = manifestFetchCacheMiddleware;
|
|
4525
|
+
exports.manifestPathForVueCliApiBase = manifestPathForVueCliApiBase;
|
|
4526
|
+
exports.presetVueCliAxios = presetVueCliAxios;
|
|
4033
4527
|
exports.registries = registries;
|
|
4034
4528
|
exports.resolveRuntimeOptions = resolveRuntimeOptions;
|
|
4035
4529
|
exports.setWebExtendPluginEnv = setWebExtendPluginEnv;
|
|
4530
|
+
exports.unwrapTableStyleManifestBody = unwrapTableStyleManifestBody;
|
|
4531
|
+
exports.wrapManifestFetchWithCache = wrapManifestFetchWithCache;
|
|
4036
4532
|
//# sourceMappingURL=index.cjs.map
|