@tmlmobilidade/databases 20260323.417.47 → 20260324.1249.38
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/clients/go-clickhouse.js +17 -17
- package/dist/clients/go-mongo.js +23 -17
- package/dist/clients/index.d.ts +4 -3
- package/dist/clients/index.js +4 -3
- package/dist/clients/{pcgidb-ticketing.d.ts → pcgi-file-manager.d.ts} +1 -1
- package/dist/clients/pcgi-file-manager.js +123 -0
- package/dist/clients/{rawdb.d.ts → pcgi-raw.d.ts} +4 -3
- package/dist/clients/{pcgidb-ticketing.js → pcgi-raw.js} +29 -23
- package/dist/clients/{pcgidb-validations.d.ts → pcgi-ticketing.d.ts} +4 -3
- package/dist/clients/{rawdb.js → pcgi-ticketing.js} +34 -27
- package/dist/clients/pcgi-validations.d.ts +30 -0
- package/dist/clients/{pcgidb-validations.js → pcgi-validations.js} +34 -27
- package/dist/interfaces/index.d.ts +1 -1
- package/dist/interfaces/index.js +1 -1
- package/dist/interfaces/{simplified-vehicle-events → vehicle-events}/index.d.ts +1 -0
- package/dist/interfaces/{simplified-vehicle-events → vehicle-events}/index.js +1 -0
- package/dist/interfaces/vehicle-events/raw-vehicle-events.d.ts +581 -0
- package/dist/interfaces/vehicle-events/raw-vehicle-events.js +42 -0
- package/dist/templates/clickhouse.d.ts +2 -2
- package/dist/templates/clickhouse.js +3 -3
- package/dist/templates/mongodb.d.ts +130 -0
- package/dist/templates/mongodb.js +249 -0
- package/dist/types/mongo/index-description.d.ts +18 -0
- package/dist/types/mongo/index-description.js +2 -0
- package/dist/types/mongo/index.d.ts +1 -0
- package/dist/types/mongo/index.js +1 -0
- package/dist/utils/clickhouse/index.d.ts +6 -0
- package/dist/utils/clickhouse/index.js +6 -0
- package/dist/utils/index.d.ts +2 -3
- package/dist/utils/index.js +2 -3
- package/dist/utils/mongo/index.d.ts +1 -0
- package/dist/utils/mongo/index.js +1 -0
- package/dist/utils/mongo/manage-indexes.d.ts +18 -0
- package/dist/utils/mongo/manage-indexes.js +35 -0
- package/package.json +3 -2
- /package/dist/interfaces/{simplified-vehicle-events → vehicle-events}/simplified-vehicle-events.d.ts +0 -0
- /package/dist/interfaces/{simplified-vehicle-events → vehicle-events}/simplified-vehicle-events.js +0 -0
- /package/dist/utils/{get-clickhouse-param-type.d.ts → clickhouse/get-clickhouse-param-type.d.ts} +0 -0
- /package/dist/utils/{get-clickhouse-param-type.js → clickhouse/get-clickhouse-param-type.js} +0 -0
- /package/dist/utils/{prepare-named-query-params.d.ts → clickhouse/prepare-named-query-params.d.ts} +0 -0
- /package/dist/utils/{prepare-named-query-params.js → clickhouse/prepare-named-query-params.js} +0 -0
- /package/dist/utils/{prepare-positional-query-params.d.ts → clickhouse/prepare-positional-query-params.d.ts} +0 -0
- /package/dist/utils/{prepare-positional-query-params.js → clickhouse/prepare-positional-query-params.js} +0 -0
- /package/dist/utils/{query-from-file.d.ts → clickhouse/query-from-file.d.ts} +0 -0
- /package/dist/utils/{query-from-file.js → clickhouse/query-from-file.js} +0 -0
- /package/dist/utils/{query-from-string.d.ts → clickhouse/query-from-string.d.ts} +0 -0
- /package/dist/utils/{query-from-string.js → clickhouse/query-from-string.js} +0 -0
- /package/dist/utils/{validate-sql-param.d.ts → clickhouse/validate-sql-param.d.ts} +0 -0
- /package/dist/utils/{validate-sql-param.js → clickhouse/validate-sql-param.js} +0 -0
|
@@ -40,7 +40,7 @@ export class GOClickHouseClient {
|
|
|
40
40
|
* This method is called internally by the service and should not be used directly.
|
|
41
41
|
*/
|
|
42
42
|
async connect() {
|
|
43
|
-
Logger.info('Connecting to
|
|
43
|
+
Logger.info('[GOClickHouseClient] Connecting to database...');
|
|
44
44
|
const connectionString = await this.getConnectionString();
|
|
45
45
|
this.client = createClient({ url: connectionString });
|
|
46
46
|
}
|
|
@@ -56,39 +56,39 @@ export class GOClickHouseClient {
|
|
|
56
56
|
//
|
|
57
57
|
//
|
|
58
58
|
// Validate required environment variables
|
|
59
|
-
if (process.env.
|
|
60
|
-
throw new Error('Missing
|
|
59
|
+
if (process.env.GO_CLICKHOUSE_TUNNEL_ENABLED !== 'true' && process.env.GO_CLICKHOUSE_TUNNEL_ENABLED !== 'false') {
|
|
60
|
+
throw new Error('Missing GO_CLICKHOUSE_TUNNEL_ENABLED. Please indicate whether SSH tunneling is required by setting GO_CLICKHOUSE_TUNNEL_ENABLED to "true" or "false".');
|
|
61
61
|
}
|
|
62
|
-
if (!process.env.
|
|
63
|
-
throw new Error('Missing
|
|
62
|
+
if (!process.env.GO_CLICKHOUSE_HOST || !process.env.GO_CLICKHOUSE_PORT) {
|
|
63
|
+
throw new Error('Missing GO_CLICKHOUSE_HOST or GO_CLICKHOUSE_PORT');
|
|
64
64
|
}
|
|
65
|
-
if (process.env.
|
|
66
|
-
return `http://${process.env.
|
|
65
|
+
if (process.env.GO_CLICKHOUSE_TUNNEL_ENABLED === 'false') {
|
|
66
|
+
return `http://${process.env.GO_CLICKHOUSE_USER}:${process.env.GO_CLICKHOUSE_PASSWORD}@${process.env.GO_CLICKHOUSE_HOST}:${process.env.GO_CLICKHOUSE_PORT}`;
|
|
67
67
|
}
|
|
68
68
|
// SSH required
|
|
69
|
-
if (!process.env.
|
|
70
|
-
throw new Error('Missing
|
|
69
|
+
if (!process.env.GO_CLICKHOUSE_TUNNEL_LOCAL_PORT) {
|
|
70
|
+
throw new Error('Missing GO_CLICKHOUSE_TUNNEL_LOCAL_PORT');
|
|
71
71
|
}
|
|
72
|
-
if (!process.env.
|
|
72
|
+
if (!process.env.GO_CLICKHOUSE_TUNNEL_SSH_HOST || !process.env.GO_CLICKHOUSE_TUNNEL_SSH_USERNAME) {
|
|
73
73
|
throw new Error('Missing SSH config');
|
|
74
74
|
}
|
|
75
75
|
const sshConfig = {
|
|
76
76
|
forwardOptions: {
|
|
77
|
-
dstAddr: process.env.
|
|
78
|
-
dstPort: Number(process.env.
|
|
77
|
+
dstAddr: process.env.GO_CLICKHOUSE_HOST,
|
|
78
|
+
dstPort: Number(process.env.GO_CLICKHOUSE_PORT),
|
|
79
79
|
srcAddr: 'localhost',
|
|
80
|
-
srcPort: Number(process.env.
|
|
80
|
+
srcPort: Number(process.env.GO_CLICKHOUSE_TUNNEL_LOCAL_PORT),
|
|
81
81
|
},
|
|
82
82
|
serverOptions: {
|
|
83
|
-
port: Number(process.env.
|
|
83
|
+
port: Number(process.env.GO_CLICKHOUSE_TUNNEL_LOCAL_PORT),
|
|
84
84
|
},
|
|
85
85
|
sshOptions: {
|
|
86
86
|
agent: process.env.SSH_AUTH_SOCK,
|
|
87
|
-
host: process.env.
|
|
87
|
+
host: process.env.GO_CLICKHOUSE_TUNNEL_SSH_HOST,
|
|
88
88
|
keepaliveCountMax: 3,
|
|
89
89
|
keepaliveInterval: 10_000,
|
|
90
90
|
port: 22,
|
|
91
|
-
username: process.env.
|
|
91
|
+
username: process.env.GO_CLICKHOUSE_TUNNEL_SSH_USERNAME,
|
|
92
92
|
},
|
|
93
93
|
tunnelOptions: {
|
|
94
94
|
autoClose: false,
|
|
@@ -105,6 +105,6 @@ export class GOClickHouseClient {
|
|
|
105
105
|
if (!addr || typeof addr !== 'object') {
|
|
106
106
|
throw new Error('[GOClickHouseClient] Failed to retrieve SSH tunnel address.');
|
|
107
107
|
}
|
|
108
|
-
return `http://${process.env.
|
|
108
|
+
return `http://${process.env.GO_CLICKHOUSE_USER}:${process.env.GO_CLICKHOUSE_PASSWORD}@localhost:${addr.port}`;
|
|
109
109
|
}
|
|
110
110
|
}
|
package/dist/clients/go-mongo.js
CHANGED
|
@@ -40,7 +40,7 @@ export class GOMongoClient {
|
|
|
40
40
|
* This method is called internally by the service and should not be used directly.
|
|
41
41
|
*/
|
|
42
42
|
async connect() {
|
|
43
|
-
Logger.info('Connecting to
|
|
43
|
+
Logger.info('[GOMongoClient] Connecting to database...');
|
|
44
44
|
const connectionString = await this.getConnectionString();
|
|
45
45
|
this.client = new MongoClient(connectionString);
|
|
46
46
|
this.client.on('close', () => {
|
|
@@ -63,39 +63,45 @@ export class GOMongoClient {
|
|
|
63
63
|
//
|
|
64
64
|
//
|
|
65
65
|
// Validate required environment variables
|
|
66
|
-
if (process.env.
|
|
67
|
-
throw new Error('Missing
|
|
66
|
+
if (process.env.GO_MONGO_TUNNEL_ENABLED !== 'true' && process.env.GO_MONGO_TUNNEL_ENABLED !== 'false') {
|
|
67
|
+
throw new Error('Missing GO_MONGO_TUNNEL_ENABLED. Please indicate whether SSH tunneling is required by setting GO_MONGO_TUNNEL_ENABLED to "true" or "false".');
|
|
68
68
|
}
|
|
69
|
-
if (!process.env.
|
|
70
|
-
throw new Error('Missing
|
|
69
|
+
if (!process.env.GO_MONGO_HOST_1 || !process.env.GO_MONGO_PORT_1) {
|
|
70
|
+
throw new Error('Missing GO_MONGO_HOST_1 or GO_MONGO_PORT_1');
|
|
71
71
|
}
|
|
72
|
-
if (process.env.
|
|
73
|
-
|
|
72
|
+
if (!process.env.GO_MONGO_HOST_2 || !process.env.GO_MONGO_PORT_2) {
|
|
73
|
+
throw new Error('Missing GO_MONGO_HOST_2 or GO_MONGO_PORT_2');
|
|
74
|
+
}
|
|
75
|
+
if (!process.env.GO_MONGO_HOST_3 || !process.env.GO_MONGO_PORT_3) {
|
|
76
|
+
throw new Error('Missing GO_MONGO_HOST_3 or GO_MONGO_PORT_3');
|
|
77
|
+
}
|
|
78
|
+
if (process.env.GO_MONGO_TUNNEL_ENABLED === 'false') {
|
|
79
|
+
return `mongodb://${process.env.GO_MONGO_USER}:${process.env.GO_MONGO_PASSWORD}@${process.env.GO_MONGO_HOST_1}:${process.env.GO_MONGO_PORT_1},${process.env.GO_MONGO_HOST_2}:${process.env.GO_MONGO_PORT_2},${process.env.GO_MONGO_HOST_3}:${process.env.GO_MONGO_PORT_3}/`;
|
|
74
80
|
}
|
|
75
81
|
// SSH required
|
|
76
|
-
if (!process.env.
|
|
77
|
-
throw new Error('Missing
|
|
82
|
+
if (!process.env.GO_MONGO_TUNNEL_LOCAL_PORT) {
|
|
83
|
+
throw new Error('Missing GO_MONGO_TUNNEL_LOCAL_PORT');
|
|
78
84
|
}
|
|
79
|
-
if (!process.env.
|
|
85
|
+
if (!process.env.GO_MONGO_TUNNEL_SSH_HOST || !process.env.GO_MONGO_TUNNEL_SSH_USERNAME) {
|
|
80
86
|
throw new Error('Missing SSH config');
|
|
81
87
|
}
|
|
82
88
|
const sshConfig = {
|
|
83
89
|
forwardOptions: {
|
|
84
|
-
dstAddr: process.env.
|
|
85
|
-
dstPort: Number(process.env.
|
|
90
|
+
dstAddr: process.env.GO_MONGO_HOST_1,
|
|
91
|
+
dstPort: Number(process.env.GO_MONGO_PORT_1),
|
|
86
92
|
srcAddr: 'localhost',
|
|
87
|
-
srcPort: Number(process.env.
|
|
93
|
+
srcPort: Number(process.env.GO_MONGO_TUNNEL_LOCAL_PORT),
|
|
88
94
|
},
|
|
89
95
|
serverOptions: {
|
|
90
|
-
port: Number(process.env.
|
|
96
|
+
port: Number(process.env.GO_MONGO_TUNNEL_LOCAL_PORT),
|
|
91
97
|
},
|
|
92
98
|
sshOptions: {
|
|
93
99
|
agent: process.env.SSH_AUTH_SOCK,
|
|
94
|
-
host: process.env.
|
|
100
|
+
host: process.env.GO_MONGO_TUNNEL_SSH_HOST,
|
|
95
101
|
keepaliveCountMax: 3,
|
|
96
102
|
keepaliveInterval: 10_000,
|
|
97
103
|
port: 22,
|
|
98
|
-
username: process.env.
|
|
104
|
+
username: process.env.GO_MONGO_TUNNEL_SSH_USERNAME,
|
|
99
105
|
},
|
|
100
106
|
tunnelOptions: {
|
|
101
107
|
autoClose: false,
|
|
@@ -112,6 +118,6 @@ export class GOMongoClient {
|
|
|
112
118
|
if (!addr || typeof addr !== 'object') {
|
|
113
119
|
throw new Error('[GOMongoClient] Failed to retrieve SSH tunnel address.');
|
|
114
120
|
}
|
|
115
|
-
return `mongodb://${process.env.
|
|
121
|
+
return `mongodb://${process.env.GO_MONGO_USER}:${process.env.GO_MONGO_PASSWORD}@localhost:${addr.port}/`;
|
|
116
122
|
}
|
|
117
123
|
}
|
package/dist/clients/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './go-clickhouse.js';
|
|
2
2
|
export * from './go-mongo.js';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
3
|
+
export * from './pcgi-file-manager.js';
|
|
4
|
+
export * from './pcgi-raw.js';
|
|
5
|
+
export * from './pcgi-ticketing.js';
|
|
6
|
+
export * from './pcgi-validations.js';
|
package/dist/clients/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './go-clickhouse.js';
|
|
2
2
|
export * from './go-mongo.js';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
3
|
+
export * from './pcgi-file-manager.js';
|
|
4
|
+
export * from './pcgi-raw.js';
|
|
5
|
+
export * from './pcgi-ticketing.js';
|
|
6
|
+
export * from './pcgi-validations.js';
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { Logger } from '@tmlmobilidade/logger';
|
|
3
|
+
import { SshTunnelService } from '@tmlmobilidade/ssh';
|
|
4
|
+
import { MongoClient } from 'mongodb';
|
|
5
|
+
/* * */
|
|
6
|
+
export class PCGIFileManagerClient {
|
|
7
|
+
//
|
|
8
|
+
static _instance = null;
|
|
9
|
+
client;
|
|
10
|
+
tunnel = null;
|
|
11
|
+
/**
|
|
12
|
+
* Disallow direct instantiation of the service.
|
|
13
|
+
* Use getClient() instead to ensure singleton behavior.
|
|
14
|
+
*/
|
|
15
|
+
constructor() { }
|
|
16
|
+
/**
|
|
17
|
+
* Returns the singleton instance of the subclass.
|
|
18
|
+
*/
|
|
19
|
+
static async getClient() {
|
|
20
|
+
// If no instance exists, create one and store the promise.
|
|
21
|
+
// This ensures that if multiple calls to getClient() happen concurrently,
|
|
22
|
+
// they will all await the same initialization process.
|
|
23
|
+
if (!this._instance) {
|
|
24
|
+
this._instance = (async () => {
|
|
25
|
+
const instance = new PCGIFileManagerClient();
|
|
26
|
+
// This behaves like the constructor,
|
|
27
|
+
// but allows for async initialization.
|
|
28
|
+
await instance.connect();
|
|
29
|
+
return instance;
|
|
30
|
+
})();
|
|
31
|
+
}
|
|
32
|
+
// Await the instance if it's still initializing,
|
|
33
|
+
// or return it immediately if ready.
|
|
34
|
+
const instance = await this._instance;
|
|
35
|
+
return instance.client;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Connects to Mongo, setting up the client instance.
|
|
39
|
+
* If SSH tunneling is required, it establishes the tunnel first.
|
|
40
|
+
* This method is called internally by the service and should not be used directly.
|
|
41
|
+
*/
|
|
42
|
+
async connect() {
|
|
43
|
+
Logger.info('[PCGIFileManagerClient] Connecting to database...');
|
|
44
|
+
const connectionString = await this.getConnectionString();
|
|
45
|
+
this.client = new MongoClient(connectionString);
|
|
46
|
+
this.client.on('close', () => {
|
|
47
|
+
console.warn('[PCGIFileManagerClient] Database connection closed unexpectedly.');
|
|
48
|
+
});
|
|
49
|
+
this.client.on('reconnect', () => {
|
|
50
|
+
console.log('[PCGIFileManagerClient] Database reconnected.');
|
|
51
|
+
});
|
|
52
|
+
await this.client.connect();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Constructs the connection string based on environment variables
|
|
56
|
+
* and SSH tunneling configuration, and handles both direct connections and SSH-tunneled
|
|
57
|
+
* connections, validating the necessary environment variables for each case.
|
|
58
|
+
* This method is called internally by the service and should not be used directly.
|
|
59
|
+
* @throws Will throw an error if required environment variables are missing or if the SSH tunnel setup fails.
|
|
60
|
+
* @returns A promise that resolves to the Mongo connection string.
|
|
61
|
+
*/
|
|
62
|
+
async getConnectionString() {
|
|
63
|
+
//
|
|
64
|
+
//
|
|
65
|
+
// Validate required environment variables
|
|
66
|
+
if (process.env.PCGI_FILE_MANAGER_TUNNEL_ENABLED !== 'true' && process.env.PCGI_FILE_MANAGER_TUNNEL_ENABLED !== 'false') {
|
|
67
|
+
throw new Error('Missing PCGI_FILE_MANAGER_TUNNEL_ENABLED. Please indicate whether SSH tunneling is required by setting PCGI_FILE_MANAGER_TUNNEL_ENABLED to "true" or "false".');
|
|
68
|
+
}
|
|
69
|
+
if (!process.env.PCGI_FILE_MANAGER_HOST_1 || !process.env.PCGI_FILE_MANAGER_PORT_1) {
|
|
70
|
+
throw new Error('Missing PCGI_FILE_MANAGER_HOST_1 or PCGI_FILE_MANAGER_PORT_1');
|
|
71
|
+
}
|
|
72
|
+
if (!process.env.PCGI_FILE_MANAGER_HOST_2 || !process.env.PCGI_FILE_MANAGER_PORT_2) {
|
|
73
|
+
throw new Error('Missing PCGI_FILE_MANAGER_HOST_2 or PCGI_FILE_MANAGER_PORT_2');
|
|
74
|
+
}
|
|
75
|
+
if (!process.env.PCGI_FILE_MANAGER_HOST_3 || !process.env.PCGI_FILE_MANAGER_PORT_3) {
|
|
76
|
+
throw new Error('Missing PCGI_FILE_MANAGER_HOST_3 or PCGI_FILE_MANAGER_PORT_3');
|
|
77
|
+
}
|
|
78
|
+
if (process.env.PCGI_FILE_MANAGER_TUNNEL_ENABLED === 'false') {
|
|
79
|
+
return `mongodb://${process.env.PCGI_FILE_MANAGER_USER}:${process.env.PCGI_FILE_MANAGER_PASSWORD}@${process.env.PCGI_FILE_MANAGER_HOST_1}:${process.env.PCGI_FILE_MANAGER_PORT_1},${process.env.PCGI_FILE_MANAGER_HOST_2}:${process.env.PCGI_FILE_MANAGER_PORT_2},${process.env.PCGI_FILE_MANAGER_HOST_3}:${process.env.PCGI_FILE_MANAGER_PORT_3}/`;
|
|
80
|
+
}
|
|
81
|
+
// SSH required
|
|
82
|
+
if (!process.env.PCGI_FILE_MANAGER_TUNNEL_LOCAL_PORT) {
|
|
83
|
+
throw new Error('Missing PCGI_FILE_MANAGER_TUNNEL_LOCAL_PORT');
|
|
84
|
+
}
|
|
85
|
+
if (!process.env.PCGI_FILE_MANAGER_TUNNEL_SSH_HOST || !process.env.PCGI_FILE_MANAGER_TUNNEL_SSH_USERNAME) {
|
|
86
|
+
throw new Error('Missing SSH config');
|
|
87
|
+
}
|
|
88
|
+
const sshConfig = {
|
|
89
|
+
forwardOptions: {
|
|
90
|
+
dstAddr: process.env.PCGI_FILE_MANAGER_HOST_1,
|
|
91
|
+
dstPort: Number(process.env.PCGI_FILE_MANAGER_PORT_1),
|
|
92
|
+
srcAddr: 'localhost',
|
|
93
|
+
srcPort: Number(process.env.PCGI_FILE_MANAGER_TUNNEL_LOCAL_PORT),
|
|
94
|
+
},
|
|
95
|
+
serverOptions: {
|
|
96
|
+
port: Number(process.env.PCGI_FILE_MANAGER_TUNNEL_LOCAL_PORT),
|
|
97
|
+
},
|
|
98
|
+
sshOptions: {
|
|
99
|
+
agent: process.env.SSH_AUTH_SOCK,
|
|
100
|
+
host: process.env.PCGI_FILE_MANAGER_TUNNEL_SSH_HOST,
|
|
101
|
+
keepaliveCountMax: 3,
|
|
102
|
+
keepaliveInterval: 10_000,
|
|
103
|
+
port: 22,
|
|
104
|
+
username: process.env.PCGI_FILE_MANAGER_TUNNEL_SSH_USERNAME,
|
|
105
|
+
},
|
|
106
|
+
tunnelOptions: {
|
|
107
|
+
autoClose: false,
|
|
108
|
+
reconnectOnError: true,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const sshOptions = {
|
|
112
|
+
maxRetries: 3,
|
|
113
|
+
};
|
|
114
|
+
this.tunnel = new SshTunnelService(sshConfig, sshOptions);
|
|
115
|
+
Logger.info('[PCGIFileManagerClient] Setting up SSH Tunnel...');
|
|
116
|
+
const connection = await this.tunnel.connect();
|
|
117
|
+
const addr = connection.address();
|
|
118
|
+
if (!addr || typeof addr !== 'object') {
|
|
119
|
+
throw new Error('[PCGIFileManagerClient] Failed to retrieve SSH tunnel address.');
|
|
120
|
+
}
|
|
121
|
+
return `mongodb://${process.env.PCGI_FILE_MANAGER_USER}:${process.env.PCGI_FILE_MANAGER_PASSWORD}@localhost:${addr.port}/`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { MongoClient } from 'mongodb';
|
|
2
|
+
export declare class PCGIRawClient {
|
|
2
3
|
private static _instance;
|
|
3
4
|
private client;
|
|
4
5
|
private tunnel;
|
|
5
6
|
/**
|
|
6
7
|
* Disallow direct instantiation of the service.
|
|
7
|
-
* Use
|
|
8
|
+
* Use getClient() instead to ensure singleton behavior.
|
|
8
9
|
*/
|
|
9
10
|
private constructor();
|
|
10
11
|
/**
|
|
11
12
|
* Returns the singleton instance of the subclass.
|
|
12
13
|
*/
|
|
13
|
-
static
|
|
14
|
+
static getClient(): Promise<MongoClient>;
|
|
14
15
|
/**
|
|
15
16
|
* Connects to Mongo, setting up the client instance.
|
|
16
17
|
* If SSH tunneling is required, it establishes the tunnel first.
|
|
@@ -3,7 +3,7 @@ import { Logger } from '@tmlmobilidade/logger';
|
|
|
3
3
|
import { SshTunnelService } from '@tmlmobilidade/ssh';
|
|
4
4
|
import { MongoClient } from 'mongodb';
|
|
5
5
|
/* * */
|
|
6
|
-
export class
|
|
6
|
+
export class PCGIRawClient {
|
|
7
7
|
//
|
|
8
8
|
static _instance = null;
|
|
9
9
|
client;
|
|
@@ -22,7 +22,7 @@ export class PCGIDBTicketingService {
|
|
|
22
22
|
// they will all await the same initialization process.
|
|
23
23
|
if (!this._instance) {
|
|
24
24
|
this._instance = (async () => {
|
|
25
|
-
const instance = new
|
|
25
|
+
const instance = new PCGIRawClient();
|
|
26
26
|
// This behaves like the constructor,
|
|
27
27
|
// but allows for async initialization.
|
|
28
28
|
await instance.connect();
|
|
@@ -40,14 +40,14 @@ export class PCGIDBTicketingService {
|
|
|
40
40
|
* This method is called internally by the service and should not be used directly.
|
|
41
41
|
*/
|
|
42
42
|
async connect() {
|
|
43
|
-
Logger.info('Connecting to
|
|
43
|
+
Logger.info('[PCGIRawClient] Connecting to database...');
|
|
44
44
|
const connectionString = await this.getConnectionString();
|
|
45
45
|
this.client = new MongoClient(connectionString);
|
|
46
46
|
this.client.on('close', () => {
|
|
47
|
-
console.warn('[
|
|
47
|
+
console.warn('[PCGIRawClient] Database connection closed unexpectedly.');
|
|
48
48
|
});
|
|
49
49
|
this.client.on('reconnect', () => {
|
|
50
|
-
console.log('[
|
|
50
|
+
console.log('[PCGIRawClient] Database reconnected.');
|
|
51
51
|
});
|
|
52
52
|
await this.client.connect();
|
|
53
53
|
}
|
|
@@ -63,39 +63,45 @@ export class PCGIDBTicketingService {
|
|
|
63
63
|
//
|
|
64
64
|
//
|
|
65
65
|
// Validate required environment variables
|
|
66
|
-
if (process.env.
|
|
67
|
-
throw new Error('Missing
|
|
66
|
+
if (process.env.PCGI_RAW_TUNNEL_ENABLED !== 'true' && process.env.PCGI_RAW_TUNNEL_ENABLED !== 'false') {
|
|
67
|
+
throw new Error('Missing PCGI_RAW_TUNNEL_ENABLED. Please indicate whether SSH tunneling is required by setting PCGI_RAW_TUNNEL_ENABLED to "true" or "false".');
|
|
68
68
|
}
|
|
69
|
-
if (!process.env.
|
|
70
|
-
throw new Error('Missing
|
|
69
|
+
if (!process.env.PCGI_RAW_HOST_1 || !process.env.PCGI_RAW_PORT_1) {
|
|
70
|
+
throw new Error('Missing PCGI_RAW_HOST_1 or PCGI_RAW_PORT_1');
|
|
71
71
|
}
|
|
72
|
-
if (process.env.
|
|
73
|
-
|
|
72
|
+
if (!process.env.PCGI_RAW_HOST_2 || !process.env.PCGI_RAW_PORT_2) {
|
|
73
|
+
throw new Error('Missing PCGI_RAW_HOST_2 or PCGI_RAW_PORT_2');
|
|
74
|
+
}
|
|
75
|
+
if (!process.env.PCGI_RAW_HOST_3 || !process.env.PCGI_RAW_PORT_3) {
|
|
76
|
+
throw new Error('Missing PCGI_RAW_HOST_3 or PCGI_RAW_PORT_3');
|
|
77
|
+
}
|
|
78
|
+
if (process.env.PCGI_RAW_TUNNEL_ENABLED === 'false') {
|
|
79
|
+
return `mongodb://${process.env.PCGI_RAW_USER}:${process.env.PCGI_RAW_PASSWORD}@${process.env.PCGI_RAW_HOST_1}:${process.env.PCGI_RAW_PORT_1},${process.env.PCGI_RAW_HOST_2}:${process.env.PCGI_RAW_PORT_2},${process.env.PCGI_RAW_HOST_3}:${process.env.PCGI_RAW_PORT_3}/`;
|
|
74
80
|
}
|
|
75
81
|
// SSH required
|
|
76
|
-
if (!process.env.
|
|
77
|
-
throw new Error('Missing
|
|
82
|
+
if (!process.env.PCGI_RAW_TUNNEL_LOCAL_PORT) {
|
|
83
|
+
throw new Error('Missing PCGI_RAW_TUNNEL_LOCAL_PORT');
|
|
78
84
|
}
|
|
79
|
-
if (!process.env.
|
|
85
|
+
if (!process.env.PCGI_RAW_TUNNEL_SSH_HOST || !process.env.PCGI_RAW_TUNNEL_SSH_USERNAME) {
|
|
80
86
|
throw new Error('Missing SSH config');
|
|
81
87
|
}
|
|
82
88
|
const sshConfig = {
|
|
83
89
|
forwardOptions: {
|
|
84
|
-
dstAddr: process.env.
|
|
85
|
-
dstPort: Number(process.env.
|
|
90
|
+
dstAddr: process.env.PCGI_RAW_HOST_1,
|
|
91
|
+
dstPort: Number(process.env.PCGI_RAW_PORT_1),
|
|
86
92
|
srcAddr: 'localhost',
|
|
87
|
-
srcPort: Number(process.env.
|
|
93
|
+
srcPort: Number(process.env.PCGI_RAW_TUNNEL_LOCAL_PORT),
|
|
88
94
|
},
|
|
89
95
|
serverOptions: {
|
|
90
|
-
port: Number(process.env.
|
|
96
|
+
port: Number(process.env.PCGI_RAW_TUNNEL_LOCAL_PORT),
|
|
91
97
|
},
|
|
92
98
|
sshOptions: {
|
|
93
99
|
agent: process.env.SSH_AUTH_SOCK,
|
|
94
|
-
host: process.env.
|
|
100
|
+
host: process.env.PCGI_RAW_TUNNEL_SSH_HOST,
|
|
95
101
|
keepaliveCountMax: 3,
|
|
96
102
|
keepaliveInterval: 10_000,
|
|
97
103
|
port: 22,
|
|
98
|
-
username: process.env.
|
|
104
|
+
username: process.env.PCGI_RAW_TUNNEL_SSH_USERNAME,
|
|
99
105
|
},
|
|
100
106
|
tunnelOptions: {
|
|
101
107
|
autoClose: false,
|
|
@@ -106,12 +112,12 @@ export class PCGIDBTicketingService {
|
|
|
106
112
|
maxRetries: 3,
|
|
107
113
|
};
|
|
108
114
|
this.tunnel = new SshTunnelService(sshConfig, sshOptions);
|
|
109
|
-
Logger.info('[
|
|
115
|
+
Logger.info('[PCGIRawClient] Setting up SSH Tunnel...');
|
|
110
116
|
const connection = await this.tunnel.connect();
|
|
111
117
|
const addr = connection.address();
|
|
112
118
|
if (!addr || typeof addr !== 'object') {
|
|
113
|
-
throw new Error('[
|
|
119
|
+
throw new Error('[PCGIRawClient] Failed to retrieve SSH tunnel address.');
|
|
114
120
|
}
|
|
115
|
-
return `
|
|
121
|
+
return `mongodb://${process.env.PCGI_RAW_USER}:${process.env.PCGI_RAW_PASSWORD}@localhost:${addr.port}/`;
|
|
116
122
|
}
|
|
117
123
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { MongoClient } from 'mongodb';
|
|
2
|
+
export declare class PCGITicketingClient {
|
|
2
3
|
private static _instance;
|
|
3
4
|
private client;
|
|
4
5
|
private tunnel;
|
|
5
6
|
/**
|
|
6
7
|
* Disallow direct instantiation of the service.
|
|
7
|
-
* Use
|
|
8
|
+
* Use getClient() instead to ensure singleton behavior.
|
|
8
9
|
*/
|
|
9
10
|
private constructor();
|
|
10
11
|
/**
|
|
11
12
|
* Returns the singleton instance of the subclass.
|
|
12
13
|
*/
|
|
13
|
-
static
|
|
14
|
+
static getClient(): Promise<MongoClient>;
|
|
14
15
|
/**
|
|
15
16
|
* Connects to Mongo, setting up the client instance.
|
|
16
17
|
* If SSH tunneling is required, it establishes the tunnel first.
|
|
@@ -3,26 +3,26 @@ import { Logger } from '@tmlmobilidade/logger';
|
|
|
3
3
|
import { SshTunnelService } from '@tmlmobilidade/ssh';
|
|
4
4
|
import { MongoClient } from 'mongodb';
|
|
5
5
|
/* * */
|
|
6
|
-
export class
|
|
6
|
+
export class PCGITicketingClient {
|
|
7
7
|
//
|
|
8
8
|
static _instance = null;
|
|
9
9
|
client;
|
|
10
10
|
tunnel = null;
|
|
11
11
|
/**
|
|
12
12
|
* Disallow direct instantiation of the service.
|
|
13
|
-
* Use
|
|
13
|
+
* Use getClient() instead to ensure singleton behavior.
|
|
14
14
|
*/
|
|
15
15
|
constructor() { }
|
|
16
16
|
/**
|
|
17
17
|
* Returns the singleton instance of the subclass.
|
|
18
18
|
*/
|
|
19
|
-
static async
|
|
19
|
+
static async getClient() {
|
|
20
20
|
// If no instance exists, create one and store the promise.
|
|
21
|
-
// This ensures that if multiple calls to
|
|
21
|
+
// This ensures that if multiple calls to getClient() happen concurrently,
|
|
22
22
|
// they will all await the same initialization process.
|
|
23
23
|
if (!this._instance) {
|
|
24
24
|
this._instance = (async () => {
|
|
25
|
-
const instance = new
|
|
25
|
+
const instance = new PCGITicketingClient();
|
|
26
26
|
// This behaves like the constructor,
|
|
27
27
|
// but allows for async initialization.
|
|
28
28
|
await instance.connect();
|
|
@@ -31,7 +31,8 @@ export class RAWDBService {
|
|
|
31
31
|
}
|
|
32
32
|
// Await the instance if it's still initializing,
|
|
33
33
|
// or return it immediately if ready.
|
|
34
|
-
|
|
34
|
+
const instance = await this._instance;
|
|
35
|
+
return instance.client;
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Connects to Mongo, setting up the client instance.
|
|
@@ -39,14 +40,14 @@ export class RAWDBService {
|
|
|
39
40
|
* This method is called internally by the service and should not be used directly.
|
|
40
41
|
*/
|
|
41
42
|
async connect() {
|
|
42
|
-
Logger.info('Connecting to
|
|
43
|
+
Logger.info('[PCGITicketingClient] Connecting to database...');
|
|
43
44
|
const connectionString = await this.getConnectionString();
|
|
44
45
|
this.client = new MongoClient(connectionString);
|
|
45
46
|
this.client.on('close', () => {
|
|
46
|
-
console.warn('[
|
|
47
|
+
console.warn('[PCGITicketingClient] Database connection closed unexpectedly.');
|
|
47
48
|
});
|
|
48
49
|
this.client.on('reconnect', () => {
|
|
49
|
-
console.log('[
|
|
50
|
+
console.log('[PCGITicketingClient] Database reconnected.');
|
|
50
51
|
});
|
|
51
52
|
await this.client.connect();
|
|
52
53
|
}
|
|
@@ -62,39 +63,45 @@ export class RAWDBService {
|
|
|
62
63
|
//
|
|
63
64
|
//
|
|
64
65
|
// Validate required environment variables
|
|
65
|
-
if (process.env.
|
|
66
|
-
throw new Error('Missing
|
|
66
|
+
if (process.env.PCGI_TICKETING_TUNNEL_ENABLED !== 'true' && process.env.PCGI_TICKETING_TUNNEL_ENABLED !== 'false') {
|
|
67
|
+
throw new Error('Missing PCGI_TICKETING_TUNNEL_ENABLED. Please indicate whether SSH tunneling is required by setting PCGI_TICKETING_TUNNEL_ENABLED to "true" or "false".');
|
|
67
68
|
}
|
|
68
|
-
if (!process.env.
|
|
69
|
-
throw new Error('Missing
|
|
69
|
+
if (!process.env.PCGI_TICKETING_HOST_1 || !process.env.PCGI_TICKETING_PORT_1) {
|
|
70
|
+
throw new Error('Missing PCGI_TICKETING_HOST_1 or PCGI_TICKETING_PORT_1');
|
|
70
71
|
}
|
|
71
|
-
if (process.env.
|
|
72
|
-
|
|
72
|
+
if (!process.env.PCGI_TICKETING_HOST_2 || !process.env.PCGI_TICKETING_PORT_2) {
|
|
73
|
+
throw new Error('Missing PCGI_TICKETING_HOST_2 or PCGI_TICKETING_PORT_2');
|
|
74
|
+
}
|
|
75
|
+
if (!process.env.PCGI_TICKETING_HOST_3 || !process.env.PCGI_TICKETING_PORT_3) {
|
|
76
|
+
throw new Error('Missing PCGI_TICKETING_HOST_3 or PCGI_TICKETING_PORT_3');
|
|
77
|
+
}
|
|
78
|
+
if (process.env.PCGI_TICKETING_TUNNEL_ENABLED === 'false') {
|
|
79
|
+
return `mongodb://${process.env.PCGI_TICKETING_USER}:${process.env.PCGI_TICKETING_PASSWORD}@${process.env.PCGI_TICKETING_HOST_1}:${process.env.PCGI_TICKETING_PORT_1},${process.env.PCGI_TICKETING_HOST_2}:${process.env.PCGI_TICKETING_PORT_2},${process.env.PCGI_TICKETING_HOST_3}:${process.env.PCGI_TICKETING_PORT_3}/`;
|
|
73
80
|
}
|
|
74
81
|
// SSH required
|
|
75
|
-
if (!process.env.
|
|
76
|
-
throw new Error('Missing
|
|
82
|
+
if (!process.env.PCGI_TICKETING_TUNNEL_LOCAL_PORT) {
|
|
83
|
+
throw new Error('Missing PCGI_TICKETING_TUNNEL_LOCAL_PORT');
|
|
77
84
|
}
|
|
78
|
-
if (!process.env.
|
|
85
|
+
if (!process.env.PCGI_TICKETING_TUNNEL_SSH_HOST || !process.env.PCGI_TICKETING_TUNNEL_SSH_USERNAME) {
|
|
79
86
|
throw new Error('Missing SSH config');
|
|
80
87
|
}
|
|
81
88
|
const sshConfig = {
|
|
82
89
|
forwardOptions: {
|
|
83
|
-
dstAddr: process.env.
|
|
84
|
-
dstPort: Number(process.env.
|
|
90
|
+
dstAddr: process.env.PCGI_TICKETING_HOST_1,
|
|
91
|
+
dstPort: Number(process.env.PCGI_TICKETING_PORT_1),
|
|
85
92
|
srcAddr: 'localhost',
|
|
86
|
-
srcPort: Number(process.env.
|
|
93
|
+
srcPort: Number(process.env.PCGI_TICKETING_TUNNEL_LOCAL_PORT),
|
|
87
94
|
},
|
|
88
95
|
serverOptions: {
|
|
89
|
-
port: Number(process.env.
|
|
96
|
+
port: Number(process.env.PCGI_TICKETING_TUNNEL_LOCAL_PORT),
|
|
90
97
|
},
|
|
91
98
|
sshOptions: {
|
|
92
99
|
agent: process.env.SSH_AUTH_SOCK,
|
|
93
|
-
host: process.env.
|
|
100
|
+
host: process.env.PCGI_TICKETING_TUNNEL_SSH_HOST,
|
|
94
101
|
keepaliveCountMax: 3,
|
|
95
102
|
keepaliveInterval: 10_000,
|
|
96
103
|
port: 22,
|
|
97
|
-
username: process.env.
|
|
104
|
+
username: process.env.PCGI_TICKETING_TUNNEL_SSH_USERNAME,
|
|
98
105
|
},
|
|
99
106
|
tunnelOptions: {
|
|
100
107
|
autoClose: false,
|
|
@@ -105,12 +112,12 @@ export class RAWDBService {
|
|
|
105
112
|
maxRetries: 3,
|
|
106
113
|
};
|
|
107
114
|
this.tunnel = new SshTunnelService(sshConfig, sshOptions);
|
|
108
|
-
Logger.info('[
|
|
115
|
+
Logger.info('[PCGITicketingClient] Setting up SSH Tunnel...');
|
|
109
116
|
const connection = await this.tunnel.connect();
|
|
110
117
|
const addr = connection.address();
|
|
111
118
|
if (!addr || typeof addr !== 'object') {
|
|
112
|
-
throw new Error('[
|
|
119
|
+
throw new Error('[PCGITicketingClient] Failed to retrieve SSH tunnel address.');
|
|
113
120
|
}
|
|
114
|
-
return `
|
|
121
|
+
return `mongodb://${process.env.PCGI_TICKETING_USER}:${process.env.PCGI_TICKETING_PASSWORD}@localhost:${addr.port}/`;
|
|
115
122
|
}
|
|
116
123
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { MongoClient } from 'mongodb';
|
|
2
|
+
export declare class PCGIValidationsClient {
|
|
3
|
+
private static _instance;
|
|
4
|
+
private client;
|
|
5
|
+
private tunnel;
|
|
6
|
+
/**
|
|
7
|
+
* Disallow direct instantiation of the service.
|
|
8
|
+
* Use getClient() instead to ensure singleton behavior.
|
|
9
|
+
*/
|
|
10
|
+
private constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Returns the singleton instance of the subclass.
|
|
13
|
+
*/
|
|
14
|
+
static getClient(): Promise<MongoClient>;
|
|
15
|
+
/**
|
|
16
|
+
* Connects to Mongo, setting up the client instance.
|
|
17
|
+
* If SSH tunneling is required, it establishes the tunnel first.
|
|
18
|
+
* This method is called internally by the service and should not be used directly.
|
|
19
|
+
*/
|
|
20
|
+
private connect;
|
|
21
|
+
/**
|
|
22
|
+
* Constructs the connection string based on environment variables
|
|
23
|
+
* and SSH tunneling configuration, and handles both direct connections and SSH-tunneled
|
|
24
|
+
* connections, validating the necessary environment variables for each case.
|
|
25
|
+
* This method is called internally by the service and should not be used directly.
|
|
26
|
+
* @throws Will throw an error if required environment variables are missing or if the SSH tunnel setup fails.
|
|
27
|
+
* @returns A promise that resolves to the Mongo connection string.
|
|
28
|
+
*/
|
|
29
|
+
private getConnectionString;
|
|
30
|
+
}
|