@forestadmin/datasource-sql 1.6.10 → 1.7.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.
- package/dist/connection/connection-options.d.ts +3 -3
- package/dist/connection/connection-options.js +8 -6
- package/dist/connection/connection-tester.d.ts +1 -0
- package/dist/connection/connection-tester.js +14 -6
- package/dist/connection/errors.d.ts +15 -3
- package/dist/connection/errors.js +32 -8
- package/dist/connection/handle-errors.js +18 -17
- package/dist/connection/index.js +33 -19
- package/dist/connection/sequelize-factory.d.ts +8 -0
- package/dist/connection/sequelize-factory.js +26 -0
- package/dist/connection/services/reverse-proxy.d.ts +15 -10
- package/dist/connection/services/reverse-proxy.js +50 -45
- package/dist/connection/services/service.d.ts +23 -12
- package/dist/connection/services/service.js +45 -13
- package/dist/connection/services/socks-proxy.d.ts +10 -0
- package/dist/connection/services/socks-proxy.js +47 -0
- package/dist/connection/services/ssh-tunnel.d.ts +14 -0
- package/dist/connection/services/ssh-tunnel.js +73 -0
- package/dist/types.d.ts +4 -0
- package/package.json +4 -2
- package/dist/connection/services/sequelize-factory.d.ts +0 -8
- package/dist/connection/services/sequelize-factory.js +0 -30
- package/dist/connection/services/tcp-server.d.ts +0 -12
- package/dist/connection/services/tcp-server.js +0 -48
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Logger } from '@forestadmin/datasource-toolkit';
|
|
2
2
|
import { Dialect, Options as SequelizeOptions } from 'sequelize';
|
|
3
|
-
import { PlainConnectionOptions, PlainConnectionOptionsOrUri, ProxyOptions } from '../types';
|
|
3
|
+
import { PlainConnectionOptions, PlainConnectionOptionsOrUri, ProxyOptions, SshOptions } from '../types';
|
|
4
4
|
/**
|
|
5
5
|
* Connection options.
|
|
6
6
|
* This wrapper is constructed from a plain object or a URI string.
|
|
@@ -13,6 +13,8 @@ import { PlainConnectionOptions, PlainConnectionOptionsOrUri, ProxyOptions } fro
|
|
|
13
13
|
*/
|
|
14
14
|
export default class ConnectionOptions {
|
|
15
15
|
proxyOptions?: ProxyOptions;
|
|
16
|
+
sshOptions?: SshOptions;
|
|
17
|
+
connectionTimeoutInMs?: number;
|
|
16
18
|
private initialHost;
|
|
17
19
|
private initialPort;
|
|
18
20
|
private logger?;
|
|
@@ -24,8 +26,6 @@ export default class ConnectionOptions {
|
|
|
24
26
|
* Ensure that this is never substituted by the proxy, nor that it includes credentials.
|
|
25
27
|
*/
|
|
26
28
|
get debugDatabaseUri(): string;
|
|
27
|
-
/** Proxy URI without credentials, which can be used in error messages INTERNALLY */
|
|
28
|
-
get debugProxyUri(): string;
|
|
29
29
|
get dialect(): Dialect;
|
|
30
30
|
get host(): string;
|
|
31
31
|
get port(): number;
|
|
@@ -28,10 +28,6 @@ class ConnectionOptions {
|
|
|
28
28
|
? this.uri?.href ?? `sqlite:${this.sequelizeOptions.storage}`
|
|
29
29
|
: `${dialect}://${this.initialHost}:${port}/${database}`;
|
|
30
30
|
}
|
|
31
|
-
/** Proxy URI without credentials, which can be used in error messages INTERNALLY */
|
|
32
|
-
get debugProxyUri() {
|
|
33
|
-
return this.proxyOptions ? `tcp://${this.proxyOptions.host}:${this.proxyOptions.port}` : 'none';
|
|
34
|
-
}
|
|
35
31
|
get dialect() {
|
|
36
32
|
let dialect = this.uri?.protocol?.slice(0, -1) || this.sequelizeOptions.dialect;
|
|
37
33
|
if (dialect === 'mysql2')
|
|
@@ -67,6 +63,10 @@ class ConnectionOptions {
|
|
|
67
63
|
options.uri = this.uri.toString();
|
|
68
64
|
if (this.proxyOptions)
|
|
69
65
|
options.proxySocks = this.proxyOptions;
|
|
66
|
+
if (this.sshOptions)
|
|
67
|
+
options.ssh = this.sshOptions;
|
|
68
|
+
if (this.connectionTimeoutInMs)
|
|
69
|
+
options.connectionTimeoutInMs = this.connectionTimeoutInMs;
|
|
70
70
|
options.dialect = this.dialect;
|
|
71
71
|
options.sslMode = this.sslMode;
|
|
72
72
|
return options;
|
|
@@ -78,8 +78,10 @@ class ConnectionOptions {
|
|
|
78
78
|
this.sequelizeOptions = {};
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
const { uri, sslMode, proxySocks, ...sequelizeOptions } = options;
|
|
81
|
+
const { uri, sslMode, proxySocks, ssh, connectionTimeoutInMs, ...sequelizeOptions } = options;
|
|
82
82
|
this.proxyOptions = proxySocks;
|
|
83
|
+
this.sshOptions = ssh;
|
|
84
|
+
this.connectionTimeoutInMs = connectionTimeoutInMs;
|
|
83
85
|
this.sequelizeOptions = sequelizeOptions;
|
|
84
86
|
this.sslMode = sslMode ?? 'manual';
|
|
85
87
|
this.uri = uri ? this.parseDatabaseUri(uri) : null;
|
|
@@ -229,4 +231,4 @@ class ConnectionOptions {
|
|
|
229
231
|
}
|
|
230
232
|
}
|
|
231
233
|
exports.default = ConnectionOptions;
|
|
232
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
234
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi1vcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Nvbm5lY3Rpb24vY29ubmVjdGlvbi1vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBR0EscUNBQWdEO0FBQ2hELG9EQUE4QjtBQVM5Qjs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFxQixpQkFBaUI7SUFZcEM7OztPQUdHO0lBQ0gsSUFBSSxnQkFBZ0I7UUFDbEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sSUFBSSxHQUFHLENBQUM7UUFDcEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSxHQUFHLENBQUM7UUFDckMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsSUFBSSxHQUFHLENBQUM7UUFFdEMsT0FBTyxPQUFPLEtBQUssUUFBUTtZQUN6QixDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksVUFBVSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFO1lBQzdELENBQUMsQ0FBQyxHQUFHLE9BQU8sTUFBTSxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksSUFBSSxRQUFRLEVBQUUsQ0FBQztJQUM3RCxDQUFDO0lBRUQsSUFBSSxPQUFPO1FBQ1QsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFDaEYsSUFBSSxPQUFPLEtBQUssUUFBUTtZQUFFLE9BQU8sR0FBRyxPQUFPLENBQUM7YUFDdkMsSUFBSSxPQUFPLEtBQUssU0FBUztZQUFFLE9BQU8sR0FBRyxPQUFPLENBQUM7YUFDN0MsSUFBSSxPQUFPLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxZQUFZO1lBQUUsT0FBTyxHQUFHLFVBQVUsQ0FBQztRQUU1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
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { Sequelize } from 'sequelize';
|
|
2
|
+
/** Test connection. If this doesn't resolve after 10s, throw a timeout error */
|
|
2
3
|
export default function testConnectionWithTimeOut(sequelize: Sequelize, databaseUri: string, timeout?: number): Promise<void>;
|
|
3
4
|
//# sourceMappingURL=connection-tester.d.ts.map
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const errors_1 = require("./errors");
|
|
4
|
+
/** Test connection. If this doesn't resolve after 10s, throw a timeout error */
|
|
4
5
|
async function testConnectionWithTimeOut(sequelize, databaseUri, timeout = 10000) {
|
|
5
|
-
|
|
6
|
-
const timeoutPromise = new Promise(resolve => {
|
|
7
|
-
setTimeout(
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
let timeoutId;
|
|
7
|
+
const timeoutPromise = new Promise((resolve, reject) => {
|
|
8
|
+
timeoutId = setTimeout(() => {
|
|
9
|
+
reject(new errors_1.DatabaseConnectError('Connection to database timed out', databaseUri));
|
|
10
|
+
}, timeout);
|
|
11
|
+
});
|
|
12
|
+
await Promise.race([
|
|
13
|
+
sequelize.authenticate()?.finally(() => {
|
|
14
|
+
clearTimeout(timeoutId);
|
|
15
|
+
}),
|
|
16
|
+
timeoutPromise,
|
|
17
|
+
]);
|
|
10
18
|
}
|
|
11
19
|
exports.default = testConnectionWithTimeOut;
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi10ZXN0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29ubmVjdGlvbi9jb25uZWN0aW9uLXRlc3Rlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLHFDQUFnRDtBQUVoRCxnRkFBZ0Y7QUFDakUsS0FBSyxVQUFVLHlCQUF5QixDQUNyRCxTQUFvQixFQUNwQixXQUFtQixFQUNuQixPQUFPLEdBQUcsS0FBSztJQUVmLElBQUksU0FBUyxDQUFDO0lBRWQsTUFBTSxjQUFjLEdBQUcsSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckQsU0FBUyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDMUIsTUFBTSxDQUFDLElBQUksNkJBQW9CLENBQUMsa0NBQWtDLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNwRixDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDZCxDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztRQUNqQixTQUFTLENBQUMsWUFBWSxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsRUFBRTtZQUNyQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUIsQ0FBQyxDQUFDO1FBQ0YsY0FBYztLQUNmLENBQUMsQ0FBQztBQUNMLENBQUM7QUFuQkQsNENBbUJDIn0=
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export type ErrorSource = 'Proxy' | 'Database';
|
|
1
|
+
export type ErrorSource = 'Proxy' | 'Database' | 'Ssh';
|
|
2
2
|
declare abstract class BaseError extends Error {
|
|
3
3
|
abstract readonly source: ErrorSource;
|
|
4
|
-
readonly
|
|
4
|
+
readonly debugUri: string;
|
|
5
5
|
readonly details: string;
|
|
6
|
-
constructor(message: string,
|
|
6
|
+
protected constructor(message: string, debugUri: string, details?: string);
|
|
7
7
|
}
|
|
8
8
|
export declare class DatabaseConnectError extends BaseError {
|
|
9
9
|
readonly source: ErrorSource;
|
|
@@ -13,5 +13,17 @@ export declare class ProxyConnectError extends BaseError {
|
|
|
13
13
|
readonly source = "Proxy";
|
|
14
14
|
constructor(message: string, debugProxyUri: string);
|
|
15
15
|
}
|
|
16
|
+
export declare class ProxyForwardError extends BaseError {
|
|
17
|
+
readonly source = "Proxy";
|
|
18
|
+
constructor(message: string, debugForwardedUri: string);
|
|
19
|
+
}
|
|
20
|
+
export declare class SshConnectError extends BaseError {
|
|
21
|
+
readonly source: ErrorSource;
|
|
22
|
+
constructor(message: string, debugSshUri: string, source?: ErrorSource);
|
|
23
|
+
}
|
|
24
|
+
export declare class SshForwardError extends BaseError {
|
|
25
|
+
readonly source = "Ssh";
|
|
26
|
+
constructor(message: string, debugForwardedUri: string);
|
|
27
|
+
}
|
|
16
28
|
export {};
|
|
17
29
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1,29 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable max-classes-per-file */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.ProxyConnectError = exports.DatabaseConnectError = void 0;
|
|
4
|
+
exports.SshForwardError = exports.SshConnectError = exports.ProxyForwardError = exports.ProxyConnectError = exports.DatabaseConnectError = void 0;
|
|
5
5
|
class BaseError extends Error {
|
|
6
|
-
constructor(message,
|
|
6
|
+
constructor(message, debugUri, details) {
|
|
7
7
|
super(details ? `${message}\n${details}` : message);
|
|
8
8
|
this.name = this.constructor.name;
|
|
9
9
|
this.details = details;
|
|
10
|
-
this.
|
|
10
|
+
this.debugUri = debugUri;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
class DatabaseConnectError extends BaseError {
|
|
14
14
|
constructor(message, debugDatabaseUri, source = 'Database') {
|
|
15
|
-
|
|
15
|
+
// remove tcp protocol because its not added by the user
|
|
16
|
+
const sanitizedUri = debugDatabaseUri.replace('tcp://', '');
|
|
17
|
+
super(`Unable to connect to the given uri: ${sanitizedUri}.`, sanitizedUri, message);
|
|
16
18
|
this.source = source;
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
exports.DatabaseConnectError = DatabaseConnectError;
|
|
20
22
|
class ProxyConnectError extends BaseError {
|
|
21
23
|
constructor(message, debugProxyUri) {
|
|
22
|
-
|
|
23
|
-
const sanitizedUri = debugProxyUri.replace('tcp://', '');
|
|
24
|
-
super(`Your proxy has encountered an error. Unable to connect to the given uri: ${sanitizedUri}.`, sanitizedUri, message);
|
|
24
|
+
super(`Your proxy has encountered an error. Unable to connect to the given uri: ${debugProxyUri}.`, debugProxyUri, message);
|
|
25
25
|
this.source = 'Proxy';
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
exports.ProxyConnectError = ProxyConnectError;
|
|
29
|
-
|
|
29
|
+
class ProxyForwardError extends BaseError {
|
|
30
|
+
constructor(message, debugForwardedUri) {
|
|
31
|
+
super(`Your proxy forwarded connection has encountered an error.` +
|
|
32
|
+
`Unable to connect to the given uri: ${debugForwardedUri}.`, debugForwardedUri, message);
|
|
33
|
+
this.source = 'Proxy';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.ProxyForwardError = ProxyForwardError;
|
|
37
|
+
class SshConnectError extends BaseError {
|
|
38
|
+
constructor(message, debugSshUri, source = 'Ssh') {
|
|
39
|
+
super(`Your ssh connection has encountered an error. ` +
|
|
40
|
+
`Unable to connect to the given ssh uri: ${debugSshUri}`, debugSshUri, message);
|
|
41
|
+
this.source = source;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.SshConnectError = SshConnectError;
|
|
45
|
+
class SshForwardError extends BaseError {
|
|
46
|
+
constructor(message, debugForwardedUri) {
|
|
47
|
+
super(`Your ssh forward connection has encountered an error. ` +
|
|
48
|
+
`Unable to connect to the given ssh uri: ${debugForwardedUri}`, debugForwardedUri, message);
|
|
49
|
+
this.source = 'Ssh';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.SshForwardError = SshForwardError;
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Nvbm5lY3Rpb24vZXJyb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx5Q0FBeUM7OztBQUl6QyxNQUFlLFNBQVUsU0FBUSxLQUFLO0lBS3BDLFlBQXNCLE9BQWUsRUFBRSxRQUFnQixFQUFFLE9BQWdCO1FBQ3ZFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxLQUFLLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVwRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzNCLENBQUM7Q0FDRjtBQUVELE1BQWEsb0JBQXFCLFNBQVEsU0FBUztJQUdqRCxZQUFZLE9BQWUsRUFBRSxnQkFBd0IsRUFBRSxTQUFzQixVQUFVO1FBQ3JGLHdEQUF3RDtRQUN4RCxNQUFNLFlBQVksR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzVELEtBQUssQ0FBQyx1Q0FBdUMsWUFBWSxHQUFHLEVBQUUsWUFBWSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXJGLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7Q0FDRjtBQVZELG9EQVVDO0FBRUQsTUFBYSxpQkFBa0IsU0FBUSxTQUFTO0lBRzlDLFlBQVksT0FBZSxFQUFFLGFBQXFCO1FBQ2hELEtBQUssQ0FDSCw0RUFBNEUsYUFBYSxHQUFHLEVBQzVGLGFBQWEsRUFDYixPQUFPLENBQ1IsQ0FBQztRQVBLLFdBQU0sR0FBRyxPQUFPLENBQUM7SUFRMUIsQ0FBQztDQUNGO0FBVkQsOENBVUM7QUFFRCxNQUFhLGlCQUFrQixTQUFRLFNBQVM7SUFHOUMsWUFBWSxPQUFlLEVBQUUsaUJBQXlCO1FBQ3BELEtBQUssQ0FDSCwyREFBMkQ7WUFDekQsdUNBQXVDLGlCQUFpQixHQUFHLEVBQzdELGlCQUFpQixFQUNqQixPQUFPLENBQ1IsQ0FBQztRQVJLLFdBQU0sR0FBRyxPQUFPLENBQUM7SUFTMUIsQ0FBQztDQUNGO0FBWEQsOENBV0M7QUFFRCxNQUFhLGVBQWdCLFNBQVEsU0FBUztJQUc1QyxZQUFZLE9BQWUsRUFBRSxXQUFtQixFQUFFLFNBQXNCLEtBQUs7UUFDM0UsS0FBSyxDQUNILGdEQUFnRDtZQUM5QywyQ0FBMkMsV0FBVyxFQUFFLEVBQzFELFdBQVcsRUFDWCxPQUFPLENBQ1IsQ0FBQztRQUNGLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7Q0FDRjtBQVpELDBDQVlDO0FBRUQsTUFBYSxlQUFnQixTQUFRLFNBQVM7SUFHNUMsWUFBWSxPQUFlLEVBQUUsaUJBQXlCO1FBQ3BELEtBQUssQ0FDSCx3REFBd0Q7WUFDdEQsMkNBQTJDLGlCQUFpQixFQUFFLEVBQ2hFLGlCQUFpQixFQUNqQixPQUFPLENBQ1IsQ0FBQztRQVJLLFdBQU0sR0FBRyxLQUFLLENBQUM7SUFTeEIsQ0FBQztDQUNGO0FBWEQsMENBV0MifQ==
|
|
@@ -2,27 +2,28 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const sequelize_1 = require("sequelize");
|
|
4
4
|
const errors_1 = require("./errors");
|
|
5
|
-
function handleProxyErrors(error, options) {
|
|
6
|
-
/** @see https://github.com/JoshGlazebrook/socks/blob/76d013/src/common/constants.ts#L10 */
|
|
7
|
-
if (error.message.includes('Socket closed') ||
|
|
8
|
-
error.message.includes('Socks5 proxy rejected connection')) {
|
|
9
|
-
throw new errors_1.DatabaseConnectError(null, options.debugDatabaseUri, 'Proxy');
|
|
10
|
-
}
|
|
11
|
-
throw new errors_1.ProxyConnectError(error.message, options.debugProxyUri);
|
|
12
|
-
}
|
|
13
|
-
function handleSequelizeError(error, options) {
|
|
14
|
-
const nameWithoutSequelize = error.name.replace('Sequelize', '');
|
|
15
|
-
const nameWithSpaces = nameWithoutSequelize.replace(/([a-z])([A-Z])/g, (_, m1, m2) => `${m1} ${m2.toLowerCase()}`);
|
|
16
|
-
throw new errors_1.DatabaseConnectError(`${nameWithSpaces}: ${error.message}`, options.debugDatabaseUri);
|
|
17
|
-
}
|
|
18
5
|
function handleErrors(error, options) {
|
|
19
|
-
if (error
|
|
20
|
-
|
|
6
|
+
if (error instanceof errors_1.ProxyForwardError) {
|
|
7
|
+
// means that the ssh is not reachable
|
|
8
|
+
if (options.sshOptions) {
|
|
9
|
+
throw new errors_1.SshConnectError(null, error.debugUri, 'Proxy');
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
// if there is no sshOptions, then the database is the destination and
|
|
13
|
+
// it means that the database is not reachable
|
|
14
|
+
throw new errors_1.DatabaseConnectError(null, error.debugUri, 'Proxy');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// it means that the database is not reachable
|
|
18
|
+
if (error instanceof errors_1.SshForwardError) {
|
|
19
|
+
throw new errors_1.DatabaseConnectError(null, error.debugUri, 'Ssh');
|
|
21
20
|
}
|
|
22
21
|
if (error instanceof sequelize_1.BaseError) {
|
|
23
|
-
|
|
22
|
+
const nameWithoutSequelize = error.name.replace('Sequelize', '');
|
|
23
|
+
const nameWithSpaces = nameWithoutSequelize.replace(/([a-z])([A-Z])/g, (_, m1, m2) => `${m1} ${m2.toLowerCase()}`);
|
|
24
|
+
throw new errors_1.DatabaseConnectError(`${nameWithSpaces}: ${error.message}`, options.debugDatabaseUri);
|
|
24
25
|
}
|
|
25
26
|
throw error;
|
|
26
27
|
}
|
|
27
28
|
exports.default = handleErrors;
|
|
28
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlLWVycm9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25uZWN0aW9uL2hhbmRsZS1lcnJvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSx5Q0FBd0Q7QUFHeEQscUNBS2tCO0FBRWxCLFNBQXdCLFlBQVksQ0FBQyxLQUFZLEVBQUUsT0FBMEI7SUFDM0UsSUFBSSxLQUFLLFlBQVksMEJBQWlCLEVBQUU7UUFDdEMsc0NBQXNDO1FBQ3RDLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRTtZQUN0QixNQUFNLElBQUksd0JBQWUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUMxRDthQUFNO1lBQ0wsc0VBQXNFO1lBQ3RFLDhDQUE4QztZQUM5QyxNQUFNLElBQUksNkJBQW9CLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDL0Q7S0FDRjtJQUVELDhDQUE4QztJQUM5QyxJQUFJLEtBQUssWUFBWSx3QkFBZSxFQUFFO1FBQ3BDLE1BQU0sSUFBSSw2QkFBb0IsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztLQUM3RDtJQUVELElBQUksS0FBSyxZQUFZLHFCQUFjLEVBQUU7UUFDbkMsTUFBTSxvQkFBb0IsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakUsTUFBTSxjQUFjLEdBQUcsb0JBQW9CLENBQUMsT0FBTyxDQUNqRCxpQkFBaUIsRUFDakIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQzNDLENBQUM7UUFFRixNQUFNLElBQUksNkJBQW9CLENBQUMsR0FBRyxjQUFjLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0tBQ2pHO0lBRUQsTUFBTSxLQUFLLENBQUM7QUFDZCxDQUFDO0FBNUJELCtCQTRCQyJ9
|
package/dist/connection/index.js
CHANGED
|
@@ -5,36 +5,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const connection_tester_1 = __importDefault(require("./connection-tester"));
|
|
7
7
|
const handle_errors_1 = __importDefault(require("./handle-errors"));
|
|
8
|
+
const sequelize_factory_1 = __importDefault(require("./sequelize-factory"));
|
|
8
9
|
const reverse_proxy_1 = __importDefault(require("./services/reverse-proxy"));
|
|
9
|
-
const
|
|
10
|
-
const
|
|
10
|
+
const socks_proxy_1 = __importDefault(require("./services/socks-proxy"));
|
|
11
|
+
const ssh_tunnel_1 = __importDefault(require("./services/ssh-tunnel"));
|
|
11
12
|
/** Attempt to connect to the database */
|
|
12
13
|
async function connect(options) {
|
|
13
|
-
let
|
|
14
|
-
let
|
|
14
|
+
let socksProxy;
|
|
15
|
+
let sshTunnel;
|
|
16
|
+
let reverseProxy;
|
|
15
17
|
let sequelize;
|
|
16
18
|
try {
|
|
19
|
+
if (options.proxyOptions || options.sshOptions) {
|
|
20
|
+
reverseProxy = new reverse_proxy_1.default();
|
|
21
|
+
await reverseProxy.start();
|
|
22
|
+
}
|
|
17
23
|
if (options.proxyOptions) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
// destination is the ssh server or the database
|
|
25
|
+
const { host, port } = options.sshOptions ?? options;
|
|
26
|
+
socksProxy = new socks_proxy_1.default(options.proxyOptions, host, port);
|
|
27
|
+
reverseProxy.link(socksProxy);
|
|
28
|
+
}
|
|
29
|
+
if (options.sshOptions) {
|
|
30
|
+
const { host, port, sshOptions } = options;
|
|
31
|
+
// database is the destination
|
|
32
|
+
sshTunnel = new ssh_tunnel_1.default(sshOptions, host, port);
|
|
33
|
+
// if socksProxy is defined, it means that we are using a proxy
|
|
34
|
+
// so we need to link to the socksProxy otherwise to the reverseProxy
|
|
35
|
+
(socksProxy ?? reverseProxy).link(sshTunnel);
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
sequelize =
|
|
30
|
-
|
|
37
|
+
// change the host and port of the sequelize options to point to the reverse proxy
|
|
38
|
+
if (reverseProxy)
|
|
39
|
+
options.changeHostAndPort(reverseProxy.host, reverseProxy.port);
|
|
40
|
+
sequelize = sequelize_factory_1.default.build(await options.buildSequelizeCtorOptions(),
|
|
41
|
+
// stop the reverse proxy when the sequelize connection is closed
|
|
42
|
+
reverseProxy?.stop.bind(reverseProxy));
|
|
43
|
+
await (0, connection_tester_1.default)(sequelize, options.debugDatabaseUri, options.connectionTimeoutInMs);
|
|
31
44
|
return sequelize;
|
|
32
45
|
}
|
|
33
46
|
catch (e) {
|
|
34
47
|
await sequelize?.close();
|
|
35
|
-
// if
|
|
36
|
-
|
|
48
|
+
// if ssh or socksProxy or reverseProxy encountered an error,
|
|
49
|
+
// we want to throw it instead of the sequelize error
|
|
50
|
+
(0, handle_errors_1.default)(sshTunnel?.error ?? socksProxy?.error ?? reverseProxy?.error ?? e, options);
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
53
|
exports.default = connect;
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29ubmVjdGlvbi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUdBLDRFQUE0RDtBQUM1RCxvRUFBMkM7QUFDM0MsNEVBQW1EO0FBQ25ELDZFQUFvRDtBQUNwRCx5RUFBZ0Q7QUFDaEQsdUVBQThDO0FBRTlDLHlDQUF5QztBQUMxQixLQUFLLFVBQVUsT0FBTyxDQUFDLE9BQTBCO0lBQzlELElBQUksVUFBc0IsQ0FBQztJQUMzQixJQUFJLFNBQW9CLENBQUM7SUFDekIsSUFBSSxZQUEwQixDQUFDO0lBQy9CLElBQUksU0FBb0IsQ0FBQztJQUV6QixJQUFJO1FBQ0YsSUFBSSxPQUFPLENBQUMsWUFBWSxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFDOUMsWUFBWSxHQUFHLElBQUksdUJBQVksRUFBRSxDQUFDO1lBQ2xDLE1BQU0sWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQzVCO1FBRUQsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ3hCLGdEQUFnRDtZQUNoRCxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksT0FBTyxDQUFDO1lBQ3JELFVBQVUsR0FBRyxJQUFJLHFCQUFVLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDOUQsWUFBWSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUMvQjtRQUVELElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRTtZQUN0QixNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUM7WUFDM0MsOEJBQThCO1lBQzlCLFNBQVMsR0FBRyxJQUFJLG9CQUFTLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNsRCwrREFBK0Q7WUFDL0QscUVBQXFFO1lBQ3JFLENBQUMsVUFBVSxJQUFJLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUM5QztRQUVELGtGQUFrRjtRQUNsRixJQUFJLFlBQVk7WUFBRSxPQUFPLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbEYsU0FBUyxHQUFHLDJCQUFnQixDQUFDLEtBQUssQ0FDaEMsTUFBTSxPQUFPLENBQUMseUJBQXlCLEVBQUU7UUFDekMsaUVBQWlFO1FBQ2pFLFlBQVksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUN0QyxDQUFDO1FBRUYsTUFBTSxJQUFBLDJCQUF5QixFQUM3QixTQUFTLEVBQ1QsT0FBTyxDQUFDLGdCQUFnQixFQUN4QixPQUFPLENBQUMscUJBQXFCLENBQzlCLENBQUM7UUFFRixPQUFPLFNBQVMsQ0FBQztLQUNsQjtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsTUFBTSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDekIsNkRBQTZEO1FBQzdELHFEQUFxRDtRQUNyRCxJQUFBLHVCQUFZLEVBQUMsU0FBUyxFQUFFLEtBQUssSUFBSSxVQUFVLEVBQUUsS0FBSyxJQUFJLFlBQVksRUFBRSxLQUFLLElBQUksQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0tBQzFGO0FBQ0gsQ0FBQztBQWxERCwwQkFrREMifQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Sequelize } from 'sequelize';
|
|
2
|
+
import { Options as SequelizeOptions } from 'sequelize/types/sequelize';
|
|
3
|
+
import Service from './services/service';
|
|
4
|
+
export default class SequelizeFactory {
|
|
5
|
+
static build(sequelizeCtorOptions: [SequelizeOptions] | [string, SequelizeOptions], stopCallback?: Service['stop']): Sequelize;
|
|
6
|
+
private static overrideCloseMethod;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=sequelize-factory.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const sequelize_1 = require("sequelize");
|
|
4
|
+
class SequelizeFactory {
|
|
5
|
+
static build(sequelizeCtorOptions, stopCallback) {
|
|
6
|
+
const sequelize = sequelizeCtorOptions.length === 1
|
|
7
|
+
? new sequelize_1.Sequelize(sequelizeCtorOptions[0])
|
|
8
|
+
: new sequelize_1.Sequelize(sequelizeCtorOptions[0], sequelizeCtorOptions[1]);
|
|
9
|
+
this.overrideCloseMethod(sequelize, stopCallback);
|
|
10
|
+
return sequelize;
|
|
11
|
+
}
|
|
12
|
+
static overrideCloseMethod(sequelize, stopCallback) {
|
|
13
|
+
// override close method to ensure to execute the stop
|
|
14
|
+
sequelize.close = async function close() {
|
|
15
|
+
try {
|
|
16
|
+
await sequelize_1.Sequelize.prototype.close.call(this);
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
if (stopCallback)
|
|
20
|
+
await stopCallback();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.default = SequelizeFactory;
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVsaXplLWZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29ubmVjdGlvbi9zZXF1ZWxpemUtZmFjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHlDQUFzQztBQUt0QyxNQUFxQixnQkFBZ0I7SUFDbkMsTUFBTSxDQUFDLEtBQUssQ0FDVixvQkFBcUUsRUFDckUsWUFBOEI7UUFFOUIsTUFBTSxTQUFTLEdBQ2Isb0JBQW9CLENBQUMsTUFBTSxLQUFLLENBQUM7WUFDL0IsQ0FBQyxDQUFDLElBQUkscUJBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4QyxDQUFDLENBQUMsSUFBSSxxQkFBUyxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxFQUFFLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFdEUsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUVsRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQW9CLEVBQUUsWUFBOEI7UUFDckYsc0RBQXNEO1FBQ3RELFNBQVMsQ0FBQyxLQUFLLEdBQUcsS0FBSyxVQUFVLEtBQUs7WUFDcEMsSUFBSTtnQkFDRixNQUFNLHFCQUFTLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDNUM7b0JBQVM7Z0JBQ1IsSUFBSSxZQUFZO29CQUFFLE1BQU0sWUFBWSxFQUFFLENBQUM7YUFDeEM7UUFDSCxDQUFDLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUF6QkQsbUNBeUJDIn0=
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import net from 'net';
|
|
3
3
|
import Service from './service';
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* ReverseProxy is used to redirect all the database requests.
|
|
6
|
+
* Sequelize does not take a socket as an argument,
|
|
7
|
+
* so we need to redirect all the traffic to a new socket.
|
|
8
|
+
* This is done by creating a server that will listen on a random port.
|
|
9
|
+
* We change the host and port of the Sequelize options to point to the reverse proxy.
|
|
10
|
+
* The reverse proxy will then redirect all the traffic to the database through the tunnel.
|
|
11
|
+
*/
|
|
5
12
|
export default class ReverseProxy extends Service {
|
|
6
|
-
private readonly
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
closeListener(): Promise<void>;
|
|
14
|
-
connectListener(socket: net.Socket): Promise<void>;
|
|
13
|
+
private readonly server;
|
|
14
|
+
get host(): string;
|
|
15
|
+
get port(): number;
|
|
16
|
+
constructor();
|
|
17
|
+
start(): Promise<void>;
|
|
18
|
+
stop(): Promise<void>;
|
|
19
|
+
protected connect(socket: net.Socket): Promise<net.Socket>;
|
|
15
20
|
}
|
|
16
21
|
//# sourceMappingURL=reverse-proxy.d.ts.map
|
|
@@ -3,61 +3,66 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const
|
|
6
|
+
const net_1 = __importDefault(require("net"));
|
|
7
7
|
const service_1 = __importDefault(require("./service"));
|
|
8
|
+
/**
|
|
9
|
+
* ReverseProxy is used to redirect all the database requests.
|
|
10
|
+
* Sequelize does not take a socket as an argument,
|
|
11
|
+
* so we need to redirect all the traffic to a new socket.
|
|
12
|
+
* This is done by creating a server that will listen on a random port.
|
|
13
|
+
* We change the host and port of the Sequelize options to point to the reverse proxy.
|
|
14
|
+
* The reverse proxy will then redirect all the traffic to the database through the tunnel.
|
|
15
|
+
*/
|
|
8
16
|
class ReverseProxy extends service_1.default {
|
|
9
|
-
get
|
|
10
|
-
return this.
|
|
17
|
+
get host() {
|
|
18
|
+
return this.server.address().address;
|
|
11
19
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.errors = [];
|
|
15
|
-
this.connectedClients = new Set();
|
|
16
|
-
this.options = proxyOptions;
|
|
17
|
-
this.targetHost = targetHost;
|
|
18
|
-
this.targetPort = targetPort;
|
|
19
|
-
if (!this.targetHost)
|
|
20
|
-
throw new Error('Host is required');
|
|
21
|
-
if (!this.targetPort)
|
|
22
|
-
throw new Error('Port is required');
|
|
20
|
+
get port() {
|
|
21
|
+
return this.server.address().port;
|
|
23
22
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
this.
|
|
23
|
+
constructor() {
|
|
24
|
+
super(null, null, null, null);
|
|
25
|
+
this.server = net_1.default.createServer(this.connect.bind(this));
|
|
27
26
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
socket.destroy(error);
|
|
35
|
-
});
|
|
36
|
-
socket.on('close', () => {
|
|
37
|
-
this.connectedClients.delete(socket);
|
|
38
|
-
if (!socks5Proxy?.socket.closed)
|
|
39
|
-
socks5Proxy?.socket.destroy();
|
|
27
|
+
start() {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
this.server.on('error', reject);
|
|
30
|
+
// By using port 0, the operating system
|
|
31
|
+
// will assign an available port for the server to listen on.
|
|
32
|
+
this.server.listen(0, '127.0.0.1', resolve);
|
|
40
33
|
});
|
|
34
|
+
}
|
|
35
|
+
async stop() {
|
|
41
36
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
37
|
+
// close all the connected clients before closing the server
|
|
38
|
+
await super.stop();
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await new Promise((resolve, reject) => {
|
|
42
|
+
this.server.close(e => {
|
|
43
|
+
if (e)
|
|
44
|
+
reject(e);
|
|
45
|
+
else
|
|
46
|
+
resolve();
|
|
47
|
+
});
|
|
52
48
|
});
|
|
53
|
-
socks5Proxy.socket.on('error', socket.destroy);
|
|
54
|
-
socks5Proxy.socket.pipe(socket).pipe(socks5Proxy.socket);
|
|
55
|
-
await super.connectListener(socks5Proxy.socket);
|
|
56
49
|
}
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
}
|
|
51
|
+
async connect(socket) {
|
|
52
|
+
try {
|
|
53
|
+
this.addConnectedClient(socket);
|
|
54
|
+
socket.on('close', () => this.destroySocketIfUnclosedAndSaveError(socket));
|
|
55
|
+
socket.on('error', error => this.destroySocketIfUnclosedAndSaveError(socket, error));
|
|
56
|
+
const tunnel = await super.connect();
|
|
57
|
+
if (tunnel)
|
|
58
|
+
tunnel.pipe(socket).pipe(tunnel);
|
|
59
|
+
return tunnel;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this.destroySocketIfUnclosedAndSaveError(socket, error);
|
|
63
|
+
// don't throw the error to avoid crashing the server because the error is already handled
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
exports.default = ReverseProxy;
|
|
63
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV2ZXJzZS1wcm94eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb25uZWN0aW9uL3NlcnZpY2VzL3JldmVyc2UtcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4Q0FBc0I7QUFFdEIsd0RBQWdDO0FBRWhDOzs7Ozs7O0dBT0c7QUFDSCxNQUFxQixZQUFhLFNBQVEsaUJBQU87SUFHL0MsSUFBSSxJQUFJO1FBQ04sT0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBc0IsQ0FBQyxPQUFPLENBQUM7SUFDNUQsQ0FBQztJQUVELElBQUksSUFBSTtRQUNOLE9BQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQXNCLENBQUMsSUFBSSxDQUFDO0lBQ3pELENBQUM7SUFFRDtRQUNFLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsTUFBTSxHQUFHLGFBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRUQsS0FBSztRQUNILE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDM0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ2hDLHdDQUF3QztZQUN4Qyw2REFBNkQ7WUFDN0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM5QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFUSxLQUFLLENBQUMsSUFBSTtRQUNqQixJQUFJO1lBQ0YsNERBQTREO1lBQzVELE1BQU0sS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3BCO2dCQUFTO1lBQ1IsTUFBTSxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDMUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQ3BCLElBQUksQ0FBQzt3QkFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7O3dCQUNaLE9BQU8sRUFBRSxDQUFDO2dCQUNqQixDQUFDLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1NBQ0o7SUFDSCxDQUFDO0lBRWtCLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBa0I7UUFDakQsSUFBSTtZQUNGLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNoQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsbUNBQW1DLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUMzRSxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUVyRixNQUFNLE1BQU0sR0FBRyxNQUFNLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNyQyxJQUFJLE1BQU07Z0JBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFN0MsT0FBTyxNQUFNLENBQUM7U0FDZjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN4RCwwRkFBMEY7U0FDM0Y7SUFDSCxDQUFDO0NBQ0Y7QUF0REQsK0JBc0RDIn0=
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import net from 'net';
|
|
3
|
-
export type ConnectionCallback = (socket: net.Socket) => Promise<
|
|
4
|
-
export type
|
|
3
|
+
export type ConnectionCallback = (socket: net.Socket) => Promise<net.Socket>;
|
|
4
|
+
export type StopCallback = () => Promise<void>;
|
|
5
5
|
export default abstract class Service {
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
private linkedService;
|
|
7
|
+
private readonly connectedClients;
|
|
8
|
+
protected readonly errors: Error[];
|
|
9
|
+
protected readonly sourceHost: string;
|
|
10
|
+
protected readonly sourcePort: number;
|
|
11
|
+
protected readonly targetHost: string;
|
|
12
|
+
protected readonly targetPort: number;
|
|
13
|
+
get error(): Error | null;
|
|
14
|
+
protected get debugUri(): string;
|
|
15
|
+
protected get debugForwardUri(): string;
|
|
16
|
+
constructor(sourceHost: string, sourcePort: number, targetHost: string, targetPort: number);
|
|
17
|
+
/** link a service */
|
|
18
|
+
link(service: Service): void;
|
|
19
|
+
/** stop the service by stopping the linked service and destroying all its clients. */
|
|
20
|
+
stop(): Promise<void>;
|
|
21
|
+
/** call the linked service connection callback */
|
|
22
|
+
protected connect(socket?: net.Socket): Promise<net.Socket>;
|
|
23
|
+
/** destroy the given socket if it is not closed and save the error */
|
|
24
|
+
protected destroySocketIfUnclosedAndSaveError(socket?: net.Socket, error?: Error): void;
|
|
25
|
+
/** register a socket as a client to be destroyed when the service is stopped */
|
|
26
|
+
protected addConnectedClient(client: net.Socket): void;
|
|
16
27
|
}
|
|
17
28
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1,22 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
class Service {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
this.connectionCallback = callback;
|
|
4
|
+
get error() {
|
|
5
|
+
return this.errors.length > 0 ? this.errors[0] : null;
|
|
7
6
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
await this.connectionCallback?.(socket);
|
|
7
|
+
get debugUri() {
|
|
8
|
+
return `${this.sourceHost}:${this.sourcePort}`;
|
|
11
9
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.closeCallback = callback;
|
|
10
|
+
get debugForwardUri() {
|
|
11
|
+
return `${this.targetHost}:${this.targetPort}`;
|
|
15
12
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
constructor(sourceHost, sourcePort, targetHost, targetPort) {
|
|
14
|
+
this.connectedClients = new Set();
|
|
15
|
+
this.errors = [];
|
|
16
|
+
this.sourceHost = sourceHost;
|
|
17
|
+
this.sourcePort = sourcePort;
|
|
18
|
+
this.targetHost = targetHost;
|
|
19
|
+
this.targetPort = targetPort;
|
|
20
|
+
}
|
|
21
|
+
/** link a service */
|
|
22
|
+
link(service) {
|
|
23
|
+
this.linkedService = service;
|
|
24
|
+
}
|
|
25
|
+
/** stop the service by stopping the linked service and destroying all its clients. */
|
|
26
|
+
async stop() {
|
|
27
|
+
try {
|
|
28
|
+
await this.linkedService?.stop();
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
this.connectedClients.forEach(client => client.destroy());
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** call the linked service connection callback */
|
|
35
|
+
async connect(socket) {
|
|
36
|
+
return (await this.linkedService?.connect(socket)) || socket;
|
|
37
|
+
}
|
|
38
|
+
/** destroy the given socket if it is not closed and save the error */
|
|
39
|
+
destroySocketIfUnclosedAndSaveError(socket, error) {
|
|
40
|
+
if (error)
|
|
41
|
+
this.errors.push(error);
|
|
42
|
+
if (socket) {
|
|
43
|
+
if (!socket.closed)
|
|
44
|
+
socket.destroy();
|
|
45
|
+
this.connectedClients.delete(socket);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** register a socket as a client to be destroyed when the service is stopped */
|
|
49
|
+
addConnectedClient(client) {
|
|
50
|
+
this.connectedClients.add(client);
|
|
19
51
|
}
|
|
20
52
|
}
|
|
21
53
|
exports.default = Service;
|
|
22
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb25uZWN0aW9uL3NlcnZpY2VzL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSxNQUE4QixPQUFPO0lBU25DLElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDeEQsQ0FBQztJQUVELElBQWMsUUFBUTtRQUNwQixPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDakQsQ0FBQztJQUVELElBQWMsZUFBZTtRQUMzQixPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDakQsQ0FBQztJQUVELFlBQVksVUFBa0IsRUFBRSxVQUFrQixFQUFFLFVBQWtCLEVBQUUsVUFBa0I7UUFuQnpFLHFCQUFnQixHQUFvQixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzVDLFdBQU0sR0FBWSxFQUFFLENBQUM7UUFtQnRDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO0lBQy9CLENBQUM7SUFFRCxxQkFBcUI7SUFDckIsSUFBSSxDQUFDLE9BQWdCO1FBQ25CLElBQUksQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDO0lBQy9CLENBQUM7SUFFRCxzRkFBc0Y7SUFDdEYsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDO1NBQ2xDO2dCQUFTO1lBQ1IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1NBQzNEO0lBQ0gsQ0FBQztJQUVELGtEQUFrRDtJQUN4QyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQW1CO1FBQ3pDLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDO0lBQy9ELENBQUM7SUFFRCxzRUFBc0U7SUFDNUQsbUNBQW1DLENBQUMsTUFBbUIsRUFBRSxLQUFhO1FBQzlFLElBQUksS0FBSztZQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRW5DLElBQUksTUFBTSxFQUFFO1lBQ1YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNO2dCQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNyQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3RDO0lBQ0gsQ0FBQztJQUVELGdGQUFnRjtJQUN0RSxrQkFBa0IsQ0FBQyxNQUFrQjtRQUM3QyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7Q0FDRjtBQTdERCwwQkE2REMifQ==
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import net from 'net';
|
|
3
|
+
import Service from './service';
|
|
4
|
+
import { ProxyOptions } from '../../types';
|
|
5
|
+
export default class SocksProxy extends Service {
|
|
6
|
+
private readonly options;
|
|
7
|
+
constructor(proxyOptions: ProxyOptions, targetHost: string, targetPort: number);
|
|
8
|
+
protected connect(): Promise<net.Socket>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=socks-proxy.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const socks_1 = require("socks");
|
|
7
|
+
const service_1 = __importDefault(require("./service"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
class SocksProxy extends service_1.default {
|
|
10
|
+
constructor(proxyOptions, targetHost, targetPort) {
|
|
11
|
+
super(proxyOptions.host, proxyOptions.port, targetHost, targetPort);
|
|
12
|
+
this.options = proxyOptions;
|
|
13
|
+
}
|
|
14
|
+
async connect() {
|
|
15
|
+
let socks5Client;
|
|
16
|
+
try {
|
|
17
|
+
socks5Client = await socks_1.SocksClient.createConnection({
|
|
18
|
+
proxy: { ...this.options, type: 5 },
|
|
19
|
+
command: 'connect',
|
|
20
|
+
destination: { host: this.targetHost, port: this.targetPort },
|
|
21
|
+
timeout: 4000,
|
|
22
|
+
});
|
|
23
|
+
this.addConnectedClient(socks5Client.socket);
|
|
24
|
+
socks5Client.socket.on('close', () => this.destroySocketIfUnclosedAndSaveError(socks5Client.socket));
|
|
25
|
+
socks5Client.socket.on('error', error => this.destroySocketIfUnclosedAndSaveError(socks5Client.socket, new errors_1.ProxyConnectError(error.message, this.debugUri)));
|
|
26
|
+
const tunnel = await super.connect(socks5Client.socket);
|
|
27
|
+
if (tunnel) {
|
|
28
|
+
// destroy the proxy socket when the tunnel is closed or an error occurs
|
|
29
|
+
// this is very important to avoid unclose database connections
|
|
30
|
+
tunnel.on('close', () => this.destroySocketIfUnclosedAndSaveError(socks5Client.socket));
|
|
31
|
+
tunnel.on('error', error => this.destroySocketIfUnclosedAndSaveError(socks5Client.socket, new errors_1.ProxyConnectError(error.message, this.debugUri)));
|
|
32
|
+
}
|
|
33
|
+
return tunnel;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
let serviceError = new errors_1.ProxyConnectError(error.message, this.debugUri);
|
|
37
|
+
if (error.message.includes('Socket closed') ||
|
|
38
|
+
error.message.includes('Socks5 proxy rejected connection')) {
|
|
39
|
+
serviceError = new errors_1.ProxyForwardError(error.message, this.debugForwardUri);
|
|
40
|
+
}
|
|
41
|
+
this.destroySocketIfUnclosedAndSaveError(socks5Client?.socket, serviceError);
|
|
42
|
+
throw serviceError;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = SocksProxy;
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja3MtcHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29ubmVjdGlvbi9zZXJ2aWNlcy9zb2Nrcy1wcm94eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLGlDQUFvQztBQUdwQyx3REFBZ0M7QUFFaEMsc0NBQWlFO0FBRWpFLE1BQXFCLFVBQVcsU0FBUSxpQkFBTztJQUc3QyxZQUFZLFlBQTBCLEVBQUUsVUFBa0IsRUFBRSxVQUFrQjtRQUM1RSxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsT0FBTyxHQUFHLFlBQVksQ0FBQztJQUM5QixDQUFDO0lBRWtCLEtBQUssQ0FBQyxPQUFPO1FBQzlCLElBQUksWUFBeUMsQ0FBQztRQUU5QyxJQUFJO1lBQ0YsWUFBWSxHQUFHLE1BQU0sbUJBQVcsQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDaEQsS0FBSyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUU7Z0JBQ25DLE9BQU8sRUFBRSxTQUFTO2dCQUNsQixXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDN0QsT0FBTyxFQUFFLElBQUk7YUFDZCxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzdDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FDbkMsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FDOUQsQ0FBQztZQUNGLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUN0QyxJQUFJLENBQUMsbUNBQW1DLENBQ3RDLFlBQVksQ0FBQyxNQUFNLEVBQ25CLElBQUksMEJBQWlCLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQ3BELENBQ0YsQ0FBQztZQUVGLE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFeEQsSUFBSSxNQUFNLEVBQUU7Z0JBQ1Ysd0VBQXdFO2dCQUN4RSwrREFBK0Q7Z0JBQy9ELE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDeEYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FDekIsSUFBSSxDQUFDLG1DQUFtQyxDQUN0QyxZQUFZLENBQUMsTUFBTSxFQUNuQixJQUFJLDBCQUFpQixDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUNwRCxDQUNGLENBQUM7YUFDSDtZQUVELE9BQU8sTUFBTSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksWUFBWSxHQUFHLElBQUksMEJBQWlCLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFdkUsSUFDRSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUM7Z0JBQ3ZDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLGtDQUFrQyxDQUFDLEVBQzFEO2dCQUNBLFlBQVksR0FBRyxJQUFJLDBCQUFpQixDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2FBQzNFO1lBRUQsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLFlBQVksRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDN0UsTUFBTSxZQUFZLENBQUM7U0FDcEI7SUFDSCxDQUFDO0NBQ0Y7QUExREQsNkJBMERDIn0=
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import net from 'net';
|
|
3
|
+
import Service from './service';
|
|
4
|
+
import { SshOptions } from '../../types';
|
|
5
|
+
export default class SshTunnel extends Service {
|
|
6
|
+
private readonly options;
|
|
7
|
+
private readonly clients;
|
|
8
|
+
constructor(options: SshOptions, targetHost: string, targetPort: number);
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
connect(socket?: net.Socket): Promise<net.Socket>;
|
|
11
|
+
private buildTunnel;
|
|
12
|
+
private endClient;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ssh-tunnel.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ssh2_1 = require("ssh2");
|
|
7
|
+
const service_1 = __importDefault(require("./service"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
class SshTunnel extends service_1.default {
|
|
10
|
+
constructor(options, targetHost, targetPort) {
|
|
11
|
+
super(options.host, options.port, targetHost, targetPort);
|
|
12
|
+
this.clients = new Set();
|
|
13
|
+
this.options = options;
|
|
14
|
+
}
|
|
15
|
+
async stop() {
|
|
16
|
+
try {
|
|
17
|
+
await super.stop();
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
this.clients.forEach(client => this.endClient(client));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async connect(socket) {
|
|
24
|
+
const client = new ssh2_1.Client();
|
|
25
|
+
// list all the clients to be able to close them all when the service is stopped
|
|
26
|
+
this.clients.add(client);
|
|
27
|
+
try {
|
|
28
|
+
return await new Promise((resolve, reject) => {
|
|
29
|
+
client.on('error', e => reject(new errors_1.SshConnectError(e.message, this.debugUri)));
|
|
30
|
+
client.on('ready', async () => {
|
|
31
|
+
try {
|
|
32
|
+
resolve(await this.buildTunnel(client));
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
reject(error);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
// connect to the SSH server
|
|
39
|
+
// will trigger the 'ready' event if the connection is successful
|
|
40
|
+
// if the connection fails, the 'error' event will be triggered
|
|
41
|
+
client.connect({ ...this.options, sock: socket });
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.endClient(client);
|
|
46
|
+
this.errors.push(error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async buildTunnel(client) {
|
|
51
|
+
// tell to the SSH server to forward all the traffic to the target host and port
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
// source host and port are not used by the SSH server
|
|
54
|
+
client.forwardOut('', 0, this.targetHost, this.targetPort, async (error, stream) => {
|
|
55
|
+
if (error)
|
|
56
|
+
return reject(new errors_1.SshForwardError(error.message, this.debugForwardUri));
|
|
57
|
+
this.addConnectedClient(stream);
|
|
58
|
+
stream.on('error', e => this.destroySocketIfUnclosedAndSaveError(stream, new errors_1.SshConnectError(e.message, this.debugUri)));
|
|
59
|
+
stream.on('close', () => {
|
|
60
|
+
this.destroySocketIfUnclosedAndSaveError(stream);
|
|
61
|
+
this.endClient(client);
|
|
62
|
+
});
|
|
63
|
+
return resolve(await super.connect(stream));
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
endClient(client) {
|
|
68
|
+
client.end();
|
|
69
|
+
this.clients.delete(client);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.default = SshTunnel;
|
|
73
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3NoLXR1bm5lbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb25uZWN0aW9uL3NlcnZpY2VzL3NzaC10dW5uZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSwrQkFBOEI7QUFFOUIsd0RBQWdDO0FBRWhDLHNDQUE2RDtBQUU3RCxNQUFxQixTQUFVLFNBQVEsaUJBQU87SUFJNUMsWUFBWSxPQUFtQixFQUFFLFVBQWtCLEVBQUUsVUFBa0I7UUFDckUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFIM0MsWUFBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFJM0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVRLEtBQUssQ0FBQyxJQUFJO1FBQ2pCLElBQUk7WUFDRixNQUFNLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNwQjtnQkFBUztZQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1NBQ3hEO0lBQ0gsQ0FBQztJQUVRLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBbUI7UUFDeEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxhQUFNLEVBQUUsQ0FBQztRQUM1QixnRkFBZ0Y7UUFDaEYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFekIsSUFBSTtZQUNGLE9BQU8sTUFBTSxJQUFJLE9BQU8sQ0FBYSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDdkQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSx3QkFBZSxDQUFDLENBQUMsQ0FBQyxP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
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Options } from 'sequelize/types';
|
|
2
|
+
import { ConnectConfig } from 'ssh2';
|
|
2
3
|
type SupportedSequelizeOptions = Pick<Options, 'database' | 'dialect' | 'dialectModule' | 'dialectModulePath' | 'dialectOptions' | 'host' | 'minifyAliases' | 'native' | 'password' | 'pool' | 'port' | 'protocol' | 'replication' | 'schema' | 'ssl' | 'storage' | 'username'>;
|
|
3
4
|
export type ProxyOptions = {
|
|
4
5
|
userId?: string;
|
|
@@ -8,10 +9,13 @@ export type ProxyOptions = {
|
|
|
8
9
|
version?: 5;
|
|
9
10
|
command?: 'connect';
|
|
10
11
|
};
|
|
12
|
+
export type SshOptions = Omit<ConnectConfig, 'sock'>;
|
|
11
13
|
export type PlainConnectionOptions = SupportedSequelizeOptions & {
|
|
12
14
|
uri?: string;
|
|
13
15
|
sslMode?: SslMode;
|
|
14
16
|
proxySocks?: ProxyOptions;
|
|
17
|
+
ssh?: SshOptions;
|
|
18
|
+
connectionTimeoutInMs?: number;
|
|
15
19
|
};
|
|
16
20
|
export type PlainConnectionOptionsOrUri = PlainConnectionOptions | string;
|
|
17
21
|
export type SslMode = 'preferred' | 'disabled' | 'required' | 'verify' | 'manual';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forestadmin/datasource-sql",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
"@forestadmin/datasource-toolkit": "1.5.0",
|
|
17
17
|
"pluralize": "^8.0.0",
|
|
18
18
|
"sequelize": "^6.28.0",
|
|
19
|
-
"socks": "^2.7.1"
|
|
19
|
+
"socks": "^2.7.1",
|
|
20
|
+
"ssh2": "^1.14.0",
|
|
21
|
+
"@types/ssh2": "^1.11.11"
|
|
20
22
|
},
|
|
21
23
|
"files": [
|
|
22
24
|
"dist/**/*.js",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Sequelize } from 'sequelize';
|
|
2
|
-
import { Options as SequelizeOptions } from 'sequelize/types/sequelize';
|
|
3
|
-
import Service from './service';
|
|
4
|
-
export default class SequelizeFactory extends Service {
|
|
5
|
-
build(sequelizeCtorOptions: [SequelizeOptions] | [string, SequelizeOptions]): Sequelize;
|
|
6
|
-
private overrideCloseMethod;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=sequelize-factory.d.ts.map
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const sequelize_1 = require("sequelize");
|
|
7
|
-
const service_1 = __importDefault(require("./service"));
|
|
8
|
-
class SequelizeFactory extends service_1.default {
|
|
9
|
-
build(sequelizeCtorOptions) {
|
|
10
|
-
const sequelize = sequelizeCtorOptions.length === 1
|
|
11
|
-
? new sequelize_1.Sequelize(sequelizeCtorOptions[0])
|
|
12
|
-
: new sequelize_1.Sequelize(sequelizeCtorOptions[0], sequelizeCtorOptions[1]);
|
|
13
|
-
this.overrideCloseMethod(sequelize);
|
|
14
|
-
return sequelize;
|
|
15
|
-
}
|
|
16
|
-
overrideCloseMethod(sequelize) {
|
|
17
|
-
const closeListener = this.closeListener.bind(this);
|
|
18
|
-
// override close method to ensure to execute the closeListener
|
|
19
|
-
sequelize.close = async function close() {
|
|
20
|
-
try {
|
|
21
|
-
await sequelize_1.Sequelize.prototype.close.call(this);
|
|
22
|
-
}
|
|
23
|
-
finally {
|
|
24
|
-
await closeListener();
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.default = SequelizeFactory;
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVsaXplLWZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29ubmVjdGlvbi9zZXJ2aWNlcy9zZXF1ZWxpemUtZmFjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHlDQUFzQztBQUd0Qyx3REFBZ0M7QUFFaEMsTUFBcUIsZ0JBQWlCLFNBQVEsaUJBQU87SUFDbkQsS0FBSyxDQUFDLG9CQUFxRTtRQUN6RSxNQUFNLFNBQVMsR0FDYixvQkFBb0IsQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUMvQixDQUFDLENBQUMsSUFBSSxxQkFBUyxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLENBQUMsQ0FBQyxJQUFJLHFCQUFTLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLEVBQUUsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV0RSxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFcEMsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVPLG1CQUFtQixDQUFDLFNBQW9CO1FBQzlDLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXBELCtEQUErRDtRQUMvRCxTQUFTLENBQUMsS0FBSyxHQUFHLEtBQUssVUFBVSxLQUFLO1lBQ3BDLElBQUk7Z0JBQ0YsTUFBTSxxQkFBUyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQzVDO29CQUFTO2dCQUNSLE1BQU0sYUFBYSxFQUFFLENBQUM7YUFDdkI7UUFDSCxDQUFDLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUF4QkQsbUNBd0JDIn0=
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import Service from './service';
|
|
2
|
-
/** TcpServer is used as proxy to redirect all the database requests */
|
|
3
|
-
export default class TcpServer extends Service {
|
|
4
|
-
private readonly server;
|
|
5
|
-
get host(): string;
|
|
6
|
-
get port(): number;
|
|
7
|
-
constructor();
|
|
8
|
-
start(): Promise<void>;
|
|
9
|
-
stop(): Promise<void>;
|
|
10
|
-
closeListener(): Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=tcp-server.d.ts.map
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const net_1 = __importDefault(require("net"));
|
|
7
|
-
const service_1 = __importDefault(require("./service"));
|
|
8
|
-
/** TcpServer is used as proxy to redirect all the database requests */
|
|
9
|
-
class TcpServer extends service_1.default {
|
|
10
|
-
get host() {
|
|
11
|
-
return this.server.address().address;
|
|
12
|
-
}
|
|
13
|
-
get port() {
|
|
14
|
-
return this.server.address().port;
|
|
15
|
-
}
|
|
16
|
-
constructor() {
|
|
17
|
-
super();
|
|
18
|
-
this.server = net_1.default.createServer(this.connectListener.bind(this));
|
|
19
|
-
}
|
|
20
|
-
start() {
|
|
21
|
-
return new Promise((resolve, reject) => {
|
|
22
|
-
this.server.on('error', reject);
|
|
23
|
-
// By using port 0, the operating system
|
|
24
|
-
// will assign an available port for the server to listen on.
|
|
25
|
-
this.server.listen(0, '127.0.0.1', resolve);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
async stop() {
|
|
29
|
-
try {
|
|
30
|
-
await super.closeListener();
|
|
31
|
-
}
|
|
32
|
-
finally {
|
|
33
|
-
await new Promise((resolve, reject) => {
|
|
34
|
-
this.server.close(e => {
|
|
35
|
-
if (e)
|
|
36
|
-
reject(e);
|
|
37
|
-
else
|
|
38
|
-
resolve();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
async closeListener() {
|
|
44
|
-
await this.stop();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
exports.default = TcpServer;
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGNwLXNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb25uZWN0aW9uL3NlcnZpY2VzL3RjcC1zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4Q0FBc0I7QUFFdEIsd0RBQWdDO0FBRWhDLHVFQUF1RTtBQUN2RSxNQUFxQixTQUFVLFNBQVEsaUJBQU87SUFHNUMsSUFBSSxJQUFJO1FBQ04sT0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBc0IsQ0FBQyxPQUFPLENBQUM7SUFDNUQsQ0FBQztJQUVELElBQUksSUFBSTtRQUNOLE9BQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQXNCLENBQUMsSUFBSSxDQUFDO0lBQ3pELENBQUM7SUFFRDtRQUNFLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxhQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVELEtBQUs7UUFDSCxPQUFPLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzNDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNoQyx3Q0FBd0M7WUFDeEMsNkRBQTZEO1lBQzdELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJO1lBQ0YsTUFBTSxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7U0FDN0I7Z0JBQVM7WUFDUixNQUFNLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUMxQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDcEIsSUFBSSxDQUFDO3dCQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQzs7d0JBQ1osT0FBTyxFQUFFLENBQUM7Z0JBQ2pCLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFFUSxLQUFLLENBQUMsYUFBYTtRQUMxQixNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUF6Q0QsNEJBeUNDIn0=
|