Skip to content

Commit

Permalink
[Issue #11] Add support for relative & absolute filepaths
Browse files Browse the repository at this point in the history
  • Loading branch information
DrewImm committed Mar 29, 2022
1 parent 1f96e51 commit c4ab96d
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Additions
- [Issue #12] Add option to prevent reading from process.env
- [Issue #11] Add support for relative & absolute filepaths

## [1.1.1]

Expand Down
4 changes: 3 additions & 1 deletion src/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { parseLines } from './parser/parse';
import { readFileLines } from './parser/read-file';
import { castValue } from './parser/cast-value';
import { variableExpansion } from './parser/variable-expansion';
import { resolveOptionsFilepath } from './options/resolve-options-filepath';

/**
* Create and hydrate a Configuration instance
Expand All @@ -32,7 +33,8 @@ export function configure<T extends Configuration>(
}

// Read vars
const lines: string[] = readFileLines(options.relativePath);
const file = resolveOptionsFilepath(options);
const lines: string[] = readFileLines(file);
const envFileVars: RawKeyValues = parseLines(lines, options);

// Create instance
Expand Down
10 changes: 8 additions & 2 deletions src/options/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ import { ParserOptions } from './parser-options';

export interface ConfigurationOptions extends ParserOptions {
/**
* Relative filename to load (relative to cwd)
* Absolute filename to load
*/
relativePath: string;
absolutePath?: string;

/**
* Relative filename to load (relative to cwd). Disabled if absolutePath
* is provided
*/
relativePath?: string;

/**
* This check throws an exception if there is a key in the .env file
Expand Down
36 changes: 36 additions & 0 deletions src/options/resolve-options-filepath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PathLike } from 'fs';
import * as path from 'path';
import { ConfigurationOptions } from './options';

/**
* Resolve the target filepath from options
*
* @param options Configuration options
* @returns Returns the target filepath
*/
export function resolveOptionsFilepath(
options: ConfigurationOptions
): PathLike {
let file: PathLike;

if (options.absolutePath) {
file = options.absolutePath;
}
else if (options.relativePath) {
file = path.join(process.cwd(), options.relativePath);
}
else {
file = process.cwd();
}

const filename = path.basename(file);

if (!filename.includes('.')) {
file = path.join(file, '.env');
}
else {
file = path.join(file);
}

return file;
}
9 changes: 3 additions & 6 deletions src/parser/read-file.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { existsSync, readFileSync } from 'fs';
import { join as joinPath } from 'path';
import { existsSync, PathLike, readFileSync } from 'fs';

import { newLineRegex } from '../regex/new-line';

/**
* Read a file into an array of non-empty lines. If no file is found, an empty
* array is returned.
*
* @param filename Input filename
* @param file Input filename
* @returns Returns an array of strings, where each non-empty line is an
* element
*/
export function readFileLines(filename: string): string[] {
const file = joinPath(process.cwd(), filename);

export function readFileLines(file: PathLike): string[] {
if (existsSync(file)) {
return readFileSync(file)
.toString()
Expand Down
1 change: 1 addition & 0 deletions test/envs/absolute.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APP_TITLE="Absolute Path"
1 change: 1 addition & 0 deletions test/envs/relative.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APP_TITLE="Relative Path"
48 changes: 47 additions & 1 deletion test/spec/configure.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,49 @@ describe('configure', () => {
})).toThrow(new UndeclaredKeyError(expectedErrorMessage));
});

it('can accept an absolute path without a filename', () => {
const env: Environment = configure(Environment, {
absolutePath: path.join(process.cwd(), 'test', 'envs'),
overwriteProcessEnv: false,
fromProcessEnv: false,
});

expect(env.APP_TITLE).toBe('Default filename');
});

it('can accept an absolute path with a filename', () => {
const env: Environment = configure(Environment, {
absolutePath: path.join(
process.cwd(),
'test/envs/absolute.env'
),
overwriteProcessEnv: false,
fromProcessEnv: false,
});

expect(env.APP_TITLE).toBe('Absolute Path');
});

it('can accept a relative path without a filename', () => {
const env: Environment = configure(Environment, {
relativePath: 'test/envs/',
overwriteProcessEnv: false,
fromProcessEnv: false,
});

expect(env.APP_TITLE).toBe('Default filename');
});

it('can accept a relative path with a filename', () => {
const env: Environment = configure(Environment, {
relativePath: 'test/envs/relative.env',
overwriteProcessEnv: false,
fromProcessEnv: false,
});

expect(env.APP_TITLE).toBe('Relative Path');
});

it('reads from process.env', () => {
process.env.TEST_READ_PROCESS_ENV = 'read';

Expand All @@ -41,7 +84,10 @@ describe('configure', () => {
it('doesn\'t read from process.env when disabled', () => {
process.env.TEST_DISABLE_READ_PROCESS_ENV = 'read';

const env = configure(ProcessEnvTestEnvironment, { fromProcessEnv: false });
const env = configure(
ProcessEnvTestEnvironment,
{ fromProcessEnv: false }
);
expect(env.TEST_DISABLE_READ_PROCESS_ENV).not.toBe('read');
});

Expand Down
43 changes: 43 additions & 0 deletions test/spec/options/resolve-options-filepath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
resolveOptionsFilepath
} from '../../../src/options/resolve-options-filepath';
import * as path from 'path';

describe('options/resolve-options-filepath', () => {
it('can use a default file', () => {
const file = resolveOptionsFilepath({ });

expect(file).toEqual(path.join(process.cwd(), '.env'));
});

it('can accept a relative file', () => {
const file = resolveOptionsFilepath(
{ relativePath: 'test/relative.env' }
);

expect(file).toEqual(path.join(
process.cwd(),
'test/relative.env'
));
});

it('can accept a relative directory', () => {
const file = resolveOptionsFilepath({ relativePath: 'test/' });

expect(file).toEqual(path.join(process.cwd(), 'test', '.env'));
});

it('can accept an absolute file', () => {
const file = resolveOptionsFilepath(
{ absolutePath: 'C:/test/absolute.env' }
);

expect(file).toEqual(path.join('C:/test/absolute.env'));
});

it('can accept an absolute directory', () => {
const file = resolveOptionsFilepath({ absolutePath: 'C:/test/' });

expect(file).toEqual(path.join('C:/test/.env'));
});
});

0 comments on commit c4ab96d

Please sign in to comment.