import { Result, ResultCollection, RuleValidator, UndefinedOr } from "@repo/rdx-utils"; import { StringValueObject } from "../helpers"; import { IOrderProps, Order } from "./Order"; import { IOrderCollection, OrderCollection } from "./OrderCollection"; export interface IOrderCriteria { getOrderCollection(): IOrderCollection; toJSON(): string; toString(): string; toObject(): Record; } export class OrderCriteria extends StringValueObject implements IOrderCriteria { private static parseOrderString = (orderString: UndefinedOr): string[][] => { // eslint-disable-next-line no-useless-escape //return OrderString.match(/(.+)(([\[])([\w]+)([\]]))([\w\W]+)*/i); const result: any[] = []; if (orderString) { const regex = /([+-]?)([\w_.]+)/gi; let matches: any; // biome-ignore lint/suspicious/noAssignInExpressions: while ((matches = regex.exec(orderString)) !== null) { result.push([...matches]); } } return result; }; protected static validate(value: UndefinedOr) { let orderString = value; if (RuleValidator.validate(RuleValidator.RULE_NOT_NULL_OR_UNDEFINED, orderString).isFailure) { return Result.ok(value); } const stringOrError = RuleValidator.validate( RuleValidator.RULE_IS_TYPE_STRING, orderString ); if (stringOrError.isFailure) { return stringOrError; } orderString = String(value); const orderOrErrors = new ResultCollection(); // biome-ignore lint/complexity/noForEach: OrderCriteria.parseOrderString(orderString).forEach((token: string[]) => { const orderOrError = Order.create({ type: token[1] || "+", field: String(token[2]), }); orderOrErrors.add(orderOrError); }); if (orderOrErrors.hasSomeFaultyResult()) { return orderOrErrors.getFirstFaultyResult() as Result; } return Result.ok(orderString); } public static create(value: UndefinedOr) { const validatedProps = OrderCriteria.validate(value); if (validatedProps.isFailure) { return Result.fail(validatedProps.error); } return Result.ok(new OrderCriteria(validatedProps.data)); } public getOrderCollection(): IOrderCollection { return this.buildOrderCollection(); } public toJSON(): string { return JSON.stringify(this.toObject()); } public toPrimitive(): string { throw new Error("NOT IMPLEMENT OrderCriteria.toPrimitive()"); } public toObject(): Record { return this.getOrderCollection().toObject(); } protected buildOrderCollection(): IOrderCollection { let _orders: IOrderProps[] | undefined = undefined; if (!this.isEmpty()) { _orders = OrderCriteria.parseOrderString(this.props).map((token: string[]) => { /** TOKEN * [1] => type + / - (opcional) * [2] => field / model.field */ const type = token[1] ? String(token[1]) : "+"; const orderOrError = Order.create({ type, field: String(token[2]), }); if (orderOrError.isFailure) { throw new Error(`Order '${token.join()}' is not valid`); } return orderOrError.data; }); } return ( _orders === undefined ? OrderCollection.createEmpty() : OrderCollection.create(_orders as Order[]) ) as IOrderCollection; } }