@tmlmobilidade/ssh 20251202.1817.5

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.
@@ -0,0 +1,49 @@
1
+ import { type Server } from 'node:net';
2
+ import { type ForwardOptions, type ServerOptions, type SshOptions, type TunnelOptions } from 'tunnel-ssh';
3
+ export interface SshConfig {
4
+ forwardOptions: ForwardOptions;
5
+ serverOptions: ServerOptions;
6
+ sshOptions: SshOptions;
7
+ tunnelOptions: TunnelOptions;
8
+ }
9
+ export interface SshTunnelServiceOptions {
10
+ maxRetries?: number;
11
+ }
12
+ export declare class SshTunnelService {
13
+ private static _instance;
14
+ get server(): Server | undefined;
15
+ private _server;
16
+ private config;
17
+ private options;
18
+ private retries;
19
+ constructor(config: SshConfig, options?: SshTunnelServiceOptions);
20
+ /**
21
+ * Get the singleton instance of SshTunnelService.
22
+ */
23
+ static getInstance(config?: SshConfig, options?: SshTunnelServiceOptions): SshTunnelService;
24
+ /**
25
+ * Establishes an SSH tunnel connection using the provided configuration options.
26
+ * @throws Throws an error if the connection fails after the maximum number of retries.
27
+ * @remarks
28
+ * - The method attempts to create an SSH tunnel using the `createTunnel` function with the specified options.
29
+ * - If the connection is successful, it logs the connected host port and sets up an error listener on the server.
30
+ * - If the connection fails, it retries the connection up to a maximum number of retries specified in the options.
31
+ * @example ```typescript
32
+ * const sshTunnelService = new SshTunnelService(config);
33
+ * sshTunnelService.connect();
34
+ * ```
35
+ */
36
+ connect(): any;
37
+ /**
38
+ * Disconnects the SSH tunnel by closing the server.
39
+ * @returns A promise that resolves when the server is successfully closed.
40
+ * @throws Will log an error message if the server fails to close.
41
+ */
42
+ disconnect(): Promise<void>;
43
+ /**
44
+ * Reconnects the SSH tunnel by first disconnecting and then connecting again.
45
+ * This method ensures that the connection is reset.
46
+ * @returns A promise that resolves when the reconnection process is complete.
47
+ */
48
+ reconnect(): Promise<void>;
49
+ }
package/dist/index.js ADDED
@@ -0,0 +1,101 @@
1
+ /* * */
2
+ import { Logger } from '@tmlmobilidade/logger';
3
+ import { createTunnel } from 'tunnel-ssh';
4
+ /* * */
5
+ export class SshTunnelService {
6
+ static _instance;
7
+ get server() {
8
+ return this._server;
9
+ }
10
+ _server;
11
+ config;
12
+ options;
13
+ retries = 0;
14
+ constructor(config, options) {
15
+ this.config = config;
16
+ if (options)
17
+ this.options = options;
18
+ }
19
+ /**
20
+ * Get the singleton instance of SshTunnelService.
21
+ */
22
+ static getInstance(config, options) {
23
+ if (!SshTunnelService._instance) {
24
+ if (!config) {
25
+ throw new Error('SSH Config is required');
26
+ }
27
+ SshTunnelService._instance = new SshTunnelService(config, options);
28
+ }
29
+ return SshTunnelService._instance;
30
+ }
31
+ /**
32
+ * Establishes an SSH tunnel connection using the provided configuration options.
33
+ * @throws Throws an error if the connection fails after the maximum number of retries.
34
+ * @remarks
35
+ * - The method attempts to create an SSH tunnel using the `createTunnel` function with the specified options.
36
+ * - If the connection is successful, it logs the connected host port and sets up an error listener on the server.
37
+ * - If the connection fails, it retries the connection up to a maximum number of retries specified in the options.
38
+ * @example ```typescript
39
+ * const sshTunnelService = new SshTunnelService(config);
40
+ * sshTunnelService.connect();
41
+ * ```
42
+ */
43
+ async connect() {
44
+ try {
45
+ if (this._server) {
46
+ // If the server is already connected, return it
47
+ console.log(`⤷ SSH Tunnel already connected.`);
48
+ return this._server;
49
+ }
50
+ const [server] = await createTunnel(this.config.tunnelOptions, this.config.serverOptions, this.config.sshOptions, this.config.forwardOptions);
51
+ Logger.info(`SSH Tunnel connected to host port ${server.address().port}`);
52
+ this._server = server;
53
+ server.on('error', (error) => {
54
+ Logger.error(`SSH Tunnel Error`, error);
55
+ });
56
+ server.on('close', () => {
57
+ Logger.info('SSH Tunnel closed.');
58
+ });
59
+ return this._server;
60
+ }
61
+ catch (error) {
62
+ if (error.code === 'EADDRINUSE') {
63
+ Logger.info(`Port "${this.config.serverOptions.port}" already in use. Retrying with a different port...`);
64
+ this.config.serverOptions.port++;
65
+ return await this.connect();
66
+ }
67
+ else if (this.retries < (this.options?.maxRetries || 3)) {
68
+ Logger.error(`Failed to connect to SSH Tunnel.`, error);
69
+ this.retries++;
70
+ Logger.info('Retrying SSH connection...');
71
+ return await this.connect();
72
+ }
73
+ else {
74
+ throw new Error('Error connecting to SSH tunnel', error);
75
+ }
76
+ }
77
+ }
78
+ /**
79
+ * Disconnects the SSH tunnel by closing the server.
80
+ * @returns A promise that resolves when the server is successfully closed.
81
+ * @throws Will log an error message if the server fails to close.
82
+ */
83
+ async disconnect() {
84
+ try {
85
+ this._server.close();
86
+ console.log(`⤷ SSH Tunnel disconnected.`);
87
+ }
88
+ catch (error) {
89
+ console.log(`⤷ ERROR: Failed to disconnect from SSH Tunnel.`, error);
90
+ }
91
+ }
92
+ /**
93
+ * Reconnects the SSH tunnel by first disconnecting and then connecting again.
94
+ * This method ensures that the connection is reset.
95
+ * @returns A promise that resolves when the reconnection process is complete.
96
+ */
97
+ async reconnect() {
98
+ await this.disconnect();
99
+ this.connect();
100
+ }
101
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@tmlmobilidade/ssh",
3
+ "version": "20251202.1817.5",
4
+ "author": {
5
+ "email": "iso@tmlmobilidade.pt",
6
+ "name": "TML-ISO"
7
+ },
8
+ "license": "AGPL-3.0-or-later",
9
+ "homepage": "https://github.com/tmlmobilidade/go#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/tmlmobilidade/go/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/tmlmobilidade/go.git"
16
+ },
17
+ "keywords": [
18
+ "public transit",
19
+ "tml",
20
+ "transportes metropolitanos de lisboa",
21
+ "go"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "scripts": {
33
+ "build": "tsc && resolve-tspaths",
34
+ "lint": "eslint ./src/ && tsc --noEmit",
35
+ "lint:fix": "eslint ./src/ --fix",
36
+ "watch": "tsc-watch --onSuccess 'resolve-tspaths'"
37
+ },
38
+ "dependencies": {
39
+ "@tmlmobilidade/logger": "*",
40
+ "tunnel-ssh": "5.2.0"
41
+ },
42
+ "devDependencies": {
43
+ "@tmlmobilidade/tsconfig": "*",
44
+ "@types/node": "24.10.1",
45
+ "resolve-tspaths": "0.8.23",
46
+ "tsc-watch": "7.2.0",
47
+ "typescript": "5.9.3"
48
+ }
49
+ }