{"version":3,"sources":["../src/select-query.ts"],"sourcesContent":["const operators = [\n  '===',\n  '!==',\n  '<',\n  '<=',\n  '>',\n  '>=',\n  'like',\n  '^like',\n  'like$',\n] as const;\n\ntype Operator = typeof operators[number];\n\n/**\n * SelectQuery provides utility methods for querying and manipulating collections of objects.\n * @template T - The type of objects in the collection.\n */\nexport class SelectQuery<T extends object> {\n  readonly #collection: T[];\n\n  /**\n   * Gets the array of valid operators for comparisons.\n   * @returns {Operator[]} - An array containing all valid operators for comparisons.\n   * @description\n   * This method returns an array of predefined operators that can be used for comparisons,\n   * such as '===', '!==', '<', '<=', '>', '>=', 'like', '^like', and 'like$'.\n   * These operators are useful in scenarios where you need to dynamically select\n   * an operator for a comparison operation.\n   */\n  static getOperators(): typeof operators {\n    return operators;\n  }\n\n  /**\n   * Creates a new SelectQuery instance with the given collection.\n   * @param {T[]} collection - An array of objects to be used for querying.\n   * @throws {Error} Throws an error if the input is not an array of objects.\n   */\n  constructor(collection: T[]) {\n    if (!Array.isArray(collection) || collection.some((item) => typeof item !== 'object' || item === null)) {\n      throw new Error('The collection should be an array of objects.');\n    }\n\n    this.#collection = collection;\n  }\n\n  /**\n   * Gets the first element of the collection.\n   * @returns {T | undefined} - The first element of the collection, or undefined if the collection is empty.\n   */\n  first(): T | undefined {\n    return this.#collection[0];\n  }\n\n  /**\n   * Gets the last element of the collection.\n   * @returns {T | undefined} - The last element of the collection, or undefined if the collection is empty.\n   */\n  last(): T | undefined {\n    return this.#collection[this.#collection.length - 1];\n  }\n\n  /**\n   * Gets all elements in the collection.\n   * @returns {T[]} - An array containing all elements in the collection.\n   */\n  get(): T[] {\n    return this.#collection;\n  }\n\n  /**\n   * Gets the number of elements in the collection.\n   * @returns {number} - The number of elements in the collection.\n   */\n  count(): number {\n    return this.#collection.length;\n  }\n\n  /**\n   * Limits the number of objects in the collection to a specified maximum.\n   * @param {number} limit - The maximum number of objects to include in the collection.\n   * @returns {SelectQuery<T>} - A new SelectQuery instance with a limited number of objects.\n   */\n  limit(limit: number): SelectQuery<T> {\n    if (limit <= 0) {\n      throw new Error('Limit must be a positive number.');\n    }\n\n    return new SelectQuery<T>(this.#collection.slice(0, limit));\n  }\n\n  /**\n   * Offsets the collection by a specified number of objects.\n   * @param {number} offset - The number of objects to skip from the beginning of the collection.\n   * @returns {SelectQuery<T>} - A new SelectQuery instance with objects after the specified offset.\n   */\n  offset(offset: number): SelectQuery<T> {\n    if (offset < 0 || offset >= this.#collection.length) {\n      throw new Error('Offset is out of range.');\n    }\n\n    return new SelectQuery<T>(this.#collection.slice(offset));\n  }\n\n  /**\n   * Paginates the collection based on a page number and page size.\n   * @param {number} num - The page number (1-based).\n   * @param {number} size - The number of objects per page.\n   * @returns {SelectQuery<T>} - A new SelectQuery instance with objects for the specified page.\n   */\n  paginate(num: number, size: number): SelectQuery<T> {\n    return this.offset((Math.max(num, 1) - 1) * size).limit(size);\n  }\n\n  /**\n   * Calculates the sum of the values for a specified property in the collection.\n   * This method iterates over each object in the collection, accessing the value\n   * of the specified property. It sums these values and returns the total. If a\n   * property's value is `undefined`, `null` it will be ignored\n   * (treated as 0) in the summation.\n   * @template K - The type of the key.\n   * @param {keyof T} key - The property key whose values are to be summed up.\n   * @returns {number} The sum of the property values.\n   * @throws {Error} Throws an error if any property value is not a number.\n   */\n  sum<K extends keyof T>(key: K): number {\n    return this.#collection.reduce((acc, item) => {\n      const value = item[key] as unknown as number;\n\n      if (value === undefined || value === null) {\n        return acc;\n      }\n\n      if (typeof value !== 'number') {\n        throw new Error(`Sum operation failed: the property '${String(key)}' must be a number in every item of the collection.`);\n      }\n\n      return acc + value;\n    }, 0);\n  }\n\n  /**\n   * Selects specific properties from each object in the collection and returns a new SelectQuery instance.\n   * @template K - The keys to select from the objects in the collection.\n   * @param {...K} keys - The keys (properties) to select.\n   * @returns {SelectQuery<Pick<T, K>>} - A new SelectQuery instance with objects containing only the selected keys.\n   */\n  select<K extends keyof T>(...keys: K[]): SelectQuery<Pick<T, K>> {\n    return new SelectQuery<Pick<T, K>>(this.#collection.map((item) => {\n      return keys.reduce((acc, key) => ({ ...acc, [key]: item[key] }), {} as Pick<T, K>);\n    }));\n  }\n\n  /**\n   * Groups elements in a collection based on a specified key.\n   * @template K - The type of the key.\n   * @param {K} key - The key (property name) by which to group elements.\n   * @returns {Record<T[K], T>} - An object with keys as unique values from the collection based on the specified key,\n   * and values as the corresponding objects from the collection.\n   */\n  keyBy<K extends keyof T>(key: K): Record<T[K] & (string | number | symbol), T> {\n    return this.#collection.reduce((acc, item) => {\n      const keyValue = item[key] as T[K] & (string | number | symbol);\n\n      return key in item ? { ...acc, [keyValue]: item } : acc;\n    }, {} as Record<T[K] & (string | number | symbol), T>);\n  }\n\n  /**\n   * Filters the collection based on a specified condition.\n   * @template K - The type of the property to compare.\n   * @param {keyof T} key - The key (property name) to compare.\n   * @param {Operator} operator - The comparison operator.\n   * @param {T[keyof T]} value - The value to compare against.\n   * @returns {SelectQuery<T>} - A new SelectQuery instance with filtered elements.\n   */\n  where<K extends keyof T>(key: K, operator: Operator, value: T[K]): SelectQuery<T> {\n    return new SelectQuery<T>(this.#collection.filter((item) => {\n      const itemValue = item[key];\n\n      switch (operator) {\n        case '===':\n          return this.#equal(itemValue, value);\n\n        case '!==':\n          return !this.#equal(itemValue, value);\n\n        case '<':\n          return this.#lessThan(itemValue, value);\n\n        case '<=':\n          return this.#lessThanOrEqualTo(itemValue, value);\n\n        case '>':\n          return this.#greaterThan(itemValue, value);\n\n        case '>=':\n          return this.#greaterThanOrEqualTo(itemValue, value);\n\n        case 'like':\n          return this.#like(itemValue, value);\n\n        case '^like':\n          return this.#like(itemValue, value, '^like');\n\n        case 'like$':\n          return this.#like(itemValue, value, 'like$');\n\n        default:\n          throw new Error(`Unknown operator: ${operator}`);\n      }\n    }));\n  }\n\n  /**\n   * Checks if the specified property of an item is equal to a given value.\n   * @template K - The type of the property to compare.\n   * @param {T[K]} itemValue - The value of the property to compare.\n   * @param {T[K]} value - The value to compare against.\n   * @returns {boolean} - Returns true if the property values are equal, otherwise returns false.\n   */\n  #equal<K extends keyof T>(itemValue: T[K], value: T[K]): boolean {\n    return itemValue === value;\n  }\n\n  /**\n   * Checks if the specified property of an item is less than a given value.\n   * @template K - The type of the property to compare.\n   * @param {T[K]} itemValue - The value of the property to compare.\n   * @param {T[K]} value - The value to compare against.\n   * @returns {boolean} - Returns true if the property value is less than the given value, otherwise returns false.\n   */\n  #lessThan<K extends keyof T>(itemValue: T[K], value: T[K]): boolean {\n    return itemValue < value;\n  }\n\n  /**\n   * Checks if the specified property of an item is less than or equal to a given value.\n   * @template K - The type of the property to compare.\n   * @param {T[K]} itemValue - The value of the property to compare.\n   * @param {T[K]} value - The value to compare against.\n   * @returns {boolean} - Returns true if the property value is less than or equal to the given value, otherwise returns false.\n   */\n  #lessThanOrEqualTo<K extends keyof T>(itemValue: T[K], value: T[K]): boolean {\n    return itemValue <= value;\n  }\n\n  /**\n   * Checks if the specified property of an item is greater than a given value.\n   * @template K - The type of the property to compare.\n   * @param {T[K]} itemValue - The value of the property to compare.\n   * @param {T[K]} value - The value to compare against.\n   * @returns {boolean} - Returns true if the property value is greater than the given value, otherwise returns false.\n   */\n  #greaterThan<K extends keyof T>(itemValue: T[K], value: T[K]): boolean {\n    return itemValue > value;\n  }\n\n  /**\n   * Checks if the specified property of an item is greater than or equal to a given value.\n   * @template K - The type of the property to compare.\n   * @param {T[K]} itemValue - The value of the property to compare.\n   * @param {T[K]} value - The value to compare against.\n   * @returns {boolean} - Returns true if the property value is greater than or equal to the given value, otherwise returns false.\n   */\n  #greaterThanOrEqualTo<K extends keyof T>(itemValue: T[K], value: T[K]): boolean {\n    return itemValue >= value;\n  }\n\n  /**\n   * Checks if the specified property of an item is like a given value with optional type-based matching.\n   * @template K - The type of the property to compare.\n   * @param {T[K]} itemValue - The value of the property to compare.\n   * @param {T[K]} value - The value to compare against.\n   * @param {'^like' | 'like$'} [type] - The optional matching type:\n   *   - ^like matches if the property value starts with the given value.\n   *   - like$ matches if the property value ends with the given value.\n   *   - if not provided or set to 'like', it matches if the property value contains the given value.\n   * @returns {boolean} - Returns true if the property value matches the given value based on the specified type, otherwise returns false.\n   */\n  #like<K extends keyof T>(itemValue: T[K], value: T[K], type?: '^like' | 'like$'): boolean {\n    const v1 = itemValue!.toString().toLowerCase();\n    const v2 = value!.toString().toLowerCase();\n\n    if (type === '^like') {\n      return v1.startsWith(v2);\n    }\n\n    if (type === 'like$') {\n      return v1.endsWith(v2);\n    }\n\n    return v1.includes(v2);\n  }\n}"],"mappings":"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","names":[]}