nodelistparser 0.1.4 → 0.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.
@@ -92,11 +92,11 @@ type SupportedConfig = HttpProxyConfig | SnellConfig | TrojanConfig | ShadowSock
92
92
  declare function decode$1(raw: string): SupportedConfig;
93
93
  declare function encode$1(config: SupportedConfig): string;
94
94
 
95
- declare namespace index$2 {
95
+ declare namespace index$3 {
96
96
  export { decode$1 as decode, encode$1 as encode };
97
97
  }
98
98
 
99
- declare function decode(config: any): SupportedConfig;
99
+ declare function decode(config: Record<string, any>): SupportedConfig;
100
100
  declare function encode(config: SupportedConfig): {
101
101
  tfo: boolean | undefined;
102
102
  plugin?: string | undefined;
@@ -253,21 +253,28 @@ declare function encode(config: SupportedConfig): {
253
253
  network?: undefined;
254
254
  };
255
255
 
256
- declare const index$1_decode: typeof decode;
257
- declare const index$1_encode: typeof encode;
258
- declare namespace index$1 {
259
- export { index$1_decode as decode, index$1_encode as encode };
256
+ declare const index$2_decode: typeof decode;
257
+ declare const index$2_encode: typeof encode;
258
+ declare namespace index$2 {
259
+ export { index$2_decode as decode, index$2_encode as encode };
260
260
  }
261
261
 
262
262
  declare function decodeOne(sip002: string): ShadowSocksConfig;
263
263
  declare function decodeBase64Multiline(text: string): string[];
264
264
  declare function decodeMultiline(text: string): ShadowSocksConfig[];
265
265
 
266
- declare const index_decodeBase64Multiline: typeof decodeBase64Multiline;
267
- declare const index_decodeMultiline: typeof decodeMultiline;
268
- declare const index_decodeOne: typeof decodeOne;
266
+ declare const index$1_decodeBase64Multiline: typeof decodeBase64Multiline;
267
+ declare const index$1_decodeMultiline: typeof decodeMultiline;
268
+ declare const index$1_decodeOne: typeof decodeOne;
269
+ declare namespace index$1 {
270
+ export { index$1_decodeBase64Multiline as decodeBase64Multiline, index$1_decodeMultiline as decodeMultiline, index$1_decodeOne as decodeOne };
271
+ }
272
+
273
+ declare function parse(line: string): TrojanConfig;
274
+
275
+ declare const index_parse: typeof parse;
269
276
  declare namespace index {
270
- export { index_decodeBase64Multiline as decodeBase64Multiline, index_decodeMultiline as decodeMultiline, index_decodeOne as decodeOne };
277
+ export { index_parse as parse };
271
278
  }
272
279
 
273
- export { type HttpProxyConfig, type Hysteria2Config, type ShadowSocksConfig, type SharedConfigBase, type SnellConfig, type Socks5Config, type SupportedConfig, type TrojanBasicConfig, type TrojanConfig, type TuicConfig, type VmessConfig, index$1 as clash, index as ss, index$2 as surge };
280
+ export { type HttpProxyConfig, type Hysteria2Config, type ShadowSocksConfig, type SharedConfigBase, type SnellConfig, type Socks5Config, type SupportedConfig, type TrojanBasicConfig, type TrojanConfig, type TuicConfig, type VmessConfig, index$2 as clash, index$1 as ss, index$3 as surge, index as trojan };
package/dist/cjs/index.js CHANGED
@@ -275,7 +275,7 @@ function encode$1(config) {
275
275
  }
276
276
  }
277
277
 
278
- var index$2 = {
278
+ var index$3 = {
279
279
  __proto__: null,
280
280
  decode: decode$1,
281
281
  encode: encode$1
@@ -467,7 +467,7 @@ function parseStringToObject(input) {
467
467
  }, {});
468
468
  }
469
469
 
470
- var index$1 = {
470
+ var index$2 = {
471
471
  __proto__: null,
472
472
  decode: decode,
473
473
  encode: encode
@@ -488,8 +488,22 @@ function decodeOne(sip002) {
488
488
  }
489
489
  const [serverName, _1] = server.split(':');
490
490
  const [_2, encodedName] = _1.split('#');
491
- const [port, _plugins] = _2.split('/');
492
- // TODO: implement plugin parsing
491
+ const [port, pluginsStr] = _2.split('/');
492
+ let plugin = null;
493
+ if (pluginsStr) {
494
+ try {
495
+ plugin = new URLSearchParams(pluginsStr).get('plugin');
496
+ } catch (e) {
497
+ const err = new Error(`[ss.decodeOne] Invalid plugins: ${pluginsStr}`);
498
+ err.cause = e;
499
+ throw err;
500
+ }
501
+ }
502
+ const pluginArgs = (plugin?.split(';') ?? []).reduce((acc, cur)=>{
503
+ const [key, value] = cur.split('=');
504
+ acc[key] = value;
505
+ return acc;
506
+ }, {});
493
507
  return {
494
508
  raw: sip002,
495
509
  type: 'ss',
@@ -498,7 +512,9 @@ function decodeOne(sip002) {
498
512
  port: number(port),
499
513
  cipher,
500
514
  password,
501
- udp: true
515
+ udp: true,
516
+ obfs: 'obfs-local' in pluginArgs && 'obfs' in pluginArgs && (pluginArgs.obfs === 'http' || pluginArgs.obfs === 'tls') ? pluginArgs.obfs : undefined,
517
+ obfsHost: 'obfs-host' in pluginArgs ? pluginArgs['obfs-host'] : undefined
502
518
  };
503
519
  }
504
520
  function decodeBase64Multiline(text) {
@@ -508,13 +524,42 @@ function decodeMultiline(text) {
508
524
  return decodeBase64Multiline(text).map((line)=>decodeOne(line));
509
525
  }
510
526
 
511
- var index = {
527
+ var index$1 = {
512
528
  __proto__: null,
513
529
  decodeBase64Multiline: decodeBase64Multiline,
514
530
  decodeMultiline: decodeMultiline,
515
531
  decodeOne: decodeOne
516
532
  };
517
533
 
518
- exports.clash = index$1;
519
- exports.ss = index;
520
- exports.surge = index$2;
534
+ function parse(line) {
535
+ const url = new URL(line);
536
+ // trojan://password@remote_host:remote_port
537
+ const password = url.username;
538
+ const server = url.hostname;
539
+ const port = Number.parseInt(url.port, 10);
540
+ if (Number.isNaN(port)) {
541
+ throw new TypeError('invalid port: ' + url.port);
542
+ }
543
+ const name = decodeURIComponent(url.hash.slice(1));
544
+ return {
545
+ raw: line,
546
+ name,
547
+ type: 'trojan',
548
+ server,
549
+ port,
550
+ password,
551
+ udp: true,
552
+ sni: url.searchParams.get('sni') ?? server,
553
+ skipCertVerify: true
554
+ };
555
+ }
556
+
557
+ var index = {
558
+ __proto__: null,
559
+ parse: parse
560
+ };
561
+
562
+ exports.clash = index$2;
563
+ exports.ss = index$1;
564
+ exports.surge = index$3;
565
+ exports.trojan = index;
@@ -92,11 +92,11 @@ type SupportedConfig = HttpProxyConfig | SnellConfig | TrojanConfig | ShadowSock
92
92
  declare function decode$1(raw: string): SupportedConfig;
93
93
  declare function encode$1(config: SupportedConfig): string;
94
94
 
95
- declare namespace index$2 {
95
+ declare namespace index$3 {
96
96
  export { decode$1 as decode, encode$1 as encode };
97
97
  }
98
98
 
99
- declare function decode(config: any): SupportedConfig;
99
+ declare function decode(config: Record<string, any>): SupportedConfig;
100
100
  declare function encode(config: SupportedConfig): {
101
101
  tfo: boolean | undefined;
102
102
  plugin?: string | undefined;
@@ -253,21 +253,28 @@ declare function encode(config: SupportedConfig): {
253
253
  network?: undefined;
254
254
  };
255
255
 
256
- declare const index$1_decode: typeof decode;
257
- declare const index$1_encode: typeof encode;
258
- declare namespace index$1 {
259
- export { index$1_decode as decode, index$1_encode as encode };
256
+ declare const index$2_decode: typeof decode;
257
+ declare const index$2_encode: typeof encode;
258
+ declare namespace index$2 {
259
+ export { index$2_decode as decode, index$2_encode as encode };
260
260
  }
261
261
 
262
262
  declare function decodeOne(sip002: string): ShadowSocksConfig;
263
263
  declare function decodeBase64Multiline(text: string): string[];
264
264
  declare function decodeMultiline(text: string): ShadowSocksConfig[];
265
265
 
266
- declare const index_decodeBase64Multiline: typeof decodeBase64Multiline;
267
- declare const index_decodeMultiline: typeof decodeMultiline;
268
- declare const index_decodeOne: typeof decodeOne;
266
+ declare const index$1_decodeBase64Multiline: typeof decodeBase64Multiline;
267
+ declare const index$1_decodeMultiline: typeof decodeMultiline;
268
+ declare const index$1_decodeOne: typeof decodeOne;
269
+ declare namespace index$1 {
270
+ export { index$1_decodeBase64Multiline as decodeBase64Multiline, index$1_decodeMultiline as decodeMultiline, index$1_decodeOne as decodeOne };
271
+ }
272
+
273
+ declare function parse(line: string): TrojanConfig;
274
+
275
+ declare const index_parse: typeof parse;
269
276
  declare namespace index {
270
- export { index_decodeBase64Multiline as decodeBase64Multiline, index_decodeMultiline as decodeMultiline, index_decodeOne as decodeOne };
277
+ export { index_parse as parse };
271
278
  }
272
279
 
273
- export { type HttpProxyConfig, type Hysteria2Config, type ShadowSocksConfig, type SharedConfigBase, type SnellConfig, type Socks5Config, type SupportedConfig, type TrojanBasicConfig, type TrojanConfig, type TuicConfig, type VmessConfig, index$1 as clash, index as ss, index$2 as surge };
280
+ export { type HttpProxyConfig, type Hysteria2Config, type ShadowSocksConfig, type SharedConfigBase, type SnellConfig, type Socks5Config, type SupportedConfig, type TrojanBasicConfig, type TrojanConfig, type TuicConfig, type VmessConfig, index$2 as clash, index$1 as ss, index$3 as surge, index as trojan };
package/dist/es/index.mjs CHANGED
@@ -275,7 +275,7 @@ function encode$1(config) {
275
275
  }
276
276
  }
277
277
 
278
- var index$2 = {
278
+ var index$3 = {
279
279
  __proto__: null,
280
280
  decode: decode$1,
281
281
  encode: encode$1
@@ -467,7 +467,7 @@ function parseStringToObject(input) {
467
467
  }, {});
468
468
  }
469
469
 
470
- var index$1 = {
470
+ var index$2 = {
471
471
  __proto__: null,
472
472
  decode: decode,
473
473
  encode: encode
@@ -488,8 +488,22 @@ function decodeOne(sip002) {
488
488
  }
489
489
  const [serverName, _1] = server.split(':');
490
490
  const [_2, encodedName] = _1.split('#');
491
- const [port, _plugins] = _2.split('/');
492
- // TODO: implement plugin parsing
491
+ const [port, pluginsStr] = _2.split('/');
492
+ let plugin = null;
493
+ if (pluginsStr) {
494
+ try {
495
+ plugin = new URLSearchParams(pluginsStr).get('plugin');
496
+ } catch (e) {
497
+ const err = new Error(`[ss.decodeOne] Invalid plugins: ${pluginsStr}`);
498
+ err.cause = e;
499
+ throw err;
500
+ }
501
+ }
502
+ const pluginArgs = (plugin?.split(';') ?? []).reduce((acc, cur)=>{
503
+ const [key, value] = cur.split('=');
504
+ acc[key] = value;
505
+ return acc;
506
+ }, {});
493
507
  return {
494
508
  raw: sip002,
495
509
  type: 'ss',
@@ -498,7 +512,9 @@ function decodeOne(sip002) {
498
512
  port: number(port),
499
513
  cipher,
500
514
  password,
501
- udp: true
515
+ udp: true,
516
+ obfs: 'obfs-local' in pluginArgs && 'obfs' in pluginArgs && (pluginArgs.obfs === 'http' || pluginArgs.obfs === 'tls') ? pluginArgs.obfs : undefined,
517
+ obfsHost: 'obfs-host' in pluginArgs ? pluginArgs['obfs-host'] : undefined
502
518
  };
503
519
  }
504
520
  function decodeBase64Multiline(text) {
@@ -508,11 +524,39 @@ function decodeMultiline(text) {
508
524
  return decodeBase64Multiline(text).map((line)=>decodeOne(line));
509
525
  }
510
526
 
511
- var index = {
527
+ var index$1 = {
512
528
  __proto__: null,
513
529
  decodeBase64Multiline: decodeBase64Multiline,
514
530
  decodeMultiline: decodeMultiline,
515
531
  decodeOne: decodeOne
516
532
  };
517
533
 
518
- export { index$1 as clash, index as ss, index$2 as surge };
534
+ function parse(line) {
535
+ const url = new URL(line);
536
+ // trojan://password@remote_host:remote_port
537
+ const password = url.username;
538
+ const server = url.hostname;
539
+ const port = Number.parseInt(url.port, 10);
540
+ if (Number.isNaN(port)) {
541
+ throw new TypeError('invalid port: ' + url.port);
542
+ }
543
+ const name = decodeURIComponent(url.hash.slice(1));
544
+ return {
545
+ raw: line,
546
+ name,
547
+ type: 'trojan',
548
+ server,
549
+ port,
550
+ password,
551
+ udp: true,
552
+ sni: url.searchParams.get('sni') ?? server,
553
+ skipCertVerify: true
554
+ };
555
+ }
556
+
557
+ var index = {
558
+ __proto__: null,
559
+ parse: parse
560
+ };
561
+
562
+ export { index$2 as clash, index$1 as ss, index$3 as surge, index as trojan };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodelistparser",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Surge / Mihomo (Clash.Meta) nodelist / proxy provider parser and generator.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,19 +37,19 @@
37
37
  "foxts": "^1.5.1"
38
38
  },
39
39
  "devDependencies": {
40
- "@eslint-sukka/node": "^6.14.0",
40
+ "@eslint-sukka/node": "^6.16.1",
41
41
  "@swc-node/register": "^1.10.9",
42
- "@swc/core": "^1.10.16",
42
+ "@swc/core": "^1.11.8",
43
43
  "@types/mocha": "^10.0.10",
44
- "@types/node": "^22.13.4",
44
+ "@types/node": "^22.13.10",
45
45
  "bumpp": "^10.0.3",
46
- "bunchee": "^6.3.4",
47
- "eslint": "^9.20.1",
48
- "eslint-config-sukka": "^6.14.0",
49
- "eslint-formatter-sukka": "^6.14.0",
46
+ "bunchee": "^6.4.0",
47
+ "eslint": "^9.22.0",
48
+ "eslint-config-sukka": "^6.16.1",
49
+ "eslint-formatter-sukka": "^6.16.1",
50
50
  "expect": "^29.7.0",
51
51
  "mocha": "^11.1.0",
52
- "typescript": "^5.7.3"
52
+ "typescript": "^5.8.2"
53
53
  },
54
54
  "scripts": {
55
55
  "lint": "eslint --format=sukka .",