envilder 0.5.1 → 0.5.3
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/README.md +83 -34
- package/lib/{cli/cli.d.ts → Cli.d.ts} +1 -1
- package/lib/Cli.d.ts.map +1 -0
- package/lib/{cli/cli.js → Cli.js} +7 -3
- package/lib/Cli.js.map +1 -0
- package/lib/cli/application/EnvilderHandler.d.ts +18 -0
- package/lib/cli/application/EnvilderHandler.d.ts.map +1 -0
- package/lib/cli/application/EnvilderHandler.js +64 -0
- package/lib/cli/application/EnvilderHandler.js.map +1 -0
- package/lib/cli/domain/EnvilderBuilder.d.ts +14 -0
- package/lib/cli/domain/EnvilderBuilder.d.ts.map +1 -0
- package/lib/cli/domain/EnvilderBuilder.js +41 -0
- package/lib/cli/domain/EnvilderBuilder.js.map +1 -0
- package/lib/cli/domain/ports/IEnvFileManager.d.ts +6 -0
- package/lib/cli/domain/ports/IEnvFileManager.d.ts.map +1 -0
- package/lib/cli/domain/ports/IEnvFileManager.js +2 -0
- package/lib/cli/domain/ports/IEnvFileManager.js.map +1 -0
- package/lib/cli/domain/ports/ISecretProvider.d.ts +4 -0
- package/lib/cli/domain/ports/ISecretProvider.d.ts.map +1 -0
- package/lib/cli/domain/ports/ISecretProvider.js +2 -0
- package/lib/cli/domain/ports/ISecretProvider.js.map +1 -0
- package/lib/cli/infrastructure/AwsSsmStoreSecrets.d.ts +8 -0
- package/lib/cli/infrastructure/AwsSsmStoreSecrets.d.ts.map +1 -0
- package/lib/cli/infrastructure/AwsSsmStoreSecrets.js +26 -0
- package/lib/cli/infrastructure/AwsSsmStoreSecrets.js.map +1 -0
- package/lib/cli/infrastructure/EnvFileManager.d.ts +7 -0
- package/lib/cli/infrastructure/EnvFileManager.d.ts.map +1 -0
- package/lib/cli/infrastructure/EnvFileManager.js +37 -0
- package/lib/cli/infrastructure/EnvFileManager.js.map +1 -0
- package/package.json +38 -27
- package/lib/cli/cli.d.ts.map +0 -1
- package/lib/cli/cli.js.map +0 -1
- package/lib/index.d.ts +0 -11
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -116
- package/lib/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
<br>
|
|
3
3
|
<img src="https://github.com/user-attachments/assets/96bf1efa-7d21-440a-a414-3a20e7f9a1f1" alt="Envilder">
|
|
4
|
-
<br>
|
|
5
|
-
Envilder
|
|
6
|
-
<br>
|
|
7
4
|
</h1>
|
|
8
5
|
|
|
9
|
-
<h4 align="center">
|
|
6
|
+
<h4 align="center">A CLI that securely centralizes your environment variables from AWS SSM as a single source of truth</h4>
|
|
10
7
|
|
|
11
8
|
<p align="center">
|
|
12
9
|
<a href="https://www.npmjs.com/package/envilder">
|
|
@@ -20,11 +17,17 @@
|
|
|
20
17
|
</a>
|
|
21
18
|
</p>
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
## 🌟 Key benefits
|
|
21
|
+
|
|
22
|
+
- **🔒 Strict access control** - AWS IAM policies control who accesses which secrets (dev vs prod)
|
|
23
|
+
- **📊 Full audit trail** - All parameter access is logged in CloudTrail for compliance requirements
|
|
24
|
+
- **🧩 Single source of truth** - No more copying .env files from Notion or emails - SSM is your only source
|
|
25
|
+
- **🔁 Idempotent operations** - Overwrites values in your `.env` file *only* for variables defined in your mapping
|
|
26
|
+
file, using the latest from SSM. Variables not in the mapping file are preserved. Safe for automation.
|
|
27
|
+
- **⚙️ Environment-aware** - Use templates like `/project/${ENV}/DB_PASSWORD` to dynamically fetch the right secrets
|
|
28
|
+
- **🧱 No extra infrastructure** - Uses AWS SSM's existing reliability instead of additional secret managers
|
|
26
29
|
|
|
27
|
-
## ⚡ Quick
|
|
30
|
+
## ⚡ Quick start
|
|
28
31
|
|
|
29
32
|
```bash
|
|
30
33
|
# Install globally
|
|
@@ -37,7 +40,7 @@ echo '{"DB_PASSWORD": "/my-app/db/password"}' > param-map.json
|
|
|
37
40
|
envilder --map=param-map.json --envfile=.env
|
|
38
41
|
```
|
|
39
42
|
|
|
40
|
-
## 🤔 What
|
|
43
|
+
## 🤔 What problem does Envilder solve?
|
|
41
44
|
|
|
42
45
|
<table>
|
|
43
46
|
<tr>
|
|
@@ -72,23 +75,23 @@ envilder --map=param-map.json --envfile=.env
|
|
|
72
75
|
|
|
73
76
|
## 💡 Why Envilder?
|
|
74
77
|
|
|
75
|
-
- 🔐 **No
|
|
76
|
-
- 🤖 **Automate
|
|
77
|
-
- 🔄 **Always in
|
|
78
|
-
- 🏎️ **Fast to
|
|
79
|
-
- 🪶 **Simple but
|
|
78
|
+
- 🔐 **No more secrets in git** - Store credentials in AWS SSM Parameter Store instead of version control
|
|
79
|
+
- 🤖 **Automate everything** - One command to generate your `.env` files across all environments
|
|
80
|
+
- 🔄 **Always in sync** - Keep your local, dev, and production environments consistent
|
|
81
|
+
- 🏎️ **Fast to set up** - Configure once, then generate `.env` files with a single command
|
|
82
|
+
- 🪶 **Simple but powerful** - Easy interface with support for encrypted parameters and multiple AWS profiles
|
|
80
83
|
|
|
81
|
-
## 🎯 Perfect for
|
|
84
|
+
## 🎯 Perfect for teams
|
|
82
85
|
|
|
83
86
|
Envilder is the tool you need if you:
|
|
84
87
|
|
|
85
|
-
- 👥 **Work in a
|
|
86
|
-
- 🔑 **Deal with API
|
|
87
|
-
- ⚙️ **Run CI/CD
|
|
88
|
-
- ☁️ **Use AWS
|
|
89
|
-
- 🌐 **Manage
|
|
88
|
+
- 👥 **Work in a development team** - Ensure everyone has the same environment without sharing raw secrets
|
|
89
|
+
- 🔑 **Deal with API keys & tokens** - Securely store and retrieve sensitive credentials
|
|
90
|
+
- ⚙️ **Run CI/CD pipelines** - Automatically generate environment files during deployments
|
|
91
|
+
- ☁️ **Use AWS already** - Leverage your existing AWS infrastructure more effectively
|
|
92
|
+
- 🌐 **Manage multiple environments** - Switch easily between dev, staging, and production
|
|
90
93
|
|
|
91
|
-
## 🔍 How
|
|
94
|
+
## 🔍 How it works (simple!)
|
|
92
95
|
|
|
93
96
|
```mermaid
|
|
94
97
|
graph LR
|
|
@@ -98,19 +101,19 @@ graph LR
|
|
|
98
101
|
E[SSM Parameters] --> B
|
|
99
102
|
```
|
|
100
103
|
|
|
101
|
-
1. 📖 **Define
|
|
104
|
+
1. 📖 **Define your mapping** - Simple JSON mapping env vars to SSM paths
|
|
102
105
|
2. 🚀 **Run Envilder** - One command with your mapping file
|
|
103
|
-
3. 🔄 **Auto-
|
|
104
|
-
4. 💾 **Get
|
|
106
|
+
3. 🔄 **Auto-fetch from AWS** - Retrieves values using your AWS credentials
|
|
107
|
+
4. 💾 **Get your .env file** - Ready to use in your project
|
|
105
108
|
|
|
106
109
|
## ⚙️ Prerequisites
|
|
107
110
|
|
|
108
111
|
You'll need:
|
|
109
112
|
|
|
110
113
|
- ✅ **AWS CLI** - Installed and configured with proper permissions to access SSM Parameter Store
|
|
111
|
-
- ✅ **Node.js** - Version
|
|
114
|
+
- ✅ **Node.js** - Version 20.0.0 or higher (as specified in `package.json`)
|
|
112
115
|
|
|
113
|
-
### AWS CLI
|
|
116
|
+
### AWS CLI setup
|
|
114
117
|
|
|
115
118
|
1. Install the AWS CLI by following the [official instructions](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
|
|
116
119
|
2. After installation, configure the AWS CLI:
|
|
@@ -132,9 +135,6 @@ You'll need:
|
|
|
132
135
|
```bash
|
|
133
136
|
# Using npm
|
|
134
137
|
npm install -g envilder
|
|
135
|
-
|
|
136
|
-
# Using yarn
|
|
137
|
-
yarn global add envilder
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
## 🚀 Usage
|
|
@@ -149,7 +149,7 @@ envilder --map=<mapping-file> --envfile=<output-file> [--profile=<aws-profile>]
|
|
|
149
149
|
| `--envfile` | Path to output .env file (required) |
|
|
150
150
|
| `--profile` | AWS CLI profile to use (optional) |
|
|
151
151
|
|
|
152
|
-
## 🔧 Quick
|
|
152
|
+
## 🔧 Quick example
|
|
153
153
|
|
|
154
154
|
1. Create a mapping file `param-map.json`:
|
|
155
155
|
|
|
@@ -172,7 +172,7 @@ envilder --map=<mapping-file> --envfile=<output-file> [--profile=<aws-profile>]
|
|
|
172
172
|
envilder --map=param-map.json --envfile=.env --profile=dev-account
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
## 🌐 Working with
|
|
175
|
+
## 🌐 Working with multiple AWS profiles
|
|
176
176
|
|
|
177
177
|
For multiple AWS accounts or environments, configure different profiles in your AWS credentials file:
|
|
178
178
|
|
|
@@ -203,17 +203,66 @@ or `%USERPROFILE%\.aws\credentials` on Windows):
|
|
|
203
203
|
envilder --map=param-map.json --envfile=.env.production --profile=prod-account
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
-
##
|
|
206
|
+
## 🛠️ Advanced usage: environment-specific parameters
|
|
207
|
+
|
|
208
|
+
Envilder works brilliantly with environment variables for dynamic parameter paths:
|
|
209
|
+
|
|
210
|
+
1. Set up your SSM parameters with environment-specific paths:
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
/project/dev/DB_PASSWORD
|
|
214
|
+
/project/stage/DB_PASSWORD
|
|
215
|
+
/project/prod/DB_PASSWORD
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
2. Create a template-based mapping file `env-map.json`:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"DB_PASSWORD": "/project/${ENV}/DB_PASSWORD"
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
3. Generate environment-specific .env files:
|
|
227
|
+
|
|
228
|
+
```powershell
|
|
229
|
+
# Development
|
|
230
|
+
$env:ENV = "dev"
|
|
231
|
+
envilder --map=env-map.json --envfile=.env.dev
|
|
232
|
+
|
|
233
|
+
# Staging
|
|
234
|
+
$env:ENV = "stage"
|
|
235
|
+
envilder --map=env-map.json --envfile=.env.stage
|
|
236
|
+
|
|
237
|
+
# Production
|
|
238
|
+
$env:ENV = "prod"
|
|
239
|
+
envilder --map=env-map.json --envfile=.env.prod --profile=prod-account
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
This approach ensures the right variables are pulled for each environment with minimal configuration.
|
|
243
|
+
|
|
244
|
+
## 📂 Sample `.env` output
|
|
207
245
|
|
|
208
246
|
```ini
|
|
209
247
|
SECRET_TOKEN=mockedEmail@example.com
|
|
210
248
|
SECRET_KEY=mockedPassword
|
|
211
249
|
```
|
|
212
250
|
|
|
213
|
-
##
|
|
251
|
+
## 🎯 Why use Envilder in practice?
|
|
252
|
+
|
|
253
|
+
Envilder eliminates common problems in development teams:
|
|
254
|
+
|
|
255
|
+
- **🛑 No more "it works on my machine"** - Everyone uses the exact same environment variables from the same source
|
|
256
|
+
- **🔄 Always fresh credentials** - Update a secret in SSM and everyone gets it automatically on next run
|
|
257
|
+
- **🛡️ Access control built-in** - Developers only see dev secrets, CI/CD systems see what they need
|
|
258
|
+
- **🧠 Zero mental overhead** - No need to remember which variables are needed - the mapping defines everything
|
|
259
|
+
- **🚫 No more sharing secrets** - Stop pasting credentials in Slack, email, or Notion documents
|
|
260
|
+
- **📋 Compliance ready** - All accesses are logged in AWS CloudTrail for auditing
|
|
261
|
+
|
|
262
|
+
## 🧪 Running tests
|
|
214
263
|
|
|
215
264
|
```bash
|
|
216
|
-
|
|
265
|
+
npm test
|
|
217
266
|
```
|
|
218
267
|
|
|
219
268
|
Check the current coverage report: [Coverage Report](https://macalbert.github.io/envilder/)
|
package/lib/Cli.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cli.d.ts","sourceRoot":"","sources":["../src/Cli.ts"],"names":[],"mappings":";AA6CA;;;;;;GAMG;AACH,wBAAsB,IAAI,kBA0BzB"}
|
|
@@ -12,7 +12,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
12
12
|
import { dirname, join } from 'node:path';
|
|
13
13
|
import { fileURLToPath } from 'node:url';
|
|
14
14
|
import { Command } from 'commander';
|
|
15
|
-
import {
|
|
15
|
+
import { EnvilderBuilder } from './cli/domain/EnvilderBuilder.js';
|
|
16
16
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
17
|
const __dirname = dirname(__filename);
|
|
18
18
|
/**
|
|
@@ -65,7 +65,11 @@ export function main() {
|
|
|
65
65
|
if (!options.map || !options.envfile) {
|
|
66
66
|
throw new Error('Missing required arguments: --map and --envfile');
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
const envilder = EnvilderBuilder.build()
|
|
69
|
+
.withDefaultFileManager()
|
|
70
|
+
.withAwsProvider(options.profile)
|
|
71
|
+
.create();
|
|
72
|
+
yield envilder.run(options.map, options.envfile);
|
|
69
73
|
});
|
|
70
74
|
}
|
|
71
75
|
// Execute the CLI
|
|
@@ -73,4 +77,4 @@ main().catch((error) => {
|
|
|
73
77
|
console.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
|
|
74
78
|
console.error(error);
|
|
75
79
|
});
|
|
76
|
-
//# sourceMappingURL=
|
|
80
|
+
//# sourceMappingURL=Cli.js.map
|
package/lib/Cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cli.js","sourceRoot":"","sources":["../src/Cli.ts"],"names":[],"mappings":";;;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;GAKG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,QAAQ,GAAG,CAAC;IACrD,IAAI,UAAU,GAAG,QAAQ,CAAC;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACrD,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,sBAAsB;QACtB,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;YAC7B,yBAAyB;YACzB,MAAM;QACR,CAAC;QAED,UAAU,GAAG,SAAS,CAAC;QACvB,KAAK,EAAE,CAAC;IACV,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,eAAe,GACnB,eAAe,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,UAAgB,IAAI;;QACxB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;QAC9B,OAAO;aACJ,IAAI,CAAC,UAAU,CAAC;aAChB,WAAW,CAAC,2DAA2D,CAAC;aACxE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;aAC5B,cAAc,CACb,cAAc,EACd,yDAAyD,CAC1D;aACA,cAAc,CAAC,kBAAkB,EAAE,uCAAuC,CAAC;aAC3E,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;QAExD,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/B,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE;aACrC,sBAAsB,EAAE;aACxB,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC;aAChC,MAAM,EAAE,CAAC;QAEZ,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC;CAAA;AAED,kBAAkB;AAClB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IEnvFileManager } from '../domain/ports/IEnvFileManager';
|
|
2
|
+
import type { ISecretProvider } from '../domain/ports/ISecretProvider';
|
|
3
|
+
export declare class Envilder {
|
|
4
|
+
private keyVault;
|
|
5
|
+
private envFileManager;
|
|
6
|
+
constructor(keyVault: ISecretProvider, envFileManager: IEnvFileManager);
|
|
7
|
+
/**
|
|
8
|
+
* Orchestrates the process of fetching environment variable values from a key vault and writing them to a local environment file.
|
|
9
|
+
*
|
|
10
|
+
* Loads a parameter mapping from a JSON file, retrieves existing environment variables, fetches updated values from the key vault, merges them, and writes the result to the specified environment file.
|
|
11
|
+
*
|
|
12
|
+
* @param mapPath - Path to the JSON file mapping environment variable names to key vault parameter names.
|
|
13
|
+
* @param envFilePath - Path to the local environment file to read and update.
|
|
14
|
+
*/
|
|
15
|
+
run(mapPath: string, envFilePath: string): Promise<void>;
|
|
16
|
+
private fetchAndUpdateEnvVariables;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=EnvilderHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvilderHandler.d.ts","sourceRoot":"","sources":["../../../src/cli/application/EnvilderHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,cAAc,CAAkB;gBAE5B,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe;IAKtE;;;;;;;OAOG;IACG,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;YAYhC,0BAA0B;CAoCzC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export class Envilder {
|
|
11
|
+
constructor(keyVault, envFileManager) {
|
|
12
|
+
this.keyVault = keyVault;
|
|
13
|
+
this.envFileManager = envFileManager;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Orchestrates the process of fetching environment variable values from a key vault and writing them to a local environment file.
|
|
17
|
+
*
|
|
18
|
+
* Loads a parameter mapping from a JSON file, retrieves existing environment variables, fetches updated values from the key vault, merges them, and writes the result to the specified environment file.
|
|
19
|
+
*
|
|
20
|
+
* @param mapPath - Path to the JSON file mapping environment variable names to key vault parameter names.
|
|
21
|
+
* @param envFilePath - Path to the local environment file to read and update.
|
|
22
|
+
*/
|
|
23
|
+
run(mapPath, envFilePath) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const paramMap = this.envFileManager.loadParamMap(mapPath);
|
|
26
|
+
const existingEnvVariables = this.envFileManager.loadExistingEnvVariables(envFilePath);
|
|
27
|
+
const updatedEnvVariables = yield this.fetchAndUpdateEnvVariables(paramMap, existingEnvVariables);
|
|
28
|
+
this.envFileManager.writeEnvFile(envFilePath, updatedEnvVariables);
|
|
29
|
+
console.log(`Environment File generated at '${envFilePath}'`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
fetchAndUpdateEnvVariables(paramMap, existingEnvVariables) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
try {
|
|
35
|
+
const errors = [];
|
|
36
|
+
for (const [envVar, secretName] of Object.entries(paramMap)) {
|
|
37
|
+
try {
|
|
38
|
+
const value = yield this.keyVault.getSecret(secretName);
|
|
39
|
+
if (!value) {
|
|
40
|
+
console.error(`Warning: No value found for: '${secretName}'`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
existingEnvVariables[envVar] = value;
|
|
44
|
+
console.log(`${envVar}=${value.length > 10 ? '*'.repeat(value.length - 3) + value.slice(-3) : '*'.repeat(value.length)}`);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error(`Error fetching parameter: '${secretName}'`);
|
|
48
|
+
errors.push(`ParameterNotFound: ${secretName}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (errors.length > 0) {
|
|
52
|
+
throw new Error(`Some parameters could not be fetched:\n${errors.join('\n')}`);
|
|
53
|
+
}
|
|
54
|
+
return existingEnvVariables;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
58
|
+
console.error(`Failed to generate environment file: ${errorMessage}`);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=EnvilderHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvilderHandler.js","sourceRoot":"","sources":["../../../src/cli/application/EnvilderHandler.ts"],"names":[],"mappings":";;;;;;;;;AAGA,MAAM,OAAO,QAAQ;IAInB,YAAY,QAAyB,EAAE,cAA+B;QACpE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAED;;;;;;;OAOG;IACG,GAAG,CAAC,OAAe,EAAE,WAAmB;;YAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC3D,MAAM,oBAAoB,GACxB,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,WAAW,CAAC,CAAC;YAC5D,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAC/D,QAAQ,EACR,oBAAoB,CACrB,CAAC;YACF,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,kCAAkC,WAAW,GAAG,CAAC,CAAC;QAChE,CAAC;KAAA;IAEa,0BAA0B,CACtC,QAAgC,EAChC,oBAA4C;;YAE5C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAa,EAAE,CAAC;gBAC5B,KAAK,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC5D,IAAI,CAAC;wBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;wBACxD,IAAI,CAAC,KAAK,EAAE,CAAC;4BACX,OAAO,CAAC,KAAK,CAAC,iCAAiC,UAAU,GAAG,CAAC,CAAC;4BAC9D,SAAS;wBACX,CAAC;wBACD,oBAAoB,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;wBACrC,OAAO,CAAC,GAAG,CACT,GAAG,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAC7G,CAAC;oBACJ,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,UAAU,GAAG,CAAC,CAAC;wBAC3D,MAAM,CAAC,IAAI,CAAC,sBAAsB,UAAU,EAAE,CAAC,CAAC;oBAClD,CAAC;gBACH,CAAC;gBACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,IAAI,KAAK,CACb,0CAA0C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9D,CAAC;gBACJ,CAAC;gBAED,OAAO,oBAAoB,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACzD,OAAO,CAAC,KAAK,CAAC,wCAAwC,YAAY,EAAE,CAAC,CAAC;gBACtE,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KAAA;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Envilder } from '../application/EnvilderHandler.js';
|
|
2
|
+
import type { IEnvFileManager } from './ports/IEnvFileManager.js';
|
|
3
|
+
import type { ISecretProvider } from './ports/ISecretProvider.js';
|
|
4
|
+
export declare class EnvilderBuilder {
|
|
5
|
+
private provider?;
|
|
6
|
+
private fileManager?;
|
|
7
|
+
static build(): EnvilderBuilder;
|
|
8
|
+
withDefaultFileManager(): this;
|
|
9
|
+
withEnvFileManager(fileManager: IEnvFileManager): this;
|
|
10
|
+
withProvider(provider: ISecretProvider): this;
|
|
11
|
+
withAwsProvider(profile?: string): this;
|
|
12
|
+
create(): Envilder;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=EnvilderBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvilderBuilder.d.ts","sourceRoot":"","sources":["../../../src/cli/domain/EnvilderBuilder.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAG7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,CAAkB;IACnC,OAAO,CAAC,WAAW,CAAC,CAAkB;IAEtC,MAAM,CAAC,KAAK,IAAI,eAAe;IAI/B,sBAAsB,IAAI,IAAI;IAK9B,kBAAkB,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI;IAKtD,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAK7C,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAYvC,MAAM,IAAI,QAAQ;CAWnB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SSM } from '@aws-sdk/client-ssm';
|
|
2
|
+
import { fromIni } from '@aws-sdk/credential-providers';
|
|
3
|
+
import { Envilder } from '../application/EnvilderHandler.js';
|
|
4
|
+
import { AwsSsmSecretProvider } from '../infrastructure/AwsSsmStoreSecrets.js';
|
|
5
|
+
import { EnvFileManager } from '../infrastructure/EnvFileManager.js';
|
|
6
|
+
export class EnvilderBuilder {
|
|
7
|
+
static build() {
|
|
8
|
+
return new EnvilderBuilder();
|
|
9
|
+
}
|
|
10
|
+
withDefaultFileManager() {
|
|
11
|
+
this.fileManager = new EnvFileManager();
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
withEnvFileManager(fileManager) {
|
|
15
|
+
this.fileManager = fileManager;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
withProvider(provider) {
|
|
19
|
+
this.provider = provider;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
withAwsProvider(profile) {
|
|
23
|
+
const ssm = profile == null
|
|
24
|
+
? new SSM()
|
|
25
|
+
: new SSM({
|
|
26
|
+
credentials: fromIni({ profile: profile }),
|
|
27
|
+
});
|
|
28
|
+
this.provider = new AwsSsmSecretProvider(ssm);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
create() {
|
|
32
|
+
if (!this.provider) {
|
|
33
|
+
throw new Error('Secret provider must be specified');
|
|
34
|
+
}
|
|
35
|
+
if (!this.fileManager) {
|
|
36
|
+
throw new Error('Env file manager must be specified');
|
|
37
|
+
}
|
|
38
|
+
return new Envilder(this.provider, this.fileManager);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=EnvilderBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvilderBuilder.js","sourceRoot":"","sources":["../../../src/cli/domain/EnvilderBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAIrE,MAAM,OAAO,eAAe;IAI1B,MAAM,CAAC,KAAK;QACV,OAAO,IAAI,eAAe,EAAE,CAAC;IAC/B,CAAC;IAED,sBAAsB;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,cAAc,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB,CAAC,WAA4B;QAC7C,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,YAAY,CAAC,QAAyB;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe,CAAC,OAAgB;QAC9B,MAAM,GAAG,GACP,OAAO,IAAI,IAAI;YACb,CAAC,CAAC,IAAI,GAAG,EAAE;YACX,CAAC,CAAC,IAAI,GAAG,CAAC;gBACN,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;aACxB,CAAC,CAAC;QAE5B,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface IEnvFileManager {
|
|
2
|
+
loadParamMap(mapPath: string): Record<string, string>;
|
|
3
|
+
loadExistingEnvVariables(envFilePath: string): Record<string, string>;
|
|
4
|
+
writeEnvFile(envFilePath: string, envVariables: Record<string, string>): void;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=IEnvFileManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IEnvFileManager.d.ts","sourceRoot":"","sources":["../../../../src/cli/domain/ports/IEnvFileManager.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtE,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CAC/E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IEnvFileManager.js","sourceRoot":"","sources":["../../../../src/cli/domain/ports/IEnvFileManager.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISecretProvider.d.ts","sourceRoot":"","sources":["../../../../src/cli/domain/ports/ISecretProvider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISecretProvider.js","sourceRoot":"","sources":["../../../../src/cli/domain/ports/ISecretProvider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type SSM } from '@aws-sdk/client-ssm';
|
|
2
|
+
import type { ISecretProvider } from '../domain/ports/ISecretProvider';
|
|
3
|
+
export declare class AwsSsmSecretProvider implements ISecretProvider {
|
|
4
|
+
private ssm;
|
|
5
|
+
constructor(ssm: SSM);
|
|
6
|
+
getSecret(name: string): Promise<string | undefined>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=AwsSsmStoreSecrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsSsmStoreSecrets.d.ts","sourceRoot":"","sources":["../../../src/cli/infrastructure/AwsSsmStoreSecrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,GAAG,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,GAAG,CAAM;gBAEL,GAAG,EAAE,GAAG;IAId,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAQ3D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { GetParameterCommand } from '@aws-sdk/client-ssm';
|
|
11
|
+
export class AwsSsmSecretProvider {
|
|
12
|
+
constructor(ssm) {
|
|
13
|
+
this.ssm = ssm;
|
|
14
|
+
}
|
|
15
|
+
getSecret(name) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const command = new GetParameterCommand({
|
|
18
|
+
Name: name,
|
|
19
|
+
WithDecryption: true,
|
|
20
|
+
});
|
|
21
|
+
const { Parameter } = yield this.ssm.send(command);
|
|
22
|
+
return Parameter === null || Parameter === void 0 ? void 0 : Parameter.Value;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=AwsSsmStoreSecrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsSsmStoreSecrets.js","sourceRoot":"","sources":["../../../src/cli/infrastructure/AwsSsmStoreSecrets.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,mBAAmB,EAAY,MAAM,qBAAqB,CAAC;AAGpE,MAAM,OAAO,oBAAoB;IAG/B,YAAY,GAAQ;QAClB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAEK,SAAS,CAAC,IAAY;;YAC1B,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC;gBACtC,IAAI,EAAE,IAAI;gBACV,cAAc,EAAE,IAAI;aACrB,CAAC,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnD,OAAO,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,KAAK,CAAC;QAC1B,CAAC;KAAA;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IEnvFileManager } from '../domain/ports/IEnvFileManager';
|
|
2
|
+
export declare class EnvFileManager implements IEnvFileManager {
|
|
3
|
+
loadParamMap(mapPath: string): Record<string, string>;
|
|
4
|
+
loadExistingEnvVariables(envFilePath: string): Record<string, string>;
|
|
5
|
+
writeEnvFile(envFilePath: string, envVariables: Record<string, string>): void;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=EnvFileManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvFileManager.d.ts","sourceRoot":"","sources":["../../../src/cli/infrastructure/EnvFileManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,qBAAa,cAAe,YAAW,eAAe;IACpD,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUrD,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAWrE,YAAY,CACV,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,IAAI;CAYR"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as dotenv from 'dotenv';
|
|
3
|
+
export class EnvFileManager {
|
|
4
|
+
loadParamMap(mapPath) {
|
|
5
|
+
const content = fs.readFileSync(mapPath, 'utf-8');
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(content);
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
console.error(`Error parsing JSON from ${mapPath}`);
|
|
11
|
+
throw new Error(`Invalid JSON in parameter map file: ${mapPath}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
loadExistingEnvVariables(envFilePath) {
|
|
15
|
+
const envVariables = {};
|
|
16
|
+
if (!fs.existsSync(envFilePath)) {
|
|
17
|
+
return envVariables;
|
|
18
|
+
}
|
|
19
|
+
const existingEnvContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
20
|
+
const parsedEnv = dotenv.parse(existingEnvContent);
|
|
21
|
+
Object.assign(envVariables, parsedEnv);
|
|
22
|
+
return envVariables;
|
|
23
|
+
}
|
|
24
|
+
writeEnvFile(envFilePath, envVariables) {
|
|
25
|
+
const envContent = Object.entries(envVariables)
|
|
26
|
+
.map(([key, value]) => {
|
|
27
|
+
const escapedValue = value
|
|
28
|
+
.replace(/\\/g, '\\\\')
|
|
29
|
+
.replace(/(\r\n|\n|\r)/g, '\\n')
|
|
30
|
+
.replace(/"/g, '\\"');
|
|
31
|
+
return `${key}=${escapedValue}`;
|
|
32
|
+
})
|
|
33
|
+
.join('\n');
|
|
34
|
+
fs.writeFileSync(envFilePath, envContent);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=EnvFileManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvFileManager.js","sourceRoot":"","sources":["../../../src/cli/infrastructure/EnvFileManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,MAAM,OAAO,cAAc;IACzB,YAAY,CAAC,OAAe;QAC1B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,wBAAwB,CAAC,WAAmB;QAC1C,MAAM,YAAY,GAA2B,EAAE,CAAC;QAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,MAAM,kBAAkB,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACjE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACvC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,YAAY,CACV,WAAmB,EACnB,YAAoC;QAEpC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;aAC5C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACpB,MAAM,YAAY,GAAG,KAAK;iBACvB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;iBACtB,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC;iBAC/B,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACxB,OAAO,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAClC,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,34 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envilder",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "A CLI
|
|
5
|
-
"
|
|
6
|
-
".": {
|
|
7
|
-
"import": "./lib/index.js",
|
|
8
|
-
"types": "./lib/index.d.ts"
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
|
-
"main": "./lib/index.js",
|
|
3
|
+
"version": "0.5.3",
|
|
4
|
+
"description": "A CLI that securely centralizes your environment variables from AWS SSM as a single source of truth",
|
|
5
|
+
"main": "./lib/Cli.js",
|
|
12
6
|
"bin": {
|
|
13
|
-
"envilder": "lib/
|
|
7
|
+
"envilder": "lib/Cli.js"
|
|
14
8
|
},
|
|
15
9
|
"scripts": {
|
|
16
|
-
"clean": "
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"format": "
|
|
21
|
-
"format:write": "
|
|
22
|
-
"lint": "
|
|
23
|
-
"lint:fix": "
|
|
10
|
+
"clean": "jest --clearCache && npm cache clean --force && rimraf lib && rimraf coverage && rimraf node_modules",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"local:install": "npm run build && node --loader ts-node/esm scripts/pack-and-install.ts",
|
|
13
|
+
"local:test-run": "npm run build && node lib/cli/cli.js --map=tests/cli/sample/param-map.json --envfile=tests/cli/sample/autogenerated.env",
|
|
14
|
+
"format": "biome format",
|
|
15
|
+
"format:write": "biome format --write",
|
|
16
|
+
"lint": "secretlint \"**/*\" && biome check --write && tsc --noEmit",
|
|
17
|
+
"lint:fix": "biome lint --fix",
|
|
24
18
|
"test": "vitest run --reporter verbose --coverage",
|
|
25
|
-
"
|
|
26
|
-
"npm-
|
|
27
|
-
"npm-release-
|
|
28
|
-
"npm-release-
|
|
29
|
-
"npm-release-prerelease": "yarn version --new-version prerelease"
|
|
19
|
+
"npm-publish": "npm run lint && npm run build && npm run test && npm pack --dry-run && npm publish",
|
|
20
|
+
"npm-release-patch": "npm version patch",
|
|
21
|
+
"npm-release-minor": "npm version minor",
|
|
22
|
+
"npm-release-prerelease": "npm version prerelease"
|
|
30
23
|
},
|
|
31
|
-
"keywords": [
|
|
24
|
+
"keywords": [
|
|
25
|
+
"env",
|
|
26
|
+
"dotenv",
|
|
27
|
+
"aws",
|
|
28
|
+
"ssm",
|
|
29
|
+
"parameter-store",
|
|
30
|
+
"cli",
|
|
31
|
+
"environment",
|
|
32
|
+
"secrets",
|
|
33
|
+
"automation",
|
|
34
|
+
"config",
|
|
35
|
+
"aws-cli",
|
|
36
|
+
"devops",
|
|
37
|
+
"ci-cd",
|
|
38
|
+
"secure",
|
|
39
|
+
"envfile"
|
|
40
|
+
],
|
|
32
41
|
"repository": {
|
|
33
42
|
"type": "git",
|
|
34
43
|
"url": "git://github.com/macalbert/envilder.git"
|
|
@@ -52,22 +61,24 @@
|
|
|
52
61
|
"@aws-sdk/client-ssm": "^3.806.0",
|
|
53
62
|
"@aws-sdk/credential-providers": "^3.806.0",
|
|
54
63
|
"@types/node": "^22.5.5",
|
|
55
|
-
"commander": "^
|
|
64
|
+
"commander": "^14.0.0",
|
|
56
65
|
"dotenv": "^16.4.5",
|
|
57
66
|
"picocolors": "^1.1.0"
|
|
58
67
|
},
|
|
59
68
|
"devDependencies": {
|
|
60
69
|
"@biomejs/biome": "^1.9.1",
|
|
61
70
|
"@secretlint/secretlint-rule-preset-recommend": "^9.3.2",
|
|
71
|
+
"@testcontainers/localstack": "^11.0.1",
|
|
62
72
|
"@vitest/coverage-v8": "^3.1.1",
|
|
73
|
+
"jest": "^29.7.0",
|
|
63
74
|
"rimraf": "^6.0.1",
|
|
64
75
|
"secretlint": "^9.3.2",
|
|
76
|
+
"testcontainers": "^11.0.1",
|
|
65
77
|
"ts-node": "^10.9.2",
|
|
66
78
|
"typescript": "^5.6.2",
|
|
67
79
|
"vitest": "^3.1.1"
|
|
68
80
|
},
|
|
69
81
|
"engines": {
|
|
70
|
-
"node": ">=20.0.0"
|
|
71
|
-
"yarn": ">=1.22"
|
|
82
|
+
"node": ">=20.0.0"
|
|
72
83
|
}
|
|
73
84
|
}
|
package/lib/cli/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":";AA4CA;;;;;;GAMG;AACH,wBAAsB,IAAI,kBAkBzB"}
|
package/lib/cli/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":";;;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;GAKG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,QAAQ,GAAG,CAAC;IACrD,IAAI,UAAU,GAAG,QAAQ,CAAC;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACrD,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,sBAAsB;QACtB,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;YAC7B,yBAAyB;YACzB,MAAM;QACR,CAAC;QAED,UAAU,GAAG,SAAS,CAAC;QACvB,KAAK,EAAE,CAAC;IACV,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAClG,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,UAAgB,IAAI;;QACxB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;QAC9B,OAAO;aACJ,IAAI,CAAC,UAAU,CAAC;aAChB,WAAW,CAAC,2DAA2D,CAAC;aACxE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;aAC5B,cAAc,CAAC,cAAc,EAAE,yDAAyD,CAAC;aACzF,cAAc,CAAC,kBAAkB,EAAE,uCAAuC,CAAC;aAC3E,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;QAExD,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/B,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,CAAC;CAAA;AAED,kBAAkB;AAClB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/lib/index.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Orchestrates the process of fetching environment variable values from AWS SSM Parameter Store and writing them to a local environment file.
|
|
3
|
-
*
|
|
4
|
-
* Loads a parameter mapping from a JSON file, retrieves existing environment variables, fetches updated values from SSM (optionally using a specified AWS profile), merges them, and writes the result to the specified environment file.
|
|
5
|
-
*
|
|
6
|
-
* @param mapPath - Path to the JSON file mapping environment variable names to SSM parameter names.
|
|
7
|
-
* @param envFilePath - Path to the local environment file to read and update.
|
|
8
|
-
* @param profile - Optional AWS profile name to use for credentials.
|
|
9
|
-
*/
|
|
10
|
-
export declare function run(mapPath: string, envFilePath: string, profile?: string): Promise<void>;
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,iBAY/E"}
|
package/lib/index.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import * as fs from 'node:fs';
|
|
11
|
-
import { GetParameterCommand, SSM } from '@aws-sdk/client-ssm';
|
|
12
|
-
import { fromIni } from '@aws-sdk/credential-providers';
|
|
13
|
-
import * as dotenv from 'dotenv';
|
|
14
|
-
/**
|
|
15
|
-
* Orchestrates the process of fetching environment variable values from AWS SSM Parameter Store and writing them to a local environment file.
|
|
16
|
-
*
|
|
17
|
-
* Loads a parameter mapping from a JSON file, retrieves existing environment variables, fetches updated values from SSM (optionally using a specified AWS profile), merges them, and writes the result to the specified environment file.
|
|
18
|
-
*
|
|
19
|
-
* @param mapPath - Path to the JSON file mapping environment variable names to SSM parameter names.
|
|
20
|
-
* @param envFilePath - Path to the local environment file to read and update.
|
|
21
|
-
* @param profile - Optional AWS profile name to use for credentials.
|
|
22
|
-
*/
|
|
23
|
-
export function run(mapPath, envFilePath, profile) {
|
|
24
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
-
const defaultAwsConfig = {};
|
|
26
|
-
const ssmClientConfig = profile ? { credentials: fromIni({ profile }) } : defaultAwsConfig;
|
|
27
|
-
const ssm = new SSM(ssmClientConfig);
|
|
28
|
-
const paramMap = loadParamMap(mapPath);
|
|
29
|
-
const existingEnvVariables = loadExistingEnvVariables(envFilePath);
|
|
30
|
-
const updatedEnvVariables = yield fetchAndUpdateEnvVariables(paramMap, existingEnvVariables, ssm);
|
|
31
|
-
writeEnvFile(envFilePath, updatedEnvVariables);
|
|
32
|
-
console.log(`Environment File generated at '${envFilePath}'`);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function loadParamMap(mapPath) {
|
|
36
|
-
const content = fs.readFileSync(mapPath, 'utf-8');
|
|
37
|
-
try {
|
|
38
|
-
return JSON.parse(content);
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
console.error(`Error parsing JSON from ${mapPath}`);
|
|
42
|
-
throw new Error(`Invalid JSON in parameter map file: ${mapPath}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function loadExistingEnvVariables(envFilePath) {
|
|
46
|
-
const envVariables = {};
|
|
47
|
-
if (!fs.existsSync(envFilePath))
|
|
48
|
-
return envVariables;
|
|
49
|
-
const existingEnvContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
50
|
-
const parsedEnv = dotenv.parse(existingEnvContent);
|
|
51
|
-
Object.assign(envVariables, parsedEnv);
|
|
52
|
-
return envVariables;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Fetches parameter values from AWS SSM for each environment variable in the map and updates the existing environment variables record.
|
|
56
|
-
*
|
|
57
|
-
* For each mapping, retrieves the corresponding SSM parameter value and updates the environment variable if found. Logs masked values and warnings for missing parameters. Throws an error if any parameters fail to fetch.
|
|
58
|
-
*
|
|
59
|
-
* @param paramMap - Mapping of environment variable names to SSM parameter names.
|
|
60
|
-
* @param existingEnvVariables - Current environment variables to be updated.
|
|
61
|
-
* @param ssm - AWS SSM client instance used for fetching parameters.
|
|
62
|
-
* @returns The updated environment variables record.
|
|
63
|
-
*
|
|
64
|
-
* @throws {Error} If any SSM parameters cannot be fetched.
|
|
65
|
-
*/
|
|
66
|
-
function fetchAndUpdateEnvVariables(paramMap, existingEnvVariables, ssm) {
|
|
67
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
-
const errors = [];
|
|
69
|
-
for (const [envVar, ssmName] of Object.entries(paramMap)) {
|
|
70
|
-
try {
|
|
71
|
-
const value = yield fetchSSMParameter(ssmName, ssm);
|
|
72
|
-
if (value) {
|
|
73
|
-
existingEnvVariables[envVar] = value;
|
|
74
|
-
console.log(`${envVar}=${value.length > 3 ? '*'.repeat(value.length - 3) + value.slice(-3) : '*'.repeat(value.length)}`);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
console.error(`Warning: No value found for: '${ssmName}'`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
81
|
-
console.error(`Error fetching parameter: '${ssmName}'`);
|
|
82
|
-
errors.push(`ParameterNotFound: ${ssmName}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (errors.length > 0) {
|
|
86
|
-
throw new Error(`Some parameters could not be fetched:\n${errors.join('\n')}`);
|
|
87
|
-
}
|
|
88
|
-
return existingEnvVariables;
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Retrieves the value of a parameter from AWS SSM Parameter Store with decryption enabled.
|
|
93
|
-
*
|
|
94
|
-
* @param ssmName - The name of the SSM parameter to retrieve.
|
|
95
|
-
* @returns The decrypted parameter value if found, or undefined if the parameter does not exist.
|
|
96
|
-
*/
|
|
97
|
-
function fetchSSMParameter(ssmName, ssm) {
|
|
98
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
-
const command = new GetParameterCommand({
|
|
100
|
-
Name: ssmName,
|
|
101
|
-
WithDecryption: true,
|
|
102
|
-
});
|
|
103
|
-
const { Parameter } = yield ssm.send(command);
|
|
104
|
-
return Parameter === null || Parameter === void 0 ? void 0 : Parameter.Value;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
function writeEnvFile(envFilePath, envVariables) {
|
|
108
|
-
const envContent = Object.entries(envVariables)
|
|
109
|
-
.map(([key, value]) => {
|
|
110
|
-
const escapedValue = value.replace(/(\n|\r|\n\r)/g, '\\n').replace(/"/g, '\\"');
|
|
111
|
-
return `${key}=${escapedValue}`;
|
|
112
|
-
})
|
|
113
|
-
.join('\n');
|
|
114
|
-
fs.writeFileSync(envFilePath, envContent);
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|