Repository: fterh/heimdall
Pull request #71 (2022-12-28 05:08:26)

Allow configurable number of words for alias generation, default to 2


Patch:
diff --git a/.env.sample b/.env.sample
index 32ffd28..6a73cf0 100644
--- a/.env.sample
+++ b/.env.sample
@@ -5,4 +5,5 @@ AWS_SMTP_USER=[MANDATORY]
 AWS_SMTP_PASS=[MANDATORY]
 BASE_DOMAIN=[MANDATORY e.g. mywebsite.com]
 DEV_SUBDOMAIN=[OPTIONAL e.g. test]
-EMAIL=[MANDATORY e.g. johnsmith@emaildomain.com]
\ No newline at end of file
+EMAIL=[MANDATORY e.g. johnsmith@emaildomain.com]
+NUM_WORDS=[OPTIONAL, >0 e.g. 4; defaults to 2 if omitted or invalid]
\ No newline at end of file
diff --git a/lib/env.ts b/lib/env.ts
index 866a121..790c82b 100644
--- a/lib/env.ts
+++ b/lib/env.ts
@@ -1,5 +1,7 @@
 require("dotenv").config();
 
+const DEFAULT_NUM_WORDS = 2;
+
 const readEnvironmentVariable = (
   key: string,
   optional: boolean = false
@@ -51,6 +53,16 @@ export let awsId: string,
 devSubdomain = readEnvironmentVariable("DEV_SUBDOMAIN", true);
 /* eslint-enable */
 
+export const readNumWords = (): number => {
+  const numWordsRaw = readEnvironmentVariable("NUM_WORDS", true);
+  const maybeNumWords = Number(numWordsRaw);
+  if (maybeNumWords === 0 || isNaN(maybeNumWords)) {
+    return DEFAULT_NUM_WORDS;
+  } else {
+    return maybeNumWords;
+  }
+};
+
 export const generateOperationalDomain = (
   stage: string,
   devSubdomain: string,
@@ -67,6 +79,7 @@ export const generateOperationalDomain = (
   return baseDomain;
 };
 
+export const numWords = readNumWords();
 export const stage = process.env["STAGE"] || "dev";
 export const operationalDomain = generateOperationalDomain(
   stage,
@@ -83,6 +96,7 @@ const exportData = {
   baseDomain,
   devSubdomain,
   email,
+  numWords,
   operationalDomain,
   stage
 };
diff --git a/lib/models/generateAliasValue.ts b/lib/models/generateAliasValue.ts
index 6c51e34..a75ff91 100644
--- a/lib/models/generateAliasValue.ts
+++ b/lib/models/generateAliasValue.ts
@@ -1,7 +1,6 @@
 // @ts-ignore
 import randomWords from "random-words";
-
-const NUM_WORDS = 4;
+import { numWords } from "../env";
 
 export default (): string => {
   console.log("Generating alias");
@@ -9,7 +8,7 @@ export default (): string => {
   const options = {
     exactly: 1,
     separator: "",
-    wordsPerString: NUM_WORDS
+    wordsPerString: numWords
   };
 
   return randomWords(options)[0];


Test patch:
diff --git a/tests/lib/env.test.ts b/tests/lib/env.test.ts
index 8f20f49..db31e96 100644
--- a/tests/lib/env.test.ts
+++ b/tests/lib/env.test.ts
@@ -1,28 +1,54 @@
-import { generateOperationalDomain } from "../../lib/env";
+import { generateOperationalDomain, readNumWords } from "../../lib/env";
 
-it("should return baseDomain in production when devSubdomain is set", () => {
-  expect(generateOperationalDomain("prod", "test", "domain.com")).toBe(
-    "domain.com"
-  );
-});
-it("should return baseDomain in production when devSubdomain is not set", () => {
-  expect(generateOperationalDomain("prod", "", "domain.com")).toBe(
-    "domain.com"
-  );
+describe("generateOperationalDomain", () => {
+  it("should return baseDomain in production when devSubdomain is set", () => {
+    expect(generateOperationalDomain("prod", "test", "domain.com")).toBe(
+      "domain.com"
+    );
+  });
+  it("should return baseDomain in production when devSubdomain is not set", () => {
+    expect(generateOperationalDomain("prod", "", "domain.com")).toBe(
+      "domain.com"
+    );
+  });
+  it("should return devSubdomain.baseDomain in development when devSubdomain is set", () => {
+    expect(generateOperationalDomain("dev", "test", "domain.com")).toBe(
+      "test.domain.com"
+    );
+  });
+  it("should throw if devSubdomain is not set in development", () => {
+    expect(() => {
+      generateOperationalDomain("dev", "", "domain.com");
+    }).toThrow(
+      new Error(
+        "DEV_SUBDOMAIN environment variable must be set when deploying to dev stage"
+      )
+    );
+  });
 });
 
-it("should return devSubdomain.baseDomain in development when devSubdomain is set", () => {
-  expect(generateOperationalDomain("dev", "test", "domain.com")).toBe(
-    "test.domain.com"
-  );
-});
+describe("readNumWords", () => {
+  const oldEnv = process.env;
+
+  beforeEach(() => {
+    jest.resetModules();
+    process.env = { ...oldEnv };
+  });
+
+  afterAll(() => {
+    process.env = oldEnv;
+  });
+
+  it("should read valid NUM_WORDS environment config paramter", () => {
+    process.env.NUM_WORDS = "5";
+    expect(readNumWords()).toBe(5);
+  });
 
-it("should throw if devSubdomain is not set in development", () => {
-  expect(() => {
-    generateOperationalDomain("dev", "", "domain.com");
-  }).toThrow(
-    new Error(
-      "DEV_SUBDOMAIN environment variable must be set when deploying to dev stage"
-    )
-  );
+  it("should default to 2 if no NUM_WORDS environment config paramter is provided", () => {
+    expect(readNumWords()).toBe(2);
+  });
+  it("should default to 2 if an invalid NUM_WORDS environment config paramter is provided", () => {
+    process.env.NUM_WORDS = "three";
+    expect(readNumWords()).toBe(2);
+  });
 });