nodelistparser 1.5.3 → 1.6.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.cjs CHANGED
@@ -1 +1 @@
1
- var s=require("foxts/guard"),e=require("foxts/string-join"),r=require("foxts/uint8array-utils");let t=Number,o=s=>s.split(",").map(s=>s.trim());function n(s){let e=s.indexOf("=");return -1===e?["",""]:[s.slice(0,e).trim(),s.slice(e+1).trim()]}let p=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),a=new Set(["version","download-bandwidth","port-hopping-interval","udp-port","shadow-tls-version"]),i=new Set,d=new Set(["username","password","sni","encrypt-method","psk","obfs","obfs-host","uuid","alpn","block-quic","ws-path","ws-headers","port-hopping","token","underlying-proxy","shadow-tls-password","shadow-tls-sni"]),u=Symbol("unsupported");function l(s){return s.split(",").reduce((s,e)=>{let[r,t]=e.split(":"),o=t.trim();return(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),s[r.trim()]=o,s},{})}function w(s){let e,r,[o,n]=s.split("://");if("ss"!==o)throw Error(`[ss.decodeOne] Unsupported type: ${o}`);let[p,a]=n.split("@");p.includes(":")?[e,...r]=p.split(":",3):[e,...r]=atob(p).split(":",3),r=r.join(":");let[i,d]=a.split(":"),[u,l]=d.split("#"),[w,c]=u.split("/"),h=null;if(c)try{h=new URLSearchParams(c).get("plugin")}catch(e){let s=Error(`[ss.decodeOne] Invalid plugins: ${c}`);throw s.cause=e,s}let y=(h?.split(";")??[]).reduce((s,e)=>{let[r,t]=e.split("=");return s[r]=t,s},{});return{raw:s,type:"ss",name:decodeURIComponent(l),server:i,port:t(w),cipher:e,password:r,udp:!0,obfs:"obfs-local"in y&&"obfs"in y&&("http"===y.obfs||"tls"===y.obfs)?y.obfs:void 0,obfsHost:"obfs-host"in y?y["obfs-host"]:void 0}}function c(s){return atob(s).replaceAll("\r\n","\n").split("\n").filter(Boolean)}exports.clash={__proto__:null,decode:function(s){if(!("type"in s)||"string"!=typeof s.type)throw TypeError("Missing or invalid type field");let e=JSON.stringify(s);switch(s.type){case"http":return{type:"http",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,underlyingProxy:s["dialer-proxy"],raw:e};case"ss":return{type:"ss",name:s.name,server:s.server,port:Number(s.port),cipher:s.cipher,password:s.password,udp:s.udp||!1,obfs:"obfs"===s.plugin?s["plugin-opts"].mode:void 0,underlyingProxy:s["dialer-proxy"],shadowTlsSni:"shadow-tls"===s.plugin?s["plugin-opts"].host:void 0,shadowTlsPassword:"shadow-tls"===s.plugin?s["plugin-opts"].password:void 0,shadowTlsVersion:"shadow-tls"===s.plugin?s["plugin-opts"].version:void 0,raw:e};case"socks5":return{type:"socks5",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],raw:e};case"trojan":return{type:"trojan",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],ws:"ws"===s.network,wsPath:s["ws-opts"]?.path,wsHeaders:s["ws-opts"]?.headers?Object.entries(s["ws-opts"]?.headers).map(([s,e])=>`${s}:${e}`).join(", "):void 0,raw:e};case"vmess":return{type:"vmess",name:s.name,server:s.server,port:Number(s.port),username:s.uuid,vmessAead:0===s.alterId||"0"===s.alterId,sni:s.servername,ws:"ws"===s.network,wsPath:s["ws-path"],encryptMethod:s.cipher,wsHeaders:s["ws-headers"]?Object.entries(s["ws-headers"]).map(([s,e])=>`${s}:${e}`).join(", "):void 0,tls:s.tls||!1,udp:s.udp??!0,underlyingProxy:s["dialer-proxy"],raw:e,skipCertVerify:s["skip-cert-verify"]||!1};case"anytls":return{type:"anytls",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!0,reuse:!!s["idle-session-check-interval"]||!!s["idle-session-timeout"]||!!s["min-idle-session"],underlyingProxy:s["dialer-proxy"],raw:e};default:throw TypeError(`Unsupported type: ${s.type} (clash decode)`)}},encode:function(e){let r={name:e.name,server:e.server,port:e.port,tfo:e.tfo,"dialer-proxy":e.underlyingProxy},t={..."skipCertVerify"in e?{"skip-cert-verify":e.skipCertVerify}:{}};switch(e.type){case"ss":if(e.shadowTlsPassword&&(e.udp||e.udpPort))throw Error("Clash doesn't support plain UDP for Shadow TLS (clash encode)");return{type:"ss",cipher:e.cipher,password:e.password,udp:e.udp,...e.obfs?{plugin:"obfs","plugin-opts":{mode:e.obfs,host:e.obfsHost,uri:e.obfsUri}}:{},...e.shadowTlsPassword?{plugin:"shadow-tls","plugin-opts":{host:e.shadowTlsSni,password:e.shadowTlsPassword,version:e.shadowTlsVersion}}:{},...r,...t};case"trojan":return{type:"trojan",password:e.password,sni:e.sni,udp:e.udp,network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?l(e.wsHeaders):void 0}:void 0,...r,...t};case"tuic":case"tuic-v5":return{type:"tuic",sni:e.sni,uuid:e.uuid,alpn:e.alpn.split(",").map(s=>s.trim()),..."tuic"===e.type?{token:e.token}:{password:e.password},udp:!0,version:"tuic"===e.type?4:"tuic-v5"===e.type?5:s.never(e),...r,...t};case"socks5":return{type:"socks5",username:e.username,password:e.password,udp:e.udp,...r,...t};case"http":return{type:"http",username:e.username,password:e.password,...r,...t};case"vmess":return{alterId:+!e.vmessAead,tls:e.tls,udp:e.udp,uuid:e.username,servername:e.sni,cipher:e.encryptMethod||"auto",network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?l(e.wsHeaders):void 0}:void 0,type:"vmess",...r,...t};case"hysteria2":return{type:"hysteria2",ports:e.port+","+e.portHopping,password:e.password,down:e.downloadBandwidth+" Mbps",...r,...t};case"anytls":return{type:"anytls",password:e.password,sni:e.sni,udp:e.udp||!0,"idle-session-check-interval":e.reuse?30:void 0,"idle-session-timeout":e.reuse?30:void 0,"min-idle-session":e.reuse?5:void 0,...r,...t};default:throw TypeError(`Unsupported type: ${e.type} (clash encode)`)}}},exports.ss={__proto__:null,decodeBase64Multiline:c,decodeMultiline:function(s){return c(s).map(s=>w(s))},decodeOne:w},exports.surge={__proto__:null,decode:function(s){let[e,r]=n(s),[l,w,c,...h]=o(r),y=t(c),m=Object.fromEntries(h.map(s=>{let[e,r]=n(s);return p.has(e)?[e,"true"===r]:a.has(e)?[e,t(r)]:i.has(e)?[e,o(r)]:d.has(e)?'"'===r[0]&&r.endsWith('"')||"'"===r[0]&&r.endsWith("'")?[e,r.slice(1,-1)]:[e,r]:[e,u]})),v={raw:s,name:e,server:w,port:y,tfo:m.tfo,blockQuic:m["block-quic"],underlyingProxy:m["underlying-proxy"]},f={sni:m.sni,skipCertVerify:m["skip-cert-verify"]};switch(l){case"snell":return{type:"snell",psk:m.psk,version:m.version,reuse:m.reuse,...v};case"ss":{let s=m["shadow-tls-password"],e=m["shadow-tls-sni"],r=m["shadow-tls-version"];return{type:"ss",cipher:m["encrypt-method"],password:m.password,udp:m["udp-relay"],obfs:m.obfs,obfsHost:m["obfs-host"],obfsUri:m["obfs-uri"],udpPort:m["udp-port"],shadowTlsPassword:s,shadowTlsSni:e,shadowTlsVersion:r,...v}}case"trojan":return{type:"trojan",password:m.password,udp:m["udp-relay"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],...f,...v};case"tuic":return{type:"tuic",uuid:m.uuid,alpn:m.alpn,token:m.token,...f,...v};case"tuic-v5":return{type:"tuic-v5",uuid:m.uuid,alpn:m.alpn,password:m.password,...f,...v};case"socks5":return{type:"socks5",username:h[0],password:h[1],udp:m["udp-relay"],...v};case"http":return{type:"http",username:h[0],password:h[1],...v};case"vmess":return{type:"vmess",username:m.username,tls:m.tls,vmessAead:m["vmess-aead"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],udp:m["udp-relay"],...f,...v};case"hysteria2":return{type:"hysteria2",password:m.password,skipCertVerify:m["skip-cert-verify"],downloadBandwidth:m["download-bandwidth"],portHopping:m["port-hopping"],portHoppingInterval:m["port-hopping-interval"],...v};case"anytls":return{type:"anytls",password:m.password,reuse:m.reuse,udp:m["udp-relay"],...f,...v};default:throw TypeError(`Unsupported type: ${l} (surge decode)`)}},encode:function(r){let t=[r.tfo&&"tfo=true",r.blockQuic&&`block-quic=${r.blockQuic}`,r.underlyingProxy&&`underlying-proxy=${r.underlyingProxy}`];switch(r.type){case"snell":return e.stringJoin([`${r.name} = snell, ${r.server}, ${r.port}, psk=${r.psk}, version=${r.version}, reuse=${r.reuse}`,...t],", ");case"ss":return e.stringJoin([`${r.name} = ss, ${r.server}, ${r.port}, encrypt-method=${r.cipher}, password=${r.password}`,r.shadowTlsPassword&&`shadow-tls-password=${r.shadowTlsPassword}`,r.shadowTlsSni&&`shadow-tls-sni=${r.shadowTlsSni}`,r.shadowTlsVersion&&`shadow-tls-version=${r.shadowTlsVersion}`,r.udp&&"udp-relay=true",r.udpPort&&`udp-port=${r.udpPort}`,r.obfs&&`obfs=${r.obfs}`,r.obfsHost&&`obfs-host=${r.obfsHost}`,r.obfsUri&&`obfs-uri=${r.obfsUri}`,...t],", ");case"trojan":return e.stringJoin([`${r.name} = trojan, ${r.server}, ${r.port}, password=${r.password}`,r.sni&&`sni=${r.sni}`,r.skipCertVerify&&"skip-cert-verify=true",...t,r.udp&&"udp-relay=true",r.ws&&"ws=true",r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`],", ");case"tuic":return e.stringJoin([`${r.name} = tuic, ${r.server}, ${r.port}, sni=${r.sni}, uuid=${r.uuid}, alpn=${r.alpn}, token=${r.token}`,...t],", ");case"socks5":return e.stringJoin([`${r.name} = socks5, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,r.udp&&"udp-relay=true",...t],", ");case"http":return e.stringJoin([`${r.name} = http, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,...t],", ");case"vmess":return e.stringJoin([`${r.name} = vmess, ${r.server}, ${r.port}`,`username=${r.username}`,`tls=${r.tls}`,`vmess-aead=${r.vmessAead}`,r.ws&&"ws=true",r.encryptMethod&&`encrypt-method=${r.encryptMethod}`,r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`,`skip-cert-verify=${r.skipCertVerify}`,`udp-relay=${r.udp}`,...t],", ");case"hysteria2":return e.stringJoin([`${r.name} = hysteria2, ${r.server}, ${r.port}`,`password=${r.password}`,`download-bandwidth=${r.downloadBandwidth}`,r.portHopping&&`port-hopping="${r.portHopping}"`,r.portHoppingInterval&&`port-hopping-interval=${r.portHoppingInterval}`,`skip-cert-verify=${r.skipCertVerify}`,...t],", ");case"tuic-v5":return e.stringJoin([`${r.name} = tuic-v5, ${r.server}, ${r.port}`,`password=${r.password}`,`uuid=${r.uuid}`,`alpn=${r.alpn}`,`skip-cert-verify=${r.skipCertVerify}`,`sni=${r.sni}`,...t],", ");case"anytls":return e.stringJoin([`${r.name} = anytls, ${r.server}, ${r.port}, password=${r.password}`,`skip-cert-verify=${r.skipCertVerify}`,r.sni&&`sni=${r.sni}`,`reuse=${r.reuse}`,...t],", ");default:s.never(r,"config.type (surge encode)")}}},exports.trojan={__proto__:null,parse:function(s){let e=new URL(s),r=e.username,t=e.hostname,o=Number.parseInt(e.port,10);return{raw:s,name:decodeURIComponent(e.hash.slice(1)),type:"trojan",server:t,port:o,password:r,udp:!0,sni:e.searchParams.get("sni")??t,skipCertVerify:!0}}},exports.vmess={__proto__:null,parse:function(s){var e;let t=JSON.parse(r.uint8ArrayToString(r.base64ToUint8Array(s.slice(8)))),o=t.ps,n=t.path;return{raw:s,name:o,server:t.add,port:Number.parseInt(t.port,10),encryptMethod:t.scy,type:"vmess",username:t.id,tls:!!t.tls,vmessAead:"0"===t.aid||0===t.aid,sni:t.sni,ws:"ws"===t.net,wsPath:"/"===(e=n)[0]?e:`/${e}`,wsHeaders:t.sni||t.host?`Host:${t.sni||t.host}`:t.add,skipCertVerify:!0,udp:!0}}};
1
+ var s=require("foxts/guard"),e=require("foxts/string-join"),r=require("foxts/uint8array-utils");let t=Number,o=s=>s.split(",").map(s=>s.trim());function n(s){let e=s.indexOf("=");return -1===e?["",""]:[s.slice(0,e).trim(),s.slice(e+1).trim()]}let p=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),a=new Set(["version","download-bandwidth","port-hopping-interval","udp-port","shadow-tls-version"]),i=new Set,d=new Set(["username","password","sni","encrypt-method","psk","obfs","obfs-host","uuid","alpn","block-quic","ws-path","ws-headers","port-hopping","token","underlying-proxy","shadow-tls-password","shadow-tls-sni"]),u=Symbol("unsupported");function l(s){return s.split(",").reduce((s,e)=>{let[r,t]=e.split(":"),o=t.trim();return(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),s[r.trim()]=o,s},{})}function w(s){let e,r,[o,n]=s.split("://");if("ss"!==o)throw Error(`[ss.decodeOne] Unsupported type: ${o}`);let[p,a]=n.split("@");p.includes(":")?[e,...r]=p.split(":",3):[e,...r]=atob(p).split(":",3),r=r.join(":");let[i,d]=a.split(":"),[u,l]=d.split("#"),[w,h]=u.split("/"),c=null;if(h)try{c=new URLSearchParams(h).get("plugin")}catch(e){let s=Error(`[ss.decodeOne] Invalid plugins: ${h}`);throw s.cause=e,s}let y=(c?.split(";")??[]).reduce((s,e)=>{let[r,t]=e.split("=");return s[r]=t,s},{});return{raw:s,type:"ss",name:decodeURIComponent(l),server:i,port:t(w),cipher:e,password:r,udp:!0,obfs:"obfs-local"in y&&"obfs"in y&&("http"===y.obfs||"tls"===y.obfs)?y.obfs:void 0,obfsHost:"obfs-host"in y?y["obfs-host"]:void 0}}function h(s){return atob(s).replaceAll("\r\n","\n").split("\n").filter(Boolean)}exports.clash={__proto__:null,decode:function(s){if(!("type"in s)||"string"!=typeof s.type)throw TypeError("Missing or invalid type field");let e=JSON.stringify(s);switch(s.type){case"http":return{type:"http",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,underlyingProxy:s["dialer-proxy"],raw:e};case"ss":return{type:"ss",name:s.name,server:s.server,port:Number(s.port),cipher:s.cipher,password:s.password,udp:s.udp||!1,obfs:"obfs"===s.plugin?s["plugin-opts"].mode:void 0,underlyingProxy:s["dialer-proxy"],shadowTlsSni:"shadow-tls"===s.plugin?s["plugin-opts"].host:void 0,shadowTlsPassword:"shadow-tls"===s.plugin?s["plugin-opts"].password:void 0,shadowTlsVersion:"shadow-tls"===s.plugin?s["plugin-opts"].version:void 0,raw:e};case"socks5":return{type:"socks5",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],raw:e};case"trojan":return{type:"trojan",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],ws:"ws"===s.network,wsPath:s["ws-opts"]?.path,wsHeaders:s["ws-opts"]?.headers?Object.entries(s["ws-opts"]?.headers).map(([s,e])=>`${s}:${e}`).join(", "):void 0,raw:e};case"vmess":return{type:"vmess",name:s.name,server:s.server,port:Number(s.port),username:s.uuid,vmessAead:0===s.alterId||"0"===s.alterId,sni:s.servername,ws:"ws"===s.network,wsPath:s["ws-path"],encryptMethod:s.cipher,wsHeaders:s["ws-headers"]?Object.entries(s["ws-headers"]).map(([s,e])=>`${s}:${e}`).join(", "):void 0,tls:s.tls||!1,udp:s.udp??!0,underlyingProxy:s["dialer-proxy"],raw:e,skipCertVerify:s["skip-cert-verify"]||!1};case"anytls":return{type:"anytls",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!0,reuse:!!s["idle-session-check-interval"]||!!s["idle-session-timeout"]||!!s["min-idle-session"],underlyingProxy:s["dialer-proxy"],raw:e};default:throw TypeError(`Unsupported type: ${s.type} (clash decode)`)}},encode:function(e){let r={name:e.name,server:e.server,port:e.port,tfo:e.tfo,"dialer-proxy":e.underlyingProxy},t={..."skipCertVerify"in e?{"skip-cert-verify":e.skipCertVerify}:{}};switch(e.type){case"ss":if(e.shadowTlsPassword&&(e.udp||e.udpPort))throw Error("Clash doesn't support plain UDP for Shadow TLS (clash encode)");return{type:"ss",cipher:e.cipher,password:e.password,udp:e.udp,...e.obfs?{plugin:"obfs","plugin-opts":{mode:e.obfs,host:e.obfsHost,uri:e.obfsUri}}:{},...e.shadowTlsPassword?{plugin:"shadow-tls","plugin-opts":{host:e.shadowTlsSni,password:e.shadowTlsPassword,version:e.shadowTlsVersion}}:{},...r,...t};case"trojan":return{type:"trojan",password:e.password,sni:e.sni,udp:e.udp,network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?l(e.wsHeaders):void 0}:void 0,...r,...t};case"tuic":case"tuic-v5":return{type:"tuic",sni:e.sni,uuid:e.uuid,alpn:e.alpn.split(",").map(s=>s.trim()),..."tuic"===e.type?{token:e.token}:{password:e.password},udp:!0,version:"tuic"===e.type?4:"tuic-v5"===e.type?5:s.never(e),...r,...t};case"socks5":return{type:"socks5",username:e.username,password:e.password,udp:e.udp,...r,...t};case"http":return{type:"http",username:e.username,password:e.password,...r,...t};case"vmess":return{alterId:+!e.vmessAead,tls:e.tls,udp:e.udp,uuid:e.username,servername:e.sni,cipher:e.encryptMethod||"auto",network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?l(e.wsHeaders):void 0}:void 0,type:"vmess",...r,...t};case"hysteria2":return{type:"hysteria2",ports:e.port+","+e.portHopping,password:e.password,down:e.downloadBandwidth+" Mbps",...r,...t};case"anytls":return{type:"anytls",password:e.password,sni:e.sni,udp:e.udp||!0,"idle-session-check-interval":e.reuse?30:void 0,"idle-session-timeout":e.reuse?30:void 0,"min-idle-session":e.reuse?5:void 0,...r,...t};default:throw TypeError(`Unsupported type: ${e.type} (clash encode)`)}}},exports.ss={__proto__:null,decodeBase64Multiline:h,decodeMultiline:function(s){return h(s).map(s=>w(s))},decodeOne:w},exports.surge={__proto__:null,decode:function(s){let[e,r]=n(s),[l,w,h,...c]=o(r),y=t(h),m=Object.fromEntries(c.map(s=>{let[e,r]=n(s);return p.has(e)?[e,"true"===r]:a.has(e)?[e,t(r)]:i.has(e)?[e,o(r)]:d.has(e)?'"'===r[0]&&r.endsWith('"')||"'"===r[0]&&r.endsWith("'")?[e,r.slice(1,-1)]:[e,r]:[e,u]})),v={raw:s,name:e,server:w,port:y,tfo:m.tfo,blockQuic:m["block-quic"],underlyingProxy:m["underlying-proxy"]},f={sni:m.sni,skipCertVerify:m["skip-cert-verify"]},$={shadowTlsPassword:m["shadow-tls-password"],shadowTlsSni:m["shadow-tls-sni"],shadowTlsVersion:m["shadow-tls-version"]};switch(l){case"snell":return{type:"snell",psk:m.psk,version:m.version,reuse:m.reuse,...$,...v};case"ss":return{type:"ss",cipher:m["encrypt-method"],password:m.password,udp:m["udp-relay"],obfs:m.obfs,obfsHost:m["obfs-host"],obfsUri:m["obfs-uri"],udpPort:m["udp-port"],...$,...v};case"trojan":return{type:"trojan",password:m.password,udp:m["udp-relay"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],...f,...v};case"tuic":return{type:"tuic",uuid:m.uuid,alpn:m.alpn,token:m.token,...f,...v};case"tuic-v5":return{type:"tuic-v5",uuid:m.uuid,alpn:m.alpn,password:m.password,...f,...v};case"socks5":return{type:"socks5",username:c[0],password:c[1],udp:m["udp-relay"],...v};case"http":return{type:"http",username:c[0],password:c[1],...v};case"vmess":return{type:"vmess",username:m.username,tls:m.tls,vmessAead:m["vmess-aead"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],udp:m["udp-relay"],...f,...v};case"hysteria2":return{type:"hysteria2",password:m.password,skipCertVerify:m["skip-cert-verify"],downloadBandwidth:m["download-bandwidth"],portHopping:m["port-hopping"],portHoppingInterval:m["port-hopping-interval"],...v};case"anytls":return{type:"anytls",password:m.password,reuse:m.reuse,udp:m["udp-relay"],...f,...v};default:throw TypeError(`Unsupported type: ${l} (surge decode)`)}},encode:function(r){let t=[r.tfo&&"tfo=true",r.blockQuic&&`block-quic=${r.blockQuic}`,r.underlyingProxy&&`underlying-proxy=${r.underlyingProxy}`];switch(r.type){case"snell":return e.stringJoin([`${r.name} = snell, ${r.server}, ${r.port}, psk=${r.psk}, version=${r.version}, reuse=${r.reuse}`,r.shadowTlsPassword&&`shadow-tls-password=${r.shadowTlsPassword}`,r.shadowTlsSni&&`shadow-tls-sni=${r.shadowTlsSni}`,r.shadowTlsVersion&&`shadow-tls-version=${r.shadowTlsVersion}`,...t],", ");case"ss":return e.stringJoin([`${r.name} = ss, ${r.server}, ${r.port}, encrypt-method=${r.cipher}, password=${r.password}`,r.shadowTlsPassword&&`shadow-tls-password=${r.shadowTlsPassword}`,r.shadowTlsSni&&`shadow-tls-sni=${r.shadowTlsSni}`,r.shadowTlsVersion&&`shadow-tls-version=${r.shadowTlsVersion}`,r.udp&&"udp-relay=true",r.udpPort&&`udp-port=${r.udpPort}`,r.obfs&&`obfs=${r.obfs}`,r.obfsHost&&`obfs-host=${r.obfsHost}`,r.obfsUri&&`obfs-uri=${r.obfsUri}`,...t],", ");case"trojan":return e.stringJoin([`${r.name} = trojan, ${r.server}, ${r.port}, password=${r.password}`,r.sni&&`sni=${r.sni}`,r.skipCertVerify&&"skip-cert-verify=true",...t,r.udp&&"udp-relay=true",r.ws&&"ws=true",r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`],", ");case"tuic":return e.stringJoin([`${r.name} = tuic, ${r.server}, ${r.port}, sni=${r.sni}, uuid=${r.uuid}, alpn=${r.alpn}, token=${r.token}`,...t],", ");case"socks5":return e.stringJoin([`${r.name} = socks5, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,r.udp&&"udp-relay=true",...t],", ");case"http":return e.stringJoin([`${r.name} = http, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,...t],", ");case"vmess":return e.stringJoin([`${r.name} = vmess, ${r.server}, ${r.port}`,`username=${r.username}`,`tls=${r.tls}`,`vmess-aead=${r.vmessAead}`,r.ws&&"ws=true",r.encryptMethod&&`encrypt-method=${r.encryptMethod}`,r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`,`skip-cert-verify=${r.skipCertVerify}`,`udp-relay=${r.udp}`,...t],", ");case"hysteria2":return e.stringJoin([`${r.name} = hysteria2, ${r.server}, ${r.port}`,`password=${r.password}`,`download-bandwidth=${r.downloadBandwidth}`,r.portHopping&&`port-hopping="${r.portHopping}"`,r.portHoppingInterval&&`port-hopping-interval=${r.portHoppingInterval}`,`skip-cert-verify=${r.skipCertVerify}`,...t],", ");case"tuic-v5":return e.stringJoin([`${r.name} = tuic-v5, ${r.server}, ${r.port}`,`password=${r.password}`,`uuid=${r.uuid}`,`alpn=${r.alpn}`,`skip-cert-verify=${r.skipCertVerify}`,`sni=${r.sni}`,...t],", ");case"anytls":return e.stringJoin([`${r.name} = anytls, ${r.server}, ${r.port}, password=${r.password}`,`skip-cert-verify=${r.skipCertVerify}`,r.sni&&`sni=${r.sni}`,null!=r.reuse&&`reuse=${r.reuse}`,...t],", ");default:s.never(r,"config.type (surge encode)")}}},exports.trojan={__proto__:null,parse:function(s){let e=new URL(s),r=e.username,t=e.hostname,o=Number.parseInt(e.port,10);return{raw:s,name:decodeURIComponent(e.hash.slice(1)),type:"trojan",server:t,port:o,password:r,udp:!0,sni:e.searchParams.get("sni")??t,skipCertVerify:!0}}},exports.vmess={__proto__:null,parse:function(s){var e;let t=JSON.parse(r.uint8ArrayToString(r.base64ToUint8Array(s.slice(8)))),o=t.ps,n=t.path;return{raw:s,name:o,server:t.add,port:Number.parseInt(t.port,10),encryptMethod:t.scy,type:"vmess",username:t.id,tls:!!t.tls,vmessAead:"0"===t.aid||0===t.aid,sni:t.sni,ws:"ws"===t.net,wsPath:"/"===(e=n)[0]?e:`/${e}`,wsHeaders:t.sni||t.host?`Host:${t.sni||t.host}`:t.add,skipCertVerify:!0,udp:!0}}};
package/dist/index.d.ts CHANGED
@@ -21,7 +21,15 @@ interface HttpProxyConfig extends SharedConfigBase {
21
21
  username: string;
22
22
  password: string;
23
23
  }
24
- interface ShadowSocksConfig extends SharedConfigBase {
24
+ interface ShadowTlsSharedExtension {
25
+ /** Shadow TLS Version */
26
+ shadowTlsVersion?: 1 | 2 | 3;
27
+ /** Shadow TLS Password */
28
+ shadowTlsPassword?: string;
29
+ /** Shadow TLS SNI */
30
+ shadowTlsSni?: string | undefined;
31
+ }
32
+ interface ShadowSocksConfig extends SharedConfigBase, ShadowTlsSharedExtension {
25
33
  type: 'ss';
26
34
  /** encrypt-method */
27
35
  cipher: string;
@@ -35,12 +43,6 @@ interface ShadowSocksConfig extends SharedConfigBase {
35
43
  obfsUri?: string;
36
44
  /** udp-port */
37
45
  udpPort?: number;
38
- /** Shadow TLS Version */
39
- shadowTlsVersion?: 1 | 2 | 3;
40
- /** Shadow TLS Password */
41
- shadowTlsPassword?: string;
42
- /** Shadow TLS SNI */
43
- shadowTlsSni?: string | undefined;
44
46
  }
45
47
  interface TrojanConfig extends SharedConfigBase, TlsSharedConfig {
46
48
  type: 'trojan';
@@ -48,13 +50,13 @@ interface TrojanConfig extends SharedConfigBase, TlsSharedConfig {
48
50
  /** udp-relay */
49
51
  udp: boolean;
50
52
  /** ws */
51
- ws: boolean | undefined;
53
+ ws?: boolean | undefined;
52
54
  /** ws-path */
53
- wsPath: string | undefined;
55
+ wsPath?: string | undefined;
54
56
  /** ws-headers */
55
- wsHeaders: string | undefined;
57
+ wsHeaders?: string | undefined;
56
58
  }
57
- interface SnellConfig extends SharedConfigBase {
59
+ interface SnellConfig extends SharedConfigBase, ShadowTlsSharedExtension {
58
60
  type: 'snell';
59
61
  psk: string;
60
62
  version: number;
@@ -65,7 +67,7 @@ interface AnyTLSConfig extends SharedConfigBase, TlsSharedConfig {
65
67
  password: string;
66
68
  /** udp-relay */
67
69
  udp: boolean;
68
- reuse: boolean;
70
+ reuse?: boolean;
69
71
  }
70
72
  interface TrojanBasicConfig extends SharedConfigBase, TlsSharedConfig {
71
73
  type: 'trojan';
@@ -305,4 +307,4 @@ declare namespace index {
305
307
  }
306
308
 
307
309
  export { index$3 as clash, index$2 as ss, index$4 as surge, index$1 as trojan, index as vmess };
308
- export type { AnyTLSConfig, HttpProxyConfig, Hysteria2Config, ShadowSocksConfig, SharedConfigBase, SnellConfig, Socks5Config, SupportedConfig, TlsSharedConfig, TrojanBasicConfig, TrojanConfig, TuicConfig, TuicV5Config, VmessConfig };
310
+ export type { AnyTLSConfig, HttpProxyConfig, Hysteria2Config, ShadowSocksConfig, ShadowTlsSharedExtension, SharedConfigBase, SnellConfig, Socks5Config, SupportedConfig, TlsSharedConfig, TrojanBasicConfig, TrojanConfig, TuicConfig, TuicV5Config, VmessConfig };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{never as s}from"foxts/guard";import{stringJoin as e}from"foxts/string-join";import{uint8ArrayToString as r,base64ToUint8Array as t}from"foxts/uint8array-utils";let o=Number,p=s=>s.split(",").map(s=>s.trim());function n(s){let e=s.indexOf("=");return -1===e?["",""]:[s.slice(0,e).trim(),s.slice(e+1).trim()]}let a=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),i=new Set(["version","download-bandwidth","port-hopping-interval","udp-port","shadow-tls-version"]),d=new Set,u=new Set(["username","password","sni","encrypt-method","psk","obfs","obfs-host","uuid","alpn","block-quic","ws-path","ws-headers","port-hopping","token","underlying-proxy","shadow-tls-password","shadow-tls-sni"]),l=Symbol("unsupported");var w={__proto__:null,decode:function(s){let[e,r]=n(s),[t,w,c,...h]=p(r),y=o(c),m=Object.fromEntries(h.map(s=>{let[e,r]=n(s);return a.has(e)?[e,"true"===r]:i.has(e)?[e,o(r)]:d.has(e)?[e,p(r)]:u.has(e)?'"'===r[0]&&r.endsWith('"')||"'"===r[0]&&r.endsWith("'")?[e,r.slice(1,-1)]:[e,r]:[e,l]})),v={raw:s,name:e,server:w,port:y,tfo:m.tfo,blockQuic:m["block-quic"],underlyingProxy:m["underlying-proxy"]},f={sni:m.sni,skipCertVerify:m["skip-cert-verify"]};switch(t){case"snell":return{type:"snell",psk:m.psk,version:m.version,reuse:m.reuse,...v};case"ss":{let s=m["shadow-tls-password"],e=m["shadow-tls-sni"],r=m["shadow-tls-version"];return{type:"ss",cipher:m["encrypt-method"],password:m.password,udp:m["udp-relay"],obfs:m.obfs,obfsHost:m["obfs-host"],obfsUri:m["obfs-uri"],udpPort:m["udp-port"],shadowTlsPassword:s,shadowTlsSni:e,shadowTlsVersion:r,...v}}case"trojan":return{type:"trojan",password:m.password,udp:m["udp-relay"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],...f,...v};case"tuic":return{type:"tuic",uuid:m.uuid,alpn:m.alpn,token:m.token,...f,...v};case"tuic-v5":return{type:"tuic-v5",uuid:m.uuid,alpn:m.alpn,password:m.password,...f,...v};case"socks5":return{type:"socks5",username:h[0],password:h[1],udp:m["udp-relay"],...v};case"http":return{type:"http",username:h[0],password:h[1],...v};case"vmess":return{type:"vmess",username:m.username,tls:m.tls,vmessAead:m["vmess-aead"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],udp:m["udp-relay"],...f,...v};case"hysteria2":return{type:"hysteria2",password:m.password,skipCertVerify:m["skip-cert-verify"],downloadBandwidth:m["download-bandwidth"],portHopping:m["port-hopping"],portHoppingInterval:m["port-hopping-interval"],...v};case"anytls":return{type:"anytls",password:m.password,reuse:m.reuse,udp:m["udp-relay"],...f,...v};default:throw TypeError(`Unsupported type: ${t} (surge decode)`)}},encode:function(r){let t=[r.tfo&&"tfo=true",r.blockQuic&&`block-quic=${r.blockQuic}`,r.underlyingProxy&&`underlying-proxy=${r.underlyingProxy}`];switch(r.type){case"snell":return e([`${r.name} = snell, ${r.server}, ${r.port}, psk=${r.psk}, version=${r.version}, reuse=${r.reuse}`,...t],", ");case"ss":return e([`${r.name} = ss, ${r.server}, ${r.port}, encrypt-method=${r.cipher}, password=${r.password}`,r.shadowTlsPassword&&`shadow-tls-password=${r.shadowTlsPassword}`,r.shadowTlsSni&&`shadow-tls-sni=${r.shadowTlsSni}`,r.shadowTlsVersion&&`shadow-tls-version=${r.shadowTlsVersion}`,r.udp&&"udp-relay=true",r.udpPort&&`udp-port=${r.udpPort}`,r.obfs&&`obfs=${r.obfs}`,r.obfsHost&&`obfs-host=${r.obfsHost}`,r.obfsUri&&`obfs-uri=${r.obfsUri}`,...t],", ");case"trojan":return e([`${r.name} = trojan, ${r.server}, ${r.port}, password=${r.password}`,r.sni&&`sni=${r.sni}`,r.skipCertVerify&&"skip-cert-verify=true",...t,r.udp&&"udp-relay=true",r.ws&&"ws=true",r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`],", ");case"tuic":return e([`${r.name} = tuic, ${r.server}, ${r.port}, sni=${r.sni}, uuid=${r.uuid}, alpn=${r.alpn}, token=${r.token}`,...t],", ");case"socks5":return e([`${r.name} = socks5, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,r.udp&&"udp-relay=true",...t],", ");case"http":return e([`${r.name} = http, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,...t],", ");case"vmess":return e([`${r.name} = vmess, ${r.server}, ${r.port}`,`username=${r.username}`,`tls=${r.tls}`,`vmess-aead=${r.vmessAead}`,r.ws&&"ws=true",r.encryptMethod&&`encrypt-method=${r.encryptMethod}`,r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`,`skip-cert-verify=${r.skipCertVerify}`,`udp-relay=${r.udp}`,...t],", ");case"hysteria2":return e([`${r.name} = hysteria2, ${r.server}, ${r.port}`,`password=${r.password}`,`download-bandwidth=${r.downloadBandwidth}`,r.portHopping&&`port-hopping="${r.portHopping}"`,r.portHoppingInterval&&`port-hopping-interval=${r.portHoppingInterval}`,`skip-cert-verify=${r.skipCertVerify}`,...t],", ");case"tuic-v5":return e([`${r.name} = tuic-v5, ${r.server}, ${r.port}`,`password=${r.password}`,`uuid=${r.uuid}`,`alpn=${r.alpn}`,`skip-cert-verify=${r.skipCertVerify}`,`sni=${r.sni}`,...t],", ");case"anytls":return e([`${r.name} = anytls, ${r.server}, ${r.port}, password=${r.password}`,`skip-cert-verify=${r.skipCertVerify}`,r.sni&&`sni=${r.sni}`,`reuse=${r.reuse}`,...t],", ");default:s(r,"config.type (surge encode)")}}};function c(s){return s.split(",").reduce((s,e)=>{let[r,t]=e.split(":"),o=t.trim();return(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),s[r.trim()]=o,s},{})}var h={__proto__:null,decode:function(s){if(!("type"in s)||"string"!=typeof s.type)throw TypeError("Missing or invalid type field");let e=JSON.stringify(s);switch(s.type){case"http":return{type:"http",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,underlyingProxy:s["dialer-proxy"],raw:e};case"ss":return{type:"ss",name:s.name,server:s.server,port:Number(s.port),cipher:s.cipher,password:s.password,udp:s.udp||!1,obfs:"obfs"===s.plugin?s["plugin-opts"].mode:void 0,underlyingProxy:s["dialer-proxy"],shadowTlsSni:"shadow-tls"===s.plugin?s["plugin-opts"].host:void 0,shadowTlsPassword:"shadow-tls"===s.plugin?s["plugin-opts"].password:void 0,shadowTlsVersion:"shadow-tls"===s.plugin?s["plugin-opts"].version:void 0,raw:e};case"socks5":return{type:"socks5",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],raw:e};case"trojan":return{type:"trojan",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],ws:"ws"===s.network,wsPath:s["ws-opts"]?.path,wsHeaders:s["ws-opts"]?.headers?Object.entries(s["ws-opts"]?.headers).map(([s,e])=>`${s}:${e}`).join(", "):void 0,raw:e};case"vmess":return{type:"vmess",name:s.name,server:s.server,port:Number(s.port),username:s.uuid,vmessAead:0===s.alterId||"0"===s.alterId,sni:s.servername,ws:"ws"===s.network,wsPath:s["ws-path"],encryptMethod:s.cipher,wsHeaders:s["ws-headers"]?Object.entries(s["ws-headers"]).map(([s,e])=>`${s}:${e}`).join(", "):void 0,tls:s.tls||!1,udp:s.udp??!0,underlyingProxy:s["dialer-proxy"],raw:e,skipCertVerify:s["skip-cert-verify"]||!1};case"anytls":return{type:"anytls",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!0,reuse:!!s["idle-session-check-interval"]||!!s["idle-session-timeout"]||!!s["min-idle-session"],underlyingProxy:s["dialer-proxy"],raw:e};default:throw TypeError(`Unsupported type: ${s.type} (clash decode)`)}},encode:function(e){let r={name:e.name,server:e.server,port:e.port,tfo:e.tfo,"dialer-proxy":e.underlyingProxy},t={..."skipCertVerify"in e?{"skip-cert-verify":e.skipCertVerify}:{}};switch(e.type){case"ss":if(e.shadowTlsPassword&&(e.udp||e.udpPort))throw Error("Clash doesn't support plain UDP for Shadow TLS (clash encode)");return{type:"ss",cipher:e.cipher,password:e.password,udp:e.udp,...e.obfs?{plugin:"obfs","plugin-opts":{mode:e.obfs,host:e.obfsHost,uri:e.obfsUri}}:{},...e.shadowTlsPassword?{plugin:"shadow-tls","plugin-opts":{host:e.shadowTlsSni,password:e.shadowTlsPassword,version:e.shadowTlsVersion}}:{},...r,...t};case"trojan":return{type:"trojan",password:e.password,sni:e.sni,udp:e.udp,network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?c(e.wsHeaders):void 0}:void 0,...r,...t};case"tuic":case"tuic-v5":return{type:"tuic",sni:e.sni,uuid:e.uuid,alpn:e.alpn.split(",").map(s=>s.trim()),..."tuic"===e.type?{token:e.token}:{password:e.password},udp:!0,version:"tuic"===e.type?4:"tuic-v5"===e.type?5:s(e),...r,...t};case"socks5":return{type:"socks5",username:e.username,password:e.password,udp:e.udp,...r,...t};case"http":return{type:"http",username:e.username,password:e.password,...r,...t};case"vmess":return{alterId:+!e.vmessAead,tls:e.tls,udp:e.udp,uuid:e.username,servername:e.sni,cipher:e.encryptMethod||"auto",network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?c(e.wsHeaders):void 0}:void 0,type:"vmess",...r,...t};case"hysteria2":return{type:"hysteria2",ports:e.port+","+e.portHopping,password:e.password,down:e.downloadBandwidth+" Mbps",...r,...t};case"anytls":return{type:"anytls",password:e.password,sni:e.sni,udp:e.udp||!0,"idle-session-check-interval":e.reuse?30:void 0,"idle-session-timeout":e.reuse?30:void 0,"min-idle-session":e.reuse?5:void 0,...r,...t};default:throw TypeError(`Unsupported type: ${e.type} (clash encode)`)}}};function y(s){let e,r,[t,p]=s.split("://");if("ss"!==t)throw Error(`[ss.decodeOne] Unsupported type: ${t}`);let[n,a]=p.split("@");n.includes(":")?[e,...r]=n.split(":",3):[e,...r]=atob(n).split(":",3),r=r.join(":");let[i,d]=a.split(":"),[u,l]=d.split("#"),[w,c]=u.split("/"),h=null;if(c)try{h=new URLSearchParams(c).get("plugin")}catch(e){let s=Error(`[ss.decodeOne] Invalid plugins: ${c}`);throw s.cause=e,s}let y=(h?.split(";")??[]).reduce((s,e)=>{let[r,t]=e.split("=");return s[r]=t,s},{});return{raw:s,type:"ss",name:decodeURIComponent(l),server:i,port:o(w),cipher:e,password:r,udp:!0,obfs:"obfs-local"in y&&"obfs"in y&&("http"===y.obfs||"tls"===y.obfs)?y.obfs:void 0,obfsHost:"obfs-host"in y?y["obfs-host"]:void 0}}function m(s){return atob(s).replaceAll("\r\n","\n").split("\n").filter(Boolean)}var v={__proto__:null,decodeBase64Multiline:m,decodeMultiline:function(s){return m(s).map(s=>y(s))},decodeOne:y},f={__proto__:null,parse:function(s){let e=new URL(s),r=e.username,t=e.hostname,o=Number.parseInt(e.port,10);return{raw:s,name:decodeURIComponent(e.hash.slice(1)),type:"trojan",server:t,port:o,password:r,udp:!0,sni:e.searchParams.get("sni")??t,skipCertVerify:!0}}},$={__proto__:null,parse:function(s){var e;let o=JSON.parse(r(t(s.slice(8)))),p=o.ps,n=o.path;return{raw:s,name:p,server:o.add,port:Number.parseInt(o.port,10),encryptMethod:o.scy,type:"vmess",username:o.id,tls:!!o.tls,vmessAead:"0"===o.aid||0===o.aid,sni:o.sni,ws:"ws"===o.net,wsPath:"/"===(e=n)[0]?e:`/${e}`,wsHeaders:o.sni||o.host?`Host:${o.sni||o.host}`:o.add,skipCertVerify:!0,udp:!0}}};export{h as clash,v as ss,w as surge,f as trojan,$ as vmess};
1
+ import{never as s}from"foxts/guard";import{stringJoin as e}from"foxts/string-join";import{uint8ArrayToString as r,base64ToUint8Array as t}from"foxts/uint8array-utils";let o=Number,p=s=>s.split(",").map(s=>s.trim());function a(s){let e=s.indexOf("=");return -1===e?["",""]:[s.slice(0,e).trim(),s.slice(e+1).trim()]}let n=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),i=new Set(["version","download-bandwidth","port-hopping-interval","udp-port","shadow-tls-version"]),d=new Set,u=new Set(["username","password","sni","encrypt-method","psk","obfs","obfs-host","uuid","alpn","block-quic","ws-path","ws-headers","port-hopping","token","underlying-proxy","shadow-tls-password","shadow-tls-sni"]),l=Symbol("unsupported");var w={__proto__:null,decode:function(s){let[e,r]=a(s),[t,w,h,...c]=p(r),y=o(h),m=Object.fromEntries(c.map(s=>{let[e,r]=a(s);return n.has(e)?[e,"true"===r]:i.has(e)?[e,o(r)]:d.has(e)?[e,p(r)]:u.has(e)?'"'===r[0]&&r.endsWith('"')||"'"===r[0]&&r.endsWith("'")?[e,r.slice(1,-1)]:[e,r]:[e,l]})),v={raw:s,name:e,server:w,port:y,tfo:m.tfo,blockQuic:m["block-quic"],underlyingProxy:m["underlying-proxy"]},f={sni:m.sni,skipCertVerify:m["skip-cert-verify"]},$={shadowTlsPassword:m["shadow-tls-password"],shadowTlsSni:m["shadow-tls-sni"],shadowTlsVersion:m["shadow-tls-version"]};switch(t){case"snell":return{type:"snell",psk:m.psk,version:m.version,reuse:m.reuse,...$,...v};case"ss":return{type:"ss",cipher:m["encrypt-method"],password:m.password,udp:m["udp-relay"],obfs:m.obfs,obfsHost:m["obfs-host"],obfsUri:m["obfs-uri"],udpPort:m["udp-port"],...$,...v};case"trojan":return{type:"trojan",password:m.password,udp:m["udp-relay"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],...f,...v};case"tuic":return{type:"tuic",uuid:m.uuid,alpn:m.alpn,token:m.token,...f,...v};case"tuic-v5":return{type:"tuic-v5",uuid:m.uuid,alpn:m.alpn,password:m.password,...f,...v};case"socks5":return{type:"socks5",username:c[0],password:c[1],udp:m["udp-relay"],...v};case"http":return{type:"http",username:c[0],password:c[1],...v};case"vmess":return{type:"vmess",username:m.username,tls:m.tls,vmessAead:m["vmess-aead"],ws:m.ws,wsPath:m["ws-path"],wsHeaders:m["ws-headers"],udp:m["udp-relay"],...f,...v};case"hysteria2":return{type:"hysteria2",password:m.password,skipCertVerify:m["skip-cert-verify"],downloadBandwidth:m["download-bandwidth"],portHopping:m["port-hopping"],portHoppingInterval:m["port-hopping-interval"],...v};case"anytls":return{type:"anytls",password:m.password,reuse:m.reuse,udp:m["udp-relay"],...f,...v};default:throw TypeError(`Unsupported type: ${t} (surge decode)`)}},encode:function(r){let t=[r.tfo&&"tfo=true",r.blockQuic&&`block-quic=${r.blockQuic}`,r.underlyingProxy&&`underlying-proxy=${r.underlyingProxy}`];switch(r.type){case"snell":return e([`${r.name} = snell, ${r.server}, ${r.port}, psk=${r.psk}, version=${r.version}, reuse=${r.reuse}`,r.shadowTlsPassword&&`shadow-tls-password=${r.shadowTlsPassword}`,r.shadowTlsSni&&`shadow-tls-sni=${r.shadowTlsSni}`,r.shadowTlsVersion&&`shadow-tls-version=${r.shadowTlsVersion}`,...t],", ");case"ss":return e([`${r.name} = ss, ${r.server}, ${r.port}, encrypt-method=${r.cipher}, password=${r.password}`,r.shadowTlsPassword&&`shadow-tls-password=${r.shadowTlsPassword}`,r.shadowTlsSni&&`shadow-tls-sni=${r.shadowTlsSni}`,r.shadowTlsVersion&&`shadow-tls-version=${r.shadowTlsVersion}`,r.udp&&"udp-relay=true",r.udpPort&&`udp-port=${r.udpPort}`,r.obfs&&`obfs=${r.obfs}`,r.obfsHost&&`obfs-host=${r.obfsHost}`,r.obfsUri&&`obfs-uri=${r.obfsUri}`,...t],", ");case"trojan":return e([`${r.name} = trojan, ${r.server}, ${r.port}, password=${r.password}`,r.sni&&`sni=${r.sni}`,r.skipCertVerify&&"skip-cert-verify=true",...t,r.udp&&"udp-relay=true",r.ws&&"ws=true",r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`],", ");case"tuic":return e([`${r.name} = tuic, ${r.server}, ${r.port}, sni=${r.sni}, uuid=${r.uuid}, alpn=${r.alpn}, token=${r.token}`,...t],", ");case"socks5":return e([`${r.name} = socks5, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,r.udp&&"udp-relay=true",...t],", ");case"http":return e([`${r.name} = http, ${r.server}, ${r.port}, ${r.username}, ${r.password}`,...t],", ");case"vmess":return e([`${r.name} = vmess, ${r.server}, ${r.port}`,`username=${r.username}`,`tls=${r.tls}`,`vmess-aead=${r.vmessAead}`,r.ws&&"ws=true",r.encryptMethod&&`encrypt-method=${r.encryptMethod}`,r.wsPath&&`ws-path=${"/"===r.wsPath[0]?r.wsPath:`/${r.wsPath}`}`,r.wsHeaders&&`ws-headers=${r.wsHeaders}`,`skip-cert-verify=${r.skipCertVerify}`,`udp-relay=${r.udp}`,...t],", ");case"hysteria2":return e([`${r.name} = hysteria2, ${r.server}, ${r.port}`,`password=${r.password}`,`download-bandwidth=${r.downloadBandwidth}`,r.portHopping&&`port-hopping="${r.portHopping}"`,r.portHoppingInterval&&`port-hopping-interval=${r.portHoppingInterval}`,`skip-cert-verify=${r.skipCertVerify}`,...t],", ");case"tuic-v5":return e([`${r.name} = tuic-v5, ${r.server}, ${r.port}`,`password=${r.password}`,`uuid=${r.uuid}`,`alpn=${r.alpn}`,`skip-cert-verify=${r.skipCertVerify}`,`sni=${r.sni}`,...t],", ");case"anytls":return e([`${r.name} = anytls, ${r.server}, ${r.port}, password=${r.password}`,`skip-cert-verify=${r.skipCertVerify}`,r.sni&&`sni=${r.sni}`,null!=r.reuse&&`reuse=${r.reuse}`,...t],", ");default:s(r,"config.type (surge encode)")}}};function h(s){return s.split(",").reduce((s,e)=>{let[r,t]=e.split(":"),o=t.trim();return(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),s[r.trim()]=o,s},{})}var c={__proto__:null,decode:function(s){if(!("type"in s)||"string"!=typeof s.type)throw TypeError("Missing or invalid type field");let e=JSON.stringify(s);switch(s.type){case"http":return{type:"http",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,underlyingProxy:s["dialer-proxy"],raw:e};case"ss":return{type:"ss",name:s.name,server:s.server,port:Number(s.port),cipher:s.cipher,password:s.password,udp:s.udp||!1,obfs:"obfs"===s.plugin?s["plugin-opts"].mode:void 0,underlyingProxy:s["dialer-proxy"],shadowTlsSni:"shadow-tls"===s.plugin?s["plugin-opts"].host:void 0,shadowTlsPassword:"shadow-tls"===s.plugin?s["plugin-opts"].password:void 0,shadowTlsVersion:"shadow-tls"===s.plugin?s["plugin-opts"].version:void 0,raw:e};case"socks5":return{type:"socks5",name:s.name,server:s.server,port:Number(s.port),username:s.username,password:s.password,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],raw:e};case"trojan":return{type:"trojan",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!1,underlyingProxy:s["dialer-proxy"],ws:"ws"===s.network,wsPath:s["ws-opts"]?.path,wsHeaders:s["ws-opts"]?.headers?Object.entries(s["ws-opts"]?.headers).map(([s,e])=>`${s}:${e}`).join(", "):void 0,raw:e};case"vmess":return{type:"vmess",name:s.name,server:s.server,port:Number(s.port),username:s.uuid,vmessAead:0===s.alterId||"0"===s.alterId,sni:s.servername,ws:"ws"===s.network,wsPath:s["ws-path"],encryptMethod:s.cipher,wsHeaders:s["ws-headers"]?Object.entries(s["ws-headers"]).map(([s,e])=>`${s}:${e}`).join(", "):void 0,tls:s.tls||!1,udp:s.udp??!0,underlyingProxy:s["dialer-proxy"],raw:e,skipCertVerify:s["skip-cert-verify"]||!1};case"anytls":return{type:"anytls",name:s.name,server:s.server,port:Number(s.port),password:s.password,sni:s.sni,skipCertVerify:s["skip-cert-verify"]||!1,udp:s.udp||!0,reuse:!!s["idle-session-check-interval"]||!!s["idle-session-timeout"]||!!s["min-idle-session"],underlyingProxy:s["dialer-proxy"],raw:e};default:throw TypeError(`Unsupported type: ${s.type} (clash decode)`)}},encode:function(e){let r={name:e.name,server:e.server,port:e.port,tfo:e.tfo,"dialer-proxy":e.underlyingProxy},t={..."skipCertVerify"in e?{"skip-cert-verify":e.skipCertVerify}:{}};switch(e.type){case"ss":if(e.shadowTlsPassword&&(e.udp||e.udpPort))throw Error("Clash doesn't support plain UDP for Shadow TLS (clash encode)");return{type:"ss",cipher:e.cipher,password:e.password,udp:e.udp,...e.obfs?{plugin:"obfs","plugin-opts":{mode:e.obfs,host:e.obfsHost,uri:e.obfsUri}}:{},...e.shadowTlsPassword?{plugin:"shadow-tls","plugin-opts":{host:e.shadowTlsSni,password:e.shadowTlsPassword,version:e.shadowTlsVersion}}:{},...r,...t};case"trojan":return{type:"trojan",password:e.password,sni:e.sni,udp:e.udp,network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?h(e.wsHeaders):void 0}:void 0,...r,...t};case"tuic":case"tuic-v5":return{type:"tuic",sni:e.sni,uuid:e.uuid,alpn:e.alpn.split(",").map(s=>s.trim()),..."tuic"===e.type?{token:e.token}:{password:e.password},udp:!0,version:"tuic"===e.type?4:"tuic-v5"===e.type?5:s(e),...r,...t};case"socks5":return{type:"socks5",username:e.username,password:e.password,udp:e.udp,...r,...t};case"http":return{type:"http",username:e.username,password:e.password,...r,...t};case"vmess":return{alterId:+!e.vmessAead,tls:e.tls,udp:e.udp,uuid:e.username,servername:e.sni,cipher:e.encryptMethod||"auto",network:e.ws?"ws":"tcp","ws-opts":e.ws?{path:e.wsPath,headers:e.wsHeaders?h(e.wsHeaders):void 0}:void 0,type:"vmess",...r,...t};case"hysteria2":return{type:"hysteria2",ports:e.port+","+e.portHopping,password:e.password,down:e.downloadBandwidth+" Mbps",...r,...t};case"anytls":return{type:"anytls",password:e.password,sni:e.sni,udp:e.udp||!0,"idle-session-check-interval":e.reuse?30:void 0,"idle-session-timeout":e.reuse?30:void 0,"min-idle-session":e.reuse?5:void 0,...r,...t};default:throw TypeError(`Unsupported type: ${e.type} (clash encode)`)}}};function y(s){let e,r,[t,p]=s.split("://");if("ss"!==t)throw Error(`[ss.decodeOne] Unsupported type: ${t}`);let[a,n]=p.split("@");a.includes(":")?[e,...r]=a.split(":",3):[e,...r]=atob(a).split(":",3),r=r.join(":");let[i,d]=n.split(":"),[u,l]=d.split("#"),[w,h]=u.split("/"),c=null;if(h)try{c=new URLSearchParams(h).get("plugin")}catch(e){let s=Error(`[ss.decodeOne] Invalid plugins: ${h}`);throw s.cause=e,s}let y=(c?.split(";")??[]).reduce((s,e)=>{let[r,t]=e.split("=");return s[r]=t,s},{});return{raw:s,type:"ss",name:decodeURIComponent(l),server:i,port:o(w),cipher:e,password:r,udp:!0,obfs:"obfs-local"in y&&"obfs"in y&&("http"===y.obfs||"tls"===y.obfs)?y.obfs:void 0,obfsHost:"obfs-host"in y?y["obfs-host"]:void 0}}function m(s){return atob(s).replaceAll("\r\n","\n").split("\n").filter(Boolean)}var v={__proto__:null,decodeBase64Multiline:m,decodeMultiline:function(s){return m(s).map(s=>y(s))},decodeOne:y},f={__proto__:null,parse:function(s){let e=new URL(s),r=e.username,t=e.hostname,o=Number.parseInt(e.port,10);return{raw:s,name:decodeURIComponent(e.hash.slice(1)),type:"trojan",server:t,port:o,password:r,udp:!0,sni:e.searchParams.get("sni")??t,skipCertVerify:!0}}},$={__proto__:null,parse:function(s){var e;let o=JSON.parse(r(t(s.slice(8)))),p=o.ps,a=o.path;return{raw:s,name:p,server:o.add,port:Number.parseInt(o.port,10),encryptMethod:o.scy,type:"vmess",username:o.id,tls:!!o.tls,vmessAead:"0"===o.aid||0===o.aid,sni:o.sni,ws:"ws"===o.net,wsPath:"/"===(e=a)[0]?e:`/${e}`,wsHeaders:o.sni||o.host?`Host:${o.sni||o.host}`:o.add,skipCertVerify:!0,udp:!0}}};export{c as clash,v as ss,w as surge,f as trojan,$ as vmess};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodelistparser",
3
- "version": "1.5.3",
3
+ "version": "1.6.0",
4
4
  "description": "Surge / Mihomo (Clash.Meta) nodelist / proxy provider parser and generator.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,28 +31,28 @@
31
31
  "author": "Sukka <https://skk.moe>",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "foxts": "^5.2.1"
34
+ "foxts": "^5.4.2"
35
35
  },
36
36
  "devDependencies": {
37
- "@eslint-sukka/node": "^8.3.0",
37
+ "@eslint-sukka/node": "^8.10.3",
38
38
  "@swc-node/register": "^1.11.1",
39
- "@swc/core": "^1.15.10",
39
+ "@swc/core": "^1.15.33",
40
40
  "@types/mocha": "^10.0.10",
41
- "@types/node": "^24.10.9",
42
- "bumpp": "^10.4.0",
43
- "bunchee": "^6.9.4",
44
- "eslint": "^9.39.2",
45
- "eslint-config-sukka": "^8.3.0",
46
- "eslint-formatter-sukka": "^8.3.0",
47
- "expect": "^30.2.0",
41
+ "@types/node": "^24.12.4",
42
+ "bumpp": "^10.4.1",
43
+ "bunchee": "^6.10.0",
44
+ "earl": "^2.0.0",
45
+ "eslint": "^10.4.0",
46
+ "eslint-config-sukka": "^8.10.3",
47
+ "eslint-formatter-sukka": "^8.10.3",
48
48
  "mocha": "^11.7.5",
49
- "typescript": "^5.9.3"
49
+ "typescript": "^6.0.3"
50
50
  },
51
51
  "scripts": {
52
52
  "lint": "eslint --format=sukka .",
53
53
  "build": "bunchee --minify --no-sourcemap",
54
54
  "test": "mocha --require @swc-node/register src/*.test.ts src/**/*.test.ts",
55
55
  "prerelease": "pnpm run lint && pnpm run test && pnpm run build",
56
- "release": "bumpp -r --all --commit \"release: %s\" --tag \"%s\""
56
+ "release": "bumpp --install -r --all --commit \"release: %s\" --tag \"%s\""
57
57
  }
58
58
  }