@pipeline-builder/pipeline-data 0.0.1
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/LICENSE +202 -0
- package/README.md +61 -0
- package/drizzle.config.ts +17 -0
- package/lib/api/access-control-builder.d.ts +148 -0
- package/lib/api/access-control-builder.js +199 -0
- package/lib/api/crud-service.d.ts +343 -0
- package/lib/api/crud-service.js +849 -0
- package/lib/api/query-builders.d.ts +82 -0
- package/lib/api/query-builders.js +460 -0
- package/lib/api/reporting-service.d.ts +685 -0
- package/lib/api/reporting-service.js +1564 -0
- package/lib/api/soft-delete-sweep.d.ts +65 -0
- package/lib/api/soft-delete-sweep.js +124 -0
- package/lib/api/viewer-context.d.ts +29 -0
- package/lib/api/viewer-context.js +63 -0
- package/lib/core/query-filters.d.ts +263 -0
- package/lib/core/query-filters.js +4 -0
- package/lib/database/drizzle-schema.d.ts +7357 -0
- package/lib/database/drizzle-schema.js +66 -0
- package/lib/database/index.d.ts +5 -0
- package/lib/database/index.js +8 -0
- package/lib/database/migrator.d.ts +20 -0
- package/lib/database/migrator.js +80 -0
- package/lib/database/postgres-connection.d.ts +201 -0
- package/lib/database/postgres-connection.js +413 -0
- package/lib/database/retry-strategy.d.ts +68 -0
- package/lib/database/retry-strategy.js +122 -0
- package/lib/database/schema/alert.d.ts +588 -0
- package/lib/database/schema/alert.js +130 -0
- package/lib/database/schema/compliance.d.ts +3319 -0
- package/lib/database/schema/compliance.js +377 -0
- package/lib/database/schema/dashboard.d.ts +474 -0
- package/lib/database/schema/dashboard.js +129 -0
- package/lib/database/schema/message-attachment.d.ts +183 -0
- package/lib/database/schema/message-attachment.js +40 -0
- package/lib/database/schema/message.d.ts +411 -0
- package/lib/database/schema/message.js +114 -0
- package/lib/database/schema/pipeline-template.d.ts +466 -0
- package/lib/database/schema/pipeline-template.js +80 -0
- package/lib/database/schema/pipeline.d.ts +1613 -0
- package/lib/database/schema/pipeline.js +332 -0
- package/lib/database/schema/plugin.d.ts +749 -0
- package/lib/database/schema/plugin.js +166 -0
- package/lib/database/tenancy.d.ts +103 -0
- package/lib/database/tenancy.js +167 -0
- package/lib/index.d.ts +32 -0
- package/lib/index.js +38 -0
- package/package.json +161 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createLogger } from '@pipeline-builder/api-core';
|
|
4
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
5
|
+
import { Pool } from 'pg';
|
|
6
|
+
import { schema } from './drizzle-schema.js';
|
|
7
|
+
import { ConnectionRetryStrategy } from './retry-strategy.js';
|
|
8
|
+
const logger = createLogger('database');
|
|
9
|
+
/**
|
|
10
|
+
* Get database configuration from environment variables
|
|
11
|
+
* Note: Uses environment variables directly to avoid circular dependency with pipeline-core
|
|
12
|
+
*/
|
|
13
|
+
function parseIntEnv(value, fallback) {
|
|
14
|
+
if (!value)
|
|
15
|
+
return fallback;
|
|
16
|
+
const parsed = parseInt(value, 10);
|
|
17
|
+
return Number.isNaN(parsed) ? fallback : parsed;
|
|
18
|
+
}
|
|
19
|
+
/** Detect Lambda environment for pool-size tuning */
|
|
20
|
+
const isLambda = !!process.env.AWS_LAMBDA_FUNCTION_NAME;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the pg TLS/SSL config from an explicit option or the environment,
|
|
23
|
+
* following the same env-tunable pattern as the pool sizing above.
|
|
24
|
+
*
|
|
25
|
+
* Precedence:
|
|
26
|
+
* 1. An explicit `options.ssl` (constructor arg) always wins — including an
|
|
27
|
+
* explicit `false` to force plaintext.
|
|
28
|
+
* 2. `DB_SSL` (`true`/`1` on, `false`/`0` off) or Postgres' standard
|
|
29
|
+
* `PGSSLMODE` (`disable` = off, any other mode = on).
|
|
30
|
+
* 3. Default: ON in production (RDS connections must be encrypted in transit),
|
|
31
|
+
* OFF everywhere else so a local Postgres without TLS keeps working.
|
|
32
|
+
*
|
|
33
|
+
* When enabled, `rejectUnauthorized` follows `DB_SSL_REJECT_UNAUTHORIZED`
|
|
34
|
+
* (default `false`): AWS RDS presents a cert signed by the RDS CA, which is not
|
|
35
|
+
* in Node's default trust store unless the CA bundle is mounted, so certificate
|
|
36
|
+
* VERIFICATION is opt-in to avoid breaking a stock RDS deploy — the channel is
|
|
37
|
+
* still ENCRYPTED. Set `DB_SSL_REJECT_UNAUTHORIZED=true` once the RDS CA bundle
|
|
38
|
+
* is wired to get full verification.
|
|
39
|
+
*/
|
|
40
|
+
export function getSslConfig(explicit) {
|
|
41
|
+
if (explicit !== undefined)
|
|
42
|
+
return explicit;
|
|
43
|
+
const dbSsl = process.env.DB_SSL?.toLowerCase();
|
|
44
|
+
const sslMode = process.env.PGSSLMODE?.toLowerCase();
|
|
45
|
+
let enabled;
|
|
46
|
+
if (dbSsl === 'true' || dbSsl === '1')
|
|
47
|
+
enabled = true;
|
|
48
|
+
else if (dbSsl === 'false' || dbSsl === '0')
|
|
49
|
+
enabled = false;
|
|
50
|
+
else if (sslMode)
|
|
51
|
+
enabled = sslMode !== 'disable';
|
|
52
|
+
else
|
|
53
|
+
enabled = process.env.NODE_ENV === 'production';
|
|
54
|
+
if (!enabled)
|
|
55
|
+
return false;
|
|
56
|
+
return { rejectUnauthorized: process.env.DB_SSL_REJECT_UNAUTHORIZED === 'true' };
|
|
57
|
+
}
|
|
58
|
+
function getDatabaseConfig() {
|
|
59
|
+
// Lambda: small pool (each invocation is short-lived, many concurrent instances)
|
|
60
|
+
// ECS/long-running: larger pool for sustained concurrency
|
|
61
|
+
const defaultPoolSize = isLambda ? 2 : 20;
|
|
62
|
+
const defaultIdleTimeout = isLambda ? 10000 : 30000;
|
|
63
|
+
return {
|
|
64
|
+
host: process.env.DB_HOST || 'postgres',
|
|
65
|
+
port: parseIntEnv(process.env.DB_PORT, 5432),
|
|
66
|
+
database: process.env.DATABASE || 'pipeline_builder',
|
|
67
|
+
user: process.env.DB_USER || 'postgres',
|
|
68
|
+
password: process.env.DB_PASSWORD || (process.env.NODE_ENV === 'production' ? (() => { throw new Error('DB_PASSWORD is required in production'); })() : ''),
|
|
69
|
+
maxPoolSize: parseIntEnv(process.env.DRIZZLE_MAX_POOL_SIZE, defaultPoolSize),
|
|
70
|
+
idleTimeoutMillis: parseIntEnv(process.env.DRIZZLE_IDLE_TIMEOUT_MILLIS, defaultIdleTimeout),
|
|
71
|
+
connectionTimeoutMillis: parseIntEnv(process.env.DRIZZLE_CONNECTION_TIMEOUT_MILLIS, 5000),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Singleton database connection class.
|
|
76
|
+
* Manages PostgreSQL connection pooling and Drizzle ORM instance.
|
|
77
|
+
*
|
|
78
|
+
* Features:
|
|
79
|
+
* - Singleton pattern for single connection pool
|
|
80
|
+
* - Automatic connection retry with backoff
|
|
81
|
+
* - Connection health monitoring
|
|
82
|
+
* - Graceful shutdown handling
|
|
83
|
+
* - Comprehensive error handling
|
|
84
|
+
* - Connection statistics tracking
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* import { Connection } from './connection';
|
|
89
|
+
*
|
|
90
|
+
* const connection = Connection.getInstance();
|
|
91
|
+
* const plugins = await connection.db.select().from(schema.plugin);
|
|
92
|
+
*
|
|
93
|
+
* // During shutdown
|
|
94
|
+
* await connection.close();
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export class Connection {
|
|
98
|
+
static instance = null;
|
|
99
|
+
/**
|
|
100
|
+
* Drizzle ORM database instance with schema
|
|
101
|
+
*/
|
|
102
|
+
db;
|
|
103
|
+
pool;
|
|
104
|
+
options;
|
|
105
|
+
retryStrategy;
|
|
106
|
+
isShuttingDown = false;
|
|
107
|
+
/**
|
|
108
|
+
* Private constructor to enforce singleton pattern.
|
|
109
|
+
* Initializes PostgreSQL connection pool and Drizzle ORM instance.
|
|
110
|
+
*
|
|
111
|
+
* @param options - Optional configuration for the connection
|
|
112
|
+
* @throws {Error} If database initialization fails after all retries
|
|
113
|
+
*/
|
|
114
|
+
constructor(options = {}) {
|
|
115
|
+
this.options = {
|
|
116
|
+
enableLogging: options.enableLogging ?? true,
|
|
117
|
+
enableAutoRetry: options.enableAutoRetry ?? true,
|
|
118
|
+
maxRetries: options.maxRetries ?? parseInt(process.env.DB_MAX_RETRIES || '3', 10),
|
|
119
|
+
retryDelay: options.retryDelay ?? parseInt(process.env.DB_RETRY_DELAY_MS || '1000', 10),
|
|
120
|
+
// Env-driven TLS: on-by-default in production, env-enableable elsewhere.
|
|
121
|
+
// getInstance() is normally called with no options, so this is the only
|
|
122
|
+
// place production RDS connections pick up SSL (formerly hard-coded off).
|
|
123
|
+
ssl: getSslConfig(options.ssl),
|
|
124
|
+
};
|
|
125
|
+
// Initialize retry strategy
|
|
126
|
+
this.retryStrategy = new ConnectionRetryStrategy({
|
|
127
|
+
maxRetries: this.options.maxRetries,
|
|
128
|
+
baseDelay: this.options.retryDelay,
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
const config = getDatabaseConfig();
|
|
132
|
+
const poolConfig = {
|
|
133
|
+
host: config.host,
|
|
134
|
+
port: config.port,
|
|
135
|
+
database: config.database,
|
|
136
|
+
user: config.user,
|
|
137
|
+
password: config.password,
|
|
138
|
+
max: config.maxPoolSize,
|
|
139
|
+
idleTimeoutMillis: config.idleTimeoutMillis,
|
|
140
|
+
connectionTimeoutMillis: config.connectionTimeoutMillis,
|
|
141
|
+
ssl: this.options.ssl,
|
|
142
|
+
allowExitOnIdle: true,
|
|
143
|
+
};
|
|
144
|
+
this.pool = new Pool(poolConfig);
|
|
145
|
+
this.setupEventHandlers();
|
|
146
|
+
this.db = drizzle(this.pool, { schema });
|
|
147
|
+
if (this.options.enableLogging) {
|
|
148
|
+
logger.info('Database connection initialized successfully');
|
|
149
|
+
this.logConnectionConfig(poolConfig);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
logger.error('Failed to initialize database connection:', error);
|
|
154
|
+
throw new Error('Database initialization failed');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Gets the singleton instance of the Connection class.
|
|
159
|
+
* Creates a new instance if one doesn't exist.
|
|
160
|
+
*
|
|
161
|
+
* @param options - Optional configuration (only used on first call)
|
|
162
|
+
* @returns The singleton Connection instance
|
|
163
|
+
*/
|
|
164
|
+
static getInstance(options) {
|
|
165
|
+
if (!Connection.instance) {
|
|
166
|
+
Connection.instance = new Connection(options);
|
|
167
|
+
}
|
|
168
|
+
return Connection.instance;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Resets the singleton instance.
|
|
172
|
+
* Useful for testing or reconfiguring the connection.
|
|
173
|
+
*
|
|
174
|
+
* @param closeExisting - Whether to close existing connection before reset
|
|
175
|
+
*/
|
|
176
|
+
static async reset(closeExisting = true) {
|
|
177
|
+
if (Connection.instance && closeExisting) {
|
|
178
|
+
await Connection.instance.close();
|
|
179
|
+
}
|
|
180
|
+
Connection.instance = null;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Tests the database connection
|
|
184
|
+
*
|
|
185
|
+
* @returns Promise that resolves to true if connection is healthy
|
|
186
|
+
*/
|
|
187
|
+
async testConnection() {
|
|
188
|
+
try {
|
|
189
|
+
const client = await this.pool.connect();
|
|
190
|
+
// Release even if the probe query throws — otherwise a flaky DB (the exact
|
|
191
|
+
// case this check exists for) leaks a pooled client each failure and can
|
|
192
|
+
// exhaust the pool on the retry path.
|
|
193
|
+
try {
|
|
194
|
+
const result = await client.query('SELECT 1');
|
|
195
|
+
if (this.options.enableLogging) {
|
|
196
|
+
logger.info('Database connection test successful');
|
|
197
|
+
}
|
|
198
|
+
return result.rows.length > 0;
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
client.release();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
logger.error('Database connection test failed:', error);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Gets connection pool statistics
|
|
211
|
+
*
|
|
212
|
+
* @returns Current connection pool statistics
|
|
213
|
+
*/
|
|
214
|
+
getStats() {
|
|
215
|
+
return {
|
|
216
|
+
totalCount: this.pool.totalCount,
|
|
217
|
+
idleCount: this.pool.idleCount,
|
|
218
|
+
waitingCount: this.pool.waitingCount,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Closes the database connection pool gracefully.
|
|
223
|
+
* Should be called during application shutdown.
|
|
224
|
+
*
|
|
225
|
+
* @param timeout - Maximum time to wait for connections to close (ms)
|
|
226
|
+
* @returns Promise that resolves when pool is closed
|
|
227
|
+
*/
|
|
228
|
+
async close(timeout = parseIntEnv(process.env.DB_CLOSE_TIMEOUT_MS, 5000)) {
|
|
229
|
+
if (this.isShuttingDown) {
|
|
230
|
+
logger.warn('Connection is already shutting down');
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.isShuttingDown = true;
|
|
234
|
+
try {
|
|
235
|
+
if (this.options.enableLogging) {
|
|
236
|
+
logger.info('Closing database connection pool...');
|
|
237
|
+
const stats = this.getStats();
|
|
238
|
+
logger.info(`Pool stats - Total: ${stats.totalCount}, Idle: ${stats.idleCount}, Waiting: ${stats.waitingCount}`);
|
|
239
|
+
}
|
|
240
|
+
// Set a timeout for graceful shutdown
|
|
241
|
+
const closePromise = this.pool.end();
|
|
242
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Connection close timeout')), timeout));
|
|
243
|
+
await Promise.race([closePromise, timeoutPromise]);
|
|
244
|
+
if (this.options.enableLogging) {
|
|
245
|
+
logger.info('Database connection closed successfully');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
logger.error('Error closing database connection:', error);
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
this.isShuttingDown = false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Checks if the connection is shutting down
|
|
258
|
+
*
|
|
259
|
+
* @returns true if connection is in shutdown state
|
|
260
|
+
*/
|
|
261
|
+
isClosing() {
|
|
262
|
+
return this.isShuttingDown;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Sets up event handlers for the connection pool
|
|
266
|
+
*/
|
|
267
|
+
setupEventHandlers() {
|
|
268
|
+
this.pool.on('error', (err) => {
|
|
269
|
+
logger.error('Unexpected error on idle client:', err);
|
|
270
|
+
if (this.options.enableAutoRetry && this.retryStrategy.getAttempts() < this.options.maxRetries) {
|
|
271
|
+
void this.retryStrategy.handleConnectionError(err, () => this.testConnection()).catch((retryErr) => {
|
|
272
|
+
logger.error('Connection retry error:', retryErr);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
this.pool.on('connect', () => {
|
|
277
|
+
this.retryStrategy.reset(); // Reset on successful connection
|
|
278
|
+
if (this.options.enableLogging) {
|
|
279
|
+
logger.debug('New database connection established');
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
this.pool.on('remove', () => {
|
|
283
|
+
if (this.options.enableLogging) {
|
|
284
|
+
logger.debug('Client removed from pool');
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Logs connection configuration (sanitized)
|
|
290
|
+
*/
|
|
291
|
+
logConnectionConfig(config) {
|
|
292
|
+
logger.info('Database Configuration:', {
|
|
293
|
+
host: `${config.host}:${config.port}`,
|
|
294
|
+
database: config.database,
|
|
295
|
+
user: config.user,
|
|
296
|
+
maxPoolSize: config.max,
|
|
297
|
+
idleTimeoutMs: config.idleTimeoutMillis,
|
|
298
|
+
connectionTimeoutMs: config.connectionTimeoutMillis,
|
|
299
|
+
ssl: config.ssl ? 'enabled' : 'disabled',
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Singleton database instance for use throughout the application.
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* import { db } from './connection';
|
|
309
|
+
*
|
|
310
|
+
* // Select queries
|
|
311
|
+
* const plugins = await db.select().from(schema.plugin);
|
|
312
|
+
*
|
|
313
|
+
* // Insert queries
|
|
314
|
+
* await db.insert(schema.plugin).values({ name: 'my-plugin' });
|
|
315
|
+
*
|
|
316
|
+
* // Transactions
|
|
317
|
+
* await db.transaction(async (tx) => {
|
|
318
|
+
* await tx.insert(schema.plugin).values({ ... });
|
|
319
|
+
* await tx.update(schema.plugin).set({ ... });
|
|
320
|
+
* });
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
// Lazy initialization to avoid race condition on module load
|
|
324
|
+
let _dbInstance = null;
|
|
325
|
+
/**
|
|
326
|
+
* Get the database instance with lazy initialization
|
|
327
|
+
* This avoids the race condition where the module is loaded before environment is configured
|
|
328
|
+
*/
|
|
329
|
+
function getDbInstance() {
|
|
330
|
+
if (!_dbInstance) {
|
|
331
|
+
_dbInstance = Connection.getInstance().db;
|
|
332
|
+
}
|
|
333
|
+
return _dbInstance;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Proxy-based lazy database instance
|
|
337
|
+
* The actual connection is only created when first accessed
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```typescript
|
|
341
|
+
* import { db } from './connection';
|
|
342
|
+
*
|
|
343
|
+
* // Connection is created here on first use, not on import
|
|
344
|
+
* const plugins = await db.select().from(schema.plugin);
|
|
345
|
+
* ```
|
|
346
|
+
*/
|
|
347
|
+
export const db = new Proxy({}, {
|
|
348
|
+
get(_, prop) {
|
|
349
|
+
const instance = getDbInstance();
|
|
350
|
+
const value = instance[prop];
|
|
351
|
+
// Bind methods to the instance to preserve 'this' context
|
|
352
|
+
if (typeof value === 'function') {
|
|
353
|
+
return value.bind(instance);
|
|
354
|
+
}
|
|
355
|
+
return value;
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
/**
|
|
359
|
+
* Gets the Connection instance for advanced operations
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* import { getConnection } from './connection';
|
|
364
|
+
*
|
|
365
|
+
* const connection = getConnection();
|
|
366
|
+
* const stats = connection.getStats();
|
|
367
|
+
* console.log(`Active connections: ${stats.totalCount}`);
|
|
368
|
+
* ```
|
|
369
|
+
*/
|
|
370
|
+
export function getConnection() {
|
|
371
|
+
return Connection.getInstance();
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Closes the database connection
|
|
375
|
+
* Should be called during application shutdown
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* import { closeConnection } from './connection';
|
|
380
|
+
*
|
|
381
|
+
* process.on('SIGTERM', async () => {
|
|
382
|
+
* await closeConnection();
|
|
383
|
+
* process.exit(0);
|
|
384
|
+
* });
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
export async function closeConnection() {
|
|
388
|
+
const connection = Connection.getInstance();
|
|
389
|
+
await connection.close();
|
|
390
|
+
_dbInstance = null; // Reset lazy instance
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Tests the database connection
|
|
394
|
+
*
|
|
395
|
+
* @returns Promise that resolves to true if connection is healthy
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```typescript
|
|
399
|
+
* import { testConnection } from './connection';
|
|
400
|
+
*
|
|
401
|
+
* if (await testConnection()) {
|
|
402
|
+
* console.log('Database is ready');
|
|
403
|
+
* } else {
|
|
404
|
+
* console.error('Database connection failed');
|
|
405
|
+
* process.exit(1);
|
|
406
|
+
* }
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
export async function testConnection() {
|
|
410
|
+
const connection = Connection.getInstance();
|
|
411
|
+
return connection.testConnection();
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXMtY29ubmVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9wb3N0Z3Jlcy1jb25uZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsSUFBSSxFQUFtQixNQUFNLElBQUksQ0FBQztBQUMzQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFOUQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBRXhDOzs7R0FHRztBQUNILFNBQVMsV0FBVyxDQUFDLEtBQXlCLEVBQUUsUUFBZ0I7SUFDOUQsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUM1QixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDbEQsQ0FBQztBQUVELHFEQUFxRDtBQUNyRCxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQztBQUV4RDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxRQUFtQztJQUM5RCxJQUFJLFFBQVEsS0FBSyxTQUFTO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFFNUMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVB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TUFBTSxVQUFVLGFBQWE7SUFDM0IsT0FBTyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDbEMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGVBQWU7SUFDbkMsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzVDLE1BQU0sVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3pCLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQyxzQkFBc0I7QUFDNUMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjO0lBQ2xDLE1BQU0sVUFBVSxHQUFHLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1QyxPQUFPLFVBQVUsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IGRyaXp6bGUgfSBmcm9tICdkcml6emxlLW9ybS9ub2RlLXBvc3RncmVzJztcbmltcG9ydCB7IFBvb2wsIHR5cGUgUG9vbENvbmZpZyB9IGZyb20gJ3BnJztcbmltcG9ydCB7IHNjaGVtYSB9IGZyb20gJy4vZHJpenpsZS1zY2hlbWEuanMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvblJldHJ5U3RyYXRlZ3kgfSBmcm9tICcuL3JldHJ5LXN0cmF0ZWd5LmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdkYXRhYmFzZScpO1xuXG4vKipcbiAqIEdldCBkYXRhYmFzZSBjb25maWd1cmF0aW9uIGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gKiBOb3RlOiBVc2VzIGVudmlyb25tZW50IHZhcmlhYmxlcyBkaXJlY3RseSB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmN5IHdpdGggcGlwZWxpbmUtY29yZVxuICovXG5mdW5jdGlvbiBwYXJzZUludEVudih2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkLCBmYWxsYmFjazogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIGZhbGxiYWNrO1xuICBjb25zdCBwYXJzZWQgPSBwYXJzZUludCh2YWx1ZSwgMTApO1xuICByZXR1cm4gTnVtYmVyLmlzTmFOKHBhcnNlZCkgPyBmYWxsYmFjayA6IHBhcnNlZDtcbn1cblxuLyoqIERldGVjdCBMYW1iZGEgZW52aXJvbm1lbnQgZm9yIHBvb2wtc2l6ZSB0dW5pbmcgKi9cbmNvbnN0IGlzTGFtYmRhID0gISFwcm9jZXNzLmVudi5BV1NfTEFNQkRBX0ZVTkNUSU9OX05BTUU7XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgcGcgVExTL1NTTCBjb25maWcgZnJvbSBhbiBleHBsaWNpdCBvcHRpb24gb3IgdGhlIGVudmlyb25tZW50LFxuICogZm9sbG93aW5nIHRoZSBzYW1lIGVudi10dW5hYmxlIHBhdHRlcm4gYXMgdGhlIHBvb2wgc2l6aW5nIGFib3ZlLlxuICpcbiAqIFByZWNlZGVuY2U6XG4gKiAgIDEuIEFuIGV4cGxpY2l0IGBvcHRpb25zLnNzbGAgKGNvbnN0cnVjdG9yIGFyZykgYWx3YXlzIHdpbnMg4oCUIGluY2x1ZGluZyBhblxuICogICAgICBleHBsaWNpdCBgZmFsc2VgIHRvIGZvcmNlIHBsYWludGV4dC5cbiAqICAgMi4gYERCX1NTTGAgKGB0cnVlYC9gMWAgb24sIGBmYWxzZWAvYDBgIG9mZikgb3IgUG9zdGdyZXMnIHN0YW5kYXJkXG4gKiAgICAgIGBQR1NTTE1PREVgIChgZGlzYWJsZWAgPSBvZmYsIGFueSBvdGhlciBtb2RlID0gb24pLlxuICogICAzLiBEZWZhdWx0OiBPTiBpbiBwcm9kdWN0aW9uIChSRFMgY29ubmVjdGlvbnMgbXVzdCBiZSBlbmNyeXB0ZWQgaW4gdHJhbnNpdCksXG4gKiAgICAgIE9GRiBldmVyeXdoZXJlIGVsc2Ugc28gYSBsb2NhbCBQb3N0Z3JlcyB3aXRob3V0IFRMUyBrZWVwcyB3b3JraW5nLlxuICpcbiAqIFdoZW4gZW5hYmxlZCwgYHJlamVjdFVuYXV0aG9yaXplZGAgZm9sbG93cyBgREJfU1NMX1JFSkVDVF9VTkFVVEhPUklaRURgXG4gKiAoZGVmYXVsdCBgZmFsc2VgKTogQVdTIFJEUyBwcmVzZW50cyBhIGNlcnQgc2lnbmVkIGJ5IHRoZSBSRFMgQ0EsIHdoaWNoIGlzIG5vdFxuICogaW4gTm9kZSdzIGRlZmF1bHQgdHJ1c3Qgc3RvcmUgdW5sZXNzIHRoZSBDQSBidW5kbGUgaXMgbW91bnRlZCwgc28gY2VydGlmaWNhdGVcbiAqIFZFUklGSUNBVElPTiBpcyBvcHQtaW4gdG8gYXZvaWQgYnJlYWtpbmcgYSBzdG9jayBSRFMgZGVwbG95IOKAlCB0aGUgY2hhbm5lbCBpc1xuICogc3RpbGwgRU5DUllQVEVELiBTZXQgYERCX1NTTF9SRUpFQ1RfVU5BVVRIT1JJWkVEPXRydWVgIG9uY2UgdGhlIFJEUyBDQSBidW5kbGVcbiAqIGlzIHdpcmVkIHRvIGdldCBmdWxsIHZlcmlmaWNhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFNzbENvbmZpZyhleHBsaWNpdD86IENvbm5lY3Rpb25PcHRpb25zWydzc2wnXSk6IGJvb2xlYW4gfCB7IHJlamVjdFVuYXV0aG9yaXplZDogYm9vbGVhbiB9IHtcbiAgaWYgKGV4cGxpY2l0ICE9PSB1bmRlZmluZWQpIHJldHVybiBleHBsaWNpdDtcblxuICBjb25zdCBkYlNzbCA9IHByb2Nlc3MuZW52LkRCX1NTTD8udG9Mb3dlckNhc2UoKTtcbiAgY29uc3Qgc3NsTW9kZSA9IHByb2Nlc3MuZW52LlBHU1NMTU9ERT8udG9Mb3dlckNhc2UoKTtcblxuICBsZXQgZW5hYmxlZDogYm9vbGVhbjtcbiAgaWYgKGRiU3NsID09PSAndHJ1ZScgfHwgZGJTc2wgPT09ICcxJykgZW5hYmxlZCA9IHRydWU7XG4gIGVsc2UgaWYgKGRiU3NsID09PSAnZmFsc2UnIHx8IGRiU3NsID09PSAnMCcpIGVuYWJsZWQgPSBmYWxzZTtcbiAgZWxzZSBpZiAoc3NsTW9kZSkgZW5hYmxlZCA9IHNzbE1vZGUgIT09ICdkaXNhYmxlJztcbiAgZWxzZSBlbmFibGVkID0gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJztcblxuICBpZiAoIWVuYWJsZWQpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHsgcmVqZWN0VW5hdXRob3JpemVkOiBwcm9jZXNzLmVudi5EQl9TU0xfUkVKRUNUX1VOQVVUSE9SSVpFRCA9PT0gJ3RydWUnIH07XG59XG5cbmZ1bmN0aW9uIGdldERhdGFiYXNlQ29uZmlnKCkge1xuICAvLyBMYW1iZGE6IHNtYWxsIHBvb2wgKGVhY2ggaW52b2NhdGlvbiBpcyBzaG9ydC1saXZlZCwgbWFueSBjb25jdXJyZW50IGluc3RhbmNlcylcbiAgLy8gRUNTL2xvbmctcnVubmluZzogbGFyZ2VyIHBvb2wgZm9yIHN1c3RhaW5lZCBjb25jdXJyZW5jeVxuICBjb25zdCBkZWZhdWx0UG9vbFNpemUgPSBpc0xhbWJkYSA/IDIgOiAyMDtcbiAgY29uc3QgZGVmYXVsdElkbGVUaW1lb3V0ID0gaXNMYW1iZGEgPyAxMDAwMCA6IDMwMDAwO1xuXG4gIHJldHVybiB7XG4gICAgaG9zdDogcHJvY2Vzcy5lbnYuREJfSE9TVCB8fCAncG9zdGdyZXMnLFxuICAgIHBvcnQ6IHBhcnNlSW50RW52KHByb2Nlc3MuZW52LkRCX1BPUlQsIDU0MzIpLFxuICAgIGRhdGFiYXNlOiBwcm9jZXNzLmVudi5EQVRBQkFTRSB8fCAncGlwZWxpbmVfYnVpbGRlcicsXG4gICAgdXNlcjogcHJvY2Vzcy5lbnYuREJfVVNFUiB8fCAncG9zdGdyZXMnLFxuICAgIHBhc3N3b3JkOiBwcm9jZXNzLmVudi5EQl9QQVNTV09SRCB8fCAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJyA/ICgoKSA9PiB7IHRocm93IG5ldyBFcnJvcignREJfUEFTU1dPUkQgaXMgcmVxdWlyZWQgaW4gcHJvZHVjdGlvbicpOyB9KSgpIGFzIHN0cmluZyA6ICcnKSxcbiAgICBtYXhQb29sU2l6ZTogcGFyc2VJbnRFbnYocHJvY2Vzcy5lbnYuRFJJWlpMRV9NQVhfUE9PTF9TSVpFLCBkZWZhdWx0UG9vbFNpemUpLFxuICAgIGlkbGVUaW1lb3V0TWlsbGlzOiBwYXJzZUludEVudihwcm9jZXNzLmVudi5EUklaWkxFX0lETEVfVElNRU9VVF9NSUxMSVMsIGRlZmF1bHRJZGxlVGltZW91dCksXG4gICAgY29ubmVjdGlvblRpbWVvdXRNaWxsaXM6IHBhcnNlSW50RW52KHByb2Nlc3MuZW52LkRSSVpaTEVfQ09OTkVDVElPTl9USU1FT1VUX01JTExJUywgNTAwMCksXG4gIH07XG59XG5cbi8qKlxuICogRGF0YWJhc2UgY29ubmVjdGlvbiBzdGF0aXN0aWNzIGZvciBtb25pdG9yaW5nXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdGlvblN0YXRzIHtcbiAgdG90YWxDb3VudDogbnVtYmVyO1xuICBpZGxlQ291bnQ6IG51bWJlcjtcbiAgd2FpdGluZ0NvdW50OiBudW1iZXI7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgdGhlIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb25uZWN0aW9uT3B0aW9ucyB7XG4gIC8qKiBXaGV0aGVyIHRvIGVuYWJsZSBjb25uZWN0aW9uIGxvZ2dpbmcgKi9cbiAgZW5hYmxlTG9nZ2luZz86IGJvb2xlYW47XG5cbiAgLyoqIFdoZXRoZXIgdG8gYXV0b21hdGljYWxseSByZXRyeSBmYWlsZWQgY29ubmVjdGlvbnMgKi9cbiAgZW5hYmxlQXV0b1JldHJ5PzogYm9vbGVhbjtcblxuICAvKiogTWF4aW11bSBudW1iZXIgb2YgY29ubmVjdGlvbiByZXRyeSBhdHRlbXB0cyAqL1xuICBtYXhSZXRyaWVzPzogbnVtYmVyO1xuXG4gIC8qKiBEZWxheSBiZXR3ZWVuIHJldHJ5IGF0dGVtcHRzIGluIG1pbGxpc2Vjb25kcyAqL1xuICByZXRyeURlbGF5PzogbnVtYmVyO1xuXG4gIC8qKiBTU0wgY29uZmlndXJhdGlvbiAqL1xuICBzc2w/OiBib29sZWFuIHwgeyByZWplY3RVbmF1dGhvcml6ZWQ6IGJvb2xlYW4gfTtcbn1cblxuLyoqXG4gKiBTaW5nbGV0b24gZGF0YWJhc2UgY29ubmVjdGlvbiBjbGFzcy5cbiAqIE1hbmFnZXMgUG9zdGdyZVNRTCBjb25uZWN0aW9uIHBvb2xpbmcgYW5kIERyaXp6bGUgT1JNIGluc3RhbmNlLlxuICpcbiAqIEZlYXR1cmVzOlxuICogLSBTaW5nbGV0b24gcGF0dGVybiBmb3Igc2luZ2xlIGNvbm5lY3Rpb24gcG9vbFxuICogLSBBdXRvbWF0aWMgY29ubmVjdGlvbiByZXRyeSB3aXRoIGJhY2tvZmZcbiAqIC0gQ29ubmVjdGlvbiBoZWFsdGggbW9uaXRvcmluZ1xuICogLSBHcmFjZWZ1bCBzaHV0ZG93biBoYW5kbGluZ1xuICogLSBDb21wcmVoZW5zaXZlIGVycm9yIGhhbmRsaW5nXG4gKiAtIENvbm5lY3Rpb24gc3RhdGlzdGljcyB0cmFja2luZ1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9jb25uZWN0aW9uJztcbiAqXG4gKiBjb25zdCBjb25uZWN0aW9uID0gQ29ubmVjdGlvbi5nZXRJbnN0YW5jZSgpO1xuICogY29uc3QgcGx1Z2lucyA9IGF3YWl0IGNvbm5lY3Rpb24uZGIuc2VsZWN0KCkuZnJvbShzY2hlbWEucGx1Z2luKTtcbiAqXG4gKiAvLyBEdXJpbmcgc2h1dGRvd25cbiAqIGF3YWl0IGNvbm5lY3Rpb24uY2xvc2UoKTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG4gIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBDb25uZWN0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIERyaXp6bGUgT1JNIGRhdGFiYXNlIGluc3RhbmNlIHdpdGggc2NoZW1hXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZGI6IFJldHVyblR5cGU8dHlwZW9mIGRyaXp6bGU+O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcG9vbDogUG9vbDtcbiAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBSZXF1aXJlZDxDb25uZWN0aW9uT3B0aW9ucz47XG4gIHByaXZhdGUgcmVhZG9ubHkgcmV0cnlTdHJhdGVneTogQ29ubmVjdGlvblJldHJ5U3RyYXRlZ3k7XG4gIHByaXZhdGUgaXNTaHV0dGluZ0Rvd24gPSBmYWxzZTtcblxuICAvKipcbiAgICogUHJpdmF0ZSBjb25zdHJ1Y3RvciB0byBlbmZvcmNlIHNpbmdsZXRvbiBwYXR0ZXJuLlxuICAgKiBJbml0aWFsaXplcyBQb3N0Z3JlU1FMIGNvbm5lY3Rpb24gcG9vbCBhbmQgRHJpenpsZSBPUk0gaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9uYWwgY29uZmlndXJhdGlvbiBmb3IgdGhlIGNvbm5lY3Rpb25cbiAgICogQHRocm93cyB7RXJyb3J9IElmIGRhdGFiYXNlIGluaXRpYWxpemF0aW9uIGZhaWxzIGFmdGVyIGFsbCByZXRyaWVzXG4gICAqL1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKG9wdGlvbnM6IENvbm5lY3Rpb25PcHRpb25zID0ge30pIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICBlbmFibGVMb2dnaW5nOiBvcHRpb25zLmVuYWJsZUxvZ2dpbmcgPz8gdHJ1ZSxcbiAgICAgIGVuYWJsZUF1dG9SZXRyeTogb3B0aW9ucy5lbmFibGVBdXRvUmV0cnkgPz8gdHJ1ZSxcbiAgICAgIG1heFJldHJpZXM6IG9wdGlvbnMubWF4UmV0cmllcyA/PyBwYXJzZUludChwcm9jZXNzLmVudi5EQl9NQVhfUkVUUklFUyB8fCAnMycsIDEwKSxcbiAgICAgIHJldHJ5RGVsYXk6IG9wdGlvbnMucmV0cnlEZWxheSA/PyBwYXJzZUludChwcm9jZXNzLmVudi5EQl9SRVRSWV9ERUxBWV9NUyB8fCAnMTAwMCcsIDEwKSxcbiAgICAgIC8vIEVudi1kcml2ZW4gVExTOiBvbi1ieS1kZWZhdWx0IGluIHByb2R1Y3Rpb24sIGVudi1lbmFibGVhYmxlIGVsc2V3aGVyZS5cbiAgICAgIC8vIGdldEluc3RhbmNlKCkgaXMgbm9ybWFsbHkgY2FsbGVkIHdpdGggbm8gb3B0aW9ucywgc28gdGhpcyBpcyB0aGUgb25seVxuICAgICAgLy8gcGxhY2UgcHJvZHVjdGlvbiBSRFMgY29ubmVjdGlvbnMgcGljayB1cCBTU0wgKGZvcm1lcmx5IGhhcmQtY29kZWQgb2ZmKS5cbiAgICAgIHNzbDogZ2V0U3NsQ29uZmlnKG9wdGlvbnMuc3NsKSxcbiAgICB9O1xuXG4gICAgLy8gSW5pdGlhbGl6ZSByZXRyeSBzdHJhdGVneVxuICAgIHRoaXMucmV0cnlTdHJhdGVneSA9IG5ldyBDb25uZWN0aW9uUmV0cnlTdHJhdGVneSh7XG4gICAgICBtYXhSZXRyaWVzOiB0aGlzLm9wdGlvbnMubWF4UmV0cmllcyxcbiAgICAgIGJhc2VEZWxheTogdGhpcy5vcHRpb25zLnJldHJ5RGVsYXksXG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgY29uZmlnID0gZ2V0RGF0YWJhc2VDb25maWcoKTtcblxuICAgICAgY29uc3QgcG9vbENvbmZpZzogUG9vbENvbmZpZyA9IHtcbiAgICAgICAgaG9zdDogY29uZmlnLmhvc3QsXG4gICAgICAgIHBvcnQ6IGNvbmZpZy5wb3J0LFxuICAgICAgICBkYXRhYmFzZTogY29uZmlnLmRhdGFiYXNlLFxuICAgICAgICB1c2VyOiBjb25maWcudXNlcixcbiAgICAgICAgcGFzc3dvcmQ6IGNvbmZpZy5wYXNzd29yZCxcbiAgICAgICAgbWF4OiBjb25maWcubWF4UG9vbFNpemUsXG4gICAgICAgIGlkbGVUaW1lb3V0TWlsbGlzOiBjb25maWcuaWRsZVRpbWVvdXRNaWxsaXMsXG4gICAgICAgIGNvbm5lY3Rpb25UaW1lb3V0TWlsbGlzOiBjb25maWcuY29ubmVjdGlvblRpbWVvdXRNaWxsaXMsXG4gICAgICAgIHNzbDogdGhpcy5vcHRpb25zLnNzbCxcbiAgICAgICAgYWxsb3dFeGl0T25JZGxlOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5wb29sID0gbmV3IFBvb2wocG9vbENvbmZpZyk7XG4gICAgICB0aGlzLnNldHVwRXZlbnRIYW5kbGVycygpO1xuXG4gICAgICB0aGlzLmRiID0gZHJpenpsZSh0aGlzLnBvb2wsIHsgc2NoZW1hIH0pO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmVuYWJsZUxvZ2dpbmcpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ0RhdGFiYXNlIGNvbm5lY3Rpb24gaW5pdGlhbGl6ZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAgICAgIHRoaXMubG9nQ29ubmVjdGlvbkNvbmZpZyhwb29sQ29uZmlnKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdGYWlsZWQgdG8gaW5pdGlhbGl6ZSBkYXRhYmFzZSBjb25uZWN0aW9uOicsIGVycm9yKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRGF0YWJhc2UgaW5pdGlhbGl6YXRpb24gZmFpbGVkJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHNpbmdsZXRvbiBpbnN0YW5jZSBvZiB0aGUgQ29ubmVjdGlvbiBjbGFzcy5cbiAgICogQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBpZiBvbmUgZG9lc24ndCBleGlzdC5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25hbCBjb25maWd1cmF0aW9uIChvbmx5IHVzZWQgb24gZmlyc3QgY2FsbClcbiAgICogQHJldHVybnMgVGhlIHNpbmdsZXRvbiBDb25uZWN0aW9uIGluc3RhbmNlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldEluc3RhbmNlKG9wdGlvbnM/OiBDb25uZWN0aW9uT3B0aW9ucyk6IENvbm5lY3Rpb24ge1xuICAgIGlmICghQ29ubmVjdGlvbi5pbnN0YW5jZSkge1xuICAgICAgQ29ubmVjdGlvbi5pbnN0YW5jZSA9IG5ldyBDb25uZWN0aW9uKG9wdGlvbnMpO1xuICAgIH1cbiAgICByZXR1cm4gQ29ubmVjdGlvbi5pbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldHMgdGhlIHNpbmdsZXRvbiBpbnN0YW5jZS5cbiAgICogVXNlZnVsIGZvciB0ZXN0aW5nIG9yIHJlY29uZmlndXJpbmcgdGhlIGNvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBjbG9zZUV4aXN0aW5nIC0gV2hldGhlciB0byBjbG9zZSBleGlzdGluZyBjb25uZWN0aW9uIGJlZm9yZSByZXNldFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhc3luYyByZXNldChjbG9zZUV4aXN0aW5nOiBib29sZWFuID0gdHJ1ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChDb25uZWN0aW9uLmluc3RhbmNlICYmIGNsb3NlRXhpc3RpbmcpIHtcbiAgICAgIGF3YWl0IENvbm5lY3Rpb24uaW5zdGFuY2UuY2xvc2UoKTtcbiAgICB9XG4gICAgQ29ubmVjdGlvbi5pbnN0YW5jZSA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogVGVzdHMgdGhlIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRydWUgaWYgY29ubmVjdGlvbiBpcyBoZWFsdGh5XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdGVzdENvbm5lY3Rpb24oKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMucG9vbC5jb25uZWN0KCk7XG4gICAgICAvLyBSZWxlYXNlIGV2ZW4gaWYgdGhlIHByb2JlIHF1ZXJ5IHRocm93cyDigJQgb3RoZXJ3aXNlIGEgZmxha3kgREIgKHRoZSBleGFjdFxuICAgICAgLy8gY2FzZSB0aGlzIGNoZWNrIGV4aXN0cyBmb3IpIGxlYWtzIGEgcG9vbGVkIGNsaWVudCBlYWNoIGZhaWx1cmUgYW5kIGNhblxuICAgICAgLy8gZXhoYXVzdCB0aGUgcG9vbCBvbiB0aGUgcmV0cnkgcGF0aC5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5xdWVyeSgnU0VMRUNUIDEnKTtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5lbmFibGVMb2dnaW5nKSB7XG4gICAgICAgICAgbG9nZ2VyLmluZm8oJ0RhdGFiYXNlIGNvbm5lY3Rpb24gdGVzdCBzdWNjZXNzZnVsJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdC5yb3dzLmxlbmd0aCA+IDA7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBjbGllbnQucmVsZWFzZSgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0RhdGFiYXNlIGNvbm5lY3Rpb24gdGVzdCBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGNvbm5lY3Rpb24gcG9vbCBzdGF0aXN0aWNzXG4gICAqXG4gICAqIEByZXR1cm5zIEN1cnJlbnQgY29ubmVjdGlvbiBwb29sIHN0YXRpc3RpY3NcbiAgICovXG4gIHB1YmxpYyBnZXRTdGF0cygpOiBDb25uZWN0aW9uU3RhdHMge1xuICAgIHJldHVybiB7XG4gICAgICB0b3RhbENvdW50OiB0aGlzLnBvb2wudG90YWxDb3VudCxcbiAgICAgIGlkbGVDb3VudDogdGhpcy5wb29sLmlkbGVDb3VudCxcbiAgICAgIHdhaXRpbmdDb3VudDogdGhpcy5wb29sLndhaXRpbmdDb3VudCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyB0aGUgZGF0YWJhc2UgY29ubmVjdGlvbiBwb29sIGdyYWNlZnVsbHkuXG4gICAqIFNob3VsZCBiZSBjYWxsZWQgZHVyaW5nIGFwcGxpY2F0aW9uIHNodXRkb3duLlxuICAgKlxuICAgKiBAcGFyYW0gdGltZW91dCAtIE1heGltdW0gdGltZSB0byB3YWl0IGZvciBjb25uZWN0aW9ucyB0byBjbG9zZSAobXMpXG4gICAqIEByZXR1cm5zIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHBvb2wgaXMgY2xvc2VkXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgY2xvc2UodGltZW91dDogbnVtYmVyID0gcGFyc2VJbnRFbnYocHJvY2Vzcy5lbnYuREJfQ0xPU0VfVElNRU9VVF9NUywgNTAwMCkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pc1NodXR0aW5nRG93bikge1xuICAgICAgbG9nZ2VyLndhcm4oJ0Nvbm5lY3Rpb24gaXMgYWxyZWFkeSBzaHV0dGluZyBkb3duJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5pc1NodXR0aW5nRG93biA9IHRydWU7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5lbmFibGVMb2dnaW5nKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKCdDbG9zaW5nIGRhdGFiYXNlIGNvbm5lY3Rpb24gcG9vbC4uLicpO1xuICAgICAgICBjb25zdCBzdGF0cyA9IHRoaXMuZ2V0U3RhdHMoKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFBvb2wgc3RhdHMgLSBUb3RhbDogJHtzdGF0cy50b3RhbENvdW50fSwgSWRsZTogJHtzdGF0cy5pZGxlQ291bnR9LCBXYWl0aW5nOiAke3N0YXRzLndhaXRpbmdDb3VudH1gKTtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IGEgdGltZW91dCBmb3IgZ3JhY2VmdWwgc2h1dGRvd25cbiAgICAgIGNvbnN0IGNsb3NlUHJvbWlzZSA9IHRoaXMucG9vbC5lbmQoKTtcbiAgICAgIGNvbnN0IHRpbWVvdXRQcm9taXNlID0gbmV3IFByb21pc2UoKF8sIHJlamVjdCkgPT5cbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiByZWplY3QobmV3IEVycm9yKCdDb25uZWN0aW9uIGNsb3NlIHRpbWVvdXQnKSksIHRpbWVvdXQpLFxuICAgICAgKTtcblxuICAgICAgYXdhaXQgUHJvbWlzZS5yYWNlKFtjbG9zZVByb21pc2UsIHRpbWVvdXRQcm9taXNlXSk7XG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZW5hYmxlTG9nZ2luZykge1xuICAgICAgICBsb2dnZXIuaW5mbygnRGF0YWJhc2UgY29ubmVjdGlvbiBjbG9zZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgY2xvc2luZyBkYXRhYmFzZSBjb25uZWN0aW9uOicsIGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmlzU2h1dHRpbmdEb3duID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgY29ubmVjdGlvbiBpcyBzaHV0dGluZyBkb3duXG4gICAqXG4gICAqIEByZXR1cm5zIHRydWUgaWYgY29ubmVjdGlvbiBpcyBpbiBzaHV0ZG93biBzdGF0ZVxuICAgKi9cbiAgcHVibGljIGlzQ2xvc2luZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc1NodXR0aW5nRG93bjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHVwIGV2ZW50IGhhbmRsZXJzIGZvciB0aGUgY29ubmVjdGlvbiBwb29sXG4gICAqL1xuICBwcml2YXRlIHNldHVwRXZlbnRIYW5kbGVycygpOiB2b2lkIHtcbiAgICB0aGlzLnBvb2wub24oJ2Vycm9yJywgKGVycikgPT4ge1xuICAgICAgbG9nZ2VyLmVycm9yKCdVbmV4cGVjdGVkIGVycm9yIG9uIGlkbGUgY2xpZW50OicsIGVycik7XG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZW5hYmxlQXV0b1JldHJ5ICYmIHRoaXMucmV0cnlTdHJhdGVneS5nZXRBdHRlbXB0cygpIDwgdGhpcy5vcHRpb25zLm1heFJldHJpZXMpIHtcbiAgICAgICAgdm9pZCB0aGlzLnJldHJ5U3RyYXRlZ3kuaGFuZGxlQ29ubmVjdGlvbkVycm9yKGVyciwgKCkgPT4gdGhpcy50ZXN0Q29ubmVjdGlvbigpKS5jYXRjaCgocmV0cnlFcnIpID0+IHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Nvbm5lY3Rpb24gcmV0cnkgZXJyb3I6JywgcmV0cnlFcnIpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMucG9vbC5vbignY29ubmVjdCcsICgpID0+IHtcbiAgICAgIHRoaXMucmV0cnlTdHJhdGVneS5yZXNldCgpOyAvLyBSZXNldCBvbiBzdWNjZXNzZnVsIGNvbm5lY3Rpb25cblxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5lbmFibGVMb2dnaW5nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnTmV3IGRhdGFiYXNlIGNvbm5lY3Rpb24gZXN0YWJsaXNoZWQnKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMucG9vbC5vbigncmVtb3ZlJywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5lbmFibGVMb2dnaW5nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQ2xpZW50IHJlbW92ZWQgZnJvbSBwb29sJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTG9ncyBjb25uZWN0aW9uIGNvbmZpZ3VyYXRpb24gKHNhbml0aXplZClcbiAgICovXG4gIHByaXZhdGUgbG9nQ29ubmVjdGlvbkNvbmZpZyhjb25maWc6IFBvb2xDb25maWcpOiB2b2lkIHtcbiAgICBsb2dnZXIuaW5mbygnRGF0YWJhc2UgQ29uZmlndXJhdGlvbjonLCB7XG4gICAgICBob3N0OiBgJHtjb25maWcuaG9zdH06JHtjb25maWcucG9ydH1gLFxuICAgICAgZGF0YWJhc2U6IGNvbmZpZy5kYXRhYmFzZSxcbiAgICAgIHVzZXI6IGNvbmZpZy51c2VyLFxuICAgICAgbWF4UG9vbFNpemU6IGNvbmZpZy5tYXgsXG4gICAgICBpZGxlVGltZW91dE1zOiBjb25maWcuaWRsZVRpbWVvdXRNaWxsaXMsXG4gICAgICBjb25uZWN0aW9uVGltZW91dE1zOiBjb25maWcuY29ubmVjdGlvblRpbWVvdXRNaWxsaXMsXG4gICAgICBzc2w6IGNvbmZpZy5zc2wgPyAnZW5hYmxlZCcgOiAnZGlzYWJsZWQnLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogU2luZ2xldG9uIGRhdGFiYXNlIGluc3RhbmNlIGZvciB1c2UgdGhyb3VnaG91dCB0aGUgYXBwbGljYXRpb24uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGRiIH0gZnJvbSAnLi9jb25uZWN0aW9uJztcbiAqXG4gKiAvLyBTZWxlY3QgcXVlcmllc1xuICogY29uc3QgcGx1Z2lucyA9IGF3YWl0IGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLnBsdWdpbik7XG4gKlxuICogLy8gSW5zZXJ0IHF1ZXJpZXNcbiAqIGF3YWl0IGRiLmluc2VydChzY2hlbWEucGx1Z2luKS52YWx1ZXMoeyBuYW1lOiAnbXktcGx1Z2luJyB9KTtcbiAqXG4gKiAvLyBUcmFuc2FjdGlvbnNcbiAqIGF3YWl0IGRiLnRyYW5zYWN0aW9uKGFzeW5jICh0eCkgPT4ge1xuICogICBhd2FpdCB0eC5pbnNlcnQoc2NoZW1hLnBsdWdpbikudmFsdWVzKHsgLi4uIH0pO1xuICogICBhd2FpdCB0eC51cGRhdGUoc2NoZW1hLnBsdWdpbikuc2V0KHsgLi4uIH0pO1xuICogfSk7XG4gKiBgYGBcbiAqL1xuXG4vLyBMYXp5IGluaXRpYWxpemF0aW9uIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIG9uIG1vZHVsZSBsb2FkXG5sZXQgX2RiSW5zdGFuY2U6IFJldHVyblR5cGU8dHlwZW9mIGRyaXp6bGU+IHwgbnVsbCA9IG51bGw7XG5cbi8qKlxuICogR2V0IHRoZSBkYXRhYmFzZSBpbnN0YW5jZSB3aXRoIGxhenkgaW5pdGlhbGl6YXRpb25cbiAqIFRoaXMgYXZvaWRzIHRoZSByYWNlIGNvbmRpdGlvbiB3aGVyZSB0aGUgbW9kdWxlIGlzIGxvYWRlZCBiZWZvcmUgZW52aXJvbm1lbnQgaXMgY29uZmlndXJlZFxuICovXG5mdW5jdGlvbiBnZXREYkluc3RhbmNlKCk6IFJldHVyblR5cGU8dHlwZW9mIGRyaXp6bGU+IHtcbiAgaWYgKCFfZGJJbnN0YW5jZSkge1xuICAgIF9kYkluc3RhbmNlID0gQ29ubmVjdGlvbi5nZXRJbnN0YW5jZSgpLmRiO1xuICB9XG4gIHJldHVybiBfZGJJbnN0YW5jZTtcbn1cblxuLyoqXG4gKiBQcm94eS1iYXNlZCBsYXp5IGRhdGFiYXNlIGluc3RhbmNlXG4gKiBUaGUgYWN0dWFsIGNvbm5lY3Rpb24gaXMgb25seSBjcmVhdGVkIHdoZW4gZmlyc3QgYWNjZXNzZWRcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgZGIgfSBmcm9tICcuL2Nvbm5lY3Rpb24nO1xuICpcbiAqIC8vIENvbm5lY3Rpb24gaXMgY3JlYXRlZCBoZXJlIG9uIGZpcnN0IHVzZSwgbm90IG9uIGltcG9ydFxuICogY29uc3QgcGx1Z2lucyA9IGF3YWl0IGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLnBsdWdpbik7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IGRiID0gbmV3IFByb3h5KHt9IGFzIFJldHVyblR5cGU8dHlwZW9mIGRyaXp6bGU+LCB7XG4gIGdldChfLCBwcm9wOiBzdHJpbmcgfCBzeW1ib2wpIHtcbiAgICBjb25zdCBpbnN0YW5jZSA9IGdldERiSW5zdGFuY2UoKTtcbiAgICBjb25zdCB2YWx1ZSA9IGluc3RhbmNlW3Byb3AgYXMga2V5b2YgdHlwZW9mIGluc3RhbmNlXTtcbiAgICAvLyBCaW5kIG1ldGhvZHMgdG8gdGhlIGluc3RhbmNlIHRvIHByZXNlcnZlICd0aGlzJyBjb250ZXh0XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHZhbHVlLmJpbmQoaW5zdGFuY2UpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH0sXG59KTtcblxuLyoqXG4gKiBHZXRzIHRoZSBDb25uZWN0aW9uIGluc3RhbmNlIGZvciBhZHZhbmNlZCBvcGVyYXRpb25zXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGdldENvbm5lY3Rpb24gfSBmcm9tICcuL2Nvbm5lY3Rpb24nO1xuICpcbiAqIGNvbnN0IGNvbm5lY3Rpb24gPSBnZXRDb25uZWN0aW9uKCk7XG4gKiBjb25zdCBzdGF0cyA9IGNvbm5lY3Rpb24uZ2V0U3RhdHMoKTtcbiAqIGNvbnNvbGUubG9nKGBBY3RpdmUgY29ubmVjdGlvbnM6ICR7c3RhdHMudG90YWxDb3VudH1gKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29ubmVjdGlvbigpOiBDb25uZWN0aW9uIHtcbiAgcmV0dXJuIENvbm5lY3Rpb24uZ2V0SW5zdGFuY2UoKTtcbn1cblxuLyoqXG4gKiBDbG9zZXMgdGhlIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiAqIFNob3VsZCBiZSBjYWxsZWQgZHVyaW5nIGFwcGxpY2F0aW9uIHNodXRkb3duXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGNsb3NlQ29ubmVjdGlvbiB9IGZyb20gJy4vY29ubmVjdGlvbic7XG4gKlxuICogcHJvY2Vzcy5vbignU0lHVEVSTScsIGFzeW5jICgpID0+IHtcbiAqICAgYXdhaXQgY2xvc2VDb25uZWN0aW9uKCk7XG4gKiAgIHByb2Nlc3MuZXhpdCgwKTtcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbG9zZUNvbm5lY3Rpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNvbm5lY3Rpb24gPSBDb25uZWN0aW9uLmdldEluc3RhbmNlKCk7XG4gIGF3YWl0IGNvbm5lY3Rpb24uY2xvc2UoKTtcbiAgX2RiSW5zdGFuY2UgPSBudWxsOyAvLyBSZXNldCBsYXp5IGluc3RhbmNlXG59XG5cbi8qKlxuICogVGVzdHMgdGhlIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiAqXG4gKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdHJ1ZSBpZiBjb25uZWN0aW9uIGlzIGhlYWx0aHlcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgdGVzdENvbm5lY3Rpb24gfSBmcm9tICcuL2Nvbm5lY3Rpb24nO1xuICpcbiAqIGlmIChhd2FpdCB0ZXN0Q29ubmVjdGlvbigpKSB7XG4gKiAgIGNvbnNvbGUubG9nKCdEYXRhYmFzZSBpcyByZWFkeScpO1xuICogfSBlbHNlIHtcbiAqICAgY29uc29sZS5lcnJvcignRGF0YWJhc2UgY29ubmVjdGlvbiBmYWlsZWQnKTtcbiAqICAgcHJvY2Vzcy5leGl0KDEpO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0ZXN0Q29ubmVjdGlvbigpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgY29uc3QgY29ubmVjdGlvbiA9IENvbm5lY3Rpb24uZ2V0SW5zdGFuY2UoKTtcbiAgcmV0dXJuIGNvbm5lY3Rpb24udGVzdENvbm5lY3Rpb24oKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for connection retry strategy
|
|
3
|
+
*/
|
|
4
|
+
export interface RetryConfig {
|
|
5
|
+
/** Maximum number of retry attempts */
|
|
6
|
+
maxRetries: number;
|
|
7
|
+
/** Base delay between retries in milliseconds */
|
|
8
|
+
baseDelay: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Implements exponential backoff retry strategy for database connections.
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Exponential backoff with configurable base delay
|
|
15
|
+
* - Attempt tracking and logging
|
|
16
|
+
* - Graceful failure after max retries
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const strategy = new ConnectionRetryStrategy({ maxRetries: 3, baseDelay: 1000 });
|
|
21
|
+
*
|
|
22
|
+
* const result = await strategy.execute(async () => {
|
|
23
|
+
* return await db.query('SELECT 1');
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class ConnectionRetryStrategy {
|
|
28
|
+
private readonly config;
|
|
29
|
+
private attempts;
|
|
30
|
+
constructor(config: RetryConfig);
|
|
31
|
+
/**
|
|
32
|
+
* Executes an operation with retry logic
|
|
33
|
+
*
|
|
34
|
+
* @param operation - Async function to execute with retries
|
|
35
|
+
* @returns Promise resolving to operation result
|
|
36
|
+
* @throws Error if all retry attempts fail
|
|
37
|
+
*/
|
|
38
|
+
execute<T>(operation: () => Promise<T>): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Handles connection errors with retry tracking
|
|
41
|
+
*
|
|
42
|
+
* @param error - Error that occurred
|
|
43
|
+
* @param testConnection - Function to test if connection is restored
|
|
44
|
+
*/
|
|
45
|
+
handleConnectionError(error: Error, testConnection: () => Promise<boolean>): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Resets the attempt counter
|
|
48
|
+
* Call this after a successful operation
|
|
49
|
+
*/
|
|
50
|
+
reset(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Gets the current attempt count
|
|
53
|
+
*/
|
|
54
|
+
getAttempts(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Calculates exponential backoff delay
|
|
57
|
+
*
|
|
58
|
+
* @param attempt - Current attempt number (1-indexed)
|
|
59
|
+
* @returns Delay in milliseconds
|
|
60
|
+
*/
|
|
61
|
+
private calculateBackoff;
|
|
62
|
+
/**
|
|
63
|
+
* Sleeps for the specified duration
|
|
64
|
+
*
|
|
65
|
+
* @param ms - Milliseconds to sleep
|
|
66
|
+
*/
|
|
67
|
+
private sleep;
|
|
68
|
+
}
|