refactor(core): example usage of Maybe monad in queryParams.factory
MODIFY
packages/core/src/+internal/utils/array.util.ts
packages/core/src/+internal/utils/array.util.ts
+import { Maybe } from '../fp/maybe';
+
export const getArrayFromEnum = (E: Object) =>
Object.keys(E).filter(key => typeof E[key as any] === 'number');
+
+export const getHead = <T>(array: T[]) =>
+ Maybe.of(array[0]);
+
+export const filterArray = <T>(f: (v: T) => boolean) => (array: T[]) =>
+ array.filter(f);
+
+export const mapArray = <T, R>(f: (v: T) => R) => (array: T[]) =>
+ array.map(f);

ADD
packages/core/src/+internal/utils/spec/array.util.spec.ts
+import { getArrayFromEnum, getHead, filterArray, mapArray } from '../array.util';
+
+describe('Array util', () => {
+ test('#getArrayFromEnum returns array from simple enumerable', () => {
+ // given
+ enum Test {
+ TEST_1,
+ TEST_2,
+ }
+
+ // when
+ const result = getArrayFromEnum(Test);
+
+ // then
+ expect(result).toEqual([
+ 'TEST_1',
+ 'TEST_2',
+ ]);
+ });
+
+ test('#getHead returns safe array head', () => {
+ // given
+ const emptyArray = [];
+ const filledArray = ['test'];
+
+ // when
+ const none = getHead<string>(emptyArray).valueOr('');
+ const some = getHead(filledArray).valueOr('');
+
+ // then
+ expect(none).toEqual('');
+ expect(some).toEqual('test');
+ });
+
+ test('#filterArray filters an array by given predicate', () => {
+ // given
+ const array = [0, 1, 2, 3, 4];
+ const predicateFn = (v: number) => v % 2 === 0;
+
+ // when
+ const result = filterArray(predicateFn)(array);
+
+ // then
+ expect(result).toEqual([0, 2, 4]);
+ });
+
+ test('#mapArray maps array items by given function', () => {
+ // given
+ const array = [0, 1, 2, 3, 4];
+ const mapFn = (v: number) => v + 1;
+
+ // when
+ const result = mapArray(mapFn)(array);
+
+ // then
+ expect(result).toEqual([1, 2, 3, 4, 5]);
+ });
+});

MODIFY
packages/core/src/router/queryParams.factory.ts
packages/core/src/router/queryParams.factory.ts
import * as querystring from 'querystring';
-import { compose } from '../+internal';
+import { Nullable, Maybe, getHead } from '../+internal';
import { QueryParameters } from '../http.interface';
-const parseQueryString = (query: string) => querystring.parse(query);
-
-const getNestedQueryParam = (
- key: string,
- paramValue: string | Object
-): string | Object => {
+const getNestedQueryParam = (params: Object) => (key: string): QueryParameters => {
+ const paramValue = params[key];
const nestedKeys = /\[.*]/.exec(key);
- if (!nestedKeys) {
- return { [key]: paramValue };
- }
-
- const extractedKeys = nestedKeys[0]
- .replace(/\[/g, '')
- .split(']')
- .filter(v => v.length > 0);
-
- const nestedQueryObject = extractedKeys.reduceRight(
+ return Maybe.of(nestedKeys)
+ .flatMap(getHead)
+ .map(_ => _.replace(/\[/g, ''))
+ .map(_ => _.split(']'))
+ .map(_ => _.filter(v => v.length > 0))
+ .map(_ => _.reduceRight(
(value, key) => ({ [key]: value }),
- paramValue
- );
-
- return { [key.replace(nestedKeys[0], '')]: nestedQueryObject };
+ paramValue,
+ ))
+ .flatMap(nestedQueryObject => Maybe.of(nestedKeys)
+ .flatMap(getHead)
+ .map(head => key.replace(head, ''))
+ .map(key => ({ [key]: nestedQueryObject }))
+ )
+ .valueOr({ [key]: paramValue });
};
-const queryParamsArrayToObject = (queryParams: Object): QueryParameters => {
- const queryParamsKey = Object.keys(queryParams);
- return Object.assign(
+const extractNestedQueryParams = (queryParams: Object): QueryParameters =>
+ Object.assign(
{},
- ...queryParamsKey.map(key => getNestedQueryParam(key, queryParams[key]))
+ ...Object.keys(queryParams).map(getNestedQueryParam(queryParams))
);
-};
-export const queryParamsFactory = (queryParams: string | undefined | null): QueryParameters =>
- !queryParams
- ? {}
- : compose(
- queryParamsArrayToObject,
- parseQueryString,
- )(queryParams);
+export const queryParamsFactory = (queryParams: Nullable<string>): QueryParameters =>
+ Maybe.of(queryParams)
+ .map(querystring.parse)
+ .map(extractNestedQueryParams)
+ .valueOr({});

refactor(core): example usage of Maybe monad in queryParams.factory