@dsmrt/axiom-cli 0.3.1 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @dsmrt/axiom-cli
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b1a56bc: adding debug logging to the cli and config packages
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [b1a56bc]
12
+ - @dsmrt/axiom-config@1.1.0
13
+
14
+ ## 1.0.0
15
+
16
+ ### Major Changes
17
+
18
+ - d767a0e: Making loadConfig return a promise; adding typescript config support and better esm/mjs/mts support; better docs
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies [d767a0e]
23
+ - @dsmrt/axiom-aws-sdk@1.0.0
24
+ - @dsmrt/axiom-config@1.0.0
25
+
3
26
  ## 0.3.1
4
27
 
5
28
  ### Patch Changes
package/dist/bin/axiom.js CHANGED
@@ -28,6 +28,16 @@ var import_yargs = __toESM(require("yargs"));
28
28
 
29
29
  // src/commands/config.ts
30
30
  var import_axiom_config = require("@dsmrt/axiom-config");
31
+
32
+ // src/debug.ts
33
+ var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
34
+ var debug = (message, ...args) => {
35
+ if (isDebugEnabled()) {
36
+ console.error(`[axiom:cli] ${message}`, ...args);
37
+ }
38
+ };
39
+
40
+ // src/commands/config.ts
31
41
  var Config = class {
32
42
  command = "config";
33
43
  describe = "print the config";
@@ -38,9 +48,13 @@ var Config = class {
38
48
  return args;
39
49
  };
40
50
  handler = async (args) => {
41
- console.log(JSON.stringify(await this.loadConfig(args)));
51
+ debug(`Config command handler called with env: ${args.env}`);
52
+ const config = await this.loadConfig(args);
53
+ debug(`Config loaded successfully, outputting as JSON`);
54
+ console.log(JSON.stringify(config));
42
55
  };
43
56
  loadConfig = async (args) => {
57
+ debug(`Loading config with env: ${args.env}`);
44
58
  return (0, import_axiom_config.loadConfig)(args);
45
59
  };
46
60
  };
@@ -59,9 +73,10 @@ var ParamsCommand = class {
59
73
  };
60
74
 
61
75
  // src/commands/params/get.ts
62
- var import_axiom_config2 = require("@dsmrt/axiom-config");
63
- var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
64
76
  var import_client_ssm = require("@aws-sdk/client-ssm");
77
+ var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
78
+ var import_axiom_config2 = require("@dsmrt/axiom-config");
79
+ var import_chalk = __toESM(require("chalk"));
65
80
 
66
81
  // src/aws/credentials-provider.ts
67
82
  var import_credential_providers = require("@aws-sdk/credential-providers");
@@ -69,19 +84,19 @@ var import_client_sts = require("@aws-sdk/client-sts");
69
84
  var import_inquirer = __toESM(require("inquirer"));
70
85
 
71
86
  // src/cache.ts
72
- var import_os = __toESM(require("os"));
73
- var import_fs = __toESM(require("fs"));
74
- var DEFAULT_DIRECTORY = `${import_os.default.homedir()}/.axiom/cache`;
87
+ var import_node_fs = __toESM(require("fs"));
88
+ var import_node_os = __toESM(require("os"));
89
+ var DEFAULT_DIRECTORY = `${import_node_os.default.homedir()}/.axiom/cache`;
75
90
  var cache_default = class {
76
91
  constructor(cacheDir = DEFAULT_DIRECTORY) {
77
92
  this.cacheDir = cacheDir;
78
93
  }
79
94
  get(name) {
80
95
  const file = `${this.cacheDir}/${name}`;
81
- if (!import_fs.default.existsSync(file)) {
96
+ if (!import_node_fs.default.existsSync(file)) {
82
97
  return;
83
98
  }
84
- const buffer = import_fs.default.readFileSync(file);
99
+ const buffer = import_node_fs.default.readFileSync(file);
85
100
  const item = JSON.parse(buffer.toString());
86
101
  if (item.expires === void 0) {
87
102
  return item.data;
@@ -94,16 +109,16 @@ var cache_default = class {
94
109
  return item.data;
95
110
  }
96
111
  delete(name) {
97
- import_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
112
+ import_node_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
98
113
  }
99
114
  set(name, value, expires) {
100
- if (!import_fs.default.existsSync(this.cacheDir)) {
101
- import_fs.default.mkdirSync(this.cacheDir, {
115
+ if (!import_node_fs.default.existsSync(this.cacheDir)) {
116
+ import_node_fs.default.mkdirSync(this.cacheDir, {
102
117
  recursive: true,
103
118
  mode: 448
104
119
  });
105
120
  }
106
- import_fs.default.writeFileSync(
121
+ import_node_fs.default.writeFileSync(
107
122
  `${this.cacheDir}/${name}`,
108
123
  JSON.stringify({
109
124
  expires,
@@ -199,38 +214,31 @@ var awsOptions = () => {
199
214
  };
200
215
  };
201
216
 
202
- // src/commands/params/utils.ts
203
- var buildPath = (config, path) => {
204
- if (path === void 0) {
205
- return config.aws?.baseParameterPath;
206
- }
207
- if (/^\//.test(path)) {
208
- return path;
209
- }
210
- return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
211
- };
212
-
213
217
  // src/commands/params/get.ts
214
- var import_chalk = __toESM(require("chalk"));
215
218
  var GetCommand = class {
216
219
  command = "get [path]";
217
220
  describe = "Get all parameters under the base path";
218
221
  builder = (args) => {
219
- const config = (0, import_axiom_config2.loadConfig)();
220
222
  args.options({ ...commonOptions(), ...awsOptions() });
221
223
  args.positional("path", {
222
224
  type: "string",
223
225
  describe: `OPTIONAL path to parameter. Supports absolute and relative paths.
224
226
  Example:
225
- "/root/myParam" or "service/secret" (which translates to, "${buildPath(
226
- config,
227
- "service/secret"
228
- )})`
227
+ "/root/myParam" or "service/secret"`
229
228
  });
230
229
  return args;
231
230
  };
232
231
  handler = async (args) => {
233
- const config = (0, import_axiom_config2.loadConfig)({ env: args.env });
232
+ debug(
233
+ `Get command handler called with env: ${args.env}, path: ${args.path}`
234
+ );
235
+ const config = await (0, import_axiom_config2.loadConfig)({ env: args.env });
236
+ debug(
237
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
238
+ );
239
+ debug(
240
+ `Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
241
+ );
234
242
  const collection = new import_axiom_aws_sdk.ParameterCollection(
235
243
  config.aws?.baseParameterPath,
236
244
  new import_client_ssm.SSMClient({
@@ -243,11 +251,13 @@ Example:
243
251
  })
244
252
  })
245
253
  );
254
+ debug(`Fetching parameters from SSM...`);
246
255
  const params = await collection.get();
256
+ debug(`Retrieved ${params.size} parameters`);
247
257
  params.forEach((parameter) => {
248
258
  console.log(
249
259
  import_chalk.default.gray(
250
- parameter.Name?.replace(/\/([^/]+)$/, "/" + import_chalk.default.bold.green("$1"))
260
+ parameter.Name?.replace(/\/([^/]+)$/, `/${import_chalk.default.bold.green("$1")}`)
251
261
  ),
252
262
  import_chalk.default.bold.white(parameter.Value)
253
263
  );
@@ -256,22 +266,31 @@ Example:
256
266
  };
257
267
 
258
268
  // src/commands/params/set.ts
259
- var import_axiom_config3 = require("@dsmrt/axiom-config");
260
- var import_inquirer2 = __toESM(require("inquirer"));
261
269
  var import_client_ssm2 = require("@aws-sdk/client-ssm");
270
+ var import_axiom_config3 = require("@dsmrt/axiom-config");
262
271
  var import_chalk2 = __toESM(require("chalk"));
272
+ var import_inquirer2 = __toESM(require("inquirer"));
273
+
274
+ // src/commands/params/utils.ts
275
+ var buildPath = (config, path) => {
276
+ if (path === void 0) {
277
+ return config.aws?.baseParameterPath;
278
+ }
279
+ if (/^\//.test(path)) {
280
+ return path;
281
+ }
282
+ return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
283
+ };
284
+
285
+ // src/commands/params/set.ts
263
286
  var SetCommand = class {
264
287
  command = "set <path> <value>";
265
288
  describe = "Set all parameters under the base path";
266
289
  builder = (args) => {
267
- const config = (0, import_axiom_config3.loadConfig)();
268
290
  args.positional("path", {
269
291
  type: "string",
270
292
  describe: `Path to parameter. Supports absolute and relative paths.
271
- Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
272
- config,
273
- "service/secret"
274
- )})`
293
+ Example: "/root/myParam" or "service/secret"`
275
294
  });
276
295
  args.demandOption("path", "Path is required");
277
296
  args.positional("value", {
@@ -300,53 +319,68 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
300
319
  });
301
320
  };
302
321
  handler = async (args) => {
303
- const config = (0, import_axiom_config3.loadConfig)({ env: args.env });
322
+ debug(
323
+ `Set command handler called with path: ${args.path}, secure: ${args.secure}, overwrite: ${args.overwrite}, force: ${args.force}`
324
+ );
325
+ const config = await (0, import_axiom_config3.loadConfig)({ env: args.env });
326
+ debug(
327
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
328
+ );
329
+ const fullPath = buildPath(config, args.path);
330
+ debug(`Full parameter path: ${fullPath}`);
304
331
  if (args.force !== true) {
332
+ debug(`Prompting user for confirmation...`);
305
333
  const res = await import_inquirer2.default.prompt({
306
334
  type: "confirm",
307
335
  name: "setParam",
308
336
  message: `Are you sure you want to set '${args.path}'?`
309
337
  });
310
338
  if (!res.setParam) {
339
+ debug(`User declined, aborting`);
311
340
  console.log("Doing nothing.");
312
341
  return;
313
342
  }
343
+ debug(`User confirmed`);
344
+ } else {
345
+ debug(`Force flag set, skipping confirmation`);
314
346
  }
347
+ debug(
348
+ `Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
349
+ );
315
350
  const client = new import_client_ssm2.SSMClient({
316
351
  region: config.aws.region,
317
352
  credentials: await CachedCredentialProvider(config.aws)
318
353
  });
354
+ debug(
355
+ `Sending parameter to SSM with type: ${args.secure ? "SecureString" : "String"}`
356
+ );
319
357
  const params = await client.send(
320
358
  new import_client_ssm2.PutParameterCommand({
321
- Name: buildPath(config, args.path),
359
+ Name: fullPath,
322
360
  Value: args.value,
323
361
  Type: args.secure ? import_client_ssm2.ParameterType.SECURE_STRING : import_client_ssm2.ParameterType.STRING,
324
362
  Overwrite: args.overwrite
325
363
  })
326
364
  );
365
+ debug(`Parameter set successfully, version: ${params.Version}`);
327
366
  console.log(import_chalk2.default.green("Version: "), import_chalk2.default.white.bold(params.Version));
328
367
  };
329
368
  };
330
369
 
331
370
  // src/commands/params/delete.ts
371
+ var import_client_ssm3 = require("@aws-sdk/client-ssm");
332
372
  var import_axiom_config4 = require("@dsmrt/axiom-config");
333
373
  var import_inquirer3 = __toESM(require("inquirer"));
334
- var import_client_ssm3 = require("@aws-sdk/client-ssm");
335
374
  var log = console.log;
336
375
  var DeleteCommand = class {
337
376
  command = "delete <path>";
338
377
  describe = "Delete SSM parameters";
339
378
  client;
340
379
  builder = (args) => {
341
- const config = (0, import_axiom_config4.loadConfig)();
342
380
  args.positional("path", {
343
381
  type: "string",
344
382
  describe: `Path to parameter. Supports absolute and relative paths.
345
- Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
346
- config,
347
- "service/secret"
348
- )})`,
349
- default: config.aws?.baseParameterPath,
383
+ Example: "/root/myParam" or "service/secret"`,
350
384
  demandOption: true
351
385
  }).demandOption("path", "Path is required");
352
386
  args.option("force", {
@@ -358,33 +392,51 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
358
392
  return args;
359
393
  };
360
394
  handler = async (args) => {
361
- const config = (0, import_axiom_config4.loadConfig)({ env: args.env });
395
+ debug(
396
+ `Delete command handler called with path: ${args.path}, force: ${args.force}`
397
+ );
398
+ const config = await (0, import_axiom_config4.loadConfig)({ env: args.env });
399
+ debug(
400
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
401
+ );
362
402
  const path = buildPath(args, args.path);
403
+ debug(`Full parameter path: ${path}`);
404
+ debug(
405
+ `Creating SSM client with region: ${config.aws?.region}, profile: ${config.aws?.profile}`
406
+ );
363
407
  const client = new import_client_ssm3.SSMClient({
364
408
  region: config.aws?.region,
365
409
  credentials: await CachedCredentialProvider(config.aws)
366
410
  });
367
411
  if (path === args.aws.baseParameterPath) {
412
+ debug(`Delete blocked: path matches base parameter path`);
368
413
  throw new Error(
369
414
  `Deleting the path (path: ${path}) that matches the base path (awsSsmParameterPath: ${args.awsSsmParameterPath}) is prohibited.`
370
415
  );
371
416
  }
372
417
  if (args.force !== true) {
418
+ debug(`Prompting user for confirmation...`);
373
419
  const res = await import_inquirer3.default.prompt({
374
420
  type: "confirm",
375
421
  name: "delete",
376
422
  message: `Are you sure you want to delete '${path}'?`
377
423
  });
378
424
  if (!res.delete) {
425
+ debug(`User declined, aborting`);
379
426
  log("Doing nothing.");
380
427
  return;
381
428
  }
429
+ debug(`User confirmed`);
430
+ } else {
431
+ debug(`Force flag set, skipping confirmation`);
382
432
  }
433
+ debug(`Sending delete command to SSM for: ${path}`);
383
434
  await client.send(
384
435
  new import_client_ssm3.DeleteParameterCommand({
385
436
  Name: path
386
437
  })
387
438
  );
439
+ debug(`Parameter deleted successfully`);
388
440
  log("\u{1F44D}");
389
441
  };
390
442
  };
@@ -393,6 +445,16 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
393
445
  (0, import_yargs.default)(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
394
446
  alias: "c",
395
447
  string: true
448
+ }).option("debug", {
449
+ alias: "d",
450
+ type: "boolean",
451
+ description: "Enable debug output",
452
+ default: false,
453
+ global: true
454
+ }).middleware((argv) => {
455
+ if (argv.debug) {
456
+ process.env.AXIOM_DEBUG = "true";
457
+ }
396
458
  }).command(new Config()).command(new ParamsCommand()).strict().usage(
397
459
  `
398
460
  Axiom - an AWS focused config cli
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-QT654PKF.mjs";
2
+ import "../chunk-CORLQJO7.mjs";
@@ -3,6 +3,16 @@ import yargs from "yargs";
3
3
 
4
4
  // src/commands/config.ts
5
5
  import { loadConfig } from "@dsmrt/axiom-config";
6
+
7
+ // src/debug.ts
8
+ var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
9
+ var debug = (message, ...args) => {
10
+ if (isDebugEnabled()) {
11
+ console.error(`[axiom:cli] ${message}`, ...args);
12
+ }
13
+ };
14
+
15
+ // src/commands/config.ts
6
16
  var Config = class {
7
17
  command = "config";
8
18
  describe = "print the config";
@@ -13,9 +23,13 @@ var Config = class {
13
23
  return args;
14
24
  };
15
25
  handler = async (args) => {
16
- console.log(JSON.stringify(await this.loadConfig(args)));
26
+ debug(`Config command handler called with env: ${args.env}`);
27
+ const config = await this.loadConfig(args);
28
+ debug(`Config loaded successfully, outputting as JSON`);
29
+ console.log(JSON.stringify(config));
17
30
  };
18
31
  loadConfig = async (args) => {
32
+ debug(`Loading config with env: ${args.env}`);
19
33
  return loadConfig(args);
20
34
  };
21
35
  };
@@ -34,9 +48,10 @@ var ParamsCommand = class {
34
48
  };
35
49
 
36
50
  // src/commands/params/get.ts
37
- import { loadConfig as loadConfig2 } from "@dsmrt/axiom-config";
38
- import { ParameterCollection } from "@dsmrt/axiom-aws-sdk";
39
51
  import { SSMClient } from "@aws-sdk/client-ssm";
52
+ import { ParameterCollection } from "@dsmrt/axiom-aws-sdk";
53
+ import { loadConfig as loadConfig2 } from "@dsmrt/axiom-config";
54
+ import chalk from "chalk";
40
55
 
41
56
  // src/aws/credentials-provider.ts
42
57
  import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
@@ -47,8 +62,8 @@ import {
47
62
  import inquirer from "inquirer";
48
63
 
49
64
  // src/cache.ts
50
- import os from "os";
51
65
  import fs from "fs";
66
+ import os from "os";
52
67
  var DEFAULT_DIRECTORY = `${os.homedir()}/.axiom/cache`;
53
68
  var cache_default = class {
54
69
  constructor(cacheDir = DEFAULT_DIRECTORY) {
@@ -177,38 +192,31 @@ var awsOptions = () => {
177
192
  };
178
193
  };
179
194
 
180
- // src/commands/params/utils.ts
181
- var buildPath = (config, path) => {
182
- if (path === void 0) {
183
- return config.aws?.baseParameterPath;
184
- }
185
- if (/^\//.test(path)) {
186
- return path;
187
- }
188
- return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
189
- };
190
-
191
195
  // src/commands/params/get.ts
192
- import chalk from "chalk";
193
196
  var GetCommand = class {
194
197
  command = "get [path]";
195
198
  describe = "Get all parameters under the base path";
196
199
  builder = (args) => {
197
- const config = loadConfig2();
198
200
  args.options({ ...commonOptions(), ...awsOptions() });
199
201
  args.positional("path", {
200
202
  type: "string",
201
203
  describe: `OPTIONAL path to parameter. Supports absolute and relative paths.
202
204
  Example:
203
- "/root/myParam" or "service/secret" (which translates to, "${buildPath(
204
- config,
205
- "service/secret"
206
- )})`
205
+ "/root/myParam" or "service/secret"`
207
206
  });
208
207
  return args;
209
208
  };
210
209
  handler = async (args) => {
211
- const config = loadConfig2({ env: args.env });
210
+ debug(
211
+ `Get command handler called with env: ${args.env}, path: ${args.path}`
212
+ );
213
+ const config = await loadConfig2({ env: args.env });
214
+ debug(
215
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
216
+ );
217
+ debug(
218
+ `Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
219
+ );
212
220
  const collection = new ParameterCollection(
213
221
  config.aws?.baseParameterPath,
214
222
  new SSMClient({
@@ -221,11 +229,13 @@ Example:
221
229
  })
222
230
  })
223
231
  );
232
+ debug(`Fetching parameters from SSM...`);
224
233
  const params = await collection.get();
234
+ debug(`Retrieved ${params.size} parameters`);
225
235
  params.forEach((parameter) => {
226
236
  console.log(
227
237
  chalk.gray(
228
- parameter.Name?.replace(/\/([^/]+)$/, "/" + chalk.bold.green("$1"))
238
+ parameter.Name?.replace(/\/([^/]+)$/, `/${chalk.bold.green("$1")}`)
229
239
  ),
230
240
  chalk.bold.white(parameter.Value)
231
241
  );
@@ -234,26 +244,35 @@ Example:
234
244
  };
235
245
 
236
246
  // src/commands/params/set.ts
237
- import { loadConfig as loadConfig3 } from "@dsmrt/axiom-config";
238
- import inquirer2 from "inquirer";
239
247
  import {
240
- SSMClient as SSMClient2,
248
+ ParameterType,
241
249
  PutParameterCommand,
242
- ParameterType
250
+ SSMClient as SSMClient2
243
251
  } from "@aws-sdk/client-ssm";
252
+ import { loadConfig as loadConfig3 } from "@dsmrt/axiom-config";
244
253
  import chalk2 from "chalk";
254
+ import inquirer2 from "inquirer";
255
+
256
+ // src/commands/params/utils.ts
257
+ var buildPath = (config, path) => {
258
+ if (path === void 0) {
259
+ return config.aws?.baseParameterPath;
260
+ }
261
+ if (/^\//.test(path)) {
262
+ return path;
263
+ }
264
+ return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
265
+ };
266
+
267
+ // src/commands/params/set.ts
245
268
  var SetCommand = class {
246
269
  command = "set <path> <value>";
247
270
  describe = "Set all parameters under the base path";
248
271
  builder = (args) => {
249
- const config = loadConfig3();
250
272
  args.positional("path", {
251
273
  type: "string",
252
274
  describe: `Path to parameter. Supports absolute and relative paths.
253
- Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
254
- config,
255
- "service/secret"
256
- )})`
275
+ Example: "/root/myParam" or "service/secret"`
257
276
  });
258
277
  args.demandOption("path", "Path is required");
259
278
  args.positional("value", {
@@ -282,53 +301,68 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
282
301
  });
283
302
  };
284
303
  handler = async (args) => {
285
- const config = loadConfig3({ env: args.env });
304
+ debug(
305
+ `Set command handler called with path: ${args.path}, secure: ${args.secure}, overwrite: ${args.overwrite}, force: ${args.force}`
306
+ );
307
+ const config = await loadConfig3({ env: args.env });
308
+ debug(
309
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
310
+ );
311
+ const fullPath = buildPath(config, args.path);
312
+ debug(`Full parameter path: ${fullPath}`);
286
313
  if (args.force !== true) {
314
+ debug(`Prompting user for confirmation...`);
287
315
  const res = await inquirer2.prompt({
288
316
  type: "confirm",
289
317
  name: "setParam",
290
318
  message: `Are you sure you want to set '${args.path}'?`
291
319
  });
292
320
  if (!res.setParam) {
321
+ debug(`User declined, aborting`);
293
322
  console.log("Doing nothing.");
294
323
  return;
295
324
  }
325
+ debug(`User confirmed`);
326
+ } else {
327
+ debug(`Force flag set, skipping confirmation`);
296
328
  }
329
+ debug(
330
+ `Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
331
+ );
297
332
  const client = new SSMClient2({
298
333
  region: config.aws.region,
299
334
  credentials: await CachedCredentialProvider(config.aws)
300
335
  });
336
+ debug(
337
+ `Sending parameter to SSM with type: ${args.secure ? "SecureString" : "String"}`
338
+ );
301
339
  const params = await client.send(
302
340
  new PutParameterCommand({
303
- Name: buildPath(config, args.path),
341
+ Name: fullPath,
304
342
  Value: args.value,
305
343
  Type: args.secure ? ParameterType.SECURE_STRING : ParameterType.STRING,
306
344
  Overwrite: args.overwrite
307
345
  })
308
346
  );
347
+ debug(`Parameter set successfully, version: ${params.Version}`);
309
348
  console.log(chalk2.green("Version: "), chalk2.white.bold(params.Version));
310
349
  };
311
350
  };
312
351
 
313
352
  // src/commands/params/delete.ts
353
+ import { DeleteParameterCommand, SSMClient as SSMClient3 } from "@aws-sdk/client-ssm";
314
354
  import { loadConfig as loadConfig4 } from "@dsmrt/axiom-config";
315
355
  import inquirer3 from "inquirer";
316
- import { SSMClient as SSMClient3, DeleteParameterCommand } from "@aws-sdk/client-ssm";
317
356
  var log = console.log;
318
357
  var DeleteCommand = class {
319
358
  command = "delete <path>";
320
359
  describe = "Delete SSM parameters";
321
360
  client;
322
361
  builder = (args) => {
323
- const config = loadConfig4();
324
362
  args.positional("path", {
325
363
  type: "string",
326
364
  describe: `Path to parameter. Supports absolute and relative paths.
327
- Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
328
- config,
329
- "service/secret"
330
- )})`,
331
- default: config.aws?.baseParameterPath,
365
+ Example: "/root/myParam" or "service/secret"`,
332
366
  demandOption: true
333
367
  }).demandOption("path", "Path is required");
334
368
  args.option("force", {
@@ -340,33 +374,51 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
340
374
  return args;
341
375
  };
342
376
  handler = async (args) => {
343
- const config = loadConfig4({ env: args.env });
377
+ debug(
378
+ `Delete command handler called with path: ${args.path}, force: ${args.force}`
379
+ );
380
+ const config = await loadConfig4({ env: args.env });
381
+ debug(
382
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
383
+ );
344
384
  const path = buildPath(args, args.path);
385
+ debug(`Full parameter path: ${path}`);
386
+ debug(
387
+ `Creating SSM client with region: ${config.aws?.region}, profile: ${config.aws?.profile}`
388
+ );
345
389
  const client = new SSMClient3({
346
390
  region: config.aws?.region,
347
391
  credentials: await CachedCredentialProvider(config.aws)
348
392
  });
349
393
  if (path === args.aws.baseParameterPath) {
394
+ debug(`Delete blocked: path matches base parameter path`);
350
395
  throw new Error(
351
396
  `Deleting the path (path: ${path}) that matches the base path (awsSsmParameterPath: ${args.awsSsmParameterPath}) is prohibited.`
352
397
  );
353
398
  }
354
399
  if (args.force !== true) {
400
+ debug(`Prompting user for confirmation...`);
355
401
  const res = await inquirer3.prompt({
356
402
  type: "confirm",
357
403
  name: "delete",
358
404
  message: `Are you sure you want to delete '${path}'?`
359
405
  });
360
406
  if (!res.delete) {
407
+ debug(`User declined, aborting`);
361
408
  log("Doing nothing.");
362
409
  return;
363
410
  }
411
+ debug(`User confirmed`);
412
+ } else {
413
+ debug(`Force flag set, skipping confirmation`);
364
414
  }
415
+ debug(`Sending delete command to SSM for: ${path}`);
365
416
  await client.send(
366
417
  new DeleteParameterCommand({
367
418
  Name: path
368
419
  })
369
420
  );
421
+ debug(`Parameter deleted successfully`);
370
422
  log("\u{1F44D}");
371
423
  };
372
424
  };
@@ -375,6 +427,16 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
375
427
  yargs(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
376
428
  alias: "c",
377
429
  string: true
430
+ }).option("debug", {
431
+ alias: "d",
432
+ type: "boolean",
433
+ description: "Enable debug output",
434
+ default: false,
435
+ global: true
436
+ }).middleware((argv) => {
437
+ if (argv.debug) {
438
+ process.env.AXIOM_DEBUG = "true";
439
+ }
378
440
  }).command(new Config()).command(new ParamsCommand()).strict().usage(
379
441
  `
380
442
  Axiom - an AWS focused config cli
@@ -385,10 +447,10 @@ USAGE:
385
447
  ).demandCommand(1, "").alias("h", "help").argv;
386
448
 
387
449
  export {
388
- commonOptions,
389
- awsOptions,
390
450
  Config,
391
451
  ParamsCommand,
452
+ commonOptions,
453
+ awsOptions,
392
454
  GetCommand,
393
455
  SetCommand,
394
456
  DeleteCommand
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { Options as Options$1, CommandModule, CommandBuilder, ArgumentsCamelCase, Argv } from 'yargs';
2
1
  import * as _dsmrt_axiom_config from '@dsmrt/axiom-config';
3
2
  import { AwsConfigs, Config as Config$1 } from '@dsmrt/axiom-config';
3
+ import { CommandModule, CommandBuilder, ArgumentsCamelCase, Argv, Options as Options$1 } from 'yargs';
4
4
  import { SSMClient } from '@aws-sdk/client-ssm';
5
5
 
6
6
  interface Item {
@@ -8,13 +8,6 @@ interface Item {
8
8
  data: unknown;
9
9
  }
10
10
 
11
- declare const commonOptions: () => {
12
- [key: string]: Options$1;
13
- };
14
- declare const awsOptions: () => {
15
- [key: string]: Options$1;
16
- };
17
-
18
11
  interface ConfigOptions {
19
12
  env: string;
20
13
  }
@@ -26,8 +19,7 @@ declare class Config<U extends ConfigOptions> implements CommandModule<object, U
26
19
  loadConfig: (args: ConfigOptions) => Promise<_dsmrt_axiom_config.ConfigContainer & object>;
27
20
  }
28
21
 
29
- interface Options {
30
- }
22
+ type Options = object;
31
23
  declare class ParamsCommand<U extends Options> implements CommandModule<object, U> {
32
24
  command: string;
33
25
  describe: string;
@@ -75,4 +67,11 @@ declare class DeleteCommand<U extends config> implements CommandModule<object, U
75
67
  handler: (args: ArgumentsCamelCase<U>) => Promise<void>;
76
68
  }
77
69
 
70
+ declare const commonOptions: () => {
71
+ [key: string]: Options$1;
72
+ };
73
+ declare const awsOptions: () => {
74
+ [key: string]: Options$1;
75
+ };
76
+
78
77
  export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Options as Options$1, CommandModule, CommandBuilder, ArgumentsCamelCase, Argv } from 'yargs';
2
1
  import * as _dsmrt_axiom_config from '@dsmrt/axiom-config';
3
2
  import { AwsConfigs, Config as Config$1 } from '@dsmrt/axiom-config';
3
+ import { CommandModule, CommandBuilder, ArgumentsCamelCase, Argv, Options as Options$1 } from 'yargs';
4
4
  import { SSMClient } from '@aws-sdk/client-ssm';
5
5
 
6
6
  interface Item {
@@ -8,13 +8,6 @@ interface Item {
8
8
  data: unknown;
9
9
  }
10
10
 
11
- declare const commonOptions: () => {
12
- [key: string]: Options$1;
13
- };
14
- declare const awsOptions: () => {
15
- [key: string]: Options$1;
16
- };
17
-
18
11
  interface ConfigOptions {
19
12
  env: string;
20
13
  }
@@ -26,8 +19,7 @@ declare class Config<U extends ConfigOptions> implements CommandModule<object, U
26
19
  loadConfig: (args: ConfigOptions) => Promise<_dsmrt_axiom_config.ConfigContainer & object>;
27
20
  }
28
21
 
29
- interface Options {
30
- }
22
+ type Options = object;
31
23
  declare class ParamsCommand<U extends Options> implements CommandModule<object, U> {
32
24
  command: string;
33
25
  describe: string;
@@ -75,4 +67,11 @@ declare class DeleteCommand<U extends config> implements CommandModule<object, U
75
67
  handler: (args: ArgumentsCamelCase<U>) => Promise<void>;
76
68
  }
77
69
 
70
+ declare const commonOptions: () => {
71
+ [key: string]: Options$1;
72
+ };
73
+ declare const awsOptions: () => {
74
+ [key: string]: Options$1;
75
+ };
76
+
78
77
  export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
package/dist/index.js CHANGED
@@ -40,86 +40,21 @@ __export(index_exports, {
40
40
  });
41
41
  module.exports = __toCommonJS(index_exports);
42
42
 
43
- // src/cache.ts
44
- var import_os = __toESM(require("os"));
45
- var import_fs = __toESM(require("fs"));
46
- var DEFAULT_DIRECTORY = `${import_os.default.homedir()}/.axiom/cache`;
47
- var cache_default = class {
48
- constructor(cacheDir = DEFAULT_DIRECTORY) {
49
- this.cacheDir = cacheDir;
50
- }
51
- get(name) {
52
- const file = `${this.cacheDir}/${name}`;
53
- if (!import_fs.default.existsSync(file)) {
54
- return;
55
- }
56
- const buffer = import_fs.default.readFileSync(file);
57
- const item = JSON.parse(buffer.toString());
58
- if (item.expires === void 0) {
59
- return item.data;
60
- }
61
- item.expires = new Date(item.expires);
62
- if (item.expires < /* @__PURE__ */ new Date()) {
63
- this.delete(name);
64
- return;
65
- }
66
- return item.data;
67
- }
68
- delete(name) {
69
- import_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
70
- }
71
- set(name, value, expires) {
72
- if (!import_fs.default.existsSync(this.cacheDir)) {
73
- import_fs.default.mkdirSync(this.cacheDir, {
74
- recursive: true,
75
- mode: 448
76
- });
77
- }
78
- import_fs.default.writeFileSync(
79
- `${this.cacheDir}/${name}`,
80
- JSON.stringify({
81
- expires,
82
- data: value
83
- }),
84
- {
85
- mode: 384
86
- }
87
- );
88
- }
89
- };
43
+ // src/bin/axiom.ts
44
+ var import_yargs = __toESM(require("yargs"));
90
45
 
91
- // src/options.ts
92
- var commonOptions = () => {
93
- return {
94
- env: {
95
- string: true,
96
- desc: "Environment name like, prod, staging, dev, etc."
97
- }
98
- };
99
- };
100
- var awsOptions = () => {
101
- return {
102
- account: {
103
- string: true,
104
- desc: "AWS Account number like, 1243944546"
105
- },
106
- region: {
107
- string: true,
108
- desc: "AWS region like, us-east-1"
109
- },
110
- profile: {
111
- string: true,
112
- desc: "AWS configured profile"
113
- },
114
- baseParameterPath: {
115
- string: true,
116
- desc: "SSM parameter path base where configs like secrets and infrastucture managed items are set"
117
- }
118
- };
46
+ // src/commands/config.ts
47
+ var import_axiom_config = require("@dsmrt/axiom-config");
48
+
49
+ // src/debug.ts
50
+ var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
51
+ var debug = (message, ...args) => {
52
+ if (isDebugEnabled()) {
53
+ console.error(`[axiom:cli] ${message}`, ...args);
54
+ }
119
55
  };
120
56
 
121
57
  // src/commands/config.ts
122
- var import_axiom_config = require("@dsmrt/axiom-config");
123
58
  var Config = class {
124
59
  command = "config";
125
60
  describe = "print the config";
@@ -130,9 +65,13 @@ var Config = class {
130
65
  return args;
131
66
  };
132
67
  handler = async (args) => {
133
- console.log(JSON.stringify(await this.loadConfig(args)));
68
+ debug(`Config command handler called with env: ${args.env}`);
69
+ const config = await this.loadConfig(args);
70
+ debug(`Config loaded successfully, outputting as JSON`);
71
+ console.log(JSON.stringify(config));
134
72
  };
135
73
  loadConfig = async (args) => {
74
+ debug(`Loading config with env: ${args.env}`);
136
75
  return (0, import_axiom_config.loadConfig)(args);
137
76
  };
138
77
  };
@@ -151,14 +90,65 @@ var ParamsCommand = class {
151
90
  };
152
91
 
153
92
  // src/commands/params/get.ts
154
- var import_axiom_config2 = require("@dsmrt/axiom-config");
155
- var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
156
93
  var import_client_ssm = require("@aws-sdk/client-ssm");
94
+ var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
95
+ var import_axiom_config2 = require("@dsmrt/axiom-config");
96
+ var import_chalk = __toESM(require("chalk"));
157
97
 
158
98
  // src/aws/credentials-provider.ts
159
99
  var import_credential_providers = require("@aws-sdk/credential-providers");
160
100
  var import_client_sts = require("@aws-sdk/client-sts");
161
101
  var import_inquirer = __toESM(require("inquirer"));
102
+
103
+ // src/cache.ts
104
+ var import_node_fs = __toESM(require("fs"));
105
+ var import_node_os = __toESM(require("os"));
106
+ var DEFAULT_DIRECTORY = `${import_node_os.default.homedir()}/.axiom/cache`;
107
+ var cache_default = class {
108
+ constructor(cacheDir = DEFAULT_DIRECTORY) {
109
+ this.cacheDir = cacheDir;
110
+ }
111
+ get(name) {
112
+ const file = `${this.cacheDir}/${name}`;
113
+ if (!import_node_fs.default.existsSync(file)) {
114
+ return;
115
+ }
116
+ const buffer = import_node_fs.default.readFileSync(file);
117
+ const item = JSON.parse(buffer.toString());
118
+ if (item.expires === void 0) {
119
+ return item.data;
120
+ }
121
+ item.expires = new Date(item.expires);
122
+ if (item.expires < /* @__PURE__ */ new Date()) {
123
+ this.delete(name);
124
+ return;
125
+ }
126
+ return item.data;
127
+ }
128
+ delete(name) {
129
+ import_node_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
130
+ }
131
+ set(name, value, expires) {
132
+ if (!import_node_fs.default.existsSync(this.cacheDir)) {
133
+ import_node_fs.default.mkdirSync(this.cacheDir, {
134
+ recursive: true,
135
+ mode: 448
136
+ });
137
+ }
138
+ import_node_fs.default.writeFileSync(
139
+ `${this.cacheDir}/${name}`,
140
+ JSON.stringify({
141
+ expires,
142
+ data: value
143
+ }),
144
+ {
145
+ mode: 384
146
+ }
147
+ );
148
+ }
149
+ };
150
+
151
+ // src/aws/credentials-provider.ts
162
152
  var CACHE_KEY_PREFIX = "axiom#aws-credentials";
163
153
  var cache = new cache_default();
164
154
  var returnCredentialsFromAssumerole = (creds) => {
@@ -211,38 +201,61 @@ var CachedCredentialProvider = (config) => {
211
201
  return CachedCredentialViaProfileAndRegion(config.profile, config.region);
212
202
  };
213
203
 
214
- // src/commands/params/utils.ts
215
- var buildPath = (config, path) => {
216
- if (path === void 0) {
217
- return config.aws?.baseParameterPath;
218
- }
219
- if (/^\//.test(path)) {
220
- return path;
221
- }
222
- return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
204
+ // src/options.ts
205
+ var commonOptions = () => {
206
+ return {
207
+ env: {
208
+ string: true,
209
+ desc: "Environment name like, prod, staging, dev, etc."
210
+ }
211
+ };
212
+ };
213
+ var awsOptions = () => {
214
+ return {
215
+ account: {
216
+ string: true,
217
+ desc: "AWS Account number like, 1243944546"
218
+ },
219
+ region: {
220
+ string: true,
221
+ desc: "AWS region like, us-east-1"
222
+ },
223
+ profile: {
224
+ string: true,
225
+ desc: "AWS configured profile"
226
+ },
227
+ baseParameterPath: {
228
+ string: true,
229
+ desc: "SSM parameter path base where configs like secrets and infrastucture managed items are set"
230
+ }
231
+ };
223
232
  };
224
233
 
225
234
  // src/commands/params/get.ts
226
- var import_chalk = __toESM(require("chalk"));
227
235
  var GetCommand = class {
228
236
  command = "get [path]";
229
237
  describe = "Get all parameters under the base path";
230
238
  builder = (args) => {
231
- const config = (0, import_axiom_config2.loadConfig)();
232
239
  args.options({ ...commonOptions(), ...awsOptions() });
233
240
  args.positional("path", {
234
241
  type: "string",
235
242
  describe: `OPTIONAL path to parameter. Supports absolute and relative paths.
236
243
  Example:
237
- "/root/myParam" or "service/secret" (which translates to, "${buildPath(
238
- config,
239
- "service/secret"
240
- )})`
244
+ "/root/myParam" or "service/secret"`
241
245
  });
242
246
  return args;
243
247
  };
244
248
  handler = async (args) => {
245
- const config = (0, import_axiom_config2.loadConfig)({ env: args.env });
249
+ debug(
250
+ `Get command handler called with env: ${args.env}, path: ${args.path}`
251
+ );
252
+ const config = await (0, import_axiom_config2.loadConfig)({ env: args.env });
253
+ debug(
254
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
255
+ );
256
+ debug(
257
+ `Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
258
+ );
246
259
  const collection = new import_axiom_aws_sdk.ParameterCollection(
247
260
  config.aws?.baseParameterPath,
248
261
  new import_client_ssm.SSMClient({
@@ -255,11 +268,13 @@ Example:
255
268
  })
256
269
  })
257
270
  );
271
+ debug(`Fetching parameters from SSM...`);
258
272
  const params = await collection.get();
273
+ debug(`Retrieved ${params.size} parameters`);
259
274
  params.forEach((parameter) => {
260
275
  console.log(
261
276
  import_chalk.default.gray(
262
- parameter.Name?.replace(/\/([^/]+)$/, "/" + import_chalk.default.bold.green("$1"))
277
+ parameter.Name?.replace(/\/([^/]+)$/, `/${import_chalk.default.bold.green("$1")}`)
263
278
  ),
264
279
  import_chalk.default.bold.white(parameter.Value)
265
280
  );
@@ -268,22 +283,31 @@ Example:
268
283
  };
269
284
 
270
285
  // src/commands/params/set.ts
271
- var import_axiom_config3 = require("@dsmrt/axiom-config");
272
- var import_inquirer2 = __toESM(require("inquirer"));
273
286
  var import_client_ssm2 = require("@aws-sdk/client-ssm");
287
+ var import_axiom_config3 = require("@dsmrt/axiom-config");
274
288
  var import_chalk2 = __toESM(require("chalk"));
289
+ var import_inquirer2 = __toESM(require("inquirer"));
290
+
291
+ // src/commands/params/utils.ts
292
+ var buildPath = (config, path) => {
293
+ if (path === void 0) {
294
+ return config.aws?.baseParameterPath;
295
+ }
296
+ if (/^\//.test(path)) {
297
+ return path;
298
+ }
299
+ return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
300
+ };
301
+
302
+ // src/commands/params/set.ts
275
303
  var SetCommand = class {
276
304
  command = "set <path> <value>";
277
305
  describe = "Set all parameters under the base path";
278
306
  builder = (args) => {
279
- const config = (0, import_axiom_config3.loadConfig)();
280
307
  args.positional("path", {
281
308
  type: "string",
282
309
  describe: `Path to parameter. Supports absolute and relative paths.
283
- Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
284
- config,
285
- "service/secret"
286
- )})`
310
+ Example: "/root/myParam" or "service/secret"`
287
311
  });
288
312
  args.demandOption("path", "Path is required");
289
313
  args.positional("value", {
@@ -312,53 +336,68 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
312
336
  });
313
337
  };
314
338
  handler = async (args) => {
315
- const config = (0, import_axiom_config3.loadConfig)({ env: args.env });
339
+ debug(
340
+ `Set command handler called with path: ${args.path}, secure: ${args.secure}, overwrite: ${args.overwrite}, force: ${args.force}`
341
+ );
342
+ const config = await (0, import_axiom_config3.loadConfig)({ env: args.env });
343
+ debug(
344
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
345
+ );
346
+ const fullPath = buildPath(config, args.path);
347
+ debug(`Full parameter path: ${fullPath}`);
316
348
  if (args.force !== true) {
349
+ debug(`Prompting user for confirmation...`);
317
350
  const res = await import_inquirer2.default.prompt({
318
351
  type: "confirm",
319
352
  name: "setParam",
320
353
  message: `Are you sure you want to set '${args.path}'?`
321
354
  });
322
355
  if (!res.setParam) {
356
+ debug(`User declined, aborting`);
323
357
  console.log("Doing nothing.");
324
358
  return;
325
359
  }
360
+ debug(`User confirmed`);
361
+ } else {
362
+ debug(`Force flag set, skipping confirmation`);
326
363
  }
364
+ debug(
365
+ `Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
366
+ );
327
367
  const client = new import_client_ssm2.SSMClient({
328
368
  region: config.aws.region,
329
369
  credentials: await CachedCredentialProvider(config.aws)
330
370
  });
371
+ debug(
372
+ `Sending parameter to SSM with type: ${args.secure ? "SecureString" : "String"}`
373
+ );
331
374
  const params = await client.send(
332
375
  new import_client_ssm2.PutParameterCommand({
333
- Name: buildPath(config, args.path),
376
+ Name: fullPath,
334
377
  Value: args.value,
335
378
  Type: args.secure ? import_client_ssm2.ParameterType.SECURE_STRING : import_client_ssm2.ParameterType.STRING,
336
379
  Overwrite: args.overwrite
337
380
  })
338
381
  );
382
+ debug(`Parameter set successfully, version: ${params.Version}`);
339
383
  console.log(import_chalk2.default.green("Version: "), import_chalk2.default.white.bold(params.Version));
340
384
  };
341
385
  };
342
386
 
343
387
  // src/commands/params/delete.ts
388
+ var import_client_ssm3 = require("@aws-sdk/client-ssm");
344
389
  var import_axiom_config4 = require("@dsmrt/axiom-config");
345
390
  var import_inquirer3 = __toESM(require("inquirer"));
346
- var import_client_ssm3 = require("@aws-sdk/client-ssm");
347
391
  var log = console.log;
348
392
  var DeleteCommand = class {
349
393
  command = "delete <path>";
350
394
  describe = "Delete SSM parameters";
351
395
  client;
352
396
  builder = (args) => {
353
- const config = (0, import_axiom_config4.loadConfig)();
354
397
  args.positional("path", {
355
398
  type: "string",
356
399
  describe: `Path to parameter. Supports absolute and relative paths.
357
- Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
358
- config,
359
- "service/secret"
360
- )})`,
361
- default: config.aws?.baseParameterPath,
400
+ Example: "/root/myParam" or "service/secret"`,
362
401
  demandOption: true
363
402
  }).demandOption("path", "Path is required");
364
403
  args.option("force", {
@@ -370,42 +409,69 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
370
409
  return args;
371
410
  };
372
411
  handler = async (args) => {
373
- const config = (0, import_axiom_config4.loadConfig)({ env: args.env });
412
+ debug(
413
+ `Delete command handler called with path: ${args.path}, force: ${args.force}`
414
+ );
415
+ const config = await (0, import_axiom_config4.loadConfig)({ env: args.env });
416
+ debug(
417
+ `Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
418
+ );
374
419
  const path = buildPath(args, args.path);
420
+ debug(`Full parameter path: ${path}`);
421
+ debug(
422
+ `Creating SSM client with region: ${config.aws?.region}, profile: ${config.aws?.profile}`
423
+ );
375
424
  const client = new import_client_ssm3.SSMClient({
376
425
  region: config.aws?.region,
377
426
  credentials: await CachedCredentialProvider(config.aws)
378
427
  });
379
428
  if (path === args.aws.baseParameterPath) {
429
+ debug(`Delete blocked: path matches base parameter path`);
380
430
  throw new Error(
381
431
  `Deleting the path (path: ${path}) that matches the base path (awsSsmParameterPath: ${args.awsSsmParameterPath}) is prohibited.`
382
432
  );
383
433
  }
384
434
  if (args.force !== true) {
435
+ debug(`Prompting user for confirmation...`);
385
436
  const res = await import_inquirer3.default.prompt({
386
437
  type: "confirm",
387
438
  name: "delete",
388
439
  message: `Are you sure you want to delete '${path}'?`
389
440
  });
390
441
  if (!res.delete) {
442
+ debug(`User declined, aborting`);
391
443
  log("Doing nothing.");
392
444
  return;
393
445
  }
446
+ debug(`User confirmed`);
447
+ } else {
448
+ debug(`Force flag set, skipping confirmation`);
394
449
  }
450
+ debug(`Sending delete command to SSM for: ${path}`);
395
451
  await client.send(
396
452
  new import_client_ssm3.DeleteParameterCommand({
397
453
  Name: path
398
454
  })
399
455
  );
456
+ debug(`Parameter deleted successfully`);
400
457
  log("\u{1F44D}");
401
458
  };
402
459
  };
403
460
 
404
461
  // src/bin/axiom.ts
405
- var import_yargs = __toESM(require("yargs"));
406
462
  (0, import_yargs.default)(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
407
463
  alias: "c",
408
464
  string: true
465
+ }).option("debug", {
466
+ alias: "d",
467
+ type: "boolean",
468
+ description: "Enable debug output",
469
+ default: false,
470
+ global: true
471
+ }).middleware((argv) => {
472
+ if (argv.debug) {
473
+ process.env.AXIOM_DEBUG = "true";
474
+ }
409
475
  }).command(new Config()).command(new ParamsCommand()).strict().usage(
410
476
  `
411
477
  Axiom - an AWS focused config cli
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  SetCommand,
7
7
  awsOptions,
8
8
  commonOptions
9
- } from "./chunk-QT654PKF.mjs";
9
+ } from "./chunk-CORLQJO7.mjs";
10
10
  export {
11
11
  Config,
12
12
  DeleteCommand,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsmrt/axiom-cli",
3
- "version": "0.3.1",
3
+ "version": "1.1.0",
4
4
  "description": "axiom cli for managing configs including secrets",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -28,20 +28,17 @@
28
28
  },
29
29
  "license": "MIT",
30
30
  "devDependencies": {
31
+ "@biomejs/biome": "^2.3.8",
31
32
  "@changesets/cli": "^2.27.11",
32
33
  "@types/inquirer": "^8.2.10",
33
- "@types/node": "^20.17.10",
34
+ "@types/node": "^22.12.0",
34
35
  "@types/yargs": "^17.0.33",
35
- "@typescript-eslint/eslint-plugin": "^6.21.0",
36
- "@typescript-eslint/parser": "^6.21.0",
37
- "@vitest/coverage-v8": "^1.6.0",
36
+ "@vitest/coverage-v8": "^4.0.0",
38
37
  "aws-sdk-client-mock": "^3.1.0",
39
- "eslint": "^8.57.1",
40
- "prettier": "^3.4.2",
41
38
  "ts-node": "^10.9.2",
42
39
  "tsup": "^8.3.5",
43
40
  "typescript": "^5.7.2",
44
- "vitest": "^1.6.0"
41
+ "vitest": "^4.0.0"
45
42
  },
46
43
  "dependencies": {
47
44
  "@aws-sdk/client-ssm": "^3.716.0",
@@ -51,12 +48,12 @@
51
48
  "chalk": "^4.1.2",
52
49
  "inquirer": "^8.2.6",
53
50
  "yargs": "^17.7.2",
54
- "@dsmrt/axiom-aws-sdk": "^0.2.2",
55
- "@dsmrt/axiom-config": "^0.2.3"
51
+ "@dsmrt/axiom-aws-sdk": "^1.0.0",
52
+ "@dsmrt/axiom-config": "^1.1.0"
56
53
  },
57
54
  "scripts": {
58
- "lint": "eslint ./src/ ./src/aws ./src/bin --ext .ts",
59
- "lint:fix": "eslint ./src/ ./src/aws ./src/bin --ext .ts --fix",
55
+ "lint": "biome lint",
56
+ "lint:fix": "biome lint --fix",
60
57
  "test": "vitest run --coverage",
61
58
  "watch": "vitest watch --coverage",
62
59
  "build": "tsup --entry ./src/bin/axiom.ts --entry ./src/index.ts --format cjs,esm --dts --clean",
package/tsconfig.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "compilerOptions": {
3
- "target": "es2022",
4
- "module": "commonjs",
5
- "esModuleInterop": true,
6
- "forceConsistentCasingInFileNames": true,
7
- "strict": true,
8
- "skipLibCheck": true,
9
- "noEmit": true
10
- },
11
- "include": ["src/index.ts"]
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "module": "commonjs",
5
+ "esModuleInterop": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "noEmit": true
10
+ },
11
+ "include": ["src/index.ts"]
12
12
  }
package/vitest.config.mts CHANGED
@@ -2,13 +2,13 @@
2
2
  import { defineConfig } from "vitest/config";
3
3
 
4
4
  export default defineConfig({
5
- test: {
6
- include: ["src/**/*.test.ts"],
7
- coverage: {
8
- provider: "v8",
9
- all: true,
10
- exclude: ["lib/**/*", "src/__mocks__/**/*"],
11
- reporter: ["text-summary", "json-summary"],
12
- },
13
- },
5
+ test: {
6
+ include: ["src/**/*.test.ts"],
7
+ coverage: {
8
+ provider: "v8",
9
+ all: true,
10
+ exclude: ["lib/**/*", "src/__mocks__/**/*"],
11
+ reporter: ["text-summary", "json-summary"],
12
+ },
13
+ },
14
14
  });