Skip to content

Commit

Permalink
feat: add getNumberArray
Browse files Browse the repository at this point in the history
  • Loading branch information
Korzun committed Apr 22, 2024
1 parent e92eff5 commit a5d954a
Show file tree
Hide file tree
Showing 2 changed files with 254 additions and 1 deletion.
124 changes: 123 additions & 1 deletion src/number.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
NotDefinedConfigError,
RangeValueConfigError,
} from './error';
import { getNumber } from './number';
import { getNumber, getNumberArray } from './number';

describe('getNumber', () => {
let env: Record<string, string | undefined>;
Expand Down Expand Up @@ -122,3 +122,125 @@ describe('getNumber', () => {
});
});
});

describe('getNumberArray', () => {
let env: Record<string, string | undefined>;
beforeEach(() => {
env = Object.assign({}, process.env);
});
Object.assign({}, process.env);
afterEach(() => {
process.env = env;
});

describe('environment variable is set', () => {
it('returns the environment variable as an array of numbers', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
const value = getNumberArray('TEST_NUMBER');
expect(value).toEqual([10.33, 20.33, 30.33]);
});
describe('allow undefined', () => {
it('returns the environment variable as an array of numbers', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
const value = getNumberArray('TEST_NUMBER', { allowUndefined: true });
expect(value).toEqual([10.33, 20.33, 30.33]);
});
});
describe('default is set', () => {
it('returns the environment variable as an array of numbers', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
const value = getNumberArray('TEST_NUMBER', { default: [10, 20] });
expect(value).toEqual([10.33, 20.33, 30.33]);
});
});
describe('allow list is defined', () => {
describe('all environmental variables numbers are in allow list', () => {
it('return the environmental variable as an array of numbers', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
const value = getNumberArray('TEST_NUMBER', {
allowList: [10.33, 20.33, 30.33],
});
expect(value).toEqual([10.33, 20.33, 30.33]);
});
});
describe('one of the environmental variable numbers is NOT in allow list', () => {
it('throws an error', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
expect(() => {
getNumberArray('TEST_NUMBER', { allowList: [10.33, 20.33] });
}).toThrow(
new ListValueConfigError('TEST_NUMBER', 30.33, [10.33, 20.33]),
);
});
});
});
describe('allow range is defined', () => {
describe('all environmental variable numbers are within allowable range', () => {
it('return the environmental variables as an array of numbers', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
const value = getNumberArray('TEST_NUMBER', {
allowRange: [10, 40],
});
expect(value).toEqual([10.33, 20.33, 30.33]);
});
});
describe('one of the environmental variable numbers is NOT within allowable range', () => {
it('throws an error', () => {
process.env.TEST_NUMBER = '10.33,20.33,30.33';
expect(() => {
getNumberArray('TEST_NUMBER', { allowRange: [10, 30] });
}).toThrow(new RangeValueConfigError('TEST_NUMBER', 30.33, [10, 30]));
});
});
});
});
describe('environment variable is set to an empty string', () => {
it('throws an error', () => {
process.env.TEST_NUMBER = '';
expect(() => {
getNumberArray('TEST_NUMBER');
}).toThrow(new NotDefinedConfigError('TEST_NUMBER'));
});

describe('allow undefined', () => {
it('returns an empty array', () => {
process.env.TEST_NUMBER = '';
const value = getNumberArray('TEST_NUMBER', { allowUndefined: true });
expect(value).toEqual([]);
});
});

describe('default is set', () => {
it('returns the default', () => {
process.env.TEST_NUMBER = '';
const value = getNumberArray('TEST_NUMBER', {
default: [10.33, 20.33],
});
expect(value).toEqual([10.33, 20.33]);
});
});
});
describe('environment variable is not set', () => {
it('throws an error', () => {
expect(() => {
getNumberArray('TEST_NUMBER');
}).toThrow(new NotDefinedConfigError('TEST_NUMBER'));
});

describe('allow undefined', () => {
it('returns an empty array', () => {
const value = getNumberArray('TEST_NUMBER', { allowUndefined: true });
expect(value).toEqual([]);
});
});

describe('default is set', () => {
it('returns the default', () => {
const value = getNumberArray('TEST_NUMBER', {
default: [10.33, 20.33],
});
expect(value).toEqual([10.33, 20.33]);
});
});
});
});
131 changes: 131 additions & 0 deletions src/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,137 @@ export function getNumber(name: string, options: GetNumberOptions = {}) {
throw error;
}

type GetNumberArrayOptionsAllowList = {
allowList?: number[];
allowRange?: undefined;
};
type GetNumberArrayOptionsAllowRange = {
allowList?: undefined;
allowRange?: [number, number];
};
type GetNumberArrayOptionsAllow =
| GetNumberArrayOptionsAllowList
| GetNumberArrayOptionsAllowRange;

type GetNumberArrayOptionsAllowUndefined = {
allowUndefined: true;
default?: undefined;
} & GetNumberArrayOptionsAllow;
type GetNumberArrayOptionsNoDefault = {
allowUndefined?: false;
default?: undefined;
} & GetNumberArrayOptionsAllow;
type GetNumberArrayOptionsDefault = {
allowUndefined?: false;
default: number[];
} & GetNumberArrayOptionsAllow;

export type GetNumberArrayOptions =
| GetNumberArrayOptionsAllowUndefined
| GetNumberArrayOptionsNoDefault
| GetNumberArrayOptionsDefault;

/**
* Returns an environmental variable as a `number` array. Optionally the value
* can be validated by an `allowList` or `allowRange`.
*/
export function getNumberArray(
name: string,
options: {
allowUndefined: true;
default?: undefined;
} & (
| {
allowList?: undefined;
allowRange?: undefined;
}
| {
allowList: number[];
}
| {
allowRange: [number, number];
}
),
): number[];
/**
* Returns an environmental variable as a `number` array or, if undefined,
* throws an error. Optionally the value can be validated by an `allowList` or
* `allowRange`.
*/
export function getNumberArray(
name: string,
options?: {
allowUndefined?: false;
default?: undefined;
} & (
| {
allowList?: undefined;
allowRange?: undefined;
}
| {
allowList: number[];
}
| {
allowRange: [number, number];
}
),
): number[];
/**
* Returns an environmental variable as a `number` array or, if undefined, the
* provided default value. Optionally the value can be validated by an
* `allowList` or `allowRange`.
*/
export function getNumberArray(
name: string,
options: {
allowUndefined?: false;
default: number[];
} & (
| {
allowList?: undefined;
allowRange?: undefined;
}
| {
allowList: number[];
}
| {
allowRange: [number, number];
}
),
): number[];
export function getNumberArray(
name: string,
options: GetNumberArrayOptions = {},
) {
const {
allowList,
allowRange,
allowUndefined,
default: defaultValue,
} = options;
const stringValue = process.env[name];
if (stringValue !== undefined && stringValue !== '') {
const values = stringValue.split(',').map((value) => {
const numberValue = Number(value);
validateList(name, value, numberValue, allowList);
validateRange(name, value, numberValue, allowRange);
return numberValue;
});
return values;
}
if (defaultValue !== undefined) {
return defaultValue;
}
if (allowUndefined) {
return [];
}
const error = new NotDefinedConfigError(name);
if (Error.captureStackTrace) {
Error.captureStackTrace(error, getNumberArray);
}
throw error;
}

const validateList = (
name: string,
stringValue: string,
Expand Down

0 comments on commit a5d954a

Please sign in to comment.