@nmakarov/cli-toolkit 0.23.0 → 0.25.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/cli-runner.cjs +137 -38
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +137 -38
- package/dist/cli-runner.js.map +1 -1
- package/dist/db.cjs +125 -38
- package/dist/db.cjs.map +1 -1
- package/dist/db.js +125 -38
- package/dist/db.js.map +1 -1
- package/dist/index.cjs +137 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +137 -38
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +12 -0
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +12 -0
- package/dist/init.js.map +1 -1
- package/dist/params.cjs +12 -0
- package/dist/params.cjs.map +1 -1
- package/dist/params.js +12 -0
- package/dist/params.js.map +1 -1
- package/package.json +1 -1
package/dist/db.cjs
CHANGED
|
@@ -57,38 +57,71 @@ var KNEX_DEFAULTS = {
|
|
|
57
57
|
};
|
|
58
58
|
var Db = class {
|
|
59
59
|
static async init(context, options = {}) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
dbName = "local";
|
|
71
|
-
}
|
|
72
|
-
if (dbName && /^(postgresql|mysql):\/\//.test(dbName)) {
|
|
73
|
-
dbConnectionString = dbName;
|
|
74
|
-
dbName = void 0;
|
|
75
|
-
}
|
|
76
|
-
if (dbName && !dbConnectionString) {
|
|
77
|
-
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
78
|
-
dbConnectionString = await context.params.get(paramName, "string");
|
|
60
|
+
const buildConfig = async () => {
|
|
61
|
+
const defs = {
|
|
62
|
+
dbName: "string",
|
|
63
|
+
dbProfile: "boolean default false"
|
|
64
|
+
};
|
|
65
|
+
const discovered = context?.params?.getAllForModule?.("db", defs) ?? {};
|
|
66
|
+
const merged = { ...discovered, ...options };
|
|
67
|
+
let { dbName, dbProfile } = merged;
|
|
68
|
+
let dbConnectionString = options.dbConnectionString ?? options.connectionString;
|
|
69
|
+
let connectionParam = dbConnectionString ? "options" : null;
|
|
79
70
|
if (!dbConnectionString) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
const src = context?.args?.getSource?.("dbConnectionString");
|
|
72
|
+
if (src === "cli" || src === "overrides" || src === "config") {
|
|
73
|
+
dbConnectionString = await context.params.get("dbConnectionString", "string");
|
|
74
|
+
connectionParam = "dbConnectionString";
|
|
75
|
+
}
|
|
83
76
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
if (!dbConnectionString && dbName && /^(postgresql|mysql):\/\//.test(dbName)) {
|
|
78
|
+
dbConnectionString = dbName;
|
|
79
|
+
dbName = void 0;
|
|
80
|
+
}
|
|
81
|
+
if (!dbConnectionString && dbName) {
|
|
82
|
+
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
83
|
+
dbConnectionString = await context.params.get(paramName, "string");
|
|
84
|
+
connectionParam = paramName;
|
|
85
|
+
if (!dbConnectionString) {
|
|
86
|
+
throw new ParamError(
|
|
87
|
+
`Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!dbConnectionString) {
|
|
92
|
+
dbConnectionString = await context.params.get("dbConnectionString", "string");
|
|
93
|
+
if (dbConnectionString) {
|
|
94
|
+
connectionParam = "dbConnectionString";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!dbConnectionString) {
|
|
98
|
+
if (!dbName) {
|
|
99
|
+
dbName = "local";
|
|
100
|
+
}
|
|
101
|
+
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
102
|
+
dbConnectionString = await context.params.get(paramName, "string");
|
|
103
|
+
connectionParam = paramName;
|
|
104
|
+
if (!dbConnectionString) {
|
|
105
|
+
throw new ParamError(
|
|
106
|
+
`Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const displayName = resolveDbDisplayName(
|
|
111
|
+
dbName,
|
|
112
|
+
connectionParam,
|
|
113
|
+
context?.args?.env,
|
|
114
|
+
merged.name
|
|
115
|
+
);
|
|
116
|
+
return {
|
|
117
|
+
...KNEX_DEFAULTS,
|
|
118
|
+
connectionString: dbConnectionString,
|
|
119
|
+
name: displayName,
|
|
120
|
+
profile: !!dbProfile,
|
|
121
|
+
logger: context.logger
|
|
122
|
+
};
|
|
91
123
|
};
|
|
124
|
+
const config = context?.params?.runWithModuleAsync ? await context.params.runWithModuleAsync("db", buildConfig) : await buildConfig();
|
|
92
125
|
return dbConnect(context, config);
|
|
93
126
|
}
|
|
94
127
|
constructor(config) {
|
|
@@ -105,7 +138,6 @@ var Db = class {
|
|
|
105
138
|
acquireConnectionTimeout: 1e4,
|
|
106
139
|
ssl: { rejectUnauthorized: false },
|
|
107
140
|
logger: console,
|
|
108
|
-
name: "default",
|
|
109
141
|
...config
|
|
110
142
|
};
|
|
111
143
|
this.logger = this.config.logger;
|
|
@@ -205,9 +237,7 @@ var Db = class {
|
|
|
205
237
|
await this.testConnection();
|
|
206
238
|
}
|
|
207
239
|
this.isConnected = true;
|
|
208
|
-
this.logger.debug?.(
|
|
209
|
-
`[Db] Connected to database "${this.config.name || this.config.connectionString}"`
|
|
210
|
-
);
|
|
240
|
+
this.logger.debug?.(formatDbConnectMessage(this.config.name, this.config.connectionString));
|
|
211
241
|
} catch (error) {
|
|
212
242
|
if (error instanceof ParamError) {
|
|
213
243
|
throw error;
|
|
@@ -225,9 +255,7 @@ var Db = class {
|
|
|
225
255
|
this.knexInstance = null;
|
|
226
256
|
this.isConnected = false;
|
|
227
257
|
this.queriesLog = [];
|
|
228
|
-
this.logger.debug?.(
|
|
229
|
-
`[Db] Disconnected from database "${this.config.name || this.config.connectionString}"`
|
|
230
|
-
);
|
|
258
|
+
this.logger.debug?.(formatDbDisconnectMessage(this.config.name, this.config.connectionString));
|
|
231
259
|
} catch (error) {
|
|
232
260
|
const errorMsg = this.getErrorMessage(error);
|
|
233
261
|
this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);
|
|
@@ -356,15 +384,74 @@ var Db = class {
|
|
|
356
384
|
function capitalizeFirstLetter(str) {
|
|
357
385
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
358
386
|
}
|
|
387
|
+
function resolveDbDisplayName(dbName, connectionParam, argsEnv, mergedName) {
|
|
388
|
+
if (dbName) {
|
|
389
|
+
return dbName;
|
|
390
|
+
}
|
|
391
|
+
if (mergedName) {
|
|
392
|
+
return mergedName;
|
|
393
|
+
}
|
|
394
|
+
if (connectionParam?.startsWith("dbConnectionString") && connectionParam.length > "dbConnectionString".length) {
|
|
395
|
+
return connectionParam.slice("dbConnectionString".length).toLowerCase();
|
|
396
|
+
}
|
|
397
|
+
if (connectionParam === "dbConnectionString" && argsEnv) {
|
|
398
|
+
return argsEnv;
|
|
399
|
+
}
|
|
400
|
+
return void 0;
|
|
401
|
+
}
|
|
402
|
+
function formatDbConnectMessage(name, connectionString) {
|
|
403
|
+
const endpointSuffix = formatConnectionEndpointSuffix(connectionString);
|
|
404
|
+
if (name) {
|
|
405
|
+
return `[Db] Connected to database "${name}"${endpointSuffix}`;
|
|
406
|
+
}
|
|
407
|
+
return `[Db] Connected${endpointSuffix}`;
|
|
408
|
+
}
|
|
409
|
+
function formatDbDisconnectMessage(name, connectionString) {
|
|
410
|
+
const endpointSuffix = formatConnectionEndpointSuffix(connectionString);
|
|
411
|
+
if (name) {
|
|
412
|
+
return `[Db] Disconnected from database "${name}"${endpointSuffix}`;
|
|
413
|
+
}
|
|
414
|
+
return `[Db] Disconnected${endpointSuffix}`;
|
|
415
|
+
}
|
|
416
|
+
function formatDbInstanceMessage(action, name) {
|
|
417
|
+
if (name) {
|
|
418
|
+
return `[Db] instance "${name}" ${action}`;
|
|
419
|
+
}
|
|
420
|
+
return `[Db] instance ${action}`;
|
|
421
|
+
}
|
|
422
|
+
function formatConnectionEndpointSuffix(connectionString) {
|
|
423
|
+
const endpoint = formatConnectionEndpoint(connectionString);
|
|
424
|
+
return endpoint ? ` (${endpoint})` : "";
|
|
425
|
+
}
|
|
426
|
+
function formatConnectionEndpoint(connectionString) {
|
|
427
|
+
try {
|
|
428
|
+
const url = new URL(connectionString);
|
|
429
|
+
const host = url.hostname;
|
|
430
|
+
if (!host) {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
let port = url.port;
|
|
434
|
+
if (!port) {
|
|
435
|
+
if (url.protocol === "postgresql:") {
|
|
436
|
+
port = "5432";
|
|
437
|
+
} else if (url.protocol === "mysql:") {
|
|
438
|
+
port = "3306";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return port ? `${host}:${port}` : host;
|
|
442
|
+
} catch {
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
359
446
|
async function dbConnect(context, config) {
|
|
360
447
|
try {
|
|
361
448
|
const db = new Db(config);
|
|
362
449
|
context.registerCleanup(async () => {
|
|
363
450
|
await db.disconnect();
|
|
364
|
-
context.logger.debug?.(
|
|
451
|
+
context.logger.debug?.(formatDbInstanceMessage("disconnected", config.name));
|
|
365
452
|
});
|
|
366
453
|
await db.connect();
|
|
367
|
-
context.logger.debug?.(
|
|
454
|
+
context.logger.debug?.(formatDbInstanceMessage("initialized", config.name));
|
|
368
455
|
return db;
|
|
369
456
|
} catch (error) {
|
|
370
457
|
if (error instanceof ParamError) {
|
package/dist/db.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/index.js","../src/errors.js"],"sourcesContent":["import knex from \"knex\";\nimport { ParamError } from \"../errors.js\";\n\nconst KNEX_DEFAULTS = {\n testConnection: true,\n pool: { min: 2, max: 10 },\n acquireConnectionTimeout: 10000,\n ssl: { rejectUnauthorized: false },\n};\n\nexport class Db {\n static async init(context, options = {}) {\n const defs = {\n dbName: \"string\",\n dbConnectionString: \"string\",\n dbProfile: \"boolean default false\",\n };\n const discovered = context?.params?.getAllForModule?.(\"db\", defs) ?? {};\n const merged = { ...discovered, ...options };\n\n let { dbName, dbConnectionString } = merged;\n const { dbProfile } = merged;\n\n if (!dbName && !dbConnectionString) {\n dbName = \"local\";\n }\n\n if (dbName && /^(postgresql|mysql):\\/\\//.test(dbName)) {\n dbConnectionString = dbName;\n dbName = undefined;\n }\n\n if (dbName && !dbConnectionString) {\n const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;\n dbConnectionString = await context.params.get(paramName, \"string\");\n if (!dbConnectionString) {\n throw new ParamError(\n `Db: cannot find dbConnectionString for dbName=\"${dbName}\" (looked for param \"${paramName}\")`\n );\n }\n }\n\n const config = {\n ...KNEX_DEFAULTS,\n connectionString: dbConnectionString,\n name: dbName || merged.name || \"default\",\n profile: !!dbProfile,\n logger: context.logger,\n };\n\n return dbConnect(context, config);\n }\n\n constructor(config) {\n if (!config || !config.connectionString) {\n throw new ParamError(\"Db: connectionString is required\");\n }\n\n this.knexInstance = null;\n this.isConnected = false;\n this.queriesLog = [];\n\n this.config = {\n testConnection: true,\n profile: false,\n pool: { min: 2, max: 10 },\n acquireConnectionTimeout: 10000,\n ssl: { rejectUnauthorized: false },\n logger: console,\n name: \"default\",\n ...config,\n };\n\n this.logger = this.config.logger;\n\n const instance = this;\n const callableWrapper = function () {\n throw new Error(\"This should never be called directly\");\n };\n callableWrapper._instance = instance;\n\n return new Proxy(callableWrapper, {\n apply: (target, _thisArg, argumentsList) => {\n const inst = target._instance;\n if (!inst.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n return inst.knexInstance(...argumentsList);\n },\n get: (target, prop) => {\n if (prop === \"_instance\") {\n return target._instance;\n }\n\n const inst = target._instance;\n\n const ownMethods = [\n \"connect\",\n \"disconnect\",\n \"testConnection\",\n \"tableExists\",\n \"getQueryLog\",\n \"getKnex\",\n \"isConnectedToDb\",\n \"getErrorMessage\",\n \"detectClient\",\n \"attachProfiler\",\n ];\n\n if (prop in inst) {\n const value = inst[prop];\n if (typeof value === \"function\" && ownMethods.includes(prop)) {\n return value.bind(inst);\n }\n if (typeof value !== \"function\") {\n return value;\n }\n }\n\n if (inst.knexInstance) {\n const knexProp = inst.knexInstance[prop];\n if (typeof knexProp === \"function\") {\n return knexProp.bind(inst.knexInstance);\n }\n return knexProp;\n }\n\n if (prop in inst) {\n const method = inst[prop];\n if (typeof method === \"function\") {\n return method.bind(inst);\n }\n return method;\n }\n\n return undefined;\n },\n });\n }\n\n detectClient(connectionString) {\n if (connectionString.match(/^postgresql/)) {\n return \"pg\";\n }\n if (connectionString.match(/^mysql/)) {\n return \"mysql2\";\n }\n return null;\n }\n\n async connect() {\n if (this.isConnected && this.knexInstance) {\n this.logger.warn?.(\"[Db] Already connected\");\n return;\n }\n\n const client = this.detectClient(this.config.connectionString);\n if (!client) {\n throw new ParamError(\n \"Db: Cannot determine client type from connection string. Expected postgresql:// or mysql://\"\n );\n }\n\n try {\n const connectionConfig = {\n connectionString: this.config.connectionString,\n family: 4,\n };\n\n this.knexInstance = knex({\n client,\n connection: connectionConfig,\n pool: this.config.pool,\n acquireConnectionTimeout: this.config.acquireConnectionTimeout,\n ...(this.config.ssl && { ssl: this.config.ssl }),\n });\n\n if (this.config.profile) {\n this.attachProfiler();\n }\n\n if (this.config.testConnection) {\n await this.testConnection();\n }\n\n this.isConnected = true;\n this.logger.debug?.(\n `[Db] Connected to database \"${this.config.name || this.config.connectionString}\"`\n );\n } catch (error) {\n if (error instanceof ParamError) {\n throw error;\n }\n const errorMsg = this.getErrorMessage(error);\n throw new ParamError(`Db: Connection failed - ${errorMsg}`);\n }\n }\n\n async disconnect() {\n if (!this.knexInstance) {\n return;\n }\n\n try {\n await this.knexInstance.destroy();\n this.knexInstance = null;\n this.isConnected = false;\n this.queriesLog = [];\n this.logger.debug?.(\n `[Db] Disconnected from database \"${this.config.name || this.config.connectionString}\"`\n );\n } catch (error) {\n const errorMsg = this.getErrorMessage(error);\n this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);\n throw error;\n }\n }\n\n getErrorMessage(error) {\n if (error instanceof AggregateError) {\n const errors = error.errors || [];\n\n if (errors.length > 0) {\n const firstError = errors[0];\n const firstErrorMsg =\n firstError instanceof Error ? firstError.message : String(firstError);\n\n const allSimilar = errors.every((e) => {\n const msg = e instanceof Error ? e.message : String(e);\n const codeMatch = msg.match(/^(\\w+)\\s/);\n const firstCodeMatch = firstErrorMsg.match(/^(\\w+)\\s/);\n return codeMatch && firstCodeMatch && codeMatch[1] === firstCodeMatch[1];\n });\n\n if (allSimilar && errors.length > 1) {\n const addresses = errors\n .map((e) => {\n const msg = e instanceof Error ? e.message : String(e);\n const addrMatch = msg.match(/([:\\d.]+:\\d+)/);\n return addrMatch ? addrMatch[1] : null;\n })\n .filter(Boolean);\n\n if (addresses.length > 0) {\n const codeMatch = firstErrorMsg.match(/^(\\w+)\\s/);\n const code = codeMatch ? codeMatch[1] : \"Connection error\";\n return `${code} (tried: ${addresses.join(\", \")})`;\n }\n }\n\n const uniqueMessages = [\n ...new Set(\n errors.map((e) => (e instanceof Error ? e.message : String(e)))\n ),\n ];\n\n if (uniqueMessages.length === 1) {\n return uniqueMessages[0];\n }\n\n return uniqueMessages.join(\"; \");\n }\n\n return error.message || \"Multiple errors occurred\";\n }\n\n if (error instanceof Error) {\n const code = error.code;\n if (code) {\n return `${code}: ${error.message || String(error)}`;\n }\n return error.message || String(error);\n }\n\n if (typeof error === \"string\") {\n return error;\n }\n\n if (error && typeof error === \"object\" && \"message\" in error) {\n const msg = String(error.message);\n const code = error.code;\n if (code) {\n return `${code}: ${msg}`;\n }\n return msg;\n }\n\n return String(error) || \"Unknown error\";\n }\n\n async testConnection() {\n if (!this.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n\n try {\n const result = await this.knexInstance.raw(\"SELECT 2+3 AS result\");\n const isOk = result.rows?.[0]?.result === 5 || result[0]?.[0]?.result === 5;\n this.logger.debug?.(`[Db] Connection test: ${isOk ? \"OK\" : \"FAILED\"}`);\n return isOk;\n } catch (error) {\n const errorMsg = this.getErrorMessage(error);\n this.logger.error?.(`[Db] Connection test failed: ${errorMsg}`);\n throw new ParamError(`Db: Connection test failed - ${errorMsg}`);\n }\n }\n\n attachProfiler() {\n if (!this.knexInstance) {\n return;\n }\n\n this.queriesLog = [];\n this.knexInstance.queriesLog = this.queriesLog;\n\n this.knexInstance.on(\"query\", (query) => {\n query.__startTime = process.hrtime();\n });\n\n this.knexInstance.on(\"query-response\", (_response, query) => {\n const [seconds, nanoseconds] = process.hrtime(query.__startTime);\n const executionTimeMs = (seconds * 1000 + nanoseconds / 1e6).toFixed(2);\n\n const logEntry = {\n sql: query.sql,\n bindings: query.bindings || [],\n executionTimeMs,\n };\n\n this.queriesLog.push(logEntry);\n this.logger.debug?.(`[Db] Query: ${query.sql} | Duration: ${executionTimeMs}ms`);\n });\n\n this.knexInstance.on(\"query-error\", (error, query) => {\n this.logger.error?.(`[Db] Query failed: ${query.sql}`, error);\n });\n }\n\n getQueryLog() {\n return [...this.queriesLog];\n }\n\n async tableExists(tableName) {\n if (!this.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n\n try {\n return await this.knexInstance.schema.hasTable(tableName);\n } catch (error) {\n this.logger.error?.(`[Db] Error checking table existence: ${error.message}`);\n throw error;\n }\n }\n\n getKnex() {\n if (!this.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n return this.knexInstance;\n }\n\n isConnectedToDb() {\n return this.isConnected && this.knexInstance !== null;\n }\n}\n\nfunction capitalizeFirstLetter(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nasync function dbConnect(context, config) {\n try {\n const db = new Db(config);\n\n context.registerCleanup(async () => {\n await db.disconnect();\n context.logger.debug?.(`[Db] instance \"${config.name}\" disconnected`);\n });\n\n await db.connect();\n\n context.logger.debug?.(`[Db] instance \"${config.name}\" initialized`);\n\n return db;\n } catch (error) {\n if (error instanceof ParamError) {\n throw error;\n }\n const errorMsg = error instanceof Error ? error.message : String(error);\n throw new ParamError(`[Db] connect error: ${errorMsg}`);\n }\n}\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message, cause) {\n super(message);this.cause = cause;;\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n"],"mappings":"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","names":["knex"]}
|
|
1
|
+
{"version":3,"sources":["../src/db/index.js","../src/errors.js"],"sourcesContent":["import knex from \"knex\";\nimport { ParamError } from \"../errors.js\";\n\nconst KNEX_DEFAULTS = {\n testConnection: true,\n pool: { min: 2, max: 10 },\n acquireConnectionTimeout: 10000,\n ssl: { rejectUnauthorized: false },\n};\n\nexport class Db {\n static async init(context, options = {}) {\n const buildConfig = async () => {\n const defs = {\n dbName: \"string\",\n dbProfile: \"boolean default false\",\n };\n const discovered = context?.params?.getAllForModule?.(\"db\", defs) ?? {};\n const merged = { ...discovered, ...options };\n\n let { dbName, dbProfile } = merged;\n let dbConnectionString = options.dbConnectionString ?? options.connectionString;\n let connectionParam = dbConnectionString ? \"options\" : null;\n\n if (!dbConnectionString) {\n const src = context?.args?.getSource?.(\"dbConnectionString\");\n if (src === \"cli\" || src === \"overrides\" || src === \"config\") {\n dbConnectionString = await context.params.get(\"dbConnectionString\", \"string\");\n connectionParam = \"dbConnectionString\";\n }\n }\n\n if (!dbConnectionString && dbName && /^(postgresql|mysql):\\/\\//.test(dbName)) {\n dbConnectionString = dbName;\n dbName = undefined;\n }\n\n if (!dbConnectionString && dbName) {\n const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;\n dbConnectionString = await context.params.get(paramName, \"string\");\n connectionParam = paramName;\n if (!dbConnectionString) {\n throw new ParamError(\n `Db: cannot find dbConnectionString for dbName=\"${dbName}\" (looked for param \"${paramName}\")`\n );\n }\n }\n\n if (!dbConnectionString) {\n dbConnectionString = await context.params.get(\"dbConnectionString\", \"string\");\n if (dbConnectionString) {\n connectionParam = \"dbConnectionString\";\n }\n }\n\n if (!dbConnectionString) {\n if (!dbName) {\n dbName = \"local\";\n }\n const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;\n dbConnectionString = await context.params.get(paramName, \"string\");\n connectionParam = paramName;\n if (!dbConnectionString) {\n throw new ParamError(\n `Db: cannot find dbConnectionString for dbName=\"${dbName}\" (looked for param \"${paramName}\")`\n );\n }\n }\n\n const displayName = resolveDbDisplayName(\n dbName,\n connectionParam,\n context?.args?.env,\n merged.name\n );\n\n return {\n ...KNEX_DEFAULTS,\n connectionString: dbConnectionString,\n name: displayName,\n profile: !!dbProfile,\n logger: context.logger,\n };\n };\n\n const config = context?.params?.runWithModuleAsync\n ? await context.params.runWithModuleAsync(\"db\", buildConfig)\n : await buildConfig();\n\n return dbConnect(context, config);\n }\n\n constructor(config) {\n if (!config || !config.connectionString) {\n throw new ParamError(\"Db: connectionString is required\");\n }\n\n this.knexInstance = null;\n this.isConnected = false;\n this.queriesLog = [];\n\n this.config = {\n testConnection: true,\n profile: false,\n pool: { min: 2, max: 10 },\n acquireConnectionTimeout: 10000,\n ssl: { rejectUnauthorized: false },\n logger: console,\n ...config,\n };\n\n this.logger = this.config.logger;\n\n const instance = this;\n const callableWrapper = function () {\n throw new Error(\"This should never be called directly\");\n };\n callableWrapper._instance = instance;\n\n return new Proxy(callableWrapper, {\n apply: (target, _thisArg, argumentsList) => {\n const inst = target._instance;\n if (!inst.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n return inst.knexInstance(...argumentsList);\n },\n get: (target, prop) => {\n if (prop === \"_instance\") {\n return target._instance;\n }\n\n const inst = target._instance;\n\n const ownMethods = [\n \"connect\",\n \"disconnect\",\n \"testConnection\",\n \"tableExists\",\n \"getQueryLog\",\n \"getKnex\",\n \"isConnectedToDb\",\n \"getErrorMessage\",\n \"detectClient\",\n \"attachProfiler\",\n ];\n\n if (prop in inst) {\n const value = inst[prop];\n if (typeof value === \"function\" && ownMethods.includes(prop)) {\n return value.bind(inst);\n }\n if (typeof value !== \"function\") {\n return value;\n }\n }\n\n if (inst.knexInstance) {\n const knexProp = inst.knexInstance[prop];\n if (typeof knexProp === \"function\") {\n return knexProp.bind(inst.knexInstance);\n }\n return knexProp;\n }\n\n if (prop in inst) {\n const method = inst[prop];\n if (typeof method === \"function\") {\n return method.bind(inst);\n }\n return method;\n }\n\n return undefined;\n },\n });\n }\n\n detectClient(connectionString) {\n if (connectionString.match(/^postgresql/)) {\n return \"pg\";\n }\n if (connectionString.match(/^mysql/)) {\n return \"mysql2\";\n }\n return null;\n }\n\n async connect() {\n if (this.isConnected && this.knexInstance) {\n this.logger.warn?.(\"[Db] Already connected\");\n return;\n }\n\n const client = this.detectClient(this.config.connectionString);\n if (!client) {\n throw new ParamError(\n \"Db: Cannot determine client type from connection string. Expected postgresql:// or mysql://\"\n );\n }\n\n try {\n const connectionConfig = {\n connectionString: this.config.connectionString,\n family: 4,\n };\n\n this.knexInstance = knex({\n client,\n connection: connectionConfig,\n pool: this.config.pool,\n acquireConnectionTimeout: this.config.acquireConnectionTimeout,\n ...(this.config.ssl && { ssl: this.config.ssl }),\n });\n\n if (this.config.profile) {\n this.attachProfiler();\n }\n\n if (this.config.testConnection) {\n await this.testConnection();\n }\n\n this.isConnected = true;\n this.logger.debug?.(formatDbConnectMessage(this.config.name, this.config.connectionString));\n } catch (error) {\n if (error instanceof ParamError) {\n throw error;\n }\n const errorMsg = this.getErrorMessage(error);\n throw new ParamError(`Db: Connection failed - ${errorMsg}`);\n }\n }\n\n async disconnect() {\n if (!this.knexInstance) {\n return;\n }\n\n try {\n await this.knexInstance.destroy();\n this.knexInstance = null;\n this.isConnected = false;\n this.queriesLog = [];\n this.logger.debug?.(formatDbDisconnectMessage(this.config.name, this.config.connectionString));\n } catch (error) {\n const errorMsg = this.getErrorMessage(error);\n this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);\n throw error;\n }\n }\n\n getErrorMessage(error) {\n if (error instanceof AggregateError) {\n const errors = error.errors || [];\n\n if (errors.length > 0) {\n const firstError = errors[0];\n const firstErrorMsg =\n firstError instanceof Error ? firstError.message : String(firstError);\n\n const allSimilar = errors.every((e) => {\n const msg = e instanceof Error ? e.message : String(e);\n const codeMatch = msg.match(/^(\\w+)\\s/);\n const firstCodeMatch = firstErrorMsg.match(/^(\\w+)\\s/);\n return codeMatch && firstCodeMatch && codeMatch[1] === firstCodeMatch[1];\n });\n\n if (allSimilar && errors.length > 1) {\n const addresses = errors\n .map((e) => {\n const msg = e instanceof Error ? e.message : String(e);\n const addrMatch = msg.match(/([:\\d.]+:\\d+)/);\n return addrMatch ? addrMatch[1] : null;\n })\n .filter(Boolean);\n\n if (addresses.length > 0) {\n const codeMatch = firstErrorMsg.match(/^(\\w+)\\s/);\n const code = codeMatch ? codeMatch[1] : \"Connection error\";\n return `${code} (tried: ${addresses.join(\", \")})`;\n }\n }\n\n const uniqueMessages = [\n ...new Set(\n errors.map((e) => (e instanceof Error ? e.message : String(e)))\n ),\n ];\n\n if (uniqueMessages.length === 1) {\n return uniqueMessages[0];\n }\n\n return uniqueMessages.join(\"; \");\n }\n\n return error.message || \"Multiple errors occurred\";\n }\n\n if (error instanceof Error) {\n const code = error.code;\n if (code) {\n return `${code}: ${error.message || String(error)}`;\n }\n return error.message || String(error);\n }\n\n if (typeof error === \"string\") {\n return error;\n }\n\n if (error && typeof error === \"object\" && \"message\" in error) {\n const msg = String(error.message);\n const code = error.code;\n if (code) {\n return `${code}: ${msg}`;\n }\n return msg;\n }\n\n return String(error) || \"Unknown error\";\n }\n\n async testConnection() {\n if (!this.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n\n try {\n const result = await this.knexInstance.raw(\"SELECT 2+3 AS result\");\n const isOk = result.rows?.[0]?.result === 5 || result[0]?.[0]?.result === 5;\n this.logger.debug?.(`[Db] Connection test: ${isOk ? \"OK\" : \"FAILED\"}`);\n return isOk;\n } catch (error) {\n const errorMsg = this.getErrorMessage(error);\n this.logger.error?.(`[Db] Connection test failed: ${errorMsg}`);\n throw new ParamError(`Db: Connection test failed - ${errorMsg}`);\n }\n }\n\n attachProfiler() {\n if (!this.knexInstance) {\n return;\n }\n\n this.queriesLog = [];\n this.knexInstance.queriesLog = this.queriesLog;\n\n this.knexInstance.on(\"query\", (query) => {\n query.__startTime = process.hrtime();\n });\n\n this.knexInstance.on(\"query-response\", (_response, query) => {\n const [seconds, nanoseconds] = process.hrtime(query.__startTime);\n const executionTimeMs = (seconds * 1000 + nanoseconds / 1e6).toFixed(2);\n\n const logEntry = {\n sql: query.sql,\n bindings: query.bindings || [],\n executionTimeMs,\n };\n\n this.queriesLog.push(logEntry);\n this.logger.debug?.(`[Db] Query: ${query.sql} | Duration: ${executionTimeMs}ms`);\n });\n\n this.knexInstance.on(\"query-error\", (error, query) => {\n this.logger.error?.(`[Db] Query failed: ${query.sql}`, error);\n });\n }\n\n getQueryLog() {\n return [...this.queriesLog];\n }\n\n async tableExists(tableName) {\n if (!this.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n\n try {\n return await this.knexInstance.schema.hasTable(tableName);\n } catch (error) {\n this.logger.error?.(`[Db] Error checking table existence: ${error.message}`);\n throw error;\n }\n }\n\n getKnex() {\n if (!this.knexInstance) {\n throw new Error(\"Db: Not connected. Call connect() first.\");\n }\n return this.knexInstance;\n }\n\n isConnectedToDb() {\n return this.isConnected && this.knexInstance !== null;\n }\n}\n\nfunction capitalizeFirstLetter(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nfunction resolveDbDisplayName(dbName, connectionParam, argsEnv, mergedName) {\n if (dbName) {\n return dbName;\n }\n if (mergedName) {\n return mergedName;\n }\n if (\n connectionParam?.startsWith(\"dbConnectionString\") &&\n connectionParam.length > \"dbConnectionString\".length\n ) {\n return connectionParam.slice(\"dbConnectionString\".length).toLowerCase();\n }\n if (connectionParam === \"dbConnectionString\" && argsEnv) {\n return argsEnv;\n }\n return undefined;\n}\n\nfunction formatDbConnectMessage(name, connectionString) {\n const endpointSuffix = formatConnectionEndpointSuffix(connectionString);\n if (name) {\n return `[Db] Connected to database \"${name}\"${endpointSuffix}`;\n }\n return `[Db] Connected${endpointSuffix}`;\n}\n\nfunction formatDbDisconnectMessage(name, connectionString) {\n const endpointSuffix = formatConnectionEndpointSuffix(connectionString);\n if (name) {\n return `[Db] Disconnected from database \"${name}\"${endpointSuffix}`;\n }\n return `[Db] Disconnected${endpointSuffix}`;\n}\n\nfunction formatDbInstanceMessage(action, name) {\n if (name) {\n return `[Db] instance \"${name}\" ${action}`;\n }\n return `[Db] instance ${action}`;\n}\n\nfunction formatConnectionEndpointSuffix(connectionString) {\n const endpoint = formatConnectionEndpoint(connectionString);\n return endpoint ? ` (${endpoint})` : \"\";\n}\n\nfunction formatConnectionEndpoint(connectionString) {\n try {\n const url = new URL(connectionString);\n const host = url.hostname;\n if (!host) {\n return null;\n }\n\n let port = url.port;\n if (!port) {\n if (url.protocol === \"postgresql:\") {\n port = \"5432\";\n } else if (url.protocol === \"mysql:\") {\n port = \"3306\";\n }\n }\n\n return port ? `${host}:${port}` : host;\n } catch {\n return null;\n }\n}\n\nasync function dbConnect(context, config) {\n try {\n const db = new Db(config);\n\n context.registerCleanup(async () => {\n await db.disconnect();\n context.logger.debug?.(formatDbInstanceMessage(\"disconnected\", config.name));\n });\n\n await db.connect();\n\n context.logger.debug?.(formatDbInstanceMessage(\"initialized\", config.name));\n\n return db;\n } catch (error) {\n if (error instanceof ParamError) {\n throw error;\n }\n const errorMsg = error instanceof Error ? error.message : String(error);\n throw new ParamError(`[Db] connect error: ${errorMsg}`);\n }\n}\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message, cause) {\n super(message);this.cause = cause;;\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n"],"mappings":"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","names":["knex"]}
|
package/dist/db.js
CHANGED
|
@@ -24,38 +24,71 @@ var KNEX_DEFAULTS = {
|
|
|
24
24
|
};
|
|
25
25
|
var Db = class {
|
|
26
26
|
static async init(context, options = {}) {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
dbName = "local";
|
|
38
|
-
}
|
|
39
|
-
if (dbName && /^(postgresql|mysql):\/\//.test(dbName)) {
|
|
40
|
-
dbConnectionString = dbName;
|
|
41
|
-
dbName = void 0;
|
|
42
|
-
}
|
|
43
|
-
if (dbName && !dbConnectionString) {
|
|
44
|
-
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
45
|
-
dbConnectionString = await context.params.get(paramName, "string");
|
|
27
|
+
const buildConfig = async () => {
|
|
28
|
+
const defs = {
|
|
29
|
+
dbName: "string",
|
|
30
|
+
dbProfile: "boolean default false"
|
|
31
|
+
};
|
|
32
|
+
const discovered = context?.params?.getAllForModule?.("db", defs) ?? {};
|
|
33
|
+
const merged = { ...discovered, ...options };
|
|
34
|
+
let { dbName, dbProfile } = merged;
|
|
35
|
+
let dbConnectionString = options.dbConnectionString ?? options.connectionString;
|
|
36
|
+
let connectionParam = dbConnectionString ? "options" : null;
|
|
46
37
|
if (!dbConnectionString) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
const src = context?.args?.getSource?.("dbConnectionString");
|
|
39
|
+
if (src === "cli" || src === "overrides" || src === "config") {
|
|
40
|
+
dbConnectionString = await context.params.get("dbConnectionString", "string");
|
|
41
|
+
connectionParam = "dbConnectionString";
|
|
42
|
+
}
|
|
50
43
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
if (!dbConnectionString && dbName && /^(postgresql|mysql):\/\//.test(dbName)) {
|
|
45
|
+
dbConnectionString = dbName;
|
|
46
|
+
dbName = void 0;
|
|
47
|
+
}
|
|
48
|
+
if (!dbConnectionString && dbName) {
|
|
49
|
+
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
50
|
+
dbConnectionString = await context.params.get(paramName, "string");
|
|
51
|
+
connectionParam = paramName;
|
|
52
|
+
if (!dbConnectionString) {
|
|
53
|
+
throw new ParamError(
|
|
54
|
+
`Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!dbConnectionString) {
|
|
59
|
+
dbConnectionString = await context.params.get("dbConnectionString", "string");
|
|
60
|
+
if (dbConnectionString) {
|
|
61
|
+
connectionParam = "dbConnectionString";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!dbConnectionString) {
|
|
65
|
+
if (!dbName) {
|
|
66
|
+
dbName = "local";
|
|
67
|
+
}
|
|
68
|
+
const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
|
|
69
|
+
dbConnectionString = await context.params.get(paramName, "string");
|
|
70
|
+
connectionParam = paramName;
|
|
71
|
+
if (!dbConnectionString) {
|
|
72
|
+
throw new ParamError(
|
|
73
|
+
`Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const displayName = resolveDbDisplayName(
|
|
78
|
+
dbName,
|
|
79
|
+
connectionParam,
|
|
80
|
+
context?.args?.env,
|
|
81
|
+
merged.name
|
|
82
|
+
);
|
|
83
|
+
return {
|
|
84
|
+
...KNEX_DEFAULTS,
|
|
85
|
+
connectionString: dbConnectionString,
|
|
86
|
+
name: displayName,
|
|
87
|
+
profile: !!dbProfile,
|
|
88
|
+
logger: context.logger
|
|
89
|
+
};
|
|
58
90
|
};
|
|
91
|
+
const config = context?.params?.runWithModuleAsync ? await context.params.runWithModuleAsync("db", buildConfig) : await buildConfig();
|
|
59
92
|
return dbConnect(context, config);
|
|
60
93
|
}
|
|
61
94
|
constructor(config) {
|
|
@@ -72,7 +105,6 @@ var Db = class {
|
|
|
72
105
|
acquireConnectionTimeout: 1e4,
|
|
73
106
|
ssl: { rejectUnauthorized: false },
|
|
74
107
|
logger: console,
|
|
75
|
-
name: "default",
|
|
76
108
|
...config
|
|
77
109
|
};
|
|
78
110
|
this.logger = this.config.logger;
|
|
@@ -172,9 +204,7 @@ var Db = class {
|
|
|
172
204
|
await this.testConnection();
|
|
173
205
|
}
|
|
174
206
|
this.isConnected = true;
|
|
175
|
-
this.logger.debug?.(
|
|
176
|
-
`[Db] Connected to database "${this.config.name || this.config.connectionString}"`
|
|
177
|
-
);
|
|
207
|
+
this.logger.debug?.(formatDbConnectMessage(this.config.name, this.config.connectionString));
|
|
178
208
|
} catch (error) {
|
|
179
209
|
if (error instanceof ParamError) {
|
|
180
210
|
throw error;
|
|
@@ -192,9 +222,7 @@ var Db = class {
|
|
|
192
222
|
this.knexInstance = null;
|
|
193
223
|
this.isConnected = false;
|
|
194
224
|
this.queriesLog = [];
|
|
195
|
-
this.logger.debug?.(
|
|
196
|
-
`[Db] Disconnected from database "${this.config.name || this.config.connectionString}"`
|
|
197
|
-
);
|
|
225
|
+
this.logger.debug?.(formatDbDisconnectMessage(this.config.name, this.config.connectionString));
|
|
198
226
|
} catch (error) {
|
|
199
227
|
const errorMsg = this.getErrorMessage(error);
|
|
200
228
|
this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);
|
|
@@ -323,15 +351,74 @@ var Db = class {
|
|
|
323
351
|
function capitalizeFirstLetter(str) {
|
|
324
352
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
325
353
|
}
|
|
354
|
+
function resolveDbDisplayName(dbName, connectionParam, argsEnv, mergedName) {
|
|
355
|
+
if (dbName) {
|
|
356
|
+
return dbName;
|
|
357
|
+
}
|
|
358
|
+
if (mergedName) {
|
|
359
|
+
return mergedName;
|
|
360
|
+
}
|
|
361
|
+
if (connectionParam?.startsWith("dbConnectionString") && connectionParam.length > "dbConnectionString".length) {
|
|
362
|
+
return connectionParam.slice("dbConnectionString".length).toLowerCase();
|
|
363
|
+
}
|
|
364
|
+
if (connectionParam === "dbConnectionString" && argsEnv) {
|
|
365
|
+
return argsEnv;
|
|
366
|
+
}
|
|
367
|
+
return void 0;
|
|
368
|
+
}
|
|
369
|
+
function formatDbConnectMessage(name, connectionString) {
|
|
370
|
+
const endpointSuffix = formatConnectionEndpointSuffix(connectionString);
|
|
371
|
+
if (name) {
|
|
372
|
+
return `[Db] Connected to database "${name}"${endpointSuffix}`;
|
|
373
|
+
}
|
|
374
|
+
return `[Db] Connected${endpointSuffix}`;
|
|
375
|
+
}
|
|
376
|
+
function formatDbDisconnectMessage(name, connectionString) {
|
|
377
|
+
const endpointSuffix = formatConnectionEndpointSuffix(connectionString);
|
|
378
|
+
if (name) {
|
|
379
|
+
return `[Db] Disconnected from database "${name}"${endpointSuffix}`;
|
|
380
|
+
}
|
|
381
|
+
return `[Db] Disconnected${endpointSuffix}`;
|
|
382
|
+
}
|
|
383
|
+
function formatDbInstanceMessage(action, name) {
|
|
384
|
+
if (name) {
|
|
385
|
+
return `[Db] instance "${name}" ${action}`;
|
|
386
|
+
}
|
|
387
|
+
return `[Db] instance ${action}`;
|
|
388
|
+
}
|
|
389
|
+
function formatConnectionEndpointSuffix(connectionString) {
|
|
390
|
+
const endpoint = formatConnectionEndpoint(connectionString);
|
|
391
|
+
return endpoint ? ` (${endpoint})` : "";
|
|
392
|
+
}
|
|
393
|
+
function formatConnectionEndpoint(connectionString) {
|
|
394
|
+
try {
|
|
395
|
+
const url = new URL(connectionString);
|
|
396
|
+
const host = url.hostname;
|
|
397
|
+
if (!host) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
let port = url.port;
|
|
401
|
+
if (!port) {
|
|
402
|
+
if (url.protocol === "postgresql:") {
|
|
403
|
+
port = "5432";
|
|
404
|
+
} else if (url.protocol === "mysql:") {
|
|
405
|
+
port = "3306";
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return port ? `${host}:${port}` : host;
|
|
409
|
+
} catch {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
326
413
|
async function dbConnect(context, config) {
|
|
327
414
|
try {
|
|
328
415
|
const db = new Db(config);
|
|
329
416
|
context.registerCleanup(async () => {
|
|
330
417
|
await db.disconnect();
|
|
331
|
-
context.logger.debug?.(
|
|
418
|
+
context.logger.debug?.(formatDbInstanceMessage("disconnected", config.name));
|
|
332
419
|
});
|
|
333
420
|
await db.connect();
|
|
334
|
-
context.logger.debug?.(
|
|
421
|
+
context.logger.debug?.(formatDbInstanceMessage("initialized", config.name));
|
|
335
422
|
return db;
|
|
336
423
|
} catch (error) {
|
|
337
424
|
if (error instanceof ParamError) {
|