vite-add-cdn-script 0.0.10 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +165 -0
- package/README.md +88 -89
- package/dist/index.js +493 -374
- package/dist/index.umd.cjs +25 -24
- package/index.d.ts +5 -6
- package/package.json +64 -64
package/dist/index.umd.cjs
CHANGED
@@ -1,24 +1,25 @@
|
|
1
|
-
(function(
|
2
|
-
`
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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/index.d.ts
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
interface IOptions {
|
2
|
-
customScript?: { [key: string]: string };
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
export default function viteAddCdnScript(options: IOptions);
|
1
|
+
interface IOptions {
|
2
|
+
customScript?: { [key: string]: string };
|
3
|
+
defaultCdns?: string[];
|
4
|
+
}
|
5
|
+
export default function viteAddCdnScript(options: IOptions);
|
package/package.json
CHANGED
@@ -1,64 +1,64 @@
|
|
1
|
-
{
|
2
|
-
"name": "vite-add-cdn-script",
|
3
|
-
"version": "0.0
|
4
|
-
"keywords": [
|
5
|
-
"vite",
|
6
|
-
"cdn",
|
7
|
-
"cdn-script",
|
8
|
-
"auto-add-cdn",
|
9
|
-
"vite-add-cdn-script"
|
10
|
-
],
|
11
|
-
"description": "A plugin for vite to add cdn script to index.html",
|
12
|
-
"repository": {
|
13
|
-
"type": "git",
|
14
|
-
"url": "git+https://github.com/baizeteam/baize-
|
15
|
-
},
|
16
|
-
"homepage": "https://github.com/baizeteam/baize-
|
17
|
-
"author": "baizeteam",
|
18
|
-
"type": "module",
|
19
|
-
"files": [
|
20
|
-
"dist",
|
21
|
-
"index.d.ts"
|
22
|
-
],
|
23
|
-
"main": "./dist/index.umd.cjs",
|
24
|
-
"module": "./dist/index.js",
|
25
|
-
"types": "./index.d.ts",
|
26
|
-
"exports": {
|
27
|
-
"types": "./index.d.ts",
|
28
|
-
"import": "./dist/index.js",
|
29
|
-
"require": "./dist/index.js"
|
30
|
-
},
|
31
|
-
"
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"
|
35
|
-
"
|
36
|
-
|
37
|
-
|
38
|
-
"@
|
39
|
-
"
|
40
|
-
"
|
41
|
-
"
|
42
|
-
"
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"jest": "^29.
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"
|
50
|
-
|
51
|
-
|
52
|
-
"
|
53
|
-
|
54
|
-
|
55
|
-
"
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
"
|
62
|
-
"
|
63
|
-
}
|
64
|
-
}
|
1
|
+
{
|
2
|
+
"name": "vite-add-cdn-script",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"keywords": [
|
5
|
+
"vite",
|
6
|
+
"cdn",
|
7
|
+
"cdn-script",
|
8
|
+
"auto-add-cdn",
|
9
|
+
"vite-add-cdn-script"
|
10
|
+
],
|
11
|
+
"description": "A plugin for vite to add cdn script to index.html",
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "git+https://github.com/baizeteam/baize-package.git"
|
15
|
+
},
|
16
|
+
"homepage": "https://github.com/baizeteam/baize-package/tree/release/package/vite-add-cdn-script#readme",
|
17
|
+
"author": "baizeteam",
|
18
|
+
"type": "module",
|
19
|
+
"files": [
|
20
|
+
"dist",
|
21
|
+
"index.d.ts"
|
22
|
+
],
|
23
|
+
"main": "./dist/index.umd.cjs",
|
24
|
+
"module": "./dist/index.js",
|
25
|
+
"types": "./index.d.ts",
|
26
|
+
"exports": {
|
27
|
+
"types": "./index.d.ts",
|
28
|
+
"import": "./dist/index.js",
|
29
|
+
"require": "./dist/index.js"
|
30
|
+
},
|
31
|
+
"devDependencies": {
|
32
|
+
"@jest/globals": "^29.7.0",
|
33
|
+
"@types/node": "^20.12.11",
|
34
|
+
"@types/node-fetch": "2",
|
35
|
+
"@types/react": "^18.3.2",
|
36
|
+
"@types/react-dom": "^18.3.0",
|
37
|
+
"@types/semver": "^7.5.8",
|
38
|
+
"@vitejs/plugin-react": "^4.2.1",
|
39
|
+
"cross-env": "^7.0.3",
|
40
|
+
"jest": "^29.7.0",
|
41
|
+
"react": "^18.2.0",
|
42
|
+
"react-dom": "^18.2.0",
|
43
|
+
"react-router-dom": "^6.23.1",
|
44
|
+
"rollup-plugin-external-globals": "^0.10.0",
|
45
|
+
"rollup-plugin-node-externals": "^7.1.2",
|
46
|
+
"ts-jest": "^29.1.4",
|
47
|
+
"ts-node": "^10.9.2",
|
48
|
+
"typescript": "^5.4.5",
|
49
|
+
"vite": "^5.2.11"
|
50
|
+
},
|
51
|
+
"publishConfig": {
|
52
|
+
"registry": "https://registry.npmjs.org/"
|
53
|
+
},
|
54
|
+
"dependencies": {
|
55
|
+
"node-fetch": "2",
|
56
|
+
"semver": "^7.6.2"
|
57
|
+
},
|
58
|
+
"scripts": {
|
59
|
+
"dev": "vite",
|
60
|
+
"build:page": "tsc && cross-env BUILD_MODE=page vite build",
|
61
|
+
"build": "tsc && cross-env BUILD_MODE=lib vite build",
|
62
|
+
"test": "jest"
|
63
|
+
}
|
64
|
+
}
|