This commit is contained in:
David Arranz 2025-10-30 13:39:30 +01:00
parent 055d70f05a
commit f7e4b036c8
14 changed files with 205 additions and 4 deletions

View File

@ -14,7 +14,6 @@
"@repo/typescript-config": "workspace:*"
},
"dependencies": {
"@codelytv/criteria": "^2.0.0",
"sequelize": "^6.37.5"
}
}

View File

@ -0,0 +1,44 @@
import { FiltersPrimitives } from "./Filter";
import { Filters } from "./Filters";
import { InvalidCriteria } from "./InvalidCriteria";
import { Order } from "./Order";
export class Criteria {
constructor(
public readonly filters: Filters,
public readonly order: Order,
public readonly pageSize: number | null,
public readonly pageNumber: number | null,
) {
if (pageNumber !== null && pageSize === null) {
throw new InvalidCriteria();
}
}
static fromPrimitives(
filters: FiltersPrimitives[],
orderBy: string | null,
orderType: string | null,
pageSize: number | null,
pageNumber: number | null,
): Criteria {
return new Criteria(
Filters.fromPrimitives(filters),
Order.fromPrimitives(orderBy, orderType),
pageSize,
pageNumber,
);
}
static withFilters(filters: FiltersPrimitives[]): Criteria {
return Criteria.fromPrimitives(filters, null, null, null, null);
}
hasOrder(): boolean {
return !this.order.isNone();
}
hasFilters(): boolean {
return !this.filters.isEmpty();
}
}

View File

@ -0,0 +1,37 @@
import { FilterField } from "./FilterField";
import { FilterOperator, Operator } from "./FilterOperator";
import { FilterValue } from "./FilterValue";
export type FiltersPrimitives = {
field: string;
operator: string;
value: string;
};
export class Filter {
readonly field: FilterField;
readonly operator: FilterOperator;
readonly value: FilterValue;
constructor(field: FilterField, operator: FilterOperator, value: FilterValue) {
this.field = field;
this.operator = operator;
this.value = value;
}
static fromPrimitives(field: string, operator: string, value: string): Filter {
return new Filter(
new FilterField(field),
new FilterOperator(Operator[operator as keyof typeof Operator]),
new FilterValue(value),
);
}
toPrimitives(): FiltersPrimitives {
return {
field: this.field.value,
operator: this.operator.value,
value: this.value.value,
};
}
}

View File

@ -0,0 +1,3 @@
export class FilterField {
constructor(public readonly value: string) {}
}

View File

@ -0,0 +1,42 @@
export enum Operator {
EQUAL = "=",
NOT_EQUAL = "!=",
GREATER_THAN = ">",
GREATER_THAN_OR_EQUAL = ">=",
LOWER_THAN = "<",
LOWER_THAN_OR_EQUAL = "<=",
CONTAINS = "CONTAINS",
NOT_CONTAINS = "NOT_CONTAINS",
}
export class FilterOperator {
constructor(public readonly value: Operator) {}
isContains(): boolean {
return this.value.valueOf() === Operator.CONTAINS.valueOf();
}
isNotContains(): boolean {
return this.value.valueOf() === Operator.NOT_CONTAINS.valueOf();
}
isNotEquals(): boolean {
return this.value.valueOf() === Operator.NOT_EQUAL.valueOf();
}
isGreaterThan(): boolean {
return this.value.valueOf() === Operator.GREATER_THAN.valueOf();
}
isGreaterThanOrEqual(): boolean {
return this.value.valueOf() === Operator.GREATER_THAN_OR_EQUAL.valueOf();
}
isLowerThan(): boolean {
return this.value.valueOf() === Operator.LOWER_THAN.valueOf();
}
isLowerThanOrEqual(): boolean {
return this.value.valueOf() === Operator.LOWER_THAN_OR_EQUAL.valueOf();
}
}

View File

@ -0,0 +1,3 @@
export class FilterValue {
constructor(public readonly value: string) {}
}

View File

@ -0,0 +1,19 @@
import { Filter, FiltersPrimitives } from "./Filter";
export class Filters {
constructor(public readonly value: Filter[]) {}
static fromPrimitives(filters: FiltersPrimitives[]): Filters {
return new Filters(
filters.map((filter) => Filter.fromPrimitives(filter.field, filter.operator, filter.value)),
);
}
toPrimitives(): FiltersPrimitives[] {
return this.value.map((filter) => filter.toPrimitives());
}
isEmpty(): boolean {
return this.value.length === 0;
}
}

View File

@ -0,0 +1,5 @@
export class InvalidCriteria extends Error {
constructor() {
super("Page size is required when page number is defined");
}
}

View File

@ -0,0 +1,23 @@
import { OrderBy } from "./OrderBy";
import { OrderType, OrderTypes } from "./OrderType";
export class Order {
constructor(
public readonly orderBy: OrderBy,
public readonly orderType: OrderType,
) {}
static none(): Order {
return new Order(new OrderBy(""), new OrderType(OrderTypes.NONE));
}
static fromPrimitives(orderBy: string | null, orderType: string | null): Order {
return orderBy !== null
? new Order(new OrderBy(orderBy), new OrderType(orderType as OrderTypes))
: Order.none();
}
isNone(): boolean {
return this.orderType.isNone();
}
}

View File

@ -0,0 +1,3 @@
export class OrderBy {
constructor(public readonly value: string) {}
}

View File

@ -0,0 +1,13 @@
export enum OrderTypes {
ASC = "ASC",
DESC = "DESC",
NONE = "NONE",
}
export class OrderType {
constructor(public readonly value: OrderTypes) {}
isNone(): boolean {
return this.value === OrderTypes.NONE;
}
}

View File

@ -0,0 +1,10 @@
export * from "./Criteria";
export * from "./Filter";
export * from "./FilterField";
export * from "./FilterOperator";
export * from "./Filters";
export * from "./FilterValue";
export * from "./InvalidCriteria";
export * from "./Order";
export * from "./OrderBy";
export * from "./OrderType";

View File

@ -1,4 +1,4 @@
import { Criteria as BaseCriteria, Filters, FiltersPrimitives, Order } from "@codelytv/criteria";
import { Criteria as BaseCriteria, Filters, FiltersPrimitives, Order } from "./codelytv";
import { INITIAL_PAGE_INDEX, INITIAL_PAGE_SIZE } from "./defaults";
export class Criteria extends BaseCriteria {

View File

@ -1,4 +1,4 @@
import { FiltersPrimitives } from "@codelytv/criteria";
import { FiltersPrimitives } from "./codelytv";
import { Criteria } from "./critera";
import { DEFAULT_ORDER, INITIAL_PAGE_INDEX, INITIAL_PAGE_SIZE } from "./defaults";
@ -74,7 +74,7 @@ export class CriteriaFromUrlConverter {
}
});
// @ts-ignore
// @ts-expect-error
return Object.values(tempFilters).filter(
(filter) =>
filter.field !== undefined && filter.operator !== undefined && filter.value !== undefined