envilder 0.4.1 → 0.5.1
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/lib/cli/cli.d.ts +10 -0
- package/lib/cli/cli.d.ts.map +1 -0
- package/lib/cli/cli.js +76 -0
- package/lib/cli/cli.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +116 -0
- package/lib/index.js.map +1 -0
- package/package.json +17 -13
- package/.gitattributes +0 -67
- package/.gitconfig +0 -2
- package/.github/dependabot.yml +0 -40
- package/.github/pull_request_template.md +0 -20
- package/.github/workflows/codeql-analysis.yml +0 -49
- package/.github/workflows/coverage-report.yml +0 -73
- package/.github/workflows/publish.yml +0 -80
- package/.github/workflows/unit-tests.yml +0 -51
- package/.secretlintrc.json +0 -7
- package/biome.json +0 -30
- package/src/cli/cliRunner.ts +0 -35
- package/src/index.ts +0 -119
- package/tests/cli/cliRunner.test.ts +0 -59
- package/tests/index.test.ts +0 -150
- package/tests/sample/autogenerated.env +0 -1
- package/tests/sample/param-map.json +0 -3
- package/tsconfig.build.json +0 -7
- package/tsconfig.json +0 -22
- package/vite.config.ts +0 -17
- package/vitest.config.js +0 -12
package/lib/cli/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Parses CLI arguments and runs the environment file generator.
|
|
4
|
+
*
|
|
5
|
+
* Expects `--map` and `--envfile` options to be provided, with an optional `--profile` for AWS CLI profile selection. Invokes the main process to generate a `.env` file from AWS SSM parameters based on the provided mapping.
|
|
6
|
+
*
|
|
7
|
+
* @throws {Error} If either `--map` or `--envfile` arguments are missing.
|
|
8
|
+
*/
|
|
9
|
+
export declare function main(): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { dirname, join } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { Command } from 'commander';
|
|
15
|
+
import { run } from '../index.js';
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
/**
|
|
19
|
+
* Find the package.json file by traversing up directories
|
|
20
|
+
* @param startDir The directory to start searching from
|
|
21
|
+
* @param maxDepth Maximum number of parent directories to check
|
|
22
|
+
* @returns Path to package.json if found, or null if not found
|
|
23
|
+
*/
|
|
24
|
+
function findPackageJson(startDir, maxDepth = 5) {
|
|
25
|
+
let currentDir = startDir;
|
|
26
|
+
let depth = 0;
|
|
27
|
+
while (depth < maxDepth) {
|
|
28
|
+
const packagePath = join(currentDir, 'package.json');
|
|
29
|
+
if (existsSync(packagePath)) {
|
|
30
|
+
return packagePath;
|
|
31
|
+
}
|
|
32
|
+
// Go up one directory
|
|
33
|
+
const parentDir = dirname(currentDir);
|
|
34
|
+
if (parentDir === currentDir) {
|
|
35
|
+
// We've reached the root
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
currentDir = parentDir;
|
|
39
|
+
depth++;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Get package.json path by searching up from current file
|
|
44
|
+
const packageJsonPath = findPackageJson(__dirname) || join(__dirname, '..', '..', 'package.json');
|
|
45
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
46
|
+
/**
|
|
47
|
+
* Parses CLI arguments and runs the environment file generator.
|
|
48
|
+
*
|
|
49
|
+
* Expects `--map` and `--envfile` options to be provided, with an optional `--profile` for AWS CLI profile selection. Invokes the main process to generate a `.env` file from AWS SSM parameters based on the provided mapping.
|
|
50
|
+
*
|
|
51
|
+
* @throws {Error} If either `--map` or `--envfile` arguments are missing.
|
|
52
|
+
*/
|
|
53
|
+
export function main() {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
const program = new Command();
|
|
56
|
+
program
|
|
57
|
+
.name('envilder')
|
|
58
|
+
.description('A CLI tool to generate .env files from AWS SSM parameters')
|
|
59
|
+
.version(packageJson.version)
|
|
60
|
+
.requiredOption('--map <path>', 'Path to the JSON file with environment variable mapping')
|
|
61
|
+
.requiredOption('--envfile <path>', 'Path to the .env file to be generated')
|
|
62
|
+
.option('--profile <name>', 'AWS CLI profile to use');
|
|
63
|
+
yield program.parseAsync(process.argv);
|
|
64
|
+
const options = program.opts();
|
|
65
|
+
if (!options.map || !options.envfile) {
|
|
66
|
+
throw new Error('Missing required arguments: --map and --envfile');
|
|
67
|
+
}
|
|
68
|
+
yield run(options.map, options.envfile, options.profile);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Execute the CLI
|
|
72
|
+
main().catch((error) => {
|
|
73
|
+
console.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
|
|
74
|
+
console.error(error);
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
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
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envilder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A CLI tool to generate .env files from AWS SSM parameters",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
|
+
"import": "./lib/index.js",
|
|
7
8
|
"types": "./lib/index.d.ts"
|
|
8
9
|
}
|
|
9
10
|
},
|
|
11
|
+
"main": "./lib/index.js",
|
|
10
12
|
"bin": {
|
|
11
|
-
"envilder": "lib/cli/
|
|
13
|
+
"envilder": "lib/cli/cli.js"
|
|
12
14
|
},
|
|
13
15
|
"scripts": {
|
|
14
16
|
"clean": "npx jest --clearCache && yarn cache clean --force && npx rimraf lib && npx rimraf node_modules && npx rimraf coverage && npx rimraf yarn.lock",
|
|
15
|
-
"test-run": "yarn build && node lib/cli/
|
|
16
|
-
"build": "tsc -p tsconfig.build.json --sourceMap --declaration",
|
|
17
|
+
"test-run": "yarn build && node lib/cli/cli.js --map=tests/sample/param-map.json --envfile=tests/sample/autogenerated.env",
|
|
18
|
+
"build": "tsc -p tsconfig.build.json --sourceMap --declaration && node --no-warnings scripts/chmod-cli.js",
|
|
19
|
+
"validate-cli": "node --no-warnings --loader ts-node/esm scripts/validate-cli.ts",
|
|
17
20
|
"format": "npx biome format",
|
|
18
21
|
"format:write": "npx biome format --write",
|
|
19
22
|
"lint": "npx secretlint \"**/*\" && biome lint --write && biome format --write && biome check --write && tsc --noEmit",
|
|
20
23
|
"lint:fix": "npx biome lint --fix",
|
|
21
24
|
"test": "vitest run --reporter verbose --coverage",
|
|
22
25
|
"cli-run": "yarn build && node --trace-warnings lib",
|
|
23
|
-
"npm-publish": "yarn lint && yarn build && yarn publish",
|
|
26
|
+
"npm-publish": "yarn lint && yarn build && yarn test && npm pack --dry-run && yarn publish",
|
|
24
27
|
"npm-release-patch": "yarn version --new-version patch",
|
|
25
28
|
"npm-release-minor": "yarn version --new-version minor",
|
|
26
29
|
"npm-release-prerelease": "yarn version --new-version prerelease"
|
|
@@ -38,30 +41,31 @@
|
|
|
38
41
|
"publishConfig": {
|
|
39
42
|
"access": "public"
|
|
40
43
|
},
|
|
44
|
+
"files": [
|
|
45
|
+
"lib/**/*",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE",
|
|
48
|
+
"ROADMAP.md"
|
|
49
|
+
],
|
|
41
50
|
"type": "module",
|
|
42
51
|
"dependencies": {
|
|
43
52
|
"@aws-sdk/client-ssm": "^3.806.0",
|
|
44
53
|
"@aws-sdk/credential-providers": "^3.806.0",
|
|
45
|
-
"@secretlint/core": "^9.2.1",
|
|
46
|
-
"@secretlint/secretlint-rule-preset-recommend": "^9.0.0",
|
|
47
54
|
"@types/node": "^22.5.5",
|
|
48
|
-
"commander": "^
|
|
55
|
+
"commander": "^13.1.0",
|
|
49
56
|
"dotenv": "^16.4.5",
|
|
50
57
|
"picocolors": "^1.1.0"
|
|
51
58
|
},
|
|
52
59
|
"devDependencies": {
|
|
53
60
|
"@biomejs/biome": "^1.9.1",
|
|
61
|
+
"@secretlint/secretlint-rule-preset-recommend": "^9.3.2",
|
|
54
62
|
"@vitest/coverage-v8": "^3.1.1",
|
|
55
63
|
"rimraf": "^6.0.1",
|
|
56
|
-
"secretlint": "^9.
|
|
64
|
+
"secretlint": "^9.3.2",
|
|
57
65
|
"ts-node": "^10.9.2",
|
|
58
66
|
"typescript": "^5.6.2",
|
|
59
67
|
"vitest": "^3.1.1"
|
|
60
68
|
},
|
|
61
|
-
"resolutions": {
|
|
62
|
-
"string-width": "4.2.3",
|
|
63
|
-
"strip-ansi": "6.0.1"
|
|
64
|
-
},
|
|
65
69
|
"engines": {
|
|
66
70
|
"node": ">=20.0.0",
|
|
67
71
|
"yarn": ">=1.22"
|
package/.gitattributes
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
###############################################################################
|
|
2
|
-
# Set default behavior to automatically normalize line endings.
|
|
3
|
-
###############################################################################
|
|
4
|
-
* text=auto
|
|
5
|
-
|
|
6
|
-
# Explicitly declare text files you want to always be normalized and converted
|
|
7
|
-
# to native line endings on checkout.
|
|
8
|
-
*.sh text eol=lf
|
|
9
|
-
|
|
10
|
-
###############################################################################
|
|
11
|
-
# Set default behavior for command prompt diff.
|
|
12
|
-
#
|
|
13
|
-
# This is need for earlier builds of msysgit that does not have it on by
|
|
14
|
-
# default for csharp files.
|
|
15
|
-
# Note: This is only used by command line
|
|
16
|
-
###############################################################################
|
|
17
|
-
#*.cs diff=csharp
|
|
18
|
-
|
|
19
|
-
###############################################################################
|
|
20
|
-
# Set the merge driver for project and solution files
|
|
21
|
-
#
|
|
22
|
-
# Merging from the command prompt will add diff markers to the files if there
|
|
23
|
-
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
|
24
|
-
# the diff markers are never inserted). Diff markers may cause the following
|
|
25
|
-
# file extensions to fail to load in VS. An alternative would be to treat
|
|
26
|
-
# these files as binary and thus will always conflict and require user
|
|
27
|
-
# intervention with every merge. To do so, just uncomment the entries below
|
|
28
|
-
###############################################################################
|
|
29
|
-
#*.sln merge=binary
|
|
30
|
-
#*.csproj merge=binary
|
|
31
|
-
#*.vbproj merge=binary
|
|
32
|
-
#*.vcxproj merge=binary
|
|
33
|
-
#*.vcproj merge=binary
|
|
34
|
-
#*.dbproj merge=binary
|
|
35
|
-
#*.fsproj merge=binary
|
|
36
|
-
#*.lsproj merge=binary
|
|
37
|
-
#*.wixproj merge=binary
|
|
38
|
-
#*.modelproj merge=binary
|
|
39
|
-
#*.sqlproj merge=binary
|
|
40
|
-
#*.wwaproj merge=binary
|
|
41
|
-
|
|
42
|
-
###############################################################################
|
|
43
|
-
# behavior for image files
|
|
44
|
-
#
|
|
45
|
-
# image files are treated as binary by default.
|
|
46
|
-
###############################################################################
|
|
47
|
-
#*.jpg binary
|
|
48
|
-
#*.png binary
|
|
49
|
-
#*.gif binary
|
|
50
|
-
|
|
51
|
-
###############################################################################
|
|
52
|
-
# diff behavior for common document formats
|
|
53
|
-
#
|
|
54
|
-
# Convert binary document formats to text before diffing them. This feature
|
|
55
|
-
# is only available from the command line. Turn it on by uncommenting the
|
|
56
|
-
# entries below.
|
|
57
|
-
###############################################################################
|
|
58
|
-
#*.doc diff=astextplain
|
|
59
|
-
#*.DOC diff=astextplain
|
|
60
|
-
#*.docx diff=astextplain
|
|
61
|
-
#*.DOCX diff=astextplain
|
|
62
|
-
#*.dot diff=astextplain
|
|
63
|
-
#*.DOT diff=astextplain
|
|
64
|
-
#*.pdf diff=astextplain
|
|
65
|
-
#*.PDF diff=astextplain
|
|
66
|
-
#*.rtf diff=astextplain
|
|
67
|
-
#*.RTF diff=astextplain
|
package/.gitconfig
DELETED
package/.github/dependabot.yml
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
-
# package ecosystems to update and where the package manifests are located.
|
|
3
|
-
# Please see the documentation for all configuration options:
|
|
4
|
-
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
5
|
-
|
|
6
|
-
version: 2
|
|
7
|
-
updates:
|
|
8
|
-
- package-ecosystem: npm
|
|
9
|
-
directory: "/"
|
|
10
|
-
pull-request-branch-name:
|
|
11
|
-
separator: "/"
|
|
12
|
-
schedule:
|
|
13
|
-
interval: monthly
|
|
14
|
-
day: monday
|
|
15
|
-
time: "10:00"
|
|
16
|
-
timezone: Europe/Madrid
|
|
17
|
-
labels:
|
|
18
|
-
- "npm"
|
|
19
|
-
- "dependencies"
|
|
20
|
-
reviewers:
|
|
21
|
-
- macalbert
|
|
22
|
-
assignees:
|
|
23
|
-
- macalbert
|
|
24
|
-
|
|
25
|
-
- package-ecosystem: github-actions
|
|
26
|
-
directory: "/"
|
|
27
|
-
pull-request-branch-name:
|
|
28
|
-
separator: "/"
|
|
29
|
-
schedule:
|
|
30
|
-
interval: monthly
|
|
31
|
-
day: monday
|
|
32
|
-
time: "10:00"
|
|
33
|
-
timezone: Europe/Madrid
|
|
34
|
-
labels:
|
|
35
|
-
- "github-actions"
|
|
36
|
-
- "dependencies"
|
|
37
|
-
reviewers:
|
|
38
|
-
- macalbert
|
|
39
|
-
assignees:
|
|
40
|
-
- macalbert
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Description
|
|
2
|
-
|
|
3
|
-
_Describe the problem or feature in addition to a link to the issues._
|
|
4
|
-
|
|
5
|
-
## Approach
|
|
6
|
-
|
|
7
|
-
_How does this change address the problem?_
|
|
8
|
-
|
|
9
|
-
## Open Questions and Pre-Merge TODOs
|
|
10
|
-
|
|
11
|
-
- [ ] Use github checklists. When solved, check the box and explain the answer.
|
|
12
|
-
|
|
13
|
-
## Learning
|
|
14
|
-
|
|
15
|
-
_Describe the research stage_
|
|
16
|
-
_Links to blog posts, patterns, libraries or addons used to solve this problem_
|
|
17
|
-
|
|
18
|
-
## Blog Posts
|
|
19
|
-
|
|
20
|
-
- [How to Pull Request](https://github.com/flexyford/pull-request) Github Repo with Learning focused Pull Request Template.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
name: CodeQL
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [main]
|
|
8
|
-
paths:
|
|
9
|
-
- ".github/workflows/codeql-analysis.yml"
|
|
10
|
-
|
|
11
|
-
push:
|
|
12
|
-
branches: [main]
|
|
13
|
-
paths:
|
|
14
|
-
- ".github/workflows/codeql-analysis.yml"
|
|
15
|
-
- "src/**"
|
|
16
|
-
- "test/**"
|
|
17
|
-
|
|
18
|
-
concurrency:
|
|
19
|
-
group: ${{ github.workflow }}-${{ github.head_ref || github.sha }}
|
|
20
|
-
cancel-in-progress: true
|
|
21
|
-
|
|
22
|
-
jobs:
|
|
23
|
-
analyze:
|
|
24
|
-
strategy:
|
|
25
|
-
fail-fast: false
|
|
26
|
-
matrix:
|
|
27
|
-
language: ["javascript"]
|
|
28
|
-
|
|
29
|
-
permissions:
|
|
30
|
-
security-events: write
|
|
31
|
-
|
|
32
|
-
runs-on: ubuntu-22.04
|
|
33
|
-
|
|
34
|
-
steps:
|
|
35
|
-
- name: Checkout Repository
|
|
36
|
-
uses: actions/checkout@v4
|
|
37
|
-
with:
|
|
38
|
-
lfs: true
|
|
39
|
-
|
|
40
|
-
- name: Initialize CodeQL
|
|
41
|
-
uses: github/codeql-action/init@v3
|
|
42
|
-
with:
|
|
43
|
-
languages: ${{ matrix.language }}
|
|
44
|
-
|
|
45
|
-
- name: Autobuild
|
|
46
|
-
uses: github/codeql-action/autobuild@v3
|
|
47
|
-
|
|
48
|
-
- name: Perform CodeQL Analysis
|
|
49
|
-
uses: github/codeql-action/analyze@v3
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
name: 🔦 code-coverage
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
|
|
6
|
-
pull_request:
|
|
7
|
-
paths:
|
|
8
|
-
- ".github/workflows/coverage-report.yml"
|
|
9
|
-
|
|
10
|
-
push:
|
|
11
|
-
branches:
|
|
12
|
-
- "main"
|
|
13
|
-
paths:
|
|
14
|
-
- ".github/workflows/coverage-report.yml"
|
|
15
|
-
- "src/**"
|
|
16
|
-
- "test/**"
|
|
17
|
-
|
|
18
|
-
concurrency:
|
|
19
|
-
group: "pages"
|
|
20
|
-
cancel-in-progress: false
|
|
21
|
-
|
|
22
|
-
permissions:
|
|
23
|
-
contents: read
|
|
24
|
-
pages: write
|
|
25
|
-
id-token: write
|
|
26
|
-
|
|
27
|
-
jobs:
|
|
28
|
-
build-coverage:
|
|
29
|
-
environment:
|
|
30
|
-
name: github-pages
|
|
31
|
-
url: ${{ steps.deployment.outputs.page_url }}
|
|
32
|
-
runs-on: ubuntu-latest
|
|
33
|
-
if: ${{ !github.event.pull_request.draft }}
|
|
34
|
-
steps:
|
|
35
|
-
- name: Check if PR is created by Dependabot
|
|
36
|
-
id: dependabot-check
|
|
37
|
-
run: |
|
|
38
|
-
if [[ "${{ github.actor }}" == *dependabot* ]]; then
|
|
39
|
-
echo "is_dependabot=true" >> "$GITHUB_OUTPUT"
|
|
40
|
-
else
|
|
41
|
-
echo "is_dependabot=false" >> "$GITHUB_OUTPUT"
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
- name: Check if the workflow should run
|
|
45
|
-
if: ${{ steps.dependabot-check.outputs.is_dependabot == 'false' }}
|
|
46
|
-
run: echo "The workflow is allowed to run for this PR"
|
|
47
|
-
|
|
48
|
-
- name: 🧲 Checkout
|
|
49
|
-
uses: actions/checkout@v4
|
|
50
|
-
|
|
51
|
-
- name: 🛠️ Setup Node.js with Cache
|
|
52
|
-
uses: actions/setup-node@v4
|
|
53
|
-
with:
|
|
54
|
-
node-version: "20.x"
|
|
55
|
-
cache: "yarn"
|
|
56
|
-
|
|
57
|
-
- name: 📦 Install dependencies
|
|
58
|
-
run: yarn install
|
|
59
|
-
|
|
60
|
-
- name: 🔥 Run tests and collect coverage
|
|
61
|
-
run: yarn test
|
|
62
|
-
|
|
63
|
-
- name: Setup Pages
|
|
64
|
-
uses: actions/configure-pages@v5
|
|
65
|
-
|
|
66
|
-
- name: Upload artifact
|
|
67
|
-
uses: actions/upload-pages-artifact@v3
|
|
68
|
-
with:
|
|
69
|
-
path: "./coverage"
|
|
70
|
-
|
|
71
|
-
- name: Deploy to GitHub Pages
|
|
72
|
-
id: deployment
|
|
73
|
-
uses: actions/deploy-pages@v4
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
name: 🍄 Power-Up Publisher
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
paths:
|
|
8
|
-
- 'src/**'
|
|
9
|
-
- 'package.json'
|
|
10
|
-
- '.github/workflows/publish.yml'
|
|
11
|
-
|
|
12
|
-
# Add explicit permissions for the GITHUB_TOKEN
|
|
13
|
-
permissions:
|
|
14
|
-
contents: write
|
|
15
|
-
packages: write
|
|
16
|
-
|
|
17
|
-
jobs:
|
|
18
|
-
publish:
|
|
19
|
-
runs-on: ubuntu-latest
|
|
20
|
-
steps:
|
|
21
|
-
- name: 🧱 Checkout repository
|
|
22
|
-
uses: actions/checkout@v3
|
|
23
|
-
with:
|
|
24
|
-
fetch-depth: 0
|
|
25
|
-
|
|
26
|
-
- name: 🔧 Setup Node.js
|
|
27
|
-
uses: actions/setup-node@v3
|
|
28
|
-
with:
|
|
29
|
-
node-version: '20'
|
|
30
|
-
registry-url: 'https://registry.npmjs.org'
|
|
31
|
-
cache: 'yarn'
|
|
32
|
-
|
|
33
|
-
- name: 🌟 Install dependencies
|
|
34
|
-
run: yarn install --frozen-lockfile
|
|
35
|
-
|
|
36
|
-
- name: 🔥 Lint
|
|
37
|
-
run: yarn lint
|
|
38
|
-
|
|
39
|
-
- name: 🍄 Run tests
|
|
40
|
-
run: yarn test
|
|
41
|
-
|
|
42
|
-
- name: 👑 Detect version bump
|
|
43
|
-
id: version-check
|
|
44
|
-
run: |
|
|
45
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
46
|
-
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
|
|
47
|
-
LAST_TAG_VERSION=${LAST_TAG#v}
|
|
48
|
-
|
|
49
|
-
echo "Current version: $CURRENT_VERSION, Last tag version: $LAST_TAG_VERSION"
|
|
50
|
-
|
|
51
|
-
# Check if the current version is greater than the last tagged version
|
|
52
|
-
if [ "$CURRENT_VERSION" != "$LAST_TAG_VERSION" ]; then
|
|
53
|
-
echo "Version has been bumped from $LAST_TAG_VERSION to $CURRENT_VERSION"
|
|
54
|
-
echo "version_changed=true" >> $GITHUB_OUTPUT
|
|
55
|
-
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
56
|
-
else
|
|
57
|
-
echo "Version not changed. Will not publish."
|
|
58
|
-
echo "version_changed=false" >> $GITHUB_OUTPUT
|
|
59
|
-
fi
|
|
60
|
-
|
|
61
|
-
- name: 🔨 Build package
|
|
62
|
-
if: steps.version-check.outputs.version_changed == 'true'
|
|
63
|
-
run: yarn build
|
|
64
|
-
|
|
65
|
-
- name: 🚩 Publish to npm
|
|
66
|
-
if: steps.version-check.outputs.version_changed == 'true'
|
|
67
|
-
run: yarn publish --non-interactive
|
|
68
|
-
env:
|
|
69
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
70
|
-
|
|
71
|
-
- name: 🏰 Create GitHub Release
|
|
72
|
-
if: steps.version-check.outputs.version_changed == 'true'
|
|
73
|
-
uses: ncipollo/release-action@v1
|
|
74
|
-
with:
|
|
75
|
-
tag: "v${{ steps.version-check.outputs.current_version }}"
|
|
76
|
-
name: "🍄 Level Up Release v${{ steps.version-check.outputs.current_version }}"
|
|
77
|
-
generateReleaseNotes: true
|
|
78
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
79
|
-
makeLatest: legacy
|
|
80
|
-
replacesArtifacts: true
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
name: 🌱 unit-tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch: {}
|
|
5
|
-
|
|
6
|
-
pull_request:
|
|
7
|
-
branches:
|
|
8
|
-
- "*"
|
|
9
|
-
types:
|
|
10
|
-
- opened
|
|
11
|
-
- reopened
|
|
12
|
-
- synchronize
|
|
13
|
-
- ready_for_review
|
|
14
|
-
paths:
|
|
15
|
-
- ".github/workflows/unit-tests.yml"
|
|
16
|
-
- "src/**"
|
|
17
|
-
|
|
18
|
-
concurrency:
|
|
19
|
-
group: ${{ github.workflow }}-${{ github.head_ref || github.sha }}
|
|
20
|
-
cancel-in-progress: true
|
|
21
|
-
|
|
22
|
-
jobs:
|
|
23
|
-
envilder-test:
|
|
24
|
-
runs-on: ubuntu-24.04
|
|
25
|
-
if: ${{ !github.event.pull_request.draft }}
|
|
26
|
-
timeout-minutes: 30
|
|
27
|
-
|
|
28
|
-
steps:
|
|
29
|
-
- name: 🚀 ♂️ Checkout
|
|
30
|
-
uses: actions/checkout@v4
|
|
31
|
-
|
|
32
|
-
- name: 🛠️ Setup Node.js with Cache
|
|
33
|
-
uses: actions/setup-node@v4
|
|
34
|
-
with:
|
|
35
|
-
node-version: '20.x'
|
|
36
|
-
cache: 'yarn'
|
|
37
|
-
|
|
38
|
-
- name: 📦 Install packages
|
|
39
|
-
run: yarn install --frozen-lockfile
|
|
40
|
-
|
|
41
|
-
- name: 🔍 Run formatting checker
|
|
42
|
-
run: yarn format
|
|
43
|
-
|
|
44
|
-
- name: 🔍 Run code quality checker
|
|
45
|
-
run: yarn lint
|
|
46
|
-
|
|
47
|
-
- name: 🚧 Build
|
|
48
|
-
run: yarn build
|
|
49
|
-
|
|
50
|
-
- name: 🚴♀️ Run unit tests
|
|
51
|
-
run: yarn test
|
package/.secretlintrc.json
DELETED
package/biome.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
|
|
3
|
-
"files": {
|
|
4
|
-
"include": ["./src/**", "./tests/**"],
|
|
5
|
-
"ignore": ["**/node_modules/**", "**/lib/**", "**/dist/**", "**/coverage/**", "**/.lock", "**/.md"]
|
|
6
|
-
},
|
|
7
|
-
"organizeImports": {
|
|
8
|
-
"enabled": true
|
|
9
|
-
},
|
|
10
|
-
"linter": {
|
|
11
|
-
"enabled": true,
|
|
12
|
-
"rules": {
|
|
13
|
-
"recommended": true
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"formatter": {
|
|
17
|
-
"enabled": true,
|
|
18
|
-
"formatWithErrors": false,
|
|
19
|
-
"indentStyle": "space",
|
|
20
|
-
"indentWidth": 2,
|
|
21
|
-
"lineWidth": 120
|
|
22
|
-
},
|
|
23
|
-
"javascript": {
|
|
24
|
-
"formatter": {
|
|
25
|
-
"quoteStyle": "single",
|
|
26
|
-
"trailingCommas": "all",
|
|
27
|
-
"semicolons": "always"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/cli/cliRunner.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
import { run } from '../index.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Parses CLI arguments and runs the environment file generator.
|
|
7
|
-
*
|
|
8
|
-
* Expects `--map` and `--envfile` options to be provided, with an optional `--profile` for AWS CLI profile selection. Invokes the main process to generate a `.env` file from AWS SSM parameters based on the provided mapping.
|
|
9
|
-
*
|
|
10
|
-
* @throws {Error} If either `--map` or `--envfile` arguments are missing.
|
|
11
|
-
*/
|
|
12
|
-
export async function cliRunner() {
|
|
13
|
-
const program = new Command();
|
|
14
|
-
|
|
15
|
-
program
|
|
16
|
-
.name('envilder')
|
|
17
|
-
.description('A CLI tool to generate .env files from AWS SSM parameters')
|
|
18
|
-
.version('0.1.0')
|
|
19
|
-
.requiredOption('--map <path>', 'Path to the JSON file with environment variable mapping')
|
|
20
|
-
.requiredOption('--envfile <path>', 'Path to the .env file to be generated')
|
|
21
|
-
.option('--profile <name>', 'AWS CLI profile to use');
|
|
22
|
-
|
|
23
|
-
await program.parseAsync(process.argv);
|
|
24
|
-
const options = program.opts();
|
|
25
|
-
|
|
26
|
-
if (!options.map || !options.envfile) {
|
|
27
|
-
throw new Error('Missing required arguments: --map and --envfile');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
await run(options.map, options.envfile, options.profile);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
cliRunner().catch((error) => {
|
|
34
|
-
console.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
|
|
35
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import { GetParameterCommand, SSM } from '@aws-sdk/client-ssm';
|
|
3
|
-
import { fromIni } from '@aws-sdk/credential-providers';
|
|
4
|
-
import * as dotenv from 'dotenv';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Orchestrates the process of fetching environment variable values from AWS SSM Parameter Store and writing them to a local environment file.
|
|
8
|
-
*
|
|
9
|
-
* 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.
|
|
10
|
-
*
|
|
11
|
-
* @param mapPath - Path to the JSON file mapping environment variable names to SSM parameter names.
|
|
12
|
-
* @param envFilePath - Path to the local environment file to read and update.
|
|
13
|
-
* @param profile - Optional AWS profile name to use for credentials.
|
|
14
|
-
*/
|
|
15
|
-
export async function run(mapPath: string, envFilePath: string, profile?: string) {
|
|
16
|
-
const defaultAwsConfig = {};
|
|
17
|
-
const ssmClientConfig = profile ? { credentials: fromIni({ profile }) } : defaultAwsConfig;
|
|
18
|
-
const ssm = new SSM(ssmClientConfig);
|
|
19
|
-
|
|
20
|
-
const paramMap = loadParamMap(mapPath);
|
|
21
|
-
const existingEnvVariables = loadExistingEnvVariables(envFilePath);
|
|
22
|
-
|
|
23
|
-
const updatedEnvVariables = await fetchAndUpdateEnvVariables(paramMap, existingEnvVariables, ssm);
|
|
24
|
-
|
|
25
|
-
writeEnvFile(envFilePath, updatedEnvVariables);
|
|
26
|
-
console.log(`Environment File generated at '${envFilePath}'`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function loadParamMap(mapPath: string): Record<string, string> {
|
|
30
|
-
const content = fs.readFileSync(mapPath, 'utf-8');
|
|
31
|
-
try {
|
|
32
|
-
return JSON.parse(content);
|
|
33
|
-
} catch (error) {
|
|
34
|
-
console.error(`Error parsing JSON from ${mapPath}`);
|
|
35
|
-
throw new Error(`Invalid JSON in parameter map file: ${mapPath}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function loadExistingEnvVariables(envFilePath: string): Record<string, string> {
|
|
40
|
-
const envVariables: Record<string, string> = {};
|
|
41
|
-
|
|
42
|
-
if (!fs.existsSync(envFilePath)) return envVariables;
|
|
43
|
-
|
|
44
|
-
const existingEnvContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
45
|
-
const parsedEnv = dotenv.parse(existingEnvContent);
|
|
46
|
-
Object.assign(envVariables, parsedEnv);
|
|
47
|
-
|
|
48
|
-
return envVariables;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Fetches parameter values from AWS SSM for each environment variable in the map and updates the existing environment variables record.
|
|
53
|
-
*
|
|
54
|
-
* 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.
|
|
55
|
-
*
|
|
56
|
-
* @param paramMap - Mapping of environment variable names to SSM parameter names.
|
|
57
|
-
* @param existingEnvVariables - Current environment variables to be updated.
|
|
58
|
-
* @param ssm - AWS SSM client instance used for fetching parameters.
|
|
59
|
-
* @returns The updated environment variables record.
|
|
60
|
-
*
|
|
61
|
-
* @throws {Error} If any SSM parameters cannot be fetched.
|
|
62
|
-
*/
|
|
63
|
-
async function fetchAndUpdateEnvVariables(
|
|
64
|
-
paramMap: Record<string, string>,
|
|
65
|
-
existingEnvVariables: Record<string, string>,
|
|
66
|
-
ssm: SSM,
|
|
67
|
-
): Promise<Record<string, string>> {
|
|
68
|
-
const errors: string[] = [];
|
|
69
|
-
|
|
70
|
-
for (const [envVar, ssmName] of Object.entries(paramMap)) {
|
|
71
|
-
try {
|
|
72
|
-
const value = await fetchSSMParameter(ssmName, ssm);
|
|
73
|
-
if (value) {
|
|
74
|
-
existingEnvVariables[envVar] = value;
|
|
75
|
-
console.log(
|
|
76
|
-
`${envVar}=${value.length > 3 ? '*'.repeat(value.length - 3) + value.slice(-3) : '*'.repeat(value.length)}`,
|
|
77
|
-
);
|
|
78
|
-
} else {
|
|
79
|
-
console.error(`Warning: No value found for: '${ssmName}'`);
|
|
80
|
-
}
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error(`Error fetching parameter: '${ssmName}'`);
|
|
83
|
-
errors.push(`ParameterNotFound: ${ssmName}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (errors.length > 0) {
|
|
88
|
-
throw new Error(`Some parameters could not be fetched:\n${errors.join('\n')}`);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return existingEnvVariables;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Retrieves the value of a parameter from AWS SSM Parameter Store with decryption enabled.
|
|
96
|
-
*
|
|
97
|
-
* @param ssmName - The name of the SSM parameter to retrieve.
|
|
98
|
-
* @returns The decrypted parameter value if found, or undefined if the parameter does not exist.
|
|
99
|
-
*/
|
|
100
|
-
async function fetchSSMParameter(ssmName: string, ssm: SSM): Promise<string | undefined> {
|
|
101
|
-
const command = new GetParameterCommand({
|
|
102
|
-
Name: ssmName,
|
|
103
|
-
WithDecryption: true,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const { Parameter } = await ssm.send(command);
|
|
107
|
-
return Parameter?.Value;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function writeEnvFile(envFilePath: string, envVariables: Record<string, string>): void {
|
|
111
|
-
const envContent = Object.entries(envVariables)
|
|
112
|
-
.map(([key, value]) => {
|
|
113
|
-
const escapedValue = value.replace(/(\n|\r|\n\r)/g, '\\n').replace(/"/g, '\\"');
|
|
114
|
-
return `${key}=${escapedValue}`;
|
|
115
|
-
})
|
|
116
|
-
.join('\n');
|
|
117
|
-
|
|
118
|
-
fs.writeFileSync(envFilePath, envContent);
|
|
119
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { cliRunner } from '../../src/cli/cliRunner';
|
|
3
|
-
import { run } from '../../src/index';
|
|
4
|
-
|
|
5
|
-
vi.mock('../../src/index', () => ({
|
|
6
|
-
run: vi.fn(),
|
|
7
|
-
}));
|
|
8
|
-
|
|
9
|
-
describe('cliRunner', () => {
|
|
10
|
-
const originalArgv = process.argv;
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
process.argv = [...originalArgv.slice(0, 2)];
|
|
14
|
-
});
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
vi.clearAllMocks();
|
|
17
|
-
process.argv = originalArgv;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('Should_CallRunWithCorrectArguments_When_ValidArgumentsAreProvided', async () => {
|
|
21
|
-
// Arrange
|
|
22
|
-
const mockMapPath = 'path/to/mockMap.json';
|
|
23
|
-
const mockEnvFilePath = 'path/to/.env';
|
|
24
|
-
process.argv.push('--map', mockMapPath, '--envfile', mockEnvFilePath);
|
|
25
|
-
|
|
26
|
-
// Act
|
|
27
|
-
await cliRunner();
|
|
28
|
-
|
|
29
|
-
// Assert
|
|
30
|
-
expect(run).toHaveBeenCalledWith(mockMapPath, mockEnvFilePath, undefined);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('Should_ThrowError_When_RequiredArgumentsAreMissing', async () => {
|
|
34
|
-
// Arrange
|
|
35
|
-
vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
36
|
-
throw new Error('process.exit called');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Act
|
|
40
|
-
const action = cliRunner();
|
|
41
|
-
|
|
42
|
-
// Assert
|
|
43
|
-
await expect(action).rejects.toThrow('process.exit called');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('Should_CallRunWithCorrectArgumentsIncludingProfile_When_ProfileIsProvided', async () => {
|
|
47
|
-
// Arrange
|
|
48
|
-
const mockMapPath = 'path/to/mockMap.json';
|
|
49
|
-
const mockEnvFilePath = 'path/to/.env';
|
|
50
|
-
const mockProfile = 'test-profile';
|
|
51
|
-
process.argv.push('--map', mockMapPath, '--envfile', mockEnvFilePath, '--profile', mockProfile);
|
|
52
|
-
|
|
53
|
-
// Act
|
|
54
|
-
await cliRunner();
|
|
55
|
-
|
|
56
|
-
// Assert
|
|
57
|
-
expect(run).toHaveBeenCalledWith(mockMapPath, mockEnvFilePath, mockProfile);
|
|
58
|
-
});
|
|
59
|
-
});
|
package/tests/index.test.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import { SSM } from '@aws-sdk/client-ssm';
|
|
3
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
-
import { run } from '../src/index';
|
|
5
|
-
|
|
6
|
-
vi.mock('@aws-sdk/client-ssm', () => {
|
|
7
|
-
return {
|
|
8
|
-
SSM: vi.fn().mockImplementation(() => ({
|
|
9
|
-
send: vi.fn((command) => {
|
|
10
|
-
if (command.input.Name === '/path/to/ssm/email') {
|
|
11
|
-
return Promise.resolve({
|
|
12
|
-
Parameter: { Value: 'mockedEmail@example.com' },
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (command.input.Name === '/path/to/ssm/password') {
|
|
17
|
-
return Promise.resolve({
|
|
18
|
-
Parameter: { Value: 'mockedPassword' },
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (command.input.Name === '/path/to/ssm/password_no_value') {
|
|
23
|
-
return Promise.resolve({ Parameter: { Value: '' } });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return Promise.reject(new Error(`ParameterNotFound: ${command.input.Name}`));
|
|
27
|
-
}),
|
|
28
|
-
})),
|
|
29
|
-
GetParameterCommand: vi.fn().mockImplementation((input) => ({
|
|
30
|
-
input,
|
|
31
|
-
})),
|
|
32
|
-
};
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe('Envilder CLI', () => {
|
|
36
|
-
const mockMapPath = './tests/param-map.json';
|
|
37
|
-
const mockEnvFilePath = './tests/.env.test';
|
|
38
|
-
|
|
39
|
-
afterEach(() => {
|
|
40
|
-
vi.clearAllMocks();
|
|
41
|
-
|
|
42
|
-
if (fs.existsSync(mockEnvFilePath)) {
|
|
43
|
-
fs.unlinkSync(mockEnvFilePath);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (fs.existsSync(mockMapPath)) {
|
|
47
|
-
fs.unlinkSync(mockMapPath);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('Should_GenerateEnvFileFromSSMParameters_When_ValidSSMParametersAreProvided', async () => {
|
|
52
|
-
// Arrange
|
|
53
|
-
const paramMapContent = {
|
|
54
|
-
NEXT_PUBLIC_CREDENTIAL_EMAIL: '/path/to/ssm/email',
|
|
55
|
-
NEXT_PUBLIC_CREDENTIAL_PASSWORD: '/path/to/ssm/password',
|
|
56
|
-
};
|
|
57
|
-
fs.writeFileSync(mockMapPath, JSON.stringify(paramMapContent));
|
|
58
|
-
|
|
59
|
-
// Act
|
|
60
|
-
await run(mockMapPath, mockEnvFilePath);
|
|
61
|
-
|
|
62
|
-
// Assert
|
|
63
|
-
const envFileContent = fs.readFileSync(mockEnvFilePath, 'utf-8');
|
|
64
|
-
expect(envFileContent).toContain('NEXT_PUBLIC_CREDENTIAL_EMAIL=mockedEmail@example.com');
|
|
65
|
-
expect(envFileContent).toContain('NEXT_PUBLIC_CREDENTIAL_PASSWORD=mockedPassword');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('Should_ThrowError_When_SSMParameterIsNotFound', async () => {
|
|
69
|
-
// Arrange
|
|
70
|
-
const paramMapContent = {
|
|
71
|
-
NEXT_PUBLIC_CREDENTIAL_EMAIL: 'non-existent parameter',
|
|
72
|
-
};
|
|
73
|
-
fs.writeFileSync(mockMapPath, JSON.stringify(paramMapContent));
|
|
74
|
-
|
|
75
|
-
// Act
|
|
76
|
-
const action = run(mockMapPath, mockEnvFilePath);
|
|
77
|
-
|
|
78
|
-
// Assert
|
|
79
|
-
await expect(action).rejects.toThrow('ParameterNotFound: non-existent parameter');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('Should_AppendNewSSMParameters_When_EnvFileContainsExistingVariables', async () => {
|
|
83
|
-
// Arrange
|
|
84
|
-
const existingEnvContent = 'EXISTING_VAR=existingValue';
|
|
85
|
-
fs.writeFileSync(mockEnvFilePath, existingEnvContent);
|
|
86
|
-
const paramMapContent = {
|
|
87
|
-
NEXT_PUBLIC_CREDENTIAL_EMAIL: '/path/to/ssm/email',
|
|
88
|
-
NEXT_PUBLIC_CREDENTIAL_PASSWORD: '/path/to/ssm/password',
|
|
89
|
-
};
|
|
90
|
-
fs.writeFileSync(mockMapPath, JSON.stringify(paramMapContent));
|
|
91
|
-
|
|
92
|
-
// Act
|
|
93
|
-
await run(mockMapPath, mockEnvFilePath);
|
|
94
|
-
|
|
95
|
-
// Assert
|
|
96
|
-
const updatedEnvFileContent = fs.readFileSync(mockEnvFilePath, 'utf-8');
|
|
97
|
-
expect(updatedEnvFileContent).toContain('EXISTING_VAR=existingValue');
|
|
98
|
-
expect(updatedEnvFileContent).toContain('NEXT_PUBLIC_CREDENTIAL_EMAIL=mockedEmail@example.com');
|
|
99
|
-
expect(updatedEnvFileContent).toContain('NEXT_PUBLIC_CREDENTIAL_PASSWORD=mockedPassword');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('Should_OverwriteSSMParameters_When_EnvFileContainsSameVariables', async () => {
|
|
103
|
-
// Arrange
|
|
104
|
-
const existingEnvContent = 'NEXT_PUBLIC_CREDENTIAL_EMAIL=oldEmail@example.com';
|
|
105
|
-
fs.writeFileSync(mockEnvFilePath, existingEnvContent);
|
|
106
|
-
const paramMapContent = {
|
|
107
|
-
NEXT_PUBLIC_CREDENTIAL_EMAIL: '/path/to/ssm/email',
|
|
108
|
-
NEXT_PUBLIC_CREDENTIAL_PASSWORD: '/path/to/ssm/password',
|
|
109
|
-
};
|
|
110
|
-
fs.writeFileSync(mockMapPath, JSON.stringify(paramMapContent));
|
|
111
|
-
|
|
112
|
-
// Act
|
|
113
|
-
await run(mockMapPath, mockEnvFilePath);
|
|
114
|
-
|
|
115
|
-
// Assert
|
|
116
|
-
const updatedEnvFileContent = fs.readFileSync(mockEnvFilePath, 'utf-8');
|
|
117
|
-
expect(updatedEnvFileContent).toContain('NEXT_PUBLIC_CREDENTIAL_EMAIL=mockedEmail@example.com');
|
|
118
|
-
expect(updatedEnvFileContent).toContain('NEXT_PUBLIC_CREDENTIAL_PASSWORD=mockedPassword');
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('Should_LogWarning_When_SSMParameterHasNoValue', async () => {
|
|
122
|
-
// Arrange
|
|
123
|
-
const paramMapContent = {
|
|
124
|
-
NEXT_PUBLIC_CREDENTIAL_PASSWORD: '/path/to/ssm/password_no_value',
|
|
125
|
-
};
|
|
126
|
-
fs.writeFileSync(mockMapPath, JSON.stringify(paramMapContent));
|
|
127
|
-
const consoleSpy = vi.spyOn(console, 'error');
|
|
128
|
-
|
|
129
|
-
// Act
|
|
130
|
-
await run(mockMapPath, mockEnvFilePath);
|
|
131
|
-
|
|
132
|
-
// Assert
|
|
133
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Warning: No value found for'));
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('Should_ConfigureSSMClientWithProfile_When_ProfileIsProvided', async () => {
|
|
137
|
-
// Arrange
|
|
138
|
-
const mockProfile = 'test-profile';
|
|
139
|
-
const paramMapContent = {
|
|
140
|
-
NEXT_PUBLIC_CREDENTIAL_EMAIL: '/path/to/ssm/email',
|
|
141
|
-
};
|
|
142
|
-
fs.writeFileSync(mockMapPath, JSON.stringify(paramMapContent));
|
|
143
|
-
|
|
144
|
-
// Act
|
|
145
|
-
await run(mockMapPath, mockEnvFilePath, mockProfile);
|
|
146
|
-
|
|
147
|
-
// Assert
|
|
148
|
-
expect(vi.mocked(SSM).mock.calls[0][0]).toEqual(expect.objectContaining({ credentials: expect.anything() }));
|
|
149
|
-
});
|
|
150
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
TOKEN_SECRET=this_is_for_test
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compileOnSave": false,
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "Node",
|
|
6
|
-
"target": "es2016",
|
|
7
|
-
"outDir": "./lib",
|
|
8
|
-
"rootDir": ".",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"noImplicitAny": true,
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"lib": ["es2022"],
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"declarationMap": true,
|
|
16
|
-
"sourceMap": true,
|
|
17
|
-
"forceConsistentCasingInFileNames": true,
|
|
18
|
-
"resolveJsonModule": true,
|
|
19
|
-
"types": ["node", "picocolors"]
|
|
20
|
-
},
|
|
21
|
-
"include": ["src/**/*"]
|
|
22
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
include: ['tests/**/*.test.ts'],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: 'v8',
|
|
10
|
-
reporter: ['text', 'html', 'json'],
|
|
11
|
-
reportsDirectory: './coverage',
|
|
12
|
-
all: true,
|
|
13
|
-
include: ['src/**/*.ts'],
|
|
14
|
-
exclude: ['node_modules', 'test', 'coverage', 'dist'],
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
});
|
package/vitest.config.js
DELETED