@nmakarov/cli-toolkit 0.18.0 → 0.23.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.
Files changed (69) hide show
  1. package/README.md +9 -0
  2. package/dist/args.cjs +1 -4
  3. package/dist/args.cjs.map +1 -1
  4. package/dist/args.js +1 -1
  5. package/dist/args.js.map +1 -1
  6. package/dist/cli-runner.cjs +1493 -516
  7. package/dist/cli-runner.cjs.map +1 -1
  8. package/dist/cli-runner.js +1509 -531
  9. package/dist/cli-runner.js.map +1 -1
  10. package/dist/db.cjs +85 -157
  11. package/dist/db.cjs.map +1 -1
  12. package/dist/db.js +84 -150
  13. package/dist/db.js.map +1 -1
  14. package/dist/errors.cjs +2 -2
  15. package/dist/errors.cjs.map +1 -1
  16. package/dist/errors.js +2 -1
  17. package/dist/errors.js.map +1 -1
  18. package/dist/filedatabase.cjs +19 -19
  19. package/dist/filedatabase.cjs.map +1 -1
  20. package/dist/filedatabase.js +19 -16
  21. package/dist/filedatabase.js.map +1 -1
  22. package/dist/http-client.cjs +9 -11
  23. package/dist/http-client.cjs.map +1 -1
  24. package/dist/http-client.js +10 -9
  25. package/dist/http-client.js.map +1 -1
  26. package/dist/http-client2.cjs +34 -33
  27. package/dist/http-client2.cjs.map +1 -1
  28. package/dist/http-client2.js +34 -30
  29. package/dist/http-client2.js.map +1 -1
  30. package/dist/index.cjs +2063 -658
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.js +2063 -663
  33. package/dist/index.js.map +1 -1
  34. package/dist/init.cjs +97 -69
  35. package/dist/init.cjs.map +1 -1
  36. package/dist/init.js +112 -83
  37. package/dist/init.js.map +1 -1
  38. package/dist/logger.cjs +5 -5
  39. package/dist/logger.cjs.map +1 -1
  40. package/dist/logger.js +5 -4
  41. package/dist/logger.js.map +1 -1
  42. package/dist/mock-server.cjs +21 -33
  43. package/dist/mock-server.cjs.map +1 -1
  44. package/dist/mock-server.js +21 -28
  45. package/dist/mock-server.js.map +1 -1
  46. package/dist/params.cjs +22 -10
  47. package/dist/params.cjs.map +1 -1
  48. package/dist/params.js +22 -7
  49. package/dist/params.js.map +1 -1
  50. package/dist/s3.cjs +286 -0
  51. package/dist/s3.cjs.map +1 -0
  52. package/dist/s3.js +273 -0
  53. package/dist/s3.js.map +1 -0
  54. package/dist/screen.cjs +34 -39
  55. package/dist/screen.cjs.map +1 -1
  56. package/dist/screen.js +48 -46
  57. package/dist/screen.js.map +1 -1
  58. package/dist/tasks.cjs +1640 -416
  59. package/dist/tasks.cjs.map +1 -1
  60. package/dist/tasks.js +1614 -412
  61. package/dist/tasks.js.map +1 -1
  62. package/dist/utils.cjs +7 -8
  63. package/dist/utils.cjs.map +1 -1
  64. package/dist/utils.js +6 -6
  65. package/dist/utils.js.map +1 -1
  66. package/package.json +36 -44
  67. package/scripts/ssm/parse-cli.js +35 -0
  68. package/scripts/ssm/ssm-admin.js +151 -0
  69. package/scripts/ssm/ssm-pull.js +147 -0
package/dist/db.cjs CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -27,20 +26,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
26
  ));
28
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
28
 
30
- // src/db.ts
29
+ // src/db/index.js
31
30
  var db_exports = {};
32
31
  __export(db_exports, {
33
- Db: () => Db,
34
- dbConnect: () => dbConnect,
35
- dbFindAndConnect: () => dbFindAndConnect,
36
- dbInit: () => dbInit
32
+ Db: () => Db
37
33
  });
38
34
  module.exports = __toCommonJS(db_exports);
39
-
40
- // src/db/index.ts
41
35
  var import_knex = __toESM(require("knex"), 1);
42
36
 
43
- // src/errors.ts
37
+ // src/errors.js
44
38
  var FrameworkError = class extends Error {
45
39
  constructor(message) {
46
40
  super(message);
@@ -54,21 +48,56 @@ var ParamError = class extends FrameworkError {
54
48
  }
55
49
  };
56
50
 
57
- // src/db/index.ts
51
+ // src/db/index.js
52
+ var KNEX_DEFAULTS = {
53
+ testConnection: true,
54
+ pool: { min: 2, max: 10 },
55
+ acquireConnectionTimeout: 1e4,
56
+ ssl: { rejectUnauthorized: false }
57
+ };
58
58
  var Db = class {
59
- knexInstance = null;
60
- config;
61
- logger;
62
- queriesLog = [];
63
- isConnected = false;
64
- /**
65
- * Constructor - accepts config object
66
- * Use dbInit() function to initialize with Context
67
- */
59
+ static async init(context, options = {}) {
60
+ const defs = {
61
+ dbName: "string",
62
+ dbConnectionString: "string",
63
+ dbProfile: "boolean default false"
64
+ };
65
+ const discovered = context?.params?.getAllForModule?.("db", defs) ?? {};
66
+ const merged = { ...discovered, ...options };
67
+ let { dbName, dbConnectionString } = merged;
68
+ const { dbProfile } = merged;
69
+ if (!dbName && !dbConnectionString) {
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");
79
+ if (!dbConnectionString) {
80
+ throw new ParamError(
81
+ `Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
82
+ );
83
+ }
84
+ }
85
+ const config = {
86
+ ...KNEX_DEFAULTS,
87
+ connectionString: dbConnectionString,
88
+ name: dbName || merged.name || "default",
89
+ profile: !!dbProfile,
90
+ logger: context.logger
91
+ };
92
+ return dbConnect(context, config);
93
+ }
68
94
  constructor(config) {
69
- if (!config.connectionString) {
95
+ if (!config || !config.connectionString) {
70
96
  throw new ParamError("Db: connectionString is required");
71
97
  }
98
+ this.knexInstance = null;
99
+ this.isConnected = false;
100
+ this.queriesLog = [];
72
101
  this.config = {
73
102
  testConnection: true,
74
103
  profile: false,
@@ -81,25 +110,23 @@ var Db = class {
81
110
  };
82
111
  this.logger = this.config.logger;
83
112
  const instance = this;
84
- const callableWrapper = function(...args) {
113
+ const callableWrapper = function() {
85
114
  throw new Error("This should never be called directly");
86
115
  };
87
116
  callableWrapper._instance = instance;
88
117
  return new Proxy(callableWrapper, {
89
- // Intercept function calls: db('table')
90
- apply: (target, thisArg, argumentsList) => {
118
+ apply: (target, _thisArg, argumentsList) => {
91
119
  const inst = target._instance;
92
120
  if (!inst.knexInstance) {
93
121
  throw new Error("Db: Not connected. Call connect() first.");
94
122
  }
95
123
  return inst.knexInstance(...argumentsList);
96
124
  },
97
- // Intercept property access: db.schema, db.raw, etc.
98
125
  get: (target, prop) => {
99
126
  if (prop === "_instance") {
100
127
  return target._instance;
101
128
  }
102
- const instance2 = target._instance;
129
+ const inst = target._instance;
103
130
  const ownMethods = [
104
131
  "connect",
105
132
  "disconnect",
@@ -112,26 +139,26 @@ var Db = class {
112
139
  "detectClient",
113
140
  "attachProfiler"
114
141
  ];
115
- if (prop in instance2) {
116
- const value = instance2[prop];
142
+ if (prop in inst) {
143
+ const value = inst[prop];
117
144
  if (typeof value === "function" && ownMethods.includes(prop)) {
118
- return value.bind(instance2);
145
+ return value.bind(inst);
119
146
  }
120
147
  if (typeof value !== "function") {
121
148
  return value;
122
149
  }
123
150
  }
124
- if (instance2.knexInstance) {
125
- const knexProp = instance2.knexInstance[prop];
151
+ if (inst.knexInstance) {
152
+ const knexProp = inst.knexInstance[prop];
126
153
  if (typeof knexProp === "function") {
127
- return knexProp.bind(instance2.knexInstance);
154
+ return knexProp.bind(inst.knexInstance);
128
155
  }
129
156
  return knexProp;
130
157
  }
131
- if (prop in instance2) {
132
- const method = instance2[prop];
158
+ if (prop in inst) {
159
+ const method = inst[prop];
133
160
  if (typeof method === "function") {
134
- return method.bind(instance2);
161
+ return method.bind(inst);
135
162
  }
136
163
  return method;
137
164
  }
@@ -139,9 +166,6 @@ var Db = class {
139
166
  }
140
167
  });
141
168
  }
142
- /**
143
- * Detect database client type from connection string
144
- */
145
169
  detectClient(connectionString) {
146
170
  if (connectionString.match(/^postgresql/)) {
147
171
  return "pg";
@@ -151,9 +175,6 @@ var Db = class {
151
175
  }
152
176
  return null;
153
177
  }
154
- /**
155
- * Connect to the database
156
- */
157
178
  async connect() {
158
179
  if (this.isConnected && this.knexInstance) {
159
180
  this.logger.warn?.("[Db] Already connected");
@@ -162,14 +183,13 @@ var Db = class {
162
183
  const client = this.detectClient(this.config.connectionString);
163
184
  if (!client) {
164
185
  throw new ParamError(
165
- `Db: Cannot determine client type from connection string. Expected postgresql:// or mysql://`
186
+ "Db: Cannot determine client type from connection string. Expected postgresql:// or mysql://"
166
187
  );
167
188
  }
168
189
  try {
169
190
  const connectionConfig = {
170
191
  connectionString: this.config.connectionString,
171
192
  family: 4
172
- // Force IPv4 only (disable IPv6)
173
193
  };
174
194
  this.knexInstance = (0, import_knex.default)({
175
195
  client,
@@ -185,7 +205,9 @@ var Db = class {
185
205
  await this.testConnection();
186
206
  }
187
207
  this.isConnected = true;
188
- this.logger.debug?.(`[Db] Connected to database "${this.config.name || this.config.connectionString}"`);
208
+ this.logger.debug?.(
209
+ `[Db] Connected to database "${this.config.name || this.config.connectionString}"`
210
+ );
189
211
  } catch (error) {
190
212
  if (error instanceof ParamError) {
191
213
  throw error;
@@ -194,9 +216,6 @@ var Db = class {
194
216
  throw new ParamError(`Db: Connection failed - ${errorMsg}`);
195
217
  }
196
218
  }
197
- /**
198
- * Disconnect from the database
199
- */
200
219
  async disconnect() {
201
220
  if (!this.knexInstance) {
202
221
  return;
@@ -206,16 +225,15 @@ var Db = class {
206
225
  this.knexInstance = null;
207
226
  this.isConnected = false;
208
227
  this.queriesLog = [];
209
- this.logger.debug?.(`[Db] Disconnected from database "${this.config.name || this.config.connectionString}"`);
228
+ this.logger.debug?.(
229
+ `[Db] Disconnected from database "${this.config.name || this.config.connectionString}"`
230
+ );
210
231
  } catch (error) {
211
232
  const errorMsg = this.getErrorMessage(error);
212
233
  this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);
213
234
  throw error;
214
235
  }
215
236
  }
216
- /**
217
- * Extract error message from various error types
218
- */
219
237
  getErrorMessage(error) {
220
238
  if (error instanceof AggregateError) {
221
239
  const errors = error.errors || [];
@@ -240,9 +258,11 @@ var Db = class {
240
258
  return `${code} (tried: ${addresses.join(", ")})`;
241
259
  }
242
260
  }
243
- const uniqueMessages = [...new Set(errors.map((e) => {
244
- return e instanceof Error ? e.message : String(e);
245
- }))];
261
+ const uniqueMessages = [
262
+ ...new Set(
263
+ errors.map((e) => e instanceof Error ? e.message : String(e))
264
+ )
265
+ ];
246
266
  if (uniqueMessages.length === 1) {
247
267
  return uniqueMessages[0];
248
268
  }
@@ -251,28 +271,25 @@ var Db = class {
251
271
  return error.message || "Multiple errors occurred";
252
272
  }
253
273
  if (error instanceof Error) {
254
- const errorWithCode = error;
255
- if (errorWithCode.code) {
256
- return `${errorWithCode.code}: ${error.message || String(error)}`;
274
+ const code = error.code;
275
+ if (code) {
276
+ return `${code}: ${error.message || String(error)}`;
257
277
  }
258
278
  return error.message || String(error);
259
279
  }
260
280
  if (typeof error === "string") {
261
281
  return error;
262
282
  }
263
- if (error?.message) {
283
+ if (error && typeof error === "object" && "message" in error) {
264
284
  const msg = String(error.message);
265
- const errorWithCode = error;
266
- if (errorWithCode.code) {
267
- return `${errorWithCode.code}: ${msg}`;
285
+ const code = error.code;
286
+ if (code) {
287
+ return `${code}: ${msg}`;
268
288
  }
269
289
  return msg;
270
290
  }
271
291
  return String(error) || "Unknown error";
272
292
  }
273
- /**
274
- * Test database connection
275
- */
276
293
  async testConnection() {
277
294
  if (!this.knexInstance) {
278
295
  throw new Error("Db: Not connected. Call connect() first.");
@@ -288,9 +305,6 @@ var Db = class {
288
305
  throw new ParamError(`Db: Connection test failed - ${errorMsg}`);
289
306
  }
290
307
  }
291
- /**
292
- * Attach query profiler to log all queries
293
- */
294
308
  attachProfiler() {
295
309
  if (!this.knexInstance) {
296
310
  return;
@@ -300,7 +314,7 @@ var Db = class {
300
314
  this.knexInstance.on("query", (query) => {
301
315
  query.__startTime = process.hrtime();
302
316
  });
303
- this.knexInstance.on("query-response", (response, query) => {
317
+ this.knexInstance.on("query-response", (_response, query) => {
304
318
  const [seconds, nanoseconds] = process.hrtime(query.__startTime);
305
319
  const executionTimeMs = (seconds * 1e3 + nanoseconds / 1e6).toFixed(2);
306
320
  const logEntry = {
@@ -315,15 +329,9 @@ var Db = class {
315
329
  this.logger.error?.(`[Db] Query failed: ${query.sql}`, error);
316
330
  });
317
331
  }
318
- /**
319
- * Get query log (only available if profiling is enabled)
320
- */
321
332
  getQueryLog() {
322
333
  return [...this.queriesLog];
323
334
  }
324
- /**
325
- * Check if a table exists
326
- */
327
335
  async tableExists(tableName) {
328
336
  if (!this.knexInstance) {
329
337
  throw new Error("Db: Not connected. Call connect() first.");
@@ -335,65 +343,28 @@ var Db = class {
335
343
  throw error;
336
344
  }
337
345
  }
338
- /**
339
- * Get the underlying Knex instance (for advanced usage)
340
- */
341
346
  getKnex() {
342
347
  if (!this.knexInstance) {
343
348
  throw new Error("Db: Not connected. Call connect() first.");
344
349
  }
345
350
  return this.knexInstance;
346
351
  }
347
- /**
348
- * Get connection status
349
- */
350
352
  isConnectedToDb() {
351
353
  return this.isConnected && this.knexInstance !== null;
352
354
  }
353
- /**
354
- * Initialize Db with context (connects and registers disconnect cleanup).
355
- * Params are read via getAllForModule("db", defs). Same as dbInit(context, dbNameOrConnectionString).
356
- */
357
- static async init(context, dbNameOrConnectionString) {
358
- return dbFindAndConnect(context, dbNameOrConnectionString);
359
- }
360
355
  };
361
356
  function capitalizeFirstLetter(str) {
362
357
  return str.charAt(0).toUpperCase() + str.slice(1);
363
358
  }
364
- async function dbConnect(context, connectionString, name, dbProfile) {
365
- const defs = {
366
- testDbConnection: "boolean default true",
367
- name: "string",
368
- poolMin: "number default 2",
369
- poolMax: "number default 10",
370
- acquireConnectionTimeout: "number default 10000",
371
- sslRejectUnauthorized: "boolean default false"
372
- };
373
- const paramsConfig = context.params.getAllForModule(defs);
374
- const config = {
375
- connectionString,
376
- name: paramsConfig.name || name || "default",
377
- testConnection: paramsConfig.testDbConnection,
378
- profile: dbProfile ?? false,
379
- pool: {
380
- min: paramsConfig.poolMin,
381
- max: paramsConfig.poolMax
382
- },
383
- acquireConnectionTimeout: paramsConfig.acquireConnectionTimeout,
384
- ssl: {
385
- rejectUnauthorized: paramsConfig.sslRejectUnauthorized
386
- },
387
- logger: context.logger
388
- };
359
+ async function dbConnect(context, config) {
389
360
  try {
390
361
  const db = new Db(config);
391
362
  context.registerCleanup(async () => {
392
363
  await db.disconnect();
393
- context.logger.debug(`[Db] instance "${name || connectionString}" destroyed`);
364
+ context.logger.debug?.(`[Db] instance "${config.name}" disconnected`);
394
365
  });
395
366
  await db.connect();
396
- context.logger.debug(`[Db] instance "${name || connectionString}" initialized`);
367
+ context.logger.debug?.(`[Db] instance "${config.name}" initialized`);
397
368
  return db;
398
369
  } catch (error) {
399
370
  if (error instanceof ParamError) {
@@ -403,51 +374,8 @@ async function dbConnect(context, connectionString, name, dbProfile) {
403
374
  throw new ParamError(`[Db] connect error: ${errorMsg}`);
404
375
  }
405
376
  }
406
- async function dbFindAndConnect(context, dbNameOrConnectionString) {
407
- let dbName;
408
- let dbConnectionString;
409
- let dbProfile;
410
- if (dbNameOrConnectionString) {
411
- if (dbNameOrConnectionString.match(/^(postgresql|mysql):\/\/[^\s]+:[^\s]+@[^\s]+:\d+\/[^\s]+$/)) {
412
- dbName = void 0;
413
- dbConnectionString = dbNameOrConnectionString;
414
- } else {
415
- dbName = dbNameOrConnectionString;
416
- }
417
- } else {
418
- const defs = {
419
- dbName: "string",
420
- dbConnectionString: "string",
421
- dbProfile: "boolean default false"
422
- };
423
- const paramsConfig = context.params.getAllForModule(defs);
424
- dbName = paramsConfig.dbName;
425
- dbConnectionString = paramsConfig.dbConnectionString;
426
- dbProfile = paramsConfig.dbProfile;
427
- }
428
- if (!dbName && !dbConnectionString) {
429
- throw new ParamError("Db: either dbName or dbConnectionString must be specified");
430
- }
431
- if (dbName) {
432
- const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
433
- dbConnectionString = await context.params.get(paramName, "string");
434
- if (!dbConnectionString) {
435
- throw new ParamError(
436
- `Db: cannot find dbConnectionString for dbName="${dbName}" (looked for param "${paramName}")`
437
- );
438
- }
439
- }
440
- const db = await dbConnect(context, dbConnectionString, dbName, dbProfile);
441
- return db;
442
- }
443
- async function dbInit(context, dbNameOrConnectionString) {
444
- return await dbFindAndConnect(context, dbNameOrConnectionString);
445
- }
446
377
  // Annotate the CommonJS export names for ESM import in node:
447
378
  0 && (module.exports = {
448
- Db,
449
- dbConnect,
450
- dbFindAndConnect,
451
- dbInit
379
+ Db
452
380
  });
453
381
  //# sourceMappingURL=db.cjs.map
package/dist/db.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/db.ts","../src/db/index.ts","../src/errors.ts"],"sourcesContent":["// Re-export Db module\nexport * from \"./db/index.js\";\n\n","/**\n * Database Client - Low-level SQL database operations\n *\n * Wraps Knex.js with connection management, profiling, and utility functions.\n * The instance can be used directly like a Knex instance: db('table').select()\n */\n\nimport knex, { Knex } from 'knex';\nimport { ParamError } from '../errors.js';\nimport type { Context } from '../init/types.js';\nimport type { DbConfig, DbOptions, DatabaseClient, QueryLogEntry, DbInstance } from './types.js';\n\n/**\n * Database client wrapper around Knex\n * \n * Usage:\n * ```typescript\n * const db = new Db({\n * connectionString: 'postgresql://user:pass@host:5432/dbname',\n * testConnection: true,\n * profile: false\n * });\n * await db.connect();\n * \n * // Use like Knex:\n * const users = await db('users').select('*');\n * await db('posts').insert({ title: 'Hello' });\n * ```\n */\nexport class Db {\n private knexInstance: Knex | null = null;\n private config: Required<DbConfig>;\n private logger: any;\n private queriesLog: QueryLogEntry[] = [];\n private isConnected: boolean = false;\n\n /**\n * Constructor - accepts config object\n * Use dbInit() function to initialize with Context\n */\n constructor(config: DbConfig) {\n if (!config.connectionString) {\n throw new ParamError('Db: connectionString is required');\n }\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 // Create a callable function wrapper that forwards to the instance\n // This allows db('table') to work like Knex\n const instance = this;\n const callableWrapper = function(...args: any[]) {\n // This function body is never executed - the Proxy apply trap handles calls\n // But we need a function to make the Proxy apply trap work\n throw new Error('This should never be called directly');\n };\n \n // Store instance reference on the wrapper for Proxy access\n (callableWrapper as any)._instance = instance;\n\n // Create a Proxy that makes the wrapper callable and forwards property access\n return new Proxy(callableWrapper, {\n // Intercept function calls: db('table')\n apply: (target, thisArg, argumentsList) => {\n const inst = (target as any)._instance;\n if (!inst.knexInstance) {\n throw new Error('Db: Not connected. Call connect() first.');\n }\n // Forward the call to the Knex instance (Knex instances are callable)\n return (inst.knexInstance as any)(...argumentsList);\n },\n // Intercept property access: db.schema, db.raw, etc.\n get: (target, prop) => {\n // Allow access to _instance for internal use\n if (prop === '_instance') {\n return (target as any)._instance;\n }\n \n const instance = (target as any)._instance;\n \n // List of our own methods that should NOT be forwarded to Knex\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 // Always return our own methods first (before checking Knex)\n if (prop in instance) {\n const value = (instance as any)[prop];\n // If it's one of our own methods, return it bound to instance\n if (typeof value === 'function' && ownMethods.includes(prop as string)) {\n return value.bind(instance);\n }\n // If it's a non-function property, return it\n if (typeof value !== 'function') {\n return value;\n }\n }\n \n // If we have a Knex instance, forward to it for everything else\n if (instance.knexInstance) {\n const knexProp = (instance.knexInstance as any)[prop];\n if (typeof knexProp === 'function') {\n // Bind methods to the Knex instance\n return knexProp.bind(instance.knexInstance);\n }\n return knexProp;\n }\n \n // Return our own methods that aren't in the ownMethods list (shouldn't happen, but fallback)\n if (prop in instance) {\n const method = (instance as any)[prop];\n if (typeof method === 'function') {\n return method.bind(instance);\n }\n return method;\n }\n \n // Property doesn't exist\n return undefined;\n },\n }) as any;\n }\n\n /**\n * Detect database client type from connection string\n */\n private detectClient(connectionString: string): DatabaseClient | null {\n if (connectionString.match(/^postgresql/)) {\n return 'pg';\n }\n if (connectionString.match(/^mysql/)) {\n return 'mysql2';\n }\n return null;\n }\n\n /**\n * Connect to the database\n */\n async connect(): Promise<void> {\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 // Force IPv4 only (disable IPv6) by setting family: 4 in connection config\n // Knex accepts connection as string or object; we wrap string to add family option\n const connectionConfig = {\n connectionString: this.config.connectionString,\n family: 4, // Force IPv4 only (disable IPv6)\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 } as any);\n\n // Attach profiler if enabled\n if (this.config.profile) {\n this.attachProfiler();\n }\n\n // Test connection if requested\n if (this.config.testConnection) {\n await this.testConnection();\n }\n\n this.isConnected = true;\n this.logger.debug?.(`[Db] Connected to database \"${this.config.name || this.config.connectionString}\"`);\n } catch (error: any) {\n // If testConnection already threw a ParamError, preserve its message\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 /**\n * Disconnect from the database\n */\n async disconnect(): Promise<void> {\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?.(`[Db] Disconnected from database \"${this.config.name || this.config.connectionString}\"`);\n } catch (error: any) {\n const errorMsg = this.getErrorMessage(error);\n this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);\n throw error;\n }\n }\n\n /**\n * Extract error message from various error types\n */\n private getErrorMessage(error: any): string {\n // Handle AggregateError (can contain multiple errors)\n if (error instanceof AggregateError) {\n const errors = error.errors || [];\n \n // If all errors are the same type (e.g., ECONNREFUSED for different IPs), show a consolidated message\n if (errors.length > 0) {\n const firstError = errors[0];\n const firstErrorMsg = firstError instanceof Error ? firstError.message : String(firstError);\n \n // Check if all errors are similar (same error code/type, different addresses)\n const allSimilar = errors.every((e: any) => {\n const msg = e instanceof Error ? e.message : String(e);\n // Extract error code (e.g., \"ECONNREFUSED\") from message\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 // Extract addresses/IPs from error messages\n const addresses = errors.map((e: any) => {\n const msg = e instanceof Error ? e.message : String(e);\n // Try to extract address (e.g., \"::1:5432\" or \"127.0.0.1:5432\")\n const addrMatch = msg.match(/([:\\d.]+:\\d+)/);\n return addrMatch ? addrMatch[1] : null;\n }).filter(Boolean);\n \n if (addresses.length > 0) {\n // Show consolidated message with all addresses\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 // Fallback: show all errors but deduplicate identical messages\n const uniqueMessages = [...new Set(errors.map((e: any) => {\n return e instanceof Error ? e.message : String(e);\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 // Handle standard Error objects\n if (error instanceof Error) {\n // Check for common database error properties (code is often present on Node.js errors)\n const errorWithCode = error as Error & { code?: string };\n if (errorWithCode.code) {\n return `${errorWithCode.code}: ${error.message || String(error)}`;\n }\n return error.message || String(error);\n }\n \n // Handle string errors\n if (typeof error === 'string') {\n return error;\n }\n \n // Handle objects with message property\n if (error?.message) {\n const msg = String(error.message);\n const errorWithCode = error as { code?: string };\n if (errorWithCode.code) {\n return `${errorWithCode.code}: ${msg}`;\n }\n return msg;\n }\n \n // Fallback: try to stringify the error\n return String(error) || 'Unknown error';\n }\n\n /**\n * Test database connection\n */\n async testConnection(): Promise<boolean> {\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: any) {\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 /**\n * Attach query profiler to log all queries\n */\n private attachProfiler(): void {\n if (!this.knexInstance) {\n return;\n }\n\n this.queriesLog = [];\n (this.knexInstance as any).queriesLog = this.queriesLog;\n\n this.knexInstance.on('query', (query: any) => {\n query.__startTime = process.hrtime();\n });\n\n this.knexInstance.on('query-response', (response: any, query: any) => {\n const [seconds, nanoseconds] = process.hrtime(query.__startTime);\n const executionTimeMs = ((seconds * 1000) + (nanoseconds / 1e6)).toFixed(2);\n\n const logEntry: QueryLogEntry = {\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: Error, query: any) => {\n this.logger.error?.(`[Db] Query failed: ${query.sql}`, error);\n });\n }\n\n /**\n * Get query log (only available if profiling is enabled)\n */\n getQueryLog(): QueryLogEntry[] {\n return [...this.queriesLog];\n }\n\n /**\n * Check if a table exists\n */\n async tableExists(tableName: string): Promise<boolean> {\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: any) {\n this.logger.error?.(`[Db] Error checking table existence: ${error.message}`);\n throw error;\n }\n }\n\n /**\n * Get the underlying Knex instance (for advanced usage)\n */\n getKnex(): Knex {\n if (!this.knexInstance) {\n throw new Error('Db: Not connected. Call connect() first.');\n }\n return this.knexInstance;\n }\n\n /**\n * Get connection status\n */\n isConnectedToDb(): boolean {\n return this.isConnected && this.knexInstance !== null;\n }\n\n /**\n * Initialize Db with context (connects and registers disconnect cleanup).\n * Params are read via getAllForModule(\"db\", defs). Same as dbInit(context, dbNameOrConnectionString).\n */\n static async init(context: Context, dbNameOrConnectionString?: string): Promise<Db> {\n return dbFindAndConnect(context, dbNameOrConnectionString);\n }\n}\n\n/**\n * Helper function to capitalize first letter of a string\n */\nfunction capitalizeFirstLetter(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Connect to database - creates Db instance, connects, registers cleanup, attaches profiler\n * \n * This is a dedicated connect function that handles:\n * - Creating Db instance with proper configuration\n * - Connecting to database\n * - Registering cleanup function\n * - Attaching profiler if needed\n * - Better error handling\n */\nexport async function dbConnect(\n context: Context,\n connectionString: string,\n name?: string,\n dbProfile?: boolean\n): Promise<Db> {\n // Get configuration from params\n const defs = {\n testDbConnection: 'boolean default true',\n name: 'string',\n poolMin: 'number default 2',\n poolMax: 'number default 10',\n acquireConnectionTimeout: 'number default 10000',\n sslRejectUnauthorized: 'boolean default false',\n };\n \n const paramsConfig = context.params.getAllForModule(defs);\n\n // Create config\n const config: DbConfig = {\n connectionString,\n name: paramsConfig.name || name || 'default',\n testConnection: paramsConfig.testDbConnection,\n profile: dbProfile ?? false,\n pool: {\n min: paramsConfig.poolMin,\n max: paramsConfig.poolMax,\n },\n acquireConnectionTimeout: paramsConfig.acquireConnectionTimeout,\n ssl: {\n rejectUnauthorized: paramsConfig.sslRejectUnauthorized,\n },\n logger: context.logger,\n };\n \n try {\n // Create Db instance\n const db = new Db(config);\n \n // Register cleanup function\n context.registerCleanup(async () => {\n await db.disconnect();\n context.logger.debug(`[Db] instance \"${name || connectionString}\" destroyed`);\n });\n \n // Connect to database (profiler is attached automatically if config.profile is true)\n await db.connect();\n \n context.logger.debug(`[Db] instance \"${name || connectionString}\" initialized`);\n \n return db;\n } catch (error: any) {\n // Better error handling\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/**\n * Find and connect to database - resolves database name or connection string\n * \n * This function handles:\n * - Direct connection string (postgresql://... or mysql://...)\n * - Database name/label that gets resolved to dbConnectionString${CapitalizedName}\n * - Reading from params if no second parameter provided\n */\nexport async function dbFindAndConnect(\n context: Context,\n dbNameOrConnectionString?: string\n): Promise<Db> {\n let dbName: string | undefined;\n let dbConnectionString: string | undefined;\n let dbProfile: boolean | undefined;\n \n // If second parameter is provided\n if (dbNameOrConnectionString) {\n // Check if it looks like a connection string (postgresql:// or mysql://)\n if (dbNameOrConnectionString.match(/^(postgresql|mysql):\\/\\/[^\\s]+:[^\\s]+@[^\\s]+:\\d+\\/[^\\s]+$/)) {\n dbName = undefined;\n dbConnectionString = dbNameOrConnectionString;\n } else {\n // Treat it as a database name/label\n dbName = dbNameOrConnectionString;\n }\n } else {\n // No second parameter - read from params\n const defs = {\n dbName: 'string',\n dbConnectionString: 'string',\n dbProfile: 'boolean default false',\n };\n \n const paramsConfig = context.params.getAllForModule(defs);\n dbName = paramsConfig.dbName;\n dbConnectionString = paramsConfig.dbConnectionString;\n dbProfile = paramsConfig.dbProfile;\n }\n \n // Validate that we have either dbName or dbConnectionString\n if (!dbName && !dbConnectionString) {\n throw new ParamError('Db: either dbName or dbConnectionString must be specified');\n }\n \n // If dbName is provided, resolve it to connection string\n if (dbName) {\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 // Connect using dedicated connect function\n const db = await dbConnect(context, dbConnectionString!, dbName, dbProfile);\n \n // Test connection (connect() already tests if testConnection is true, but we can test explicitly here too)\n // The test is already done in db.connect() if config.testConnection is true\n \n return db;\n}\n\n/**\n * Initialize Db instance with context (auto-connects)\n * \n * This is the standard \"init\" function that auto-initializes the DB component.\n * It calls dbFindAndConnect, optionally passing a second parameter.\n * \n * Usage:\n * ```typescript\n * // Auto-initialize from params:\n * const db = await dbInit(context);\n * \n * // Or with database name/label:\n * const db = await dbInit(context, 'local');\n * \n * // Or with direct connection string:\n * const db = await dbInit(context, 'postgresql://user:pass@host:5432/dbname');\n * ```\n */\nexport async function dbInit(\n context: Context,\n dbNameOrConnectionString?: string\n): Promise<Db> {\n return await dbFindAndConnect(context, dbNameOrConnectionString);\n}\n\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\nexport class HttpClientError extends FrameworkError {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = \"HttpClientError\";\n }\n}\n\nexport class FileDatabaseError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"FileDatabaseError\";\n }\n}\n\n"],"mappings":"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","names":["instance","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 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"]}