cdn-script-core 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # cdn-script-core
2
+
3
+ 获取 cdn 脚本,并生成 script 标签。
@@ -0,0 +1,169 @@
1
+ declare enum cdnTypes {
2
+ jsdelivr = "jsdelivr",
3
+ unpkg = "unpkg",
4
+ bootcdn = "bootcdn",
5
+ cdnjs = "cdnjs"
6
+ }
7
+
8
+ export declare class ConsoleManage {
9
+ private logList;
10
+ private prefixString;
11
+ constructor(prefixString?: string);
12
+ log(message: string): void;
13
+ warn(message: string): void;
14
+ error(message: string): void;
15
+ info(message: string): void;
16
+ consoleAll(): void;
17
+ addMessageList(addType: `${ConsoleType}`, messages: string[] | {
18
+ toString: () => string;
19
+ }[]): void;
20
+ clear(): void;
21
+ }
22
+
23
+ export declare enum ConsoleType {
24
+ log = "log",
25
+ warn = "warn",
26
+ error = "error",
27
+ info = "info"
28
+ }
29
+
30
+ export declare type ExternalOption = any;
31
+
32
+ /**
33
+ * 查找指定包的 CDN 链接,并返回 CDN 链接和版本不匹配的包的列表
34
+ * @param external 需要查找 CDN 链接的包列表
35
+ * @param packageData 包数据,包含依赖信息
36
+ * @example
37
+ * {
38
+ * "dependencies": {
39
+ * "react": "^17.0.2",
40
+ * "react-dom": "^17.0.2"
41
+ * },
42
+ * "devDependencies": {
43
+ * "vite": "^2.6.3"
44
+ * }
45
+ * }
46
+ * @param customScript 自定义脚本
47
+ * @param defaultCdns 默认的 CDN 列表
48
+ * @return 一个 Promise,当解析完成时,将返回一个对象。
49
+ */
50
+ export declare function findUrls({ external, packageData, customScript, defaultCdns, }: {
51
+ external: string[];
52
+ packageData: {
53
+ devDependencies?: Record<string, string>;
54
+ dependencies: Record<string, string>;
55
+ };
56
+ customScript: {
57
+ [key: string]: string;
58
+ };
59
+ defaultCdns: PropertyCdn[];
60
+ }): Promise<{
61
+ urls: {
62
+ urls: string[];
63
+ key: string;
64
+ version?: string;
65
+ }[];
66
+ noVersionPackages: string[];
67
+ errorList: Error[];
68
+ }>;
69
+
70
+ /**
71
+ * 生成加载外部脚本的 HTML 脚本标记字符串,并在加载失败时自动尝试下一个 URL
72
+ * @param urlListRes 包含 URL 和键值的对象数组
73
+ * @param packNameUrl 包含键和 URL 数组的对象
74
+ * @return <script> 标签和错误处理脚本组成字符串
75
+ */
76
+ export declare function generateScript(urlListRes: {
77
+ urls: string[];
78
+ key: string;
79
+ }[]): string;
80
+
81
+ declare function getExternalScript({ libName, customScript, external: inputExternal, defaultCdns, }: {
82
+ libName: string;
83
+ external: ExternalOption;
84
+ customScript: {
85
+ [key: string]: string;
86
+ };
87
+ defaultCdns: PropertyCdn[];
88
+ }): Promise<string>;
89
+ export default getExternalScript;
90
+
91
+ /**
92
+ * 文件获取失败错误
93
+ */
94
+ export declare class GetFileListError extends Error {
95
+ constructor({ packageName, version, cdn }: {
96
+ packageName: string;
97
+ version: string;
98
+ cdn: PropertyCdn;
99
+ });
100
+ }
101
+
102
+ /**
103
+ * 获取指定包的依赖包的package.json
104
+ * @param packageVersionInfo 包的版本信息
105
+ * @return 拼接后的package.json的dependencies字段和错误列表
106
+ */
107
+ export declare const getPackageDependencies: ({ packageVersionInfo, }: {
108
+ packageVersionInfo: {
109
+ key: string;
110
+ urls: string[];
111
+ version?: string;
112
+ }[];
113
+ }) => Promise<{
114
+ urlPackageJsonRes: {
115
+ dependencies: {
116
+ [key: string]: string;
117
+ };
118
+ };
119
+ errorList: Error[];
120
+ }>;
121
+
122
+ /**
123
+ * 网络请求失败
124
+ */
125
+ export declare class NetworkError extends Error {
126
+ constructor(message: string);
127
+ }
128
+
129
+ /**
130
+ * 找不到依赖包
131
+ */
132
+ export declare class NoVersionError extends Error {
133
+ cdn: PropertyCdn;
134
+ packageName: string;
135
+ version: string;
136
+ constructor({ packageName, version, cdn }: {
137
+ packageName: string;
138
+ version: string;
139
+ cdn: PropertyCdn;
140
+ });
141
+ getErrorInfo(): {
142
+ cdn: "jsdelivr" | "unpkg" | "bootcdn" | "cdnjs";
143
+ packageName: string;
144
+ version: string;
145
+ };
146
+ }
147
+
148
+ /**
149
+ * 依赖包网络请求失败
150
+ */
151
+ export declare class PackageNetworkError extends NetworkError {
152
+ cdn: PropertyCdn;
153
+ packageName: string;
154
+ version: string;
155
+ constructor({ packageName, version, cdn }: {
156
+ packageName: string;
157
+ version: string;
158
+ cdn: PropertyCdn;
159
+ });
160
+ getErrorInfo(): {
161
+ cdn: "jsdelivr" | "unpkg" | "bootcdn" | "cdnjs";
162
+ packageName: string;
163
+ version: string;
164
+ };
165
+ }
166
+
167
+ declare type PropertyCdn = `${cdnTypes}`;
168
+
169
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,691 @@
1
+ var z = Object.defineProperty;
2
+ var B = (s, e, t) => e in s ? z(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var h = (s, e, t) => (B(s, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import _ from "node-fetch";
5
+ import M from "semver";
6
+ import O from "node:path";
7
+ import P from "node:fs";
8
+ var T = /* @__PURE__ */ ((s) => (s.log = "log", s.warn = "warn", s.error = "error", s.info = "info", s))(T || {});
9
+ class K {
10
+ constructor(e) {
11
+ // 打印记录
12
+ h(this, "logList", []);
13
+ // 打印前缀
14
+ h(this, "prefixString", "cdn-script");
15
+ e && (this.prefixString = e);
16
+ }
17
+ // 打印方法
18
+ log(e) {
19
+ this.logList.push({
20
+ type: "log",
21
+ message: e
22
+ });
23
+ }
24
+ warn(e) {
25
+ this.logList.push({
26
+ type: "warn",
27
+ message: e
28
+ });
29
+ }
30
+ error(e) {
31
+ this.logList.push({
32
+ type: "error",
33
+ message: e
34
+ });
35
+ }
36
+ info(e) {
37
+ this.logList.push({
38
+ type: "info",
39
+ message: e
40
+ });
41
+ }
42
+ // 打印全部
43
+ consoleAll() {
44
+ console.log(""), this.logList.forEach((e) => {
45
+ console[e.type](`${this.prefixString} ${e.message}`);
46
+ });
47
+ }
48
+ addMessageList(e, t) {
49
+ t.forEach((r) => {
50
+ this.logList.push({
51
+ type: e,
52
+ message: r.toString()
53
+ });
54
+ });
55
+ }
56
+ // 清除打印记录
57
+ clear() {
58
+ this.logList = [];
59
+ }
60
+ }
61
+ class g extends Error {
62
+ constructor(e) {
63
+ super(e), this.name = "NetworkError";
64
+ }
65
+ }
66
+ class m extends g {
67
+ constructor({ packageName: t, version: r, cdn: n }) {
68
+ super(`${n} ${t}@${r} 网络请求失败`);
69
+ h(this, "cdn");
70
+ h(this, "packageName");
71
+ h(this, "version");
72
+ this.name = "PackageNetworkError", this.cdn = n, this.packageName = t, this.version = r;
73
+ }
74
+ getErrorInfo() {
75
+ return {
76
+ cdn: this.cdn,
77
+ packageName: this.packageName,
78
+ version: this.version
79
+ };
80
+ }
81
+ }
82
+ class $ extends Error {
83
+ constructor({ packageName: t, version: r, cdn: n }) {
84
+ super(`${n}上没有${t}@${r}的版本`);
85
+ h(this, "cdn");
86
+ h(this, "packageName");
87
+ h(this, "version");
88
+ this.name = "NoVersionError", this.cdn = n, this.packageName = t, this.version = r;
89
+ }
90
+ getErrorInfo() {
91
+ return {
92
+ cdn: this.cdn,
93
+ packageName: this.packageName,
94
+ version: this.version
95
+ };
96
+ }
97
+ }
98
+ class W extends Error {
99
+ constructor({ packageName: e, version: t, cdn: r }) {
100
+ super(`在 ${r} 中找不到 ${e}@${t} 文件,请检查包名或版本号`), this.name = "GetFileListError";
101
+ }
102
+ }
103
+ function X(s, e) {
104
+ const t = s.replace(/^\D/, "").split("."), r = e.replace(/^\D/, "").split("."), n = Math.max(t.length, r.length);
105
+ for (; t.length < n; )
106
+ t.push("0");
107
+ for (; r.length < n; )
108
+ r.push("0");
109
+ for (let c = 0; c < n; c++) {
110
+ const l = parseInt(t[c], 10), o = parseInt(r[c], 10);
111
+ if (l > o)
112
+ return 1;
113
+ if (l < o)
114
+ return -1;
115
+ }
116
+ return 0;
117
+ }
118
+ function b(s, e) {
119
+ for (let t in e)
120
+ Object.prototype.hasOwnProperty.call(e, t) && (s[t] ? X(s[t], e[t]) === -1 && (s[t] = e[t]) : s[t] = e[t]);
121
+ return s;
122
+ }
123
+ class Y {
124
+ constructor(e) {
125
+ h(this, "_max");
126
+ h(this, "_count");
127
+ h(this, "_taskQueue");
128
+ this._max = e || 5, this._count = 0, this._taskQueue = [];
129
+ }
130
+ /**
131
+ * 请求封装
132
+ * @param caller 请求函数
133
+ * @param args 请求参数
134
+ * @returns {Promise<any>} 返回一个promise
135
+ */
136
+ call(e, ...t) {
137
+ return new Promise((r, n) => {
138
+ const c = this._createTask(e, t, r, n);
139
+ this._count >= this._max ? this._taskQueue.push(c) : c();
140
+ });
141
+ }
142
+ /**
143
+ * 创建一个任务
144
+ * @param caller 实际执行的函数
145
+ * @param args 执行函数的参数
146
+ * @param resolve
147
+ * @param reject
148
+ * @returns {Function} 返回一个任务函数
149
+ * @private
150
+ */
151
+ _createTask(e, t, r, n) {
152
+ return () => {
153
+ e(...t).then(r).catch(n).finally(() => {
154
+ this._count--, this._taskQueue.length && this._taskQueue.shift()();
155
+ }), this._count++;
156
+ };
157
+ }
158
+ }
159
+ const S = new Y(5), R = async (s) => {
160
+ try {
161
+ const e = await _(s, { method: "HEAD", redirect: "manual" });
162
+ return e.status >= 300 && e.status < 400 ? await R(e.headers.get("location") || "") : s;
163
+ } catch (e) {
164
+ throw new g(e.message);
165
+ }
166
+ }, Z = {
167
+ //get请求封装
168
+ get: async (s) => {
169
+ try {
170
+ const e = await _(s);
171
+ if (e.ok) {
172
+ const t = e.headers.get("content-type"), r = await e.text();
173
+ return t && t.includes("application/json") ? JSON.parse(r) : r;
174
+ } else
175
+ throw new g(`请求失败,状态码:${e.status}`);
176
+ } catch (e) {
177
+ throw new g(e.message);
178
+ }
179
+ }
180
+ }, y = {
181
+ get: S.call.bind(S, Z.get)
182
+ }, ee = async (s, e) => {
183
+ try {
184
+ const t = await y.get(`https://api.bootcdn.cn/libraries/${s}`);
185
+ if (t.length === 0)
186
+ throw new $({
187
+ packageName: s,
188
+ version: e,
189
+ cdn: "bootcdn"
190
+ });
191
+ const r = t[0], c = r.assets.reverse().find((o) => {
192
+ if (M.satisfies(o.version, e))
193
+ return !0;
194
+ });
195
+ if (!c)
196
+ throw new $({
197
+ packageName: s,
198
+ version: e,
199
+ cdn: "bootcdn"
200
+ });
201
+ return { fileList: c.files.map((o) => ({
202
+ name: "/" + o
203
+ })), recommendFileName: r.filename, version: c.version };
204
+ } catch (t) {
205
+ throw t instanceof g ? new m({
206
+ packageName: s,
207
+ version: e,
208
+ cdn: "bootcdn"
209
+ }) : t;
210
+ }
211
+ }, te = (s, e, t) => `https://cdn.bootcdn.net/ajax/libs/${s}/${e}${t}`, se = {
212
+ getFileList: ee,
213
+ getUrl: te
214
+ };
215
+ async function V(s, e, t = !1) {
216
+ try {
217
+ if (!t && e.match(/^\D/)) {
218
+ const n = await ne(s, e);
219
+ for (let c of n)
220
+ if (M.satisfies(c, e))
221
+ return V(s, c, !0);
222
+ throw new $({
223
+ packageName: s,
224
+ version: e,
225
+ cdn: "cdnjs"
226
+ });
227
+ }
228
+ const r = await y.get(`https://api.cdnjs.com/libraries/${s}/${e}`);
229
+ if (r.error)
230
+ throw new $({
231
+ packageName: s,
232
+ version: e,
233
+ cdn: "cdnjs"
234
+ });
235
+ return {
236
+ fileList: r.rawFiles.map((n) => ({
237
+ name: "/" + n
238
+ })),
239
+ version: e
240
+ };
241
+ } catch (r) {
242
+ throw r instanceof g ? new m({
243
+ packageName: s,
244
+ version: e,
245
+ cdn: "cdnjs"
246
+ }) : r;
247
+ }
248
+ }
249
+ const re = (s, e, t) => `https://cdnjs.cloudflare.com/ajax/libs/${s}/${e}${t}`, ne = async (s, e) => {
250
+ try {
251
+ return (await y.get(`https://api.cdnjs.com/libraries/${s}?fields=versions`)).versions;
252
+ } catch (t) {
253
+ throw t instanceof g ? new m({
254
+ packageName: s,
255
+ version: e,
256
+ cdn: "cdnjs"
257
+ }) : t;
258
+ }
259
+ }, ce = {
260
+ getFileList: V,
261
+ getUrl: re
262
+ }, J = (s, e = "") => s.reduce((t, r) => (r.type === "file" ? t.push({ name: `${e}/${r.name}` }) : r.files && t.push(...J(r.files, `${e}/${r.name}`)), t), []);
263
+ async function A(s, e, t = !1) {
264
+ try {
265
+ if (!t && e.match(/^\D/)) {
266
+ const n = await ie(s, e);
267
+ if (typeof n == "string")
268
+ return A(s, n, !0);
269
+ throw new $({
270
+ packageName: s,
271
+ version: e,
272
+ cdn: "jsdelivr"
273
+ });
274
+ }
275
+ const r = await y.get(`https://data.jsdelivr.com/v1/packages/npm/${s}@${e}`);
276
+ if (r.status)
277
+ throw new $({
278
+ packageName: s,
279
+ version: e,
280
+ cdn: "jsdelivr"
281
+ });
282
+ return { fileList: J(r.files), version: e };
283
+ } catch (r) {
284
+ throw r instanceof g ? new m({
285
+ packageName: s,
286
+ version: e,
287
+ cdn: "jsdelivr"
288
+ }) : r;
289
+ }
290
+ }
291
+ const oe = (s, e, t) => `https://cdn.jsdelivr.net/npm/${s}@${e}${t}`, ie = async (s, e) => {
292
+ try {
293
+ return (await y.get(
294
+ `https://data.jsdelivr.com/v1/packages/npm/${s}/resolved?specifier=${e}`
295
+ )).version;
296
+ } catch (t) {
297
+ throw t instanceof g ? new m({
298
+ packageName: s,
299
+ version: e,
300
+ cdn: "jsdelivr"
301
+ }) : t;
302
+ }
303
+ }, ae = {
304
+ getFileList: A,
305
+ // 拼接url
306
+ getUrl: oe
307
+ }, I = (s) => s.reduce((e, t) => (t.type === "file" ? e.push({ name: t.path }) : t.files && e.push(...I(t.files)), e), []);
308
+ async function le(s, e) {
309
+ var t;
310
+ try {
311
+ const n = (t = (await R(`https://unpkg.com/${s}@${e}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)"))) == null ? void 0 : t[0];
312
+ if (n) {
313
+ const c = await y.get(`https://unpkg.com/${s}@${n}/?meta`);
314
+ return { fileList: I(c.files || []), version: n };
315
+ } else
316
+ throw new $({
317
+ packageName: s,
318
+ version: e,
319
+ cdn: "unpkg"
320
+ });
321
+ } catch (r) {
322
+ throw r instanceof g ? new m({
323
+ packageName: s,
324
+ version: e,
325
+ cdn: "unpkg"
326
+ }) : r;
327
+ }
328
+ }
329
+ function ue(s, e, t) {
330
+ return `https://unpkg.com/${s}@${e}${t}`;
331
+ }
332
+ const de = {
333
+ getFileList: le,
334
+ getUrl: ue
335
+ }, he = async (s) => {
336
+ try {
337
+ const e = /^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;
338
+ if (e.test(s)) {
339
+ const t = s.replace(e, (r, n) => `${n}package.json`);
340
+ return await y.get(t);
341
+ } else
342
+ throw new Error(`${s} 不是正确的url`);
343
+ } catch (e) {
344
+ throw e;
345
+ }
346
+ }, fe = (s, e) => {
347
+ var t, r;
348
+ return ((t = s.dependencies) == null ? void 0 : t[e]) || ((r = s.devDependencies) == null ? void 0 : r[e]);
349
+ }, x = async (s, e, t) => {
350
+ if (!e.match(/\d+(.\d+)?(.\d+)?/))
351
+ throw new Error(`${s} version ${e} is not valid`);
352
+ const n = await E[t].getFileList(s, e), c = pe(n, s);
353
+ if (!c)
354
+ throw new W({
355
+ packageName: s,
356
+ version: e,
357
+ cdn: t
358
+ });
359
+ return E[t].getUrl(s, n.version, c);
360
+ }, pe = ({ fileList: s }, e) => {
361
+ var c, l;
362
+ let t = [
363
+ `umd/${e}.production.min.js`,
364
+ /umd\/.+?\.production\.min\.js$/,
365
+ /dist\/.+?\.production\.min\.js$/,
366
+ /dist\/.+?\.umd\.min\.js$/,
367
+ `dist/${e}.prod.min.js`,
368
+ /dist\/.+?\.global.prod.min.js/,
369
+ `dist/${e}.min.js`,
370
+ /.+?\.global.prod.min.js/,
371
+ /.+?.global.prod.js/,
372
+ /lib\/.+?\.min\.js$/,
373
+ /dist\/.+?\.min\.js$/,
374
+ /index\.min\.js$/,
375
+ /index\.js$/,
376
+ /\.min\.js$/,
377
+ /\.js$/
378
+ ];
379
+ const r = ["runtime", "compiler", ".esm", ".cjs", "development"].filter((o) => !e.includes(o));
380
+ let n = "";
381
+ for (let o of t)
382
+ if (o instanceof RegExp ? n = ((c = s.find((i) => o.test(i.name) && !r.some((d) => i.name.includes(d)))) == null ? void 0 : c.name) || "" : n = ((l = s.find((i) => i.name.includes(o) && !r.some((d) => i.name.includes(d)))) == null ? void 0 : l.name) || "", n)
383
+ break;
384
+ return n;
385
+ }, E = {
386
+ jsdelivr: ae,
387
+ bootcdn: se,
388
+ cdnjs: ce,
389
+ unpkg: de
390
+ };
391
+ var L = /* @__PURE__ */ ((s) => (s.noFound = "noFound", s.NetworkError = "networkError", s))(L || {});
392
+ class ge {
393
+ constructor() {
394
+ h(this, "cdnCache", {
395
+ packageDependencies: {},
396
+ cdnsUrl: {}
397
+ });
398
+ h(this, "cdnCachePath", "");
399
+ this.cdnCachePath = O.resolve(process.cwd(), "./.cdn-cache.json");
400
+ }
401
+ // 初始化cdn缓存
402
+ async init() {
403
+ try {
404
+ const e = await P.readFileSync(this.cdnCachePath, "utf-8");
405
+ this.cdnCache = JSON.parse(e);
406
+ } catch {
407
+ console.log("cdn缓存文件不存在,创建缓存文件"), this.cdnCache = {
408
+ packageDependencies: {},
409
+ cdnsUrl: {}
410
+ }, await P.writeFileSync(this.cdnCachePath, "", "utf-8");
411
+ }
412
+ }
413
+ /**
414
+ * 获取cdn缓存
415
+ * @param packageName 包名
416
+ * @param version 版本
417
+ */
418
+ getCdnCache(e, t) {
419
+ var r;
420
+ return (r = this.cdnCache.cdnsUrl[e]) == null ? void 0 : r[t];
421
+ }
422
+ /**
423
+ * 设置cdn缓存
424
+ * @param packageName 包名
425
+ * @param version 版本
426
+ * @param urls 地址列表
427
+ */
428
+ setCdnCache(e, t, r) {
429
+ this.cdnCache.cdnsUrl[e] ? this.cdnCache.cdnsUrl[e][t] = r : this.cdnCache.cdnsUrl[e] = {
430
+ [t]: r
431
+ };
432
+ }
433
+ /**
434
+ * 更新cdn缓存
435
+ */
436
+ async save() {
437
+ await P.writeFileSync(this.cdnCachePath, JSON.stringify(this.cdnCache), "utf-8");
438
+ }
439
+ /**
440
+ * 获取依赖包的package.json
441
+ * @param packageName 包名
442
+ * @param identification 版本号或者url
443
+ */
444
+ getPackageDependencies(e, t) {
445
+ var r;
446
+ return (r = this.cdnCache.packageDependencies[e]) == null ? void 0 : r[t];
447
+ }
448
+ /**
449
+ * 设置依赖包的package.json
450
+ * @param packageName 包名
451
+ * @param identification 版本号或者url
452
+ * @param dependencies 依赖
453
+ */
454
+ setPackageDependencies(e, t, r) {
455
+ this.cdnCache.packageDependencies[e] ? this.cdnCache.packageDependencies[e][t] = r : this.cdnCache.packageDependencies[e] = {
456
+ [t]: r
457
+ };
458
+ }
459
+ }
460
+ let C;
461
+ const N = async () => (C || (C = new ge(), await C.init()), C);
462
+ async function F({
463
+ external: s,
464
+ packageData: e,
465
+ customScript: t,
466
+ defaultCdns: r
467
+ }) {
468
+ let n = [], c = !1, l = [];
469
+ const o = await N();
470
+ return await Promise.all(
471
+ s.map(async (i) => {
472
+ const d = fe(e, i);
473
+ if (t[i])
474
+ return {
475
+ urls: [t[i]],
476
+ key: i
477
+ };
478
+ if (!d)
479
+ return n.push(i), {
480
+ urls: [],
481
+ key: i
482
+ };
483
+ const f = o.getCdnCache(i, d);
484
+ if (f) {
485
+ const p = new Set(r), j = /* @__PURE__ */ new Map(), k = f.filter((a, u) => {
486
+ if (p.has(a.cdnName) && a.success)
487
+ return p.delete(a.cdnName), !0;
488
+ !a.success && a.error === L.noFound ? p.delete(a.cdnName) : j.set(a.cdnName, u);
489
+ }).map((a) => a.url);
490
+ if (p.size > 0) {
491
+ const a = await Promise.allSettled(
492
+ [...p].map(async (u) => ({
493
+ cdnName: u,
494
+ success: !0,
495
+ url: await x(i, d, u)
496
+ }))
497
+ ).then((u) => u.filter((w) => {
498
+ if (w.status === "fulfilled")
499
+ return k.push(w.value.url), !0;
500
+ l.push(w.reason);
501
+ }));
502
+ a.length > 0 && (a.forEach((u) => {
503
+ const w = j.get(u.value.cdnName);
504
+ w !== void 0 ? f[w] = u.value : f.push(u.value);
505
+ }), o.setCdnCache(i, d, f), c = !0);
506
+ }
507
+ return {
508
+ urls: k,
509
+ version: d,
510
+ key: i
511
+ };
512
+ } else {
513
+ c = !0, console.log(`从网络获取${i}${d}的cdn地址`);
514
+ const p = await Promise.allSettled(
515
+ r.map(async (a) => ({
516
+ cdnName: a,
517
+ success: !0,
518
+ url: await x(i, d, a)
519
+ }))
520
+ ).then((a) => a.map((u) => {
521
+ if (u.status === "fulfilled")
522
+ return u.value;
523
+ if (l.push(u.reason), u.reason instanceof m || u.reason instanceof $)
524
+ return {
525
+ cdnName: u.reason.cdn,
526
+ success: !1,
527
+ error: u.reason instanceof m ? L.NetworkError : L.noFound
528
+ };
529
+ }).filter((u) => !!u)), j = p.filter((a) => a.success).map(
530
+ (a) => a.url
531
+ );
532
+ if (j.length === 0)
533
+ throw new Error(`
534
+ ${l.map((a) => a.message).join(`
535
+ `)}获取${i} ${d}的cdn地址失败`);
536
+ const k = {
537
+ urls: j,
538
+ version: d,
539
+ key: i
540
+ };
541
+ return o.setCdnCache(i, d, p), k;
542
+ }
543
+ })
544
+ ).then((i) => (c && o.save(), {
545
+ urls: i,
546
+ noVersionPackages: n,
547
+ errorList: l
548
+ }));
549
+ }
550
+ const we = async ({
551
+ packageVersionInfo: s
552
+ }) => {
553
+ const e = { dependencies: {} };
554
+ let t = !1;
555
+ const r = await N(), n = [];
556
+ return await Promise.allSettled(
557
+ s.map(async (c) => {
558
+ if (!c)
559
+ return;
560
+ const { urls: l } = c, o = l[0];
561
+ if (!o)
562
+ return;
563
+ const i = c.version || o, d = r.getPackageDependencies(c.key, i);
564
+ if (d)
565
+ return b(e.dependencies, d.dependencies);
566
+ const f = await he(o);
567
+ r.setPackageDependencies(c.key, i, {
568
+ dependencies: f.dependencies
569
+ }), t = !0, b(e.dependencies, f.dependencies);
570
+ })
571
+ ).then((c) => (t && r.save(), c.forEach((l) => {
572
+ l.status === "rejected" && n.push(l.reason);
573
+ }), {
574
+ urlPackageJsonRes: e,
575
+ errorList: n
576
+ }));
577
+ };
578
+ function me(s) {
579
+ let e = "";
580
+ const t = {};
581
+ return s.forEach((n) => {
582
+ if (!n)
583
+ return;
584
+ const { urls: c, key: l } = n;
585
+ t[l] = c;
586
+ const o = c[0];
587
+ e += `<script src="${o}" type="text/javascript" crossorigin="anonymous" onerror="errorCDN(this)" data-cur="0" data-key="${l}"><\/script>
588
+ `;
589
+ }), e = `<script>
590
+ function errorCDN(e) {
591
+ const packNameUrl = JSON.parse('${JSON.stringify(t)}');
592
+ const nextCur = parseInt(e.getAttribute("data-cur")) + 1;
593
+ const key = e.getAttribute("data-key");
594
+ const curPackNameUrl = packNameUrl[key]
595
+ if(nextCur>=curPackNameUrl.length){return;}
596
+ // 新的cdn链接
597
+ const url = curPackNameUrl[nextCur]
598
+ // 克隆原标签
599
+ const tagName = e.tagName
600
+ const cdnDOM = document.createElement(tagName);
601
+ cdnDOM.setAttribute(tagName === 'SCRIPT' ?'src' : 'href', url);
602
+ Object.keys(e.dataset).forEach(_key => {
603
+ cdnDOM.setAttribute('data-'+_key, e.dataset[_key]);
604
+ })
605
+ cdnDOM.setAttribute("data-cur", nextCur.toString());
606
+ cdnDOM.setAttribute("onerror", "errorCDN(this)");
607
+ document.head.appendChild(cdnDOM);
608
+ e.remove();
609
+ }
610
+ <\/script>`.replace(/^\s*\/\/.*?$/gm, "") + e, e;
611
+ }
612
+ function Q(s) {
613
+ return Object.prototype.toString.call(s);
614
+ }
615
+ function $e(s) {
616
+ return Q(s) === "[object String]";
617
+ }
618
+ function ye(s) {
619
+ return Q(s) === "[object Object]";
620
+ }
621
+ async function Ue({
622
+ libName: s,
623
+ customScript: e,
624
+ external: t,
625
+ defaultCdns: r
626
+ }) {
627
+ let n = new K(s);
628
+ const c = O.resolve(process.cwd(), "package.json");
629
+ if (!t)
630
+ return "";
631
+ let l = [];
632
+ if ($e(t))
633
+ l = [t];
634
+ else if (Array.isArray(t))
635
+ l = t.filter((o) => typeof o == "string");
636
+ else if (ye(t))
637
+ l = Object.keys(t);
638
+ else
639
+ return "";
640
+ try {
641
+ const o = P.readFileSync(c, "utf-8"), i = JSON.parse(o), {
642
+ urls: d,
643
+ noVersionPackages: f,
644
+ errorList: p
645
+ } = await F({
646
+ external: l,
647
+ packageData: i,
648
+ customScript: e,
649
+ defaultCdns: r
650
+ });
651
+ if (n.addMessageList("warn", p), f.length > 0) {
652
+ const { urlPackageJsonRes: k, errorList: a } = await we({
653
+ packageVersionInfo: d
654
+ });
655
+ n.addMessageList("warn", a);
656
+ const {
657
+ urls: u,
658
+ noVersionPackages: w,
659
+ errorList: q
660
+ } = await F({
661
+ external: f,
662
+ packageData: k,
663
+ customScript: e,
664
+ defaultCdns: r
665
+ });
666
+ if (n.addMessageList("warn", q), u.map((v) => {
667
+ var D;
668
+ if (!v)
669
+ return;
670
+ const { urls: G, key: H } = v;
671
+ (D = d.find((U) => (U == null ? void 0 : U.key) === H)) == null || D.urls.push(...G);
672
+ }), w.length > 0)
673
+ throw new Error(`找不到${w.join(",")}的版本`);
674
+ }
675
+ return n.consoleAll(), me(d);
676
+ } catch (o) {
677
+ throw n.consoleAll(), o;
678
+ }
679
+ }
680
+ export {
681
+ K as ConsoleManage,
682
+ T as ConsoleType,
683
+ W as GetFileListError,
684
+ g as NetworkError,
685
+ $ as NoVersionError,
686
+ m as PackageNetworkError,
687
+ Ue as default,
688
+ F as findUrls,
689
+ me as generateScript,
690
+ we as getPackageDependencies
691
+ };
@@ -0,0 +1,25 @@
1
+ (function(a,f){typeof exports=="object"&&typeof module<"u"?f(exports,require("node-fetch"),require("semver"),require("node:path"),require("node:fs")):typeof define=="function"&&define.amd?define(["exports","node-fetch","semver","node:path","node:fs"],f):(a=typeof globalThis<"u"?globalThis:a||self,f(a.index={},a.fetch,a.semver,a.path,a.fs))})(this,function(a,f,j,F,v){"use strict";var me=Object.defineProperty;var ye=(a,f,j)=>f in a?me(a,f,{enumerable:!0,configurable:!0,writable:!0,value:j}):a[f]=j;var g=(a,f,j)=>(ye(a,typeof f!="symbol"?f+"":f,j),j);var b=(r=>(r.log="log",r.warn="warn",r.error="error",r.info="info",r))(b||{});class _{constructor(e){g(this,"logList",[]);g(this,"prefixString","cdn-script");e&&(this.prefixString=e)}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](`${this.prefixString} ${e.message}`)})}addMessageList(e,t){t.forEach(s=>{this.logList.push({type:e,message:s.toString()})})}clear(){this.logList=[]}}class p extends Error{constructor(e){super(e),this.name="NetworkError"}}class m extends p{constructor({packageName:t,version:s,cdn:n}){super(`${n} ${t}@${s} 网络请求失败`);g(this,"cdn");g(this,"packageName");g(this,"version");this.name="PackageNetworkError",this.cdn=n,this.packageName=t,this.version=s}getErrorInfo(){return{cdn:this.cdn,packageName:this.packageName,version:this.version}}}class y extends Error{constructor({packageName:t,version:s,cdn:n}){super(`${n}上没有${t}@${s}的版本`);g(this,"cdn");g(this,"packageName");g(this,"version");this.name="NoVersionError",this.cdn=n,this.packageName=t,this.version=s}getErrorInfo(){return{cdn:this.cdn,packageName:this.packageName,version:this.version}}}class M extends Error{constructor({packageName:e,version:t,cdn:s}){super(`在 ${s} 中找不到 ${e}@${t} 文件,请检查包名或版本号`),this.name="GetFileListError"}}function K(r,e){const t=r.replace(/^\D/,"").split("."),s=e.replace(/^\D/,"").split("."),n=Math.max(t.length,s.length);for(;t.length<n;)t.push("0");for(;s.length<n;)s.push("0");for(let c=0;c<n;c++){const d=parseInt(t[c],10),i=parseInt(s[c],10);if(d>i)return 1;if(d<i)return-1}return 0}function x(r,e){for(let t in e)Object.prototype.hasOwnProperty.call(e,t)&&(r[t]?K(r[t],e[t])===-1&&(r[t]=e[t]):r[t]=e[t]);return r}class W{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((s,n)=>{const c=this._createTask(e,t,s,n);this._count>=this._max?this._taskQueue.push(c):c()})}_createTask(e,t,s,n){return()=>{e(...t).then(s).catch(n).finally(()=>{this._count--,this._taskQueue.length&&this._taskQueue.shift()()}),this._count++}}}const O=new W(5),R=async r=>{try{const e=await f(r,{method:"HEAD",redirect:"manual"});return e.status>=300&&e.status<400?await R(e.headers.get("location")||""):r}catch(e){throw new p(e.message)}},X={get:async r=>{try{const e=await f(r);if(e.ok){const t=e.headers.get("content-type"),s=await e.text();return t&&t.includes("application/json")?JSON.parse(s):s}else throw new p(`请求失败,状态码:${e.status}`)}catch(e){throw new p(e.message)}}},P={get:O.call.bind(O,X.get)},Y={getFileList:async(r,e)=>{try{const t=await P.get(`https://api.bootcdn.cn/libraries/${r}`);if(t.length===0)throw new y({packageName:r,version:e,cdn:"bootcdn"});const s=t[0],c=s.assets.reverse().find(i=>{if(j.satisfies(i.version,e))return!0});if(!c)throw new y({packageName:r,version:e,cdn:"bootcdn"});return{fileList:c.files.map(i=>({name:"/"+i})),recommendFileName:s.filename,version:c.version}}catch(t){throw t instanceof p?new m({packageName:r,version:e,cdn:"bootcdn"}):t}},getUrl:(r,e,t)=>`https://cdn.bootcdn.net/ajax/libs/${r}/${e}${t}`};async function V(r,e,t=!1){try{if(!t&&e.match(/^\D/)){const n=await ee(r,e);for(let c of n)if(j.satisfies(c,e))return V(r,c,!0);throw new y({packageName:r,version:e,cdn:"cdnjs"})}const s=await P.get(`https://api.cdnjs.com/libraries/${r}/${e}`);if(s.error)throw new y({packageName:r,version:e,cdn:"cdnjs"});return{fileList:s.rawFiles.map(n=>({name:"/"+n})),version:e}}catch(s){throw s instanceof p?new m({packageName:r,version:e,cdn:"cdnjs"}):s}}const Z=(r,e,t)=>`https://cdnjs.cloudflare.com/ajax/libs/${r}/${e}${t}`,ee=async(r,e)=>{try{return(await P.get(`https://api.cdnjs.com/libraries/${r}?fields=versions`)).versions}catch(t){throw t instanceof p?new m({packageName:r,version:e,cdn:"cdnjs"}):t}},te={getFileList:V,getUrl:Z},J=(r,e="")=>r.reduce((t,s)=>(s.type==="file"?t.push({name:`${e}/${s.name}`}):s.files&&t.push(...J(s.files,`${e}/${s.name}`)),t),[]);async function A(r,e,t=!1){try{if(!t&&e.match(/^\D/)){const n=await se(r,e);if(typeof n=="string")return A(r,n,!0);throw new y({packageName:r,version:e,cdn:"jsdelivr"})}const s=await P.get(`https://data.jsdelivr.com/v1/packages/npm/${r}@${e}`);if(s.status)throw new y({packageName:r,version:e,cdn:"jsdelivr"});return{fileList:J(s.files),version:e}}catch(s){throw s instanceof p?new m({packageName:r,version:e,cdn:"jsdelivr"}):s}}const re=(r,e,t)=>`https://cdn.jsdelivr.net/npm/${r}@${e}${t}`,se=async(r,e)=>{try{return(await P.get(`https://data.jsdelivr.com/v1/packages/npm/${r}/resolved?specifier=${e}`)).version}catch(t){throw t instanceof p?new m({packageName:r,version:e,cdn:"jsdelivr"}):t}},ne={getFileList:A,getUrl:re},N=r=>r.reduce((e,t)=>(t.type==="file"?e.push({name:t.path}):t.files&&e.push(...N(t.files)),e),[]);async function ce(r,e){var t;try{const n=(t=(await R(`https://unpkg.com/${r}@${e}/?meta`)).match(new RegExp("(?<=@)\\d+\\.\\d+\\.\\d+(?=\\/\\?meta)")))==null?void 0:t[0];if(n){const c=await P.get(`https://unpkg.com/${r}@${n}/?meta`);return{fileList:N(c.files||[]),version:n}}else throw new y({packageName:r,version:e,cdn:"unpkg"})}catch(s){throw s instanceof p?new m({packageName:r,version:e,cdn:"unpkg"}):s}}function ie(r,e,t){return`https://unpkg.com/${r}@${e}${t}`}const oe={getFileList:ce,getUrl:ie},ae=async r=>{try{const e=/^(https?:\/\/.*\d+\.\d+\.\d+\/).+?\.js$/;if(e.test(r)){const t=r.replace(e,(s,n)=>`${n}package.json`);return await P.get(t)}else throw new Error(`${r} 不是正确的url`)}catch(e){throw e}},le=(r,e)=>{var t,s;return((t=r.dependencies)==null?void 0:t[e])||((s=r.devDependencies)==null?void 0:s[e])},I=async(r,e,t)=>{if(!e.match(/\d+(.\d+)?(.\d+)?/))throw new Error(`${r} version ${e} is not valid`);const n=await q[t].getFileList(r,e),c=de(n,r);if(!c)throw new M({packageName:r,version:e,cdn:t});return q[t].getUrl(r,n.version,c)},de=({fileList:r},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 s=["runtime","compiler",".esm",".cjs","development"].filter(i=>!e.includes(i));let n="";for(let i of t)if(i instanceof RegExp?n=((c=r.find(o=>i.test(o.name)&&!s.some(h=>o.name.includes(h))))==null?void 0:c.name)||"":n=((d=r.find(o=>o.name.includes(i)&&!s.some(h=>o.name.includes(h))))==null?void 0:d.name)||"",n)break;return n},q={jsdelivr:ne,bootcdn:Y,cdnjs:te,unpkg:oe};var U=(r=>(r.noFound="noFound",r.NetworkError="networkError",r))(U||{});class ue{constructor(){g(this,"cdnCache",{packageDependencies:{},cdnsUrl:{}});g(this,"cdnCachePath","");this.cdnCachePath=F.resolve(process.cwd(),"./.cdn-cache.json")}async init(){try{const e=await v.readFileSync(this.cdnCachePath,"utf-8");this.cdnCache=JSON.parse(e)}catch{console.log("cdn缓存文件不存在,创建缓存文件"),this.cdnCache={packageDependencies:{},cdnsUrl:{}},await v.writeFileSync(this.cdnCachePath,"","utf-8")}}getCdnCache(e,t){var s;return(s=this.cdnCache.cdnsUrl[e])==null?void 0:s[t]}setCdnCache(e,t,s){this.cdnCache.cdnsUrl[e]?this.cdnCache.cdnsUrl[e][t]=s:this.cdnCache.cdnsUrl[e]={[t]:s}}async save(){await v.writeFileSync(this.cdnCachePath,JSON.stringify(this.cdnCache),"utf-8")}getPackageDependencies(e,t){var s;return(s=this.cdnCache.packageDependencies[e])==null?void 0:s[t]}setPackageDependencies(e,t,s){this.cdnCache.packageDependencies[e]?this.cdnCache.packageDependencies[e][t]=s:this.cdnCache.packageDependencies[e]={[t]:s}}}let D;const Q=async()=>(D||(D=new ue,await D.init()),D);async function S({external:r,packageData:e,customScript:t,defaultCdns:s}){let n=[],c=!1,d=[];const i=await Q();return await Promise.all(r.map(async o=>{const h=le(e,o);if(t[o])return{urls:[t[o]],key:o};if(!h)return n.push(o),{urls:[],key:o};const w=i.getCdnCache(o,h);if(w){const $=new Set(s),C=new Map,L=w.filter((l,u)=>{if($.has(l.cdnName)&&l.success)return $.delete(l.cdnName),!0;!l.success&&l.error===U.noFound?$.delete(l.cdnName):C.set(l.cdnName,u)}).map(l=>l.url);if($.size>0){const l=await Promise.allSettled([...$].map(async u=>({cdnName:u,success:!0,url:await I(o,h,u)}))).then(u=>u.filter(k=>{if(k.status==="fulfilled")return L.push(k.value.url),!0;d.push(k.reason)}));l.length>0&&(l.forEach(u=>{const k=C.get(u.value.cdnName);k!==void 0?w[k]=u.value:w.push(u.value)}),i.setCdnCache(o,h,w),c=!0)}return{urls:L,version:h,key:o}}else{c=!0,console.log(`从网络获取${o}${h}的cdn地址`);const $=await Promise.allSettled(s.map(async l=>({cdnName:l,success:!0,url:await I(o,h,l)}))).then(l=>l.map(u=>{if(u.status==="fulfilled")return u.value;if(d.push(u.reason),u.reason instanceof m||u.reason instanceof y)return{cdnName:u.reason.cdn,success:!1,error:u.reason instanceof m?U.NetworkError:U.noFound}}).filter(u=>!!u)),C=$.filter(l=>l.success).map(l=>l.url);if(C.length===0)throw new Error(`
2
+ ${d.map(l=>l.message).join(`
3
+ `)}获取${o} ${h}的cdn地址失败`);const L={urls:C,version:h,key:o};return i.setCdnCache(o,h,$),L}})).then(o=>(c&&i.save(),{urls:o,noVersionPackages:n,errorList:d}))}const T=async({packageVersionInfo:r})=>{const e={dependencies:{}};let t=!1;const s=await Q(),n=[];return await Promise.allSettled(r.map(async c=>{if(!c)return;const{urls:d}=c,i=d[0];if(!i)return;const o=c.version||i,h=s.getPackageDependencies(c.key,o);if(h)return x(e.dependencies,h.dependencies);const w=await ae(i);s.setPackageDependencies(c.key,o,{dependencies:w.dependencies}),t=!0,x(e.dependencies,w.dependencies)})).then(c=>(t&&s.save(),c.forEach(d=>{d.status==="rejected"&&n.push(d.reason)}),{urlPackageJsonRes:e,errorList:n}))};function G(r){let e="";const t={};return r.forEach(n=>{if(!n)return;const{urls:c,key:d}=n;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 H(r){return Object.prototype.toString.call(r)}function he(r){return H(r)==="[object String]"}function fe(r){return H(r)==="[object Object]"}async function ge({libName:r,customScript:e,external:t,defaultCdns:s}){let n=new _(r);const c=F.resolve(process.cwd(),"package.json");if(!t)return"";let d=[];if(he(t))d=[t];else if(Array.isArray(t))d=t.filter(i=>typeof i=="string");else if(fe(t))d=Object.keys(t);else return"";try{const i=v.readFileSync(c,"utf-8"),o=JSON.parse(i),{urls:h,noVersionPackages:w,errorList:$}=await S({external:d,packageData:o,customScript:e,defaultCdns:s});if(n.addMessageList("warn",$),w.length>0){const{urlPackageJsonRes:L,errorList:l}=await T({packageVersionInfo:h});n.addMessageList("warn",l);const{urls:u,noVersionPackages:k,errorList:pe}=await S({external:w,packageData:L,customScript:e,defaultCdns:s});if(n.addMessageList("warn",pe),u.map(z=>{var B;if(!z)return;const{urls:we,key:$e}=z;(B=h.find(E=>(E==null?void 0:E.key)===$e))==null||B.urls.push(...we)}),k.length>0)throw new Error(`找不到${k.join(",")}的版本`)}return n.consoleAll(),G(h)}catch(i){throw n.consoleAll(),i}}a.ConsoleManage=_,a.ConsoleType=b,a.GetFileListError=M,a.NetworkError=p,a.NoVersionError=y,a.PackageNetworkError=m,a.default=ge,a.findUrls=S,a.generateScript=G,a.getPackageDependencies=T,Object.defineProperties(a,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "cdn-script-core",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "type": "module",
6
+ "main": "./dist/index.umd.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "index.d.ts"
12
+ ],
13
+ "keywords": [],
14
+ "author": "",
15
+ "license": "ISC",
16
+ "exports": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js",
19
+ "require": "./dist/index.js"
20
+ },
21
+ "devDependencies": {
22
+ "@jest/globals": "^29.7.0",
23
+ "@types/node": "^20.12.11",
24
+ "@types/node-fetch": "2",
25
+ "@types/react": "^18.3.2",
26
+ "@types/react-dom": "^18.3.0",
27
+ "@types/semver": "^7.5.8",
28
+ "@vitejs/plugin-react": "^4.2.1",
29
+ "cross-env": "^7.0.3",
30
+ "jest": "^29.7.0",
31
+ "react": "^18.2.0",
32
+ "react-dom": "^18.2.0",
33
+ "react-router-dom": "^6.23.1",
34
+ "rollup-plugin-external-globals": "^0.10.0",
35
+ "rollup-plugin-node-externals": "^7.1.2",
36
+ "ts-jest": "^29.1.4",
37
+ "ts-node": "^10.9.2",
38
+ "typescript": "^5.4.5",
39
+ "vite": "^5.2.11",
40
+ "vite-plugin-dts": "^3.8.0"
41
+ },
42
+ "publishConfig": {
43
+ "registry": "https://registry.npmjs.org/"
44
+ },
45
+ "dependencies": {
46
+ "node-fetch": "2",
47
+ "semver": "^7.6.2"
48
+ },
49
+ "scripts": {
50
+ "build": " vite build",
51
+ "test": "jest"
52
+ }
53
+ }