envx-cli 1.0.0 → 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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 EnvX Contributors
3
+ Copyright (c) 2025 Rahul Retnan
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -29,19 +29,23 @@ Before using EnvX, ensure you have:
29
29
  ### Installing GPG
30
30
 
31
31
  #### macOS
32
+
32
33
  ```bash
33
34
  brew install gnupg
34
35
  ```
35
36
 
36
37
  #### Ubuntu/Debian
38
+
37
39
  ```bash
38
40
  sudo apt-get install gnupg
39
41
  ```
40
42
 
41
43
  #### Windows
44
+
42
45
  Download from [https://gnupg.org/download/](https://gnupg.org/download/)
43
46
 
44
47
  #### Verify Installation
48
+
45
49
  ```bash
46
50
  gpg --version
47
51
  ```
@@ -49,46 +53,54 @@ gpg --version
49
53
  ## Installation
50
54
 
51
55
  ### Global Installation (Recommended)
56
+
52
57
  ```bash
53
- npm install -g envx
58
+ npm install -g envx-cli
54
59
  ```
55
60
 
56
61
  ### Local Installation
62
+
57
63
  ```bash
58
- npm install envx
64
+ npm install envx-cli
59
65
  npx envx --help
60
66
  ```
61
67
 
62
68
  ## Quick Start
63
69
 
64
70
  1. **Initialize EnvX in your project:**
71
+
65
72
  ```bash
66
73
  envx init
67
74
  ```
68
75
 
69
76
  2. **Create environment files:**
77
+
70
78
  ```bash
71
79
  envx create -e development
72
80
  envx create -e production
73
81
  ```
74
82
 
75
83
  3. **Set up secrets for encryption:**
84
+
76
85
  ```bash
77
86
  envx interactive
78
87
  ```
79
88
 
80
89
  4. **Encrypt your environment files:**
90
+
81
91
  ```bash
82
92
  envx encrypt -e production
83
93
  ```
84
94
 
85
95
  5. **Commit encrypted files to git:**
96
+
86
97
  ```bash
87
98
  git add *.gpg
88
99
  git commit -m "Add encrypted environment files"
89
100
  ```
90
101
 
91
102
  6. **Decrypt when needed:**
103
+
92
104
  ```bash
93
105
  envx decrypt -e production
94
106
  ```
@@ -96,6 +108,7 @@ envx decrypt -e production
96
108
  ## Commands
97
109
 
98
110
  ### `envx init`
111
+
99
112
  Initialize EnvX in a new project with guided setup.
100
113
 
101
114
  ```bash
@@ -103,6 +116,7 @@ envx init
103
116
  ```
104
117
 
105
118
  ### `envx create`
119
+
106
120
  Create new environment files.
107
121
 
108
122
  ```bash
@@ -120,6 +134,7 @@ envx create -e staging --overwrite
120
134
  ```
121
135
 
122
136
  **Options:**
137
+
123
138
  - `-e, --environment <env>` - Environment name
124
139
  - `-t, --template <path>` - Template file path
125
140
  - `-i, --interactive` - Interactive mode
@@ -127,52 +142,71 @@ envx create -e staging --overwrite
127
142
  - `-c, --cwd <path>` - Working directory
128
143
 
129
144
  ### `envx encrypt`
145
+
130
146
  Encrypt environment files using GPG.
131
147
 
132
148
  ```bash
133
149
  # Encrypt specific environment
134
150
  envx encrypt -e production
135
151
 
152
+ # Encrypt all environments at once
153
+ envx encrypt --all
154
+
136
155
  # Use custom secret from .envrc
137
156
  envx encrypt -e production -s CUSTOM_SECRET
138
157
 
139
- # Interactive file selection
158
+ # Interactive file selection (for single environment)
140
159
  envx encrypt -e staging -i
141
160
 
161
+ # Encrypt all with specific passphrase
162
+ envx encrypt --all -p "your-passphrase"
163
+
142
164
  # Specify passphrase directly (not recommended)
143
165
  envx encrypt -e development -p "your-passphrase"
144
166
  ```
145
167
 
146
168
  **Options:**
147
- - `-e, --environment <env>` - Environment name (required)
169
+
170
+ - `-e, --environment <env>` - Environment name (required unless using --all)
171
+ - `-a, --all` - Process all available environments
148
172
  - `-p, --passphrase <pass>` - Encryption passphrase
149
173
  - `-s, --secret <secret>` - Secret variable name from .envrc
150
- - `-i, --interactive` - Interactive file selection
174
+ - `-i, --interactive` - Interactive file selection (disabled with --all)
151
175
  - `-c, --cwd <path>` - Working directory
152
176
 
153
177
  ### `envx decrypt`
178
+
154
179
  Decrypt environment files.
155
180
 
156
181
  ```bash
157
182
  # Decrypt specific environment
158
183
  envx decrypt -e production
159
184
 
185
+ # Decrypt all environments at once
186
+ envx decrypt --all
187
+
160
188
  # Overwrite existing files without confirmation
161
189
  envx decrypt -e development --overwrite
162
190
 
163
- # Interactive file selection
191
+ # Decrypt all with overwrite flag
192
+ envx decrypt --all --overwrite
193
+
194
+ # Interactive file selection (for single environment)
164
195
  envx decrypt -e staging -i
165
196
  ```
166
197
 
167
198
  **Options:**
168
- - `-e, --environment <env>` - Environment name (required)
199
+
200
+ - `-e, --environment <env>` - Environment name (required unless using --all)
201
+ - `-a, --all` - Process all available environments
169
202
  - `-p, --passphrase <pass>` - Decryption passphrase
170
203
  - `-s, --secret <secret>` - Secret variable name from .envrc
171
- - `-i, --interactive` - Interactive file selection
204
+ - `-i, --interactive` - Interactive file selection (disabled with --all)
172
205
  - `--overwrite` - Overwrite existing files without confirmation
173
206
  - `-c, --cwd <path>` - Working directory
174
207
 
175
208
  ### `envx interactive`
209
+
176
210
  Interactive setup for `.envrc` file with secrets.
177
211
 
178
212
  ```bash
@@ -187,11 +221,13 @@ envx interactive --generate
187
221
  ```
188
222
 
189
223
  **Options:**
224
+
190
225
  - `--overwrite` - Overwrite existing .envrc file
191
226
  - `--generate` - Generate random secrets
192
227
  - `-c, --cwd <path>` - Working directory
193
228
 
194
229
  ### `envx list`
230
+
195
231
  List all environment files and their status.
196
232
 
197
233
  ```bash
@@ -203,9 +239,11 @@ envx ls
203
239
  ```
204
240
 
205
241
  **Options:**
242
+
206
243
  - `-c, --cwd <path>` - Working directory
207
244
 
208
245
  ### `envx status`
246
+
209
247
  Show project encryption status and recommendations.
210
248
 
211
249
  ```bash
@@ -213,6 +251,7 @@ envx status
213
251
  ```
214
252
 
215
253
  **Options:**
254
+
216
255
  - `-c, --cwd <path>` - Working directory
217
256
 
218
257
  ## Workflow Examples
@@ -220,12 +259,14 @@ envx status
220
259
  ### Basic Workflow
221
260
 
222
261
  1. **Create environment files:**
262
+
223
263
  ```bash
224
264
  envx create -e development
225
265
  envx create -e production
226
266
  ```
227
267
 
228
268
  2. **Edit your environment files:**
269
+
229
270
  ```bash
230
271
  # Edit .env.development
231
272
  echo "DATABASE_URL=postgresql://localhost:5432/myapp_dev" >> .env.development
@@ -237,16 +278,19 @@ echo "API_KEY=prod-api-key-secret" >> .env.production
237
278
  ```
238
279
 
239
280
  3. **Set up encryption secrets:**
281
+
240
282
  ```bash
241
283
  envx interactive
242
284
  ```
243
285
 
244
286
  4. **Encrypt production secrets:**
287
+
245
288
  ```bash
246
289
  envx encrypt -e production
247
290
  ```
248
291
 
249
292
  5. **Add to version control:**
293
+
250
294
  ```bash
251
295
  echo ".env.*" >> .gitignore
252
296
  echo "!*.gpg" >> .gitignore
@@ -257,6 +301,7 @@ git commit -m "Add encrypted production environment"
257
301
  ### Team Workflow
258
302
 
259
303
  1. **Clone repository and decrypt:**
304
+
260
305
  ```bash
261
306
  git clone <your-repo>
262
307
  cd <your-repo>
@@ -264,6 +309,7 @@ envx decrypt -e production
264
309
  ```
265
310
 
266
311
  2. **Make changes and re-encrypt:**
312
+
267
313
  ```bash
268
314
  # Edit .env.production
269
315
  envx encrypt -e production
@@ -271,6 +317,38 @@ git add .env.production.gpg
271
317
  git commit -m "Update production configuration"
272
318
  ```
273
319
 
320
+ ### Batch Operations
321
+
322
+ **Process all environments at once:**
323
+
324
+ ```bash
325
+ # Encrypt all environment files
326
+ envx encrypt --all
327
+
328
+ # Decrypt all environment files
329
+ envx decrypt --all
330
+
331
+ # Decrypt all with overwrite protection disabled
332
+ envx decrypt --all --overwrite
333
+ ```
334
+
335
+ **Benefits of using `--all`:**
336
+
337
+ - ✅ **Efficiency**: Process multiple environments in one command
338
+ - ✅ **Consistency**: Same passphrase/secret handling across all environments
339
+ - ✅ **Automation**: Perfect for CI/CD pipelines and scripts
340
+ - ✅ **Safety**: Each environment is processed independently - failures in one don't stop others
341
+ - ✅ **Reporting**: Comprehensive summary showing results for each environment
342
+
343
+ **Key Features of `--all` Flag:**
344
+
345
+ - **Sequential Processing**: Environments are processed one by one to avoid resource conflicts
346
+ - **Independent Operations**: Failure in one environment doesn't stop processing of others
347
+ - **Smart Passphrase Resolution**: Uses provided passphrase, environment-specific secrets, or prompts as needed
348
+ - **Comprehensive Reporting**: Shows detailed results for each environment plus overall summary
349
+ - **Safety Checks**: Validates compatibility with other flags (incompatible with `--environment` and `--interactive`)
350
+ - **Flexible Configuration**: Works with all existing options like `--passphrase`, `--secret`, `--cwd`, and `--overwrite`
351
+
274
352
  ## Configuration
275
353
 
276
354
  ### `.envrc` File
@@ -289,6 +367,7 @@ export PRODUCTION_SECRET="your-production-secret"
289
367
  EnvX follows the convention: `<STAGE>_SECRET`
290
368
 
291
369
  Examples:
370
+
292
371
  - `DEVELOPMENT_SECRET`
293
372
  - `STAGING_SECRET`
294
373
  - `PRODUCTION_SECRET`
@@ -342,6 +421,7 @@ your-project/
342
421
  EnvX works great with [direnv](https://direnv.net/) for automatic environment loading:
343
422
 
344
423
  1. **Install direnv:**
424
+
345
425
  ```bash
346
426
  # macOS
347
427
  brew install direnv
@@ -351,6 +431,7 @@ sudo apt install direnv
351
431
  ```
352
432
 
353
433
  2. **Add to your shell profile:**
434
+
354
435
  ```bash
355
436
  # For bash
356
437
  echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
@@ -360,6 +441,7 @@ echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
360
441
  ```
361
442
 
362
443
  3. **Allow direnv in your project:**
444
+
363
445
  ```bash
364
446
  direnv allow
365
447
  ```
@@ -371,17 +453,20 @@ Now your secrets will be automatically loaded when you enter the project directo
371
453
  ### GPG Issues
372
454
 
373
455
  **Problem:** `gpg: command not found`
456
+
374
457
  ```bash
375
458
  # Install GPG (see Prerequisites section)
376
459
  ```
377
460
 
378
461
  **Problem:** `gpg: decryption failed: Bad session key`
462
+
379
463
  ```bash
380
464
  # Wrong passphrase - try again or check your .envrc file
381
465
  envx decrypt -e production
382
466
  ```
383
467
 
384
468
  **Problem:** `gpg: can't connect to the agent`
469
+
385
470
  ```bash
386
471
  # Restart GPG agent
387
472
  gpgconf --kill gpg-agent
@@ -391,6 +476,7 @@ gpgconf --launch gpg-agent
391
476
  ### Permission Issues
392
477
 
393
478
  **Problem:** `EACCES: permission denied`
479
+
394
480
  ```bash
395
481
  # Check file permissions
396
482
  ls -la .env.*
@@ -400,6 +486,7 @@ chmod 644 .env.*
400
486
  ### File Not Found
401
487
 
402
488
  **Problem:** `Template file not found`
489
+
403
490
  ```bash
404
491
  # Check if template exists
405
492
  ls -la .env.example
@@ -460,16 +547,18 @@ The test suite prioritizes **essential functionality** over comprehensive covera
460
547
 
461
548
  ### Test Coverage
462
549
 
463
- **Current Status**: ✅ 95 tests passing, ~7s execution time
550
+ **Current Status**: ✅ 120 tests passing, ~11s execution time
464
551
 
465
- - **Core Tests**: 82 tests covering essential functionality
552
+ - **Core Tests**: 104 tests covering essential functionality
466
553
  - Schema validation: 25 tests (command input validation)
467
554
  - File utilities: 39 tests (path manipulation, secret generation)
468
- - Command logic: 18 tests (workflow patterns and decision logic)
555
+ - Command logic: 25 tests (workflow patterns and decision logic)
556
+ - All-flag functionality: 15 tests (batch operations, error handling)
469
557
 
470
- - **Integration Tests**: 13 tests covering real CLI usage
558
+ - **Integration Tests**: 16 tests covering real CLI usage
471
559
  - Help/version commands
472
560
  - Create command functionality
561
+ - All-flag compatibility testing
473
562
  - Error handling scenarios
474
563
  - Environment validation
475
564
 
@@ -480,7 +569,8 @@ __tests__/
480
569
  ├── core/ # Essential functionality tests
481
570
  │ ├── schemas.test.ts # Input validation for all commands
482
571
  │ ├── file.test.ts # File utilities and path manipulation
483
- └── commands.test.ts # Command workflow logic patterns
572
+ ├── commands.test.ts # Command workflow logic patterns
573
+ │ └── all-flag.test.ts # Batch operations and --all flag functionality
484
574
  └── integration/ # End-to-end CLI tests
485
575
  └── cli.test.ts # Real CLI execution scenarios
486
576
  ```
@@ -547,4 +637,4 @@ MIT © [rahulretnan](https://github.com/rahulretnan)
547
637
 
548
638
  **Made with ❤️ by developers, for developers.**
549
639
 
550
- *Remember: Security is not a feature, it's a requirement. EnvX helps you maintain security without sacrificing developer experience.*
640
+ _Remember: Security is not a feature, it's a requirement. EnvX helps you maintain security without sacrificing developer experience._
@@ -1,3 +1,3 @@
1
- import { Command } from "commander";
1
+ import { Command } from 'commander';
2
2
  export declare const createCreateCommand: () => Command;
3
3
  //# sourceMappingURL=create.d.ts.map
@@ -12,14 +12,14 @@ const exec_1 = require("../utils/exec");
12
12
  const file_1 = require("../utils/file");
13
13
  const interactive_1 = require("../utils/interactive");
14
14
  const createCreateCommand = () => {
15
- const command = new commander_1.Command("create");
15
+ const command = new commander_1.Command('create');
16
16
  command
17
- .description("Create new environment files")
18
- .option("-e, --environment <env>", "Environment name (e.g., development, staging, production)")
19
- .option("-t, --template <path>", "Template file path to use as base")
20
- .option("-c, --cwd <path>", "Working directory path")
21
- .option("-i, --interactive", "Interactive mode for creating multiple environments")
22
- .option("--overwrite", "Overwrite existing files without confirmation")
17
+ .description('Create new environment files')
18
+ .option('-e, --environment <env>', 'Environment name (e.g., development, staging, production)')
19
+ .option('-t, --template <path>', 'Template file path to use as base')
20
+ .option('-c, --cwd <path>', 'Working directory path')
21
+ .option('-i, --interactive', 'Interactive mode for creating multiple environments')
22
+ .option('--overwrite', 'Overwrite existing files without confirmation')
23
23
  .action(async (options) => {
24
24
  try {
25
25
  await executeCreate(options);
@@ -33,11 +33,11 @@ const createCreateCommand = () => {
33
33
  };
34
34
  exports.createCreateCommand = createCreateCommand;
35
35
  async function executeCreate(rawOptions) {
36
- exec_1.CliUtils.header("Environment File Creation");
36
+ exec_1.CliUtils.header('Environment File Creation');
37
37
  const cwd = rawOptions.cwd || exec_1.ExecUtils.getCurrentDir();
38
38
  const existingEnvironments = await file_1.FileUtils.findAllEnvironments(cwd);
39
39
  if (existingEnvironments.length > 0) {
40
- exec_1.CliUtils.info(`Existing environments: ${existingEnvironments.map((env) => exec_1.CliUtils.formatEnvironment(env)).join(", ")}`);
40
+ exec_1.CliUtils.info(`Existing environments: ${existingEnvironments.map(env => exec_1.CliUtils.formatEnvironment(env)).join(', ')}`);
41
41
  }
42
42
  let environment = rawOptions.environment;
43
43
  let template = rawOptions.template;
@@ -46,31 +46,32 @@ async function executeCreate(rawOptions) {
46
46
  return;
47
47
  }
48
48
  if (!environment) {
49
- environment = await interactive_1.InteractiveUtils.promptEnvironmentName("Enter environment name:");
49
+ environment = await interactive_1.InteractiveUtils.promptEnvironmentName('Enter environment name:');
50
50
  }
51
51
  if (!file_1.FileUtils.isValidEnvironmentName(environment)) {
52
- throw new Error("Environment name can only contain letters, numbers, hyphens, and underscores");
52
+ throw new Error('Environment name can only contain letters, numbers, hyphens, and underscores');
53
53
  }
54
- const options = (0, schemas_1.validateCreateOptions)({
54
+ (0, schemas_1.validateCreateOptions)({
55
55
  environment,
56
56
  template,
57
57
  cwd,
58
+ overwrite: rawOptions.overwrite,
58
59
  });
59
60
  if (existingEnvironments.includes(environment)) {
60
61
  exec_1.CliUtils.warning(`Environment '${environment}' already exists`);
61
62
  const envFiles = await file_1.FileUtils.findEnvFiles(environment, cwd);
62
63
  if (envFiles.length > 0) {
63
- console.log("Existing files:");
64
- envFiles.forEach((file) => {
64
+ console.log('Existing files:');
65
+ envFiles.forEach(file => {
65
66
  const displayPath = file.encrypted
66
67
  ? file_1.FileUtils.getEncryptedPath(file.path)
67
68
  : file.path;
68
69
  console.log(` • ${exec_1.CliUtils.formatPath(displayPath, cwd)}`);
69
70
  });
70
71
  if (!rawOptions.overwrite) {
71
- const confirm = await interactive_1.InteractiveUtils.confirmOperation("Do you want to create additional files for this environment?", false);
72
+ const confirm = await interactive_1.InteractiveUtils.confirmOperation('Do you want to create additional files for this environment?', false);
72
73
  if (!confirm) {
73
- exec_1.CliUtils.info("Operation cancelled.");
74
+ exec_1.CliUtils.info('Operation cancelled.');
74
75
  return;
75
76
  }
76
77
  }
@@ -90,7 +91,7 @@ async function executeCreate(rawOptions) {
90
91
  if ((await file_1.FileUtils.fileExists(envFilePath)) && !rawOptions.overwrite) {
91
92
  const confirm = await interactive_1.InteractiveUtils.confirmOperation(`File ${chalk_1.default.cyan(relativePath)} already exists. Overwrite?`, false);
92
93
  if (!confirm) {
93
- exec_1.CliUtils.info("Operation cancelled.");
94
+ exec_1.CliUtils.info('Operation cancelled.');
94
95
  return;
95
96
  }
96
97
  }
@@ -100,10 +101,10 @@ async function executeCreate(rawOptions) {
100
101
  if (result.success) {
101
102
  exec_1.CliUtils.success(`Created: ${chalk_1.default.cyan(relativePath)}`);
102
103
  console.log();
103
- exec_1.CliUtils.info("Next steps:");
104
+ exec_1.CliUtils.info('Next steps:');
104
105
  console.log(chalk_1.default.gray(`• Edit ${relativePath} and add your environment variables`));
105
106
  console.log(chalk_1.default.gray(`• Use "envx encrypt -e ${environment}" to encrypt the file`));
106
- console.log(chalk_1.default.gray("• Add the encrypted .gpg file to version control"));
107
+ console.log(chalk_1.default.gray('• Add the encrypted .gpg file to version control'));
107
108
  }
108
109
  else {
109
110
  exec_1.CliUtils.error(result.message);
@@ -117,36 +118,36 @@ async function executeCreate(rawOptions) {
117
118
  }
118
119
  }
119
120
  async function executeInteractiveCreate(cwd, existingEnvironments, template, overwrite) {
120
- exec_1.CliUtils.subheader("Interactive Environment Creation");
121
+ exec_1.CliUtils.subheader('Interactive Environment Creation');
121
122
  const commonEnvironments = [
122
- "development",
123
- "staging",
124
- "production",
125
- "local",
126
- "test",
123
+ 'development',
124
+ 'staging',
125
+ 'production',
126
+ 'local',
127
+ 'test',
127
128
  ];
128
- const suggestedEnvironments = commonEnvironments.filter((env) => !existingEnvironments.includes(env));
129
+ const suggestedEnvironments = commonEnvironments.filter(env => !existingEnvironments.includes(env));
129
130
  if (suggestedEnvironments.length > 0) {
130
- exec_1.CliUtils.info("Suggested environments:");
131
- suggestedEnvironments.forEach((env) => {
131
+ exec_1.CliUtils.info('Suggested environments:');
132
+ suggestedEnvironments.forEach(env => {
132
133
  console.log(` • ${exec_1.CliUtils.formatEnvironment(env)}`);
133
134
  });
134
135
  console.log();
135
136
  }
136
- const { createMode } = (await interactive_1.InteractiveUtils.confirmOperation("Do you want to select from suggested environments?"))
137
- ? { createMode: "suggested" }
138
- : { createMode: "custom" };
137
+ const { createMode } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to select from suggested environments?'))
138
+ ? { createMode: 'suggested' }
139
+ : { createMode: 'custom' };
139
140
  let environmentsToCreate = [];
140
- if (createMode === "suggested" && suggestedEnvironments.length > 0) {
141
- environmentsToCreate = await interactive_1.InteractiveUtils.selectMultipleEnvironments(suggestedEnvironments, "Select environments to create:");
141
+ if (createMode === 'suggested' && suggestedEnvironments.length > 0) {
142
+ environmentsToCreate = await interactive_1.InteractiveUtils.selectMultipleEnvironments(suggestedEnvironments, 'Select environments to create:');
142
143
  }
143
- const { addCustom } = (await interactive_1.InteractiveUtils.confirmOperation("Do you want to add custom environments?", createMode === "custom"))
144
+ const { addCustom } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to add custom environments?', createMode === 'custom'))
144
145
  ? { addCustom: true }
145
146
  : { addCustom: false };
146
147
  if (addCustom) {
147
148
  let addingMore = true;
148
149
  while (addingMore) {
149
- const newEnv = await interactive_1.InteractiveUtils.promptEnvironmentName("Enter environment name:");
150
+ const newEnv = await interactive_1.InteractiveUtils.promptEnvironmentName('Enter environment name:');
150
151
  if (!environmentsToCreate.includes(newEnv) &&
151
152
  !existingEnvironments.includes(newEnv)) {
152
153
  environmentsToCreate.push(newEnv);
@@ -154,7 +155,7 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
154
155
  }
155
156
  else if (existingEnvironments.includes(newEnv)) {
156
157
  exec_1.CliUtils.warning(`Environment ${exec_1.CliUtils.formatEnvironment(newEnv)} already exists`);
157
- const confirm = await interactive_1.InteractiveUtils.confirmOperation("Do you want to create files for this environment anyway?");
158
+ const confirm = await interactive_1.InteractiveUtils.confirmOperation('Do you want to create files for this environment anyway?');
158
159
  if (confirm) {
159
160
  environmentsToCreate.push(newEnv);
160
161
  }
@@ -162,22 +163,22 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
162
163
  else {
163
164
  exec_1.CliUtils.warning(`Environment ${exec_1.CliUtils.formatEnvironment(newEnv)} already in creation list`);
164
165
  }
165
- const { continueAdding } = (await interactive_1.InteractiveUtils.confirmOperation("Do you want to add another environment?", false))
166
+ const { continueAdding } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to add another environment?', false))
166
167
  ? { continueAdding: true }
167
168
  : { continueAdding: false };
168
169
  addingMore = continueAdding;
169
170
  }
170
171
  }
171
172
  if (environmentsToCreate.length === 0) {
172
- exec_1.CliUtils.warning("No environments selected for creation.");
173
+ exec_1.CliUtils.warning('No environments selected for creation.');
173
174
  return;
174
175
  }
175
176
  if (!template) {
176
- const { useTemplate } = (await interactive_1.InteractiveUtils.confirmOperation("Do you want to use a template file?", false))
177
+ const { useTemplate } = (await interactive_1.InteractiveUtils.confirmOperation('Do you want to use a template file?', false))
177
178
  ? { useTemplate: true }
178
179
  : { useTemplate: false };
179
180
  if (useTemplate) {
180
- const commonTemplates = [".env.example", ".env.template", ".env.sample"];
181
+ const commonTemplates = ['.env.example', '.env.template', '.env.sample'];
181
182
  const foundTemplates = [];
182
183
  for (const templateName of commonTemplates) {
183
184
  const templatePath = path_1.default.join(cwd, templateName);
@@ -186,9 +187,9 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
186
187
  }
187
188
  }
188
189
  if (foundTemplates.length > 0) {
189
- const { templateChoice } = (await interactive_1.InteractiveUtils.selectFiles([...foundTemplates, "Enter custom path"], "Select template file:"));
190
- if (templateChoice === "Enter custom path") {
191
- const { customTemplate } = (await interactive_1.InteractiveUtils.promptEnvironmentName("Enter template file path:"));
190
+ const { templateChoice } = (await interactive_1.InteractiveUtils.selectFiles([...foundTemplates, 'Enter custom path'], 'Select template file:'));
191
+ if (templateChoice === 'Enter custom path') {
192
+ const { customTemplate } = (await interactive_1.InteractiveUtils.promptEnvironmentName('Enter template file path:'));
192
193
  template = customTemplate;
193
194
  }
194
195
  else {
@@ -196,7 +197,7 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
196
197
  }
197
198
  }
198
199
  else {
199
- const { customTemplate } = (await interactive_1.InteractiveUtils.promptEnvironmentName("Enter template file path:"));
200
+ const { customTemplate } = (await interactive_1.InteractiveUtils.promptEnvironmentName('Enter template file path:'));
200
201
  template = customTemplate;
201
202
  }
202
203
  if (template) {
@@ -215,20 +216,20 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
215
216
  }
216
217
  }
217
218
  console.log();
218
- exec_1.CliUtils.subheader("Creation Summary");
219
+ exec_1.CliUtils.subheader('Creation Summary');
219
220
  console.log(`Will create ${environmentsToCreate.length} environment file(s):`);
220
- environmentsToCreate.forEach((env) => {
221
+ environmentsToCreate.forEach(env => {
221
222
  console.log(` • .env.${exec_1.CliUtils.formatEnvironment(env)}`);
222
223
  });
223
224
  if (template) {
224
225
  console.log(`Using template: ${exec_1.CliUtils.formatPath(template, cwd)}`);
225
226
  }
226
- const confirm = await interactive_1.InteractiveUtils.confirmOperation("Create these environment files?");
227
+ const confirm = await interactive_1.InteractiveUtils.confirmOperation('Create these environment files?');
227
228
  if (!confirm) {
228
- exec_1.CliUtils.info("Operation cancelled.");
229
+ exec_1.CliUtils.info('Operation cancelled.');
229
230
  return;
230
231
  }
231
- exec_1.CliUtils.subheader("Creating Files");
232
+ exec_1.CliUtils.subheader('Creating Files');
232
233
  let successCount = 0;
233
234
  let errorCount = 0;
234
235
  for (const environment of environmentsToCreate.sort()) {
@@ -240,7 +241,7 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
240
241
  if ((await file_1.FileUtils.fileExists(envFilePath)) && !overwrite) {
241
242
  const fileConfirm = await interactive_1.InteractiveUtils.confirmOperation(`File already exists. Overwrite ${relativePath}?`, false);
242
243
  if (!fileConfirm) {
243
- exec_1.CliUtils.warning("Skipped existing file");
244
+ exec_1.CliUtils.warning('Skipped existing file');
244
245
  continue;
245
246
  }
246
247
  }
@@ -260,7 +261,7 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
260
261
  }
261
262
  }
262
263
  console.log();
263
- exec_1.CliUtils.subheader("Creation Results");
264
+ exec_1.CliUtils.subheader('Creation Results');
264
265
  if (successCount > 0) {
265
266
  exec_1.CliUtils.success(`Successfully created ${successCount} file(s)`);
266
267
  }
@@ -269,8 +270,8 @@ async function executeInteractiveCreate(cwd, existingEnvironments, template, ove
269
270
  }
270
271
  if (successCount > 0) {
271
272
  console.log();
272
- exec_1.CliUtils.info("Next steps:");
273
- console.log(chalk_1.default.gray("• Edit the created files and add your environment variables"));
273
+ exec_1.CliUtils.info('Next steps:');
274
+ console.log(chalk_1.default.gray('• Edit the created files and add your environment variables'));
274
275
  console.log(chalk_1.default.gray('• Use "envx encrypt" to encrypt sensitive files'));
275
276
  console.log(chalk_1.default.gray('• Use "envx interactive" to set up .envrc with secrets'));
276
277
  }