@dsmrt/axiom-cli 1.1.0 → 1.3.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,22 @@
1
1
  # @dsmrt/axiom-cli
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5edaee0: load config by env
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [5edaee0]
12
+ - @dsmrt/axiom-config@1.2.0
13
+
14
+ ## 1.2.0
15
+
16
+ ### Minor Changes
17
+
18
+ - 6c846be: adding cli subcommand for init for config files
19
+
3
20
  ## 1.1.0
4
21
 
5
22
  ### Minor Changes
package/dist/bin/axiom.js CHANGED
@@ -59,6 +59,219 @@ var Config = class {
59
59
  };
60
60
  };
61
61
 
62
+ // src/commands/init.ts
63
+ var import_node_fs = require("fs");
64
+ var import_node_path = require("path");
65
+ var import_inquirer = __toESM(require("inquirer"));
66
+ var Init = class {
67
+ command = "init";
68
+ describe = "Initialize Axiom configuration files";
69
+ builder = (args) => {
70
+ args.option("force", {
71
+ alias: "f",
72
+ type: "boolean",
73
+ description: "Overwrite existing config files",
74
+ default: false
75
+ }).option("name", {
76
+ type: "string",
77
+ description: "Project name"
78
+ }).option("account", {
79
+ type: "string",
80
+ description: "AWS account ID"
81
+ }).option("region", {
82
+ type: "string",
83
+ description: "AWS region"
84
+ }).option("profile", {
85
+ type: "string",
86
+ description: "AWS profile name"
87
+ }).option("custom-types", {
88
+ type: "boolean",
89
+ description: "Create custom types file for extending config"
90
+ });
91
+ return args;
92
+ };
93
+ handler = async (args) => {
94
+ debug(`Init command handler called with args: ${JSON.stringify(args)}`);
95
+ const cwd = process.cwd();
96
+ if (!(0, import_node_fs.existsSync)(cwd)) {
97
+ (0, import_node_fs.mkdirSync)(cwd, { recursive: true });
98
+ }
99
+ const configPath = (0, import_node_path.join)(cwd, ".axiom.ts");
100
+ const devConfigPath = (0, import_node_path.join)(cwd, ".axiom.dev.ts");
101
+ const typesPath = (0, import_node_path.join)(cwd, "axiom.config.d.ts");
102
+ if (!args.force) {
103
+ const existingFiles = [];
104
+ if ((0, import_node_fs.existsSync)(configPath)) existingFiles.push(".axiom.ts");
105
+ if ((0, import_node_fs.existsSync)(devConfigPath)) existingFiles.push(".axiom.dev.ts");
106
+ if ((0, import_node_fs.existsSync)(typesPath)) existingFiles.push("axiom.config.d.ts");
107
+ if (existingFiles.length > 0) {
108
+ console.error(
109
+ `\u274C Config files already exist: ${existingFiles.join(", ")}`
110
+ );
111
+ console.error(" Use --force to overwrite them.");
112
+ process.exit(1);
113
+ }
114
+ }
115
+ const answers = await import_inquirer.default.prompt([
116
+ {
117
+ type: "input",
118
+ name: "name",
119
+ message: "Project name:",
120
+ default: args.name || "my-app",
121
+ when: !args.name
122
+ },
123
+ {
124
+ type: "input",
125
+ name: "account",
126
+ message: "AWS account ID:",
127
+ default: args.account || "123456789012",
128
+ when: !args.account,
129
+ validate: (input) => {
130
+ if (/^\d{12}$/.test(input)) return true;
131
+ return "AWS account ID must be 12 digits";
132
+ }
133
+ },
134
+ {
135
+ type: "input",
136
+ name: "region",
137
+ message: "AWS region:",
138
+ default: args.region || "us-east-1",
139
+ when: !args.region
140
+ },
141
+ {
142
+ type: "input",
143
+ name: "profile",
144
+ message: "AWS profile name:",
145
+ default: args.profile || "default",
146
+ when: !args.profile
147
+ },
148
+ {
149
+ type: "confirm",
150
+ name: "createCustomTypes",
151
+ message: "Would you like to add custom config properties?",
152
+ default: true,
153
+ when: args.customTypes === void 0
154
+ }
155
+ ]);
156
+ const config = {
157
+ name: args.name || answers.name,
158
+ account: args.account || answers.account,
159
+ region: args.region || answers.region,
160
+ profile: args.profile || answers.profile,
161
+ createCustomTypes: args.customTypes !== void 0 ? args.customTypes : answers.createCustomTypes
162
+ };
163
+ debug(`Creating config files with config: ${JSON.stringify(config)}`);
164
+ if (config.createCustomTypes) {
165
+ const typesContent = this.generateTypesFile();
166
+ (0, import_node_fs.writeFileSync)(typesPath, typesContent);
167
+ console.log(`\u2705 Created ${typesPath}`);
168
+ debug(`Created types file: ${typesPath}`);
169
+ }
170
+ const baseConfigContent = this.generateBaseConfig(
171
+ config,
172
+ config.createCustomTypes
173
+ );
174
+ (0, import_node_fs.writeFileSync)(configPath, baseConfigContent);
175
+ console.log(`\u2705 Created ${configPath}`);
176
+ debug(`Created base config: ${configPath}`);
177
+ const devConfigContent = this.generateDevConfig(config.createCustomTypes);
178
+ (0, import_node_fs.writeFileSync)(devConfigPath, devConfigContent);
179
+ console.log(`\u2705 Created ${devConfigPath}`);
180
+ debug(`Created dev config: ${devConfigPath}`);
181
+ console.log("\n\u{1F389} Axiom configuration initialized successfully!");
182
+ console.log("\n\u{1F4DD} Next steps:");
183
+ console.log(" 1. Edit .axiom.ts to customize your base configuration");
184
+ console.log(
185
+ " 2. Edit .axiom.dev.ts to customize your development configuration"
186
+ );
187
+ if (config.createCustomTypes) {
188
+ console.log(
189
+ " 3. Edit axiom.config.d.ts to add your custom config properties"
190
+ );
191
+ }
192
+ console.log(
193
+ ` ${config.createCustomTypes ? "4" : "3"}. Run 'axiom config' to verify your configuration`
194
+ );
195
+ };
196
+ generateTypesFile() {
197
+ return `/**
198
+ * Custom Axiom Configuration Types
199
+ *
200
+ * Extend this interface to add custom properties to your Axiom config.
201
+ * These properties will be type-safe when using loadConfig() in your code.
202
+ *
203
+ * Example:
204
+ *
205
+ * export interface CustomConfig {
206
+ * apiUrl: string;
207
+ * apiKey: string;
208
+ * maxRetries: number;
209
+ * features: {
210
+ * authentication: boolean;
211
+ * analytics: boolean;
212
+ * };
213
+ * }
214
+ */
215
+
216
+ export interface CustomConfig {
217
+ // Add your custom properties here
218
+ // Example:
219
+ // apiUrl: string;
220
+ // maxRetries: number;
221
+ }
222
+ `;
223
+ }
224
+ generateBaseConfig(config, hasCustomTypes) {
225
+ const importStatement = hasCustomTypes ? `import type { Config } from "@dsmrt/axiom-config";
226
+ import type { CustomConfig } from "./axiom.config";
227
+
228
+ type AxiomConfig = Config & CustomConfig;
229
+
230
+ const config: AxiomConfig = {` : `import type { Config } from "@dsmrt/axiom-config";
231
+
232
+ const config: Config = {`;
233
+ return `${importStatement}
234
+ name: "${config.name}",
235
+ env: "prod",
236
+ aws: {
237
+ account: "${config.account}",
238
+ region: "${config.region}",
239
+ profile: "${config.profile}",
240
+ },
241
+ baseParameterPath: "/${config.name}/prod",${hasCustomTypes ? `
242
+
243
+ // Add your custom config properties here
244
+ // Example:
245
+ // apiUrl: "https://api.example.com",
246
+ // maxRetries: 3,` : ""}
247
+ };
248
+
249
+ export default config;
250
+ `;
251
+ }
252
+ generateDevConfig(hasCustomTypes) {
253
+ const importStatement = hasCustomTypes ? `import type { Config } from "@dsmrt/axiom-config";
254
+ import type { CustomConfig } from "./axiom.config";
255
+
256
+ type AxiomConfig = Config & CustomConfig;
257
+
258
+ const config: Partial<AxiomConfig> = {` : `import type { Config } from "@dsmrt/axiom-config";
259
+
260
+ const config: Partial<Config> = {`;
261
+ return `${importStatement}
262
+ env: "dev",
263
+ baseParameterPath: undefined, // Will be auto-generated as /{name}/dev${hasCustomTypes ? `,
264
+
265
+ // Override custom config properties for dev environment
266
+ // Example:
267
+ // apiUrl: "https://api.dev.example.com",` : ""}
268
+ };
269
+
270
+ export default config;
271
+ `;
272
+ }
273
+ };
274
+
62
275
  // src/commands/params/base.ts
63
276
  var ParamsCommand = class {
64
277
  command = "params";
@@ -81,10 +294,10 @@ var import_chalk = __toESM(require("chalk"));
81
294
  // src/aws/credentials-provider.ts
82
295
  var import_credential_providers = require("@aws-sdk/credential-providers");
83
296
  var import_client_sts = require("@aws-sdk/client-sts");
84
- var import_inquirer = __toESM(require("inquirer"));
297
+ var import_inquirer2 = __toESM(require("inquirer"));
85
298
 
86
299
  // src/cache.ts
87
- var import_node_fs = __toESM(require("fs"));
300
+ var import_node_fs2 = __toESM(require("fs"));
88
301
  var import_node_os = __toESM(require("os"));
89
302
  var DEFAULT_DIRECTORY = `${import_node_os.default.homedir()}/.axiom/cache`;
90
303
  var cache_default = class {
@@ -93,10 +306,10 @@ var cache_default = class {
93
306
  }
94
307
  get(name) {
95
308
  const file = `${this.cacheDir}/${name}`;
96
- if (!import_node_fs.default.existsSync(file)) {
309
+ if (!import_node_fs2.default.existsSync(file)) {
97
310
  return;
98
311
  }
99
- const buffer = import_node_fs.default.readFileSync(file);
312
+ const buffer = import_node_fs2.default.readFileSync(file);
100
313
  const item = JSON.parse(buffer.toString());
101
314
  if (item.expires === void 0) {
102
315
  return item.data;
@@ -109,16 +322,16 @@ var cache_default = class {
109
322
  return item.data;
110
323
  }
111
324
  delete(name) {
112
- import_node_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
325
+ import_node_fs2.default.unlinkSync(`${this.cacheDir}/${name}`);
113
326
  }
114
327
  set(name, value, expires) {
115
- if (!import_node_fs.default.existsSync(this.cacheDir)) {
116
- import_node_fs.default.mkdirSync(this.cacheDir, {
328
+ if (!import_node_fs2.default.existsSync(this.cacheDir)) {
329
+ import_node_fs2.default.mkdirSync(this.cacheDir, {
117
330
  recursive: true,
118
331
  mode: 448
119
332
  });
120
333
  }
121
- import_node_fs.default.writeFileSync(
334
+ import_node_fs2.default.writeFileSync(
122
335
  `${this.cacheDir}/${name}`,
123
336
  JSON.stringify({
124
337
  expires,
@@ -173,7 +386,7 @@ var roleAssumerCallable = (config) => {
173
386
  };
174
387
  };
175
388
  var mfaCodeProvider = async (mfaSerial) => {
176
- const mfaCode = await import_inquirer.default.prompt({
389
+ const mfaCode = await import_inquirer2.default.prompt({
177
390
  name: "code",
178
391
  message: `Enter MFA code for ${mfaSerial}: `,
179
392
  type: "password"
@@ -269,7 +482,7 @@ Example:
269
482
  var import_client_ssm2 = require("@aws-sdk/client-ssm");
270
483
  var import_axiom_config3 = require("@dsmrt/axiom-config");
271
484
  var import_chalk2 = __toESM(require("chalk"));
272
- var import_inquirer2 = __toESM(require("inquirer"));
485
+ var import_inquirer3 = __toESM(require("inquirer"));
273
486
 
274
487
  // src/commands/params/utils.ts
275
488
  var buildPath = (config, path) => {
@@ -330,7 +543,7 @@ Example: "/root/myParam" or "service/secret"`
330
543
  debug(`Full parameter path: ${fullPath}`);
331
544
  if (args.force !== true) {
332
545
  debug(`Prompting user for confirmation...`);
333
- const res = await import_inquirer2.default.prompt({
546
+ const res = await import_inquirer3.default.prompt({
334
547
  type: "confirm",
335
548
  name: "setParam",
336
549
  message: `Are you sure you want to set '${args.path}'?`
@@ -370,7 +583,7 @@ Example: "/root/myParam" or "service/secret"`
370
583
  // src/commands/params/delete.ts
371
584
  var import_client_ssm3 = require("@aws-sdk/client-ssm");
372
585
  var import_axiom_config4 = require("@dsmrt/axiom-config");
373
- var import_inquirer3 = __toESM(require("inquirer"));
586
+ var import_inquirer4 = __toESM(require("inquirer"));
374
587
  var log = console.log;
375
588
  var DeleteCommand = class {
376
589
  command = "delete <path>";
@@ -416,7 +629,7 @@ Example: "/root/myParam" or "service/secret"`,
416
629
  }
417
630
  if (args.force !== true) {
418
631
  debug(`Prompting user for confirmation...`);
419
- const res = await import_inquirer3.default.prompt({
632
+ const res = await import_inquirer4.default.prompt({
420
633
  type: "confirm",
421
634
  name: "delete",
422
635
  message: `Are you sure you want to delete '${path}'?`
@@ -455,7 +668,7 @@ Example: "/root/myParam" or "service/secret"`,
455
668
  if (argv.debug) {
456
669
  process.env.AXIOM_DEBUG = "true";
457
670
  }
458
- }).command(new Config()).command(new ParamsCommand()).strict().usage(
671
+ }).command(new Init()).command(new Config()).command(new ParamsCommand()).strict().usage(
459
672
  `
460
673
  Axiom - an AWS focused config cli
461
674
 
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-CORLQJO7.mjs";
2
+ import "../chunk-QRHY3BEA.mjs";
@@ -34,6 +34,219 @@ var Config = class {
34
34
  };
35
35
  };
36
36
 
37
+ // src/commands/init.ts
38
+ import { existsSync, mkdirSync, writeFileSync } from "fs";
39
+ import { join } from "path";
40
+ import inquirer from "inquirer";
41
+ var Init = class {
42
+ command = "init";
43
+ describe = "Initialize Axiom configuration files";
44
+ builder = (args) => {
45
+ args.option("force", {
46
+ alias: "f",
47
+ type: "boolean",
48
+ description: "Overwrite existing config files",
49
+ default: false
50
+ }).option("name", {
51
+ type: "string",
52
+ description: "Project name"
53
+ }).option("account", {
54
+ type: "string",
55
+ description: "AWS account ID"
56
+ }).option("region", {
57
+ type: "string",
58
+ description: "AWS region"
59
+ }).option("profile", {
60
+ type: "string",
61
+ description: "AWS profile name"
62
+ }).option("custom-types", {
63
+ type: "boolean",
64
+ description: "Create custom types file for extending config"
65
+ });
66
+ return args;
67
+ };
68
+ handler = async (args) => {
69
+ debug(`Init command handler called with args: ${JSON.stringify(args)}`);
70
+ const cwd = process.cwd();
71
+ if (!existsSync(cwd)) {
72
+ mkdirSync(cwd, { recursive: true });
73
+ }
74
+ const configPath = join(cwd, ".axiom.ts");
75
+ const devConfigPath = join(cwd, ".axiom.dev.ts");
76
+ const typesPath = join(cwd, "axiom.config.d.ts");
77
+ if (!args.force) {
78
+ const existingFiles = [];
79
+ if (existsSync(configPath)) existingFiles.push(".axiom.ts");
80
+ if (existsSync(devConfigPath)) existingFiles.push(".axiom.dev.ts");
81
+ if (existsSync(typesPath)) existingFiles.push("axiom.config.d.ts");
82
+ if (existingFiles.length > 0) {
83
+ console.error(
84
+ `\u274C Config files already exist: ${existingFiles.join(", ")}`
85
+ );
86
+ console.error(" Use --force to overwrite them.");
87
+ process.exit(1);
88
+ }
89
+ }
90
+ const answers = await inquirer.prompt([
91
+ {
92
+ type: "input",
93
+ name: "name",
94
+ message: "Project name:",
95
+ default: args.name || "my-app",
96
+ when: !args.name
97
+ },
98
+ {
99
+ type: "input",
100
+ name: "account",
101
+ message: "AWS account ID:",
102
+ default: args.account || "123456789012",
103
+ when: !args.account,
104
+ validate: (input) => {
105
+ if (/^\d{12}$/.test(input)) return true;
106
+ return "AWS account ID must be 12 digits";
107
+ }
108
+ },
109
+ {
110
+ type: "input",
111
+ name: "region",
112
+ message: "AWS region:",
113
+ default: args.region || "us-east-1",
114
+ when: !args.region
115
+ },
116
+ {
117
+ type: "input",
118
+ name: "profile",
119
+ message: "AWS profile name:",
120
+ default: args.profile || "default",
121
+ when: !args.profile
122
+ },
123
+ {
124
+ type: "confirm",
125
+ name: "createCustomTypes",
126
+ message: "Would you like to add custom config properties?",
127
+ default: true,
128
+ when: args.customTypes === void 0
129
+ }
130
+ ]);
131
+ const config = {
132
+ name: args.name || answers.name,
133
+ account: args.account || answers.account,
134
+ region: args.region || answers.region,
135
+ profile: args.profile || answers.profile,
136
+ createCustomTypes: args.customTypes !== void 0 ? args.customTypes : answers.createCustomTypes
137
+ };
138
+ debug(`Creating config files with config: ${JSON.stringify(config)}`);
139
+ if (config.createCustomTypes) {
140
+ const typesContent = this.generateTypesFile();
141
+ writeFileSync(typesPath, typesContent);
142
+ console.log(`\u2705 Created ${typesPath}`);
143
+ debug(`Created types file: ${typesPath}`);
144
+ }
145
+ const baseConfigContent = this.generateBaseConfig(
146
+ config,
147
+ config.createCustomTypes
148
+ );
149
+ writeFileSync(configPath, baseConfigContent);
150
+ console.log(`\u2705 Created ${configPath}`);
151
+ debug(`Created base config: ${configPath}`);
152
+ const devConfigContent = this.generateDevConfig(config.createCustomTypes);
153
+ writeFileSync(devConfigPath, devConfigContent);
154
+ console.log(`\u2705 Created ${devConfigPath}`);
155
+ debug(`Created dev config: ${devConfigPath}`);
156
+ console.log("\n\u{1F389} Axiom configuration initialized successfully!");
157
+ console.log("\n\u{1F4DD} Next steps:");
158
+ console.log(" 1. Edit .axiom.ts to customize your base configuration");
159
+ console.log(
160
+ " 2. Edit .axiom.dev.ts to customize your development configuration"
161
+ );
162
+ if (config.createCustomTypes) {
163
+ console.log(
164
+ " 3. Edit axiom.config.d.ts to add your custom config properties"
165
+ );
166
+ }
167
+ console.log(
168
+ ` ${config.createCustomTypes ? "4" : "3"}. Run 'axiom config' to verify your configuration`
169
+ );
170
+ };
171
+ generateTypesFile() {
172
+ return `/**
173
+ * Custom Axiom Configuration Types
174
+ *
175
+ * Extend this interface to add custom properties to your Axiom config.
176
+ * These properties will be type-safe when using loadConfig() in your code.
177
+ *
178
+ * Example:
179
+ *
180
+ * export interface CustomConfig {
181
+ * apiUrl: string;
182
+ * apiKey: string;
183
+ * maxRetries: number;
184
+ * features: {
185
+ * authentication: boolean;
186
+ * analytics: boolean;
187
+ * };
188
+ * }
189
+ */
190
+
191
+ export interface CustomConfig {
192
+ // Add your custom properties here
193
+ // Example:
194
+ // apiUrl: string;
195
+ // maxRetries: number;
196
+ }
197
+ `;
198
+ }
199
+ generateBaseConfig(config, hasCustomTypes) {
200
+ const importStatement = hasCustomTypes ? `import type { Config } from "@dsmrt/axiom-config";
201
+ import type { CustomConfig } from "./axiom.config";
202
+
203
+ type AxiomConfig = Config & CustomConfig;
204
+
205
+ const config: AxiomConfig = {` : `import type { Config } from "@dsmrt/axiom-config";
206
+
207
+ const config: Config = {`;
208
+ return `${importStatement}
209
+ name: "${config.name}",
210
+ env: "prod",
211
+ aws: {
212
+ account: "${config.account}",
213
+ region: "${config.region}",
214
+ profile: "${config.profile}",
215
+ },
216
+ baseParameterPath: "/${config.name}/prod",${hasCustomTypes ? `
217
+
218
+ // Add your custom config properties here
219
+ // Example:
220
+ // apiUrl: "https://api.example.com",
221
+ // maxRetries: 3,` : ""}
222
+ };
223
+
224
+ export default config;
225
+ `;
226
+ }
227
+ generateDevConfig(hasCustomTypes) {
228
+ const importStatement = hasCustomTypes ? `import type { Config } from "@dsmrt/axiom-config";
229
+ import type { CustomConfig } from "./axiom.config";
230
+
231
+ type AxiomConfig = Config & CustomConfig;
232
+
233
+ const config: Partial<AxiomConfig> = {` : `import type { Config } from "@dsmrt/axiom-config";
234
+
235
+ const config: Partial<Config> = {`;
236
+ return `${importStatement}
237
+ env: "dev",
238
+ baseParameterPath: undefined, // Will be auto-generated as /{name}/dev${hasCustomTypes ? `,
239
+
240
+ // Override custom config properties for dev environment
241
+ // Example:
242
+ // apiUrl: "https://api.dev.example.com",` : ""}
243
+ };
244
+
245
+ export default config;
246
+ `;
247
+ }
248
+ };
249
+
37
250
  // src/commands/params/base.ts
38
251
  var ParamsCommand = class {
39
252
  command = "params";
@@ -59,7 +272,7 @@ import {
59
272
  AssumeRoleCommand,
60
273
  STSClient
61
274
  } from "@aws-sdk/client-sts";
62
- import inquirer from "inquirer";
275
+ import inquirer2 from "inquirer";
63
276
 
64
277
  // src/cache.ts
65
278
  import fs from "fs";
@@ -151,7 +364,7 @@ var roleAssumerCallable = (config) => {
151
364
  };
152
365
  };
153
366
  var mfaCodeProvider = async (mfaSerial) => {
154
- const mfaCode = await inquirer.prompt({
367
+ const mfaCode = await inquirer2.prompt({
155
368
  name: "code",
156
369
  message: `Enter MFA code for ${mfaSerial}: `,
157
370
  type: "password"
@@ -251,7 +464,7 @@ import {
251
464
  } from "@aws-sdk/client-ssm";
252
465
  import { loadConfig as loadConfig3 } from "@dsmrt/axiom-config";
253
466
  import chalk2 from "chalk";
254
- import inquirer2 from "inquirer";
467
+ import inquirer3 from "inquirer";
255
468
 
256
469
  // src/commands/params/utils.ts
257
470
  var buildPath = (config, path) => {
@@ -312,7 +525,7 @@ Example: "/root/myParam" or "service/secret"`
312
525
  debug(`Full parameter path: ${fullPath}`);
313
526
  if (args.force !== true) {
314
527
  debug(`Prompting user for confirmation...`);
315
- const res = await inquirer2.prompt({
528
+ const res = await inquirer3.prompt({
316
529
  type: "confirm",
317
530
  name: "setParam",
318
531
  message: `Are you sure you want to set '${args.path}'?`
@@ -352,7 +565,7 @@ Example: "/root/myParam" or "service/secret"`
352
565
  // src/commands/params/delete.ts
353
566
  import { DeleteParameterCommand, SSMClient as SSMClient3 } from "@aws-sdk/client-ssm";
354
567
  import { loadConfig as loadConfig4 } from "@dsmrt/axiom-config";
355
- import inquirer3 from "inquirer";
568
+ import inquirer4 from "inquirer";
356
569
  var log = console.log;
357
570
  var DeleteCommand = class {
358
571
  command = "delete <path>";
@@ -398,7 +611,7 @@ Example: "/root/myParam" or "service/secret"`,
398
611
  }
399
612
  if (args.force !== true) {
400
613
  debug(`Prompting user for confirmation...`);
401
- const res = await inquirer3.prompt({
614
+ const res = await inquirer4.prompt({
402
615
  type: "confirm",
403
616
  name: "delete",
404
617
  message: `Are you sure you want to delete '${path}'?`
@@ -437,7 +650,7 @@ yargs(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
437
650
  if (argv.debug) {
438
651
  process.env.AXIOM_DEBUG = "true";
439
652
  }
440
- }).command(new Config()).command(new ParamsCommand()).strict().usage(
653
+ }).command(new Init()).command(new Config()).command(new ParamsCommand()).strict().usage(
441
654
  `
442
655
  Axiom - an AWS focused config cli
443
656
 
@@ -448,6 +661,7 @@ USAGE:
448
661
 
449
662
  export {
450
663
  Config,
664
+ Init,
451
665
  ParamsCommand,
452
666
  commonOptions,
453
667
  awsOptions,
package/dist/index.d.mts CHANGED
@@ -19,6 +19,24 @@ declare class Config<U extends ConfigOptions> implements CommandModule<object, U
19
19
  loadConfig: (args: ConfigOptions) => Promise<_dsmrt_axiom_config.ConfigContainer & object>;
20
20
  }
21
21
 
22
+ interface InitOptions {
23
+ force?: boolean;
24
+ name?: string;
25
+ account?: string;
26
+ region?: string;
27
+ profile?: string;
28
+ customTypes?: boolean;
29
+ }
30
+ declare class Init<U extends InitOptions> implements CommandModule<object, U> {
31
+ command: string;
32
+ describe: string;
33
+ builder: CommandBuilder<object, U>;
34
+ handler: (args: ArgumentsCamelCase<U>) => Promise<void>;
35
+ private generateTypesFile;
36
+ private generateBaseConfig;
37
+ private generateDevConfig;
38
+ }
39
+
22
40
  type Options = object;
23
41
  declare class ParamsCommand<U extends Options> implements CommandModule<object, U> {
24
42
  command: string;
@@ -74,4 +92,4 @@ declare const awsOptions: () => {
74
92
  [key: string]: Options$1;
75
93
  };
76
94
 
77
- export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
95
+ export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, Init, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
package/dist/index.d.ts CHANGED
@@ -19,6 +19,24 @@ declare class Config<U extends ConfigOptions> implements CommandModule<object, U
19
19
  loadConfig: (args: ConfigOptions) => Promise<_dsmrt_axiom_config.ConfigContainer & object>;
20
20
  }
21
21
 
22
+ interface InitOptions {
23
+ force?: boolean;
24
+ name?: string;
25
+ account?: string;
26
+ region?: string;
27
+ profile?: string;
28
+ customTypes?: boolean;
29
+ }
30
+ declare class Init<U extends InitOptions> implements CommandModule<object, U> {
31
+ command: string;
32
+ describe: string;
33
+ builder: CommandBuilder<object, U>;
34
+ handler: (args: ArgumentsCamelCase<U>) => Promise<void>;
35
+ private generateTypesFile;
36
+ private generateBaseConfig;
37
+ private generateDevConfig;
38
+ }
39
+
22
40
  type Options = object;
23
41
  declare class ParamsCommand<U extends Options> implements CommandModule<object, U> {
24
42
  command: string;
@@ -74,4 +92,4 @@ declare const awsOptions: () => {
74
92
  [key: string]: Options$1;
75
93
  };
76
94
 
77
- export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
95
+ export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, Init, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  Config: () => Config,
34
34
  DeleteCommand: () => DeleteCommand,
35
35
  GetCommand: () => GetCommand,
36
+ Init: () => Init,
36
37
  ParamsCommand: () => ParamsCommand,
37
38
  SetCommand: () => SetCommand,
38
39
  awsOptions: () => awsOptions,
@@ -76,6 +77,219 @@ var Config = class {
76
77
  };
77
78
  };
78
79
 
80
+ // src/commands/init.ts
81
+ var import_node_fs = require("fs");
82
+ var import_node_path = require("path");
83
+ var import_inquirer = __toESM(require("inquirer"));
84
+ var Init = class {
85
+ command = "init";
86
+ describe = "Initialize Axiom configuration files";
87
+ builder = (args) => {
88
+ args.option("force", {
89
+ alias: "f",
90
+ type: "boolean",
91
+ description: "Overwrite existing config files",
92
+ default: false
93
+ }).option("name", {
94
+ type: "string",
95
+ description: "Project name"
96
+ }).option("account", {
97
+ type: "string",
98
+ description: "AWS account ID"
99
+ }).option("region", {
100
+ type: "string",
101
+ description: "AWS region"
102
+ }).option("profile", {
103
+ type: "string",
104
+ description: "AWS profile name"
105
+ }).option("custom-types", {
106
+ type: "boolean",
107
+ description: "Create custom types file for extending config"
108
+ });
109
+ return args;
110
+ };
111
+ handler = async (args) => {
112
+ debug(`Init command handler called with args: ${JSON.stringify(args)}`);
113
+ const cwd = process.cwd();
114
+ if (!(0, import_node_fs.existsSync)(cwd)) {
115
+ (0, import_node_fs.mkdirSync)(cwd, { recursive: true });
116
+ }
117
+ const configPath = (0, import_node_path.join)(cwd, ".axiom.ts");
118
+ const devConfigPath = (0, import_node_path.join)(cwd, ".axiom.dev.ts");
119
+ const typesPath = (0, import_node_path.join)(cwd, "axiom.config.d.ts");
120
+ if (!args.force) {
121
+ const existingFiles = [];
122
+ if ((0, import_node_fs.existsSync)(configPath)) existingFiles.push(".axiom.ts");
123
+ if ((0, import_node_fs.existsSync)(devConfigPath)) existingFiles.push(".axiom.dev.ts");
124
+ if ((0, import_node_fs.existsSync)(typesPath)) existingFiles.push("axiom.config.d.ts");
125
+ if (existingFiles.length > 0) {
126
+ console.error(
127
+ `\u274C Config files already exist: ${existingFiles.join(", ")}`
128
+ );
129
+ console.error(" Use --force to overwrite them.");
130
+ process.exit(1);
131
+ }
132
+ }
133
+ const answers = await import_inquirer.default.prompt([
134
+ {
135
+ type: "input",
136
+ name: "name",
137
+ message: "Project name:",
138
+ default: args.name || "my-app",
139
+ when: !args.name
140
+ },
141
+ {
142
+ type: "input",
143
+ name: "account",
144
+ message: "AWS account ID:",
145
+ default: args.account || "123456789012",
146
+ when: !args.account,
147
+ validate: (input) => {
148
+ if (/^\d{12}$/.test(input)) return true;
149
+ return "AWS account ID must be 12 digits";
150
+ }
151
+ },
152
+ {
153
+ type: "input",
154
+ name: "region",
155
+ message: "AWS region:",
156
+ default: args.region || "us-east-1",
157
+ when: !args.region
158
+ },
159
+ {
160
+ type: "input",
161
+ name: "profile",
162
+ message: "AWS profile name:",
163
+ default: args.profile || "default",
164
+ when: !args.profile
165
+ },
166
+ {
167
+ type: "confirm",
168
+ name: "createCustomTypes",
169
+ message: "Would you like to add custom config properties?",
170
+ default: true,
171
+ when: args.customTypes === void 0
172
+ }
173
+ ]);
174
+ const config = {
175
+ name: args.name || answers.name,
176
+ account: args.account || answers.account,
177
+ region: args.region || answers.region,
178
+ profile: args.profile || answers.profile,
179
+ createCustomTypes: args.customTypes !== void 0 ? args.customTypes : answers.createCustomTypes
180
+ };
181
+ debug(`Creating config files with config: ${JSON.stringify(config)}`);
182
+ if (config.createCustomTypes) {
183
+ const typesContent = this.generateTypesFile();
184
+ (0, import_node_fs.writeFileSync)(typesPath, typesContent);
185
+ console.log(`\u2705 Created ${typesPath}`);
186
+ debug(`Created types file: ${typesPath}`);
187
+ }
188
+ const baseConfigContent = this.generateBaseConfig(
189
+ config,
190
+ config.createCustomTypes
191
+ );
192
+ (0, import_node_fs.writeFileSync)(configPath, baseConfigContent);
193
+ console.log(`\u2705 Created ${configPath}`);
194
+ debug(`Created base config: ${configPath}`);
195
+ const devConfigContent = this.generateDevConfig(config.createCustomTypes);
196
+ (0, import_node_fs.writeFileSync)(devConfigPath, devConfigContent);
197
+ console.log(`\u2705 Created ${devConfigPath}`);
198
+ debug(`Created dev config: ${devConfigPath}`);
199
+ console.log("\n\u{1F389} Axiom configuration initialized successfully!");
200
+ console.log("\n\u{1F4DD} Next steps:");
201
+ console.log(" 1. Edit .axiom.ts to customize your base configuration");
202
+ console.log(
203
+ " 2. Edit .axiom.dev.ts to customize your development configuration"
204
+ );
205
+ if (config.createCustomTypes) {
206
+ console.log(
207
+ " 3. Edit axiom.config.d.ts to add your custom config properties"
208
+ );
209
+ }
210
+ console.log(
211
+ ` ${config.createCustomTypes ? "4" : "3"}. Run 'axiom config' to verify your configuration`
212
+ );
213
+ };
214
+ generateTypesFile() {
215
+ return `/**
216
+ * Custom Axiom Configuration Types
217
+ *
218
+ * Extend this interface to add custom properties to your Axiom config.
219
+ * These properties will be type-safe when using loadConfig() in your code.
220
+ *
221
+ * Example:
222
+ *
223
+ * export interface CustomConfig {
224
+ * apiUrl: string;
225
+ * apiKey: string;
226
+ * maxRetries: number;
227
+ * features: {
228
+ * authentication: boolean;
229
+ * analytics: boolean;
230
+ * };
231
+ * }
232
+ */
233
+
234
+ export interface CustomConfig {
235
+ // Add your custom properties here
236
+ // Example:
237
+ // apiUrl: string;
238
+ // maxRetries: number;
239
+ }
240
+ `;
241
+ }
242
+ generateBaseConfig(config, hasCustomTypes) {
243
+ const importStatement = hasCustomTypes ? `import type { Config } from "@dsmrt/axiom-config";
244
+ import type { CustomConfig } from "./axiom.config";
245
+
246
+ type AxiomConfig = Config & CustomConfig;
247
+
248
+ const config: AxiomConfig = {` : `import type { Config } from "@dsmrt/axiom-config";
249
+
250
+ const config: Config = {`;
251
+ return `${importStatement}
252
+ name: "${config.name}",
253
+ env: "prod",
254
+ aws: {
255
+ account: "${config.account}",
256
+ region: "${config.region}",
257
+ profile: "${config.profile}",
258
+ },
259
+ baseParameterPath: "/${config.name}/prod",${hasCustomTypes ? `
260
+
261
+ // Add your custom config properties here
262
+ // Example:
263
+ // apiUrl: "https://api.example.com",
264
+ // maxRetries: 3,` : ""}
265
+ };
266
+
267
+ export default config;
268
+ `;
269
+ }
270
+ generateDevConfig(hasCustomTypes) {
271
+ const importStatement = hasCustomTypes ? `import type { Config } from "@dsmrt/axiom-config";
272
+ import type { CustomConfig } from "./axiom.config";
273
+
274
+ type AxiomConfig = Config & CustomConfig;
275
+
276
+ const config: Partial<AxiomConfig> = {` : `import type { Config } from "@dsmrt/axiom-config";
277
+
278
+ const config: Partial<Config> = {`;
279
+ return `${importStatement}
280
+ env: "dev",
281
+ baseParameterPath: undefined, // Will be auto-generated as /{name}/dev${hasCustomTypes ? `,
282
+
283
+ // Override custom config properties for dev environment
284
+ // Example:
285
+ // apiUrl: "https://api.dev.example.com",` : ""}
286
+ };
287
+
288
+ export default config;
289
+ `;
290
+ }
291
+ };
292
+
79
293
  // src/commands/params/base.ts
80
294
  var ParamsCommand = class {
81
295
  command = "params";
@@ -98,10 +312,10 @@ var import_chalk = __toESM(require("chalk"));
98
312
  // src/aws/credentials-provider.ts
99
313
  var import_credential_providers = require("@aws-sdk/credential-providers");
100
314
  var import_client_sts = require("@aws-sdk/client-sts");
101
- var import_inquirer = __toESM(require("inquirer"));
315
+ var import_inquirer2 = __toESM(require("inquirer"));
102
316
 
103
317
  // src/cache.ts
104
- var import_node_fs = __toESM(require("fs"));
318
+ var import_node_fs2 = __toESM(require("fs"));
105
319
  var import_node_os = __toESM(require("os"));
106
320
  var DEFAULT_DIRECTORY = `${import_node_os.default.homedir()}/.axiom/cache`;
107
321
  var cache_default = class {
@@ -110,10 +324,10 @@ var cache_default = class {
110
324
  }
111
325
  get(name) {
112
326
  const file = `${this.cacheDir}/${name}`;
113
- if (!import_node_fs.default.existsSync(file)) {
327
+ if (!import_node_fs2.default.existsSync(file)) {
114
328
  return;
115
329
  }
116
- const buffer = import_node_fs.default.readFileSync(file);
330
+ const buffer = import_node_fs2.default.readFileSync(file);
117
331
  const item = JSON.parse(buffer.toString());
118
332
  if (item.expires === void 0) {
119
333
  return item.data;
@@ -126,16 +340,16 @@ var cache_default = class {
126
340
  return item.data;
127
341
  }
128
342
  delete(name) {
129
- import_node_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
343
+ import_node_fs2.default.unlinkSync(`${this.cacheDir}/${name}`);
130
344
  }
131
345
  set(name, value, expires) {
132
- if (!import_node_fs.default.existsSync(this.cacheDir)) {
133
- import_node_fs.default.mkdirSync(this.cacheDir, {
346
+ if (!import_node_fs2.default.existsSync(this.cacheDir)) {
347
+ import_node_fs2.default.mkdirSync(this.cacheDir, {
134
348
  recursive: true,
135
349
  mode: 448
136
350
  });
137
351
  }
138
- import_node_fs.default.writeFileSync(
352
+ import_node_fs2.default.writeFileSync(
139
353
  `${this.cacheDir}/${name}`,
140
354
  JSON.stringify({
141
355
  expires,
@@ -190,7 +404,7 @@ var roleAssumerCallable = (config) => {
190
404
  };
191
405
  };
192
406
  var mfaCodeProvider = async (mfaSerial) => {
193
- const mfaCode = await import_inquirer.default.prompt({
407
+ const mfaCode = await import_inquirer2.default.prompt({
194
408
  name: "code",
195
409
  message: `Enter MFA code for ${mfaSerial}: `,
196
410
  type: "password"
@@ -286,7 +500,7 @@ Example:
286
500
  var import_client_ssm2 = require("@aws-sdk/client-ssm");
287
501
  var import_axiom_config3 = require("@dsmrt/axiom-config");
288
502
  var import_chalk2 = __toESM(require("chalk"));
289
- var import_inquirer2 = __toESM(require("inquirer"));
503
+ var import_inquirer3 = __toESM(require("inquirer"));
290
504
 
291
505
  // src/commands/params/utils.ts
292
506
  var buildPath = (config, path) => {
@@ -347,7 +561,7 @@ Example: "/root/myParam" or "service/secret"`
347
561
  debug(`Full parameter path: ${fullPath}`);
348
562
  if (args.force !== true) {
349
563
  debug(`Prompting user for confirmation...`);
350
- const res = await import_inquirer2.default.prompt({
564
+ const res = await import_inquirer3.default.prompt({
351
565
  type: "confirm",
352
566
  name: "setParam",
353
567
  message: `Are you sure you want to set '${args.path}'?`
@@ -387,7 +601,7 @@ Example: "/root/myParam" or "service/secret"`
387
601
  // src/commands/params/delete.ts
388
602
  var import_client_ssm3 = require("@aws-sdk/client-ssm");
389
603
  var import_axiom_config4 = require("@dsmrt/axiom-config");
390
- var import_inquirer3 = __toESM(require("inquirer"));
604
+ var import_inquirer4 = __toESM(require("inquirer"));
391
605
  var log = console.log;
392
606
  var DeleteCommand = class {
393
607
  command = "delete <path>";
@@ -433,7 +647,7 @@ Example: "/root/myParam" or "service/secret"`,
433
647
  }
434
648
  if (args.force !== true) {
435
649
  debug(`Prompting user for confirmation...`);
436
- const res = await import_inquirer3.default.prompt({
650
+ const res = await import_inquirer4.default.prompt({
437
651
  type: "confirm",
438
652
  name: "delete",
439
653
  message: `Are you sure you want to delete '${path}'?`
@@ -472,7 +686,7 @@ Example: "/root/myParam" or "service/secret"`,
472
686
  if (argv.debug) {
473
687
  process.env.AXIOM_DEBUG = "true";
474
688
  }
475
- }).command(new Config()).command(new ParamsCommand()).strict().usage(
689
+ }).command(new Init()).command(new Config()).command(new ParamsCommand()).strict().usage(
476
690
  `
477
691
  Axiom - an AWS focused config cli
478
692
 
@@ -485,6 +699,7 @@ USAGE:
485
699
  Config,
486
700
  DeleteCommand,
487
701
  GetCommand,
702
+ Init,
488
703
  ParamsCommand,
489
704
  SetCommand,
490
705
  awsOptions,
package/dist/index.mjs CHANGED
@@ -2,15 +2,17 @@ import {
2
2
  Config,
3
3
  DeleteCommand,
4
4
  GetCommand,
5
+ Init,
5
6
  ParamsCommand,
6
7
  SetCommand,
7
8
  awsOptions,
8
9
  commonOptions
9
- } from "./chunk-CORLQJO7.mjs";
10
+ } from "./chunk-QRHY3BEA.mjs";
10
11
  export {
11
12
  Config,
12
13
  DeleteCommand,
13
14
  GetCommand,
15
+ Init,
14
16
  ParamsCommand,
15
17
  SetCommand,
16
18
  awsOptions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsmrt/axiom-cli",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "axiom cli for managing configs including secrets",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -49,7 +49,7 @@
49
49
  "inquirer": "^8.2.6",
50
50
  "yargs": "^17.7.2",
51
51
  "@dsmrt/axiom-aws-sdk": "^1.0.0",
52
- "@dsmrt/axiom-config": "^1.1.0"
52
+ "@dsmrt/axiom-config": "^1.2.0"
53
53
  },
54
54
  "scripts": {
55
55
  "lint": "biome lint",