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