vite-add-cdn-script 0.0.11 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,23 +1,30 @@
1
- var q = Object.defineProperty;
2
- var G = (r, t, e) => t in r ? q(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
- var g = (r, t, e) => (G(r, typeof t != "symbol" ? t + "" : t, e), e);
4
- import A from "node:path";
5
- import E from "node:fs";
1
+ var X = Object.defineProperty;
2
+ var Y = (s, e, t) => e in s ? X(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var f = (s, e, t) => (Y(s, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import M from "node:path";
5
+ import P from "node:fs";
6
6
  import O from "node-fetch";
7
7
  import V from "semver";
8
- class B {
8
+ var L = /* @__PURE__ */ ((s) => (s.noFound = "noFound", s.NetworkError = "networkError", s))(L || {});
9
+ class Z {
9
10
  constructor() {
10
- g(this, "cdnCache", {});
11
- g(this, "cdnCachePath", "");
12
- this.cdnCachePath = A.resolve(process.cwd(), "./.cdn-cache.json");
11
+ f(this, "cdnCache", {
12
+ packageDependencies: {},
13
+ cdnsUrl: {}
14
+ });
15
+ f(this, "cdnCachePath", "");
16
+ this.cdnCachePath = M.resolve(process.cwd(), "./.cdn-cache.json");
13
17
  }
14
18
  // 初始化cdn缓存
15
19
  async init() {
16
20
  try {
17
- const t = await E.readFileSync(this.cdnCachePath, "utf-8");
18
- this.cdnCache = JSON.parse(t);
21
+ const e = await P.readFileSync(this.cdnCachePath, "utf-8");
22
+ this.cdnCache = JSON.parse(e);
19
23
  } catch {
20
- console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {}, await E.writeFileSync(this.cdnCachePath, "", "utf-8");
24
+ console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {
25
+ packageDependencies: {},
26
+ cdnsUrl: {}
27
+ }, await P.writeFileSync(this.cdnCachePath, "", "utf-8");
21
28
  }
22
29
  }
23
30
  /**
@@ -25,9 +32,9 @@ class B {
25
32
  * @param packageName 包名
26
33
  * @param version 版本
27
34
  */
28
- getCdnCache(t, e) {
29
- var s;
30
- return (s = this.cdnCache[t]) == null ? void 0 : s[e];
35
+ getCdnCache(e, t) {
36
+ var r;
37
+ return (r = this.cdnCache.cdnsUrl[e]) == null ? void 0 : r[t];
31
38
  }
32
39
  /**
33
40
  * 设置cdn缓存
@@ -35,46 +42,88 @@ class B {
35
42
  * @param version 版本
36
43
  * @param urls 地址列表
37
44
  */
38
- setCdnCache(t, e, s) {
39
- this.cdnCache[t] ? this.cdnCache[t][e] = s : this.cdnCache[t] = {
40
- [e]: s
45
+ setCdnCache(e, t, r) {
46
+ this.cdnCache.cdnsUrl[e] ? this.cdnCache.cdnsUrl[e][t] = r : this.cdnCache.cdnsUrl[e] = {
47
+ [t]: r
41
48
  };
42
49
  }
43
50
  /**
44
51
  * 更新cdn缓存
45
52
  */
46
53
  async save() {
47
- await E.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
54
+ await P.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
55
+ }
56
+ /**
57
+ * 获取依赖包的package.json
58
+ * @param packageName 包名
59
+ * @param identification 版本号或者url
60
+ */
61
+ getPackageDependencies(e, t) {
62
+ var r;
63
+ return (r = this.cdnCache.packageDependencies[e]) == null ? void 0 : r[t];
64
+ }
65
+ /**
66
+ * 设置依赖包的package.json
67
+ * @param packageName 包名
68
+ * @param identification 版本号或者url
69
+ * @param dependencies 依赖
70
+ */
71
+ setPackageDependencies(e, t, r) {
72
+ this.cdnCache.packageDependencies[e] ? this.cdnCache.packageDependencies[e][t] = r : this.cdnCache.packageDependencies[e] = {
73
+ [t]: r
74
+ };
48
75
  }
49
76
  }
50
- let U;
51
- const z = async () => (U || (U = new B(), await U.init()), U);
52
- class u extends Error {
53
- constructor(t) {
54
- super(t), this.name = "NetworkError";
77
+ let C;
78
+ const A = async () => (C || (C = new Z(), await C.init()), C);
79
+ class g extends Error {
80
+ constructor(e) {
81
+ super(e), this.name = "NetworkError";
55
82
  }
56
83
  }
57
- class P extends u {
58
- constructor({ packageName: t, version: e, cdn: s }) {
59
- super(`${s} ${t}@${e} 网络请求失败`), this.name = "PackageNetworkError";
84
+ class y extends g {
85
+ constructor({ packageName: t, version: r, cdn: n }) {
86
+ super(`${n} ${t}@${r} 网络请求失败`);
87
+ f(this, "cdn");
88
+ f(this, "packageName");
89
+ f(this, "version");
90
+ this.name = "PackageNetworkError", this.cdn = n, this.packageName = t, this.version = r;
91
+ }
92
+ getErrorInfo() {
93
+ return {
94
+ cdn: this.cdn,
95
+ packageName: this.packageName,
96
+ version: this.version
97
+ };
60
98
  }
61
99
  }
62
- class m extends Error {
63
- constructor({ packageName: t, version: e, cdn: s }) {
64
- super(`${s}上没有${t}@${e}的版本`), this.name = "NoVersionError";
100
+ class k extends Error {
101
+ constructor({ packageName: t, version: r, cdn: n }) {
102
+ super(`${n}上没有${t}@${r}的版本`);
103
+ f(this, "cdn");
104
+ f(this, "packageName");
105
+ f(this, "version");
106
+ this.name = "NoVersionError", this.cdn = n, this.packageName = t, this.version = r;
107
+ }
108
+ getErrorInfo() {
109
+ return {
110
+ cdn: this.cdn,
111
+ packageName: this.packageName,
112
+ version: this.version
113
+ };
65
114
  }
66
115
  }
67
- class K extends Error {
68
- constructor({ packageName: t, version: e, cdn: s }) {
69
- super(`在 ${s} 中找不到 ${t}@${e} 文件,请检查包名或版本号`), this.name = "GetFileListError";
116
+ class ee extends Error {
117
+ constructor({ packageName: e, version: t, cdn: r }) {
118
+ super(`在 ${r} 中找不到 ${e}@${t} 文件,请检查包名或版本号`), this.name = "GetFileListError";
70
119
  }
71
120
  }
72
- class N {
73
- constructor(t) {
74
- g(this, "_max");
75
- g(this, "_count");
76
- g(this, "_taskQueue");
77
- this._max = t || 5, this._count = 0, this._taskQueue = [];
121
+ class te {
122
+ constructor(e) {
123
+ f(this, "_max");
124
+ f(this, "_count");
125
+ f(this, "_taskQueue");
126
+ this._max = e || 5, this._count = 0, this._taskQueue = [];
78
127
  }
79
128
  /**
80
129
  * 请求封装
@@ -82,10 +131,10 @@ class N {
82
131
  * @param args 请求参数
83
132
  * @returns {Promise<any>} 返回一个promise
84
133
  */
85
- call(t, ...e) {
86
- return new Promise((s, n) => {
87
- const o = this._createTask(t, e, s, n);
88
- this._count >= this._max ? this._taskQueue.push(o) : o();
134
+ call(e, ...t) {
135
+ return new Promise((r, n) => {
136
+ const c = this._createTask(e, t, r, n);
137
+ this._count >= this._max ? this._taskQueue.push(c) : c();
89
138
  });
90
139
  }
91
140
  /**
@@ -97,225 +146,225 @@ class N {
97
146
  * @returns {Function} 返回一个任务函数
98
147
  * @private
99
148
  */
100
- _createTask(t, e, s, n) {
149
+ _createTask(e, t, r, n) {
101
150
  return () => {
102
- t(...e).then(s).catch(n).finally(() => {
151
+ e(...t).then(r).catch(n).finally(() => {
103
152
  this._count--, this._taskQueue.length && this._taskQueue.shift()();
104
153
  }), this._count++;
105
154
  };
106
155
  }
107
156
  }
108
- const _ = new N(5), J = async (r) => {
157
+ const b = new te(5), J = async (s) => {
109
158
  try {
110
- const t = await O(r, { method: "HEAD", redirect: "manual" });
111
- return t.status >= 300 && t.status < 400 ? await J(t.headers.get("location") || "") : r;
112
- } catch (t) {
113
- throw Promise.reject(new u(t.message));
159
+ const e = await O(s, { method: "HEAD", redirect: "manual" });
160
+ return e.status >= 300 && e.status < 400 ? await J(e.headers.get("location") || "") : s;
161
+ } catch (e) {
162
+ throw new g(e.message);
114
163
  }
115
- }, W = {
164
+ }, se = {
116
165
  //get请求封装
117
- get: async (r) => {
166
+ get: async (s) => {
118
167
  try {
119
- const t = await O(r);
120
- if (t.ok) {
121
- const e = t.headers.get("content-type"), s = await t.text();
122
- return e && e.includes("application/json") ? JSON.parse(s) : s;
168
+ const e = await O(s);
169
+ if (e.ok) {
170
+ const t = e.headers.get("content-type"), r = await e.text();
171
+ return t && t.includes("application/json") ? JSON.parse(r) : r;
123
172
  } else
124
- throw new u(`请求失败,状态码:${t.status}`);
125
- } catch (t) {
126
- throw new u(t.message);
173
+ throw new g(`请求失败,状态码:${e.status}`);
174
+ } catch (e) {
175
+ throw new g(e.message);
127
176
  }
128
177
  }
129
- }, $ = {
130
- get: _.call.bind(_, W.get)
131
- }, X = async (r, t) => {
178
+ }, j = {
179
+ get: b.call.bind(b, se.get)
180
+ }, re = async (s, e) => {
132
181
  try {
133
- const e = await $.get(`https://api.bootcdn.cn/libraries/${r}`);
134
- if (e.length === 0)
135
- throw new m({
136
- packageName: r,
137
- version: t,
182
+ const t = await j.get(`https://api.bootcdn.cn/libraries/${s}`);
183
+ if (t.length === 0)
184
+ throw new k({
185
+ packageName: s,
186
+ version: e,
138
187
  cdn: "bootcdn"
139
188
  });
140
- const s = e[0], o = s.assets.reverse().find((c) => {
141
- if (V.satisfies(c.version, t))
189
+ const r = t[0], c = r.assets.reverse().find((i) => {
190
+ if (V.satisfies(i.version, e))
142
191
  return !0;
143
192
  });
144
- if (!o)
145
- throw new m({
146
- packageName: r,
147
- version: t,
193
+ if (!c)
194
+ throw new k({
195
+ packageName: s,
196
+ version: e,
148
197
  cdn: "bootcdn"
149
198
  });
150
- return { fileList: o.files.map((c) => ({
151
- name: "/" + c
152
- })), recommendFileName: s.filename, version: o.version };
153
- } catch (e) {
154
- throw e instanceof u ? new P({
155
- packageName: r,
156
- version: t,
157
- cdn: "unpkg"
158
- }) : e;
199
+ return { fileList: c.files.map((i) => ({
200
+ name: "/" + i
201
+ })), recommendFileName: r.filename, version: c.version };
202
+ } catch (t) {
203
+ throw t instanceof g ? new y({
204
+ packageName: s,
205
+ version: e,
206
+ cdn: "bootcdn"
207
+ }) : t;
159
208
  }
160
- }, Y = (r, t, e) => `https://cdn.bootcdn.net/ajax/libs/${r}/${t}${e}`, Z = {
161
- getFileList: X,
162
- getUrl: Y
209
+ }, ne = (s, e, t) => `https://cdn.bootcdn.net/ajax/libs/${s}/${e}${t}`, ce = {
210
+ getFileList: re,
211
+ getUrl: ne
163
212
  };
164
- async function M(r, t, e = !1) {
213
+ async function I(s, e, t = !1) {
165
214
  try {
166
- if (!e && t.match(/^\D/)) {
167
- const n = await et(r, t);
168
- for (let o of n)
169
- if (V.satisfies(o, t))
170
- return M(r, o, !0);
171
- throw new m({
172
- packageName: r,
173
- version: t,
215
+ if (!t && e.match(/^\D/)) {
216
+ const n = await ie(s, e);
217
+ for (let c of n)
218
+ if (V.satisfies(c, e))
219
+ return I(s, c, !0);
220
+ throw new k({
221
+ packageName: s,
222
+ version: e,
174
223
  cdn: "cdnjs"
175
224
  });
176
225
  }
177
- const s = await $.get(`https://api.cdnjs.com/libraries/${r}/${t}`);
178
- if (s.error)
179
- throw new m({
180
- packageName: r,
181
- version: t,
226
+ const r = await j.get(`https://api.cdnjs.com/libraries/${s}/${e}`);
227
+ if (r.error)
228
+ throw new k({
229
+ packageName: s,
230
+ version: e,
182
231
  cdn: "cdnjs"
183
232
  });
184
233
  return {
185
- fileList: s.rawFiles.map((n) => ({
234
+ fileList: r.rawFiles.map((n) => ({
186
235
  name: "/" + n
187
236
  })),
188
- version: t
237
+ version: e
189
238
  };
190
- } catch (s) {
191
- throw s instanceof u ? new P({
192
- packageName: r,
193
- version: t,
194
- cdn: "unpkg"
195
- }) : s;
239
+ } catch (r) {
240
+ throw r instanceof g ? new y({
241
+ packageName: s,
242
+ version: e,
243
+ cdn: "cdnjs"
244
+ }) : r;
196
245
  }
197
246
  }
198
- const tt = (r, t, e) => `https://cdnjs.cloudflare.com/ajax/libs/${r}/${t}${e}`, et = async (r, t) => {
247
+ const oe = (s, e, t) => `https://cdnjs.cloudflare.com/ajax/libs/${s}/${e}${t}`, ie = async (s, e) => {
199
248
  try {
200
- return (await $.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions;
201
- } catch (e) {
202
- throw e instanceof u ? new P({
203
- packageName: r,
204
- version: t,
205
- cdn: "unpkg"
206
- }) : e;
249
+ return (await j.get(`https://api.cdnjs.com/libraries/${s}?fields=versions`)).versions;
250
+ } catch (t) {
251
+ throw t instanceof g ? new y({
252
+ packageName: s,
253
+ version: e,
254
+ cdn: "cdnjs"
255
+ }) : t;
207
256
  }
208
- }, rt = {
209
- getFileList: M,
210
- getUrl: tt
211
- }, I = (r, t = "") => r.reduce((e, s) => (s.type === "file" ? e.push({ name: `${t}/${s.name}` }) : s.files && e.push(...I(s.files, `${t}/${s.name}`)), e), []);
212
- async function Q(r, t, e = !1) {
257
+ }, ae = {
258
+ getFileList: I,
259
+ getUrl: oe
260
+ }, N = (s, e = "") => s.reduce((t, r) => (r.type === "file" ? t.push({ name: `${e}/${r.name}` }) : r.files && t.push(...N(r.files, `${e}/${r.name}`)), t), []);
261
+ async function Q(s, e, t = !1) {
213
262
  try {
214
- if (!e && t.match(/^\D/)) {
215
- const n = await nt(r, t);
263
+ if (!t && e.match(/^\D/)) {
264
+ const n = await de(s, e);
216
265
  if (typeof n == "string")
217
- return Q(r, n, !0);
218
- throw new m({
219
- packageName: r,
220
- version: t,
266
+ return Q(s, n, !0);
267
+ throw new k({
268
+ packageName: s,
269
+ version: e,
221
270
  cdn: "jsdelivr"
222
271
  });
223
272
  }
224
- const s = await $.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${t}`);
225
- if (s.status)
226
- throw new m({
227
- packageName: r,
228
- version: t,
273
+ const r = await j.get(`https://data.jsdelivr.com/v1/packages/npm/${s}@${e}`);
274
+ if (r.status)
275
+ throw new k({
276
+ packageName: s,
277
+ version: e,
229
278
  cdn: "jsdelivr"
230
279
  });
231
- return { fileList: I(s.files), version: t };
232
- } catch (s) {
233
- throw s instanceof u ? new P({
234
- packageName: r,
235
- version: t,
236
- cdn: "unpkg"
237
- }) : s;
280
+ return { fileList: N(r.files), version: e };
281
+ } catch (r) {
282
+ throw r instanceof g ? new y({
283
+ packageName: s,
284
+ version: e,
285
+ cdn: "jsdelivr"
286
+ }) : r;
238
287
  }
239
288
  }
240
- const st = (r, t, e) => `https://cdn.jsdelivr.net/npm/${r}@${t}${e}`, nt = async (r, t) => {
289
+ const le = (s, e, t) => `https://cdn.jsdelivr.net/npm/${s}@${e}${t}`, de = async (s, e) => {
241
290
  try {
242
- return (await $.get(
243
- `https://data.jsdelivr.com/v1/packages/npm/${r}/resolved?specifier=${t}`
291
+ return (await j.get(
292
+ `https://data.jsdelivr.com/v1/packages/npm/${s}/resolved?specifier=${e}`
244
293
  )).version;
245
- } catch (e) {
246
- throw e instanceof u ? new P({
247
- packageName: r,
248
- version: t,
249
- cdn: "unpkg"
250
- }) : e;
294
+ } catch (t) {
295
+ throw t instanceof g ? new y({
296
+ packageName: s,
297
+ version: e,
298
+ cdn: "jsdelivr"
299
+ }) : t;
251
300
  }
252
- }, ct = {
301
+ }, ue = {
253
302
  getFileList: Q,
254
303
  // 拼接url
255
- getUrl: st
256
- }, T = (r) => r.reduce((t, e) => (e.type === "file" ? t.push({ name: e.path }) : e.files && t.push(...T(e.files)), t), []);
257
- async function ot(r, t) {
258
- var e;
304
+ getUrl: le
305
+ }, T = (s) => s.reduce((e, t) => (t.type === "file" ? e.push({ name: t.path }) : t.files && e.push(...T(t.files)), e), []);
306
+ async function he(s, e) {
307
+ var t;
259
308
  try {
260
- const n = (e = (await J(`https://unpkg.com/${r}@${t}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)"))) == null ? void 0 : e[0];
309
+ const n = (t = (await J(`https://unpkg.com/${s}@${e}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)"))) == null ? void 0 : t[0];
261
310
  if (n) {
262
- const o = await $.get(`https://unpkg.com/${r}@${n}/?meta`);
263
- return { fileList: T(o.files || []), version: n };
311
+ const c = await j.get(`https://unpkg.com/${s}@${n}/?meta`);
312
+ return { fileList: T(c.files || []), version: n };
264
313
  } else
265
- throw new m({
266
- packageName: r,
267
- version: t,
314
+ throw new k({
315
+ packageName: s,
316
+ version: e,
268
317
  cdn: "unpkg"
269
318
  });
270
- } catch (s) {
271
- throw s instanceof u ? new P({
272
- packageName: r,
273
- version: t,
319
+ } catch (r) {
320
+ throw r instanceof g ? new y({
321
+ packageName: s,
322
+ version: e,
274
323
  cdn: "unpkg"
275
- }) : s;
324
+ }) : r;
276
325
  }
277
326
  }
278
- function it(r, t, e) {
279
- return `https://unpkg.com/${r}@${t}${e}`;
327
+ function fe(s, e, t) {
328
+ return `https://unpkg.com/${s}@${e}${t}`;
280
329
  }
281
- const at = {
282
- getFileList: ot,
283
- getUrl: it
284
- }, lt = async (r) => {
330
+ const pe = {
331
+ getFileList: he,
332
+ getUrl: fe
333
+ }, ge = async (s) => {
285
334
  try {
286
- const t = /^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;
287
- if (t.test(r)) {
288
- const e = r.replace(t, (s, n) => `${n}package.json`);
289
- return await $.get(e);
335
+ const e = /^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;
336
+ if (e.test(s)) {
337
+ const t = s.replace(e, (r, n) => `${n}package.json`);
338
+ return await j.get(t);
290
339
  } else
291
- throw new Error(`${r} 不是正确的url`);
292
- } catch (t) {
293
- throw t;
294
- }
295
- }, ut = (r, t) => {
296
- var e, s;
297
- return ((e = r.dependencies) == null ? void 0 : e[t]) || ((s = r.devDependencies) == null ? void 0 : s[t]);
298
- }, dt = async (r, t, e) => {
299
- if (!t.match(/\d+(.\d+)?(.\d+)?/))
300
- throw new Error(`${r} version ${t} is not valid`);
301
- const n = await D[e].getFileList(r, t), o = ht(n, r);
302
- if (!o)
303
- throw new K({
304
- packageName: r,
305
- version: t,
306
- cdn: e
340
+ throw new Error(`${s} 不是正确的url`);
341
+ } catch (e) {
342
+ throw e;
343
+ }
344
+ }, we = (s, e) => {
345
+ var t, r;
346
+ return ((t = s.dependencies) == null ? void 0 : t[e]) || ((r = s.devDependencies) == null ? void 0 : r[e]);
347
+ }, F = async (s, e, t) => {
348
+ if (!e.match(/\d+(.\d+)?(.\d+)?/))
349
+ throw new Error(`${s} version ${e} is not valid`);
350
+ const n = await S[t].getFileList(s, e), c = me(n, s);
351
+ if (!c)
352
+ throw new ee({
353
+ packageName: s,
354
+ version: e,
355
+ cdn: t
307
356
  });
308
- return D[e].getUrl(r, n.version, o);
309
- }, ht = ({ fileList: r }, t) => {
310
- var o, a;
311
- let e = [
312
- `umd/${t}.production.min.js`,
357
+ return S[t].getUrl(s, n.version, c);
358
+ }, me = ({ fileList: s }, e) => {
359
+ var c, d;
360
+ let t = [
361
+ `umd/${e}.production.min.js`,
313
362
  /umd\/.+?\.production\.min\.js$/,
314
363
  /dist\/.+?\.production\.min\.js$/,
315
364
  /dist\/.+?\.umd\.min\.js$/,
316
- `dist/${t}.prod.min.js`,
365
+ `dist/${e}.prod.min.js`,
317
366
  /dist\/.+?\.global.prod.min.js/,
318
- `dist/${t}.min.js`,
367
+ `dist/${e}.min.js`,
319
368
  /.+?\.global.prod.min.js/,
320
369
  /.+?.global.prod.js/,
321
370
  /lib\/.+?\.min\.js$/,
@@ -325,72 +374,196 @@ const at = {
325
374
  /\.min\.js$/,
326
375
  /\.js$/
327
376
  ];
328
- const s = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((c) => !t.includes(c));
377
+ const r = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((i) => !e.includes(i));
329
378
  let n = "";
330
- for (let c of e)
331
- if (c instanceof RegExp ? n = ((o = r.find((i) => c.test(i.name) && !s.some((f) => i.name.includes(f)))) == null ? void 0 : o.name) || "" : n = ((a = r.find((i) => i.name.includes(c) && !s.some((f) => i.name.includes(f)))) == null ? void 0 : a.name) || "", n)
379
+ for (let i of t)
380
+ if (i instanceof RegExp ? n = ((c = s.find((o) => i.test(o.name) && !r.some((u) => o.name.includes(u)))) == null ? void 0 : c.name) || "" : n = ((d = s.find((o) => o.name.includes(i) && !r.some((u) => o.name.includes(u)))) == null ? void 0 : d.name) || "", n)
332
381
  break;
333
382
  return n;
334
- }, D = {
335
- jsdelivr: ct,
336
- bootcdn: Z,
337
- cdnjs: rt,
338
- unpkg: at
383
+ }, S = {
384
+ jsdelivr: ue,
385
+ bootcdn: ce,
386
+ cdnjs: ae,
387
+ unpkg: pe
339
388
  };
340
- function ft(r, t) {
341
- const e = r.replace(/^\D/, "").split("."), s = t.replace(/^\D/, "").split("."), n = Math.max(e.length, s.length);
342
- for (; e.length < n; )
343
- e.push("0");
344
- for (; s.length < n; )
345
- s.push("0");
346
- for (let o = 0; o < n; o++) {
347
- const a = parseInt(e[o], 10), c = parseInt(s[o], 10);
348
- if (a > c)
389
+ function $e(s, e) {
390
+ const t = s.replace(/^\D/, "").split("."), r = e.replace(/^\D/, "").split("."), n = Math.max(t.length, r.length);
391
+ for (; t.length < n; )
392
+ t.push("0");
393
+ for (; r.length < n; )
394
+ r.push("0");
395
+ for (let c = 0; c < n; c++) {
396
+ const d = parseInt(t[c], 10), i = parseInt(r[c], 10);
397
+ if (d > i)
349
398
  return 1;
350
- if (a < c)
399
+ if (d < i)
351
400
  return -1;
352
401
  }
353
402
  return 0;
354
403
  }
355
- function pt(r, t) {
356
- for (let e in t)
357
- Object.prototype.hasOwnProperty.call(t, e) && (r[e] ? ft(r[e], t[e]) === -1 && (r[e] = t[e]) : r[e] = t[e]);
358
- return r;
404
+ function _(s, e) {
405
+ for (let t in e)
406
+ Object.prototype.hasOwnProperty.call(e, t) && (s[t] ? $e(s[t], e[t]) === -1 && (s[t] = e[t]) : s[t] = e[t]);
407
+ return s;
408
+ }
409
+ async function R({
410
+ external: s,
411
+ packageData: e,
412
+ customScript: t,
413
+ defaultCdns: r
414
+ }) {
415
+ let n = [], c = !1, d = [];
416
+ const i = await A();
417
+ return await Promise.all(
418
+ s.map(async (o) => {
419
+ const u = we(e, o);
420
+ if (t[o])
421
+ return {
422
+ urls: [t[o]],
423
+ key: o
424
+ };
425
+ if (!u)
426
+ return n.push(o), {
427
+ urls: [],
428
+ key: o
429
+ };
430
+ const p = i.getCdnCache(o, u);
431
+ if (p) {
432
+ const h = new Set(r), w = /* @__PURE__ */ new Map(), m = p.filter((a, l) => {
433
+ if (h.has(a.cdnName) && a.success)
434
+ return h.delete(a.cdnName), !0;
435
+ !a.success && a.error === L.noFound ? h.delete(a.cdnName) : w.set(a.cdnName, l);
436
+ }).map((a) => a.url);
437
+ if (h.size > 0) {
438
+ const a = await Promise.allSettled(
439
+ [...h].map(async (l) => ({
440
+ cdnName: l,
441
+ success: !0,
442
+ url: await F(o, u, l)
443
+ }))
444
+ ).then((l) => l.filter(($) => {
445
+ if ($.status === "fulfilled")
446
+ return m.push($.value.url), !0;
447
+ d.push($.reason);
448
+ }));
449
+ a.length > 0 && (a.forEach((l) => {
450
+ const $ = w.get(l.value.cdnName);
451
+ $ !== void 0 ? p[$] = l.value : p.push(l.value);
452
+ }), i.setCdnCache(o, u, p), c = !0);
453
+ }
454
+ return {
455
+ urls: m,
456
+ version: u,
457
+ key: o
458
+ };
459
+ } else {
460
+ c = !0, console.log(`从网络获取${o}${u}的cdn地址`);
461
+ const h = await Promise.allSettled(
462
+ r.map(async (a) => ({
463
+ cdnName: a,
464
+ success: !0,
465
+ url: await F(o, u, a)
466
+ }))
467
+ ).then((a) => a.map((l) => {
468
+ if (l.status === "fulfilled")
469
+ return l.value;
470
+ if (d.push(l.reason), l.reason instanceof y || l.reason instanceof k)
471
+ return {
472
+ cdnName: l.reason.cdn,
473
+ success: !1,
474
+ error: l.reason instanceof y ? L.NetworkError : L.noFound
475
+ };
476
+ }).filter((l) => !!l)), w = h.filter((a) => a.success).map(
477
+ (a) => a.url
478
+ );
479
+ if (w.length === 0)
480
+ throw new Error(`
481
+ ${d.map((a) => a.message).join(`
482
+ `)}获取${o} ${u}的cdn地址失败`);
483
+ const m = {
484
+ urls: w,
485
+ version: u,
486
+ key: o
487
+ };
488
+ return i.setCdnCache(o, u, h), m;
489
+ }
490
+ })
491
+ ).then((o) => (c && i.save(), {
492
+ urls: o,
493
+ noVersionPackages: n,
494
+ errorList: d
495
+ }));
359
496
  }
360
- class wt {
497
+ const ye = async ({
498
+ packageVersionInfo: s
499
+ }) => {
500
+ const e = { dependencies: {} };
501
+ let t = !1;
502
+ const r = await A(), n = [];
503
+ return await Promise.allSettled(
504
+ s.map(async (c) => {
505
+ if (!c)
506
+ return;
507
+ const { urls: d } = c, i = d[0];
508
+ if (!i)
509
+ return;
510
+ const o = c.version || i, u = r.getPackageDependencies(c.key, o);
511
+ if (u)
512
+ return _(e.dependencies, u.dependencies);
513
+ const p = await ge(i);
514
+ r.setPackageDependencies(c.key, o, {
515
+ dependencies: p.dependencies
516
+ }), t = !0, _(e.dependencies, p.dependencies);
517
+ })
518
+ ).then((c) => (t && r.save(), c.forEach((d) => {
519
+ d.status === "rejected" && n.push(d.reason);
520
+ }), {
521
+ urlPackageJsonRes: e,
522
+ errorList: n
523
+ }));
524
+ }, H = "vite-add-cdn-script";
525
+ class ke {
361
526
  constructor() {
362
527
  // 打印记录
363
- g(this, "logList", []);
528
+ f(this, "logList", []);
364
529
  }
365
530
  // 打印方法
366
- log(t) {
531
+ log(e) {
367
532
  this.logList.push({
368
533
  type: "log",
369
- message: t
534
+ message: e
370
535
  });
371
536
  }
372
- warn(t) {
537
+ warn(e) {
373
538
  this.logList.push({
374
539
  type: "warn",
375
- message: t
540
+ message: e
376
541
  });
377
542
  }
378
- error(t) {
543
+ error(e) {
379
544
  this.logList.push({
380
545
  type: "error",
381
- message: t
546
+ message: e
382
547
  });
383
548
  }
384
- info(t) {
549
+ info(e) {
385
550
  this.logList.push({
386
551
  type: "info",
387
- message: t
552
+ message: e
388
553
  });
389
554
  }
390
555
  // 打印全部
391
556
  consoleAll() {
392
- this.logList.forEach((t) => {
393
- console[t.type](`${H} ${t.message}`);
557
+ console.log(""), this.logList.forEach((e) => {
558
+ console[e.type](`${H} ${e.message}`);
559
+ });
560
+ }
561
+ addMessageList(e, t) {
562
+ t.forEach((r) => {
563
+ this.logList.push({
564
+ type: e,
565
+ message: r.toString()
566
+ });
394
567
  });
395
568
  }
396
569
  // 清除打印记录
@@ -398,165 +571,111 @@ class wt {
398
571
  this.logList = [];
399
572
  }
400
573
  }
401
- const H = "vite-add-cdn-script", b = new wt();
402
- async function R({
403
- external: r,
404
- packageData: t,
405
- customScript: e,
406
- defaultCdns: s
407
- }) {
408
- let n = [], o = !1;
409
- const a = await z();
410
- return await Promise.all(
411
- r.map(async (c) => {
412
- const i = ut(t, c);
413
- if (e[c])
414
- return {
415
- urls: [],
416
- key: c
417
- };
418
- if (!i)
419
- return n.push(c), {
420
- urls: [],
421
- key: c
422
- };
423
- const f = a.getCdnCache(c, i);
424
- if (f)
425
- return {
426
- urls: f,
427
- key: c
428
- };
429
- {
430
- o = !0, console.log(`从网络获取${c}${i}的cdn地址`);
431
- const d = await Promise.allSettled(
432
- s.map(async (j) => await dt(c, i, j))
433
- ).then((j) => j.filter((l) => {
434
- if (l.status === "fulfilled")
435
- return l.value, !0;
436
- b.warn(l.reason.toString());
437
- }).map((l) => l.value));
438
- if (d.length === 0)
439
- throw new Error(`获取${c} ${i}的cdn地址失败`);
440
- const y = {
441
- urls: d,
442
- key: c
443
- };
444
- return a.setCdnCache(c, i, y.urls), y;
445
- }
446
- })
447
- ).then((c) => (o && a.save(), {
448
- urls: c,
449
- noVersionPackages: n
450
- }));
574
+ var q = /* @__PURE__ */ ((s) => (s.PRE = "pre", s.POST = "post", s))(q || {});
575
+ function je(s) {
576
+ let e = "";
577
+ const t = {};
578
+ return s.forEach((n) => {
579
+ if (!n)
580
+ return;
581
+ const { urls: c, key: d } = n;
582
+ t[d] = c;
583
+ const i = c[0];
584
+ e += `<script src="${i}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${d}"><\/script>
585
+ `;
586
+ }), e = `<script>
587
+ function errorCDN(e) {
588
+ const packNameUrl = JSON.parse('${JSON.stringify(t)}');
589
+ const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
590
+ const key = e.getAttribute("data-key");
591
+ const curPackNameUrl = packNameUrl[key]
592
+ if(nextCur>=curPackNameUrl.length){return;}
593
+ // 新的cdn链接
594
+ const url = curPackNameUrl[nextCur]
595
+ // 克隆原标签
596
+ const tagName = e.tagName
597
+ const cdnDOM = document.createElement(tagName);
598
+ cdnDOM.setAttribute(tagName === 'SCRIPT' ?'src' : 'href', url);
599
+ Object.keys(e.dataset).forEach(_key => {
600
+ cdnDOM.setAttribute('data-'+_key, e.dataset[_key]);
601
+ })
602
+ cdnDOM.setAttribute("data-cur", nextCur.toString());
603
+ cdnDOM.setAttribute("onerror", "errorCDN(this)");
604
+ document.head.appendChild(cdnDOM);
605
+ e.remove();
606
+ }
607
+ <\/script>`.replace(/^\s*\/\/.*?$/gm, "") + e, e;
451
608
  }
452
- function Pt(r) {
453
- const { customScript: t = {}, defaultCdns: e = ["jsdelivr", "unpkg"] } = r;
454
- let s;
609
+ function De(s) {
610
+ const { customScript: e = {}, defaultCdns: t = ["jsdelivr", "unpkg"] } = s;
611
+ let r;
455
612
  return {
456
613
  name: H,
457
- enforce: "pre",
614
+ enforce: q.PRE,
458
615
  apply: "build",
459
616
  config(n) {
460
- s = n;
617
+ r = n;
461
618
  },
462
619
  async transformIndexHtml(n) {
463
- var a, c;
464
- if (!e || e.length === 0)
620
+ var i, o;
621
+ if (!t || t.length === 0)
465
622
  throw new Error("defaultCdns不能为空");
466
- const o = A.resolve(process.cwd(), "package.json");
623
+ let c = new ke();
624
+ const d = M.resolve(process.cwd(), "package.json");
467
625
  try {
468
- const i = E.readFileSync(o, "utf-8"), f = JSON.parse(i), d = (c = (a = s.build) == null ? void 0 : a.rollupOptions) == null ? void 0 : c.external;
469
- if (!d)
626
+ const u = P.readFileSync(d, "utf-8"), p = JSON.parse(u), h = (o = (i = r.build) == null ? void 0 : i.rollupOptions) == null ? void 0 : o.external;
627
+ if (!h)
470
628
  return n;
471
- let y = [];
472
- if (typeof d == "string")
473
- y = [d];
474
- else if (Array.isArray(d))
475
- y = d.filter((w) => typeof w == "string");
476
- else if (typeof d == "object")
629
+ let w = [];
630
+ if (typeof h == "string")
631
+ w = [h];
632
+ else if (Array.isArray(h))
633
+ w = h.filter((v) => typeof v == "string");
634
+ else if (typeof h == "object")
477
635
  return n;
478
- const j = {};
479
- let l = "";
480
- const { urls: S, noVersionPackages: F } = await R({
481
- external: y,
482
- packageData: f,
483
- customScript: t,
484
- defaultCdns: e
636
+ const {
637
+ urls: m,
638
+ noVersionPackages: a,
639
+ errorList: l
640
+ } = await R({
641
+ external: w,
642
+ packageData: p,
643
+ customScript: e,
644
+ defaultCdns: t
485
645
  });
486
- if (F.length > 0) {
487
- const w = { dependencies: {} };
488
- await Promise.allSettled(
489
- S.map(async (h) => {
490
- if (!h)
491
- return;
492
- const { key: C, urls: v } = h, k = t[C] || v[0];
493
- if (!k)
494
- return;
495
- const x = await lt(k);
496
- pt(w.dependencies, x.dependencies);
497
- })
498
- ).then((h) => {
499
- h.forEach((C) => {
500
- C.status === "rejected" && b.warn(C.reason.toString());
501
- });
646
+ if (c.addMessageList("warn", l), a.length > 0) {
647
+ const { urlPackageJsonRes: v, errorList: G } = await ye({
648
+ packageVersionInfo: m
502
649
  });
503
- const { urls: L, noVersionPackages: p } = await R({
504
- external: F,
505
- packageData: w,
506
- customScript: t,
507
- defaultCdns: e
650
+ c.addMessageList("warn", G);
651
+ const {
652
+ urls: z,
653
+ noVersionPackages: U,
654
+ errorList: B
655
+ } = await R({
656
+ external: a,
657
+ packageData: v,
658
+ customScript: e,
659
+ defaultCdns: t
508
660
  });
509
- if (L.map((h) => {
510
- var k;
511
- if (!h)
661
+ if (c.addMessageList("warn", B), z.map((x) => {
662
+ var E;
663
+ if (!x)
512
664
  return;
513
- const { urls: C, key: v } = h;
514
- (k = S.find((x) => (x == null ? void 0 : x.key) === v)) == null || k.urls.push(...C);
515
- }), p.length > 0)
516
- throw console.error(`找不到${p.join(",")}的版本`), new Error(`找不到${p.join(",")}的版本`);
517
- }
518
- return b.consoleAll(), S.forEach((w) => {
519
- if (!w)
520
- return;
521
- const { urls: L, key: p } = w;
522
- if (t[p])
523
- l += t[p];
524
- else {
525
- j[p] = L;
526
- const h = L[0];
527
- l += `<script src="${h}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${p}"><\/script>
528
- `;
529
- }
530
- }), l = `<script>
531
- function errorCDN(e) {
532
- const packNameUrl = JSON.parse('${JSON.stringify(j)}');
533
- const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
534
-
535
- const key = e.getAttribute("data-key");
536
- const curPackNameUrl = packNameUrl[key]
537
- if(nextCur>=curPackNameUrl.length){return;}
538
- // 新的cdn链接
539
- const url = curPackNameUrl[nextCur]
540
- // 克隆原标签
541
- const tagName = e.tagName
542
- const cdnDOM = document.createElement(tagName);
543
- cdnDOM.setAttribute(tagName === 'SCRIPT' ?'src' : 'href', url);
544
- Object.keys(e.dataset).forEach(_key => {
545
- cdnDOM.setAttribute('data-'+_key, e.dataset[_key]);
546
- })
547
- cdnDOM.setAttribute("data-cur", nextCur.toString());
548
- cdnDOM.setAttribute("onerror", "errorCDN(this)");
549
- document.head.appendChild(cdnDOM);
550
- e.remove();
665
+ const { urls: K, key: W } = x;
666
+ (E = m.find((D) => (D == null ? void 0 : D.key) === W)) == null || E.urls.push(...K);
667
+ }), U.length > 0)
668
+ throw console.error(`找不到${U.join(",")}的版本`), new Error(`找不到${U.join(",")}的版本`);
551
669
  }
552
- <\/script>` + l, n = n.replace("</head>", `${l}</head>`), n;
553
- } catch (i) {
554
- b.consoleAll(), console.error("vite-add-cdn-script error:", i.message), process.exit(1);
670
+ c.consoleAll();
671
+ const $ = je(m);
672
+ return n = n.replace("</head>", `${$}</head>`), n;
673
+ } catch (u) {
674
+ c.consoleAll(), console.error("vite-add-cdn-script error:", u.message), process.exit(1);
555
675
  }
556
676
  }
557
677
  };
558
678
  }
559
679
  export {
560
- Pt as default,
561
- H as libName
680
+ De as default
562
681
  };
@@ -1,24 +1,25 @@
1
- (function(o,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("node:path"),require("node:fs"),require("node-fetch"),require("semver")):typeof define=="function"&&define.amd?define(["exports","node:path","node:fs","node-fetch","semver"],l):(o=typeof globalThis<"u"?globalThis:o||self,l(o.index={},o.path,o.fs,o.fetch,o.semver))})(this,function(o,l,h,O,R){"use strict";var pt=Object.defineProperty;var wt=(o,l,h)=>l in o?pt(o,l,{enumerable:!0,configurable:!0,writable:!0,value:h}):o[l]=h;var C=(o,l,h)=>(wt(o,typeof l!="symbol"?l+"":l,h),h);class G{constructor(){C(this,"cdnCache",{});C(this,"cdnCachePath","");this.cdnCachePath=l.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const t=await h.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(t)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={},await h.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(t,e){var n;return(n=this.cdnCache[t])==null?void 0:n[e]}setCdnCache(t,e,n){this.cdnCache[t]?this.cdnCache[t][e]=n:this.cdnCache[t]={[e]:n}}async save(){await h.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}}let b;const B=async()=>(b||(b=new G,await b.init()),b);class f extends Error{constructor(t){super(t),this.name="NetworkError"}}class P extends f{constructor({packageName:t,version:e,cdn:n}){super(`${n} ${t}@${e} 网络请求失败`),this.name="PackageNetworkError"}}class $ extends Error{constructor({packageName:t,version:e,cdn:n}){super(`${n}上没有${t}@${e}的版本`),this.name="NoVersionError"}}class N extends Error{constructor({packageName:t,version:e,cdn:n}){super(`在 ${n} 中找不到 ${t}@${e} 文件,请检查包名或版本号`),this.name="GetFileListError"}}class z{constructor(t){C(this,"_max");C(this,"_count");C(this,"_taskQueue");this._max=t||5,this._count=0,this._taskQueue=[]}call(t,...e){return new Promise((n,s)=>{const c=this._createTask(t,e,n,s);this._count>=this._max?this._taskQueue.push(c):c()})}_createTask(t,e,n,s){return()=>{t(...e).then(n).catch(s).finally(()=>{this._count--,this._taskQueue.length&&this._taskQueue.shift()()}),this._count++}}}const A=new z(5),V=async r=>{try{const t=await O(r,{method:"HEAD",redirect:"manual"});return t.status>=300&&t.status<400?await V(t.headers.get("location")||""):r}catch(t){throw Promise.reject(new f(t.message))}},K={get:async r=>{try{const t=await O(r);if(t.ok){const e=t.headers.get("content-type"),n=await t.text();return e&&e.includes("application/json")?JSON.parse(n):n}else throw new f(`请求失败,状态码:${t.status}`)}catch(t){throw new f(t.message)}}},y={get:A.call.bind(A,K.get)},W={getFileList:async(r,t)=>{try{const e=await y.get(`https://api.bootcdn.cn/libraries/${r}`);if(e.length===0)throw new $({packageName:r,version:t,cdn:"bootcdn"});const n=e[0],c=n.assets.reverse().find(i=>{if(R.satisfies(i.version,t))return!0});if(!c)throw new $({packageName:r,version:t,cdn:"bootcdn"});return{fileList:c.files.map(i=>({name:"/"+i})),recommendFileName:n.filename,version:c.version}}catch(e){throw e instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):e}},getUrl:(r,t,e)=>`https://cdn.bootcdn.net/ajax/libs/${r}/${t}${e}`};async function J(r,t,e=!1){try{if(!e&&t.match(/^\D/)){const s=await Y(r,t);for(let c of s)if(R.satisfies(c,t))return J(r,c,!0);throw new $({packageName:r,version:t,cdn:"cdnjs"})}const n=await y.get(`https://api.cdnjs.com/libraries/${r}/${t}`);if(n.error)throw new $({packageName:r,version:t,cdn:"cdnjs"});return{fileList:n.rawFiles.map(s=>({name:"/"+s})),version:t}}catch(n){throw n instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):n}}const X=(r,t,e)=>`https://cdnjs.cloudflare.com/ajax/libs/${r}/${t}${e}`,Y=async(r,t)=>{try{return(await y.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions}catch(e){throw e instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):e}},Z={getFileList:J,getUrl:X},M=(r,t="")=>r.reduce((e,n)=>(n.type==="file"?e.push({name:`${t}/${n.name}`}):n.files&&e.push(...M(n.files,`${t}/${n.name}`)),e),[]);async function I(r,t,e=!1){try{if(!e&&t.match(/^\D/)){const s=await et(r,t);if(typeof s=="string")return I(r,s,!0);throw new $({packageName:r,version:t,cdn:"jsdelivr"})}const n=await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${t}`);if(n.status)throw new $({packageName:r,version:t,cdn:"jsdelivr"});return{fileList:M(n.files),version:t}}catch(n){throw n instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):n}}const tt=(r,t,e)=>`https://cdn.jsdelivr.net/npm/${r}@${t}${e}`,et=async(r,t)=>{try{return(await y.get(`https://data.jsdelivr.com/v1/packages/npm/${r}/resolved?specifier=${t}`)).version}catch(e){throw e instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):e}},rt={getFileList:I,getUrl:tt},T=r=>r.reduce((t,e)=>(e.type==="file"?t.push({name:e.path}):e.files&&t.push(...T(e.files)),t),[]);async function nt(r,t){var e;try{const s=(e=(await V(`https://unpkg.com/${r}@${t}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)")))==null?void 0:e[0];if(s){const c=await y.get(`https://unpkg.com/${r}@${s}/?meta`);return{fileList:T(c.files||[]),version:s}}else throw new $({packageName:r,version:t,cdn:"unpkg"})}catch(n){throw n instanceof f?new P({packageName:r,version:t,cdn:"unpkg"}):n}}function st(r,t,e){return`https://unpkg.com/${r}@${t}${e}`}const it={getFileList:nt,getUrl:st},ct=async r=>{try{const t=/^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(t.test(r)){const e=r.replace(t,(n,s)=>`${s}package.json`);return await y.get(e)}else throw new Error(`${r} 不是正确的url`)}catch(t){throw t}},ot=(r,t)=>{var e,n;return((e=r.dependencies)==null?void 0:e[t])||((n=r.devDependencies)==null?void 0:n[t])},at=async(r,t,e)=>{if(!t.match(/\d+(.\d+)?(.\d+)?/))throw new Error(`${r} version ${t} is not valid`);const s=await q[e].getFileList(r,t),c=lt(s,r);if(!c)throw new N({packageName:r,version:t,cdn:e});return q[e].getUrl(r,s.version,c)},lt=({fileList:r},t)=>{var c,u;let e=[`umd/${t}.production.min.js`,/umd\/.+?\.production\.min\.js$/,/dist\/.+?\.production\.min\.js$/,/dist\/.+?\.umd\.min\.js$/,`dist/${t}.prod.min.js`,/dist\/.+?\.global.prod.min.js/,`dist/${t}.min.js`,/.+?\.global.prod.min.js/,/.+?.global.prod.js/,/lib\/.+?\.min\.js$/,/dist\/.+?\.min\.js$/,/index\.min\.js$/,/index\.js$/,/\.min\.js$/,/\.js$/];const n=["runtime","compiler",".esm",".cjs","development"].filter(i=>!t.includes(i));let s="";for(let i of e)if(i instanceof RegExp?s=((c=r.find(a=>i.test(a.name)&&!n.some(g=>a.name.includes(g))))==null?void 0:c.name)||"":s=((u=r.find(a=>a.name.includes(i)&&!n.some(g=>a.name.includes(g))))==null?void 0:u.name)||"",s)break;return s},q={jsdelivr:rt,bootcdn:W,cdnjs:Z,unpkg:it};function ut(r,t){const e=r.replace(/^\D/,"").split("."),n=t.replace(/^\D/,"").split("."),s=Math.max(e.length,n.length);for(;e.length<s;)e.push("0");for(;n.length<s;)n.push("0");for(let c=0;c<s;c++){const u=parseInt(e[c],10),i=parseInt(n[c],10);if(u>i)return 1;if(u<i)return-1}return 0}function dt(r,t){for(let e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]?ut(r[e],t[e])===-1&&(r[e]=t[e]):r[e]=t[e]);return r}class ht{constructor(){C(this,"logList",[])}log(t){this.logList.push({type:"log",message:t})}warn(t){this.logList.push({type:"warn",message:t})}error(t){this.logList.push({type:"error",message:t})}info(t){this.logList.push({type:"info",message:t})}consoleAll(){this.logList.forEach(t=>{console[t.type](`${_} ${t.message}`)})}clear(){this.logList=[]}}const _="vite-add-cdn-script",v=new ht;async function Q({external:r,packageData:t,customScript:e,defaultCdns:n}){let s=[],c=!1;const u=await B();return await Promise.all(r.map(async i=>{const a=ot(t,i);if(e[i])return{urls:[],key:i};if(!a)return s.push(i),{urls:[],key:i};const g=u.getCdnCache(i,a);if(g)return{urls:g,key:i};{c=!0,console.log(`从网络获取${i}${a}的cdn地址`);const p=await Promise.allSettled(n.map(async x=>await at(i,a,x))).then(x=>x.filter(d=>{if(d.status==="fulfilled")return d.value,!0;v.warn(d.reason.toString())}).map(d=>d.value));if(p.length===0)throw new Error(`获取${i} ${a}的cdn地址失败`);const k={urls:p,key:i};return u.setCdnCache(i,a,k.urls),k}})).then(i=>(c&&u.save(),{urls:i,noVersionPackages:s}))}function ft(r){const{customScript:t={},defaultCdns:e=["jsdelivr","unpkg"]}=r;let n;return{name:_,enforce:"pre",apply:"build",config(s){n=s},async transformIndexHtml(s){var u,i;if(!e||e.length===0)throw new Error("defaultCdns不能为空");const c=l.resolve(process.cwd(),"package.json");try{const a=h.readFileSync(c,"utf-8"),g=JSON.parse(a),p=(i=(u=n.build)==null?void 0:u.rollupOptions)==null?void 0:i.external;if(!p)return s;let k=[];if(typeof p=="string")k=[p];else if(Array.isArray(p))k=p.filter(j=>typeof j=="string");else if(typeof p=="object")return s;const x={};let d="";const{urls:F,noVersionPackages:H}=await Q({external:k,packageData:g,customScript:t,defaultCdns:e});if(H.length>0){const j={dependencies:{}};await Promise.allSettled(F.map(async w=>{if(!w)return;const{key:L,urls:D}=w,U=t[L]||D[0];if(!U)return;const E=await ct(U);dt(j.dependencies,E.dependencies)})).then(w=>{w.forEach(L=>{L.status==="rejected"&&v.warn(L.reason.toString())})});const{urls:S,noVersionPackages:m}=await Q({external:H,packageData:j,customScript:t,defaultCdns:e});if(S.map(w=>{var U;if(!w)return;const{urls:L,key:D}=w;(U=F.find(E=>(E==null?void 0:E.key)===D))==null||U.urls.push(...L)}),m.length>0)throw console.error(`找不到${m.join(",")}的版本`),new Error(`找不到${m.join(",")}的版本`)}return v.consoleAll(),F.forEach(j=>{if(!j)return;const{urls:S,key:m}=j;if(t[m])d+=t[m];else{x[m]=S;const w=S[0];d+=`<script src="${w}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${m}"><\/script>
2
- `}}),d=`<script>
3
- function errorCDN(e) {
4
- const packNameUrl = JSON.parse('${JSON.stringify(x)}');
5
- const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
6
-
7
- const key = e.getAttribute("data-key");
8
- const curPackNameUrl = packNameUrl[key]
9
- if(nextCur>=curPackNameUrl.length){return;}
10
- // 新的cdn链接
11
- const url = curPackNameUrl[nextCur]
12
- // 克隆原标签
13
- const tagName = e.tagName
14
- const cdnDOM = document.createElement(tagName);
15
- cdnDOM.setAttribute(tagName === 'SCRIPT' ?'src' : 'href', url);
16
- Object.keys(e.dataset).forEach(_key => {
17
- cdnDOM.setAttribute('data-'+_key, e.dataset[_key]);
18
- })
19
- cdnDOM.setAttribute("data-cur", nextCur.toString());
20
- cdnDOM.setAttribute("onerror", "errorCDN(this)");
21
- document.head.appendChild(cdnDOM);
22
- e.remove();
23
- }
24
- <\/script>`+d,s=s.replace("</head>",`${d}</head>`),s}catch(a){v.consoleAll(),console.error("vite-add-cdn-script error:",a.message),process.exit(1)}}}}o.default=ft,o.libName=_,Object.defineProperties(o,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
1
+ (function(h,f){typeof exports=="object"&&typeof module<"u"?module.exports=f(require("node:path"),require("node:fs"),require("node-fetch"),require("semver")):typeof define=="function"&&define.amd?define(["node:path","node:fs","node-fetch","semver"],f):(h=typeof globalThis<"u"?globalThis:h||self,h.index=f(h.path,h.fs,h.fetch,h.semver))})(this,function(h,f,y,F){"use strict";var ye=Object.defineProperty;var ke=(h,f,y)=>f in h?ye(h,f,{enumerable:!0,configurable:!0,writable:!0,value:y}):h[f]=y;var g=(h,f,y)=>(ke(h,typeof f!="symbol"?f+"":f,y),y);var v=(s=>(s.noFound="noFound",s.NetworkError="networkError",s))(v||{});class G{constructor(){g(this,"cdnCache",{packageDependencies:{},cdnsUrl:{}});g(this,"cdnCachePath","");this.cdnCachePath=h.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const e=await f.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(e)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={packageDependencies:{},cdnsUrl:{}},await f.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(e,t){var n;return(n=this.cdnCache.cdnsUrl[e])==null?void 0:n[t]}setCdnCache(e,t,n){this.cdnCache.cdnsUrl[e]?this.cdnCache.cdnsUrl[e][t]=n:this.cdnCache.cdnsUrl[e]={[t]:n}}async save(){await f.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}getPackageDependencies(e,t){var n;return(n=this.cdnCache.packageDependencies[e])==null?void 0:n[t]}setPackageDependencies(e,t,n){this.cdnCache.packageDependencies[e]?this.cdnCache.packageDependencies[e][t]=n:this.cdnCache.packageDependencies[e]={[t]:n}}}let U;const S=async()=>(U||(U=new G,await U.init()),U);class w extends Error{constructor(e){super(e),this.name="NetworkError"}}class k extends w{constructor({packageName:t,version:n,cdn:r}){super(`${r} ${t}@${n} 网络请求失败`);g(this,"cdn");g(this,"packageName");g(this,"version");this.name="PackageNetworkError",this.cdn=r,this.packageName=t,this.version=n}getErrorInfo(){return{cdn:this.cdn,packageName:this.packageName,version:this.version}}}class j extends Error{constructor({packageName:t,version:n,cdn:r}){super(`${r}上没有${t}@${n}的版本`);g(this,"cdn");g(this,"packageName");g(this,"version");this.name="NoVersionError",this.cdn=r,this.packageName=t,this.version=n}getErrorInfo(){return{cdn:this.cdn,packageName:this.packageName,version:this.version}}}class z extends Error{constructor({packageName:e,version:t,cdn:n}){super(`在 ${n} 中找不到 ${e}@${t} 文件,请检查包名或版本号`),this.name="GetFileListError"}}class B{constructor(e){g(this,"_max");g(this,"_count");g(this,"_taskQueue");this._max=e||5,this._count=0,this._taskQueue=[]}call(e,...t){return new Promise((n,r)=>{const c=this._createTask(e,t,n,r);this._count>=this._max?this._taskQueue.push(c):c()})}_createTask(e,t,n,r){return()=>{e(...t).then(n).catch(r).finally(()=>{this._count--,this._taskQueue.length&&this._taskQueue.shift()()}),this._count++}}}const b=new B(5),_=async s=>{try{const e=await y(s,{method:"HEAD",redirect:"manual"});return e.status>=300&&e.status<400?await _(e.headers.get("location")||""):s}catch(e){throw new w(e.message)}},K={get:async s=>{try{const e=await y(s);if(e.ok){const t=e.headers.get("content-type"),n=await e.text();return t&&t.includes("application/json")?JSON.parse(n):n}else throw new w(`请求失败,状态码:${e.status}`)}catch(e){throw new w(e.message)}}},L={get:b.call.bind(b,K.get)},W={getFileList:async(s,e)=>{try{const t=await L.get(`https://api.bootcdn.cn/libraries/${s}`);if(t.length===0)throw new j({packageName:s,version:e,cdn:"bootcdn"});const n=t[0],c=n.assets.reverse().find(i=>{if(F.satisfies(i.version,e))return!0});if(!c)throw new j({packageName:s,version:e,cdn:"bootcdn"});return{fileList:c.files.map(i=>({name:"/"+i})),recommendFileName:n.filename,version:c.version}}catch(t){throw t instanceof w?new k({packageName:s,version:e,cdn:"bootcdn"}):t}},getUrl:(s,e,t)=>`https://cdn.bootcdn.net/ajax/libs/${s}/${e}${t}`};async function R(s,e,t=!1){try{if(!t&&e.match(/^\D/)){const r=await Y(s,e);for(let c of r)if(F.satisfies(c,e))return R(s,c,!0);throw new j({packageName:s,version:e,cdn:"cdnjs"})}const n=await L.get(`https://api.cdnjs.com/libraries/${s}/${e}`);if(n.error)throw new j({packageName:s,version:e,cdn:"cdnjs"});return{fileList:n.rawFiles.map(r=>({name:"/"+r})),version:e}}catch(n){throw n instanceof w?new k({packageName:s,version:e,cdn:"cdnjs"}):n}}const X=(s,e,t)=>`https://cdnjs.cloudflare.com/ajax/libs/${s}/${e}${t}`,Y=async(s,e)=>{try{return(await L.get(`https://api.cdnjs.com/libraries/${s}?fields=versions`)).versions}catch(t){throw t instanceof w?new k({packageName:s,version:e,cdn:"cdnjs"}):t}},Z={getFileList:R,getUrl:X},M=(s,e="")=>s.reduce((t,n)=>(n.type==="file"?t.push({name:`${e}/${n.name}`}):n.files&&t.push(...M(n.files,`${e}/${n.name}`)),t),[]);async function O(s,e,t=!1){try{if(!t&&e.match(/^\D/)){const r=await te(s,e);if(typeof r=="string")return O(s,r,!0);throw new j({packageName:s,version:e,cdn:"jsdelivr"})}const n=await L.get(`https://data.jsdelivr.com/v1/packages/npm/${s}@${e}`);if(n.status)throw new j({packageName:s,version:e,cdn:"jsdelivr"});return{fileList:M(n.files),version:e}}catch(n){throw n instanceof w?new k({packageName:s,version:e,cdn:"jsdelivr"}):n}}const ee=(s,e,t)=>`https://cdn.jsdelivr.net/npm/${s}@${e}${t}`,te=async(s,e)=>{try{return(await L.get(`https://data.jsdelivr.com/v1/packages/npm/${s}/resolved?specifier=${e}`)).version}catch(t){throw t instanceof w?new k({packageName:s,version:e,cdn:"jsdelivr"}):t}},se={getFileList:O,getUrl:ee},V=s=>s.reduce((e,t)=>(t.type==="file"?e.push({name:t.path}):t.files&&e.push(...V(t.files)),e),[]);async function ne(s,e){var t;try{const r=(t=(await _(`https://unpkg.com/${s}@${e}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)")))==null?void 0:t[0];if(r){const c=await L.get(`https://unpkg.com/${s}@${r}/?meta`);return{fileList:V(c.files||[]),version:r}}else throw new j({packageName:s,version:e,cdn:"unpkg"})}catch(n){throw n instanceof w?new k({packageName:s,version:e,cdn:"unpkg"}):n}}function re(s,e,t){return`https://unpkg.com/${s}@${e}${t}`}const ce={getFileList:ne,getUrl:re},oe=async s=>{try{const e=/^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(e.test(s)){const t=s.replace(e,(n,r)=>`${r}package.json`);return await L.get(t)}else throw new Error(`${s} 不是正确的url`)}catch(e){throw e}},ie=(s,e)=>{var t,n;return((t=s.dependencies)==null?void 0:t[e])||((n=s.devDependencies)==null?void 0:n[e])},A=async(s,e,t)=>{if(!e.match(/\d+(.\d+)?(.\d+)?/))throw new Error(`${s} version ${e} is not valid`);const r=await J[t].getFileList(s,e),c=ae(r,s);if(!c)throw new z({packageName:s,version:e,cdn:t});return J[t].getUrl(s,r.version,c)},ae=({fileList:s},e)=>{var c,d;let t=[`umd/${e}.production.min.js`,/umd\/.+?\.production\.min\.js$/,/dist\/.+?\.production\.min\.js$/,/dist\/.+?\.umd\.min\.js$/,`dist/${e}.prod.min.js`,/dist\/.+?\.global.prod.min.js/,`dist/${e}.min.js`,/.+?\.global.prod.min.js/,/.+?.global.prod.js/,/lib\/.+?\.min\.js$/,/dist\/.+?\.min\.js$/,/index\.min\.js$/,/index\.js$/,/\.min\.js$/,/\.js$/];const n=["runtime","compiler",".esm",".cjs","development"].filter(i=>!e.includes(i));let r="";for(let i of t)if(i instanceof RegExp?r=((c=s.find(o=>i.test(o.name)&&!n.some(u=>o.name.includes(u))))==null?void 0:c.name)||"":r=((d=s.find(o=>o.name.includes(i)&&!n.some(u=>o.name.includes(u))))==null?void 0:d.name)||"",r)break;return r},J={jsdelivr:se,bootcdn:W,cdnjs:Z,unpkg:ce};function le(s,e){const t=s.replace(/^\D/,"").split("."),n=e.replace(/^\D/,"").split("."),r=Math.max(t.length,n.length);for(;t.length<r;)t.push("0");for(;n.length<r;)n.push("0");for(let c=0;c<r;c++){const d=parseInt(t[c],10),i=parseInt(n[c],10);if(d>i)return 1;if(d<i)return-1}return 0}function I(s,e){for(let t in e)Object.prototype.hasOwnProperty.call(e,t)&&(s[t]?le(s[t],e[t])===-1&&(s[t]=e[t]):s[t]=e[t]);return s}async function N({external:s,packageData:e,customScript:t,defaultCdns:n}){let r=[],c=!1,d=[];const i=await S();return await Promise.all(s.map(async o=>{const u=ie(e,o);if(t[o])return{urls:[t[o]],key:o};if(!u)return r.push(o),{urls:[],key:o};const $=i.getCdnCache(o,u);if($){const p=new Set(n),m=new Map,C=$.filter((a,l)=>{if(p.has(a.cdnName)&&a.success)return p.delete(a.cdnName),!0;!a.success&&a.error===v.noFound?p.delete(a.cdnName):m.set(a.cdnName,l)}).map(a=>a.url);if(p.size>0){const a=await Promise.allSettled([...p].map(async l=>({cdnName:l,success:!0,url:await A(o,u,l)}))).then(l=>l.filter(P=>{if(P.status==="fulfilled")return C.push(P.value.url),!0;d.push(P.reason)}));a.length>0&&(a.forEach(l=>{const P=m.get(l.value.cdnName);P!==void 0?$[P]=l.value:$.push(l.value)}),i.setCdnCache(o,u,$),c=!0)}return{urls:C,version:u,key:o}}else{c=!0,console.log(`从网络获取${o}${u}的cdn地址`);const p=await Promise.allSettled(n.map(async a=>({cdnName:a,success:!0,url:await A(o,u,a)}))).then(a=>a.map(l=>{if(l.status==="fulfilled")return l.value;if(d.push(l.reason),l.reason instanceof k||l.reason instanceof j)return{cdnName:l.reason.cdn,success:!1,error:l.reason instanceof k?v.NetworkError:v.noFound}}).filter(l=>!!l)),m=p.filter(a=>a.success).map(a=>a.url);if(m.length===0)throw new Error(`
2
+ ${d.map(a=>a.message).join(`
3
+ `)}获取${o} ${u}的cdn地址失败`);const C={urls:m,version:u,key:o};return i.setCdnCache(o,u,p),C}})).then(o=>(c&&i.save(),{urls:o,noVersionPackages:r,errorList:d}))}const de=async({packageVersionInfo:s})=>{const e={dependencies:{}};let t=!1;const n=await S(),r=[];return await Promise.allSettled(s.map(async c=>{if(!c)return;const{urls:d}=c,i=d[0];if(!i)return;const o=c.version||i,u=n.getPackageDependencies(c.key,o);if(u)return I(e.dependencies,u.dependencies);const $=await oe(i);n.setPackageDependencies(c.key,o,{dependencies:$.dependencies}),t=!0,I(e.dependencies,$.dependencies)})).then(c=>(t&&n.save(),c.forEach(d=>{d.status==="rejected"&&r.push(d.reason)}),{urlPackageJsonRes:e,errorList:r}))},q="vite-add-cdn-script";class ue{constructor(){g(this,"logList",[])}log(e){this.logList.push({type:"log",message:e})}warn(e){this.logList.push({type:"warn",message:e})}error(e){this.logList.push({type:"error",message:e})}info(e){this.logList.push({type:"info",message:e})}consoleAll(){console.log(""),this.logList.forEach(e=>{console[e.type](`${q} ${e.message}`)})}addMessageList(e,t){t.forEach(n=>{this.logList.push({type:e,message:n.toString()})})}clear(){this.logList=[]}}var T=(s=>(s.PRE="pre",s.POST="post",s))(T||{});function he(s){let e="";const t={};return s.forEach(r=>{if(!r)return;const{urls:c,key:d}=r;t[d]=c;const i=c[0];e+=`<script src="${i}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${d}"><\/script>
4
+ `}),e=`<script>
5
+ function errorCDN(e) {
6
+ const packNameUrl = JSON.parse('${JSON.stringify(t)}');
7
+ const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
8
+ const key = e.getAttribute("data-key");
9
+ const curPackNameUrl = packNameUrl[key]
10
+ if(nextCur>=curPackNameUrl.length){return;}
11
+ // 新的cdn链接
12
+ const url = curPackNameUrl[nextCur]
13
+ // 克隆原标签
14
+ const tagName = e.tagName
15
+ const cdnDOM = document.createElement(tagName);
16
+ cdnDOM.setAttribute(tagName === 'SCRIPT' ?'src' : 'href', url);
17
+ Object.keys(e.dataset).forEach(_key => {
18
+ cdnDOM.setAttribute('data-'+_key, e.dataset[_key]);
19
+ })
20
+ cdnDOM.setAttribute("data-cur", nextCur.toString());
21
+ cdnDOM.setAttribute("onerror", "errorCDN(this)");
22
+ document.head.appendChild(cdnDOM);
23
+ e.remove();
24
+ }
25
+ <\/script>`.replace(/^\s*\/\/.*?$/gm,"")+e,e}function fe(s){const{customScript:e={},defaultCdns:t=["jsdelivr","unpkg"]}=s;let n;return{name:q,enforce:T.PRE,apply:"build",config(r){n=r},async transformIndexHtml(r){var i,o;if(!t||t.length===0)throw new Error("defaultCdns不能为空");let c=new ue;const d=h.resolve(process.cwd(),"package.json");try{const u=f.readFileSync(d,"utf-8"),$=JSON.parse(u),p=(o=(i=n.build)==null?void 0:i.rollupOptions)==null?void 0:o.external;if(!p)return r;let m=[];if(typeof p=="string")m=[p];else if(Array.isArray(p))m=p.filter(x=>typeof x=="string");else if(typeof p=="object")return r;const{urls:C,noVersionPackages:a,errorList:l}=await N({external:m,packageData:$,customScript:e,defaultCdns:t});if(c.addMessageList("warn",l),a.length>0){const{urlPackageJsonRes:x,errorList:pe}=await de({packageVersionInfo:C});c.addMessageList("warn",pe);const{urls:ge,noVersionPackages:D,errorList:we}=await N({external:a,packageData:x,customScript:e,defaultCdns:t});if(c.addMessageList("warn",we),ge.map(Q=>{var H;if(!Q)return;const{urls:$e,key:me}=Q;(H=C.find(E=>(E==null?void 0:E.key)===me))==null||H.urls.push(...$e)}),D.length>0)throw console.error(`找不到${D.join(",")}的版本`),new Error(`找不到${D.join(",")}的版本`)}c.consoleAll();const P=he(C);return r=r.replace("</head>",`${P}</head>`),r}catch(u){c.consoleAll(),console.error("vite-add-cdn-script error:",u.message),process.exit(1)}}}}return fe});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-add-cdn-script",
3
- "version": "0.0.11",
3
+ "version": "1.0.0",
4
4
  "keywords": [
5
5
  "vite",
6
6
  "cdn",