145 lines
3.8 KiB
TypeScript
145 lines
3.8 KiB
TypeScript
import Joi from "joi";
|
|
|
|
import { ValueObject } from "@repo/rdx-ddd";
|
|
import { Result, RuleValidator } from "@repo/rdx-utils";
|
|
import {
|
|
INITIAL_PAGE_INDEX,
|
|
INITIAL_PAGE_SIZE,
|
|
MAX_PAGE_SIZE,
|
|
MIN_PAGE_INDEX,
|
|
MIN_PAGE_SIZE,
|
|
} from "./defaults";
|
|
|
|
export interface IOffsetPagingProps {
|
|
offset: number | string | undefined;
|
|
limit: number | string | undefined;
|
|
}
|
|
|
|
export interface IOffsetPaging {
|
|
offset: number;
|
|
limit: number;
|
|
}
|
|
|
|
export class OffsetPaging extends ValueObject<IOffsetPaging> {
|
|
public static readonly LIMIT_DEFAULT_VALUE: number = INITIAL_PAGE_SIZE;
|
|
public static readonly LIMIT_MINIMAL_VALUE: number = MIN_PAGE_SIZE;
|
|
public static readonly LIMIT_MAXIMAL_VALUE: number = MAX_PAGE_SIZE;
|
|
|
|
public static readonly OFFSET_DEFAULT_VALUE: number = INITIAL_PAGE_INDEX;
|
|
public static readonly OFFSET_MINIMAL_VALUE: number = MIN_PAGE_INDEX;
|
|
public static readonly OFFSET_MAXIMAL_VALUE: number = Number.MAX_SAFE_INTEGER;
|
|
|
|
public static createWithMaxLimit(): Result<OffsetPaging> {
|
|
return OffsetPaging.create({
|
|
offset: OffsetPaging.OFFSET_DEFAULT_VALUE,
|
|
limit: OffsetPaging.LIMIT_MAXIMAL_VALUE,
|
|
});
|
|
}
|
|
|
|
public static createWithDefaultValues(): Result<OffsetPaging> {
|
|
return OffsetPaging.create({
|
|
offset: OffsetPaging.OFFSET_DEFAULT_VALUE,
|
|
limit: OffsetPaging.LIMIT_DEFAULT_VALUE,
|
|
});
|
|
}
|
|
|
|
public static create(paginationProps: IOffsetPagingProps) {
|
|
const offset = paginationProps.offset || OffsetPaging.OFFSET_DEFAULT_VALUE;
|
|
const limit = paginationProps.limit || OffsetPaging.LIMIT_DEFAULT_VALUE;
|
|
|
|
const validatedProps = OffsetPaging.validate(offset, limit);
|
|
|
|
if (validatedProps.isFailure) {
|
|
return Result.fail(validatedProps.error);
|
|
}
|
|
|
|
const paging: IOffsetPaging = validatedProps.data as IOffsetPaging;
|
|
|
|
return Result.ok<OffsetPaging>(new OffsetPaging(paging));
|
|
}
|
|
|
|
private static validate(offset: string | number, limit: string | number) {
|
|
const numberOrError = RuleValidator.validate(RuleValidator.RULE_IS_TYPE_NUMBER, offset);
|
|
|
|
if (numberOrError.isFailure) {
|
|
return numberOrError;
|
|
}
|
|
|
|
const _offset = typeof offset === "string" ? Number.parseInt(offset, 10) : offset;
|
|
|
|
const offsetValidate = RuleValidator.validate(
|
|
Joi.number().min(OffsetPaging.OFFSET_MINIMAL_VALUE).max(OffsetPaging.OFFSET_MAXIMAL_VALUE),
|
|
offset
|
|
);
|
|
|
|
if (offsetValidate.isFailure) {
|
|
return Result.fail(
|
|
new Error(`Page need to be larger than or equal to ${OffsetPaging.OFFSET_MINIMAL_VALUE}.`)
|
|
);
|
|
}
|
|
|
|
// limit
|
|
const limitNumberOrError = RuleValidator.validate(RuleValidator.RULE_IS_TYPE_NUMBER, limit);
|
|
|
|
if (limitNumberOrError.isFailure) {
|
|
return limitNumberOrError;
|
|
}
|
|
|
|
const _limit = typeof limit === "string" ? Number.parseInt(limit, 10) : limit;
|
|
|
|
const limitValidate = RuleValidator.validate(
|
|
Joi.number().min(0).max(OffsetPaging.LIMIT_MAXIMAL_VALUE),
|
|
offset
|
|
);
|
|
|
|
if (limitValidate.isFailure) {
|
|
return Result.fail(
|
|
new Error(`Page size need to be smaller than ${OffsetPaging.LIMIT_MAXIMAL_VALUE}`)
|
|
);
|
|
}
|
|
|
|
return Result.ok({
|
|
offset: _offset,
|
|
limit: _limit,
|
|
});
|
|
}
|
|
|
|
private constructor(props: IOffsetPaging) {
|
|
super(props);
|
|
}
|
|
|
|
getValue() {
|
|
return this.props;
|
|
}
|
|
|
|
get offset(): number {
|
|
return this.props.offset;
|
|
}
|
|
|
|
get limit(): number {
|
|
return this.props.limit;
|
|
}
|
|
|
|
public next(): OffsetPaging {
|
|
return new OffsetPaging({
|
|
offset: this.props.offset + this.props.limit,
|
|
limit: this.props.limit,
|
|
});
|
|
}
|
|
|
|
public toJSON(): string {
|
|
return JSON.stringify(this.toObject());
|
|
}
|
|
|
|
public toPrimitive(): string {
|
|
throw new Error("NOT IMPLEMENT OffsetPaging.toPrimitive()");
|
|
}
|
|
|
|
public toObject(): Record<string, any> {
|
|
return {
|
|
limit: this.props.limit,
|
|
offset: this.props.offset,
|
|
};
|
|
}
|
|
}
|