@karmaniverous/get-dotenv 2.4.4 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bin/getdotenv/index.js +18 -10
- package/dist/default/lib/dotenvExpand.js +47 -0
- package/dist/default/lib/getAwsSsoCredentials.js +33 -0
- package/dist/default/lib/index.js +14 -0
- package/lib/dotenvExpand.js +49 -0
- package/lib/getAwsSsoCredentials.js +28 -0
- package/lib/index.js +2 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ dotenv files. You can:
|
|
|
85
85
|
arguments for other options.
|
|
86
86
|
* Specify the token that identifies dotenv files (e.g. '.env').
|
|
87
87
|
* Specify the token that identifies private vatiables (e.g. '.local').
|
|
88
|
+
* Load AWS SSO session credentials from an AWS Toolkit profile.
|
|
88
89
|
|
|
89
90
|
Options:
|
|
90
91
|
-p, --paths <strings...> space-delimited paths to dotenv directory (default './')
|
|
@@ -103,6 +104,7 @@ Options:
|
|
|
103
104
|
-t, --dotenv-token <string> token indicating a dotenv file (default: '.env')
|
|
104
105
|
-i, --private-token <string> token indicating private variables (default: 'local')
|
|
105
106
|
-q, --quit-on-error terminate sequential process on error (default: false)
|
|
107
|
+
-a, --aws-sso-profile <string> local AWS SSO profile (follows dotenv-expand rules)
|
|
106
108
|
-h, --help display help for command
|
|
107
109
|
```
|
|
108
110
|
|
package/bin/getdotenv/index.js
CHANGED
|
@@ -2,20 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
// Import npm packages.
|
|
4
4
|
import spawn from 'cross-spawn';
|
|
5
|
-
import _ from 'lodash';
|
|
6
5
|
import { parseArgsStringToArgv } from 'string-argv';
|
|
7
6
|
|
|
8
7
|
// Import package exports.
|
|
9
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
dotenvExpand,
|
|
10
|
+
getAwsSsoCredentials,
|
|
11
|
+
getDotenv,
|
|
12
|
+
parseBranch,
|
|
13
|
+
} from '@karmaniverous/get-dotenv';
|
|
10
14
|
|
|
11
15
|
// Create CLI.
|
|
12
16
|
import { program } from 'commander';
|
|
13
17
|
|
|
14
|
-
const envMerge = (value) =>
|
|
15
|
-
!_.isUndefined(value) && value.startsWith('$')
|
|
16
|
-
? process.env[value.slice(1)]
|
|
17
|
-
: value;
|
|
18
|
-
|
|
19
18
|
// CLI description.
|
|
20
19
|
program
|
|
21
20
|
.name('getdotenv')
|
|
@@ -40,6 +39,7 @@ program
|
|
|
40
39
|
` arguments for other options.`,
|
|
41
40
|
`* Specify the token that identifies dotenv files (e.g. '.env').`,
|
|
42
41
|
`* Specify the token that identifies private vatiables (e.g. '.local').`,
|
|
42
|
+
`* Load AWS SSO session credentials from an AWS Toolkit profile.`,
|
|
43
43
|
].join('\n')
|
|
44
44
|
);
|
|
45
45
|
|
|
@@ -57,17 +57,17 @@ program
|
|
|
57
57
|
.option(
|
|
58
58
|
'-d, --default-environment <string>',
|
|
59
59
|
'default environment (prefix with $ to use environment variable)',
|
|
60
|
-
|
|
60
|
+
dotenvExpand
|
|
61
61
|
)
|
|
62
62
|
.option(
|
|
63
63
|
'-b, --branch-to-default',
|
|
64
64
|
'derive default environment from the current git branch (default: false)',
|
|
65
|
-
|
|
65
|
+
dotenvExpand
|
|
66
66
|
)
|
|
67
67
|
.option(
|
|
68
68
|
'-e, --environment <string>',
|
|
69
69
|
'designated environment (prefix with $ to use environment variable)',
|
|
70
|
-
|
|
70
|
+
dotenvExpand
|
|
71
71
|
)
|
|
72
72
|
.option(
|
|
73
73
|
'-n, --exclude-env',
|
|
@@ -93,11 +93,16 @@ program
|
|
|
93
93
|
.option(
|
|
94
94
|
'-q, --quit-on-error',
|
|
95
95
|
'terminate sequential process on error (default: false)'
|
|
96
|
+
)
|
|
97
|
+
.option(
|
|
98
|
+
'-a, --aws-sso-profile <string>',
|
|
99
|
+
'local AWS SSO profile (follows dotenv-expand rules)'
|
|
96
100
|
);
|
|
97
101
|
|
|
98
102
|
// Parse CLI options from command line.
|
|
99
103
|
program.parse();
|
|
100
104
|
const {
|
|
105
|
+
awsSsoProfile,
|
|
101
106
|
branchToDefault,
|
|
102
107
|
command,
|
|
103
108
|
defaultEnvironment,
|
|
@@ -140,6 +145,9 @@ await getDotenv({
|
|
|
140
145
|
privateToken,
|
|
141
146
|
});
|
|
142
147
|
|
|
148
|
+
// Get AWS SSO credentials.
|
|
149
|
+
if (awsSsoProfile) getAwsSsoCredentials(dotenvExpand(awsSsoProfile));
|
|
150
|
+
|
|
143
151
|
// Execute shell command.
|
|
144
152
|
if (command || program.args.length) {
|
|
145
153
|
const argvs = (command ?? program.args.join(' '))
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.dotenvExpand = void 0;
|
|
7
|
+
// like String.prototype.search but returns the last index
|
|
8
|
+
const _searchLast = (str, rgx) => {
|
|
9
|
+
const matches = Array.from(str.matchAll(rgx));
|
|
10
|
+
return matches.length > 0 ? matches.slice(-1)[0].index : -1;
|
|
11
|
+
};
|
|
12
|
+
const _interpolate = envValue => {
|
|
13
|
+
// find the last unescaped dollar sign in the
|
|
14
|
+
// value so that we can evaluate it
|
|
15
|
+
const lastUnescapedDollarSignIndex = _searchLast(envValue, /(?!(?<=\\))\$/g);
|
|
16
|
+
|
|
17
|
+
// If we couldn't match any unescaped dollar sign
|
|
18
|
+
// let's return the string as is
|
|
19
|
+
if (lastUnescapedDollarSignIndex === -1) return envValue;
|
|
20
|
+
|
|
21
|
+
// This is the right-most group of variables in the string
|
|
22
|
+
const rightMostGroup = envValue.slice(lastUnescapedDollarSignIndex);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This finds the inner most variable/group divided
|
|
26
|
+
* by variable name and default value (if present)
|
|
27
|
+
* (
|
|
28
|
+
* (?!(?<=\\))\$ // only match dollar signs that are not escaped
|
|
29
|
+
* {? // optional opening curly brace
|
|
30
|
+
* ([\w]+) // match the variable name
|
|
31
|
+
* (?::-([^}\\]*))? // match an optional default value
|
|
32
|
+
* }? // optional closing curly brace
|
|
33
|
+
* )
|
|
34
|
+
*/
|
|
35
|
+
const matchGroup = /((?!(?<=\\))\${?([\w]+)(?::-([^}\\]*))?}?)/;
|
|
36
|
+
const match = rightMostGroup.match(matchGroup);
|
|
37
|
+
if (match != null) {
|
|
38
|
+
const [, group, variableName, defaultValue] = match;
|
|
39
|
+
return _interpolate(envValue.replace(group, process.env[variableName] || defaultValue || ''));
|
|
40
|
+
}
|
|
41
|
+
return envValue;
|
|
42
|
+
};
|
|
43
|
+
const _resolveEscapeSequences = value => {
|
|
44
|
+
return value.replace(/\\\$/g, '$');
|
|
45
|
+
};
|
|
46
|
+
const dotenvExpand = value => _resolveEscapeSequences(_interpolate(value));
|
|
47
|
+
exports.dotenvExpand = dotenvExpand;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getAwsSsoCredentials = void 0;
|
|
7
|
+
var _crossSpawn = _interopRequireDefault(require("cross-spawn"));
|
|
8
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
+
// npm imports
|
|
10
|
+
|
|
11
|
+
const getAwsSsoCredentials = localProfile => {
|
|
12
|
+
if (!localProfile) {
|
|
13
|
+
delete process.env.AWS_ACCESS_KEY_ID;
|
|
14
|
+
delete process.env.AWS_SECRET_ACCESS_KEY;
|
|
15
|
+
delete process.env.AWS_SESSION_TOKEN;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const {
|
|
19
|
+
status,
|
|
20
|
+
stderr,
|
|
21
|
+
stdout
|
|
22
|
+
} = _crossSpawn.default.sync('aws', ['configure', 'export-credentials', '--profile', localProfile]);
|
|
23
|
+
if (status) throw new Error(stderr.toString());
|
|
24
|
+
const {
|
|
25
|
+
AccessKeyId,
|
|
26
|
+
SecretAccessKey,
|
|
27
|
+
SessionToken
|
|
28
|
+
} = JSON.parse(stdout.toString());
|
|
29
|
+
process.env.AWS_ACCESS_KEY_ID = AccessKeyId;
|
|
30
|
+
process.env.AWS_SECRET_ACCESS_KEY = SecretAccessKey;
|
|
31
|
+
process.env.AWS_SESSION_TOKEN = SessionToken;
|
|
32
|
+
};
|
|
33
|
+
exports.getAwsSsoCredentials = getAwsSsoCredentials;
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "dotenvExpand", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _dotenvExpand.dotenvExpand;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "getAwsSsoCredentials", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _getAwsSsoCredentials.getAwsSsoCredentials;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
6
18
|
Object.defineProperty(exports, "getDotenv", {
|
|
7
19
|
enumerable: true,
|
|
8
20
|
get: function () {
|
|
@@ -21,5 +33,7 @@ Object.defineProperty(exports, "parseBranch", {
|
|
|
21
33
|
return _parseBranch.parseBranch;
|
|
22
34
|
}
|
|
23
35
|
});
|
|
36
|
+
var _dotenvExpand = require("./dotenvExpand.js");
|
|
37
|
+
var _getAwsSsoCredentials = require("./getAwsSsoCredentials.js");
|
|
24
38
|
var _getDotenv = require("./getDotenv.js");
|
|
25
39
|
var _parseBranch = require("./parseBranch.js");
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// like String.prototype.search but returns the last index
|
|
2
|
+
const _searchLast = (str, rgx) => {
|
|
3
|
+
const matches = Array.from(str.matchAll(rgx));
|
|
4
|
+
return matches.length > 0 ? matches.slice(-1)[0].index : -1;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const _interpolate = (envValue) => {
|
|
8
|
+
// find the last unescaped dollar sign in the
|
|
9
|
+
// value so that we can evaluate it
|
|
10
|
+
const lastUnescapedDollarSignIndex = _searchLast(envValue, /(?!(?<=\\))\$/g);
|
|
11
|
+
|
|
12
|
+
// If we couldn't match any unescaped dollar sign
|
|
13
|
+
// let's return the string as is
|
|
14
|
+
if (lastUnescapedDollarSignIndex === -1) return envValue;
|
|
15
|
+
|
|
16
|
+
// This is the right-most group of variables in the string
|
|
17
|
+
const rightMostGroup = envValue.slice(lastUnescapedDollarSignIndex);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This finds the inner most variable/group divided
|
|
21
|
+
* by variable name and default value (if present)
|
|
22
|
+
* (
|
|
23
|
+
* (?!(?<=\\))\$ // only match dollar signs that are not escaped
|
|
24
|
+
* {? // optional opening curly brace
|
|
25
|
+
* ([\w]+) // match the variable name
|
|
26
|
+
* (?::-([^}\\]*))? // match an optional default value
|
|
27
|
+
* }? // optional closing curly brace
|
|
28
|
+
* )
|
|
29
|
+
*/
|
|
30
|
+
const matchGroup = /((?!(?<=\\))\${?([\w]+)(?::-([^}\\]*))?}?)/;
|
|
31
|
+
const match = rightMostGroup.match(matchGroup);
|
|
32
|
+
|
|
33
|
+
if (match != null) {
|
|
34
|
+
const [, group, variableName, defaultValue] = match;
|
|
35
|
+
|
|
36
|
+
return _interpolate(
|
|
37
|
+
envValue.replace(group, process.env[variableName] || defaultValue || '')
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return envValue;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const _resolveEscapeSequences = (value) => {
|
|
45
|
+
return value.replace(/\\\$/g, '$');
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const dotenvExpand = (value) =>
|
|
49
|
+
_resolveEscapeSequences(_interpolate(value));
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// npm imports
|
|
2
|
+
import spawn from 'cross-spawn';
|
|
3
|
+
|
|
4
|
+
export const getAwsSsoCredentials = (localProfile) => {
|
|
5
|
+
if (!localProfile) {
|
|
6
|
+
delete process.env.AWS_ACCESS_KEY_ID;
|
|
7
|
+
delete process.env.AWS_SECRET_ACCESS_KEY;
|
|
8
|
+
delete process.env.AWS_SESSION_TOKEN;
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { status, stderr, stdout } = spawn.sync('aws', [
|
|
13
|
+
'configure',
|
|
14
|
+
'export-credentials',
|
|
15
|
+
'--profile',
|
|
16
|
+
localProfile,
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
if (status) throw new Error(stderr.toString());
|
|
20
|
+
|
|
21
|
+
const { AccessKeyId, SecretAccessKey, SessionToken } = JSON.parse(
|
|
22
|
+
stdout.toString()
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
process.env.AWS_ACCESS_KEY_ID = AccessKeyId;
|
|
26
|
+
process.env.AWS_SECRET_ACCESS_KEY = SecretAccessKey;
|
|
27
|
+
process.env.AWS_SESSION_TOKEN = SessionToken;
|
|
28
|
+
};
|
package/lib/index.js
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"bin": {
|
|
4
4
|
"getdotenv": "bin/getdotenv/index.js"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.6.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -85,12 +85,12 @@
|
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"cli": "node ./bin/getdotenv",
|
|
88
|
-
"lint": "eslint lib/** bin/**",
|
|
89
|
-
"test": "mocha",
|
|
90
88
|
"build": "babel lib -d dist/default/lib --delete-dir-on-start --config-file ./dist/default/.babelrc",
|
|
91
89
|
"doc": "jsdoc2md -c doc/jsdoc.config.json -f lib/**/*.* -t doc/api-template.hbs > doc/3-api.jsdoc2.md && concat-md doc --hide-anchor-links > README.md",
|
|
92
|
-
"
|
|
93
|
-
"
|
|
90
|
+
"lint": "eslint lib/** bin/**",
|
|
91
|
+
"prerelease": "npm run lint && npm run test && npm run build && npm run doc",
|
|
92
|
+
"release": "release-it",
|
|
93
|
+
"test": "mocha"
|
|
94
94
|
},
|
|
95
95
|
"type": "module"
|
|
96
96
|
}
|