Skip to content

Commit 997bfaf

Browse files
committed
update helpers
1 parent 6354119 commit 997bfaf

File tree

9 files changed

+418
-554
lines changed

9 files changed

+418
-554
lines changed

lib/console/consoleIO.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ConsoleLogger } from './logger';
77
export class ConsoleIO {
88
schema: ArgumentParserOutput;
99
rawValues: Record<string, any>;
10-
values: Record<string, any> = { arguments: {}, options: {} };
10+
values = { arguments: {}, options: {} };
1111
hasErrors: boolean;
1212
missingArguments: string[];
1313

@@ -36,6 +36,14 @@ export class ConsoleIO {
3636
return this.values.options[key];
3737
}
3838

39+
arguments(): Record<string, any> {
40+
return this.values.arguments;
41+
}
42+
43+
options(): Record<string, any> {
44+
return this.values.options;
45+
}
46+
3947
handle(): ConsoleIO {
4048
this.schema = ArgumentParser.from(this.schemaString);
4149
this.values = { arguments: {}, options: {} };
@@ -68,16 +76,11 @@ export class ConsoleIO {
6876
this.validateArguments();
6977
if (this.hasErrors) return this;
7078

71-
/**
72-
* Parse options
73-
*/
7479
for (const option of this.schema.options) {
75-
const value = Obj.get(this.argv, option.name, ...option.alias);
76-
if (value) {
77-
this.values.options[option.name] = value;
78-
} else {
79-
this.values.options[option.name] = option.defaultValue;
80-
}
80+
const values = Object.values(
81+
Obj.pick(this.argv, [option.name, ...option.alias]),
82+
);
83+
this.values.options[option.name] = values[0] ? values[0] : undefined;
8184
}
8285

8386
return this;

lib/utils/helpers.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,14 @@ import { Obj } from './object';
99
import { Str } from './string';
1010

1111
export const isEmpty = (value: any) => {
12-
if (Str.isString(value)) {
13-
return value === '';
14-
}
15-
16-
if (Arr.isArray(value)) {
17-
return !value.length;
18-
}
19-
20-
if (Obj.isObj(value)) {
21-
return Obj.isEmpty(value);
22-
}
23-
24-
if (Number.isNaN(value) || value === undefined) {
25-
return true;
26-
}
27-
12+
if (Str.isString(value)) return value === '';
13+
if (Arr.isArray(value)) return !value.length;
14+
if (Obj.isObj(value)) return Obj.isEmpty(value);
15+
if (Number.isNaN(value) || value === undefined) return true;
2816
return false;
2917
};
3018

31-
export const isBoolean = (value: any): boolean => {
32-
return typeof value === 'boolean';
33-
};
19+
export const isBoolean = (value: any): boolean => typeof value === 'boolean';
3420

3521
export const toBoolean = (value: any) => {
3622
if (!Str.isString(value) || typeof value !== 'boolean') return undefined;

lib/utils/object.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,26 +102,24 @@ export class Obj {
102102
return !Obj.isEmpty(obj);
103103
}
104104

105-
static get<T>(
105+
static get<T = any>(
106106
obj: Record<string, any>,
107107
key: string,
108-
...aliasKeys: string[]
108+
defaultValue?: T,
109109
): T {
110-
const keys = [key, ...aliasKeys];
111-
for (const key of keys) {
112-
if (key in obj) return obj[key];
113-
const splitKeys = key.split('.');
114-
if (!splitKeys.length) return;
110+
if (key in obj) return obj[key];
111+
const splitKeys = key.split('.');
112+
if (!splitKeys.length) return;
115113

116-
if (Arr.isArray(obj[splitKeys[0]])) {
117-
return Arr.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
118-
}
114+
if (Arr.isArray(obj[splitKeys[0]])) {
115+
return Arr.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
116+
}
119117

120-
if (Obj.isObj(obj[splitKeys[0]])) {
121-
return Obj.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
122-
}
118+
if (Obj.isObj(obj[splitKeys[0]])) {
119+
return Obj.get(obj[splitKeys[0]], splitKeys.slice(1).join('.'));
123120
}
124-
return undefined;
121+
122+
return defaultValue;
125123
}
126124

127125
static sort<T = Record<string, any>>(obj: T): T {

lib/utils/tests/array.spec.ts

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,94 @@ import { Arr } from '../array';
22

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

5-
describe('Array Helpers', () => {
5+
describe('Array Helper', () => {
66
beforeEach(async () => {});
77

8-
it('should collapse a nested array in a single level array', () => {
9-
const sample1 = ['a', ['b', ['c'], 1], 2];
10-
expect(Arr.collapse(sample1)).toStrictEqual(['a', 'b', 'c', 1, 2]);
8+
// it('should throw exception', () => {
9+
// const arr = {};
10+
// expect(Arr.toObj(arr as [], [])).toThrow(InvalidValue);
11+
// });
12+
13+
it('should return object', () => {
14+
const arr = [
15+
2,
16+
['bar', 'piyush', 'intent'],
17+
{ foo: 'bar' },
18+
[{ bar: 'foo' }],
19+
];
20+
21+
const keys = ['foo', 'chhabra', 'best framework', 'obj'];
22+
expect(Arr.toObj(arr, keys)).toStrictEqual([
23+
{ foo: 'bar', chhabra: 'piyush', 'best framework': 'intent' },
24+
{ foo: { bar: 'foo' } },
25+
]);
26+
});
27+
28+
// it('should throw exception', () => {
29+
// const arr = {};
30+
// expect(Arr.isArray(arr as [], true)).toThrow(InvalidValue);
31+
// });
32+
33+
it('should return false', () => {
34+
const arr = {};
35+
expect(Arr.isArray(arr as [])).toBeFalsy();
36+
});
37+
38+
it('should return false', () => {
39+
const arr = [];
40+
expect(Arr.isArray(arr)).toBeTruthy();
41+
});
42+
43+
it('should return array of nested members flattened', () => {
44+
const arr = [1, [2, 3, 4], [[5, 6], [[7], 8], 9]];
45+
expect(Arr.collapse(arr)).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
46+
});
47+
48+
it('should return array with random order of input', () => {
49+
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
50+
const mockMath = Object.create(global.Math);
51+
mockMath.random = () => 0.5;
52+
global.Math = mockMath;
53+
expect(Arr.random(arr)).toStrictEqual([1, 6, 2, 8, 3, 7, 4, 9, 5]);
54+
});
55+
56+
it('should return array with sorted order of input', () => {
57+
const arr = [6, 1, 2, 8, 3, 7, 4, 9, 5];
58+
expect(Arr.sort(arr)).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
59+
});
60+
61+
it('should return array with descending order of input', () => {
62+
const arr = [6, 1, 2, 8, 3, 7, 4, 9, 5];
63+
expect(Arr.sortDesc(arr)).toStrictEqual([9, 8, 7, 6, 5, 4, 3, 2, 1]);
64+
});
65+
66+
it('should return array with common elements from both input arrays', () => {
67+
const arr1 = [1, 2, 3, 4, 5];
68+
const arr2 = [4, 5, 6, 7, 8];
69+
expect(Arr.intersect(arr1, arr2)).toStrictEqual([4, 5]);
70+
});
71+
72+
it('should return array with elements keys mentioned to pick', () => {
73+
const arr = [
74+
{ developer: { id: 1, name: 'Taylor' } },
75+
{ developer: { id: 2, name: 'Abigail' } },
76+
];
77+
const pick = ['*.developer.name'];
78+
expect(Arr.pick(arr, pick)).toStrictEqual([
79+
{ developer: { name: 'Taylor' } },
80+
{ developer: { name: 'Abigail' } },
81+
]);
82+
});
83+
84+
it('should return array with all elements except the keys mentioned', () => {
85+
const arr = [
86+
{ developer: { id: 1, name: 'Taylor' } },
87+
{ developer: { id: 2, name: 'Abigail' } },
88+
];
89+
const pick = ['*.developer.name'];
90+
expect(Arr.except(arr, pick)).toStrictEqual([
91+
{ developer: { id: 1 } },
92+
{ developer: { id: 2 } },
93+
]);
1194
});
1295
});

lib/utils/tests/number.spec.ts

Lines changed: 88 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,117 @@ import { Num } from '../number';
22

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

5-
describe('Number Helpers', () => {
5+
describe('Numbers Helper', () => {
66
beforeEach(async () => {});
77

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

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

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

23-
it('should conver the number to indian currency format', () => {
24-
const num = 12300;
25-
expect(Num.currency(num, { currency: 'INR' })).toStrictEqual('₹12,300.00');
25+
it('should return number itself', () => {
26+
const number = 12345;
27+
const min = 12300;
28+
const max = 12400;
29+
expect(Num.clamp(number, min, max)).toBe(number);
2630
});
2731

28-
it('should conver the number to dollar currency format', () => {
29-
const num = 12300;
30-
expect(Num.currency(num, { currency: 'USD' })).toStrictEqual('$12,300.00');
32+
it('should return minimum number', () => {
33+
const number = 12345;
34+
const min = 12350;
35+
const max = 12400;
36+
expect(Num.clamp(number, min, max)).toBe(min);
3137
});
3238

33-
it('should convert the number to file size representation', () => {
34-
const samples = { 1000: '1KB', 1024: '1KB', [1024 * 1024 * 1.5]: '1.57MB' };
35-
expect(Num.fileSize(1000)).toStrictEqual('1KB');
36-
expect(Num.fileSize(1024)).toStrictEqual('1KB');
37-
expect(Num.fileSize(1024 * 1024 * 1.5, { precision: 2 })).toStrictEqual(
38-
'1.57MB',
39-
);
39+
it('should return maximum number', () => {
40+
const number = 12345;
41+
const min = 12300;
42+
const max = 12340;
43+
expect(Num.clamp(number, min, max)).toBe(max);
4044
});
4145

42-
it('should convert the number to human readable format', () => {
43-
expect(Num.forHumans(100)).toStrictEqual('100');
44-
expect(Num.forHumans(1200)).toStrictEqual('1.2 thousand');
46+
it('should return number in currency style in INR', () => {
47+
const number = 12345;
48+
const options = { currency: 'INR', locale: 'en' };
49+
expect(Num.currency(number, options)).toBe('₹12,345.00');
4550
});
4651

47-
it('should convert the number to human readable format, with precision', () => {
48-
expect(Num.forHumans(1230, { precision: 2 })).toStrictEqual(
49-
'1.23 thousand',
50-
);
52+
it('should return number in currency style in USD', () => {
53+
const number = 12345;
54+
const options = { currency: 'USD', locale: 'en' };
55+
expect(Num.currency(number, options)).toBe('$12,345.00');
56+
});
57+
58+
it('should return number in file size format', () => {
59+
const number = 12345;
60+
expect(Num.fileSize(number)).toBe('12.3KB');
61+
});
62+
63+
it('should return number in file size format with precision 3', () => {
64+
const number = 123456789;
65+
const options = { precision: 3 };
66+
expect(Num.fileSize(number, options)).toBe('123.457MB');
67+
});
68+
69+
it('should return number in humanize form with precision 1', () => {
70+
const number = 12345;
71+
const options = { precision: 1, locale: 'en' };
72+
expect(Num.forHumans(number, options)).toBe('12.3 thousand');
5173
});
5274

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

57-
it('should format the number to the given locale string', () => {
58-
expect(Num.format(1000)).toStrictEqual('1,000');
59-
expect(Num.format(1000, { locale: 'fr' })).toStrictEqual('1 000');
60-
expect(Num.format(1200)).toStrictEqual('1,200');
81+
it('should return number in number system format with precision 1(default)', () => {
82+
const number = 12345.78;
83+
const options = { locale: 'en' };
84+
expect(Num.format(number, options)).toBe('12,345.8');
6185
});
6286

63-
it('converts the given number to the ordinal format', () => {
64-
expect(Num.ordinal(1)).toStrictEqual('1st');
65-
expect(Num.ordinal(2)).toStrictEqual('2nd');
66-
expect(Num.ordinal(3)).toStrictEqual('3rd');
67-
expect(Num.ordinal(20)).toStrictEqual('20th');
87+
it('should return number in percents when passed as decimal portion with precision 1(default)', () => {
88+
const number = 17.8;
89+
const options = { locale: 'en' };
90+
expect(Num.percentage(number, options)).toBe('17.8%');
6891
});
6992

70-
it('converts the number to a percentage format with support for precision and locale config', () => {
71-
expect(Num.percentage(10)).toStrictEqual('10.0%');
72-
expect(Num.percentage(10, { locale: 'fr' })).toStrictEqual('10,0 %');
73-
expect(Num.percentage(10.123, { precision: 2 })).toStrictEqual('10.12%');
93+
it('should return number in ordinal format', () => {
94+
const number = 231;
95+
expect(Num.ordinal(number)).toBe('231st');
96+
});
97+
98+
it('should return number in ordinal format', () => {
99+
const number = 12345;
100+
expect(Num.ordinal(number)).toBe('12345th');
101+
});
102+
103+
it('should return number in english words', () => {
104+
const number = 12345;
105+
expect(Num.spell(number)).toBe(
106+
'twelve thousand three hundred and forty five only',
107+
);
108+
});
109+
110+
it('should return false', () => {
111+
const number = '12345';
112+
expect(Num.isInteger(number)).toBe(false);
113+
});
114+
it('should return true', () => {
115+
const number = 12345;
116+
expect(Num.isInteger(number)).toBe(true);
74117
});
75118
});

0 commit comments

Comments
 (0)