Skip to content

Commit

Permalink
feat: enhance parsing of parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
tada5hi committed Feb 14, 2023
1 parent 7cef633 commit 2cc8b4d
Show file tree
Hide file tree
Showing 20 changed files with 96 additions and 125 deletions.
5 changes: 1 addition & 4 deletions src/build/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ import {
export function buildQuery<T extends ObjectLiteral = ObjectLiteral>(
input?: BuildInput<T>,
) : string {
if (
typeof input === 'undefined' ||
input === null
) {
if (!input) {
return '';
}

Expand Down
2 changes: 1 addition & 1 deletion src/build/parameter/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type BuildParameterInput<
P extends `${Parameter.RELATIONS}` | `${URLParameter.RELATIONS}` ?
RelationsBuildInput<T> :
P extends `${Parameter.PAGINATION}` | `${URLParameter.PAGINATION}` ?
PaginationBuildInput<T> :
PaginationBuildInput :
P extends `${Parameter.SORT}` | `${URLParameter.SORT}` ?
SortBuildInput<T> :
never;
41 changes: 17 additions & 24 deletions src/parameter/fields/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* view the LICENSE file that was distributed with this source code.
*/

import { merge } from 'smob';
import { isObject, merge } from 'smob';
import { ObjectLiteral } from '../../type';
import {
applyMapping, buildFieldWithPath, groupArrayByKeyPath, hasOwnProperty, isFieldPathAllowedByRelations,
Expand Down Expand Up @@ -37,7 +37,7 @@ function buildReverseRecord(
}

export function parseQueryFields<T extends ObjectLiteral = ObjectLiteral>(
data: unknown,
input: unknown,
options?: FieldsParseOptions<T>,
) : FieldsParseOutput {
options = options || {};
Expand All @@ -63,26 +63,22 @@ export function parseQueryFields<T extends ObjectLiteral = ObjectLiteral>(
(
typeof options.default !== 'undefined' ||
typeof options.allowed !== 'undefined'
) && keys.length === 0
) &&
keys.length === 0
) {
return [];
}

const prototype: string = Object.prototype.toString.call(data);
if (
prototype !== '[object Object]' &&
prototype !== '[object Array]' &&
prototype !== '[object String]'
) {
data = { [DEFAULT_ID]: [] };
}

if (prototype === '[object String]') {
data = { [DEFAULT_ID]: data };
}
let data : Record<string, any> = {
[DEFAULT_ID]: [],
};

if (prototype === '[object Array]') {
data = { [DEFAULT_ID]: data };
if (isObject(input)) {
data = input;
} else if (typeof input === 'string') {
data = { [DEFAULT_ID]: input };
} else if (Array.isArray(input)) {
data = { [DEFAULT_ID]: input };
}

options.mapping = options.mapping || {};
Expand All @@ -106,16 +102,13 @@ export function parseQueryFields<T extends ObjectLiteral = ObjectLiteral>(

let fields : string[] = [];

if (
hasOwnProperty(data, path)
) {
if (hasOwnProperty(data, path)) {
fields = parseFieldsInput(data[path]);
} else if (
hasOwnProperty(reverseMapping, path)
hasOwnProperty(reverseMapping, path) &&
hasOwnProperty(data, reverseMapping[path])
) {
if (hasOwnProperty(data, reverseMapping[path])) {
fields = parseFieldsInput(data[reverseMapping[path]]);
}
fields = parseFieldsInput(data[reverseMapping[path]]);
}

let transformed : FieldsInputTransformed = {
Expand Down
43 changes: 19 additions & 24 deletions src/parameter/fields/utils/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { FieldsInputTransformed } from '../type';
import { FieldOperator } from '../constants';

export function removeFieldInputOperator(field: string) {
return field.substring(0, 1) === FieldOperator.INCLUDE ||
field.substring(0, 1) === FieldOperator.EXCLUDE ?
const firstCharacter = field.substring(0, 1);

return firstCharacter === FieldOperator.INCLUDE ||
firstCharacter === FieldOperator.EXCLUDE ?
field.substring(1) :
field;
}
Expand All @@ -27,9 +29,11 @@ export function transformFieldsInput(
for (let i = 0; i < fields.length; i++) {
let operator: FieldOperator | undefined;

if (fields[i].substring(0, 1) === FieldOperator.INCLUDE) {
const character = fields[i].substring(0, 1);

if (character === FieldOperator.INCLUDE) {
operator = FieldOperator.INCLUDE;
} else if (fields[i].substring(0, 1) === FieldOperator.EXCLUDE) {
} else if (character === FieldOperator.EXCLUDE) {
operator = FieldOperator.EXCLUDE;
}

Expand All @@ -54,27 +58,18 @@ export function transformFieldsInput(
return output;
}

export function parseFieldsInput(data: unknown): string[] {
const valuePrototype: string = Object.prototype.toString.call(data);
if (
valuePrototype !== '[object Array]' &&
valuePrototype !== '[object String]'
) {
return [];
}
export function parseFieldsInput(input: unknown): string[] {
let output: string[] = [];

let fieldsArr: string[] = [];

/* istanbul ignore next */
if (valuePrototype === '[object String]') {
fieldsArr = (data as string).split(',');
}

/* istanbul ignore next */
if (valuePrototype === '[object Array]') {
fieldsArr = (data as unknown[])
.filter((val) => typeof val === 'string') as string[];
if (typeof input === 'string') {
output = input.split(',');
} else if (Array.isArray(input)) {
for (let i = 0; i < input.length; i++) {
if (typeof input[i] === 'string') {
output.push(input[i]);
}
}
}

return fieldsArr;
return output;
}
2 changes: 1 addition & 1 deletion src/parameter/filters/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function buildQueryFilters<T extends ObjectLiteral = ObjectLiteral>(
});
}

export function mergeQueryFilters<T>(
export function mergeQueryFilters(
target?: Record<string, any>,
source?: Record<string, any>,
) : Record<string, any> {
Expand Down
2 changes: 1 addition & 1 deletion src/parameter/filters/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function transformFiltersParseOutputElement(element: FiltersParseOutputElement)

function buildDefaultFiltersParseOutput<T extends ObjectLiteral = ObjectLiteral>(
options: FiltersParseOptions<T>,
input?: Record<string, FiltersParseOutputElement>,
input: Record<string, FiltersParseOutputElement> = {},
) : FiltersParseOutput {
const inputKeys = Object.keys(input || {});

Expand Down
9 changes: 4 additions & 5 deletions src/parameter/pagination/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
*/

import { merge } from 'smob';
import { ObjectLiteral } from '../../type';
import { PaginationBuildInput } from './type';

export function mergeQueryPagination<T extends ObjectLiteral = ObjectLiteral>(
target?: PaginationBuildInput<T>,
source?: PaginationBuildInput<T>,
) : PaginationBuildInput<T> {
export function mergeQueryPagination(
target?: PaginationBuildInput,
source?: PaginationBuildInput,
) : PaginationBuildInput {
return merge({}, target || {}, source || {});
}
4 changes: 2 additions & 2 deletions src/parameter/pagination/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* view the LICENSE file that was distributed with this source code.
*/

import { isObject } from 'smob';
import { PaginationParseOptions, PaginationParseOutput } from './type';

// --------------------------------------------------
Expand Down Expand Up @@ -46,8 +47,7 @@ export function parseQueryPagination(

const pagination : PaginationParseOutput = {};

const prototype: string = Object.prototype.toString.call(data);
if (prototype !== '[object Object]') {
if (!isObject(data)) {
return finalizePagination(pagination, options);
}

Expand Down
2 changes: 1 addition & 1 deletion src/parameter/pagination/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// Build
// -----------------------------------------------------------

export type PaginationBuildInput<T> = {
export type PaginationBuildInput = {
limit?: number,
offset?: number
};
Expand Down
2 changes: 1 addition & 1 deletion src/parameter/relations/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function buildQueryRelations<T extends ObjectLiteral = ObjectLiteral>(
input?: RelationsBuildInput<T>,
) : string[] {
if (typeof input === 'undefined') {
return input;
return [];
}

return flattenToKeyPathArray(input);
Expand Down
30 changes: 12 additions & 18 deletions src/parameter/relations/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import { includeParents, isValidRelationPath } from './utils';
// --------------------------------------------------

export function parseQueryRelations<T extends ObjectLiteral = ObjectLiteral>(
data: unknown,
options?: RelationsParseOptions<T>,
input: unknown,
options: RelationsParseOptions<T> = {},
): RelationsParseOutput {
options = options || {};

Expand All @@ -36,20 +36,14 @@ export function parseQueryRelations<T extends ObjectLiteral = ObjectLiteral>(

let items: string[] = [];

const prototype: string = Object.prototype.toString.call(data);
if (
prototype !== '[object Array]' &&
prototype !== '[object String]'
) {
return [];
}

if (prototype === '[object String]') {
items = (data as string).split(',');
}

if (prototype === '[object Array]') {
items = (data as any[]).filter((el) => typeof el === 'string');
if (typeof input === 'string') {
items = input.split(',');
} else if (Array.isArray(input)) {
for (let i = 0; i < input.length; i++) {
if (typeof input[i] === 'string') {
items.push(input[i]);
}
}
}

if (items.length === 0) {
Expand All @@ -64,7 +58,7 @@ export function parseQueryRelations<T extends ObjectLiteral = ObjectLiteral>(
}

if (options.allowed) {
items = items.filter((item) => isPathCoveredByParseAllowedOption(options.allowed, item));
items = items.filter((item) => isPathCoveredByParseAllowedOption(options.allowed as string[], item));
} else {
items = items.filter((item) => isValidRelationPath(item));
}
Expand Down Expand Up @@ -94,7 +88,7 @@ export function parseQueryRelations<T extends ObjectLiteral = ObjectLiteral>(
) {
value = options.pathMapping[key];
} else {
value = parts.pop();
value = parts.pop() as string;
}

return {
Expand Down
13 changes: 6 additions & 7 deletions src/parameter/sort/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* view the LICENSE file that was distributed with this source code.
*/

import { isObject } from 'smob';
import { ObjectLiteral } from '../../type';
import {
applyMapping,
Expand Down Expand Up @@ -87,13 +88,11 @@ export function parseQuerySort<T extends ObjectLiteral = ObjectLiteral>(

options.mapping = options.mapping || {};

const prototype = Object.prototype.toString.call(data);

/* istanbul ignore next */
if (
prototype !== '[object String]' &&
prototype !== '[object Array]' &&
prototype !== '[object Object]'
typeof data !== 'string' &&
!Array.isArray(data) &&
!isObject(data)
) {
return buildDefaultSortParseOutput(options);
}
Expand Down Expand Up @@ -198,15 +197,15 @@ export function parseQuerySort<T extends ObjectLiteral = ObjectLiteral>(
for (let i = 0; i < options.allowed.length; i++) {
const temp : SortParseOutput = [];

const keyPaths = flattenParseAllowedOption(options.allowed[i]);
const keyPaths = flattenParseAllowedOption(options.allowed[i] as string[]);

for (let j = 0; j < keyPaths.length; j++) {
let keyWithAlias : string = keyPaths[j];
let key : string;

const parts = keyWithAlias.split('.');
if (parts.length > 1) {
key = parts.pop();
key = parts.pop() as string;
} else {
key = keyWithAlias;

Expand Down
12 changes: 8 additions & 4 deletions src/parameter/utils/parse/allowed-option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
* view the LICENSE file that was distributed with this source code.
*/

import { NestedKeys, NestedResourceKeys } from '../../../type';
import { NestedKeys, NestedResourceKeys, ObjectLiteral } from '../../../type';
import { flattenToKeyPathArray } from '../../../utils';
import { ParseAllowedOption } from '../../type';

export function flattenParseAllowedOption<T>(
input: ParseAllowedOption<T>,
export function flattenParseAllowedOption<T extends ObjectLiteral>(
input?: ParseAllowedOption<T>,
) : string[] {
if (typeof input === 'undefined') {
return [];
}

return flattenToKeyPathArray(input);
}

export function isPathCoveredByParseAllowedOption<T>(
export function isPathCoveredByParseAllowedOption<T extends ObjectLiteral>(
input: ParseAllowedOption<T> |
NestedKeys<T>[] |
NestedResourceKeys<T>[],
Expand Down
4 changes: 2 additions & 2 deletions src/parse/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { ParseInput, ParseOptions, ParseOutput } from './type';

export function parseQuery<T extends ObjectLiteral = ObjectLiteral>(
input: ParseInput,
options?: ParseOptions<T>,
options: ParseOptions<T> = {},
) : ParseOutput {
options = options || {};

Expand All @@ -30,7 +30,7 @@ export function parseQuery<T extends ObjectLiteral = ObjectLiteral>(
}
}

return data;
return data || {} as T;
};

const output : ParseOutput = {};
Expand Down
4 changes: 2 additions & 2 deletions src/parse/parameter/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,6 @@ function invalidToEmptyObject<V>(
): NonNullable<V> {
return typeof value === 'boolean' ||
typeof value === 'undefined' ?
{} as V :
value;
{} as NonNullable<V> :
value as NonNullable<V>;
}
Loading

0 comments on commit 2cc8b4d

Please sign in to comment.