@bbk47/toolbox 1.0.8 → 2.0.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.
Files changed (90) hide show
  1. package/lib/deferred.d.ts +7 -0
  2. package/lib/deferred.d.ts.map +1 -0
  3. package/lib/deferred.js +8 -4
  4. package/lib/deferred.js.map +1 -0
  5. package/lib/encrypt.d.ts +19 -0
  6. package/lib/encrypt.d.ts.map +1 -0
  7. package/lib/encrypt.js +78 -79
  8. package/lib/encrypt.js.map +1 -0
  9. package/lib/index.d.ts +19 -0
  10. package/lib/index.d.ts.map +1 -0
  11. package/lib/index.js +58 -12
  12. package/lib/index.js.map +1 -0
  13. package/lib/logger.d.ts +11 -0
  14. package/lib/logger.d.ts.map +1 -0
  15. package/lib/logger.js +23 -14
  16. package/lib/logger.js.map +1 -0
  17. package/lib/md5.d.ts +2 -0
  18. package/lib/md5.d.ts.map +1 -0
  19. package/lib/md5.js +9 -6
  20. package/lib/md5.js.map +1 -0
  21. package/lib/merge.d.ts +2 -0
  22. package/lib/merge.d.ts.map +1 -0
  23. package/lib/merge.js +7 -8
  24. package/lib/merge.js.map +1 -0
  25. package/lib/proxy.d.ts +6 -0
  26. package/lib/proxy.d.ts.map +1 -0
  27. package/lib/proxy.js +23 -20
  28. package/lib/proxy.js.map +1 -0
  29. package/lib/retry.d.ts +6 -0
  30. package/lib/retry.d.ts.map +1 -0
  31. package/lib/retry.js +11 -13
  32. package/lib/retry.js.map +1 -0
  33. package/lib/server.d.ts +14 -0
  34. package/lib/server.d.ts.map +1 -0
  35. package/lib/server.js +36 -26
  36. package/lib/server.js.map +1 -0
  37. package/lib/socks5.d.ts +8 -0
  38. package/lib/socks5.d.ts.map +1 -0
  39. package/lib/socks5.js +24 -27
  40. package/lib/socks5.js.map +1 -0
  41. package/lib/timeout.d.ts +2 -0
  42. package/lib/timeout.d.ts.map +1 -0
  43. package/lib/timeout.js +6 -2
  44. package/lib/timeout.js.map +1 -0
  45. package/lib/transport/creater.d.ts +14 -0
  46. package/lib/transport/creater.d.ts.map +1 -0
  47. package/lib/transport/creater.js +45 -37
  48. package/lib/transport/creater.js.map +1 -0
  49. package/lib/transport/helper.d.ts +14 -0
  50. package/lib/transport/helper.d.ts.map +1 -0
  51. package/lib/transport/helper.js +27 -26
  52. package/lib/transport/helper.js.map +1 -0
  53. package/lib/transport/index.d.ts +6 -0
  54. package/lib/transport/index.d.ts.map +1 -0
  55. package/lib/transport/index.js +43 -11
  56. package/lib/transport/index.js.map +1 -0
  57. package/lib/transport/transport.d.ts +23 -0
  58. package/lib/transport/transport.d.ts.map +1 -0
  59. package/lib/transport/transport.js +18 -15
  60. package/lib/transport/transport.js.map +1 -0
  61. package/lib/uuid.d.ts +2 -0
  62. package/lib/uuid.d.ts.map +1 -0
  63. package/lib/uuid.js +14 -20
  64. package/lib/uuid.js.map +1 -0
  65. package/package.json +17 -4
  66. package/src/deferred.ts +14 -0
  67. package/src/encrypt.ts +119 -0
  68. package/src/index.ts +29 -0
  69. package/src/logger.ts +59 -0
  70. package/src/md5.ts +5 -0
  71. package/src/merge.ts +16 -0
  72. package/src/proxy.ts +65 -0
  73. package/src/retry.ts +32 -0
  74. package/src/server.ts +77 -0
  75. package/src/socks5.ts +46 -0
  76. package/src/timeout.ts +3 -0
  77. package/src/transport/creater.ts +88 -0
  78. package/src/transport/helper.ts +73 -0
  79. package/src/transport/index.ts +6 -0
  80. package/src/transport/transport.ts +54 -0
  81. package/src/uuid.ts +37 -0
  82. package/.github/workflows/test.yml +0 -30
  83. package/.prettierrc +0 -11
  84. package/test/deferred.js +0 -24
  85. package/test/encrypt.js +0 -25
  86. package/test/md5.js +0 -9
  87. package/test/merge.js +0 -11
  88. package/test/retry.js +0 -61
  89. package/test/socks5.js +0 -42
  90. package/test/uuid.js +0 -11
@@ -1,38 +1,41 @@
1
- const { websocketSend, tcpsocketSend, bindWebsocket, bindStreamSocket } = require('./helper');
2
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transport = void 0;
4
+ const helper_1 = require("./helper");
3
5
  class Transport {
4
6
  constructor(opts) {
5
7
  this.type = opts.type;
6
8
  this.conn = opts.conn;
7
9
  }
8
-
9
10
  sendPacket(binarydata) {
10
11
  if (this.type === 'ws') {
11
- websocketSend(this.conn, binarydata);
12
- } else {
13
- tcpsocketSend(this.conn, binarydata);
12
+ (0, helper_1.websocketSend)(this.conn, binarydata);
13
+ }
14
+ else {
15
+ (0, helper_1.tcpsocketSend)(this.conn, binarydata);
14
16
  }
15
17
  }
16
-
17
18
  bindEvents(onData, onError, onClose) {
18
19
  if (this.type === 'ws') {
19
- bindWebsocket(this.conn, onData, onError, onClose);
20
- } else {
21
- bindStreamSocket(this.conn, onData, onError, onClose);
20
+ (0, helper_1.bindWebsocket)(this.conn, onData, onError, onClose);
21
+ }
22
+ else {
23
+ (0, helper_1.bindStreamSocket)(this.conn, onData, onError, onClose);
22
24
  }
23
25
  }
24
-
25
26
  close() {
26
27
  try {
27
28
  if (this.type === 'ws' || this.type === 'h2') {
28
29
  this.conn.close();
29
- } else {
30
+ }
31
+ else {
30
32
  this.conn.destroy();
31
33
  }
32
- } catch (err) {
34
+ }
35
+ catch (_err) {
33
36
  // ignore
34
37
  }
35
38
  }
36
39
  }
37
-
38
- module.exports = Transport;
40
+ exports.Transport = Transport;
41
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":";;;AAEA,qCAAyF;AAezF,MAAa,SAAS;IAIlB,YAAY,IAAkD;QAC1D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,UAAU,CAAC,UAAkB;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACrB,IAAA,sBAAa,EAAC,IAAI,CAAC,IAA4B,EAAE,UAAU,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACJ,IAAA,sBAAa,EAAC,IAAI,CAAC,IAA6B,EAAE,UAAU,CAAC,CAAC;QAClE,CAAC;IACL,CAAC;IAED,UAAU,CAAC,MAAoB,EAAE,OAAsB,EAAE,OAAsB;QAC3E,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACrB,IAAA,sBAAa,EAAC,IAAI,CAAC,IAA4B,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/E,CAAC;aAAM,CAAC;YACJ,IAAA,yBAAgB,EAAC,IAAI,CAAC,IAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACjE,CAAC;IACL,CAAC;IAED,KAAK;QACD,IAAI,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC1C,IAAI,CAAC,IAAY,CAAC,KAAK,EAAE,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACH,IAAI,CAAC,IAAY,CAAC,OAAO,EAAE,CAAC;YACjC,CAAC;QACL,CAAC;QAAC,OAAO,IAAI,EAAE,CAAC;YACZ,SAAS;QACb,CAAC;IACL,CAAC;CACJ;AApCD,8BAoCC"}
package/lib/uuid.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export default function uuid(): string;
2
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAkCA,MAAM,CAAC,OAAO,UAAU,IAAI,IAAI,MAAM,CAErC"}
package/lib/uuid.js CHANGED
@@ -1,16 +1,16 @@
1
- // const uuid = require('uuid').v4;
2
-
3
- var lut = [];
4
- for (var i = 0; i < 256; i++) {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = uuid;
4
+ const lut = [];
5
+ for (let i = 0; i < 256; i++) {
5
6
  lut[i] = (i < 16 ? '0' : '') + i.toString(16);
6
7
  }
7
8
  function e7() {
8
- var d0 = (Math.random() * 0xffffffff) | 0;
9
- var d1 = (Math.random() * 0xffffffff) | 0;
10
- var d2 = (Math.random() * 0xffffffff) | 0;
11
- var d3 = (Math.random() * 0xffffffff) | 0;
12
- return (
13
- lut[d0 & 0xff] +
9
+ const d0 = (Math.random() * 0xffffffff) | 0;
10
+ const d1 = (Math.random() * 0xffffffff) | 0;
11
+ const d2 = (Math.random() * 0xffffffff) | 0;
12
+ const d3 = (Math.random() * 0xffffffff) | 0;
13
+ return (lut[d0 & 0xff] +
14
14
  lut[(d0 >> 8) & 0xff] +
15
15
  lut[(d0 >> 16) & 0xff] +
16
16
  lut[(d0 >> 24) & 0xff] +
@@ -29,15 +29,9 @@ function e7() {
29
29
  lut[d3 & 0xff] +
30
30
  lut[(d3 >> 8) & 0xff] +
31
31
  lut[(d3 >> 16) & 0xff] +
32
- lut[(d3 >> 24) & 0xff]
33
- );
32
+ lut[(d3 >> 24) & 0xff]);
34
33
  }
35
-
36
- function getRamdomUUID() {
37
- const id = e7();
38
- return id.replace(/-/g, '');
34
+ function uuid() {
35
+ return e7().replace(/-/g, '');
39
36
  }
40
-
41
- // console.log(getRamdomUUID());
42
-
43
- module.exports = getRamdomUUID;
37
+ //# sourceMappingURL=uuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":";;AAkCA,uBAEC;AApCD,MAAM,GAAG,GAAa,EAAE,CAAC;AACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;IAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,EAAE;IACP,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5C,OAAO,CACH,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;QACd,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACrB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACtB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACtB,GAAG;QACH,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;QACd,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACrB,GAAG;QACH,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAC/B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACtB,GAAG;QACH,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACvB,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACrB,GAAG;QACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACtB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACtB,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;QACd,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACrB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACtB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CACzB,CAAC;AACN,CAAC;AAED,SAAwB,IAAI;IACxB,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "name": "@bbk47/toolbox",
3
- "version": "1.0.8",
3
+ "version": "2.0.0",
4
4
  "description": "toolbox for bbk",
5
5
  "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "files": [
8
+ "lib",
9
+ "src"
10
+ ],
6
11
  "scripts": {
7
- "test": "mocha ./test"
12
+ "build": "tsc",
13
+ "test": "jest",
14
+ "test:coverage": "jest --coverage",
15
+ "prepublishOnly": "npm run build && npm test"
8
16
  },
9
17
  "repository": {
10
18
  "type": "git",
@@ -17,10 +25,15 @@
17
25
  },
18
26
  "homepage": "https://github.com/bbk47/toolboxjs#readme",
19
27
  "dependencies": {
20
- "date-format": "^3.0.0",
21
28
  "ws": "2.3.x"
22
29
  },
23
30
  "devDependencies": {
24
- "mocha": "^5.2.0"
31
+ "@jest/globals": "^30.4.1",
32
+ "@types/jest": "^30.0.0",
33
+ "@types/node": "^26.0.0",
34
+ "@types/ws": "^8.18.1",
35
+ "jest": "^30.4.2",
36
+ "ts-jest": "^29.4.11",
37
+ "typescript": "^6.0.3"
25
38
  }
26
39
  }
@@ -0,0 +1,14 @@
1
+ export interface Deferred<T = any> {
2
+ promise: Promise<T>;
3
+ resolve: (value: T | PromiseLike<T>) => void;
4
+ reject: (reason?: any) => void;
5
+ }
6
+
7
+ export default function deferred<T = any>(): Deferred<T> {
8
+ const defer = {} as Deferred<T>;
9
+ defer.promise = new Promise<T>((resolve, reject) => {
10
+ defer.resolve = resolve;
11
+ defer.reject = reject;
12
+ });
13
+ return defer;
14
+ }
package/src/encrypt.ts ADDED
@@ -0,0 +1,119 @@
1
+ import crypto from 'crypto';
2
+
3
+ type CipherKey = string;
4
+ interface KeyIVCache {
5
+ [key: string]: [Buffer, Buffer];
6
+ }
7
+ interface KeyIV {
8
+ key: Buffer;
9
+ iv: Buffer;
10
+ }
11
+
12
+ const bytes_to_key_results: KeyIVCache = {};
13
+
14
+ const EVP_BytesToKey = function (
15
+ password: Buffer,
16
+ key_len: number,
17
+ iv_len: number
18
+ ): [Buffer, Buffer] {
19
+ const cacheKey = `${password}:${key_len}:${iv_len}`;
20
+ if (bytes_to_key_results[cacheKey]) {
21
+ return bytes_to_key_results[cacheKey];
22
+ }
23
+ const m: Buffer[] = [];
24
+ let i = 0;
25
+ let count = 0;
26
+ while (count < key_len + iv_len) {
27
+ const md5hash = crypto.createHash('md5');
28
+ let data: Buffer = password;
29
+ if (i > 0) {
30
+ data = Buffer.concat([m[i - 1], password]);
31
+ }
32
+ md5hash.update(data);
33
+ const d = md5hash.digest();
34
+ m.push(d);
35
+ count += d.length;
36
+ i += 1;
37
+ }
38
+ const ms = Buffer.concat(m);
39
+ const key = ms.slice(0, key_len);
40
+ const iv = ms.slice(key_len, key_len + iv_len);
41
+ bytes_to_key_results[cacheKey] = [key, iv];
42
+ return [key, iv];
43
+ };
44
+
45
+ export type CipherMethod =
46
+ | 'aes-128-cfb'
47
+ | 'aes-192-cfb'
48
+ | 'aes-256-cfb'
49
+ | 'bf-cfb'
50
+ | 'camellia-128-cfb'
51
+ | 'camellia-192-cfb'
52
+ | 'camellia-256-cfb'
53
+ | 'cast5-cfb'
54
+ | 'des-cfb'
55
+ | 'idea-cfb'
56
+ | 'rc2-cfb'
57
+ | 'rc4'
58
+ | 'seed-cfb';
59
+
60
+ const method_supported: Record<CipherMethod, [number, number]> = {
61
+ 'aes-128-cfb': [16, 16],
62
+ 'aes-192-cfb': [24, 16],
63
+ 'aes-256-cfb': [32, 16],
64
+ 'bf-cfb': [16, 8],
65
+ 'camellia-128-cfb': [16, 16],
66
+ 'camellia-192-cfb': [24, 16],
67
+ 'camellia-256-cfb': [32, 16],
68
+ 'cast5-cfb': [16, 8],
69
+ 'des-cfb': [8, 8],
70
+ 'idea-cfb': [16, 8],
71
+ 'rc2-cfb': [16, 8],
72
+ rc4: [16, 0],
73
+ 'seed-cfb': [16, 16],
74
+ };
75
+
76
+ export class Encryptor {
77
+ key: CipherKey;
78
+ method: CipherMethod;
79
+ _EVP_KEY: Buffer;
80
+ _IV: Buffer;
81
+
82
+ constructor(key: string = 'MVP123', method: CipherMethod = 'aes-256-cfb') {
83
+ this.key = key;
84
+ this.method = method;
85
+ if (!method_supported[this.method]) {
86
+ throw new Error('Not support method!');
87
+ }
88
+ const keyIV = this.getKeyIV(key, method);
89
+ this._EVP_KEY = keyIV.key;
90
+ this._IV = keyIV.iv;
91
+ }
92
+
93
+ get_cipher_len(method: string): [number, number] {
94
+ const m = method.toLowerCase() as CipherMethod;
95
+ return method_supported[m];
96
+ }
97
+
98
+ getKeyIV(password: string, method: string): KeyIV {
99
+ const m = method.toLowerCase() as CipherMethod;
100
+ const passwordBuf = Buffer.from(password, 'ascii');
101
+ const [keyLen, ivLen] = this.get_cipher_len(m);
102
+ const ref = EVP_BytesToKey(passwordBuf, keyLen, ivLen);
103
+ return { key: ref[0], iv: ref[1] };
104
+ }
105
+
106
+ encrypt(buf: Buffer): Buffer {
107
+ const cipher = crypto.createCipheriv(this.method, this._EVP_KEY, this._IV);
108
+ const encrypted = cipher.update(buf);
109
+ const result = cipher.final();
110
+ return Buffer.concat([encrypted, result]);
111
+ }
112
+
113
+ decrypt(buf: Buffer): Buffer {
114
+ const decipher = crypto.createDecipheriv(this.method, this._EVP_KEY, this._IV);
115
+ const decrypted = decipher.update(buf);
116
+ const result = decipher.final();
117
+ return Buffer.concat([decrypted, result]);
118
+ }
119
+ }
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ export { default as deferred } from './deferred';
2
+ export type { Deferred } from './deferred';
3
+
4
+ export * as encrypt from './encrypt';
5
+ export type { CipherMethod } from './encrypt';
6
+
7
+ export { default as logger } from './logger';
8
+ export type { LogLevel, Logger } from './logger';
9
+
10
+ export { default as md5 } from './md5';
11
+
12
+ export { default as merge } from './merge';
13
+
14
+ export * as proxy from './proxy';
15
+ export type { OnConnect, ConnectCallback } from './proxy';
16
+
17
+ export { default as retry } from './retry';
18
+ export type { RetryOptions } from './retry';
19
+
20
+ export * as server from './server';
21
+
22
+ export * as socks5 from './socks5';
23
+ export type { Socks5AddrInfo } from './socks5';
24
+
25
+ export * as timeout from './timeout';
26
+
27
+ export * as transport from './transport';
28
+
29
+ export { default as uuid } from './uuid';
package/src/logger.ts ADDED
@@ -0,0 +1,59 @@
1
+ export type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'log' | 'debug';
2
+
3
+ export interface Logger {
4
+ fatal: (msg: string) => void;
5
+ error: (msg: string) => void;
6
+ warn: (msg: string) => void;
7
+ info: (msg: string) => void;
8
+ log: (msg: string) => void;
9
+ debug: (msg: string) => void;
10
+ }
11
+
12
+ interface LevelConfig {
13
+ piv: number;
14
+ colour: string;
15
+ }
16
+
17
+ const levelVal: Record<LogLevel, LevelConfig> = {
18
+ fatal: { piv: 1, colour: '\x1b[31m%s\x1b[0m' },
19
+ error: { piv: 2, colour: '\x1b[31m%s\x1b[0m' },
20
+ warn: { piv: 3, colour: '\x1b[33m%s\x1b[0m' },
21
+ info: { piv: 4, colour: '\x1b[32m%s\x1b[0m' },
22
+ log: { piv: 5, colour: '\x1b[37m%s\x1b[0m' },
23
+ debug: { piv: 6, colour: '\x1b[35m%s\x1b[0m' },
24
+ };
25
+
26
+ function formatDate(date: Date): string {
27
+ const pad = (n: number) => String(n).padStart(2, '0');
28
+ return `${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
29
+ }
30
+
31
+ export default function getCustomLogger(
32
+ label: string,
33
+ level: LogLevel,
34
+ _logFile?: string
35
+ ): Logger {
36
+ const noop = () => undefined;
37
+ const setPiv = levelVal[level].piv;
38
+
39
+ function makeLogFn(key: LogLevel): (msg: string) => void {
40
+ if (levelVal[key].piv <= setPiv) {
41
+ const colour = levelVal[key].colour;
42
+ return (msg: string) => {
43
+ const date = formatDate(new Date());
44
+ const prefix = `${date} [${key[0].toUpperCase()}] ${label} `;
45
+ console.log(colour, prefix, msg);
46
+ };
47
+ }
48
+ return noop;
49
+ }
50
+
51
+ return {
52
+ fatal: makeLogFn('fatal'),
53
+ error: makeLogFn('error'),
54
+ warn: makeLogFn('warn'),
55
+ info: makeLogFn('info'),
56
+ log: makeLogFn('log'),
57
+ debug: makeLogFn('debug'),
58
+ };
59
+ }
package/src/md5.ts ADDED
@@ -0,0 +1,5 @@
1
+ import crypto from 'crypto';
2
+
3
+ export default function md5(s: string | number): string {
4
+ return crypto.createHash('md5').update(String(s)).digest('hex');
5
+ }
package/src/merge.ts ADDED
@@ -0,0 +1,16 @@
1
+ export default function merge<T extends Record<string, any>>(
2
+ target: T,
3
+ ...sources: (Record<string, any> | null | undefined)[]
4
+ ): T & Record<string, any> {
5
+ target = target || ({} as T);
6
+ sources.forEach((temp) => {
7
+ if (temp) {
8
+ Object.keys(temp).forEach((key) => {
9
+ if (temp[key] !== null && temp[key] !== undefined) {
10
+ (target as Record<string, any>)[key] = temp[key];
11
+ }
12
+ });
13
+ }
14
+ });
15
+ return target;
16
+ }
package/src/proxy.ts ADDED
@@ -0,0 +1,65 @@
1
+ import net from 'net';
2
+ import { buildSocks5Addr } from './socks5';
3
+
4
+ export type ConnectCallback = (err?: Error | null) => void;
5
+ export type OnConnect = (addr: Buffer, callback: ConnectCallback) => void;
6
+
7
+ export function createSocks5Proxy(cSock: net.Socket, onConnect: OnConnect): void {
8
+ let stage = 'INIT';
9
+ cSock.on('data', function dataListener(data: Buffer) {
10
+ if (stage === 'INIT') {
11
+ cSock.write('\x05\x00');
12
+ stage = 'ADDR';
13
+ return;
14
+ } else if (stage === 'ADDR') {
15
+ onConnect(data.slice(3), (err) => {
16
+ if (!err) {
17
+ stage = 'STREAM';
18
+ cSock.write('\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00');
19
+ cSock.removeAllListeners('data');
20
+ cSock.pause();
21
+ } else {
22
+ cSock.destroy();
23
+ }
24
+ });
25
+ return;
26
+ }
27
+ });
28
+
29
+ cSock.on('error', () => {
30
+ cSock.destroy();
31
+ });
32
+ }
33
+
34
+ export function createConnectProxy(cSock: net.Socket, onConnect: OnConnect): void {
35
+ let stage = 'INIT';
36
+ cSock.on('data', (data: Buffer) => {
37
+ if (stage === 'INIT') {
38
+ const str = data.toString('ascii');
39
+ const lines = str.split(/\s/g);
40
+ if (lines[0] !== 'CONNECT') {
41
+ cSock.destroy();
42
+ return;
43
+ }
44
+ const hoststr = lines[1];
45
+ const reqhost = hoststr.split(':');
46
+ const hostname = reqhost[0];
47
+ const port = Number(reqhost[1]);
48
+ const socksAddrInfo = buildSocks5Addr(hostname, port);
49
+ onConnect(socksAddrInfo, (err) => {
50
+ if (!err) {
51
+ cSock.write(Buffer.from('HTTP/1.1 200 Connection Established\r\n\r\n'));
52
+ stage = 'STREAM';
53
+ cSock.removeAllListeners('data');
54
+ cSock.pause();
55
+ } else {
56
+ cSock.destroy();
57
+ }
58
+ });
59
+ }
60
+ });
61
+
62
+ cSock.on('error', () => {
63
+ cSock.destroy();
64
+ });
65
+ }
package/src/retry.ts ADDED
@@ -0,0 +1,32 @@
1
+ const delay = (time: number): Promise<void> =>
2
+ new Promise((resolve) => setTimeout(resolve, time));
3
+
4
+ export interface RetryOptions {
5
+ times?: number;
6
+ interval?: number;
7
+ }
8
+
9
+ export default function retryPromise<T>(
10
+ fn: () => Promise<T>,
11
+ opts: RetryOptions = {},
12
+ errcall?: (err: Error) => void
13
+ ): Promise<T> {
14
+ const retryCount = opts.times !== undefined ? opts.times : 5;
15
+
16
+ function invoker(idx: number): Promise<T> {
17
+ if (idx >= retryCount) {
18
+ return Promise.reject(
19
+ new Error(`expect retryCount ${retryCount} is attached!`)
20
+ );
21
+ }
22
+ return fn().catch((err: Error) => {
23
+ errcall && errcall(err);
24
+ if (opts.interval) {
25
+ return delay(opts.interval).then(() => invoker(idx + 1));
26
+ } else {
27
+ return invoker(idx + 1);
28
+ }
29
+ });
30
+ }
31
+ return invoker(0);
32
+ }
package/src/server.ts ADDED
@@ -0,0 +1,77 @@
1
+ import net from 'net';
2
+ import http from 'http';
3
+ import tls from 'tls';
4
+ import http2 from 'http2';
5
+ import url from 'url';
6
+ import WebSocket from 'ws';
7
+
8
+ export type HttpHandler = (req: http.IncomingMessage, res: http.ServerResponse) => void;
9
+ export type WsHandler = (ws: WebSocket) => void;
10
+ export type StreamHandler = (stream: net.Socket | http2.ServerHttp2Stream) => void;
11
+ export type ConnHandler = (conn: net.Socket | tls.TLSSocket) => void;
12
+
13
+ export function createWsServer(
14
+ workPath: string,
15
+ handler: WsHandler,
16
+ httpHandler?: HttpHandler
17
+ ): http.Server {
18
+ const server = http.createServer(function (req, res) {
19
+ if (httpHandler) {
20
+ httpHandler(req, res);
21
+ }
22
+ });
23
+ // ws 2.x exposes Server as WebSocket.Server
24
+ const WsServer = (WebSocket as any).Server as typeof WebSocket;
25
+ const wss: any = new (WsServer as any)({ noServer: true, clientTracking: false });
26
+ wss.on('connection', function (wsconn: WebSocket) {
27
+ handler(wsconn);
28
+ });
29
+ server.on('upgrade', function (request, socket, head) {
30
+ const pathname = url.parse(request.url || '').pathname;
31
+ if (pathname === workPath) {
32
+ wss.handleUpgrade(request, socket as net.Socket, head, function done(ws: WebSocket) {
33
+ wss.emit('connection', ws, request);
34
+ });
35
+ } else {
36
+ socket.destroy();
37
+ }
38
+ });
39
+ return server;
40
+ }
41
+
42
+ export function createHttp2Server(
43
+ tlsOpts: tls.TlsOptions,
44
+ workPath: string,
45
+ handler: (stream: http2.ServerHttp2Stream) => void,
46
+ httpHandler?: (req: http2.Http2ServerRequest, res: http2.Http2ServerResponse) => void
47
+ ): http2.Http2SecureServer {
48
+ const http2Opts = Object.assign({ allowHTTP1: true }, tlsOpts);
49
+ const server = http2.createSecureServer(http2Opts, function (req, res) {
50
+ if (httpHandler) {
51
+ httpHandler(req, res);
52
+ }
53
+ });
54
+ server.on('stream', function (stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) {
55
+ const path = headers[':path'];
56
+ if (path === workPath) {
57
+ handler(stream);
58
+ } else {
59
+ stream.destroy();
60
+ }
61
+ });
62
+ return server;
63
+ }
64
+
65
+ export function createTcpServer(handler: ConnHandler): net.Server {
66
+ const server = net.createServer(function (conn) {
67
+ handler(conn);
68
+ });
69
+ return server;
70
+ }
71
+
72
+ export function createTlsServer(tlsOpts: tls.TlsOptions, handler: ConnHandler): tls.Server {
73
+ const server = tls.createServer(tlsOpts, function (conn) {
74
+ handler(conn);
75
+ });
76
+ return server;
77
+ }
package/src/socks5.ts ADDED
@@ -0,0 +1,46 @@
1
+ export interface Socks5AddrInfo {
2
+ dstAddr: string;
3
+ dstPort: number;
4
+ }
5
+
6
+ export function parseSocks5Addr(buf: Buffer, offset = 0): Socks5AddrInfo {
7
+ if (offset > 0) {
8
+ buf = buf.slice(offset);
9
+ }
10
+ const type = buf.readUInt8(0);
11
+ const addrData = buf.slice(1);
12
+ let dstAddr = '';
13
+ let dstPort = 0;
14
+
15
+ if (type === 0x01) {
16
+ const IP = addrData.slice(0, -2);
17
+ const PORT = addrData.slice(-2);
18
+ dstAddr = Array.from(IP)
19
+ .map((temp) => Number(temp).toString(10))
20
+ .join('.');
21
+ dstPort = PORT[0] * 256 + PORT[1];
22
+ } else if (type === 0x03) {
23
+ const addrLen = addrData.readUInt8(0);
24
+ const domain = addrData.slice(1, addrLen + 1);
25
+ const port = addrData.slice(addrLen + 1);
26
+ dstAddr = domain.toString();
27
+ dstPort = port[0] * 256 + port[1];
28
+ }
29
+ return { dstAddr, dstPort };
30
+ }
31
+
32
+ export function buildSocks5Addr(hostname: string, port: number): Buffer {
33
+ if (/^(\d+\.){3}\d+$/.test(hostname)) {
34
+ const parts = hostname.split('.').map((p) => Number(p));
35
+ const portBuf = Buffer.from([Math.floor(port / 256), port % 256]);
36
+ const preBuf = Buffer.from([0x01, parts[0], parts[1], parts[2], parts[3]]);
37
+ return Buffer.concat([preBuf, portBuf]);
38
+ } else {
39
+ const preBuf = Buffer.from([0x03, hostname.length]);
40
+ const domainBuf = Buffer.from(hostname);
41
+ const portBuf = Buffer.from([Math.floor(port / 256), port % 256]);
42
+ return Buffer.concat([preBuf, domainBuf, portBuf]);
43
+ }
44
+ }
45
+
46
+ export const parseAddrInfo = parseSocks5Addr;
package/src/timeout.ts ADDED
@@ -0,0 +1,3 @@
1
+ export function timeoutPromise(time: number): Promise<string> {
2
+ return new Promise((resolve) => setTimeout(() => resolve('timeout:' + time), time));
3
+ }