UNPKG

@decaf-ts/core

Version:

Core persistence module for the decaf framework

345 lines 15.7 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import { Model, required, } from "@decaf-ts/decorator-validation"; import { GroupOperator, Operator } from "./constants.js"; import { QueryError } from "./errors.js"; /** * @description Represents a logical condition for database queries * @summary A class that encapsulates query conditions with support for complex logical operations. * This class allows for building and combining query conditions using logical operators (AND, OR, NOT) * and comparison operators (equals, not equals, greater than, etc.). * @template M - The model type this condition operates on * @param {string | Condition<M>} attr1 - The attribute name or a nested condition * @param {Operator | GroupOperator} operator - The operator to use for the condition * @param {any} comparison - The value to compare against or another condition * @class Condition * @example * // Create a simple condition * const nameCondition = Condition.attribute("name").eq("John"); * * // Create a complex condition * const complexCondition = Condition.attribute("age").gt(18) * .and(Condition.attribute("status").eq("active")); * * // Use the builder pattern * const userQuery = Condition.builder() * .attribute("email").regexp(".*@example.com") * .and(Condition.attribute("lastLogin").gt(new Date("2023-01-01"))); * @mermaid * sequenceDiagram * participant Dev * participant Condition * Dev->>Condition: builder().attribute("age").gt(18) * Condition-->>Dev: Condition(age > 18) * Dev->>Condition: .and(attribute("status").eq("active")) * Condition-->>Dev: Condition((age > 18) AND (status = "active")) */ export class Condition extends Model { constructor(attr1, operator, comparison) { super(); this.attr1 = undefined; this.operator = undefined; this.comparison = undefined; if (!operator && !comparison) { Model.fromModel(this, attr1); } else { this.attr1 = attr1; this.operator = operator; this.comparison = comparison; } } /** * @description Combines this condition with another using logical AND * @summary Joins two conditions with an AND operator, requiring both to be true * @param {Condition<M>} condition - The condition to combine with this one * @return {Condition<M>} A new condition representing the AND operation */ and(condition) { return Condition.and(this, condition); } /** * @description Combines this condition with another using logical OR * @summary Joins two conditions with an OR operator, requiring at least one to be true * @param {Condition<M>} condition - The condition to combine with this one * @return {Condition<M>} A new condition representing the OR operation */ or(condition) { return Condition.or(this, condition); } /** * @description Creates a negation condition * @summary Excludes a value from the result by applying a NOT operator * @param {any} val - The value to negate * @return {Condition<M>} A new condition representing the NOT operation */ not(val) { return new Condition(this, Operator.NOT, val); } /** * @description Validates the condition and checks for errors * @summary Extends the base validation to ensure the condition is properly formed * @param {...string[]} exceptions - Fields to exclude from validation * @return {ModelErrorDefinition | undefined} Error definition if validation fails, undefined otherwise */ hasErrors(...exceptions) { const conditionCheck = () => { const invalidOpMessage = `Invalid operator ${this.operator}}`; if (typeof this.attr1 === "string") { if (this.comparison instanceof Condition) return { comparison: { condition: "Both sides of the comparison must be of the same type", }, }; if (Object.values(Operator).indexOf(this.operator) === -1) return { operator: { condition: invalidOpMessage, }, }; } if (this.attr1 instanceof Condition) { if (!(this.comparison instanceof Condition) && this.operator !== Operator.NOT) return { comparison: { condition: invalidOpMessage, }, }; if (Object.values(GroupOperator).indexOf(this.operator) === -1 && this.operator !== Operator.NOT) return { operator: { condition: invalidOpMessage, }, }; } }; const errors = super.hasErrors(...exceptions); if (!this.isAsync()) return (errors ?? conditionCheck()); return (async () => { const resolved = await Promise.resolve(errors); return resolved ?? conditionCheck(); })(); } /** * @description Creates a new condition that combines two conditions with logical AND * @summary Static method that joins two conditions with an AND operator, requiring both to be true * @template M - The model type this condition operates on * @param {Condition<M>} condition1 - The first condition * @param {Condition<M>} condition2 - The second condition * @return {Condition<M>} A new condition representing the AND operation */ static and(condition1, condition2) { return Condition.group(condition1, GroupOperator.AND, condition2); } /** * @description Creates a new condition that combines two conditions with logical OR * @summary Static method that joins two conditions with an OR operator, requiring at least one to be true * @template M - The model type this condition operates on * @param {Condition<M>} condition1 - The first condition * @param {Condition<M>} condition2 - The second condition * @return {Condition<M>} A new condition representing the OR operation */ static or(condition1, condition2) { return Condition.group(condition1, GroupOperator.OR, condition2); } /** * @description Creates a new condition that groups two conditions with a specified operator * @summary Private static method that combines two conditions using the specified group operator * @template M - The model type this condition operates on * @param {Condition<M>} condition1 - The first condition * @param {GroupOperator} operator - The group operator to use (AND, OR) * @param {Condition<M>} condition2 - The second condition * @return {Condition<M>} A new condition representing the grouped operation */ static group(condition1, operator, condition2) { return new Condition(condition1, operator, condition2); } /** * @description Creates a condition builder for a specific model attribute * @summary Static method that initializes a condition builder with the specified attribute * @template M - The model type this condition operates on * @param attr - The model attribute to build a condition for * @return {AttributeOption<M>} A condition builder initialized with the attribute */ static attribute(attr) { return new Condition.Builder().attribute(attr); } /** * @description Alias for the attribute method * @summary Shorthand method that initializes a condition builder with the specified attribute * @template M - The model type this condition operates on * @param attr - The model attribute to build a condition for * @return {AttributeOption<M>} A condition builder initialized with the attribute */ static attr(attr) { return this.attribute(attr); } /** * @description Provides a fluent API to build query conditions * @summary A builder class that simplifies the creation of database query conditions * with a chainable interface for setting attributes and operators * @template M - The model type this condition builder operates on * @class ConditionBuilder */ static { this.Builder = class ConditionBuilder { constructor() { this.attr1 = undefined; this.operator = undefined; this.comparison = undefined; } /** * @description Sets the attribute for the condition * @summary Specifies which model attribute the condition will operate on * @param attr - The model attribute to use in the condition * @return {AttributeOption<M>} This builder instance for method chaining */ attribute(attr) { this.attr1 = attr; return this; } /** * @description Alias for the attribute method * @summary Shorthand method to specify which model attribute the condition will operate on * @param attr - The model attribute to use in the condition * @return {AttributeOption<M>} This builder instance for method chaining */ attr(attr) { return this.attribute(attr); } /** * @description Creates an equality condition * @summary Builds a condition that checks if the attribute equals the specified value * @param {any} val - The value to compare the attribute against * @return {Condition<M>} A new condition representing the equality comparison */ eq(val) { return this.setOp(Operator.EQUAL, val); } /** * @description Creates an inequality condition * @summary Builds a condition that checks if the attribute is different from the specified value * @param {any} val - The value to compare the attribute against * @return {Condition<M>} A new condition representing the inequality comparison */ dif(val) { return this.setOp(Operator.DIFFERENT, val); } /** * @description Creates a greater than condition * @summary Builds a condition that checks if the attribute is greater than the specified value * @param {any} val - The value to compare the attribute against * @return {Condition<M>} A new condition representing the greater than comparison */ gt(val) { return this.setOp(Operator.BIGGER, val); } /** * @description Creates a less than condition * @summary Builds a condition that checks if the attribute is less than the specified value * @param {any} val - The value to compare the attribute against * @return {Condition<M>} A new condition representing the less than comparison */ lt(val) { return this.setOp(Operator.SMALLER, val); } /** * @description Creates a greater than or equal to condition * @summary Builds a condition that checks if the attribute is greater than or equal to the specified value * @param {any} val - The value to compare the attribute against * @return {Condition<M>} A new condition representing the greater than or equal comparison */ gte(val) { return this.setOp(Operator.BIGGER_EQ, val); } /** * @description Creates a less than or equal to condition * @summary Builds a condition that checks if the attribute is less than or equal to the specified value * @param {any} val - The value to compare the attribute against * @return {Condition<M>} A new condition representing the less than or equal comparison */ lte(val) { return this.setOp(Operator.SMALLER_EQ, val); } /** * @description Creates an inclusion condition * @summary Builds a condition that checks if the attribute value is included in the specified array * @param {any[]} arr - The array of values to check against * @return {Condition<M>} A new condition representing the inclusion comparison */ in(arr) { return this.setOp(Operator.IN, arr); } /** * @description Creates a regular expression condition * @summary Builds a condition that checks if the attribute matches the specified regular expression pattern * @param {any} val - The regular expression pattern to match against * @return {Condition<M>} A new condition representing the regular expression comparison */ regexp(val) { return this.setOp(Operator.REGEXP, new RegExp(val).source); } /** * @description Sets the operator and comparison value for the condition * @summary Private method that configures the condition with the specified operator and value * @param {Operator} op - The operator to use for the condition * @param {any} val - The value to compare against * @return {Condition<M>} A new condition with the specified operator and value */ setOp(op, val) { this.operator = op; this.comparison = val; return this.build(); } /** * @description Constructs a Condition instance from the builder's state * @summary Finalizes the condition building process by creating a new Condition instance * @throws {QueryError} If the condition cannot be built due to invalid parameters * @return {Condition<M>} A new condition instance with the configured attributes */ build() { try { return new Condition(this.attr1, this.operator, this.comparison); } catch (e) { throw new QueryError(e); } } }; } /** * @description Creates a new condition builder * @summary Factory method that returns a new instance of the condition builder * @template M - The model type this condition builder will operate on * @return {ConditionBuilderOption<M>} A new condition builder instance */ static builder() { return new Condition.Builder(); } static from(obj) { return new Condition(obj); } } __decorate([ required(), __metadata("design:type", Object) ], Condition.prototype, "attr1", void 0); __decorate([ required(), __metadata("design:type", String) ], Condition.prototype, "operator", void 0); __decorate([ required(), __metadata("design:type", Object) ], Condition.prototype, "comparison", void 0); //# sourceMappingURL=Condition.js.map