Skip to content

CheckerEnvKeys ​

Checks that multiple lists of keys match and that each list contains no duplicates. For security, the checker does not read files itself; parsing them is left to the user.

For watch mode, env files must be inside rootDir. Pass keys through the envKeys getter, as shown in the examples: an array created once will not update.

ts
envKeys: Array<{ 
  name: string; 
  keys: Array<string> 
}>

An array of objects, each containing:

name — the name of the key set (the file name is often a convenient choice)

keys — an array of environment variable names (or another list of keys)

Example: Keeping env files in sync

The checker compares keys in .env and .example.env and reports mismatches

ts
new CheckerEnvKeys({
  get envKeys() {
    function readEnvKeys(fileName: string) {
      return {
        name: fileName,
        keys: Object.keys(parseEnv(fs.readFileSync(path.resolve(rootDir, fileName), 'utf8'))),
      };
    }

    return [readEnvKeys('.env'), readEnvKeys('.example.env')];
  },
}),
Run Sandbox
USER: .env was created with content:
text
NODE_ENV=development
EXPRESS_PORT=3000
USER: .example.env was created with content:
env
NODE_ENV=development
EXPRESS_PORT=3000
ARFA Generator shows logs:
txt
[ARFA-GEN] finished in 0ms

Example: Env files and a typed env object

Keys from the files are compared with keys from an existing env object. This lets the checker find variables declared in code but missing from the env files

ts
new CheckerEnvKeys({
  get envKeys() {
    function readEnvKeys(fileName: string) {
      return {
        name: fileName,
        keys: Object.keys(parseEnv(fs.readFileSync(path.resolve(rootDir, fileName), 'utf8'))),
      };
    }

    class Env {
      NODE_ENV: 'development' | 'production' = 'development';
      EXPRESS_PORT = 0;
      HOT_RELOAD = false;

      constructor(source: Record<string, string | undefined>) {
        this.NODE_ENV = source.NODE_ENV === 'production' ? 'production' : 'development';
        this.EXPRESS_PORT = Number(source.EXPRESS_PORT ?? 0);
        this.HOT_RELOAD = source.HOT_RELOAD === 'true';
      }
    }

    const env = new Env(process.env);

    return [
      readEnvKeys('.env'),
      readEnvKeys('example.dev.env'),
      readEnvKeys('example.prod.env'),
      { name: 'parsed', keys: Object.keys(env) },
    ];
  },
}),
Run Sandbox
USER: .env was created with content:
text
NODE_ENV=development
EXPRESS_PORT=3000
USER: example.dev.env was created with content:
env
NODE_ENV=development
EXPRESS_PORT=3000
USER: example.prod.env was created with content:
env
NODE_ENV=production
EXPRESS_PORT=8080
ARFA Generator shows logs:
txt
[ARFA-GEN] [env-keys] Keys mismatch
[ARFA-GEN]   .env vs parsed: .env missing HOT_RELOAD
[ARFA-GEN] [env-keys] Keys mismatch
[ARFA-GEN]   example.dev.env vs parsed: example.dev.env missing HOT_RELOAD
[ARFA-GEN] [env-keys] Keys mismatch
[ARFA-GEN]   example.prod.env vs parsed: example.prod.env missing HOT_RELOAD
[ARFA-GEN] finished in 0ms

Example: Duplicate keys in an env file

This example reads the file line by line to demonstrate duplicate detection

ts
new CheckerEnvKeys({
  get envKeys() {
    const content = fs.readFileSync(path.resolve(rootDir, '.env'), 'utf8');

    return [
      {
        name: '.env',
        keys: content.split(/\r?\n/).flatMap((line) => Object.keys(parseEnv(line))),
      },
    ];
  },
}),
Run Sandbox
USER: .env was created with content:
text
NODE_ENV=development
EXPRESS_PORT=3000
ARFA Generator shows logs:
txt
[ARFA-GEN] finished in 0ms

MIT License