Skip to content

Commit 446c676

Browse files
committed
Enhances #354 for stricter env method
1 parent b42df8c commit 446c676

File tree

2 files changed

+37
-21
lines changed

2 files changed

+37
-21
lines changed

lib/index.js

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ const { rm, isString, isBoolean, isObject, isNumber, isUndefined, match } = requ
88
const utf8 = require('is-utf8')
99
const Ware = require('ware')
1010

11+
const symbol = {
12+
env: Symbol('env')
13+
}
14+
1115
/**
1216
* Metalsmith representation of the files in `metalsmith.source()`.
1317
* The keys represent the file paths and the values are {@link File} objects
@@ -97,7 +101,7 @@ function Metalsmith(directory) {
97101
this.metadata({})
98102
this.source('src')
99103
this.destination('build')
100-
this.env({})
104+
this[symbol.env] = Object.create(null)
101105
this.concurrency(Infinity)
102106
this.clean(true)
103107
this.frontmatter(true)
@@ -297,7 +301,7 @@ Metalsmith.prototype.match = function (patterns, input, options) {
297301
}
298302

299303
/**
300-
* Get or set one or multiple metalsmith environment variables.
304+
* Get or set one or multiple metalsmith environment variables. Metalsmith env vars are case-insensitive.
301305
* @param {string|Object} [vars] name of the environment variable, or an object with `{ name: 'value' }` pairs
302306
* @param {string|number|boolean} [value] value of the environment variable
303307
* @example
@@ -317,29 +321,21 @@ Metalsmith.prototype.match = function (patterns, input, options) {
317321
* })
318322
*/
319323
Metalsmith.prototype.env = function (vars, value) {
320-
if (!arguments.length) return this._env
321-
322-
if (arguments.length === 1) {
323-
assert(
324-
isString(vars) || isObject(vars),
325-
'You must pass an environment variable name, or an object with name:value pairs'
326-
)
327-
if (isString(vars)) {
328-
return this._env[vars]
324+
if (isString(vars)) {
325+
if (arguments.length === 1) {
326+
return this[symbol.env][vars.toUpperCase()]
329327
}
330-
if (isObject(vars)) {
331-
this._env = Object.assign(this._env || Object.create(null), vars)
328+
if (!(isFunction(value) || isObject(value))) {
329+
this[symbol.env][vars.toUpperCase()] = value
332330
return this
333331
}
332+
throw new TypeError('Environment variable values can only be primitive: Number, Boolean, String or null')
334333
}
335-
if (arguments.length === 2) {
336-
assert(
337-
isString(vars) && (isString(value) || isNumber(value) || isBoolean(value)),
338-
'Environment variable values can only be primitives, no objects or functions'
339-
)
340-
this._env[vars] = value
334+
if (isObject(vars)) {
335+
Object.entries(vars).forEach(([key, value]) => this.env(key, value))
341336
return this
342337
}
338+
if (isUndefined(vars)) return Object.assign(Object.create(null), this[symbol.env])
343339
}
344340

345341
/**

test/index.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,30 @@ describe('Metalsmith', function () {
153153
assert(Object.keys(m.env()).length === 0)
154154
})
155155

156+
it('should not be accessible directly from the Metalsmith instance', function () {
157+
const m = Metalsmith('test/tmp')
158+
assert(!Object.keys(m).includes('env') && !Object.keys(m).includes('_env'))
159+
})
160+
156161
it('should allow getting & chainable setting single environment variables', function () {
157162
const m = Metalsmith('test/tmp').env('DEBUG', true).env('ENV', 'development')
158163

159164
assert(m.env('DEBUG'))
160165
assert(m.env('ENV') === 'development')
161166
})
162167

168+
it('should throw on non-primitive values', function () {
169+
assert.throws(() => Metalsmith('test/tmp').env('DEBUG', {}))
170+
assert.throws(() => Metalsmith('test/tmp').env('DEBUG', () => {}))
171+
})
172+
173+
it('should treat a lowercase and uppercase variable as the same', function () {
174+
const m = Metalsmith('test/tmp')
175+
m.env('debug', true)
176+
m.env('DEBUG', false)
177+
assert(m.env('debug') === m.env('DEBUG'))
178+
})
179+
163180
it('should allow setting a batch of environment variables', function () {
164181
const m = Metalsmith('test/tmp').env({ DEBUG: true, ENV: 'development' })
165182

@@ -169,8 +186,11 @@ describe('Metalsmith', function () {
169186
it('should provide out of the box support for process.env', function () {
170187
const npmvar = process.env.npm_config_shell
171188
const m = Metalsmith('test/tmp').env(process.env)
172-
173-
assert.deepStrictEqual(m.env(), Object.assign(Object.create(null), process.env))
189+
const uppercased = Object.entries(process.env).reduce((vars, [name, value]) => {
190+
vars[name.toUpperCase()] = value
191+
return vars
192+
}, {})
193+
assert.deepStrictEqual(m.env(), Object.assign(Object.create(null), uppercased))
174194

175195
m.env('npm_config_shell', '/bin/not-really')
176196
assert.strictEqual(process.env.npm_config_shell, npmvar)

0 commit comments

Comments
 (0)