ssh_tunnel_proxy 2.1.1 → 3.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 (109) hide show
  1. package/LICENSE +19 -3
  2. package/MIGRATION.md +227 -0
  3. package/README.md +360 -212
  4. package/build/bridge.d.ts +14 -0
  5. package/build/bridge.d.ts.map +1 -0
  6. package/build/bridge.js +12 -0
  7. package/build/bridge.js.map +1 -0
  8. package/build/connection.d.ts +60 -0
  9. package/build/connection.d.ts.map +1 -0
  10. package/build/connection.js +198 -0
  11. package/build/connection.js.map +1 -0
  12. package/build/credentials.d.ts +24 -0
  13. package/build/credentials.d.ts.map +1 -0
  14. package/build/credentials.js +102 -0
  15. package/build/credentials.js.map +1 -0
  16. package/build/errors.d.ts +19 -0
  17. package/build/errors.d.ts.map +1 -0
  18. package/build/errors.js +64 -0
  19. package/build/errors.js.map +1 -0
  20. package/build/forward-spec.d.ts +34 -0
  21. package/build/forward-spec.d.ts.map +1 -0
  22. package/build/forward-spec.js +175 -0
  23. package/build/forward-spec.js.map +1 -0
  24. package/build/index.d.ts +19 -0
  25. package/build/index.d.ts.map +1 -0
  26. package/build/index.js +71 -0
  27. package/build/index.js.map +1 -0
  28. package/build/legacy.d.ts +70 -0
  29. package/build/legacy.d.ts.map +1 -0
  30. package/build/legacy.js +188 -0
  31. package/build/legacy.js.map +1 -0
  32. package/build/local-forward.d.ts +31 -0
  33. package/build/local-forward.d.ts.map +1 -0
  34. package/build/local-forward.js +231 -0
  35. package/build/local-forward.js.map +1 -0
  36. package/build/model.d.ts +126 -0
  37. package/build/model.d.ts.map +1 -0
  38. package/build/model.js +55 -0
  39. package/build/model.js.map +1 -0
  40. package/build/port-policy.d.ts +43 -0
  41. package/build/port-policy.d.ts.map +1 -0
  42. package/build/port-policy.js +138 -0
  43. package/build/port-policy.js.map +1 -0
  44. package/build/remote-forward.d.ts +40 -0
  45. package/build/remote-forward.d.ts.map +1 -0
  46. package/build/remote-forward.js +226 -0
  47. package/build/remote-forward.js.map +1 -0
  48. package/build/tunnel.d.ts +121 -0
  49. package/build/tunnel.d.ts.map +1 -0
  50. package/build/tunnel.js +599 -0
  51. package/build/tunnel.js.map +1 -0
  52. package/examples/config.example.json +86 -0
  53. package/examples/setup_ssh.sh +12 -0
  54. package/examples/tunnel-cli.js +461 -0
  55. package/examples/tunnel-worker.js +98 -0
  56. package/examples/zrok-termux.ts +147 -0
  57. package/package.json +43 -53
  58. package/proto/sshtunnel/v1/tunnel.proto +343 -0
  59. package/dist/TestMessage.d.ts +0 -13
  60. package/dist/TestMessage.js +0 -32
  61. package/dist/TestMessage.js.map +0 -1
  62. package/dist/cjs/TestMessage.d.ts +0 -13
  63. package/dist/cjs/TestMessage.js +0 -32
  64. package/dist/cjs/TestMessage.js.map +0 -1
  65. package/dist/cjs/index.d.ts +0 -73
  66. package/dist/cjs/index.js +0 -621
  67. package/dist/cjs/index.js.map +0 -1
  68. package/dist/cjs/keypair_storage.d.ts +0 -12
  69. package/dist/cjs/keypair_storage.js +0 -143
  70. package/dist/cjs/keypair_storage.js.map +0 -1
  71. package/dist/cjs/ngrok_service.d.ts +0 -11
  72. package/dist/cjs/ngrok_service.js +0 -40
  73. package/dist/cjs/ngrok_service.js.map +0 -1
  74. package/dist/cjs/ssh2-node.d.ts +0 -1
  75. package/dist/cjs/ssh2-node.js +0 -211
  76. package/dist/cjs/ssh2-node.js.map +0 -1
  77. package/dist/esm/TestMessage.d.ts +0 -13
  78. package/dist/esm/TestMessage.js +0 -29
  79. package/dist/esm/TestMessage.js.map +0 -1
  80. package/dist/esm/index.d.ts +0 -73
  81. package/dist/esm/index.js +0 -616
  82. package/dist/esm/index.js.map +0 -1
  83. package/dist/esm/keypair_storage.d.ts +0 -12
  84. package/dist/esm/keypair_storage.js +0 -117
  85. package/dist/esm/keypair_storage.js.map +0 -1
  86. package/dist/esm/ngrok_service.d.ts +0 -11
  87. package/dist/esm/ngrok_service.js +0 -37
  88. package/dist/esm/ngrok_service.js.map +0 -1
  89. package/dist/esm/ssh2-node.d.ts +0 -1
  90. package/dist/esm/ssh2-node.js +0 -184
  91. package/dist/esm/ssh2-node.js.map +0 -1
  92. package/dist/index.d.ts +0 -73
  93. package/dist/index.js +0 -620
  94. package/dist/index.js.map +0 -1
  95. package/dist/keypair_storage.d.ts +0 -12
  96. package/dist/keypair_storage.js +0 -120
  97. package/dist/keypair_storage.js.map +0 -1
  98. package/dist/ngrok_service.d.ts +0 -11
  99. package/dist/ngrok_service.js +0 -40
  100. package/dist/ngrok_service.js.map +0 -1
  101. package/dist/ssh2-node.d.ts +0 -1
  102. package/dist/ssh2-node.js +0 -188
  103. package/dist/ssh2-node.js.map +0 -1
  104. package/dist/types/TestMessage.d.ts +0 -13
  105. package/dist/types/index.d.ts +0 -73
  106. package/dist/types/keypair_storage.d.ts +0 -12
  107. package/dist/types/ngrok_service.d.ts +0 -11
  108. package/dist/types/ssh2-node.d.ts +0 -1
  109. package/ssh2-node +0 -2
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ /*
3
+ * forward-spec.ts — pure parsing of the OpenSSH-style forward strings.
4
+ *
5
+ * The v1 configuration syntax is preserved so existing config.json files keep
6
+ * working, but the parsing rules are now explicit: field counts are checked
7
+ * before destructuring, and ports must be bare decimal integers.
8
+ *
9
+ * Local forward (ssh -L):
10
+ * "localPort:remoteHost:remotePort"
11
+ * "bindAddress:localPort:remoteHost:remotePort"
12
+ *
13
+ * Remote forward (ssh -R):
14
+ * "bindPort:targetHost:targetPort"
15
+ * "bindAddress:bindPort:targetHost:targetPort"
16
+ *
17
+ * Note the v1 3-field remote form was "localPort:host:remotePort" with the
18
+ * fields in an order that read backwards relative to OpenSSH. See MIGRATION.md;
19
+ * `parseRemoteForwardSpec` documents the mapping it applies.
20
+ *
21
+ * License: MIT
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.DEFAULT_REMOTE_BIND_ADDRESS = exports.DEFAULT_LISTEN_ADDRESS = void 0;
25
+ exports.parseLocalForwardSpec = parseLocalForwardSpec;
26
+ exports.parseRemoteForwardSpec = parseRemoteForwardSpec;
27
+ exports.validateLocalForward = validateLocalForward;
28
+ exports.validateRemoteForward = validateRemoteForward;
29
+ exports.parseAndValidateLocalForward = parseAndValidateLocalForward;
30
+ exports.parseAndValidateRemoteForward = parseAndValidateRemoteForward;
31
+ exports.describeLocalForward = describeLocalForward;
32
+ exports.describeRemoteForward = describeRemoteForward;
33
+ const errors_1 = require("./errors");
34
+ const port_policy_1 = require("./port-policy");
35
+ exports.DEFAULT_LISTEN_ADDRESS = '127.0.0.1';
36
+ exports.DEFAULT_REMOTE_BIND_ADDRESS = 'localhost';
37
+ const LOCAL_FORWARD_SHAPE = 'localPort:remoteHost:remotePort or bindAddress:localPort:remoteHost:remotePort';
38
+ const REMOTE_FORWARD_SHAPE = 'bindPort:targetHost:targetPort or bindAddress:bindPort:targetHost:targetPort';
39
+ function invalid(spec, shape, detail) {
40
+ const suffix = detail ? ` (${detail})` : '';
41
+ return new errors_1.TunnelError('INVALID_FORWARD_SPEC', `Invalid forward "${spec}"; expected ${shape}${suffix}`);
42
+ }
43
+ function splitSpec(spec, shape) {
44
+ if (typeof spec !== 'string' || spec.trim().length === 0) {
45
+ throw new errors_1.TunnelError('INVALID_FORWARD_SPEC', `Invalid forward ${JSON.stringify(spec)}; expected ${shape}`);
46
+ }
47
+ const fields = spec.split(':');
48
+ if (fields.length < 3 || fields.length > 4) {
49
+ throw invalid(spec, shape, `got ${fields.length} colon-separated fields`);
50
+ }
51
+ return fields;
52
+ }
53
+ function requirePort(spec, text, shape, label) {
54
+ const port = (0, port_policy_1.parsePort)(text);
55
+ if (port === undefined) {
56
+ throw invalid(spec, shape, `${label} "${text}" is not a decimal port in 1-65535`);
57
+ }
58
+ return port;
59
+ }
60
+ /**
61
+ * Parse a local-forward string into a structured {@link LocalForward}.
62
+ * Syntax only — call {@link validateLocalForward} to apply a {@link PortPolicy}.
63
+ */
64
+ function parseLocalForwardSpec(spec) {
65
+ const fields = splitSpec(spec, LOCAL_FORWARD_SHAPE);
66
+ const [listenHost, listenPortText, targetHostText, targetPortText] = fields.length === 4
67
+ ? fields
68
+ : [exports.DEFAULT_LISTEN_ADDRESS, fields[0], fields[1], fields[2]];
69
+ if (listenHost.trim().length === 0) {
70
+ throw invalid(spec, LOCAL_FORWARD_SHAPE, 'bind address is empty');
71
+ }
72
+ if (targetHostText.trim().length === 0) {
73
+ throw invalid(spec, LOCAL_FORWARD_SHAPE, 'remote host is required');
74
+ }
75
+ return {
76
+ id: spec,
77
+ listen: {
78
+ host: listenHost,
79
+ port: requirePort(spec, listenPortText, LOCAL_FORWARD_SHAPE, 'local listen port'),
80
+ },
81
+ target: {
82
+ host: targetHostText,
83
+ port: requirePort(spec, targetPortText, LOCAL_FORWARD_SHAPE, 'remote target port'),
84
+ },
85
+ };
86
+ }
87
+ /**
88
+ * Parse a remote-forward string into a structured {@link RemoteForward}.
89
+ *
90
+ * Field mapping, matching v1 behaviour:
91
+ * 3 fields: bindPort : targetHost : targetPort, bind address defaults to
92
+ * "localhost" on the peer.
93
+ * 4 fields: bindAddress : bindPort : targetHost : targetPort.
94
+ *
95
+ * A bind port of 0 asks the SSH peer to assign one; the assigned value is
96
+ * reported in ForwardStatus.assignedPort.
97
+ */
98
+ function parseRemoteForwardSpec(spec) {
99
+ const fields = splitSpec(spec, REMOTE_FORWARD_SHAPE);
100
+ const [bindHost, bindPortText, targetHostText, targetPortText] = fields.length === 4
101
+ ? fields
102
+ : [exports.DEFAULT_REMOTE_BIND_ADDRESS, fields[0], fields[1], fields[2]];
103
+ if (bindHost.trim().length === 0) {
104
+ throw invalid(spec, REMOTE_FORWARD_SHAPE, 'bind address is empty');
105
+ }
106
+ if (targetHostText.trim().length === 0) {
107
+ throw invalid(spec, REMOTE_FORWARD_SHAPE, 'target host is required');
108
+ }
109
+ const bindPort = bindPortText === '0' ? 0 : (0, port_policy_1.parsePort)(bindPortText);
110
+ if (!(0, port_policy_1.isValidBindPort)(bindPort)) {
111
+ throw invalid(spec, REMOTE_FORWARD_SHAPE, `bind port "${bindPortText}" is not 0-65535`);
112
+ }
113
+ return {
114
+ id: spec,
115
+ bind: { host: bindHost, port: bindPort },
116
+ target: {
117
+ host: targetHostText,
118
+ port: requirePort(spec, targetPortText, REMOTE_FORWARD_SHAPE, 'target port'),
119
+ },
120
+ };
121
+ }
122
+ /**
123
+ * Apply a {@link PortPolicy} to a structured local forward and return a
124
+ * normalized copy. Throws a {@link TunnelError} on the first violation.
125
+ */
126
+ function validateLocalForward(forward, policy = {}) {
127
+ const id = forward.id ?? describeLocalForward(forward);
128
+ const listenHost = forward.listen?.host ?? exports.DEFAULT_LISTEN_ADDRESS;
129
+ (0, port_policy_1.assertHostAllowed)(listenHost, {}, id);
130
+ const loopbackListen = new Set(['127.0.0.1', 'localhost', '::1', '[::1]']);
131
+ if (!loopbackListen.has(listenHost)) {
132
+ throw new errors_1.TunnelError('HOST_NOT_PERMITTED', `Local listen host ${listenHost} is not loopback; bind 127.0.0.1 or ::1`, { forwardId: id });
133
+ }
134
+ (0, port_policy_1.assertPortAllowed)(forward.listen?.port, 'local-listen', policy, id);
135
+ (0, port_policy_1.assertHostAllowed)(forward.target?.host, policy, id);
136
+ (0, port_policy_1.assertPortAllowed)(forward.target?.port, 'remote-target', policy, id);
137
+ return {
138
+ ...forward,
139
+ id,
140
+ listen: { host: listenHost, port: forward.listen.port },
141
+ target: { host: forward.target.host, port: forward.target.port },
142
+ };
143
+ }
144
+ /** Apply a {@link PortPolicy} to a structured remote forward. */
145
+ function validateRemoteForward(forward, policy = {}) {
146
+ const id = forward.id ?? describeRemoteForward(forward);
147
+ const bindHost = forward.bind?.host ?? exports.DEFAULT_REMOTE_BIND_ADDRESS;
148
+ (0, port_policy_1.assertHostAllowed)(bindHost, {}, id);
149
+ (0, port_policy_1.assertPortAllowed)(forward.bind?.port, 'remote-bind', policy, id);
150
+ (0, port_policy_1.assertHostAllowed)(forward.target?.host, {}, id);
151
+ (0, port_policy_1.assertPortAllowed)(forward.target?.port, 'local-listen', policy, id);
152
+ return {
153
+ ...forward,
154
+ id,
155
+ bind: { host: bindHost, port: forward.bind.port },
156
+ target: { host: forward.target.host, port: forward.target.port },
157
+ };
158
+ }
159
+ /** Parse and validate in one step. */
160
+ function parseAndValidateLocalForward(spec, policy = {}) {
161
+ return validateLocalForward(parseLocalForwardSpec(spec), policy);
162
+ }
163
+ /** Parse and validate in one step. */
164
+ function parseAndValidateRemoteForward(spec, policy = {}) {
165
+ return validateRemoteForward(parseRemoteForwardSpec(spec), policy);
166
+ }
167
+ function describeLocalForward(forward) {
168
+ const host = forward.listen?.host ?? exports.DEFAULT_LISTEN_ADDRESS;
169
+ return `L:${host}:${forward.listen?.port}->${forward.target?.host}:${forward.target?.port}`;
170
+ }
171
+ function describeRemoteForward(forward) {
172
+ const host = forward.bind?.host ?? exports.DEFAULT_REMOTE_BIND_ADDRESS;
173
+ return `R:${host}:${forward.bind?.port}->${forward.target?.host}:${forward.target?.port}`;
174
+ }
175
+ //# sourceMappingURL=forward-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward-spec.js","sourceRoot":"","sources":["../src/forward-spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export { SSHTunnel } from './tunnel';
2
+ export type { SSHTunnelOptions, TunnelEvents } from './tunnel';
3
+ export { LocalForwardHandle } from './local-forward';
4
+ export { RemoteForwardHandle } from './remote-forward';
5
+ export { ProxiedConnection } from './connection';
6
+ export type { ProxiedConnectionOptions } from './connection';
7
+ export type { TransportBridge } from './bridge';
8
+ export { TUNNEL_ERROR_CODES, TunnelError, isTunnelError, asTunnelError } from './errors';
9
+ export type { TunnelErrorCode, TunnelErrorDetails } from './errors';
10
+ export { DEFAULT_LISTEN_ADDRESS, DEFAULT_REMOTE_BIND_ADDRESS, describeLocalForward, describeRemoteForward, parseAndValidateLocalForward, parseAndValidateRemoteForward, parseLocalForwardSpec, parseRemoteForwardSpec, validateLocalForward, validateRemoteForward, } from './forward-spec';
11
+ export { FIRST_UNPRIVILEGED_PORT, MAX_PORT, MIN_PORT, assertHostAllowed, assertPortAllowed, checkPort, isValidBindPort, isValidHost, isValidPort, parsePort, } from './port-policy';
12
+ export type { PortCheckResult, PortRole } from './port-policy';
13
+ export { credential, expandHome, resolveAgentSocket, resolveCredential } from './credentials';
14
+ export type { CredentialResolver, ResolveOptions } from './credentials';
15
+ export { CONNECTION_STATES, CREDENTIAL_SOURCES, FORWARD_DIRECTIONS, FORWARD_STATES, REACHABILITY_VALUES, TUNNEL_STATES, DEFAULT_KEEPALIVE_COUNT_MAX, DEFAULT_KEEPALIVE_INTERVAL_MS, DEFAULT_READY_TIMEOUT_MS, DEFAULT_RECONNECT_POLICY, MODEL_VERSION, } from './model';
16
+ export type { ConnectionState, ConnectionStatus, CredentialRef, CredentialSource, Endpoint, ForwardDirection, ForwardState, ForwardStatus, LocalForward, PortPolicy, Reachability, ReconnectPolicy, RemoteForward, SshTransport, TunnelConfig, TunnelState, TunnelStatus, } from './model';
17
+ export { SSHTunnelProxy, legacyConfigToTunnelConfig, whitelistToPortPolicy, } from './legacy';
18
+ export type { LegacySSHConfig } from './legacy';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzF,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEpE,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,EAC5B,6BAA6B,EAC7B,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,uBAAuB,EACvB,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,EACX,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC9F,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAExE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /*
3
+ * ssh_tunnel_proxy v2
4
+ *
5
+ * Programmatic local and reverse TCP port forwarding over SSH for Node.js,
6
+ * built for services and devices that only have an outbound SSH transport.
7
+ *
8
+ * Author: Autonomous
9
+ * First release: 1-29-2023
10
+ * License: MIT
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.whitelistToPortPolicy = exports.legacyConfigToTunnelConfig = exports.SSHTunnelProxy = exports.MODEL_VERSION = exports.DEFAULT_RECONNECT_POLICY = exports.DEFAULT_READY_TIMEOUT_MS = exports.DEFAULT_KEEPALIVE_INTERVAL_MS = exports.DEFAULT_KEEPALIVE_COUNT_MAX = exports.TUNNEL_STATES = exports.REACHABILITY_VALUES = exports.FORWARD_STATES = exports.FORWARD_DIRECTIONS = exports.CREDENTIAL_SOURCES = exports.CONNECTION_STATES = exports.resolveCredential = exports.resolveAgentSocket = exports.expandHome = exports.credential = exports.parsePort = exports.isValidPort = exports.isValidHost = exports.isValidBindPort = exports.checkPort = exports.assertPortAllowed = exports.assertHostAllowed = exports.MIN_PORT = exports.MAX_PORT = exports.FIRST_UNPRIVILEGED_PORT = exports.validateRemoteForward = exports.validateLocalForward = exports.parseRemoteForwardSpec = exports.parseLocalForwardSpec = exports.parseAndValidateRemoteForward = exports.parseAndValidateLocalForward = exports.describeRemoteForward = exports.describeLocalForward = exports.DEFAULT_REMOTE_BIND_ADDRESS = exports.DEFAULT_LISTEN_ADDRESS = exports.asTunnelError = exports.isTunnelError = exports.TunnelError = exports.TUNNEL_ERROR_CODES = exports.ProxiedConnection = exports.RemoteForwardHandle = exports.LocalForwardHandle = exports.SSHTunnel = void 0;
14
+ var tunnel_1 = require("./tunnel");
15
+ Object.defineProperty(exports, "SSHTunnel", { enumerable: true, get: function () { return tunnel_1.SSHTunnel; } });
16
+ var local_forward_1 = require("./local-forward");
17
+ Object.defineProperty(exports, "LocalForwardHandle", { enumerable: true, get: function () { return local_forward_1.LocalForwardHandle; } });
18
+ var remote_forward_1 = require("./remote-forward");
19
+ Object.defineProperty(exports, "RemoteForwardHandle", { enumerable: true, get: function () { return remote_forward_1.RemoteForwardHandle; } });
20
+ var connection_1 = require("./connection");
21
+ Object.defineProperty(exports, "ProxiedConnection", { enumerable: true, get: function () { return connection_1.ProxiedConnection; } });
22
+ var errors_1 = require("./errors");
23
+ Object.defineProperty(exports, "TUNNEL_ERROR_CODES", { enumerable: true, get: function () { return errors_1.TUNNEL_ERROR_CODES; } });
24
+ Object.defineProperty(exports, "TunnelError", { enumerable: true, get: function () { return errors_1.TunnelError; } });
25
+ Object.defineProperty(exports, "isTunnelError", { enumerable: true, get: function () { return errors_1.isTunnelError; } });
26
+ Object.defineProperty(exports, "asTunnelError", { enumerable: true, get: function () { return errors_1.asTunnelError; } });
27
+ var forward_spec_1 = require("./forward-spec");
28
+ Object.defineProperty(exports, "DEFAULT_LISTEN_ADDRESS", { enumerable: true, get: function () { return forward_spec_1.DEFAULT_LISTEN_ADDRESS; } });
29
+ Object.defineProperty(exports, "DEFAULT_REMOTE_BIND_ADDRESS", { enumerable: true, get: function () { return forward_spec_1.DEFAULT_REMOTE_BIND_ADDRESS; } });
30
+ Object.defineProperty(exports, "describeLocalForward", { enumerable: true, get: function () { return forward_spec_1.describeLocalForward; } });
31
+ Object.defineProperty(exports, "describeRemoteForward", { enumerable: true, get: function () { return forward_spec_1.describeRemoteForward; } });
32
+ Object.defineProperty(exports, "parseAndValidateLocalForward", { enumerable: true, get: function () { return forward_spec_1.parseAndValidateLocalForward; } });
33
+ Object.defineProperty(exports, "parseAndValidateRemoteForward", { enumerable: true, get: function () { return forward_spec_1.parseAndValidateRemoteForward; } });
34
+ Object.defineProperty(exports, "parseLocalForwardSpec", { enumerable: true, get: function () { return forward_spec_1.parseLocalForwardSpec; } });
35
+ Object.defineProperty(exports, "parseRemoteForwardSpec", { enumerable: true, get: function () { return forward_spec_1.parseRemoteForwardSpec; } });
36
+ Object.defineProperty(exports, "validateLocalForward", { enumerable: true, get: function () { return forward_spec_1.validateLocalForward; } });
37
+ Object.defineProperty(exports, "validateRemoteForward", { enumerable: true, get: function () { return forward_spec_1.validateRemoteForward; } });
38
+ var port_policy_1 = require("./port-policy");
39
+ Object.defineProperty(exports, "FIRST_UNPRIVILEGED_PORT", { enumerable: true, get: function () { return port_policy_1.FIRST_UNPRIVILEGED_PORT; } });
40
+ Object.defineProperty(exports, "MAX_PORT", { enumerable: true, get: function () { return port_policy_1.MAX_PORT; } });
41
+ Object.defineProperty(exports, "MIN_PORT", { enumerable: true, get: function () { return port_policy_1.MIN_PORT; } });
42
+ Object.defineProperty(exports, "assertHostAllowed", { enumerable: true, get: function () { return port_policy_1.assertHostAllowed; } });
43
+ Object.defineProperty(exports, "assertPortAllowed", { enumerable: true, get: function () { return port_policy_1.assertPortAllowed; } });
44
+ Object.defineProperty(exports, "checkPort", { enumerable: true, get: function () { return port_policy_1.checkPort; } });
45
+ Object.defineProperty(exports, "isValidBindPort", { enumerable: true, get: function () { return port_policy_1.isValidBindPort; } });
46
+ Object.defineProperty(exports, "isValidHost", { enumerable: true, get: function () { return port_policy_1.isValidHost; } });
47
+ Object.defineProperty(exports, "isValidPort", { enumerable: true, get: function () { return port_policy_1.isValidPort; } });
48
+ Object.defineProperty(exports, "parsePort", { enumerable: true, get: function () { return port_policy_1.parsePort; } });
49
+ var credentials_1 = require("./credentials");
50
+ Object.defineProperty(exports, "credential", { enumerable: true, get: function () { return credentials_1.credential; } });
51
+ Object.defineProperty(exports, "expandHome", { enumerable: true, get: function () { return credentials_1.expandHome; } });
52
+ Object.defineProperty(exports, "resolveAgentSocket", { enumerable: true, get: function () { return credentials_1.resolveAgentSocket; } });
53
+ Object.defineProperty(exports, "resolveCredential", { enumerable: true, get: function () { return credentials_1.resolveCredential; } });
54
+ var model_1 = require("./model");
55
+ Object.defineProperty(exports, "CONNECTION_STATES", { enumerable: true, get: function () { return model_1.CONNECTION_STATES; } });
56
+ Object.defineProperty(exports, "CREDENTIAL_SOURCES", { enumerable: true, get: function () { return model_1.CREDENTIAL_SOURCES; } });
57
+ Object.defineProperty(exports, "FORWARD_DIRECTIONS", { enumerable: true, get: function () { return model_1.FORWARD_DIRECTIONS; } });
58
+ Object.defineProperty(exports, "FORWARD_STATES", { enumerable: true, get: function () { return model_1.FORWARD_STATES; } });
59
+ Object.defineProperty(exports, "REACHABILITY_VALUES", { enumerable: true, get: function () { return model_1.REACHABILITY_VALUES; } });
60
+ Object.defineProperty(exports, "TUNNEL_STATES", { enumerable: true, get: function () { return model_1.TUNNEL_STATES; } });
61
+ Object.defineProperty(exports, "DEFAULT_KEEPALIVE_COUNT_MAX", { enumerable: true, get: function () { return model_1.DEFAULT_KEEPALIVE_COUNT_MAX; } });
62
+ Object.defineProperty(exports, "DEFAULT_KEEPALIVE_INTERVAL_MS", { enumerable: true, get: function () { return model_1.DEFAULT_KEEPALIVE_INTERVAL_MS; } });
63
+ Object.defineProperty(exports, "DEFAULT_READY_TIMEOUT_MS", { enumerable: true, get: function () { return model_1.DEFAULT_READY_TIMEOUT_MS; } });
64
+ Object.defineProperty(exports, "DEFAULT_RECONNECT_POLICY", { enumerable: true, get: function () { return model_1.DEFAULT_RECONNECT_POLICY; } });
65
+ Object.defineProperty(exports, "MODEL_VERSION", { enumerable: true, get: function () { return model_1.MODEL_VERSION; } });
66
+ // v1 compatibility. New code should use SSHTunnel.
67
+ var legacy_1 = require("./legacy");
68
+ Object.defineProperty(exports, "SSHTunnelProxy", { enumerable: true, get: function () { return legacy_1.SSHTunnelProxy; } });
69
+ Object.defineProperty(exports, "legacyConfigToTunnelConfig", { enumerable: true, get: function () { return legacy_1.legacyConfigToTunnelConfig; } });
70
+ Object.defineProperty(exports, "whitelistToPortPolicy", { enumerable: true, get: function () { return legacy_1.whitelistToPortPolicy; } });
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,mCAAqC;AAA5B,mGAAA,SAAS,OAAA;AAGlB,iDAAqD;AAA5C,mHAAA,kBAAkB,OAAA;AAC3B,mDAAuD;AAA9C,qHAAA,mBAAmB,OAAA;AAC5B,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAI1B,mCAAyF;AAAhF,4GAAA,kBAAkB,OAAA;AAAE,qGAAA,WAAW,OAAA;AAAE,uGAAA,aAAa,OAAA;AAAE,uGAAA,aAAa,OAAA;AAGtE,+CAWwB;AAVtB,sHAAA,sBAAsB,OAAA;AACtB,2HAAA,2BAA2B,OAAA;AAC3B,oHAAA,oBAAoB,OAAA;AACpB,qHAAA,qBAAqB,OAAA;AACrB,4HAAA,4BAA4B,OAAA;AAC5B,6HAAA,6BAA6B,OAAA;AAC7B,qHAAA,qBAAqB,OAAA;AACrB,sHAAA,sBAAsB,OAAA;AACtB,oHAAA,oBAAoB,OAAA;AACpB,qHAAA,qBAAqB,OAAA;AAGvB,6CAWuB;AAVrB,sHAAA,uBAAuB,OAAA;AACvB,uGAAA,QAAQ,OAAA;AACR,uGAAA,QAAQ,OAAA;AACR,gHAAA,iBAAiB,OAAA;AACjB,gHAAA,iBAAiB,OAAA;AACjB,wGAAA,SAAS,OAAA;AACT,8GAAA,eAAe,OAAA;AACf,0GAAA,WAAW,OAAA;AACX,0GAAA,WAAW,OAAA;AACX,wGAAA,SAAS,OAAA;AAIX,6CAA8F;AAArF,yGAAA,UAAU,OAAA;AAAE,yGAAA,UAAU,OAAA;AAAE,iHAAA,kBAAkB,OAAA;AAAE,gHAAA,iBAAiB,OAAA;AAGtE,iCAYiB;AAXf,0GAAA,iBAAiB,OAAA;AACjB,2GAAA,kBAAkB,OAAA;AAClB,2GAAA,kBAAkB,OAAA;AAClB,uGAAA,cAAc,OAAA;AACd,4GAAA,mBAAmB,OAAA;AACnB,sGAAA,aAAa,OAAA;AACb,oHAAA,2BAA2B,OAAA;AAC3B,sHAAA,6BAA6B,OAAA;AAC7B,iHAAA,wBAAwB,OAAA;AACxB,iHAAA,wBAAwB,OAAA;AACxB,sGAAA,aAAa,OAAA;AAsBf,mDAAmD;AACnD,mCAIkB;AAHhB,wGAAA,cAAc,OAAA;AACd,oHAAA,0BAA0B,OAAA;AAC1B,+GAAA,qBAAqB,OAAA"}
@@ -0,0 +1,70 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { Writable } from 'node:stream';
3
+ import type { Client } from 'ssh2';
4
+ import type { ForwardStatus, PortPolicy, TunnelConfig, TunnelStatus } from './model';
5
+ import { SSHTunnel } from './tunnel';
6
+ /** The v1 configuration object, minus the options that v2 removed. */
7
+ export interface LegacySSHConfig {
8
+ hostname?: string;
9
+ username: string;
10
+ password?: string;
11
+ host?: string;
12
+ port?: string | number;
13
+ proxy_ports?: string[];
14
+ remote_ports?: string[];
15
+ private_key?: string | null;
16
+ private_key_filename?: string | null;
17
+ whitelist?: Record<string, unknown> | null;
18
+ keepaliveInterval?: number;
19
+ server_name?: string;
20
+ disabled?: boolean;
21
+ /** Commands to run once the tunnel is up, as in v1. */
22
+ exec?: string[];
23
+ ngrok_api?: string;
24
+ service_name?: string;
25
+ shell?: boolean;
26
+ }
27
+ export declare function whitelistToPortPolicy(whitelist?: Record<string, unknown> | null): PortPolicy;
28
+ /** Translate a v1 config into a v2 {@link TunnelConfig}. */
29
+ export declare function legacyConfigToTunnelConfig(opts: LegacySSHConfig, whitelist?: Record<string, unknown> | null): TunnelConfig;
30
+ /**
31
+ * Drop-in replacement for the v1 class, implemented on top of {@link SSHTunnel}.
32
+ *
33
+ * New code should use SSHTunnel directly: it exposes forward ids, per-connection
34
+ * state, atomic multi-forward setup, and typed lifecycle events, none of which
35
+ * the v1 method names can express.
36
+ */
37
+ export declare class SSHTunnelProxy extends EventEmitter {
38
+ debug_en: boolean;
39
+ debug_ssh: boolean;
40
+ private tunnel?;
41
+ /** Kept for source compatibility; port policy is now explicit. */
42
+ validate_port_number(port: number, whitelist?: Record<string, unknown> | null): boolean;
43
+ /** Kept for source compatibility; throws a TunnelError on the first bad spec. */
44
+ validate_local_forward(proxy_ports?: string[] | null, whitelist?: Record<string, unknown> | null): boolean;
45
+ private announcedReady;
46
+ connectSSH(opts: LegacySSHConfig, whitelist?: Record<string, unknown> | null): Promise<void>;
47
+ /**
48
+ * v1 returned nothing here. v2 returns the resulting forward statuses, which is
49
+ * a superset: existing callers that ignore the return value are unaffected, and
50
+ * new code can read back the port a `0` bind was actually given.
51
+ */
52
+ setupProxyPorts(proxy_ports: string[]): Promise<ForwardStatus[]>;
53
+ setupRemotePorts(remote_ports: string[]): Promise<ForwardStatus[]>;
54
+ /**
55
+ * Like v1: with no streams supplied the output goes to this process's stdout and
56
+ * stderr. Unlike v1, the collected stdout is also returned.
57
+ */
58
+ execCmd(cmd: string, dataStream?: Writable, errStream?: Writable): Promise<string>;
59
+ getStatus(): TunnelStatus;
60
+ /** Escape hatch for code that reached into the ssh2 client directly. */
61
+ getClient(): Client;
62
+ /** The v2 tunnel behind this shim, for incremental migration. */
63
+ getTunnel(): SSHTunnel;
64
+ close(): Promise<void>;
65
+ /** v1 no-ops retained so existing Electron wiring keeps compiling. */
66
+ onNetworkOnline(): void;
67
+ onNetworkOffline(): void;
68
+ private requireTunnel;
69
+ }
70
+ //# sourceMappingURL=legacy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy.d.ts","sourceRoot":"","sources":["../src/legacy.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAKnC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAErF,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAGhB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAQD,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,UAAU,CAM5F;AAED,4DAA4D;AAC5D,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,eAAe,EACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACzC,YAAY,CA4Cd;AAED;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,YAAY;IACvC,QAAQ,UAAS;IACjB,SAAS,UAAS;IAEzB,OAAO,CAAC,MAAM,CAAC,CAAY;IAE3B,kEAAkE;IAC3D,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO;IAI9F,iFAAiF;IAC1E,sBAAsB,CAC3B,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACzC,OAAO;IASV,OAAO,CAAC,cAAc,CAAS;IAElB,UAAU,CACrB,IAAI,EAAE,eAAe,EACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACzC,OAAO,CAAC,IAAI,CAAC;IAqChB;;;;OAIG;IACU,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAIhE,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAI/E;;;OAGG;IACU,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxF,SAAS,IAAI,YAAY;IAIhC,wEAAwE;IACjE,SAAS,IAAI,MAAM;IAU1B,iEAAiE;IAC1D,SAAS,IAAI,SAAS;IAIhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAInC,sEAAsE;IAC/D,eAAe,IAAI,IAAI;IACvB,gBAAgB,IAAI,IAAI;IAE/B,OAAO,CAAC,aAAa;CAMtB"}
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ /*
3
+ * legacy.ts — v1 compatibility surface.
4
+ *
5
+ * Existing callers keep `proxy_ports` / `remote_ports` string arrays, the
6
+ * `whitelist` object, and the `ssh_tunnel_ready` / `status` events. Everything is
7
+ * translated into the v2 model and executed by SSHTunnel.
8
+ *
9
+ * Options that were removed rather than renamed throw immediately with a pointer
10
+ * to MIGRATION.md, so nobody silently loses key management or ngrok resolution.
11
+ *
12
+ * License: MIT
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.SSHTunnelProxy = void 0;
16
+ exports.whitelistToPortPolicy = whitelistToPortPolicy;
17
+ exports.legacyConfigToTunnelConfig = legacyConfigToTunnelConfig;
18
+ const node_events_1 = require("node:events");
19
+ const credentials_1 = require("./credentials");
20
+ const errors_1 = require("./errors");
21
+ const forward_spec_1 = require("./forward-spec");
22
+ const port_policy_1 = require("./port-policy");
23
+ const tunnel_1 = require("./tunnel");
24
+ const REMOVED_OPTIONS = [
25
+ ['ngrok_api', 'ngrok resolution was removed; point transport.endpoint at an existing SSH listener'],
26
+ ['service_name', 'system-keychain key storage was removed; use transport.privateKey with a file/env/callback ref'],
27
+ ['shell', 'interactive shell support was removed; use a terminal client'],
28
+ ];
29
+ function whitelistToPortPolicy(whitelist) {
30
+ if (!whitelist)
31
+ return {};
32
+ const ports = Object.keys(whitelist)
33
+ .map((key) => Number(key))
34
+ .filter((port) => Number.isInteger(port) && port > 0 && port < 1024);
35
+ return ports.length > 0 ? { allowedPrivilegedPorts: ports } : {};
36
+ }
37
+ /** Translate a v1 config into a v2 {@link TunnelConfig}. */
38
+ function legacyConfigToTunnelConfig(opts, whitelist) {
39
+ for (const [key, advice] of REMOVED_OPTIONS) {
40
+ if (opts[key] !== undefined && opts[key] !== null && opts[key] !== false) {
41
+ throw new errors_1.TunnelError('INVALID_FORWARD_SPEC', `Option "${String(key)}" is no longer supported in ssh_tunnel_proxy v2: ${advice}. See MIGRATION.md.`);
42
+ }
43
+ }
44
+ const host = opts.host ?? opts.hostname;
45
+ if (!host) {
46
+ throw new errors_1.TunnelError('INVALID_FORWARD_SPEC', 'A host (or hostname) is required');
47
+ }
48
+ const port = Number(opts.port ?? 22);
49
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
50
+ throw new errors_1.TunnelError('INVALID_FORWARD_SPEC', `Invalid SSH port: ${String(opts.port)}`);
51
+ }
52
+ const config = {
53
+ id: opts.server_name ?? `${host}:${port}`,
54
+ transport: {
55
+ endpoint: { host, port },
56
+ username: opts.username,
57
+ keepaliveIntervalMs: opts.keepaliveInterval,
58
+ },
59
+ portPolicy: whitelistToPortPolicy(whitelist ?? opts.whitelist),
60
+ };
61
+ // proxy_ports / remote_ports stay as spec strings and are handed to
62
+ // SSHTunnel.addLocalForwards / addRemoteForwards after connect, so the v1
63
+ // string syntax has exactly one parser.
64
+ if (opts.private_key_filename) {
65
+ config.transport.privateKey = credentials_1.credential.file(opts.private_key_filename);
66
+ }
67
+ else if (opts.private_key) {
68
+ config.transport.privateKey = credentials_1.credential.inline(opts.private_key);
69
+ }
70
+ if (opts.password && opts.password.length > 0) {
71
+ config.transport.password = credentials_1.credential.inline(opts.password);
72
+ }
73
+ return config;
74
+ }
75
+ /**
76
+ * Drop-in replacement for the v1 class, implemented on top of {@link SSHTunnel}.
77
+ *
78
+ * New code should use SSHTunnel directly: it exposes forward ids, per-connection
79
+ * state, atomic multi-forward setup, and typed lifecycle events, none of which
80
+ * the v1 method names can express.
81
+ */
82
+ class SSHTunnelProxy extends node_events_1.EventEmitter {
83
+ debug_en = false;
84
+ debug_ssh = false;
85
+ tunnel;
86
+ /** Kept for source compatibility; port policy is now explicit. */
87
+ validate_port_number(port, whitelist) {
88
+ return (0, port_policy_1.checkPort)(port, 'remote-target', whitelistToPortPolicy(whitelist)).allowed;
89
+ }
90
+ /** Kept for source compatibility; throws a TunnelError on the first bad spec. */
91
+ validate_local_forward(proxy_ports, whitelist) {
92
+ if (!proxy_ports)
93
+ return true;
94
+ const policy = whitelistToPortPolicy(whitelist);
95
+ for (const spec of proxy_ports) {
96
+ (0, forward_spec_1.parseAndValidateLocalForward)(spec, policy);
97
+ }
98
+ return true;
99
+ }
100
+ announcedReady = false;
101
+ async connectSSH(opts, whitelist) {
102
+ const config = legacyConfigToTunnelConfig(opts, whitelist);
103
+ const tunnel = new tunnel_1.SSHTunnel(config, { debugSsh: this.debug_ssh });
104
+ this.tunnel = tunnel;
105
+ tunnel.on('debug', (message, ...args) => {
106
+ if (this.debug_en)
107
+ console.log(message, ...args);
108
+ this.emit('debug', message, ...args);
109
+ });
110
+ tunnel.on('error', (error) => this.emit('error', error));
111
+ tunnel.on('ready', (status) => {
112
+ this.emit('status', '', 'ready', `${status.endpoint.host}:${status.endpoint.port}`);
113
+ // v1 signalled readiness once the forwards were usable. On the first connect
114
+ // that happens below, after the ports are set up; on a reconnect the forwards
115
+ // are re-established before `ready`, so signal again here.
116
+ if (this.announcedReady)
117
+ this.emit('ssh_tunnel_ready', {});
118
+ });
119
+ tunnel.on('close', () => this.emit('status', '', 'closed', ''));
120
+ await tunnel.connect();
121
+ if (opts.proxy_ports && opts.proxy_ports.length > 0) {
122
+ await tunnel.addLocalForwards(opts.proxy_ports);
123
+ }
124
+ if (opts.remote_ports && opts.remote_ports.length > 0) {
125
+ await tunnel.addRemoteForwards(opts.remote_ports);
126
+ }
127
+ this.announcedReady = true;
128
+ this.emit('ssh_tunnel_ready', {});
129
+ // v1 ran `opts.exec` commands once the tunnel was up.
130
+ for (const cmd of opts.exec ?? []) {
131
+ await this.execCmd(cmd);
132
+ }
133
+ }
134
+ /**
135
+ * v1 returned nothing here. v2 returns the resulting forward statuses, which is
136
+ * a superset: existing callers that ignore the return value are unaffected, and
137
+ * new code can read back the port a `0` bind was actually given.
138
+ */
139
+ async setupProxyPorts(proxy_ports) {
140
+ return this.requireTunnel().addLocalForwards(proxy_ports);
141
+ }
142
+ async setupRemotePorts(remote_ports) {
143
+ return this.requireTunnel().addRemoteForwards(remote_ports);
144
+ }
145
+ /**
146
+ * Like v1: with no streams supplied the output goes to this process's stdout and
147
+ * stderr. Unlike v1, the collected stdout is also returned.
148
+ */
149
+ async execCmd(cmd, dataStream, errStream) {
150
+ const result = await this.requireTunnel().exec(cmd, {
151
+ stdout: dataStream ?? process.stdout,
152
+ stderr: errStream ?? process.stderr,
153
+ });
154
+ return result.stdout;
155
+ }
156
+ getStatus() {
157
+ return this.requireTunnel().getStatus();
158
+ }
159
+ /** Escape hatch for code that reached into the ssh2 client directly. */
160
+ getClient() {
161
+ const tunnel = this.requireTunnel();
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
+ const client = tunnel.client;
164
+ if (!client) {
165
+ throw new errors_1.TunnelError('TRANSPORT_NOT_READY', 'No SSH client; call connectSSH first');
166
+ }
167
+ return client;
168
+ }
169
+ /** The v2 tunnel behind this shim, for incremental migration. */
170
+ getTunnel() {
171
+ return this.requireTunnel();
172
+ }
173
+ async close() {
174
+ if (this.tunnel)
175
+ await this.tunnel.close();
176
+ }
177
+ /** v1 no-ops retained so existing Electron wiring keeps compiling. */
178
+ onNetworkOnline() { }
179
+ onNetworkOffline() { }
180
+ requireTunnel() {
181
+ if (!this.tunnel) {
182
+ throw new errors_1.TunnelError('TRANSPORT_NOT_READY', 'Call connectSSH before using the tunnel');
183
+ }
184
+ return this.tunnel;
185
+ }
186
+ }
187
+ exports.SSHTunnelProxy = SSHTunnelProxy;
188
+ //# sourceMappingURL=legacy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy.js","sourceRoot":"","sources":["../src/legacy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { TransportBridge } from './bridge';
2
+ import type { ForwardState, ForwardStatus, LocalForward } from './model';
3
+ export declare class LocalForwardHandle {
4
+ readonly forwardId: string;
5
+ readonly spec: LocalForward;
6
+ private state;
7
+ private server?;
8
+ private lastError?;
9
+ private totalConnections;
10
+ private readonly connections;
11
+ private readonly bridge;
12
+ private readonly idleTimeoutMs;
13
+ constructor(spec: LocalForward, bridge: TransportBridge, idleTimeoutMs?: number);
14
+ getState(): ForwardState;
15
+ getStatus(): ForwardStatus;
16
+ listConnections(): import("./model").ConnectionStatus[];
17
+ /** Bind the local listener. Resolves once the port is actually listening. */
18
+ open(): Promise<ForwardStatus>;
19
+ /**
20
+ * Mark the forward as degraded: the listener stays bound so callers do not see
21
+ * connection-refused during a reconnect, but new connections fail fast until
22
+ * the transport returns.
23
+ */
24
+ markDegraded(reason: string): void;
25
+ markActive(): void;
26
+ close(): Promise<ForwardStatus>;
27
+ private closeConnections;
28
+ private handleSocket;
29
+ private transition;
30
+ }
31
+ //# sourceMappingURL=local-forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-forward.d.ts","sourceRoot":"","sources":["../src/local-forward.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAIhD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEzE,qBAAa,kBAAkB;IAC7B,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,IAAI,EAAE,YAAY,CAAC;IAEnC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwC;IACpE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;gBAE3B,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,SAAI;IAOnE,QAAQ,IAAI,YAAY;IAIxB,SAAS,IAAI,aAAa;IAc1B,eAAe;IAItB,6EAA6E;IAChE,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;IAkE3C;;;;OAIG;IACI,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOlC,UAAU,IAAI,IAAI;IAOZ,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC;IAmB5C,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,YAAY;IA+GpB,OAAO,CAAC,UAAU;CAMnB"}