envilder 0.2.0 → 0.2.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.
@@ -28,6 +28,6 @@ export function cliRunner() {
28
28
  });
29
29
  }
30
30
  cliRunner().catch((error) => {
31
- console.error('Error in CLI Runner:', error);
31
+ console.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
32
32
  });
33
33
  //# sourceMappingURL=cliRunner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cliRunner.js","sourceRoot":"","sources":["../../src/cli/cliRunner.ts"],"names":[],"mappings":";;;;;;;;;;AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,MAAM,UAAgB,SAAS;;QAC7B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;QAE9B,OAAO;aACJ,IAAI,CAAC,UAAU,CAAC;aAChB,WAAW,CAAC,2DAA2D,CAAC;aACxE,OAAO,CAAC,OAAO,CAAC;aAChB,cAAc,CAAC,cAAc,EAAE,yDAAyD,CAAC;aACzF,cAAc,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAC;QAE/E,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,CAAC,CAAC;IAC1C,CAAC;CAAA;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cliRunner.js","sourceRoot":"","sources":["../../src/cli/cliRunner.ts"],"names":[],"mappings":";;;;;;;;;;AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,MAAM,UAAgB,SAAS;;QAC7B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;QAE9B,OAAO;aACJ,IAAI,CAAC,UAAU,CAAC;aAChB,WAAW,CAAC,2DAA2D,CAAC;aACxE,OAAO,CAAC,OAAO,CAAC;aAChB,cAAc,CAAC,cAAc,EAAE,yDAAyD,CAAC;aACzF,cAAc,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAC;QAE/E,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,CAAC,CAAC;IAC1C,CAAC;CAAA;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC7E,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAQ7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAQ7D"}
package/lib/index.js CHANGED
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import * as fs from 'node:fs';
11
11
  import { GetParameterCommand, SSM } from '@aws-sdk/client-ssm';
12
+ import * as dotenv from 'dotenv';
12
13
  const ssm = new SSM({});
13
14
  export function run(mapPath, envFilePath) {
14
15
  return __awaiter(this, void 0, void 0, function* () {
@@ -16,46 +17,50 @@ export function run(mapPath, envFilePath) {
16
17
  const existingEnvVariables = loadExistingEnvVariables(envFilePath);
17
18
  const updatedEnvVariables = yield fetchAndUpdateEnvVariables(paramMap, existingEnvVariables);
18
19
  writeEnvFile(envFilePath, updatedEnvVariables);
19
- console.log(`.env file generated at ${envFilePath}`);
20
+ console.log(`Environment File generated at '${envFilePath}'`);
20
21
  });
21
22
  }
22
23
  function loadParamMap(mapPath) {
23
24
  const content = fs.readFileSync(mapPath, 'utf-8');
24
- return JSON.parse(content);
25
+ try {
26
+ return JSON.parse(content);
27
+ }
28
+ catch (error) {
29
+ console.error(`Error parsing JSON from ${mapPath}`);
30
+ throw new Error(`Invalid JSON in parameter map file: ${mapPath}`);
31
+ }
25
32
  }
26
33
  function loadExistingEnvVariables(envFilePath) {
27
34
  const envVariables = {};
28
35
  if (!fs.existsSync(envFilePath))
29
36
  return envVariables;
30
37
  const existingEnvContent = fs.readFileSync(envFilePath, 'utf-8');
31
- const lines = existingEnvContent.split('\n');
32
- for (const line of lines) {
33
- const [key, value] = line.split('=');
34
- if (key && value) {
35
- envVariables[key] = value;
36
- }
37
- }
38
+ const parsedEnv = dotenv.parse(existingEnvContent);
39
+ Object.assign(envVariables, parsedEnv);
38
40
  return envVariables;
39
41
  }
40
42
  function fetchAndUpdateEnvVariables(paramMap, existingEnvVariables) {
41
43
  return __awaiter(this, void 0, void 0, function* () {
42
- console.log('Fetching parameters...');
44
+ const errors = [];
43
45
  for (const [envVar, ssmName] of Object.entries(paramMap)) {
44
46
  try {
45
47
  const value = yield fetchSSMParameter(ssmName);
46
48
  if (value) {
47
49
  existingEnvVariables[envVar] = value;
48
- console.log(`${envVar}=${value}`);
50
+ console.log(`${envVar}=${value.length > 3 ? '*'.repeat(value.length - 3) + value.slice(-3) : '*'.repeat(value.length)}`);
49
51
  }
50
52
  else {
51
- console.error(`Warning: No value found for ${ssmName}`);
53
+ console.error(`Warning: No value found for: '${ssmName}'`);
52
54
  }
53
55
  }
54
56
  catch (error) {
55
- console.error(`Error fetching parameter ${ssmName}: ${error}`);
56
- throw new Error(`ParameterNotFound: ${ssmName}`);
57
+ console.error(`Error fetching parameter: '${ssmName}'`);
58
+ errors.push(`ParameterNotFound: ${ssmName}`);
57
59
  }
58
60
  }
61
+ if (errors.length > 0) {
62
+ throw new Error(`Some parameters could not be fetched:\n${errors.join('\n')}`);
63
+ }
59
64
  return existingEnvVariables;
60
65
  });
61
66
  }
@@ -71,7 +76,10 @@ function fetchSSMParameter(ssmName) {
71
76
  }
72
77
  function writeEnvFile(envFilePath, envVariables) {
73
78
  const envContent = Object.entries(envVariables)
74
- .map(([key, value]) => `${key}=${value}`)
79
+ .map(([key, value]) => {
80
+ const escapedValue = value.replace(/(\n|\r|\n\r)/g, '\\n').replace(/"/g, '\\"');
81
+ return `${key}=${escapedValue}`;
82
+ })
75
83
  .join('\n');
76
84
  fs.writeFileSync(envFilePath, envContent);
77
85
  }
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;AAExB,MAAM,UAAgB,GAAG,CAAC,OAAe,EAAE,WAAmB;;QAC5D,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,oBAAoB,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC;QAEnE,MAAM,mBAAmB,GAAG,MAAM,0BAA0B,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QAE7F,YAAY,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,kCAAkC,WAAW,GAAG,CAAC,CAAC;IAChE,CAAC;CAAA;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,WAAmB;IACnD,MAAM,YAAY,GAA2B,EAAE,CAAC;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,YAAY,CAAC;IAErD,MAAM,kBAAkB,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACnD,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAEvC,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAe,0BAA0B,CACvC,QAAgC,EAChC,oBAA4C;;QAE5C,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBAC/C,IAAI,KAAK,EAAE,CAAC;oBACV,oBAAoB,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;oBACrC,OAAO,CAAC,GAAG,CACT,GAAG,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,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,CAC5G,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CAAC,iCAAiC,OAAO,GAAG,CAAC,CAAC;gBAC7D,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,OAAO,GAAG,CAAC,CAAC;gBACxD,MAAM,CAAC,IAAI,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;QAED,OAAO,oBAAoB,CAAC;IAC9B,CAAC;CAAA;AAED,SAAe,iBAAiB,CAAC,OAAe;;QAC9C,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC;YACtC,IAAI,EAAE,OAAO;YACb,cAAc,EAAE,IAAI;SACrB,CAAC,CAAC;QAEH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,KAAK,CAAC;IAC1B,CAAC;CAAA;AAED,SAAS,YAAY,CAAC,WAAmB,EAAE,YAAoC;IAC7E,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;SAC5C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACpB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChF,OAAO,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;IAClC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAC5C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envilder",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A CLI tool to generate .env files from AWS SSM parameters",
5
5
  "exports": {
6
6
  ".": {
@@ -42,6 +42,7 @@
42
42
  "@secretlint/secretlint-rule-preset-recommend": "^8.2.4",
43
43
  "@types/node": "^22.5.5",
44
44
  "commander": "^12.1.0",
45
+ "dotenv": "^16.4.5",
45
46
  "picocolors": "^1.1.0"
46
47
  },
47
48
  "devDependencies": {
@@ -24,5 +24,5 @@ export async function cliRunner() {
24
24
  }
25
25
 
26
26
  cliRunner().catch((error) => {
27
- console.error('Error in CLI Runner:', error);
27
+ console.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
28
28
  });
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as fs from 'node:fs';
2
2
  import { GetParameterCommand, SSM } from '@aws-sdk/client-ssm';
3
+ import * as dotenv from 'dotenv';
3
4
 
4
5
  const ssm = new SSM({});
5
6
 
@@ -10,26 +11,27 @@ export async function run(mapPath: string, envFilePath: string) {
10
11
  const updatedEnvVariables = await fetchAndUpdateEnvVariables(paramMap, existingEnvVariables);
11
12
 
12
13
  writeEnvFile(envFilePath, updatedEnvVariables);
13
- console.log(`.env file generated at ${envFilePath}`);
14
+ console.log(`Environment File generated at '${envFilePath}'`);
14
15
  }
15
16
 
16
17
  function loadParamMap(mapPath: string): Record<string, string> {
17
18
  const content = fs.readFileSync(mapPath, 'utf-8');
18
- return JSON.parse(content);
19
+ try {
20
+ return JSON.parse(content);
21
+ } catch (error) {
22
+ console.error(`Error parsing JSON from ${mapPath}`);
23
+ throw new Error(`Invalid JSON in parameter map file: ${mapPath}`);
24
+ }
19
25
  }
20
26
 
21
27
  function loadExistingEnvVariables(envFilePath: string): Record<string, string> {
22
28
  const envVariables: Record<string, string> = {};
29
+
23
30
  if (!fs.existsSync(envFilePath)) return envVariables;
24
31
 
25
32
  const existingEnvContent = fs.readFileSync(envFilePath, 'utf-8');
26
- const lines = existingEnvContent.split('\n');
27
- for (const line of lines) {
28
- const [key, value] = line.split('=');
29
- if (key && value) {
30
- envVariables[key] = value;
31
- }
32
- }
33
+ const parsedEnv = dotenv.parse(existingEnvContent);
34
+ Object.assign(envVariables, parsedEnv);
33
35
 
34
36
  return envVariables;
35
37
  }
@@ -38,23 +40,29 @@ async function fetchAndUpdateEnvVariables(
38
40
  paramMap: Record<string, string>,
39
41
  existingEnvVariables: Record<string, string>,
40
42
  ): Promise<Record<string, string>> {
41
- console.log('Fetching parameters...');
43
+ const errors: string[] = [];
42
44
 
43
45
  for (const [envVar, ssmName] of Object.entries(paramMap)) {
44
46
  try {
45
47
  const value = await fetchSSMParameter(ssmName);
46
48
  if (value) {
47
49
  existingEnvVariables[envVar] = value;
48
- console.log(`${envVar}=${value}`);
50
+ console.log(
51
+ `${envVar}=${value.length > 3 ? '*'.repeat(value.length - 3) + value.slice(-3) : '*'.repeat(value.length)}`,
52
+ );
49
53
  } else {
50
- console.error(`Warning: No value found for ${ssmName}`);
54
+ console.error(`Warning: No value found for: '${ssmName}'`);
51
55
  }
52
56
  } catch (error) {
53
- console.error(`Error fetching parameter ${ssmName}: ${error}`);
54
- throw new Error(`ParameterNotFound: ${ssmName}`);
57
+ console.error(`Error fetching parameter: '${ssmName}'`);
58
+ errors.push(`ParameterNotFound: ${ssmName}`);
55
59
  }
56
60
  }
57
61
 
62
+ if (errors.length > 0) {
63
+ throw new Error(`Some parameters could not be fetched:\n${errors.join('\n')}`);
64
+ }
65
+
58
66
  return existingEnvVariables;
59
67
  }
60
68
 
@@ -70,7 +78,10 @@ async function fetchSSMParameter(ssmName: string): Promise<string | undefined> {
70
78
 
71
79
  function writeEnvFile(envFilePath: string, envVariables: Record<string, string>): void {
72
80
  const envContent = Object.entries(envVariables)
73
- .map(([key, value]) => `${key}=${value}`)
81
+ .map(([key, value]) => {
82
+ const escapedValue = value.replace(/(\n|\r|\n\r)/g, '\\n').replace(/"/g, '\\"');
83
+ return `${key}=${escapedValue}`;
84
+ })
74
85
  .join('\n');
75
86
 
76
87
  fs.writeFileSync(envFilePath, envContent);
@@ -79,9 +79,7 @@ describe('Envilder CLI', () => {
79
79
  const mockMapPath = './tests/param_map.json';
80
80
  const mockEnvFilePath = './tests/.env.test';
81
81
 
82
- const existingEnvContent = `
83
- EXISTING_VAR=existingValue
84
- `;
82
+ const existingEnvContent = 'EXISTING_VAR=existingValue';
85
83
  fs.writeFileSync(mockEnvFilePath, existingEnvContent);
86
84
  const paramMapContent = {
87
85
  NEXT_PUBLIC_CREDENTIAL_EMAIL: '/path/to/ssm/email',
@@ -105,9 +103,7 @@ describe('Envilder CLI', () => {
105
103
  // Arrange
106
104
  const mockMapPath = './tests/param_map.json';
107
105
  const mockEnvFilePath = './tests/.env.test';
108
- const existingEnvContent = `
109
- NEXT_PUBLIC_CREDENTIAL_EMAIL=oldEmail@example.com
110
- `;
106
+ const existingEnvContent = 'NEXT_PUBLIC_CREDENTIAL_EMAIL=oldEmail@example.com';
111
107
  fs.writeFileSync(mockEnvFilePath, existingEnvContent);
112
108
  const paramMapContent = {
113
109
  NEXT_PUBLIC_CREDENTIAL_EMAIL: '/path/to/ssm/email',