@karmaniverous/get-dotenv 2.6.8 → 3.0.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.
@@ -7,7 +7,8 @@ exports.getDotenvSync = exports.getDotenv = void 0;
7
7
  var _dotenvExpand = require("dotenv-expand");
8
8
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
9
9
  var _path = _interopRequireDefault(require("path"));
10
- var _uuid = require("uuid");
10
+ var _nanoid = require("nanoid");
11
+ var _dotenvDefaults = require("./dotenvDefaults.js");
11
12
  var _readDotenv = require("./readDotenv.js");
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  // npm imports
@@ -19,19 +20,21 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
19
20
  *
20
21
  * @typedef {Object} OptionsType
21
22
  *
22
- * @property {string} [dotenvToken] - token indicating a dotenv file (default: '.env')
23
+ * @property {string} [dotenvToken] - token indicating a dotenv file
23
24
  * @property {string} [dynamicPath] - path to file exporting an object keyed to dynamic variable functions
24
25
  * @property {string} [env] - target environment
25
- * @property {bool} [excludeDynamic] - exclude dynamic variables (default: false)
26
- * @property {bool} [excludeEnv] - exclude environment-specific variables (default: false)
27
- * @property {bool} [excludeGlobal] - exclude global & dynamic variables (default: false)
28
- * @property {bool} [excludePrivate] - exclude private variables (default: false)
29
- * @property {bool} [excludePublic] - exclude public variables (default: false)
30
- * @property {bool} [loadProcess] - load dotenv to process.env (default: false)
31
- * @property {bool} [log] - log result to console (default: false)
26
+ * @property {bool} [excludeDynamic] - exclude dynamic variables
27
+ * @property {bool} [excludeEnv] - exclude environment-specific variables
28
+ * @property {bool} [excludeGlobal] - exclude global & dynamic variables
29
+ * @property {bool} [excludePrivate] - exclude private variables
30
+ * @property {bool} [excludePublic] - exclude public variables
31
+ * @property {bool} [loadProcess] - load dotenv to process.env
32
+ * @property {bool} [log] - log result to logger
33
+ * @property {function} [logger] - logger function
32
34
  * @property {string} [outputPath] - if populated, writes consolidated .env file to this path (follows {@link https://github.com/motdotla/dotenv-expand/blob/master/tests/.env dotenv-expand rules})
33
- * @property {string[]} [paths] - array of input directory paths (default ['./'])
34
- * @property {string} [privateToken] - token indicating private variables (default: 'local').
35
+ * @property {string[]} [paths] - array of input directory paths
36
+ * @property {string} [privateToken] - token indicating private variables
37
+ * @property {object} [vars] - explicit variables to include
35
38
  */
36
39
 
37
40
  /**
@@ -45,40 +48,52 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
45
48
  * @returns {Promise<object>} The combined parsed dotenv object.
46
49
  */
47
50
  const getDotenv = async function () {
51
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
52
+ // Apply defaults.
48
53
  let {
49
- dotenvToken = '.env',
54
+ dotenvToken,
50
55
  env,
51
56
  dynamicPath,
52
- excludeDynamic = false,
53
- excludeEnv = false,
54
- excludeGlobal = false,
55
- excludePrivate = false,
56
- excludePublic = false,
57
- loadProcess = false,
58
- log = false,
57
+ excludeDynamic,
58
+ excludeEnv,
59
+ excludeGlobal,
60
+ excludePrivate,
61
+ excludePublic,
62
+ loadProcess,
63
+ log,
64
+ logger,
59
65
  outputPath,
60
- paths = ['./'],
61
- privateToken = 'local'
62
- } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
66
+ paths,
67
+ privateToken,
68
+ vars = {}
69
+ } = {
70
+ ..._dotenvDefaults.dotenvDefaults,
71
+ ...options
72
+ };
73
+
63
74
  // Read .env files.
64
- const parsed = await paths.reduce(async (e, p) => ({
65
- ...(await e),
66
- ...(excludePublic ? {} : {
67
- ...(excludeGlobal ? {} : await (0, _readDotenv.readDotenv)(_path.default.resolve(p, dotenvToken))),
68
- ...(env && !excludeEnv ? await (0, _readDotenv.readDotenv)(_path.default.resolve(p, `${dotenvToken}.${env}`)) : {})
69
- }),
70
- ...(excludePrivate ? {} : {
71
- ...(excludeGlobal ? {} : await (0, _readDotenv.readDotenv)(_path.default.resolve(p, `${dotenvToken}.${privateToken}`))),
72
- ...(env && !excludeEnv ? await (0, _readDotenv.readDotenv)(_path.default.resolve(p, `${dotenvToken}.${env}.${privateToken}`)) : {})
73
- })
74
- }), {});
75
- const outputKey = (0, _uuid.v4)();
75
+ const loaded = await paths.reduce(async (e, p) => {
76
+ let publicGlobal = excludePublic || excludeGlobal ? {} : (0, _readDotenv.readDotenv)(_path.default.resolve(p, dotenvToken));
77
+ let publicEnv = excludePublic || excludeEnv ? {} : (0, _readDotenv.readDotenv)(_path.default.resolve(p, `${dotenvToken}.${env}`));
78
+ let privateGlobal = excludePrivate || excludeGlobal ? {} : (0, _readDotenv.readDotenv)(_path.default.resolve(p, `${dotenvToken}.${privateToken}`));
79
+ let privateEnv = excludePrivate || excludeEnv ? {} : (0, _readDotenv.readDotenv)(_path.default.resolve(p, `${dotenvToken}.${env}.${privateToken}`));
80
+ [e, publicGlobal, publicEnv, privateGlobal, privateEnv] = await Promise.all([e, publicGlobal, publicEnv, privateGlobal, privateEnv]);
81
+ return {
82
+ ...e,
83
+ ...publicGlobal,
84
+ ...publicEnv,
85
+ ...privateGlobal,
86
+ ...privateEnv
87
+ };
88
+ }, {});
89
+ const outputKey = (0, _nanoid.nanoid)();
76
90
  const {
77
91
  parsed: dotenv
78
92
  } = (0, _dotenvExpand.expand)({
79
93
  ignoreProcessEnv: true,
80
94
  parsed: {
81
- ...parsed,
95
+ ...loaded,
96
+ ...vars,
82
97
  ...(outputPath ? {
83
98
  [outputKey]: outputPath
84
99
  } : {})
@@ -108,14 +123,14 @@ const getDotenv = async function () {
108
123
  }
109
124
 
110
125
  // Log result.
111
- if (log) console.log(dotenv);
126
+ if (log) logger(dotenv);
112
127
 
113
128
  // Load process.env.
114
129
  if (loadProcess) Object.assign(process.env, dotenv, {
115
130
  getdotenvOptions: JSON.stringify({
116
131
  dotenvToken,
117
- dynamicPath,
118
132
  env,
133
+ dynamicPath,
119
134
  excludeDynamic,
120
135
  excludeEnv,
121
136
  excludeGlobal,
@@ -142,40 +157,50 @@ const getDotenv = async function () {
142
157
  */
143
158
  exports.getDotenv = getDotenv;
144
159
  const getDotenvSync = function () {
160
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
161
+ // Apply defaults.
145
162
  let {
146
- dotenvToken = '.env',
147
- dynamicPath,
163
+ dotenvToken,
148
164
  env,
149
- excludeDynamic = false,
150
- excludeEnv = false,
151
- excludeGlobal = false,
152
- excludePrivate = false,
153
- excludePublic = false,
154
- loadProcess = false,
155
- log = false,
165
+ dynamicPath,
166
+ excludeDynamic,
167
+ excludeEnv,
168
+ excludeGlobal,
169
+ excludePrivate,
170
+ excludePublic,
171
+ loadProcess,
172
+ log,
156
173
  outputPath,
157
- paths = ['./'],
158
- privateToken = 'local'
159
- } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
174
+ paths,
175
+ privateToken,
176
+ vars
177
+ } = {
178
+ ..._dotenvDefaults.dotenvDefaults,
179
+ ...options
180
+ };
181
+
160
182
  // Read .env files.
161
- const parsed = paths.reduce((e, p) => ({
162
- ...e,
163
- ...(excludePublic ? {} : {
164
- ...(excludeGlobal ? {} : (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, dotenvToken))),
165
- ...(env && !excludeEnv ? (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, `${dotenvToken}.${env}`)) : {})
166
- }),
167
- ...(excludePrivate ? {} : {
168
- ...(excludeGlobal ? {} : (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, `${dotenvToken}.${privateToken}`))),
169
- ...(env && !excludeEnv ? (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, `${dotenvToken}.${env}.${privateToken}`)) : {})
170
- })
171
- }), {});
172
- const outputKey = (0, _uuid.v4)();
183
+ const loaded = paths.reduce((e, p) => {
184
+ let publicGlobal = excludePublic || excludeGlobal ? {} : (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, dotenvToken));
185
+ let publicEnv = excludePublic || excludeEnv ? {} : (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, `${dotenvToken}.${env}`));
186
+ let privateGlobal = excludePrivate || excludeGlobal ? {} : (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, `${dotenvToken}.${privateToken}`));
187
+ let privateEnv = excludePrivate || excludeEnv ? {} : (0, _readDotenv.readDotenvSync)(_path.default.resolve(p, `${dotenvToken}.${env}.${privateToken}`));
188
+ return {
189
+ ...e,
190
+ ...publicGlobal,
191
+ ...publicEnv,
192
+ ...privateGlobal,
193
+ ...privateEnv
194
+ };
195
+ }, {});
196
+ const outputKey = (0, _nanoid.nanoid)();
173
197
  const {
174
198
  parsed: dotenv
175
199
  } = (0, _dotenvExpand.expand)({
176
200
  ignoreProcessEnv: true,
177
201
  parsed: {
178
- ...parsed,
202
+ ...loaded,
203
+ ...vars,
179
204
  ...(outputPath ? {
180
205
  [outputKey]: outputPath
181
206
  } : {})
@@ -9,10 +9,10 @@ Object.defineProperty(exports, "dotenvExpand", {
9
9
  return _dotenvExpand.dotenvExpand;
10
10
  }
11
11
  });
12
- Object.defineProperty(exports, "getAwsSsoCredentials", {
12
+ Object.defineProperty(exports, "getCli", {
13
13
  enumerable: true,
14
14
  get: function () {
15
- return _getAwsSsoCredentials.getAwsSsoCredentials;
15
+ return _getCli.getCli;
16
16
  }
17
17
  });
18
18
  Object.defineProperty(exports, "getDotenv", {
@@ -27,13 +27,6 @@ Object.defineProperty(exports, "getDotenvSync", {
27
27
  return _getDotenv.getDotenvSync;
28
28
  }
29
29
  });
30
- Object.defineProperty(exports, "parseBranch", {
31
- enumerable: true,
32
- get: function () {
33
- return _parseBranch.parseBranch;
34
- }
35
- });
36
30
  var _dotenvExpand = require("./dotenvExpand.js");
37
- var _getAwsSsoCredentials = require("./getAwsSsoCredentials.js");
38
31
  var _getDotenv = require("./getDotenv.js");
39
- var _parseBranch = require("./parseBranch.js");
32
+ var _getCli = require("./getCli.js");
@@ -0,0 +1,13 @@
1
+ export const dotenvDefaults = {
2
+ dotenvToken: '.env',
3
+ excludeDynamic: false,
4
+ excludeEnv: false,
5
+ excludeGlobal: false,
6
+ excludePrivate: false,
7
+ excludePublic: false,
8
+ loadProcess: false,
9
+ log: false,
10
+ logger: console.log,
11
+ paths: ['./'],
12
+ privateToken: 'local',
13
+ };
package/lib/getCli.js ADDED
@@ -0,0 +1,282 @@
1
+ // npm imports
2
+ import { boolean } from 'boolean';
3
+ import { Command } from 'commander';
4
+ import { execaCommand } from 'execa';
5
+ import fromPairs from 'lodash.frompairs';
6
+ import isString from 'lodash.isstring';
7
+
8
+ // lib imports
9
+ import { dotenvDefaults } from './dotenvDefaults.js';
10
+ import { dotenvExpand } from './dotenvExpand.js';
11
+ import { getDotenv } from './getDotenv.js';
12
+
13
+ const booleanExpand = (value) => boolean(dotenvExpand(value));
14
+
15
+ /**
16
+ * GetDotenv CLI Options type
17
+ *
18
+ * @typedef {Object} GetDotenvCliOptions
19
+ * @property {string} [cliInvocation] - cli invocation string (used for cli help)
20
+ * @property {string} [dotenvToken] - token indicating a dotenv file
21
+ * @property {string} [dynamicPath] - path to file exporting an object keyed to dynamic variable functions
22
+ * @property {string} [env] - target environment
23
+ * @property {bool} [excludeDynamic] - exclude dynamic variables
24
+ * @property {bool} [excludeEnv] - exclude environment-specific variables
25
+ * @property {bool} [excludeGlobal] - exclude global & dynamic variables
26
+ * @property {bool} [excludePrivate] - exclude private variables
27
+ * @property {bool} [excludePublic] - exclude public variables
28
+ * @property {bool} [log] - log result to console
29
+ * @property {function} [logger] - logger function
30
+ * @property {string} [outputPath] - if populated, writes consolidated .env file to this path (follows {@link https://github.com/motdotla/dotenv-expand/blob/master/tests/.env dotenv-expand rules})
31
+ * @property {string} [paths] - space-delimited list of input directory paths
32
+ * @property {string} [privateToken] - token indicating private variables.
33
+ * @property {bool|string} [shell] - execa shell option
34
+ * @property {bool} [suppressDotenv] - suppress dotenv loading
35
+ */
36
+
37
+ /**
38
+ * GetDotenv CLI Pre-hook Callback type. Transforms inbound options & executes side effects.
39
+ *
40
+ * @async
41
+ * @callback GetDotenvPreHookCallback
42
+ * @param {GetDotenvCliOptions} options - inbound GetDotenv CLI Options object
43
+ * @returns {GetDotenvCliOptions} transformed GetDotenv CLI Options object (undefined return value is ignored)
44
+ */
45
+
46
+ /**
47
+ * GetDotenv CLI Post-hook Callback type. Executes side effects within getdotenv context.
48
+ *
49
+ * @async
50
+ * @callback GetDotenvPostHookCallback
51
+ * @param {GetDotenvCliOptions} options - GetDotenv CLI Options object
52
+ * @param {object} dotenv - dotenv object
53
+ */
54
+
55
+ /**
56
+ * GetDotenv CLI Config type
57
+ *
58
+ * @typedef {Object} GetDotenvCliConfig
59
+ * @property {object} [config] - config options
60
+ * @property {GetDotenvCliOptions} [config.defaultOptions] - default options
61
+ * @property {GetDotenvPreHookCallback} [config.preHook] - transforms inbound options & executes side effects
62
+ * @property {GetDotenvPostHookCallback} [config.postHook] - executes side effects within getdotenv context
63
+ */
64
+
65
+ /**
66
+ * Generate a CLI for get-dotenv.
67
+ *
68
+ * @param {GetDotenvCliConfig} [config] - config object
69
+ * @returns {object} The CLI command.
70
+ */
71
+ export const getCli = ({ defaultOptions = {}, preHook, postHook } = {}) => {
72
+ let {
73
+ cliInvocation = 'getdotenv',
74
+ command,
75
+ dotenvToken,
76
+ dynamicPath,
77
+ env,
78
+ excludeDynamic,
79
+ excludeEnv,
80
+ excludeGlobal,
81
+ excludePrivate,
82
+ excludePublic,
83
+ log,
84
+ outputPath,
85
+ paths,
86
+ pathsDelimiter = '\\s+',
87
+ privateToken,
88
+ shell,
89
+ suppressDotenv,
90
+ vars,
91
+ varsAssignor = '=',
92
+ varsDelimiter = '\\s+',
93
+ } = {
94
+ ...dotenvDefaults,
95
+ ...defaultOptions,
96
+ };
97
+
98
+ if (Array.isArray(paths)) paths = paths.join(' ');
99
+
100
+ return (
101
+ new Command()
102
+ .name(cliInvocation)
103
+ // .usage('[options] [command] [command options] [commad args]')
104
+ .description(
105
+ 'Base CLI. All options except delimiters follow dotenv-expand rules.'
106
+ )
107
+ .enablePositionalOptions()
108
+ .passThroughOptions()
109
+ .option('-e, --env <string>', 'environment name', dotenvExpand, env)
110
+ .option(
111
+ '-p, --paths <string>',
112
+ 'delimited list of paths to dotenv directory',
113
+ dotenvExpand,
114
+ paths
115
+ )
116
+ .option(
117
+ '--paths-delimiter <string>',
118
+ 'regex paths delimiter',
119
+ pathsDelimiter
120
+ )
121
+ .option(
122
+ '-v, --vars <string>',
123
+ 'delimited list KEY=VALUE pairs',
124
+ dotenvExpand,
125
+ vars
126
+ )
127
+ .option(
128
+ '--vars-delimiter <string>',
129
+ 'regex vars delimiter',
130
+ varsDelimiter
131
+ )
132
+ .option(
133
+ '--vars-assignor <string>',
134
+ 'regex vars assignment operator',
135
+ varsAssignor
136
+ )
137
+ .option(
138
+ '-y, --dynamic-path <string>',
139
+ 'dynamic variables path',
140
+ dotenvExpand,
141
+ dynamicPath
142
+ )
143
+ .option(
144
+ '-o, --output-path <string>',
145
+ 'consolidated output file, follows dotenv-expand rules using loaded env vars',
146
+ dotenvExpand,
147
+ outputPath
148
+ )
149
+ .option(
150
+ '-n, --exclude-env [bool]',
151
+ 'exclude environment-specific variables',
152
+ booleanExpand,
153
+ excludeEnv ?? false
154
+ )
155
+ .option(
156
+ '-g, --exclude-global [bool]',
157
+ 'exclude global & dynamic variables',
158
+ booleanExpand,
159
+ excludeGlobal ?? false
160
+ )
161
+ .option(
162
+ '-r, --exclude-private [bool]',
163
+ 'exclude private variables',
164
+ booleanExpand,
165
+ excludePrivate ?? false
166
+ )
167
+ .option(
168
+ '-u, --exclude-public [bool]',
169
+ 'exclude public variables',
170
+ booleanExpand,
171
+ excludePublic ?? false
172
+ )
173
+ .option(
174
+ '-z, --exclude-dynamic [bool]',
175
+ 'exclude dynamic variables',
176
+ booleanExpand,
177
+ excludeDynamic ?? false
178
+ )
179
+ .option(
180
+ '-l, --log [bool]',
181
+ 'console log extracted variables',
182
+ booleanExpand,
183
+ log ?? false
184
+ )
185
+ .option(
186
+ '-x, --suppress-dotenv',
187
+ 'suppress dotenv loading',
188
+ booleanExpand,
189
+ suppressDotenv ?? false
190
+ )
191
+ .option(
192
+ '-c, --command <string>',
193
+ 'shell command string',
194
+ dotenvExpand,
195
+ command
196
+ )
197
+ .option('-s, --shell <string>', 'execa shell option', dotenvExpand, shell)
198
+ .option(
199
+ '--dotenv-token <string>',
200
+ 'token indicating a dotenv file',
201
+ dotenvExpand,
202
+ dotenvToken
203
+ )
204
+ .option(
205
+ '--private-token <string>',
206
+ 'token indicating private variables',
207
+ dotenvExpand,
208
+ privateToken
209
+ )
210
+ .addCommand(
211
+ new Command()
212
+ .name('cmd')
213
+ .description('execute shell command string (default command)')
214
+ .configureHelp({ showGlobalOptions: true })
215
+ .enablePositionalOptions()
216
+ .passThroughOptions()
217
+ .action(async (options, { args, parent }) => {
218
+ if (args.length)
219
+ await execaCommand(args.join(' '), {
220
+ stdio: 'inherit',
221
+ shell: parent.opts().shell,
222
+ });
223
+ }),
224
+ { isDefault: true }
225
+ )
226
+ .hook('preSubcommand', async (thisCommand) => {
227
+ // Inherit options from parent command.
228
+ let options = {
229
+ ...(process.env['getdotenvOptions']
230
+ ? JSON.parse(process.env['getdotenvOptions'])
231
+ : {}),
232
+ ...thisCommand.opts(),
233
+ };
234
+
235
+ // Execute pre-hook.
236
+ if (preHook) options = (await preHook(options)) ?? options;
237
+
238
+ // Get options.
239
+ let {
240
+ command,
241
+ paths,
242
+ pathsDelimiter,
243
+ suppressDotenv,
244
+ vars: varsStr,
245
+ varsDelimiter,
246
+ varsAssignor,
247
+ ...rest
248
+ } = options;
249
+
250
+ // Parse vars.
251
+ const vars = varsStr?.length
252
+ ? fromPairs(
253
+ varsStr
254
+ .split(new RegExp(varsDelimiter))
255
+ .map((v) => v.split(new RegExp(varsAssignor)))
256
+ )
257
+ : undefined;
258
+
259
+ // Execute getdotenv.
260
+ if (paths?.length && !suppressDotenv) {
261
+ if (isString(paths)) paths = paths?.split(new RegExp(pathsDelimiter));
262
+
263
+ var dotenv = await getDotenv({
264
+ ...rest,
265
+ loadProcess: true,
266
+ paths,
267
+ vars,
268
+ });
269
+ }
270
+
271
+ // Execute post-hook.
272
+ if (postHook) await postHook(options, dotenv);
273
+
274
+ // Execute shell command.
275
+ if (command)
276
+ await execaCommand(command, {
277
+ stdio: 'inherit',
278
+ shell,
279
+ });
280
+ })
281
+ );
282
+ };