@nmakarov/cli-toolkit 0.21.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.
Files changed (68) hide show
  1. package/dist/args.cjs +1 -4
  2. package/dist/args.cjs.map +1 -1
  3. package/dist/args.js +1 -1
  4. package/dist/args.js.map +1 -1
  5. package/dist/cli-runner.cjs +1370 -623
  6. package/dist/cli-runner.cjs.map +1 -1
  7. package/dist/cli-runner.js +1415 -667
  8. package/dist/cli-runner.js.map +1 -1
  9. package/dist/db.cjs +173 -158
  10. package/dist/db.cjs.map +1 -1
  11. package/dist/db.js +172 -151
  12. package/dist/db.js.map +1 -1
  13. package/dist/errors.cjs +2 -2
  14. package/dist/errors.cjs.map +1 -1
  15. package/dist/errors.js +2 -1
  16. package/dist/errors.js.map +1 -1
  17. package/dist/filedatabase.cjs +19 -19
  18. package/dist/filedatabase.cjs.map +1 -1
  19. package/dist/filedatabase.js +19 -16
  20. package/dist/filedatabase.js.map +1 -1
  21. package/dist/http-client.cjs +9 -11
  22. package/dist/http-client.cjs.map +1 -1
  23. package/dist/http-client.js +10 -9
  24. package/dist/http-client.js.map +1 -1
  25. package/dist/http-client2.cjs +34 -37
  26. package/dist/http-client2.cjs.map +1 -1
  27. package/dist/http-client2.js +34 -34
  28. package/dist/http-client2.js.map +1 -1
  29. package/dist/index.cjs +1831 -713
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +1837 -713
  32. package/dist/index.js.map +1 -1
  33. package/dist/init.cjs +93 -68
  34. package/dist/init.cjs.map +1 -1
  35. package/dist/init.js +108 -82
  36. package/dist/init.js.map +1 -1
  37. package/dist/logger.cjs +5 -5
  38. package/dist/logger.cjs.map +1 -1
  39. package/dist/logger.js +5 -4
  40. package/dist/logger.js.map +1 -1
  41. package/dist/mock-server.cjs +21 -33
  42. package/dist/mock-server.cjs.map +1 -1
  43. package/dist/mock-server.js +21 -28
  44. package/dist/mock-server.js.map +1 -1
  45. package/dist/params.cjs +18 -9
  46. package/dist/params.cjs.map +1 -1
  47. package/dist/params.js +18 -6
  48. package/dist/params.js.map +1 -1
  49. package/dist/s3.cjs +286 -0
  50. package/dist/s3.cjs.map +1 -0
  51. package/dist/s3.js +273 -0
  52. package/dist/s3.js.map +1 -0
  53. package/dist/screen.cjs +34 -39
  54. package/dist/screen.cjs.map +1 -1
  55. package/dist/screen.js +48 -46
  56. package/dist/screen.js.map +1 -1
  57. package/dist/tasks.cjs +1354 -501
  58. package/dist/tasks.cjs.map +1 -1
  59. package/dist/tasks.js +1369 -527
  60. package/dist/tasks.js.map +1 -1
  61. package/dist/utils.cjs +7 -8
  62. package/dist/utils.cjs.map +1 -1
  63. package/dist/utils.js +6 -6
  64. package/dist/utils.js.map +1 -1
  65. package/package.json +32 -47
  66. package/scripts/ssm/{parse-cli.ts → parse-cli.js} +4 -4
  67. package/scripts/ssm/{ssm-admin.ts → ssm-admin.js} +12 -12
  68. package/scripts/ssm/{ssm-pull.ts → ssm-pull.js} +10 -13
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,89 @@ 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 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;
70
+ if (!dbConnectionString) {
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
+ }
76
+ }
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
+ };
123
+ };
124
+ const config = context?.params?.runWithModuleAsync ? await context.params.runWithModuleAsync("db", buildConfig) : await buildConfig();
125
+ return dbConnect(context, config);
126
+ }
68
127
  constructor(config) {
69
- if (!config.connectionString) {
128
+ if (!config || !config.connectionString) {
70
129
  throw new ParamError("Db: connectionString is required");
71
130
  }
131
+ this.knexInstance = null;
132
+ this.isConnected = false;
133
+ this.queriesLog = [];
72
134
  this.config = {
73
135
  testConnection: true,
74
136
  profile: false,
@@ -76,30 +138,27 @@ var Db = class {
76
138
  acquireConnectionTimeout: 1e4,
77
139
  ssl: { rejectUnauthorized: false },
78
140
  logger: console,
79
- name: "default",
80
141
  ...config
81
142
  };
82
143
  this.logger = this.config.logger;
83
144
  const instance = this;
84
- const callableWrapper = function(...args) {
145
+ const callableWrapper = function() {
85
146
  throw new Error("This should never be called directly");
86
147
  };
87
148
  callableWrapper._instance = instance;
88
149
  return new Proxy(callableWrapper, {
89
- // Intercept function calls: db('table')
90
- apply: (target, thisArg, argumentsList) => {
150
+ apply: (target, _thisArg, argumentsList) => {
91
151
  const inst = target._instance;
92
152
  if (!inst.knexInstance) {
93
153
  throw new Error("Db: Not connected. Call connect() first.");
94
154
  }
95
155
  return inst.knexInstance(...argumentsList);
96
156
  },
97
- // Intercept property access: db.schema, db.raw, etc.
98
157
  get: (target, prop) => {
99
158
  if (prop === "_instance") {
100
159
  return target._instance;
101
160
  }
102
- const instance2 = target._instance;
161
+ const inst = target._instance;
103
162
  const ownMethods = [
104
163
  "connect",
105
164
  "disconnect",
@@ -112,26 +171,26 @@ var Db = class {
112
171
  "detectClient",
113
172
  "attachProfiler"
114
173
  ];
115
- if (prop in instance2) {
116
- const value = instance2[prop];
174
+ if (prop in inst) {
175
+ const value = inst[prop];
117
176
  if (typeof value === "function" && ownMethods.includes(prop)) {
118
- return value.bind(instance2);
177
+ return value.bind(inst);
119
178
  }
120
179
  if (typeof value !== "function") {
121
180
  return value;
122
181
  }
123
182
  }
124
- if (instance2.knexInstance) {
125
- const knexProp = instance2.knexInstance[prop];
183
+ if (inst.knexInstance) {
184
+ const knexProp = inst.knexInstance[prop];
126
185
  if (typeof knexProp === "function") {
127
- return knexProp.bind(instance2.knexInstance);
186
+ return knexProp.bind(inst.knexInstance);
128
187
  }
129
188
  return knexProp;
130
189
  }
131
- if (prop in instance2) {
132
- const method = instance2[prop];
190
+ if (prop in inst) {
191
+ const method = inst[prop];
133
192
  if (typeof method === "function") {
134
- return method.bind(instance2);
193
+ return method.bind(inst);
135
194
  }
136
195
  return method;
137
196
  }
@@ -139,9 +198,6 @@ var Db = class {
139
198
  }
140
199
  });
141
200
  }
142
- /**
143
- * Detect database client type from connection string
144
- */
145
201
  detectClient(connectionString) {
146
202
  if (connectionString.match(/^postgresql/)) {
147
203
  return "pg";
@@ -151,9 +207,6 @@ var Db = class {
151
207
  }
152
208
  return null;
153
209
  }
154
- /**
155
- * Connect to the database
156
- */
157
210
  async connect() {
158
211
  if (this.isConnected && this.knexInstance) {
159
212
  this.logger.warn?.("[Db] Already connected");
@@ -162,14 +215,13 @@ var Db = class {
162
215
  const client = this.detectClient(this.config.connectionString);
163
216
  if (!client) {
164
217
  throw new ParamError(
165
- `Db: Cannot determine client type from connection string. Expected postgresql:// or mysql://`
218
+ "Db: Cannot determine client type from connection string. Expected postgresql:// or mysql://"
166
219
  );
167
220
  }
168
221
  try {
169
222
  const connectionConfig = {
170
223
  connectionString: this.config.connectionString,
171
224
  family: 4
172
- // Force IPv4 only (disable IPv6)
173
225
  };
174
226
  this.knexInstance = (0, import_knex.default)({
175
227
  client,
@@ -185,7 +237,7 @@ var Db = class {
185
237
  await this.testConnection();
186
238
  }
187
239
  this.isConnected = true;
188
- this.logger.debug?.(`[Db] Connected to database "${this.config.name || this.config.connectionString}"`);
240
+ this.logger.debug?.(formatDbConnectMessage(this.config.name, this.config.connectionString));
189
241
  } catch (error) {
190
242
  if (error instanceof ParamError) {
191
243
  throw error;
@@ -194,9 +246,6 @@ var Db = class {
194
246
  throw new ParamError(`Db: Connection failed - ${errorMsg}`);
195
247
  }
196
248
  }
197
- /**
198
- * Disconnect from the database
199
- */
200
249
  async disconnect() {
201
250
  if (!this.knexInstance) {
202
251
  return;
@@ -206,16 +255,13 @@ var Db = class {
206
255
  this.knexInstance = null;
207
256
  this.isConnected = false;
208
257
  this.queriesLog = [];
209
- this.logger.debug?.(`[Db] Disconnected from database "${this.config.name || this.config.connectionString}"`);
258
+ this.logger.debug?.(formatDbDisconnectMessage(this.config.name, this.config.connectionString));
210
259
  } catch (error) {
211
260
  const errorMsg = this.getErrorMessage(error);
212
261
  this.logger.error?.(`[Db] Error disconnecting: ${errorMsg}`);
213
262
  throw error;
214
263
  }
215
264
  }
216
- /**
217
- * Extract error message from various error types
218
- */
219
265
  getErrorMessage(error) {
220
266
  if (error instanceof AggregateError) {
221
267
  const errors = error.errors || [];
@@ -240,9 +286,11 @@ var Db = class {
240
286
  return `${code} (tried: ${addresses.join(", ")})`;
241
287
  }
242
288
  }
243
- const uniqueMessages = [...new Set(errors.map((e) => {
244
- return e instanceof Error ? e.message : String(e);
245
- }))];
289
+ const uniqueMessages = [
290
+ ...new Set(
291
+ errors.map((e) => e instanceof Error ? e.message : String(e))
292
+ )
293
+ ];
246
294
  if (uniqueMessages.length === 1) {
247
295
  return uniqueMessages[0];
248
296
  }
@@ -251,28 +299,25 @@ var Db = class {
251
299
  return error.message || "Multiple errors occurred";
252
300
  }
253
301
  if (error instanceof Error) {
254
- const errorWithCode = error;
255
- if (errorWithCode.code) {
256
- return `${errorWithCode.code}: ${error.message || String(error)}`;
302
+ const code = error.code;
303
+ if (code) {
304
+ return `${code}: ${error.message || String(error)}`;
257
305
  }
258
306
  return error.message || String(error);
259
307
  }
260
308
  if (typeof error === "string") {
261
309
  return error;
262
310
  }
263
- if (error?.message) {
311
+ if (error && typeof error === "object" && "message" in error) {
264
312
  const msg = String(error.message);
265
- const errorWithCode = error;
266
- if (errorWithCode.code) {
267
- return `${errorWithCode.code}: ${msg}`;
313
+ const code = error.code;
314
+ if (code) {
315
+ return `${code}: ${msg}`;
268
316
  }
269
317
  return msg;
270
318
  }
271
319
  return String(error) || "Unknown error";
272
320
  }
273
- /**
274
- * Test database connection
275
- */
276
321
  async testConnection() {
277
322
  if (!this.knexInstance) {
278
323
  throw new Error("Db: Not connected. Call connect() first.");
@@ -288,9 +333,6 @@ var Db = class {
288
333
  throw new ParamError(`Db: Connection test failed - ${errorMsg}`);
289
334
  }
290
335
  }
291
- /**
292
- * Attach query profiler to log all queries
293
- */
294
336
  attachProfiler() {
295
337
  if (!this.knexInstance) {
296
338
  return;
@@ -300,7 +342,7 @@ var Db = class {
300
342
  this.knexInstance.on("query", (query) => {
301
343
  query.__startTime = process.hrtime();
302
344
  });
303
- this.knexInstance.on("query-response", (response, query) => {
345
+ this.knexInstance.on("query-response", (_response, query) => {
304
346
  const [seconds, nanoseconds] = process.hrtime(query.__startTime);
305
347
  const executionTimeMs = (seconds * 1e3 + nanoseconds / 1e6).toFixed(2);
306
348
  const logEntry = {
@@ -315,15 +357,9 @@ var Db = class {
315
357
  this.logger.error?.(`[Db] Query failed: ${query.sql}`, error);
316
358
  });
317
359
  }
318
- /**
319
- * Get query log (only available if profiling is enabled)
320
- */
321
360
  getQueryLog() {
322
361
  return [...this.queriesLog];
323
362
  }
324
- /**
325
- * Check if a table exists
326
- */
327
363
  async tableExists(tableName) {
328
364
  if (!this.knexInstance) {
329
365
  throw new Error("Db: Not connected. Call connect() first.");
@@ -335,65 +371,87 @@ var Db = class {
335
371
  throw error;
336
372
  }
337
373
  }
338
- /**
339
- * Get the underlying Knex instance (for advanced usage)
340
- */
341
374
  getKnex() {
342
375
  if (!this.knexInstance) {
343
376
  throw new Error("Db: Not connected. Call connect() first.");
344
377
  }
345
378
  return this.knexInstance;
346
379
  }
347
- /**
348
- * Get connection status
349
- */
350
380
  isConnectedToDb() {
351
381
  return this.isConnected && this.knexInstance !== null;
352
382
  }
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
383
  };
361
384
  function capitalizeFirstLetter(str) {
362
385
  return str.charAt(0).toUpperCase() + str.slice(1);
363
386
  }
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
- };
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
+ }
446
+ async function dbConnect(context, config) {
389
447
  try {
390
448
  const db = new Db(config);
391
449
  context.registerCleanup(async () => {
392
450
  await db.disconnect();
393
- context.logger.debug(`[Db] instance "${name || connectionString}" destroyed`);
451
+ context.logger.debug?.(formatDbInstanceMessage("disconnected", config.name));
394
452
  });
395
453
  await db.connect();
396
- context.logger.debug(`[Db] instance "${name || connectionString}" initialized`);
454
+ context.logger.debug?.(formatDbInstanceMessage("initialized", config.name));
397
455
  return db;
398
456
  } catch (error) {
399
457
  if (error instanceof ParamError) {
@@ -403,51 +461,8 @@ async function dbConnect(context, connectionString, name, dbProfile) {
403
461
  throw new ParamError(`[Db] connect error: ${errorMsg}`);
404
462
  }
405
463
  }
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.getAll(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
464
  // Annotate the CommonJS export names for ESM import in node:
447
465
  0 && (module.exports = {
448
- Db,
449
- dbConnect,
450
- dbFindAndConnect,
451
- dbInit
466
+ Db
452
467
  });
453
468
  //# sourceMappingURL=db.cjs.map