green-tunnel 2.0.2 → 3.0.2

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 (156) hide show
  1. package/dist/core/config.d.ts +13 -0
  2. package/dist/core/config.d.ts.map +1 -0
  3. package/dist/core/config.js +87 -0
  4. package/dist/core/config.js.map +1 -0
  5. package/dist/core/dns/decode.d.ts +12 -0
  6. package/dist/core/dns/decode.d.ts.map +1 -0
  7. package/dist/core/dns/decode.js +23 -0
  8. package/dist/core/dns/decode.js.map +1 -0
  9. package/dist/core/dns/doh.d.ts +19 -0
  10. package/dist/core/dns/doh.d.ts.map +1 -0
  11. package/dist/core/dns/doh.js +54 -0
  12. package/dist/core/dns/doh.js.map +1 -0
  13. package/dist/core/dns/dot.d.ts +13 -0
  14. package/dist/core/dns/dot.d.ts.map +1 -0
  15. package/dist/core/dns/dot.js +79 -0
  16. package/dist/core/dns/dot.js.map +1 -0
  17. package/dist/core/dns/index.d.ts +8 -0
  18. package/dist/core/dns/index.d.ts.map +1 -0
  19. package/dist/core/dns/index.js +18 -0
  20. package/dist/core/dns/index.js.map +1 -0
  21. package/dist/core/dns/plain.d.ts +17 -0
  22. package/dist/core/dns/plain.d.ts.map +1 -0
  23. package/dist/core/dns/plain.js +45 -0
  24. package/dist/core/dns/plain.js.map +1 -0
  25. package/dist/core/dns/resolver.d.ts +27 -0
  26. package/dist/core/dns/resolver.d.ts.map +1 -0
  27. package/dist/core/dns/resolver.js +81 -0
  28. package/dist/core/dns/resolver.js.map +1 -0
  29. package/dist/core/errors.d.ts +32 -0
  30. package/dist/core/errors.d.ts.map +1 -0
  31. package/dist/core/errors.js +37 -0
  32. package/dist/core/errors.js.map +1 -0
  33. package/dist/core/http/head.d.ts +40 -0
  34. package/dist/core/http/head.d.ts.map +1 -0
  35. package/dist/core/http/head.js +122 -0
  36. package/dist/core/http/head.js.map +1 -0
  37. package/dist/core/http/rewriter.d.ts +20 -0
  38. package/dist/core/http/rewriter.d.ts.map +1 -0
  39. package/dist/core/http/rewriter.js +184 -0
  40. package/dist/core/http/rewriter.js.map +1 -0
  41. package/dist/core/index.d.ts +28 -0
  42. package/dist/core/index.d.ts.map +1 -0
  43. package/dist/core/index.js +27 -0
  44. package/dist/core/index.js.map +1 -0
  45. package/dist/core/logger.d.ts +38 -0
  46. package/dist/core/logger.d.ts.map +1 -0
  47. package/dist/core/logger.js +92 -0
  48. package/dist/core/logger.js.map +1 -0
  49. package/dist/core/net/socket.d.ts +30 -0
  50. package/dist/core/net/socket.d.ts.map +1 -0
  51. package/dist/core/net/socket.js +98 -0
  52. package/dist/core/net/socket.js.map +1 -0
  53. package/dist/core/proxy/connect-tunnel.d.ts +14 -0
  54. package/dist/core/proxy/connect-tunnel.d.ts.map +1 -0
  55. package/dist/core/proxy/connect-tunnel.js +44 -0
  56. package/dist/core/proxy/connect-tunnel.js.map +1 -0
  57. package/dist/core/proxy/connection.d.ts +12 -0
  58. package/dist/core/proxy/connection.d.ts.map +1 -0
  59. package/dist/core/proxy/connection.js +88 -0
  60. package/dist/core/proxy/connection.js.map +1 -0
  61. package/dist/core/proxy/context.d.ts +15 -0
  62. package/dist/core/proxy/context.d.ts.map +1 -0
  63. package/dist/core/proxy/context.js +2 -0
  64. package/dist/core/proxy/context.js.map +1 -0
  65. package/dist/core/proxy/index.d.ts +33 -0
  66. package/dist/core/proxy/index.d.ts.map +1 -0
  67. package/dist/core/proxy/index.js +162 -0
  68. package/dist/core/proxy/index.js.map +1 -0
  69. package/dist/core/proxy/pipe.d.ts +12 -0
  70. package/dist/core/proxy/pipe.d.ts.map +1 -0
  71. package/dist/core/proxy/pipe.js +42 -0
  72. package/dist/core/proxy/pipe.js.map +1 -0
  73. package/dist/core/proxy/plain-tunnel.d.ts +12 -0
  74. package/dist/core/proxy/plain-tunnel.d.ts.map +1 -0
  75. package/dist/core/proxy/plain-tunnel.js +29 -0
  76. package/dist/core/proxy/plain-tunnel.js.map +1 -0
  77. package/dist/core/system-proxy/darwin.d.ts +32 -0
  78. package/dist/core/system-proxy/darwin.d.ts.map +1 -0
  79. package/dist/core/system-proxy/darwin.js +146 -0
  80. package/dist/core/system-proxy/darwin.js.map +1 -0
  81. package/dist/core/system-proxy/driver.d.ts +21 -0
  82. package/dist/core/system-proxy/driver.d.ts.map +1 -0
  83. package/dist/core/system-proxy/driver.js +2 -0
  84. package/dist/core/system-proxy/driver.js.map +1 -0
  85. package/dist/core/system-proxy/exec.d.ts +21 -0
  86. package/dist/core/system-proxy/exec.d.ts.map +1 -0
  87. package/dist/core/system-proxy/exec.js +62 -0
  88. package/dist/core/system-proxy/exec.js.map +1 -0
  89. package/dist/core/system-proxy/index.d.ts +45 -0
  90. package/dist/core/system-proxy/index.d.ts.map +1 -0
  91. package/dist/core/system-proxy/index.js +151 -0
  92. package/dist/core/system-proxy/index.js.map +1 -0
  93. package/dist/core/system-proxy/linux.d.ts +18 -0
  94. package/dist/core/system-proxy/linux.d.ts.map +1 -0
  95. package/dist/core/system-proxy/linux.js +100 -0
  96. package/dist/core/system-proxy/linux.js.map +1 -0
  97. package/dist/core/system-proxy/recovery.d.ts +23 -0
  98. package/dist/core/system-proxy/recovery.d.ts.map +1 -0
  99. package/dist/core/system-proxy/recovery.js +147 -0
  100. package/dist/core/system-proxy/recovery.js.map +1 -0
  101. package/dist/core/system-proxy/windows.d.ts +15 -0
  102. package/dist/core/system-proxy/windows.d.ts.map +1 -0
  103. package/dist/core/system-proxy/windows.js +96 -0
  104. package/dist/core/system-proxy/windows.js.map +1 -0
  105. package/dist/core/tls/fragment.d.ts +28 -0
  106. package/dist/core/tls/fragment.d.ts.map +1 -0
  107. package/dist/core/tls/fragment.js +81 -0
  108. package/dist/core/tls/fragment.js.map +1 -0
  109. package/dist/core/types.d.ts +138 -0
  110. package/dist/core/types.d.ts.map +1 -0
  111. package/dist/core/types.js +7 -0
  112. package/dist/core/types.js.map +1 -0
  113. package/dist/index.d.ts +11 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +11 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/main.d.ts +3 -0
  118. package/dist/main.d.ts.map +1 -0
  119. package/dist/main.js +155 -0
  120. package/dist/main.js.map +1 -0
  121. package/dist/options.d.ts +25 -0
  122. package/dist/options.d.ts.map +1 -0
  123. package/dist/options.js +144 -0
  124. package/dist/options.js.map +1 -0
  125. package/dist/ui.d.ts +17 -0
  126. package/dist/ui.d.ts.map +1 -0
  127. package/dist/ui.js +89 -0
  128. package/dist/ui.js.map +1 -0
  129. package/dist/version.d.ts +3 -0
  130. package/dist/version.d.ts.map +1 -0
  131. package/dist/version.js +13 -0
  132. package/dist/version.js.map +1 -0
  133. package/package.json +31 -30
  134. package/LICENSE +0 -21
  135. package/README.md +0 -172
  136. package/bin/gt.js +0 -170
  137. package/src/config.js +0 -15
  138. package/src/dns/base.js +0 -47
  139. package/src/dns/https.js +0 -30
  140. package/src/dns/tls.js +0 -15
  141. package/src/dns/unencrypted.js +0 -25
  142. package/src/handlers/http.js +0 -65
  143. package/src/handlers/https.js +0 -78
  144. package/src/handlers/request.js +0 -32
  145. package/src/http/request.js +0 -45
  146. package/src/http/response.js +0 -45
  147. package/src/http/utils.js +0 -86
  148. package/src/index.cjs +0 -7
  149. package/src/index.js +0 -4
  150. package/src/logger.js +0 -11
  151. package/src/proxy.js +0 -74
  152. package/src/scripts/windows/wininet-reset-settings.ps1 +0 -14
  153. package/src/utils/analytics.js +0 -59
  154. package/src/utils/buffer.js +0 -35
  155. package/src/utils/socket.js +0 -32
  156. package/src/utils/system-proxy.js +0 -153
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Typed errors. v2 swallowed nearly every failure into a debug log, which is
3
+ * why a broken DNS lookup silently became a connection to 127.0.0.1. Everything
4
+ * here is meant to reach the caller.
5
+ */
6
+ export class GreenTunnelError extends Error {
7
+ name = 'GreenTunnelError';
8
+ }
9
+ export class DnsError extends GreenTunnelError {
10
+ name = 'DnsError';
11
+ hostname;
12
+ constructor(hostname, message, options) {
13
+ super(`DNS lookup failed for "${hostname}": ${message}`, options);
14
+ this.hostname = hostname;
15
+ }
16
+ }
17
+ export class ConnectError extends GreenTunnelError {
18
+ name = 'ConnectError';
19
+ host;
20
+ port;
21
+ constructor(host, port, message, options) {
22
+ super(`Cannot connect to ${host}:${String(port)}: ${message}`, options);
23
+ this.host = host;
24
+ this.port = port;
25
+ }
26
+ }
27
+ export class ProtocolError extends GreenTunnelError {
28
+ name = 'ProtocolError';
29
+ }
30
+ export class SystemProxyError extends GreenTunnelError {
31
+ name = 'SystemProxyError';
32
+ }
33
+ /** Narrow an unknown catch binding to something with a message. */
34
+ export function toError(value) {
35
+ return value instanceof Error ? value : new Error(String(value));
36
+ }
37
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACvB,IAAI,GAAW,kBAAkB,CAAC;CACrD;AAED,MAAM,OAAO,QAAS,SAAQ,gBAAgB;IAC1B,IAAI,GAAG,UAAU,CAAC;IAC3B,QAAQ,CAAS;IAE1B,YAAY,QAAgB,EAAE,OAAe,EAAE,OAA6B;QAC1E,KAAK,CAAC,0BAA0B,QAAQ,MAAM,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,gBAAgB;IAC9B,IAAI,GAAG,cAAc,CAAC;IAC/B,IAAI,CAAS;IACb,IAAI,CAAS;IAEtB,YAAY,IAAY,EAAE,IAAY,EAAE,OAAe,EAAE,OAA6B;QACpF,KAAK,CAAC,qBAAqB,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,gBAAgB;IAC/B,IAAI,GAAG,eAAe,CAAC;CAC1C;AAED,MAAM,OAAO,gBAAiB,SAAQ,gBAAgB;IAClC,IAAI,GAAG,kBAAkB,CAAC;CAC7C;AAED,mEAAmE;AACnE,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,40 @@
1
+ export interface HeaderField {
2
+ readonly name: string;
3
+ readonly value: string;
4
+ }
5
+ export interface RequestHead {
6
+ readonly method: string;
7
+ /** Request target exactly as sent: origin-form, absolute-form or authority-form. */
8
+ readonly target: string;
9
+ readonly version: string;
10
+ /** Kept as an ordered list — duplicates and casing are significant on the wire. */
11
+ readonly headers: readonly HeaderField[];
12
+ }
13
+ /**
14
+ * Parse the head of an HTTP/1.x request (request line + fields, no trailing
15
+ * blank line). Throws `ProtocolError` rather than producing a half-built object.
16
+ */
17
+ export declare function parseRequestHead(raw: string): RequestHead;
18
+ /** Serialize a head back onto the wire, including the terminating blank line. */
19
+ export declare function serializeRequestHead(head: RequestHead): string;
20
+ export declare function getHeader(head: RequestHead, name: string): string | undefined;
21
+ /**
22
+ * Turn a proxied request into one an origin server will accept:
23
+ * absolute-form target becomes origin-form, proxy-only headers are dropped, and
24
+ * a `Host` header is synthesized if the client relied on the absolute URI.
25
+ */
26
+ export declare function toOriginForm(head: RequestHead): RequestHead;
27
+ /** Resolve the upstream host and port a proxied request is aimed at. */
28
+ export declare function resolveUpstream(head: RequestHead, defaultPort: number): {
29
+ host: string;
30
+ port: number;
31
+ };
32
+ /**
33
+ * Split `host:port`, `[::1]:443` or a bare host. Throws when there is no host,
34
+ * so we never end up dialling `undefined` (which resolves to localhost).
35
+ */
36
+ export declare function splitAuthority(authority: string, defaultPort: number): {
37
+ host: string;
38
+ port: number;
39
+ };
40
+ //# sourceMappingURL=head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../../src/core/http/head.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C;AAKD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CA2BzD;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAM9D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG7E;AAWD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAa3D;AAcD,wEAAwE;AACxE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,WAAW,EAAE,MAAM,GAClB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAMA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAsBA"}
@@ -0,0 +1,122 @@
1
+ import { ProtocolError } from '../errors.js';
2
+ /** Methods a client may legally send to a proxy. */
3
+ const METHOD_PATTERN = /^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/;
4
+ /**
5
+ * Parse the head of an HTTP/1.x request (request line + fields, no trailing
6
+ * blank line). Throws `ProtocolError` rather than producing a half-built object.
7
+ */
8
+ export function parseRequestHead(raw) {
9
+ const lines = raw.split('\r\n');
10
+ const requestLine = lines.shift();
11
+ if (!requestLine) {
12
+ throw new ProtocolError('Empty HTTP request line');
13
+ }
14
+ const parts = requestLine.split(' ').filter((part) => part.length > 0);
15
+ const [method, target, version = 'HTTP/1.1'] = parts;
16
+ if (!method || !target || parts.length < 2) {
17
+ throw new ProtocolError(`Malformed HTTP request line: ${JSON.stringify(requestLine)}`);
18
+ }
19
+ if (!METHOD_PATTERN.test(method)) {
20
+ throw new ProtocolError(`Invalid HTTP method: ${JSON.stringify(method)}`);
21
+ }
22
+ const headers = [];
23
+ for (const line of lines) {
24
+ if (line.length === 0)
25
+ continue;
26
+ const separator = line.indexOf(':');
27
+ if (separator < 1) {
28
+ throw new ProtocolError(`Malformed HTTP header: ${JSON.stringify(line)}`);
29
+ }
30
+ headers.push({ name: line.slice(0, separator), value: line.slice(separator + 1).trim() });
31
+ }
32
+ return { method, target, version, headers };
33
+ }
34
+ /** Serialize a head back onto the wire, including the terminating blank line. */
35
+ export function serializeRequestHead(head) {
36
+ const lines = [`${head.method} ${head.target} ${head.version}`];
37
+ for (const { name, value } of head.headers) {
38
+ lines.push(`${name}: ${value}`);
39
+ }
40
+ return `${lines.join('\r\n')}\r\n\r\n`;
41
+ }
42
+ export function getHeader(head, name) {
43
+ const wanted = name.toLowerCase();
44
+ return head.headers.find((field) => field.name.toLowerCase() === wanted)?.value;
45
+ }
46
+ /**
47
+ * Headers that address *this* proxy and must not be relayed upstream.
48
+ *
49
+ * Deliberately narrow: `Connection`, `Transfer-Encoding` and friends are left
50
+ * alone because we forward the body byte-for-byte, so the framing the client
51
+ * chose has to stay intact.
52
+ */
53
+ const PROXY_ONLY_HEADERS = new Set(['proxy-connection', 'proxy-authorization']);
54
+ /**
55
+ * Turn a proxied request into one an origin server will accept:
56
+ * absolute-form target becomes origin-form, proxy-only headers are dropped, and
57
+ * a `Host` header is synthesized if the client relied on the absolute URI.
58
+ */
59
+ export function toOriginForm(head) {
60
+ const headers = head.headers.filter((field) => !PROXY_ONLY_HEADERS.has(field.name.toLowerCase()));
61
+ let target = head.target;
62
+ if (isAbsoluteForm(target)) {
63
+ const url = parseAbsoluteTarget(target);
64
+ target = `${url.pathname}${url.search}`;
65
+ if (!headers.some((field) => field.name.toLowerCase() === 'host')) {
66
+ headers.unshift({ name: 'Host', value: url.host });
67
+ }
68
+ }
69
+ return { method: head.method, target, version: head.version, headers };
70
+ }
71
+ function isAbsoluteForm(target) {
72
+ return /^[a-z][a-z0-9+.-]*:\/\//i.test(target);
73
+ }
74
+ function parseAbsoluteTarget(target) {
75
+ try {
76
+ return new URL(target);
77
+ }
78
+ catch (cause) {
79
+ throw new ProtocolError(`Invalid absolute request target: ${target}`, { cause });
80
+ }
81
+ }
82
+ /** Resolve the upstream host and port a proxied request is aimed at. */
83
+ export function resolveUpstream(head, defaultPort) {
84
+ const authority = isAbsoluteForm(head.target)
85
+ ? parseAbsoluteTarget(head.target).host
86
+ : (getHeader(head, 'host') ?? '');
87
+ return splitAuthority(authority, defaultPort);
88
+ }
89
+ /**
90
+ * Split `host:port`, `[::1]:443` or a bare host. Throws when there is no host,
91
+ * so we never end up dialling `undefined` (which resolves to localhost).
92
+ */
93
+ export function splitAuthority(authority, defaultPort) {
94
+ const trimmed = authority.trim();
95
+ if (trimmed.length === 0) {
96
+ throw new ProtocolError('Request has no target authority (missing Host header)');
97
+ }
98
+ if (trimmed.startsWith('[')) {
99
+ const end = trimmed.indexOf(']');
100
+ if (end < 0)
101
+ throw new ProtocolError(`Malformed IPv6 authority: ${authority}`);
102
+ const host = trimmed.slice(1, end);
103
+ const rest = trimmed.slice(end + 1);
104
+ return { host, port: rest.startsWith(':') ? parsePort(rest.slice(1), authority) : defaultPort };
105
+ }
106
+ const separator = trimmed.lastIndexOf(':');
107
+ if (separator < 0) {
108
+ return { host: trimmed, port: defaultPort };
109
+ }
110
+ return {
111
+ host: trimmed.slice(0, separator),
112
+ port: parsePort(trimmed.slice(separator + 1), authority),
113
+ };
114
+ }
115
+ function parsePort(raw, authority) {
116
+ const port = Number.parseInt(raw, 10);
117
+ if (!Number.isInteger(port) || port < 1 || port > 65_535) {
118
+ throw new ProtocolError(`Invalid port in authority: ${authority}`);
119
+ }
120
+ return port;
121
+ }
122
+ //# sourceMappingURL=head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.js","sourceRoot":"","sources":["../../../src/core/http/head.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { Transform } from 'node:stream';
2
+ /**
3
+ * Rewrites every request head on a keep-alive proxy connection while forwarding
4
+ * bodies byte-for-byte.
5
+ *
6
+ * v2 ran its rewrite over *every* chunk and asked "does this look like a
7
+ * request?" — so a POST body that happened to start with the word `GET`, or any
8
+ * binary upload, was silently mangled. Tracking `Content-Length` / chunked
9
+ * framing is the only correct way to know where the next head actually begins.
10
+ */
11
+ export declare class HttpRequestRewriter {
12
+ #private;
13
+ /** Feed raw client bytes in, get rewritten bytes out. */
14
+ transform(chunk: Buffer): Buffer[];
15
+ /** Flush whatever is still buffered when the client half-closes. */
16
+ flush(): Buffer[];
17
+ }
18
+ /** Stream wrapper so the rewriter can sit inside a `pipeline()`. */
19
+ export declare function createRequestRewriteStream(): Transform;
20
+ //# sourceMappingURL=rewriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewriter.d.ts","sourceRoot":"","sources":["../../../src/core/http/rewriter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA0B,MAAM,aAAa,CAAC;AAWhE;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;;IAK9B,yDAAyD;IACzD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAkBlC,oEAAoE;IACpE,KAAK,IAAI,MAAM,EAAE;CAiIlB;AAED,oEAAoE;AACpE,wBAAgB,0BAA0B,IAAI,SAAS,CAqBtD"}
@@ -0,0 +1,184 @@
1
+ import { Transform } from 'node:stream';
2
+ import { ProtocolError, toError } from '../errors.js';
3
+ import { getHeader, parseRequestHead, serializeRequestHead, toOriginForm } from './head.js';
4
+ const MAX_HEAD_BYTES = 64 * 1024;
5
+ const CRLF = '\r\n';
6
+ const HEAD_TERMINATOR = '\r\n\r\n';
7
+ /**
8
+ * Rewrites every request head on a keep-alive proxy connection while forwarding
9
+ * bodies byte-for-byte.
10
+ *
11
+ * v2 ran its rewrite over *every* chunk and asked "does this look like a
12
+ * request?" — so a POST body that happened to start with the word `GET`, or any
13
+ * binary upload, was silently mangled. Tracking `Content-Length` / chunked
14
+ * framing is the only correct way to know where the next head actually begins.
15
+ */
16
+ export class HttpRequestRewriter {
17
+ #state = 'head';
18
+ #buffer = Buffer.alloc(0);
19
+ #remaining = 0;
20
+ /** Feed raw client bytes in, get rewritten bytes out. */
21
+ transform(chunk) {
22
+ this.#buffer = this.#buffer.length === 0 ? chunk : Buffer.concat([this.#buffer, chunk]);
23
+ const out = [];
24
+ for (;;) {
25
+ if (this.#state === 'passthrough') {
26
+ if (this.#buffer.length > 0) {
27
+ out.push(this.#buffer);
28
+ this.#buffer = Buffer.alloc(0);
29
+ }
30
+ return out;
31
+ }
32
+ const progressed = this.#step(out);
33
+ if (!progressed)
34
+ return out;
35
+ }
36
+ }
37
+ /** Flush whatever is still buffered when the client half-closes. */
38
+ flush() {
39
+ if (this.#buffer.length === 0)
40
+ return [];
41
+ const rest = this.#buffer;
42
+ this.#buffer = Buffer.alloc(0);
43
+ return [rest];
44
+ }
45
+ /** Returns false when it needs more bytes. */
46
+ #step(out) {
47
+ switch (this.#state) {
48
+ case 'head':
49
+ return this.#stepHead(out);
50
+ case 'body-length':
51
+ case 'chunk-data':
52
+ return this.#stepCountedBytes(out);
53
+ case 'chunk-size':
54
+ return this.#stepChunkSize(out);
55
+ case 'chunk-crlf':
56
+ return this.#stepChunkCrlf(out);
57
+ case 'trailers':
58
+ return this.#stepTrailers(out);
59
+ default:
60
+ return false;
61
+ }
62
+ }
63
+ #stepHead(out) {
64
+ const end = this.#buffer.indexOf(HEAD_TERMINATOR);
65
+ if (end < 0) {
66
+ if (this.#buffer.length > MAX_HEAD_BYTES) {
67
+ throw new ProtocolError(`HTTP request head exceeds ${String(MAX_HEAD_BYTES)} bytes`);
68
+ }
69
+ return false;
70
+ }
71
+ const raw = this.#buffer.subarray(0, end).toString('latin1');
72
+ this.#consume(end + HEAD_TERMINATOR.length);
73
+ const head = toOriginForm(parseRequestHead(raw));
74
+ out.push(Buffer.from(serializeRequestHead(head), 'latin1'));
75
+ // A successful Upgrade turns the rest of the connection into an opaque
76
+ // tunnel — stop trying to parse it as HTTP.
77
+ if (getHeader(head, 'upgrade')) {
78
+ this.#state = 'passthrough';
79
+ return true;
80
+ }
81
+ const encoding = getHeader(head, 'transfer-encoding')?.toLowerCase();
82
+ if (encoding?.includes('chunked')) {
83
+ this.#state = 'chunk-size';
84
+ return true;
85
+ }
86
+ const length = getHeader(head, 'content-length');
87
+ if (length !== undefined) {
88
+ const parsed = Number.parseInt(length, 10);
89
+ if (!Number.isInteger(parsed) || parsed < 0) {
90
+ throw new ProtocolError(`Invalid Content-Length: ${length}`);
91
+ }
92
+ this.#remaining = parsed;
93
+ this.#state = parsed > 0 ? 'body-length' : 'head';
94
+ return true;
95
+ }
96
+ this.#state = 'head';
97
+ return true;
98
+ }
99
+ /** Forward exactly `#remaining` bytes verbatim, then advance. */
100
+ #stepCountedBytes(out) {
101
+ const take = Math.min(this.#remaining, this.#buffer.length);
102
+ if (take > 0) {
103
+ out.push(this.#buffer.subarray(0, take));
104
+ this.#consume(take);
105
+ this.#remaining -= take;
106
+ }
107
+ if (this.#remaining > 0)
108
+ return false;
109
+ this.#state = this.#state === 'body-length' ? 'head' : 'chunk-crlf';
110
+ return true;
111
+ }
112
+ #stepChunkSize(out) {
113
+ const end = this.#buffer.indexOf(CRLF);
114
+ if (end < 0) {
115
+ if (this.#buffer.length > MAX_HEAD_BYTES) {
116
+ throw new ProtocolError('Chunk size line is implausibly long');
117
+ }
118
+ return false;
119
+ }
120
+ const line = this.#buffer.subarray(0, end).toString('latin1');
121
+ out.push(this.#buffer.subarray(0, end + CRLF.length));
122
+ this.#consume(end + CRLF.length);
123
+ const size = Number.parseInt(line.split(';', 1)[0]?.trim() ?? '', 16);
124
+ if (!Number.isInteger(size) || size < 0) {
125
+ throw new ProtocolError(`Invalid chunk size: ${JSON.stringify(line)}`);
126
+ }
127
+ if (size === 0) {
128
+ this.#state = 'trailers';
129
+ }
130
+ else {
131
+ this.#remaining = size;
132
+ this.#state = 'chunk-data';
133
+ }
134
+ return true;
135
+ }
136
+ #stepChunkCrlf(out) {
137
+ if (this.#buffer.length < CRLF.length)
138
+ return false;
139
+ out.push(this.#buffer.subarray(0, CRLF.length));
140
+ this.#consume(CRLF.length);
141
+ this.#state = 'chunk-size';
142
+ return true;
143
+ }
144
+ #stepTrailers(out) {
145
+ const end = this.#buffer.indexOf(CRLF);
146
+ if (end < 0)
147
+ return false;
148
+ out.push(this.#buffer.subarray(0, end + CRLF.length));
149
+ this.#consume(end + CRLF.length);
150
+ if (end === 0)
151
+ this.#state = 'head';
152
+ return true;
153
+ }
154
+ #consume(bytes) {
155
+ this.#buffer = this.#buffer.subarray(bytes);
156
+ }
157
+ }
158
+ /** Stream wrapper so the rewriter can sit inside a `pipeline()`. */
159
+ export function createRequestRewriteStream() {
160
+ const rewriter = new HttpRequestRewriter();
161
+ return new Transform({
162
+ transform(chunk, _encoding, callback) {
163
+ try {
164
+ for (const piece of rewriter.transform(chunk))
165
+ this.push(piece);
166
+ callback();
167
+ }
168
+ catch (error) {
169
+ callback(toError(error));
170
+ }
171
+ },
172
+ flush(callback) {
173
+ try {
174
+ for (const piece of rewriter.flush())
175
+ this.push(piece);
176
+ callback();
177
+ }
178
+ catch (error) {
179
+ callback(toError(error));
180
+ }
181
+ },
182
+ });
183
+ }
184
+ //# sourceMappingURL=rewriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewriter.js","sourceRoot":"","sources":["../../../src/core/http/rewriter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The engine. No Electron, no CLI — nothing under this directory may import
3
+ * from outside it, which ESLint enforces (see `eslint.config.js`).
4
+ *
5
+ * Re-exported wholesale by `../index.js`, so consumers reach all of this as
6
+ * `green-tunnel`:
7
+ *
8
+ * ```ts
9
+ * import { Proxy, SystemProxy, DEFAULT_BYPASS } from 'green-tunnel';
10
+ *
11
+ * const proxy = new Proxy({ port: 8000, dns: { mode: 'doh' } });
12
+ * const { host, port } = await proxy.start();
13
+ *
14
+ * const system = new SystemProxy();
15
+ * await system.enable({ host, port, bypass: DEFAULT_BYPASS });
16
+ * ```
17
+ */
18
+ export { Proxy, type ProxyDependencies } from './proxy/index.js';
19
+ export { DEFAULT_DNS, DEFAULT_FRAGMENT, DEFAULT_SETTINGS, assertValidSettings, resolveSettings, } from './config.js';
20
+ export { ConnectError, DnsError, GreenTunnelError, ProtocolError, SystemProxyError, toError, } from './errors.js';
21
+ export { LOG_LEVELS, Logger, createLogger, isLogLevel, stderrSink, type LogLevel, type LogRecord, type LogSink, type LoggerOptions, } from './logger.js';
22
+ export { CachingDnsResolver, DohResolver, DotResolver, PlainResolver, createDnsResolver, type DnsResolver, type QueryType, } from './dns/index.js';
23
+ export { DEFAULT_BYPASS, SystemProxy, createSystemProxyDriver, defaultRecoveryPath, isSystemProxySupported, recoverSystemProxy, type SystemProxyDriver, type SystemProxyOptions, } from './system-proxy/index.js';
24
+ export { fragmentClientHello, isClientHello, splitBytes } from './tls/fragment.js';
25
+ export { HttpRequestRewriter, createRequestRewriteStream } from './http/rewriter.js';
26
+ export { getHeader, parseRequestHead, resolveUpstream, serializeRequestHead, splitAuthority, toOriginForm, type HeaderField, type RequestHead, } from './http/head.js';
27
+ export type { DeepPartial, DnsMode, DnsRecord, DnsSettings, FragmentSettings, IpFamilyPreference, ProxyAddress, ProxyEndpointState, ProxyEventMap, ProxyOptions, ProxySettings, ProxyStats, SystemProxySettings, SystemProxySnapshot, SystemProxySnapshotEntry, TunnelInfo, TunnelKind, } from './types.js';
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,OAAO,GACR,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,MAAM,EACN,YAAY,EACZ,UAAU,EACV,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,GACf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,cAAc,EACd,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAErF,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,WAAW,EACX,OAAO,EACP,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The engine. No Electron, no CLI — nothing under this directory may import
3
+ * from outside it, which ESLint enforces (see `eslint.config.js`).
4
+ *
5
+ * Re-exported wholesale by `../index.js`, so consumers reach all of this as
6
+ * `green-tunnel`:
7
+ *
8
+ * ```ts
9
+ * import { Proxy, SystemProxy, DEFAULT_BYPASS } from 'green-tunnel';
10
+ *
11
+ * const proxy = new Proxy({ port: 8000, dns: { mode: 'doh' } });
12
+ * const { host, port } = await proxy.start();
13
+ *
14
+ * const system = new SystemProxy();
15
+ * await system.enable({ host, port, bypass: DEFAULT_BYPASS });
16
+ * ```
17
+ */
18
+ export { Proxy } from './proxy/index.js';
19
+ export { DEFAULT_DNS, DEFAULT_FRAGMENT, DEFAULT_SETTINGS, assertValidSettings, resolveSettings, } from './config.js';
20
+ export { ConnectError, DnsError, GreenTunnelError, ProtocolError, SystemProxyError, toError, } from './errors.js';
21
+ export { LOG_LEVELS, Logger, createLogger, isLogLevel, stderrSink, } from './logger.js';
22
+ export { CachingDnsResolver, DohResolver, DotResolver, PlainResolver, createDnsResolver, } from './dns/index.js';
23
+ export { DEFAULT_BYPASS, SystemProxy, createSystemProxyDriver, defaultRecoveryPath, isSystemProxySupported, recoverSystemProxy, } from './system-proxy/index.js';
24
+ export { fragmentClientHello, isClientHello, splitBytes } from './tls/fragment.js';
25
+ export { HttpRequestRewriter, createRequestRewriteStream } from './http/rewriter.js';
26
+ export { getHeader, parseRequestHead, resolveUpstream, serializeRequestHead, splitAuthority, toOriginForm, } from './http/head.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,OAAO,GACR,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,MAAM,EACN,YAAY,EACZ,UAAU,EACV,UAAU,GAKX,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,aAAa,EACb,iBAAiB,GAGlB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,cAAc,EACd,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,GAGnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAErF,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,YAAY,GAGb,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,38 @@
1
+ export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
2
+ export interface LogRecord {
3
+ readonly level: Exclude<LogLevel, 'silent'>;
4
+ readonly scope: string;
5
+ readonly message: string;
6
+ readonly time: number;
7
+ readonly error?: Error;
8
+ }
9
+ export type LogSink = (record: LogRecord) => void;
10
+ export interface LoggerOptions {
11
+ readonly level?: LogLevel;
12
+ /** Where records go. Defaults to a coloured stderr writer. */
13
+ readonly sink?: LogSink;
14
+ }
15
+ /** Every level, quietest first — for `--log-level` help and level pickers. */
16
+ export declare const LOG_LEVELS: readonly LogLevel[];
17
+ export declare function isLogLevel(value: string): value is LogLevel;
18
+ export declare const stderrSink: LogSink;
19
+ /**
20
+ * A ~50-line replacement for `debug`. Levelled, scoped, and pluggable so the
21
+ * Electron main process can forward records straight into the UI.
22
+ */
23
+ export declare class Logger {
24
+ #private;
25
+ readonly scope: string;
26
+ constructor(scope?: string, options?: LoggerOptions);
27
+ get level(): LogLevel;
28
+ setLevel(level: LogLevel): void;
29
+ setSink(sink: LogSink): void;
30
+ child(scope: string): Logger;
31
+ error(message: string, error?: Error): void;
32
+ warn(message: string): void;
33
+ info(message: string): void;
34
+ debug(message: string): void;
35
+ trace(message: string): void;
36
+ }
37
+ export declare function createLogger(options?: LoggerOptions): Logger;
38
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAWD,8EAA8E;AAC9E,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAOzC,CAAC;AAUF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,eAAO,MAAM,UAAU,EAAE,OAOxB,CAAC;AAQF;;;GAGG;AACH,qBAAa,MAAM;;IACjB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAGX,KAAK,SAAiB,EAAE,OAAO,GAAE,aAAkB;IAK/D,IAAI,KAAK,IAAI,QAAQ,CAEpB;IAED,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI5B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAU5B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAY7B;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAEhE"}
@@ -0,0 +1,92 @@
1
+ import { styleText } from 'node:util';
2
+ const RANK = {
3
+ silent: 0,
4
+ error: 1,
5
+ warn: 2,
6
+ info: 3,
7
+ debug: 4,
8
+ trace: 5,
9
+ };
10
+ /** Every level, quietest first — for `--log-level` help and level pickers. */
11
+ export const LOG_LEVELS = [
12
+ 'silent',
13
+ 'error',
14
+ 'warn',
15
+ 'info',
16
+ 'debug',
17
+ 'trace',
18
+ ];
19
+ const COLOR = {
20
+ error: 'red',
21
+ warn: 'yellow',
22
+ info: 'cyan',
23
+ debug: 'gray',
24
+ trace: 'gray',
25
+ };
26
+ export function isLogLevel(value) {
27
+ return Object.hasOwn(RANK, value);
28
+ }
29
+ export const stderrSink = (record) => {
30
+ const time = new Date(record.time).toISOString().slice(11, 23);
31
+ const head = styleText(COLOR[record.level], `${record.level.padEnd(5)} ${record.scope}`);
32
+ console.error(`${styleText('gray', time)} ${head} ${record.message}`);
33
+ if (record.error?.stack) {
34
+ console.error(styleText('gray', record.error.stack));
35
+ }
36
+ };
37
+ /**
38
+ * A ~50-line replacement for `debug`. Levelled, scoped, and pluggable so the
39
+ * Electron main process can forward records straight into the UI.
40
+ */
41
+ export class Logger {
42
+ scope;
43
+ #state;
44
+ constructor(scope = 'green-tunnel', options = {}) {
45
+ this.scope = scope;
46
+ this.#state = { level: options.level ?? 'error', sink: options.sink ?? stderrSink };
47
+ }
48
+ get level() {
49
+ return this.#state.level;
50
+ }
51
+ setLevel(level) {
52
+ this.#state.level = level;
53
+ }
54
+ setSink(sink) {
55
+ this.#state.sink = sink;
56
+ }
57
+ child(scope) {
58
+ const child = new Logger(`${this.scope}:${scope}`);
59
+ // Deliberately the *same* state object, not a copy of the values: the log
60
+ // panel raises the level while the app is running, and a child created
61
+ // before that would otherwise stay stuck at whatever the level was when it
62
+ // was made — silently swallowing exactly the records the user asked for.
63
+ child.#state = this.#state;
64
+ return child;
65
+ }
66
+ error(message, error) {
67
+ this.#emit('error', message, error);
68
+ }
69
+ warn(message) {
70
+ this.#emit('warn', message);
71
+ }
72
+ info(message) {
73
+ this.#emit('info', message);
74
+ }
75
+ debug(message) {
76
+ this.#emit('debug', message);
77
+ }
78
+ trace(message) {
79
+ this.#emit('trace', message);
80
+ }
81
+ #emit(level, message, error) {
82
+ if (RANK[level] > RANK[this.#state.level])
83
+ return;
84
+ this.#state.sink(error
85
+ ? { level, scope: this.scope, message, time: Date.now(), error }
86
+ : { level, scope: this.scope, message, time: Date.now() });
87
+ }
88
+ }
89
+ export function createLogger(options = {}) {
90
+ return new Logger('green-tunnel', options);
91
+ }
92
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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"}