From 13e1b9d5f09099f2c537c49803757f946d16dbe0 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 15 Apr 2021 11:16:47 -0700 Subject: [PATCH] New: Add requireFirst() method (fixes #13) --- README.md | 4 +++- src/env.js | 21 +++++++++++++++++ tests/env.test.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b939e9..e51b646 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,6 @@ However, you can also import the unminified version for debugging purposes: import { Env } from "https://cdn.skypack.dev/@humanwhocodes/env"; ``` - By default, an `Env` instance will read from an empty object. ## API @@ -83,6 +82,9 @@ const username = env.first(["USERNAME", "USERNAME2"], "humanwhocodes"); // read a variable and throw an error if it doesn't exist // or is an empty string const username = env.require("USERNAME"); + +// read the first found variable throw an error if none exist +const username = env.requireFirst(["USERNAME", "USERNAME2"]); ``` To retrieve more than one required environment variable at one time, you can use the `required` property with destructuring assignment: diff --git a/src/env.js b/src/env.js index 21d4e3c..fefea5a 100644 --- a/src/env.js +++ b/src/env.js @@ -145,6 +145,27 @@ export class Env { } } + /** + * Retrieves the first environment variable found in a list of environment + * variable names and throws an error if none of the variables are found. + * @param {string[]} keys An array of environment variable names. + * @returns {string} The environment variable value. + * @throws {TypeError} If keys is not an array with at least one item. + * @throws {Error} When the environment variable doesn't exist or is an + * empty string. + */ + requireFirst(keys) { + + const value = this.first(keys); + if (typeof value === "undefined") { + keyNotFound(`[${keys}]`); + } else if (value === "") { + throw emptyString(`[${keys}]`); + } else { + return value; + } + } + /** * Lazy-loading property containing a proxy that can be used to * automatically throw errors when an undefined environment variable diff --git a/tests/env.test.js b/tests/env.test.js index c6e0c81..635ab96 100644 --- a/tests/env.test.js +++ b/tests/env.test.js @@ -171,6 +171,66 @@ describe("Env", () => { }); + describe("requireFirst()", () => { + + const source = { + USERNAME: "humanwhocodes", + USERNAME2: "nzakas" + }; + + it("should throw an error when the first argument is not an array", () => { + const env = new Env(source); + + assert.throws(() => { + env.requireFirst("USERNAME"); + }, /First argument/); + + }); + + it("should throw an error when the first argument doesn't have at least one item", () => { + const env = new Env(source); + + assert.throws(() => { + env.requireFirst([]); + }, /First argument/); + + }); + + it("should throw an error when none of the arguments exist", () => { + const env = new Env(source); + + assert.throws(() => { + env.requireFirst(["foo", "bar"]); + }, /Required environment variable '\[foo,bar\]' not found/); + + }); + + it("should get the first environment variable when one exists", () => { + const env = new Env(source); + const value = env.requireFirst(["USERNAME"]); + assert.strictEqual(value, source.USERNAME); + }); + + it("should get the first environment variable when only one exists", () => { + const env = new Env(source); + const value = env.requireFirst(["USERNAME", "ALT_USERNAME"]); + assert.strictEqual(value, source.USERNAME); + }); + + it("should get the first environment variable when both exist exists", () => { + const env = new Env(source); + const value = env.requireFirst(["USERNAME", "USERNAME2"]); + assert.strictEqual(value, source.USERNAME); + }); + + it("should get the second environment variable when it exists and the first doesn't", () => { + const env = new Env(source); + const value = env.requireFirst(["ALT_USERNAME", "USERNAME"]); + assert.strictEqual(value, source.USERNAME); + }); + + }); + describe("exists", () => { const source = {