nodelistparser 1.1.0 → 1.2.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.
@@ -7,6 +7,8 @@ interface SharedConfigBase {
7
7
  tfo?: boolean;
8
8
  /** block-quic */
9
9
  blockQuic?: string;
10
+ /** underlying-proxy */
11
+ underlyingProxy?: string;
10
12
  }
11
13
  interface TlsSharedConfig {
12
14
  /** sni */
@@ -54,14 +56,12 @@ interface TrojanBasicConfig extends SharedConfigBase, TlsSharedConfig {
54
56
  }
55
57
  interface TuicConfig extends SharedConfigBase, TlsSharedConfig {
56
58
  type: 'tuic';
57
- sni: string;
58
59
  uuid: string;
59
60
  alpn: string;
60
61
  token: string;
61
62
  }
62
63
  interface TuicV5Config extends SharedConfigBase, TlsSharedConfig {
63
64
  type: 'tuic-v5';
64
- sni: string;
65
65
  uuid: string;
66
66
  alpn: string;
67
67
  password: string;
@@ -108,6 +108,7 @@ declare namespace index$4 {
108
108
  declare function decode(config: Record<string, any>): SupportedConfig;
109
109
  declare function encode(config: SupportedConfig): {
110
110
  tfo: boolean | undefined;
111
+ 'dialer-proxy': string | undefined;
111
112
  plugin?: string | undefined;
112
113
  'plugin-opts'?: {
113
114
  mode: "http" | "tls";
@@ -134,6 +135,7 @@ declare function encode(config: SupportedConfig): {
134
135
  'skip-cert-verify'?: undefined;
135
136
  } | {
136
137
  tfo: boolean | undefined;
138
+ 'dialer-proxy': string | undefined;
137
139
  name: string;
138
140
  type: string;
139
141
  server: string;
@@ -155,6 +157,7 @@ declare function encode(config: SupportedConfig): {
155
157
  down?: undefined;
156
158
  } | {
157
159
  tfo: boolean | undefined;
160
+ 'dialer-proxy': string | undefined;
158
161
  'skip-cert-verify': boolean;
159
162
  udp: boolean;
160
163
  version: number;
@@ -163,7 +166,7 @@ declare function encode(config: SupportedConfig): {
163
166
  type: string;
164
167
  server: string;
165
168
  port: number;
166
- sni: string;
169
+ sni: string | undefined;
167
170
  uuid: string;
168
171
  alpn: string[];
169
172
  alterId?: undefined;
@@ -179,6 +182,7 @@ declare function encode(config: SupportedConfig): {
179
182
  down?: undefined;
180
183
  } | {
181
184
  tfo: boolean | undefined;
185
+ 'dialer-proxy': string | undefined;
182
186
  'skip-cert-verify': boolean;
183
187
  udp: boolean;
184
188
  version: number;
@@ -187,7 +191,7 @@ declare function encode(config: SupportedConfig): {
187
191
  type: string;
188
192
  server: string;
189
193
  port: number;
190
- sni: string;
194
+ sni: string | undefined;
191
195
  uuid: string;
192
196
  alpn: string[];
193
197
  alterId?: undefined;
@@ -202,6 +206,7 @@ declare function encode(config: SupportedConfig): {
202
206
  down?: undefined;
203
207
  } | {
204
208
  tfo: boolean | undefined;
209
+ 'dialer-proxy': string | undefined;
205
210
  name: string;
206
211
  type: string;
207
212
  server: string;
@@ -223,6 +228,7 @@ declare function encode(config: SupportedConfig): {
223
228
  'skip-cert-verify'?: undefined;
224
229
  } | {
225
230
  tfo: boolean | undefined;
231
+ 'dialer-proxy': string | undefined;
226
232
  name: string;
227
233
  type: string;
228
234
  server: string;
@@ -327,4 +333,4 @@ declare namespace index {
327
333
  }
328
334
 
329
335
  export { index$3 as clash, index$2 as ss, index$4 as surge, index$1 as trojan, index as vmess };
330
- export type { HttpProxyConfig, Hysteria2Config, ShadowSocksConfig, SharedConfigBase, SnellConfig, Socks5Config, SupportedConfig, TrojanBasicConfig, TrojanConfig, TuicConfig, TuicV5Config, VmessConfig };
336
+ export type { HttpProxyConfig, Hysteria2Config, ShadowSocksConfig, SharedConfigBase, SnellConfig, Socks5Config, SupportedConfig, TlsSharedConfig, TrojanBasicConfig, TrojanConfig, TuicConfig, TuicV5Config, VmessConfig };
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- var e=require("foxts/guard"),s=require("node:buffer");const r=e=>"true"===e,t=Number,p=e=>e.split(",").map(e=>e.trim());function o(e){let s=e.indexOf("=");return -1===s?["",""]:[e.slice(0,s).trim(),e.slice(s+1).trim()]}const n=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),a=e=>n.has(e),i=new Set(["version","download-bandwidth","port-hopping-interval","udp-port"]),u=e=>i.has(e),d=new Set([]),c=e=>d.has(e),l=new Set(["username","password","sni","encrypt-method","psk","obfs","obfs-host","uuid","alpn","block-quic","ws-path","ws-headers","port-hopping","token"]),w=e=>l.has(e),m=Symbol("unsupported"),f=e=>e.filter(Boolean).join(", ");function v(e){return e.split(",").reduce((e,s)=>{let[r,t]=s.split(":");return e[r.trim()]=t.trim(),e},{})}function y(e){let s,r,[p,o]=e.split("://");if("ss"!==p)throw Error(`[ss.decodeOne] Unsupported type: ${p}`);let[n,a]=o.split("@");n.includes(":")?[s,r]=n.split(":"):[s,r]=atob(n).split(":");let[i,u]=a.split(":"),[d,c]=u.split("#"),[l,w]=d.split("/"),m=null;if(w)try{m=new URLSearchParams(w).get("plugin")}catch(s){let e=Error(`[ss.decodeOne] Invalid plugins: ${w}`);throw e.cause=s,e}let f=(m?.split(";")??[]).reduce((e,s)=>{let[r,t]=s.split("=");return e[r]=t,e},{});return{raw:e,type:"ss",name:decodeURIComponent(c),server:i,port:t(l),cipher:s,password:r,udp:!0,obfs:"obfs-local"in f&&"obfs"in f&&("http"===f.obfs||"tls"===f.obfs)?f.obfs:void 0,obfsHost:"obfs-host"in f?f["obfs-host"]:void 0}}function h(e){return atob(e).replaceAll("\r\n","\n").split("\n").filter(Boolean)}const $=new TextDecoder;exports.clash={__proto__:null,decode:function(e){if(!("type"in e)||"string"!=typeof e.type)throw TypeError("Missing or invalid type field");let s=JSON.stringify(e);switch(e.type){case"http":return{type:"http",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,raw:s};case"ss":return{type:"ss",name:e.name,server:e.server,port:Number(e.port),cipher:e.cipher,password:e.password,udp:e.udp||!1,obfs:"obfs"===e.plugin?e["plugin-opts"].mode:void 0,raw:s};case"socks5":return{type:"socks5",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,udp:e.udp||!1,raw:s};case"trojan":return{type:"trojan",name:e.name,server:e.server,port:Number(e.port),password:e.password,sni:e.sni,skipCertVerify:e["skip-cert-verify"]||!1,udp:e.udp||!1,raw:s};case"vmess":return{type:"vmess",name:e.name,server:e.server,port:Number(e.port),username:e.uuid,vmessAead:1===e.alterId||"1"===e.alterId,sni:e.servername,ws:"ws"===e.network,wsPath:e["ws-path"],wsHeaders:e["ws-headers"]?Object.entries(e["ws-headers"]).map(([e,s])=>`${e}:${s}`).join(", "):void 0,tls:e.tls||!1,udp:e.udp??!0,raw:s,skipCertVerify:e["skip-cert-verify"]||!1};default:throw TypeError(`Unsupported type: ${e.type} (clash decode)`)}},encode:function(s){let r={tfo:s.tfo};switch(s.type){case"ss":return{name:s.name,type:"ss",server:s.server,port:s.port,cipher:s.cipher,password:s.password,udp:s.udp,...s.obfs?{plugin:"obfs","plugin-opts":{mode:s.obfs,host:s.obfsHost,uri:s.obfsUri}}:{},...r};case"trojan":return{name:s.name,type:"trojan",server:s.server,port:s.port,password:s.password,sni:s.sni,"skip-cert-verify":s.skipCertVerify,udp:s.udp,...r};case"tuic":case"tuic-v5":return{name:s.name,type:"tuic",server:s.server,port:s.port,sni:s.sni,uuid:s.uuid,alpn:s.alpn.split(",").map(e=>e.trim()),..."tuic"===s.type?{token:s.token}:{password:s.password},"skip-cert-verify":s.skipCertVerify,udp:!0,version:"tuic"===s.type?4:"tuic-v5"===s.type?5:e.never(s),...r};case"socks5":return{name:s.name,type:"socks5",server:s.server,port:s.port,username:s.username,password:s.password,udp:s.udp,...r};case"http":return{name:s.name,type:"http",server:s.server,port:s.port,username:s.username,password:s.password,...r};case"vmess":return{alterId:s.vmessAead?0:void 0,tls:s.tls,udp:s.udp,uuid:s.username,name:s.name,servername:s.sni,"ws-path":s.wsPath,server:s.server,"ws-headers":s.wsHeaders?v(s.wsHeaders):void 0,cipher:"auto","ws-opts":{path:s.wsPath,headers:s.wsHeaders?v(s.wsHeaders):void 0},type:"vmess",port:s.port,network:s.ws?"ws":"tcp"};case"hysteria2":return{name:s.name,type:"hysteria2",server:s.server,port:s.port,ports:s.portHopping,password:s.password,down:s.downloadBandwidth+" Mbps","skip-cert-verify":s.skipCertVerify};default:throw TypeError(`Unsupported type: ${s.type} (clash encode)`)}}},exports.ss={__proto__:null,decodeBase64Multiline:h,decodeMultiline:function(e){return h(e).map(e=>y(e))},decodeOne:y},exports.surge={__proto__:null,decode:function(e){let[s,n]=o(e),[i,d,l,...f]=p(n),v=t(l),y=Object.fromEntries(f.map(e=>{let[s,n]=o(e);return a(s)?[s,r(n)]:u(s)?[s,t(n)]:c(s)?[s,p(n)]:w(s)?'"'===n[0]&&n.endsWith('"')||"'"===n[0]&&n.endsWith("'")?[s,n.slice(1,-1)]:[s,n]:[s,m]})),h={raw:e,name:s,server:d,port:v,tfo:y.tfo,blockQuic:y["block-quic"]};switch(i){case"snell":return{type:"snell",psk:y.psk,version:y.version,reuse:y.reuse,...h};case"ss":return{type:"ss",cipher:y["encrypt-method"],password:y.password,udp:y["udp-relay"],obfs:y.obfs,obfsHost:y["obfs-host"],obfsUri:y["obfs-uri"],udpPort:y["udp-port"],...h};case"trojan":return{type:"trojan",password:y.password,sni:y.sni,skipCertVerify:y["skip-cert-verify"],udp:y["udp-relay"],...h};case"tuic":return{type:"tuic",sni:y.sni,uuid:y.uuid,alpn:y.alpn,token:y.token,skipCertVerify:y["skip-cert-verify"],...h};case"tuic-v5":return{type:"tuic-v5",uuid:y.uuid,alpn:y.alpn,password:y.password,sni:y.sni,skipCertVerify:y["skip-cert-verify"],...h};case"socks5":return{type:"socks5",username:f[0],password:f[1],udp:y["udp-relay"],...h};case"http":return{type:"http",username:f[0],password:f[1],...h};case"vmess":return{type:"vmess",username:y.username,tls:y.tls,vmessAead:y["vmess-aead"],ws:y.ws,wsPath:y["ws-path"],wsHeaders:y["ws-headers"],skipCertVerify:y["skip-cert-verify"],udp:y["udp-relay"],sni:y.sni,...h};case"hysteria2":return{type:"hysteria2",password:y.password,skipCertVerify:y["skip-cert-verify"],downloadBandwidth:y["download-bandwidth"],portHopping:y["port-hopping"],portHoppingInterval:y["port-hopping-interval"],...h};default:throw TypeError(`Unsupported type: ${i} (surge decode)`)}},encode:function(s){let r=[s.tfo&&"tfo=true",s.blockQuic&&`block-quic=${s.blockQuic}`];switch(s.type){case"snell":return f([`${s.name} = snell, ${s.server}, ${s.port}, psk=${s.psk}, version=${s.version}, reuse=${s.reuse}`,...r]);case"ss":return f([`${s.name} = ss, ${s.server}, ${s.port}, encrypt-method=${s.cipher}, password=${s.password}`,s.udp&&"udp-relay=true",s.udpPort&&`udp-port=${s.udpPort}`,s.obfs&&`obfs=${s.obfs}`,s.obfsHost&&`obfs-host=${s.obfsHost}`,s.obfsUri&&`obfs-uri=${s.obfsUri}`,...r]);case"trojan":return f([`${s.name} = trojan, ${s.server}, ${s.port}, password=${s.password}`,s.sni&&`sni=${s.sni}`,s.skipCertVerify&&"skip-cert-verify=true",...r,s.udp&&"udp-relay=true"]);case"tuic":return f([`${s.name} = tuic, ${s.server}, ${s.port}, sni=${s.sni}, uuid=${s.uuid}, alpn=${s.alpn}, token=${s.token}`,...r]);case"socks5":return f([`${s.name} = socks5, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,s.udp&&"udp-relay=true",...r]);case"http":return f([`${s.name} = http, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,...r]);case"vmess":return f([`${s.name} = vmess, ${s.server}, ${s.port}`,`username=${s.username}`,`tls=${s.tls}`,`vmess-aead=${s.vmessAead}`,"ws=true",s.wsPath&&`ws-path=${"/"===s.wsPath[0]?s.wsPath:`/${s.wsPath}`}`,s.wsHeaders&&`ws-headers=${s.wsHeaders}`,`skip-cert-verify=${s.skipCertVerify}`,`tfo=${s.tfo}`,`udp-relay=${s.udp}`]);case"hysteria2":return f([`${s.name} = hysteria2, ${s.server}, ${s.port}`,`password=${s.password}`,`download-bandwidth=${s.downloadBandwidth}`,s.portHopping&&`port-hopping="${s.portHopping}"`,s.portHoppingInterval&&`port-hopping-interval=${s.portHoppingInterval}`,`skip-cert-verify=${s.skipCertVerify}`,...r]);case"tuic-v5":return f([`${s.name} = tuic-v5, ${s.server}, ${s.port}`,`password=${s.password}`,`uuid=${s.uuid}`,`alpn=${s.alpn}`,`skip-cert-verify=${s.skipCertVerify}`,`sni=${s.sni}`,...r]);default:e.never(s,"type (clash encode)")}}},exports.trojan={__proto__:null,parse:function(e){let s=new URL(e),r=s.username,t=s.hostname,p=Number.parseInt(s.port,10);if(Number.isNaN(p))throw TypeError("invalid port: "+s.port);return{raw:e,name:decodeURIComponent(s.hash.slice(1)),type:"trojan",server:t,port:p,password:r,udp:!0,sni:s.searchParams.get("sni")??t,skipCertVerify:!0}}},exports.vmess={__proto__:null,parse:function(e){let r=JSON.parse($.decode(s.Buffer.from(e.slice(8),"base64"))),t=r.ps,p=r.path;return{raw:e,name:t,server:r.add,port:Number.parseInt(r.port,10),type:"vmess",username:r.id,tls:r.tls,vmessAead:"0"===r.aid,sni:r.sni,ws:"ws"===r.net,wsPath:"/"===p[0]?p:`/${p}`,wsHeaders:r.sni||r.host?`Host:${r.sni||r.host}`:r.add,skipCertVerify:!0,udp:!0}}};
1
+ var e=require("foxts/guard"),r=require("foxts/string-join"),s=require("node:buffer");const t=Number,o=e=>e.split(",").map(e=>e.trim());function p(e){let r=e.indexOf("=");return -1===r?["",""]:[e.slice(0,r).trim(),e.slice(r+1).trim()]}const n=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),a=new Set(["version","download-bandwidth","port-hopping-interval","udp-port"]),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"]),u=Symbol("unsupported");function l(e){return e.split(",").reduce((e,r)=>{let[s,t]=r.split(":");return e[s.trim()]=t.trim(),e},{})}function c(e){let r,s,[o,p]=e.split("://");if("ss"!==o)throw Error(`[ss.decodeOne] Unsupported type: ${o}`);let[n,a]=p.split("@");n.includes(":")?[r,s]=n.split(":"):[r,s]=atob(n).split(":");let[i,d]=a.split(":"),[u,l]=d.split("#"),[c,y]=u.split("/"),w=null;if(y)try{w=new URLSearchParams(y).get("plugin")}catch(r){let e=Error(`[ss.decodeOne] Invalid plugins: ${y}`);throw e.cause=r,e}let m=(w?.split(";")??[]).reduce((e,r)=>{let[s,t]=r.split("=");return e[s]=t,e},{});return{raw:e,type:"ss",name:decodeURIComponent(l),server:i,port:t(c),cipher:r,password:s,udp:!0,obfs:"obfs-local"in m&&"obfs"in m&&("http"===m.obfs||"tls"===m.obfs)?m.obfs:void 0,obfsHost:"obfs-host"in m?m["obfs-host"]:void 0}}function y(e){return atob(e).replaceAll("\r\n","\n").split("\n").filter(Boolean)}const w=new TextDecoder;exports.clash={__proto__:null,decode:function(e){if(!("type"in e)||"string"!=typeof e.type)throw TypeError("Missing or invalid type field");let r=JSON.stringify(e);switch(e.type){case"http":return{type:"http",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,underlyingProxy:e["dialer-proxy"],raw:r};case"ss":return{type:"ss",name:e.name,server:e.server,port:Number(e.port),cipher:e.cipher,password:e.password,udp:e.udp||!1,obfs:"obfs"===e.plugin?e["plugin-opts"].mode:void 0,underlyingProxy:e["dialer-proxy"],raw:r};case"socks5":return{type:"socks5",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,udp:e.udp||!1,underlyingProxy:e["dialer-proxy"],raw:r};case"trojan":return{type:"trojan",name:e.name,server:e.server,port:Number(e.port),password:e.password,sni:e.sni,skipCertVerify:e["skip-cert-verify"]||!1,udp:e.udp||!1,underlyingProxy:e["dialer-proxy"],raw:r};case"vmess":return{type:"vmess",name:e.name,server:e.server,port:Number(e.port),username:e.uuid,vmessAead:1===e.alterId||"1"===e.alterId,sni:e.servername,ws:"ws"===e.network,wsPath:e["ws-path"],wsHeaders:e["ws-headers"]?Object.entries(e["ws-headers"]).map(([e,r])=>`${e}:${r}`).join(", "):void 0,tls:e.tls||!1,udp:e.udp??!0,underlyingProxy:e["dialer-proxy"],raw:r,skipCertVerify:e["skip-cert-verify"]||!1};default:throw TypeError(`Unsupported type: ${e.type} (clash decode)`)}},encode:function(r){let s={tfo:r.tfo,"dialer-proxy":r.underlyingProxy};switch(r.type){case"ss":return{name:r.name,type:"ss",server:r.server,port:r.port,cipher:r.cipher,password:r.password,udp:r.udp,...r.obfs?{plugin:"obfs","plugin-opts":{mode:r.obfs,host:r.obfsHost,uri:r.obfsUri}}:{},...s};case"trojan":return{name:r.name,type:"trojan",server:r.server,port:r.port,password:r.password,sni:r.sni,"skip-cert-verify":r.skipCertVerify,udp:r.udp,...s};case"tuic":case"tuic-v5":return{name:r.name,type:"tuic",server:r.server,port:r.port,sni:r.sni,uuid:r.uuid,alpn:r.alpn.split(",").map(e=>e.trim()),..."tuic"===r.type?{token:r.token}:{password:r.password},"skip-cert-verify":r.skipCertVerify,udp:!0,version:"tuic"===r.type?4:"tuic-v5"===r.type?5:e.never(r),...s};case"socks5":return{name:r.name,type:"socks5",server:r.server,port:r.port,username:r.username,password:r.password,udp:r.udp,...s};case"http":return{name:r.name,type:"http",server:r.server,port:r.port,username:r.username,password:r.password,...s};case"vmess":return{alterId:r.vmessAead?0:void 0,tls:r.tls,udp:r.udp,uuid:r.username,name:r.name,servername:r.sni,"ws-path":r.wsPath,server:r.server,"ws-headers":r.wsHeaders?l(r.wsHeaders):void 0,cipher:"auto","ws-opts":{path:r.wsPath,headers:r.wsHeaders?l(r.wsHeaders):void 0},type:"vmess",port:r.port,network:r.ws?"ws":"tcp"};case"hysteria2":return{name:r.name,type:"hysteria2",server:r.server,port:r.port,ports:r.portHopping,password:r.password,down:r.downloadBandwidth+" Mbps","skip-cert-verify":r.skipCertVerify};default:throw TypeError(`Unsupported type: ${r.type} (clash encode)`)}}},exports.ss={__proto__:null,decodeBase64Multiline:y,decodeMultiline:function(e){return y(e).map(e=>c(e))},decodeOne:c},exports.surge={__proto__:null,decode:function(e){let[r,s]=p(e),[l,c,y,...w]=o(s),m=t(y),f=Object.fromEntries(w.map(e=>{let[r,s]=p(e);return n.has(r)?[r,"true"===s]:a.has(r)?[r,t(s)]:i.has(r)?[r,o(s)]:d.has(r)?'"'===s[0]&&s.endsWith('"')||"'"===s[0]&&s.endsWith("'")?[r,s.slice(1,-1)]:[r,s]:[r,u]})),v={raw:e,name:r,server:c,port:m,tfo:f.tfo,blockQuic:f["block-quic"],underlyingProxy:f["underlying-proxy"]},h={sni:f.sni,skipCertVerify:f["skip-cert-verify"]};switch(l){case"snell":return{type:"snell",psk:f.psk,version:f.version,reuse:f.reuse,...v};case"ss":return{type:"ss",cipher:f["encrypt-method"],password:f.password,udp:f["udp-relay"],obfs:f.obfs,obfsHost:f["obfs-host"],obfsUri:f["obfs-uri"],udpPort:f["udp-port"],...v};case"trojan":return{type:"trojan",password:f.password,udp:f["udp-relay"],...h,...v};case"tuic":return{type:"tuic",uuid:f.uuid,alpn:f.alpn,token:f.token,...h,...v};case"tuic-v5":return{type:"tuic-v5",uuid:f.uuid,alpn:f.alpn,password:f.password,...h,...v};case"socks5":return{type:"socks5",username:w[0],password:w[1],udp:f["udp-relay"],...v};case"http":return{type:"http",username:w[0],password:w[1],...v};case"vmess":return{type:"vmess",username:f.username,tls:f.tls,vmessAead:f["vmess-aead"],ws:f.ws,wsPath:f["ws-path"],wsHeaders:f["ws-headers"],udp:f["udp-relay"],...h,...v};case"hysteria2":return{type:"hysteria2",password:f.password,skipCertVerify:f["skip-cert-verify"],downloadBandwidth:f["download-bandwidth"],portHopping:f["port-hopping"],portHoppingInterval:f["port-hopping-interval"],...v};default:throw TypeError(`Unsupported type: ${l} (surge decode)`)}},encode:function(s){let t=[s.tfo&&"tfo=true",s.blockQuic&&`block-quic=${s.blockQuic}`,s.underlyingProxy&&`underlying-proxy=${s.underlyingProxy}`];switch(s.type){case"snell":return r.stringJoin([`${s.name} = snell, ${s.server}, ${s.port}, psk=${s.psk}, version=${s.version}, reuse=${s.reuse}`,...t],", ");case"ss":return r.stringJoin([`${s.name} = ss, ${s.server}, ${s.port}, encrypt-method=${s.cipher}, password=${s.password}`,s.udp&&"udp-relay=true",s.udpPort&&`udp-port=${s.udpPort}`,s.obfs&&`obfs=${s.obfs}`,s.obfsHost&&`obfs-host=${s.obfsHost}`,s.obfsUri&&`obfs-uri=${s.obfsUri}`,...t],", ");case"trojan":return r.stringJoin([`${s.name} = trojan, ${s.server}, ${s.port}, password=${s.password}`,s.sni&&`sni=${s.sni}`,s.skipCertVerify&&"skip-cert-verify=true",...t,s.udp&&"udp-relay=true"],", ");case"tuic":return r.stringJoin([`${s.name} = tuic, ${s.server}, ${s.port}, sni=${s.sni}, uuid=${s.uuid}, alpn=${s.alpn}, token=${s.token}`,...t],", ");case"socks5":return r.stringJoin([`${s.name} = socks5, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,s.udp&&"udp-relay=true",...t],", ");case"http":return r.stringJoin([`${s.name} = http, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,...t],", ");case"vmess":return r.stringJoin([`${s.name} = vmess, ${s.server}, ${s.port}`,`username=${s.username}`,`tls=${s.tls}`,`vmess-aead=${s.vmessAead}`,"ws=true",s.wsPath&&`ws-path=${"/"===s.wsPath[0]?s.wsPath:`/${s.wsPath}`}`,s.wsHeaders&&`ws-headers=${s.wsHeaders}`,`skip-cert-verify=${s.skipCertVerify}`,`tfo=${s.tfo}`,`udp-relay=${s.udp}`],", ");case"hysteria2":return r.stringJoin([`${s.name} = hysteria2, ${s.server}, ${s.port}`,`password=${s.password}`,`download-bandwidth=${s.downloadBandwidth}`,s.portHopping&&`port-hopping="${s.portHopping}"`,s.portHoppingInterval&&`port-hopping-interval=${s.portHoppingInterval}`,`skip-cert-verify=${s.skipCertVerify}`,...t],", ");case"tuic-v5":return r.stringJoin([`${s.name} = tuic-v5, ${s.server}, ${s.port}`,`password=${s.password}`,`uuid=${s.uuid}`,`alpn=${s.alpn}`,`skip-cert-verify=${s.skipCertVerify}`,`sni=${s.sni}`,...t],", ");default:e.never(s,"type (surge encode)")}}},exports.trojan={__proto__:null,parse:function(e){let r=new URL(e),s=r.username,t=r.hostname,o=Number.parseInt(r.port,10);if(Number.isNaN(o))throw TypeError("invalid port: "+r.port);return{raw:e,name:decodeURIComponent(r.hash.slice(1)),type:"trojan",server:t,port:o,password:s,udp:!0,sni:r.searchParams.get("sni")??t,skipCertVerify:!0}}},exports.vmess={__proto__:null,parse:function(e){let r=JSON.parse(w.decode(s.Buffer.from(e.slice(8),"base64"))),t=r.ps,o=r.path;return{raw:e,name:t,server:r.add,port:Number.parseInt(r.port,10),type:"vmess",username:r.id,tls:r.tls,vmessAead:"0"===r.aid,sni:r.sni,ws:"ws"===r.net,wsPath:"/"===o[0]?o:`/${o}`,wsHeaders:r.sni||r.host?`Host:${r.sni||r.host}`:r.add,skipCertVerify:!0,udp:!0}}};
@@ -7,6 +7,8 @@ interface SharedConfigBase {
7
7
  tfo?: boolean;
8
8
  /** block-quic */
9
9
  blockQuic?: string;
10
+ /** underlying-proxy */
11
+ underlyingProxy?: string;
10
12
  }
11
13
  interface TlsSharedConfig {
12
14
  /** sni */
@@ -54,14 +56,12 @@ interface TrojanBasicConfig extends SharedConfigBase, TlsSharedConfig {
54
56
  }
55
57
  interface TuicConfig extends SharedConfigBase, TlsSharedConfig {
56
58
  type: 'tuic';
57
- sni: string;
58
59
  uuid: string;
59
60
  alpn: string;
60
61
  token: string;
61
62
  }
62
63
  interface TuicV5Config extends SharedConfigBase, TlsSharedConfig {
63
64
  type: 'tuic-v5';
64
- sni: string;
65
65
  uuid: string;
66
66
  alpn: string;
67
67
  password: string;
@@ -108,6 +108,7 @@ declare namespace index$4 {
108
108
  declare function decode(config: Record<string, any>): SupportedConfig;
109
109
  declare function encode(config: SupportedConfig): {
110
110
  tfo: boolean | undefined;
111
+ 'dialer-proxy': string | undefined;
111
112
  plugin?: string | undefined;
112
113
  'plugin-opts'?: {
113
114
  mode: "http" | "tls";
@@ -134,6 +135,7 @@ declare function encode(config: SupportedConfig): {
134
135
  'skip-cert-verify'?: undefined;
135
136
  } | {
136
137
  tfo: boolean | undefined;
138
+ 'dialer-proxy': string | undefined;
137
139
  name: string;
138
140
  type: string;
139
141
  server: string;
@@ -155,6 +157,7 @@ declare function encode(config: SupportedConfig): {
155
157
  down?: undefined;
156
158
  } | {
157
159
  tfo: boolean | undefined;
160
+ 'dialer-proxy': string | undefined;
158
161
  'skip-cert-verify': boolean;
159
162
  udp: boolean;
160
163
  version: number;
@@ -163,7 +166,7 @@ declare function encode(config: SupportedConfig): {
163
166
  type: string;
164
167
  server: string;
165
168
  port: number;
166
- sni: string;
169
+ sni: string | undefined;
167
170
  uuid: string;
168
171
  alpn: string[];
169
172
  alterId?: undefined;
@@ -179,6 +182,7 @@ declare function encode(config: SupportedConfig): {
179
182
  down?: undefined;
180
183
  } | {
181
184
  tfo: boolean | undefined;
185
+ 'dialer-proxy': string | undefined;
182
186
  'skip-cert-verify': boolean;
183
187
  udp: boolean;
184
188
  version: number;
@@ -187,7 +191,7 @@ declare function encode(config: SupportedConfig): {
187
191
  type: string;
188
192
  server: string;
189
193
  port: number;
190
- sni: string;
194
+ sni: string | undefined;
191
195
  uuid: string;
192
196
  alpn: string[];
193
197
  alterId?: undefined;
@@ -202,6 +206,7 @@ declare function encode(config: SupportedConfig): {
202
206
  down?: undefined;
203
207
  } | {
204
208
  tfo: boolean | undefined;
209
+ 'dialer-proxy': string | undefined;
205
210
  name: string;
206
211
  type: string;
207
212
  server: string;
@@ -223,6 +228,7 @@ declare function encode(config: SupportedConfig): {
223
228
  'skip-cert-verify'?: undefined;
224
229
  } | {
225
230
  tfo: boolean | undefined;
231
+ 'dialer-proxy': string | undefined;
226
232
  name: string;
227
233
  type: string;
228
234
  server: string;
@@ -327,4 +333,4 @@ declare namespace index {
327
333
  }
328
334
 
329
335
  export { index$3 as clash, index$2 as ss, index$4 as surge, index$1 as trojan, index as vmess };
330
- export type { HttpProxyConfig, Hysteria2Config, ShadowSocksConfig, SharedConfigBase, SnellConfig, Socks5Config, SupportedConfig, TrojanBasicConfig, TrojanConfig, TuicConfig, TuicV5Config, VmessConfig };
336
+ export type { HttpProxyConfig, Hysteria2Config, ShadowSocksConfig, SharedConfigBase, SnellConfig, Socks5Config, SupportedConfig, TlsSharedConfig, TrojanBasicConfig, TrojanConfig, TuicConfig, TuicV5Config, VmessConfig };
package/dist/es/index.mjs CHANGED
@@ -1 +1 @@
1
- import{never as e}from"foxts/guard";import{Buffer as s}from"node:buffer";let r=e=>"true"===e,t=Number,p=e=>e.split(",").map(e=>e.trim());function o(e){let s=e.indexOf("=");return -1===s?["",""]:[e.slice(0,s).trim(),e.slice(s+1).trim()]}let n=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),a=e=>n.has(e),i=new Set(["version","download-bandwidth","port-hopping-interval","udp-port"]),d=e=>i.has(e),u=new Set([]),c=e=>u.has(e),l=new Set(["username","password","sni","encrypt-method","psk","obfs","obfs-host","uuid","alpn","block-quic","ws-path","ws-headers","port-hopping","token"]),w=e=>l.has(e),m=Symbol("unsupported"),f=e=>e.filter(Boolean).join(", ");var v={__proto__:null,decode:function(e){let[s,n]=o(e),[i,u,l,...f]=p(n),v=t(l),y=Object.fromEntries(f.map(e=>{let[s,n]=o(e);return a(s)?[s,r(n)]:d(s)?[s,t(n)]:c(s)?[s,p(n)]:w(s)?'"'===n[0]&&n.endsWith('"')||"'"===n[0]&&n.endsWith("'")?[s,n.slice(1,-1)]:[s,n]:[s,m]})),h={raw:e,name:s,server:u,port:v,tfo:y.tfo,blockQuic:y["block-quic"]};switch(i){case"snell":return{type:"snell",psk:y.psk,version:y.version,reuse:y.reuse,...h};case"ss":return{type:"ss",cipher:y["encrypt-method"],password:y.password,udp:y["udp-relay"],obfs:y.obfs,obfsHost:y["obfs-host"],obfsUri:y["obfs-uri"],udpPort:y["udp-port"],...h};case"trojan":return{type:"trojan",password:y.password,sni:y.sni,skipCertVerify:y["skip-cert-verify"],udp:y["udp-relay"],...h};case"tuic":return{type:"tuic",sni:y.sni,uuid:y.uuid,alpn:y.alpn,token:y.token,skipCertVerify:y["skip-cert-verify"],...h};case"tuic-v5":return{type:"tuic-v5",uuid:y.uuid,alpn:y.alpn,password:y.password,sni:y.sni,skipCertVerify:y["skip-cert-verify"],...h};case"socks5":return{type:"socks5",username:f[0],password:f[1],udp:y["udp-relay"],...h};case"http":return{type:"http",username:f[0],password:f[1],...h};case"vmess":return{type:"vmess",username:y.username,tls:y.tls,vmessAead:y["vmess-aead"],ws:y.ws,wsPath:y["ws-path"],wsHeaders:y["ws-headers"],skipCertVerify:y["skip-cert-verify"],udp:y["udp-relay"],sni:y.sni,...h};case"hysteria2":return{type:"hysteria2",password:y.password,skipCertVerify:y["skip-cert-verify"],downloadBandwidth:y["download-bandwidth"],portHopping:y["port-hopping"],portHoppingInterval:y["port-hopping-interval"],...h};default:throw TypeError(`Unsupported type: ${i} (surge decode)`)}},encode:function(s){let r=[s.tfo&&"tfo=true",s.blockQuic&&`block-quic=${s.blockQuic}`];switch(s.type){case"snell":return f([`${s.name} = snell, ${s.server}, ${s.port}, psk=${s.psk}, version=${s.version}, reuse=${s.reuse}`,...r]);case"ss":return f([`${s.name} = ss, ${s.server}, ${s.port}, encrypt-method=${s.cipher}, password=${s.password}`,s.udp&&"udp-relay=true",s.udpPort&&`udp-port=${s.udpPort}`,s.obfs&&`obfs=${s.obfs}`,s.obfsHost&&`obfs-host=${s.obfsHost}`,s.obfsUri&&`obfs-uri=${s.obfsUri}`,...r]);case"trojan":return f([`${s.name} = trojan, ${s.server}, ${s.port}, password=${s.password}`,s.sni&&`sni=${s.sni}`,s.skipCertVerify&&"skip-cert-verify=true",...r,s.udp&&"udp-relay=true"]);case"tuic":return f([`${s.name} = tuic, ${s.server}, ${s.port}, sni=${s.sni}, uuid=${s.uuid}, alpn=${s.alpn}, token=${s.token}`,...r]);case"socks5":return f([`${s.name} = socks5, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,s.udp&&"udp-relay=true",...r]);case"http":return f([`${s.name} = http, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,...r]);case"vmess":return f([`${s.name} = vmess, ${s.server}, ${s.port}`,`username=${s.username}`,`tls=${s.tls}`,`vmess-aead=${s.vmessAead}`,"ws=true",s.wsPath&&`ws-path=${"/"===s.wsPath[0]?s.wsPath:`/${s.wsPath}`}`,s.wsHeaders&&`ws-headers=${s.wsHeaders}`,`skip-cert-verify=${s.skipCertVerify}`,`tfo=${s.tfo}`,`udp-relay=${s.udp}`]);case"hysteria2":return f([`${s.name} = hysteria2, ${s.server}, ${s.port}`,`password=${s.password}`,`download-bandwidth=${s.downloadBandwidth}`,s.portHopping&&`port-hopping="${s.portHopping}"`,s.portHoppingInterval&&`port-hopping-interval=${s.portHoppingInterval}`,`skip-cert-verify=${s.skipCertVerify}`,...r]);case"tuic-v5":return f([`${s.name} = tuic-v5, ${s.server}, ${s.port}`,`password=${s.password}`,`uuid=${s.uuid}`,`alpn=${s.alpn}`,`skip-cert-verify=${s.skipCertVerify}`,`sni=${s.sni}`,...r]);default:e(s,"type (clash encode)")}}};function y(e){return e.split(",").reduce((e,s)=>{let[r,t]=s.split(":");return e[r.trim()]=t.trim(),e},{})}var h={__proto__:null,decode:function(e){if(!("type"in e)||"string"!=typeof e.type)throw TypeError("Missing or invalid type field");let s=JSON.stringify(e);switch(e.type){case"http":return{type:"http",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,raw:s};case"ss":return{type:"ss",name:e.name,server:e.server,port:Number(e.port),cipher:e.cipher,password:e.password,udp:e.udp||!1,obfs:"obfs"===e.plugin?e["plugin-opts"].mode:void 0,raw:s};case"socks5":return{type:"socks5",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,udp:e.udp||!1,raw:s};case"trojan":return{type:"trojan",name:e.name,server:e.server,port:Number(e.port),password:e.password,sni:e.sni,skipCertVerify:e["skip-cert-verify"]||!1,udp:e.udp||!1,raw:s};case"vmess":return{type:"vmess",name:e.name,server:e.server,port:Number(e.port),username:e.uuid,vmessAead:1===e.alterId||"1"===e.alterId,sni:e.servername,ws:"ws"===e.network,wsPath:e["ws-path"],wsHeaders:e["ws-headers"]?Object.entries(e["ws-headers"]).map(([e,s])=>`${e}:${s}`).join(", "):void 0,tls:e.tls||!1,udp:e.udp??!0,raw:s,skipCertVerify:e["skip-cert-verify"]||!1};default:throw TypeError(`Unsupported type: ${e.type} (clash decode)`)}},encode:function(s){let r={tfo:s.tfo};switch(s.type){case"ss":return{name:s.name,type:"ss",server:s.server,port:s.port,cipher:s.cipher,password:s.password,udp:s.udp,...s.obfs?{plugin:"obfs","plugin-opts":{mode:s.obfs,host:s.obfsHost,uri:s.obfsUri}}:{},...r};case"trojan":return{name:s.name,type:"trojan",server:s.server,port:s.port,password:s.password,sni:s.sni,"skip-cert-verify":s.skipCertVerify,udp:s.udp,...r};case"tuic":case"tuic-v5":return{name:s.name,type:"tuic",server:s.server,port:s.port,sni:s.sni,uuid:s.uuid,alpn:s.alpn.split(",").map(e=>e.trim()),..."tuic"===s.type?{token:s.token}:{password:s.password},"skip-cert-verify":s.skipCertVerify,udp:!0,version:"tuic"===s.type?4:"tuic-v5"===s.type?5:e(s),...r};case"socks5":return{name:s.name,type:"socks5",server:s.server,port:s.port,username:s.username,password:s.password,udp:s.udp,...r};case"http":return{name:s.name,type:"http",server:s.server,port:s.port,username:s.username,password:s.password,...r};case"vmess":return{alterId:s.vmessAead?0:void 0,tls:s.tls,udp:s.udp,uuid:s.username,name:s.name,servername:s.sni,"ws-path":s.wsPath,server:s.server,"ws-headers":s.wsHeaders?y(s.wsHeaders):void 0,cipher:"auto","ws-opts":{path:s.wsPath,headers:s.wsHeaders?y(s.wsHeaders):void 0},type:"vmess",port:s.port,network:s.ws?"ws":"tcp"};case"hysteria2":return{name:s.name,type:"hysteria2",server:s.server,port:s.port,ports:s.portHopping,password:s.password,down:s.downloadBandwidth+" Mbps","skip-cert-verify":s.skipCertVerify};default:throw TypeError(`Unsupported type: ${s.type} (clash encode)`)}}};function $(e){let s,r,[p,o]=e.split("://");if("ss"!==p)throw Error(`[ss.decodeOne] Unsupported type: ${p}`);let[n,a]=o.split("@");n.includes(":")?[s,r]=n.split(":"):[s,r]=atob(n).split(":");let[i,d]=a.split(":"),[u,c]=d.split("#"),[l,w]=u.split("/"),m=null;if(w)try{m=new URLSearchParams(w).get("plugin")}catch(s){let e=Error(`[ss.decodeOne] Invalid plugins: ${w}`);throw e.cause=s,e}let f=(m?.split(";")??[]).reduce((e,s)=>{let[r,t]=s.split("=");return e[r]=t,e},{});return{raw:e,type:"ss",name:decodeURIComponent(c),server:i,port:t(l),cipher:s,password:r,udp:!0,obfs:"obfs-local"in f&&"obfs"in f&&("http"===f.obfs||"tls"===f.obfs)?f.obfs:void 0,obfsHost:"obfs-host"in f?f["obfs-host"]:void 0}}function b(e){return atob(e).replaceAll("\r\n","\n").split("\n").filter(Boolean)}var k={__proto__:null,decodeBase64Multiline:b,decodeMultiline:function(e){return b(e).map(e=>$(e))},decodeOne:$},g={__proto__:null,parse:function(e){let s=new URL(e),r=s.username,t=s.hostname,p=Number.parseInt(s.port,10);if(Number.isNaN(p))throw TypeError("invalid port: "+s.port);return{raw:e,name:decodeURIComponent(s.hash.slice(1)),type:"trojan",server:t,port:p,password:r,udp:!0,sni:s.searchParams.get("sni")??t,skipCertVerify:!0}}};let H=new TextDecoder;var _={__proto__:null,parse:function(e){let r=JSON.parse(H.decode(s.from(e.slice(8),"base64"))),t=r.ps,p=r.path;return{raw:e,name:t,server:r.add,port:Number.parseInt(r.port,10),type:"vmess",username:r.id,tls:r.tls,vmessAead:"0"===r.aid,sni:r.sni,ws:"ws"===r.net,wsPath:"/"===p[0]?p:`/${p}`,wsHeaders:r.sni||r.host?`Host:${r.sni||r.host}`:r.add,skipCertVerify:!0,udp:!0}}};export{h as clash,k as ss,v as surge,g as trojan,_ as vmess};
1
+ import{never as e}from"foxts/guard";import{stringJoin as r}from"foxts/string-join";import{Buffer as s}from"node:buffer";let t=Number,p=e=>e.split(",").map(e=>e.trim());function o(e){let r=e.indexOf("=");return -1===r?["",""]:[e.slice(0,r).trim(),e.slice(r+1).trim()]}let n=new Set(["udp-relay","tfo","reuse","skip-cert-verify","tls","vmess-aead","ws"]),a=new Set(["version","download-bandwidth","port-hopping-interval","udp-port"]),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"]),u=Symbol("unsupported");var l={__proto__:null,decode:function(e){let[r,s]=o(e),[l,c,y,...w]=p(s),m=t(y),f=Object.fromEntries(w.map(e=>{let[r,s]=o(e);return n.has(r)?[r,"true"===s]:a.has(r)?[r,t(s)]:i.has(r)?[r,p(s)]:d.has(r)?'"'===s[0]&&s.endsWith('"')||"'"===s[0]&&s.endsWith("'")?[r,s.slice(1,-1)]:[r,s]:[r,u]})),v={raw:e,name:r,server:c,port:m,tfo:f.tfo,blockQuic:f["block-quic"],underlyingProxy:f["underlying-proxy"]},h={sni:f.sni,skipCertVerify:f["skip-cert-verify"]};switch(l){case"snell":return{type:"snell",psk:f.psk,version:f.version,reuse:f.reuse,...v};case"ss":return{type:"ss",cipher:f["encrypt-method"],password:f.password,udp:f["udp-relay"],obfs:f.obfs,obfsHost:f["obfs-host"],obfsUri:f["obfs-uri"],udpPort:f["udp-port"],...v};case"trojan":return{type:"trojan",password:f.password,udp:f["udp-relay"],...h,...v};case"tuic":return{type:"tuic",uuid:f.uuid,alpn:f.alpn,token:f.token,...h,...v};case"tuic-v5":return{type:"tuic-v5",uuid:f.uuid,alpn:f.alpn,password:f.password,...h,...v};case"socks5":return{type:"socks5",username:w[0],password:w[1],udp:f["udp-relay"],...v};case"http":return{type:"http",username:w[0],password:w[1],...v};case"vmess":return{type:"vmess",username:f.username,tls:f.tls,vmessAead:f["vmess-aead"],ws:f.ws,wsPath:f["ws-path"],wsHeaders:f["ws-headers"],udp:f["udp-relay"],...h,...v};case"hysteria2":return{type:"hysteria2",password:f.password,skipCertVerify:f["skip-cert-verify"],downloadBandwidth:f["download-bandwidth"],portHopping:f["port-hopping"],portHoppingInterval:f["port-hopping-interval"],...v};default:throw TypeError(`Unsupported type: ${l} (surge decode)`)}},encode:function(s){let t=[s.tfo&&"tfo=true",s.blockQuic&&`block-quic=${s.blockQuic}`,s.underlyingProxy&&`underlying-proxy=${s.underlyingProxy}`];switch(s.type){case"snell":return r([`${s.name} = snell, ${s.server}, ${s.port}, psk=${s.psk}, version=${s.version}, reuse=${s.reuse}`,...t],", ");case"ss":return r([`${s.name} = ss, ${s.server}, ${s.port}, encrypt-method=${s.cipher}, password=${s.password}`,s.udp&&"udp-relay=true",s.udpPort&&`udp-port=${s.udpPort}`,s.obfs&&`obfs=${s.obfs}`,s.obfsHost&&`obfs-host=${s.obfsHost}`,s.obfsUri&&`obfs-uri=${s.obfsUri}`,...t],", ");case"trojan":return r([`${s.name} = trojan, ${s.server}, ${s.port}, password=${s.password}`,s.sni&&`sni=${s.sni}`,s.skipCertVerify&&"skip-cert-verify=true",...t,s.udp&&"udp-relay=true"],", ");case"tuic":return r([`${s.name} = tuic, ${s.server}, ${s.port}, sni=${s.sni}, uuid=${s.uuid}, alpn=${s.alpn}, token=${s.token}`,...t],", ");case"socks5":return r([`${s.name} = socks5, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,s.udp&&"udp-relay=true",...t],", ");case"http":return r([`${s.name} = http, ${s.server}, ${s.port}, ${s.username}, ${s.password}`,...t],", ");case"vmess":return r([`${s.name} = vmess, ${s.server}, ${s.port}`,`username=${s.username}`,`tls=${s.tls}`,`vmess-aead=${s.vmessAead}`,"ws=true",s.wsPath&&`ws-path=${"/"===s.wsPath[0]?s.wsPath:`/${s.wsPath}`}`,s.wsHeaders&&`ws-headers=${s.wsHeaders}`,`skip-cert-verify=${s.skipCertVerify}`,`tfo=${s.tfo}`,`udp-relay=${s.udp}`],", ");case"hysteria2":return r([`${s.name} = hysteria2, ${s.server}, ${s.port}`,`password=${s.password}`,`download-bandwidth=${s.downloadBandwidth}`,s.portHopping&&`port-hopping="${s.portHopping}"`,s.portHoppingInterval&&`port-hopping-interval=${s.portHoppingInterval}`,`skip-cert-verify=${s.skipCertVerify}`,...t],", ");case"tuic-v5":return r([`${s.name} = tuic-v5, ${s.server}, ${s.port}`,`password=${s.password}`,`uuid=${s.uuid}`,`alpn=${s.alpn}`,`skip-cert-verify=${s.skipCertVerify}`,`sni=${s.sni}`,...t],", ");default:e(s,"type (surge encode)")}}};function c(e){return e.split(",").reduce((e,r)=>{let[s,t]=r.split(":");return e[s.trim()]=t.trim(),e},{})}var y={__proto__:null,decode:function(e){if(!("type"in e)||"string"!=typeof e.type)throw TypeError("Missing or invalid type field");let r=JSON.stringify(e);switch(e.type){case"http":return{type:"http",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,underlyingProxy:e["dialer-proxy"],raw:r};case"ss":return{type:"ss",name:e.name,server:e.server,port:Number(e.port),cipher:e.cipher,password:e.password,udp:e.udp||!1,obfs:"obfs"===e.plugin?e["plugin-opts"].mode:void 0,underlyingProxy:e["dialer-proxy"],raw:r};case"socks5":return{type:"socks5",name:e.name,server:e.server,port:Number(e.port),username:e.username,password:e.password,udp:e.udp||!1,underlyingProxy:e["dialer-proxy"],raw:r};case"trojan":return{type:"trojan",name:e.name,server:e.server,port:Number(e.port),password:e.password,sni:e.sni,skipCertVerify:e["skip-cert-verify"]||!1,udp:e.udp||!1,underlyingProxy:e["dialer-proxy"],raw:r};case"vmess":return{type:"vmess",name:e.name,server:e.server,port:Number(e.port),username:e.uuid,vmessAead:1===e.alterId||"1"===e.alterId,sni:e.servername,ws:"ws"===e.network,wsPath:e["ws-path"],wsHeaders:e["ws-headers"]?Object.entries(e["ws-headers"]).map(([e,r])=>`${e}:${r}`).join(", "):void 0,tls:e.tls||!1,udp:e.udp??!0,underlyingProxy:e["dialer-proxy"],raw:r,skipCertVerify:e["skip-cert-verify"]||!1};default:throw TypeError(`Unsupported type: ${e.type} (clash decode)`)}},encode:function(r){let s={tfo:r.tfo,"dialer-proxy":r.underlyingProxy};switch(r.type){case"ss":return{name:r.name,type:"ss",server:r.server,port:r.port,cipher:r.cipher,password:r.password,udp:r.udp,...r.obfs?{plugin:"obfs","plugin-opts":{mode:r.obfs,host:r.obfsHost,uri:r.obfsUri}}:{},...s};case"trojan":return{name:r.name,type:"trojan",server:r.server,port:r.port,password:r.password,sni:r.sni,"skip-cert-verify":r.skipCertVerify,udp:r.udp,...s};case"tuic":case"tuic-v5":return{name:r.name,type:"tuic",server:r.server,port:r.port,sni:r.sni,uuid:r.uuid,alpn:r.alpn.split(",").map(e=>e.trim()),..."tuic"===r.type?{token:r.token}:{password:r.password},"skip-cert-verify":r.skipCertVerify,udp:!0,version:"tuic"===r.type?4:"tuic-v5"===r.type?5:e(r),...s};case"socks5":return{name:r.name,type:"socks5",server:r.server,port:r.port,username:r.username,password:r.password,udp:r.udp,...s};case"http":return{name:r.name,type:"http",server:r.server,port:r.port,username:r.username,password:r.password,...s};case"vmess":return{alterId:r.vmessAead?0:void 0,tls:r.tls,udp:r.udp,uuid:r.username,name:r.name,servername:r.sni,"ws-path":r.wsPath,server:r.server,"ws-headers":r.wsHeaders?c(r.wsHeaders):void 0,cipher:"auto","ws-opts":{path:r.wsPath,headers:r.wsHeaders?c(r.wsHeaders):void 0},type:"vmess",port:r.port,network:r.ws?"ws":"tcp"};case"hysteria2":return{name:r.name,type:"hysteria2",server:r.server,port:r.port,ports:r.portHopping,password:r.password,down:r.downloadBandwidth+" Mbps","skip-cert-verify":r.skipCertVerify};default:throw TypeError(`Unsupported type: ${r.type} (clash encode)`)}}};function w(e){let r,s,[p,o]=e.split("://");if("ss"!==p)throw Error(`[ss.decodeOne] Unsupported type: ${p}`);let[n,a]=o.split("@");n.includes(":")?[r,s]=n.split(":"):[r,s]=atob(n).split(":");let[i,d]=a.split(":"),[u,l]=d.split("#"),[c,y]=u.split("/"),w=null;if(y)try{w=new URLSearchParams(y).get("plugin")}catch(r){let e=Error(`[ss.decodeOne] Invalid plugins: ${y}`);throw e.cause=r,e}let m=(w?.split(";")??[]).reduce((e,r)=>{let[s,t]=r.split("=");return e[s]=t,e},{});return{raw:e,type:"ss",name:decodeURIComponent(l),server:i,port:t(c),cipher:r,password:s,udp:!0,obfs:"obfs-local"in m&&"obfs"in m&&("http"===m.obfs||"tls"===m.obfs)?m.obfs:void 0,obfsHost:"obfs-host"in m?m["obfs-host"]:void 0}}function m(e){return atob(e).replaceAll("\r\n","\n").split("\n").filter(Boolean)}var f={__proto__:null,decodeBase64Multiline:m,decodeMultiline:function(e){return m(e).map(e=>w(e))},decodeOne:w},v={__proto__:null,parse:function(e){let r=new URL(e),s=r.username,t=r.hostname,p=Number.parseInt(r.port,10);if(Number.isNaN(p))throw TypeError("invalid port: "+r.port);return{raw:e,name:decodeURIComponent(r.hash.slice(1)),type:"trojan",server:t,port:p,password:s,udp:!0,sni:r.searchParams.get("sni")??t,skipCertVerify:!0}}};let h=new TextDecoder;var $={__proto__:null,parse:function(e){let r=JSON.parse(h.decode(s.from(e.slice(8),"base64"))),t=r.ps,p=r.path;return{raw:e,name:t,server:r.add,port:Number.parseInt(r.port,10),type:"vmess",username:r.id,tls:r.tls,vmessAead:"0"===r.aid,sni:r.sni,ws:"ws"===r.net,wsPath:"/"===p[0]?p:`/${p}`,wsHeaders:r.sni||r.host?`Host:${r.sni||r.host}`:r.add,skipCertVerify:!0,udp:!0}}};export{y as clash,f as ss,l as surge,v as trojan,$ as vmess};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodelistparser",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Surge / Mihomo (Clash.Meta) nodelist / proxy provider parser and generator.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,28 +34,28 @@
34
34
  "author": "Sukka <https://skk.moe>",
35
35
  "license": "MIT",
36
36
  "dependencies": {
37
- "foxts": "^3.3.1"
37
+ "foxts": "^3.10.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@eslint-sukka/node": "^6.20.0",
40
+ "@eslint-sukka/node": "^6.22.1",
41
41
  "@swc-node/register": "^1.10.10",
42
- "@swc/core": "^1.11.24",
42
+ "@swc/core": "^1.13.2",
43
43
  "@types/mocha": "^10.0.10",
44
- "@types/node": "^22.15.18",
45
- "bumpp": "^10.1.1",
46
- "bunchee": "^6.5.2",
47
- "eslint": "^9.27.0",
48
- "eslint-config-sukka": "^6.20.0",
49
- "eslint-formatter-sukka": "^6.20.0",
50
- "expect": "^29.7.0",
51
- "mocha": "^11.3.0",
44
+ "@types/node": "^22.16.5",
45
+ "bumpp": "^10.2.0",
46
+ "bunchee": "^6.5.4",
47
+ "eslint": "^9.32.0",
48
+ "eslint-config-sukka": "^6.22.1",
49
+ "eslint-formatter-sukka": "^6.22.1",
50
+ "expect": "^30.0.5",
51
+ "mocha": "^11.7.1",
52
52
  "typescript": "^5.8.3"
53
53
  },
54
54
  "scripts": {
55
55
  "lint": "eslint --format=sukka .",
56
56
  "build": "bunchee --minify --no-sourcemap",
57
57
  "test": "mocha --require @swc-node/register src/*.test.ts src/**/*.test.ts",
58
- "prerelease": "pnpm run lint && pnpm run build",
58
+ "prerelease": "pnpm run lint && pnpm run test && pnpm run build",
59
59
  "release": "bumpp -r --all --commit \"release: %s\" --tag \"%s\""
60
60
  }
61
61
  }