Skip to content

Commit

Permalink
update helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
vinayak25 committed Oct 20, 2024
1 parent 6354119 commit 997bfaf
Show file tree
Hide file tree
Showing 9 changed files with 418 additions and 554 deletions.
23 changes: 13 additions & 10 deletions lib/console/consoleIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ConsoleLogger } from './logger';
export class ConsoleIO {
schema: ArgumentParserOutput;
rawValues: Record<string, any>;
values: Record<string, any> = { arguments: {}, options: {} };
values = { arguments: {}, options: {} };
hasErrors: boolean;
missingArguments: string[];

Expand Down Expand Up @@ -36,6 +36,14 @@ export class ConsoleIO {
return this.values.options[key];
}

arguments(): Record<string, any> {
return this.values.arguments;
}

options(): Record<string, any> {
return this.values.options;
}

handle(): ConsoleIO {
this.schema = ArgumentParser.from(this.schemaString);
this.values = { arguments: {}, options: {} };
Expand Down Expand Up @@ -68,16 +76,11 @@ export class ConsoleIO {
this.validateArguments();
if (this.hasErrors) return this;

/**
* Parse options
*/
for (const option of this.schema.options) {
const value = Obj.get(this.argv, option.name, ...option.alias);
if (value) {
this.values.options[option.name] = value;
} else {
this.values.options[option.name] = option.defaultValue;
}
const values = Object.values(
Obj.pick(this.argv, [option.name, ...option.alias]),
);
this.values.options[option.name] = values[0] ? values[0] : undefined;
}

return this;
Expand Down
24 changes: 5 additions & 19 deletions lib/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,14 @@ import { Obj } from './object';
import { Str } from './string';

export const isEmpty = (value: any) => {
if (Str.isString(value)) {
return value === '';
}

if (Arr.isArray(value)) {
return !value.length;
}

if (Obj.isObj(value)) {
return Obj.isEmpty(value);
}

if (Number.isNaN(value) || value === undefined) {
return true;
}

if (Str.isString(value)) return value === '';
if (Arr.isArray(value)) return !value.length;
if (Obj.isObj(value)) return Obj.isEmpty(value);
if (Number.isNaN(value) || value === undefined) return true;
return false;
};

export const isBoolean = (value: any): boolean => {
return typeof value === 'boolean';
};
export const isBoolean = (value: any): boolean => typeof value === 'boolean';

export const toBoolean = (value: any) => {
if (!Str.isString(value) || typeof value !== 'boolean') return undefined;
Expand Down
26 changes: 12 additions & 14 deletions lib/utils/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,26 +102,24 @@ export class Obj {
return !Obj.isEmpty(obj);
}

static get<T>(
static get<T = any>(
obj: Record<string, any>,
key: string,
...aliasKeys: string[]
defaultValue?: T,
): T {
const keys = [key, ...aliasKeys];
for (const key of keys) {
if (key in obj) return obj[key];
const splitKeys = key.split('.');
if (!splitKeys.length) return;
if (key in obj) return obj[key];
const splitKeys = key.split('.');
if (!splitKeys.length) return;

if (Arr.isArray(obj[splitKeys[0]])) {
return Arr.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
}
if (Arr.isArray(obj[splitKeys[0]])) {
return Arr.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
}

if (Obj.isObj(obj[splitKeys[0]])) {
return Obj.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
}
if (Obj.isObj(obj[splitKeys[0]])) {
return Obj.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
}
return undefined;

return defaultValue;
}

static sort<T = Record<string, any>>(obj: T): T {
Expand Down
91 changes: 87 additions & 4 deletions lib/utils/tests/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,94 @@ import { Arr } from '../array';

jest.mock('../../config/service');

describe('Array Helpers', () => {
describe('Array Helper', () => {
beforeEach(async () => {});

it('should collapse a nested array in a single level array', () => {
const sample1 = ['a', ['b', ['c'], 1], 2];
expect(Arr.collapse(sample1)).toStrictEqual(['a', 'b', 'c', 1, 2]);
// it('should throw exception', () => {
// const arr = {};
// expect(Arr.toObj(arr as [], [])).toThrow(InvalidValue);
// });

it('should return object', () => {
const arr = [
2,
['bar', 'piyush', 'intent'],
{ foo: 'bar' },
[{ bar: 'foo' }],
];

const keys = ['foo', 'chhabra', 'best framework', 'obj'];
expect(Arr.toObj(arr, keys)).toStrictEqual([
{ foo: 'bar', chhabra: 'piyush', 'best framework': 'intent' },
{ foo: { bar: 'foo' } },
]);
});

// it('should throw exception', () => {
// const arr = {};
// expect(Arr.isArray(arr as [], true)).toThrow(InvalidValue);
// });

it('should return false', () => {
const arr = {};
expect(Arr.isArray(arr as [])).toBeFalsy();
});

it('should return false', () => {
const arr = [];
expect(Arr.isArray(arr)).toBeTruthy();
});

it('should return array of nested members flattened', () => {
const arr = [1, [2, 3, 4], [[5, 6], [[7], 8], 9]];
expect(Arr.collapse(arr)).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
});

it('should return array with random order of input', () => {
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const mockMath = Object.create(global.Math);
mockMath.random = () => 0.5;
global.Math = mockMath;
expect(Arr.random(arr)).toStrictEqual([1, 6, 2, 8, 3, 7, 4, 9, 5]);
});

it('should return array with sorted order of input', () => {
const arr = [6, 1, 2, 8, 3, 7, 4, 9, 5];
expect(Arr.sort(arr)).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
});

it('should return array with descending order of input', () => {
const arr = [6, 1, 2, 8, 3, 7, 4, 9, 5];
expect(Arr.sortDesc(arr)).toStrictEqual([9, 8, 7, 6, 5, 4, 3, 2, 1]);
});

it('should return array with common elements from both input arrays', () => {
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [4, 5, 6, 7, 8];
expect(Arr.intersect(arr1, arr2)).toStrictEqual([4, 5]);
});

it('should return array with elements keys mentioned to pick', () => {
const arr = [
{ developer: { id: 1, name: 'Taylor' } },
{ developer: { id: 2, name: 'Abigail' } },
];
const pick = ['*.developer.name'];
expect(Arr.pick(arr, pick)).toStrictEqual([
{ developer: { name: 'Taylor' } },
{ developer: { name: 'Abigail' } },
]);
});

it('should return array with all elements except the keys mentioned', () => {
const arr = [
{ developer: { id: 1, name: 'Taylor' } },
{ developer: { id: 2, name: 'Abigail' } },
];
const pick = ['*.developer.name'];
expect(Arr.except(arr, pick)).toStrictEqual([
{ developer: { id: 1 } },
{ developer: { id: 2 } },
]);
});
});
133 changes: 88 additions & 45 deletions lib/utils/tests/number.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,117 @@ import { Num } from '../number';

jest.mock('../../config/service');

describe('Number Helpers', () => {
describe('Numbers Helper', () => {
beforeEach(async () => {});

it('abbreviates the passed number to abbreviated format', () => {
const num = 1000;
expect(Num.abbreviate(num)).toStrictEqual('1K');
it('should abbrevate with en locale to 1 decimal point precision', () => {
const number = 12345;
expect(Num.abbreviate(number)).toBe('12.3K');
});

it('abbreviates the passed number to a abbreviated format, but with precision', () => {
const num = 1200;
expect(Num.abbreviate(num, { precision: 2 })).toStrictEqual('1.2K');
it('should abbrevate with en locale to 3 decimal precision', () => {
const number = 12345;
const options = { precision: 3, locale: 'en' };
expect(Num.abbreviate(number, options)).toBe('12.345K');
});

it('abbreviates the passed number to a abbreviated format, but with different locale', () => {
const num = 1200;
expect(Num.abbreviate(num, { locale: 'hi' })).toStrictEqual('1.2 हज़ार');
it('should abbrevate with en-IN locale to 3 decimal precision', () => {
const number = 12345;
const options = { precision: 3, locale: 'en-IN' };
expect(Num.abbreviate(number, options)).toBe('12.345K');
});

it('should conver the number to indian currency format', () => {
const num = 12300;
expect(Num.currency(num, { currency: 'INR' })).toStrictEqual('₹12,300.00');
it('should return number itself', () => {
const number = 12345;
const min = 12300;
const max = 12400;
expect(Num.clamp(number, min, max)).toBe(number);
});

it('should conver the number to dollar currency format', () => {
const num = 12300;
expect(Num.currency(num, { currency: 'USD' })).toStrictEqual('$12,300.00');
it('should return minimum number', () => {
const number = 12345;
const min = 12350;
const max = 12400;
expect(Num.clamp(number, min, max)).toBe(min);
});

it('should convert the number to file size representation', () => {
const samples = { 1000: '1KB', 1024: '1KB', [1024 * 1024 * 1.5]: '1.57MB' };
expect(Num.fileSize(1000)).toStrictEqual('1KB');
expect(Num.fileSize(1024)).toStrictEqual('1KB');
expect(Num.fileSize(1024 * 1024 * 1.5, { precision: 2 })).toStrictEqual(
'1.57MB',
);
it('should return maximum number', () => {
const number = 12345;
const min = 12300;
const max = 12340;
expect(Num.clamp(number, min, max)).toBe(max);
});

it('should convert the number to human readable format', () => {
expect(Num.forHumans(100)).toStrictEqual('100');
expect(Num.forHumans(1200)).toStrictEqual('1.2 thousand');
it('should return number in currency style in INR', () => {
const number = 12345;
const options = { currency: 'INR', locale: 'en' };
expect(Num.currency(number, options)).toBe('₹12,345.00');
});

it('should convert the number to human readable format, with precision', () => {
expect(Num.forHumans(1230, { precision: 2 })).toStrictEqual(
'1.23 thousand',
);
it('should return number in currency style in USD', () => {
const number = 12345;
const options = { currency: 'USD', locale: 'en' };
expect(Num.currency(number, options)).toBe('$12,345.00');
});

it('should return number in file size format', () => {
const number = 12345;
expect(Num.fileSize(number)).toBe('12.3KB');
});

it('should return number in file size format with precision 3', () => {
const number = 123456789;
const options = { precision: 3 };
expect(Num.fileSize(number, options)).toBe('123.457MB');
});

it('should return number in humanize form with precision 1', () => {
const number = 12345;
const options = { precision: 1, locale: 'en' };
expect(Num.forHumans(number, options)).toBe('12.3 thousand');
});

it('should convert the number to human readable format, with locale', () => {
expect(Num.forHumans(1200, { locale: 'fr' })).toStrictEqual('1,2 millier');
it('should return number in humanize form with precision 3', () => {
const number = 123456789;
const options = { precision: 3, locale: 'en' };
expect(Num.forHumans(number, options)).toBe('123.457 million');
});

it('should format the number to the given locale string', () => {
expect(Num.format(1000)).toStrictEqual('1,000');
expect(Num.format(1000, { locale: 'fr' })).toStrictEqual('1 000');
expect(Num.format(1200)).toStrictEqual('1,200');
it('should return number in number system format with precision 1(default)', () => {
const number = 12345.78;
const options = { locale: 'en' };
expect(Num.format(number, options)).toBe('12,345.8');
});

it('converts the given number to the ordinal format', () => {
expect(Num.ordinal(1)).toStrictEqual('1st');
expect(Num.ordinal(2)).toStrictEqual('2nd');
expect(Num.ordinal(3)).toStrictEqual('3rd');
expect(Num.ordinal(20)).toStrictEqual('20th');
it('should return number in percents when passed as decimal portion with precision 1(default)', () => {
const number = 17.8;
const options = { locale: 'en' };
expect(Num.percentage(number, options)).toBe('17.8%');
});

it('converts the number to a percentage format with support for precision and locale config', () => {
expect(Num.percentage(10)).toStrictEqual('10.0%');
expect(Num.percentage(10, { locale: 'fr' })).toStrictEqual('10,0 %');
expect(Num.percentage(10.123, { precision: 2 })).toStrictEqual('10.12%');
it('should return number in ordinal format', () => {
const number = 231;
expect(Num.ordinal(number)).toBe('231st');
});

it('should return number in ordinal format', () => {
const number = 12345;
expect(Num.ordinal(number)).toBe('12345th');
});

it('should return number in english words', () => {
const number = 12345;
expect(Num.spell(number)).toBe(
'twelve thousand three hundred and forty five only',
);
});

it('should return false', () => {
const number = '12345';
expect(Num.isInteger(number)).toBe(false);
});
it('should return true', () => {
const number = 12345;
expect(Num.isInteger(number)).toBe(true);
});
});
Loading

0 comments on commit 997bfaf

Please sign in to comment.