@cloud-ru/ft-request-payload-transform
Version:
149 lines (123 loc) • 3.89 kB
text/typescript
import { EXTRACT_VALUES_REG, PARAM_KEYS } from './constants';
export * from './types';
import {
isPaginationKey,
isValueNotEmpty,
parseStringToValue,
removeEmptyValuesFromObject,
stringifyRequestParams,
} from './helpers';
import {
FieldFilter,
FieldSort,
FilterCondition,
PaginationParams,
RequestPayloadParams,
SortDirection,
} from './types';
type RequestPayloadFormatMethods = {
toObject(): Partial<RequestPayloadParams>;
toString(params?: { encode?: boolean }): string;
};
type RequestPayloadCreator = RequestPayloadFormatMethods & {
filter(params: FieldFilter): RequestPayloadCreator;
ordering(params: FieldSort): RequestPayloadCreator;
pagination(params: PaginationParams): RequestPayloadCreator;
search(value: RequestPayloadParams['search']): RequestPayloadCreator;
};
export function createRequestPayload(params?: undefined): RequestPayloadCreator;
export function createRequestPayload(params: RequestPayloadParams): RequestPayloadFormatMethods;
export function createRequestPayload(
params?: RequestPayloadParams,
): RequestPayloadFormatMethods | RequestPayloadCreator {
const result: Partial<RequestPayloadParams> = params || {};
function toObject() {
return removeEmptyValuesFromObject(result);
}
function toString({ encode }: { encode?: boolean } = { encode: true }) {
return stringifyRequestParams(toObject(), { encode });
}
if (params !== undefined) {
return {
toObject,
toString,
} as RequestPayloadFormatMethods;
}
return {
filter(params) {
if (!result.filter) {
result.filter = [];
}
result.filter.push(params);
return this;
},
ordering(params) {
if (!result.ordering) {
result.ordering = [];
}
result.ordering.push(params);
return this;
},
pagination(params) {
result.pagination = params;
return this;
},
search(value) {
result.search = value;
return this;
},
toObject,
toString,
} as RequestPayloadCreator;
}
export function parseQueryParamsString(params: string): Partial<RequestPayloadParams> | undefined {
if (!params.length) return undefined;
const paramsArray = decodeURIComponent(params).split('&');
const result = paramsArray.reduce<
Partial<Omit<RequestPayloadParams, 'pagination'>> & { pagination?: Partial<PaginationParams> }
>((acc, cur) => {
const [param, value] = cur.split('=');
if (isValueNotEmpty(value)) {
if (param === PARAM_KEYS.ordering) {
const arrayValue = value.replace(/[[\]]/g, '').split(',');
if (arrayValue.length) {
acc[param] = arrayValue.map(ordering => {
const direction = ordering.startsWith('-') ? '-' : '+';
const field = ordering.replace(direction, '');
return {
field,
direction: direction as SortDirection,
};
});
}
return acc;
}
if (param === PARAM_KEYS.filter) {
const matches = Array.from(value.matchAll(EXTRACT_VALUES_REG), ([, f, c, v]) => [f, c, v]);
if (matches.length) {
acc[param] = matches
.map(
([field, condition, value]) =>
({
field,
condition: condition as FilterCondition,
value: parseStringToValue(value),
}) as FieldFilter,
)
.filter(({ value }) => value !== undefined);
}
return acc;
}
if (isPaginationKey(param)) {
if (!acc.pagination) {
acc.pagination = {};
}
acc.pagination[param] = parseStringToValue(value);
return acc;
}
acc[param as keyof RequestPayloadParams] = parseStringToValue(value);
}
return acc;
}, {});
return result as RequestPayloadParams;
}