UNPKG

puddysql

Version:

🍮 Powerful SQL toolkit for Node.js, built with flexibility and structure in mind. Easily manage SQLite3/PostgreSQL, advanced queries, smart tag systems, and full JSON-friendly filters.

1,158 lines 51.4 kB
export default PuddySqlQuery;
/**
 * Defines the schema structure used to create or modify SQL tables programmatically.
 *
 * Each entry in the array represents a single column definition as a 4-item tuple:
 *   [columnName, columnType, columnOptions, columnMeta]
 *
 * - `columnName` (`string`) – The name of the column (e.g., `"id"`, `"username"`).
 * - `columnType` (`string`) – The SQL data type (e.g., `"TEXT"`, `"INTEGER"`, `"BOOLEAN"`).
 * - `columnOptions` (`string`) – SQL options like `NOT NULL`, `PRIMARY KEY`, `DEFAULT`, etc.
 * - `columnMeta` (`any`) – Arbitrary metadata related to the column (e.g., for UI, descriptions, tags).
 */
export type SqlTableConfig = Array<[string, string, string, string]>;
/**
 * Represents the result of a paginated SQL query to locate the exact position of a specific item.
 */
export type FindResult = {
    /**
     * - The current page number where the item is located (starting from 1).
     */
    page: number;
    /**
     * - The total number of pages available in the dataset.
     */
    pages: number;
    /**
     * - The total number of items in the dataset.
     */
    total: number;
    /**
     * - The exact index position of the item in the entire dataset (starting from 0).
     */
    position: number;
    /**
     * - The actual item found, if included in the result.
     */
    item?: FreeObj | undefined;
};
/**
 * - Tag group definition to build the clause from.
 */
export type TagCriteria = {
    /**
     * - SQL column name for tag data (defaults to `this.getColumnName()`).
     */
    column?: string | undefined;
    /**
     * - Optional table name used (defaults to `this.defaultTableName`).
     */
    tableName?: string | undefined;
    /**
     * - Whether wildcards are allowed in matching.
     */
    allowWildcards?: boolean | undefined;
    /**
     * - Tag values or grouped OR conditions to include.
     */
    include?: (string | string[])[] | undefined;
};
/**
 * Represents the result of a paginated query.
 */
export type PaginationResult = {
    /**
     * - Array of items returned for the current page.
     */
    items: any[];
    /**
     * - Total number of available pages based on the query and per-page limit.
     */
    totalPages: number;
    /**
     * - Total number of items matching the query without pagination.
     */
    totalItems: number;
};
/**
 * Represents a flexible select query input, allowing for different forms.
 */
export type SelectQuery = (string | string[] | {
    aliases?: Record<string, string>;
    values?: string[];
    boost?: {
        alias?: string;
        value?: BoostValue[];
    };
} | null);
/**
 * - Parameter cache used to build the WHERE clause.
 */
export type Pcache = {
    /**
     * - Starting parameter index for SQL placeholders (e.g., `$1`, `$2`...).
     */
    index?: number | undefined;
    /**
     * - Collected values for SQL query binding.
     */
    values?: any[] | undefined;
};
/**
 * An object type where keys can be strings, numbers, or symbols, and values can be any unknown type.
 * Useful for generic data containers where the structure is not strictly defined.
 */
export type FreeObj = Record<string | number | symbol, any>;
/**
 * Represents conditions used in a SQL WHERE clause.
 */
export type WhereConditions = {
    /**
     * - Logical operator to combine conditions (`AND`/`OR`). Case-insensitive.
     *    Only used when `conditions` is provided.
     */
    group?: "AND" | "OR" | "or" | "and" | undefined;
    /**
     * - Array of grouped `WhereConditions` or `QueryGroup` entries.
     *    Used for nesting logical clauses.
     */
    conditions?: QueryGroup[] | undefined;
    /**
     * - Optional function name applied to the column (e.g., UPPER, LOWER).
     */
    funcName?: string | null | undefined;
    /**
     * - Comparison operator (e.g., '=', 'LIKE', 'IN').
     */
    operator?: string | null | undefined;
    /**
     * - Value to compare against.
     */
    value?: string | null | undefined;
    /**
     * - Custom function for value transformation (e.g., for SOUNDEX).
     */
    valType?: string | null | undefined;
    /**
     * - Logical position indicator (e.g., 'left', 'right') for chaining.
     */
    lPos?: "left" | "right" | null | undefined;
    /**
     * - Replacement operator, used to override the main one.
     */
    newOp?: string | null | undefined;
    /**
     * - Name of the column to apply the condition on.
     */
    column?: string | null | undefined;
};
/**
 * Represents a flexible condition group used in dynamic SQL WHERE clause generation.
 *
 * A `QueryGroup` can take two forms:
 *
 * 1. **Single condition object** — represents a single `WhereConditions` instance:
 *    ```js
 *    {
 *      column: 'name',
 *      operator: '=',
 *      value: 'pudding'
 *    }
 *    ```
 *
 * 2. **Named group of conditions** — an object mapping condition names or keys
 *    to individual `WhereConditions` objects:
 *    ```js
 *    {
 *      searchByName: {
 *        column: 'name',
 *        operator: 'ILIKE',
 *        value: '%fluttershy%'
 *      },
 *      searchByType: {
 *        column: 'type',
 *        operator: '=',
 *        value: 'pegasus'
 *      }
 *    }
 *    ```
 *
 * This structure allows dynamic grouping of multiple WHERE conditions
 * (useful for advanced filters, tag clauses, or scoped searches).
 */
export type QueryGroup = WhereConditions | Record<string, WhereConditions>;
/**
 * Represents a boosting rule for weighted query ranking.
 */
export type BoostValue = {
    /**
     * - List of columns to apply the boost on.
     */
    columns?: string[] | undefined;
    /**
     * - Operator used in the condition (e.g., '=', 'LIKE').
     */
    operator?: "" | "LIKE" | "ILIKE" | undefined;
    /**
     * - Value to match in the condition.
     */
    value?: string | string[] | undefined;
    /**
     * - When true, performs matching using `json_each()` for JSON/ARRAY columns instead of text comparison.
     */
    array?: boolean | undefined;
    /**
     * - Weight factor to boost results matching the condition.
     */
    weight?: number | undefined;
};
/**
 * Each join object must contain:
 * - `table`: The name of the table to join.
 * - `compare`: The ON clause condition.
 * - `type` (optional): One of the supported JOIN types (e.g., 'left', 'inner'). Defaults to 'left'.
 */
export type JoinObj = {
    table: string;
    compare: string;
    type?: string;
};
export type TableSettings = {
    name?: string | undefined;
    /**
     * - SELECT clause configuration. Can be simplified; complex expressions are auto-formatted.
     */
    select?: SelectQuery | undefined;
    /**
     * - Optional JOIN table name.
     */
    join?: string | null | undefined;
    /**
     * - Condition used to match JOIN tables.
     */
    joinCompare?: string | null | undefined;
    /**
     * - Optional ORDER BY clause.
     */
    order?: string | null | undefined;
    /**
     * - Primary key column name.
     */
    id?: string | undefined;
    /**
     * - Optional secondary key column name.
     */
    subId?: string | null | undefined;
};
/**
 * Configuration settings for a SQL entity, defining how it should be queried and joined.
 */
export type Settings = {
    /**
     * - The default columns to select in a query (e.g., `"*"`, or `"id, name"`).
     */
    select: string;
    /**
     * - The name of the main table or view.
     */
    name: string;
    /**
     * - The primary key column name.
     */
    id: string;
    /**
     * - Optional column used to match in JOIN conditions (e.g., `"main.id = sub.fk_id"`).
     */
    joinCompare: string | null;
    /**
     * - Default column used to order results (e.g., `"created_at DESC"`).
     */
    order: string | null;
    /**
     * - Secondary identifier column name (for composite keys or scoped tables).
     */
    subId: string | null;
    /**
     * - SQL JOIN clause to apply (e.g., `"LEFT JOIN profiles ON users.id = profiles.user_id"`).
     */
    join: string | null;
};
/**
 * A function that takes a WhereConditions object and returns a modified WhereConditions object.
 * Typically used to append or transform SQL WHERE clauses.
 */
export type WhereConditionsFunc = (conditions: WhereConditions) => WhereConditions;
/**
 * A map of condition identifiers to their associated transformation functions.
 * Each key represents a named SQL condition function.
 */
export type SqlConditions = Record<string, WhereConditionsFunc>;
/**
 * Defines the schema structure used to create or modify SQL tables programmatically.
 *
 * Each entry in the array represents a single column definition as a 4-item tuple:
 *   [columnName, columnType, columnOptions, columnMeta]
 *
 * - `columnName` (`string`) – The name of the column (e.g., `"id"`, `"username"`).
 * - `columnType` (`string`) – The SQL data type (e.g., `"TEXT"`, `"INTEGER"`, `"BOOLEAN"`).
 * - `columnOptions` (`string`) – SQL options like `NOT NULL`, `PRIMARY KEY`, `DEFAULT`, etc.
 * - `columnMeta` (`any`) – Arbitrary metadata related to the column (e.g., for UI, descriptions, tags).
 *
 * @typedef {Array<[string, string, string, string]>} SqlTableConfig
 */
/**
 * Represents the result of a paginated SQL query to locate the exact position of a specific item.
 *
 * @typedef {Object} FindResult
 * @property {number} page - The current page number where the item is located (starting from 1).
 * @property {number} pages - The total number of pages available in the dataset.
 * @property {number} total - The total number of items in the dataset.
 * @property {number} position - The exact index position of the item in the entire dataset (starting from 0).
 * @property {FreeObj} [item] - The actual item found, if included in the result.
 */
/**
 * Tag group definition used to build dynamic SQL clauses for tag filtering.
 *
 * @typedef {Object} TagCriteria - Tag group definition to build the clause from.
 * @property {string} [group.column] - SQL column name for tag data (defaults to `this.getColumnName()`).
 * @property {string} [group.tableName] - Optional table name used (defaults to `this.defaultTableName`).
 * @property {boolean} [group.allowWildcards=false] - Whether wildcards are allowed in matching.
 * @property {Array<string|string[]>} [group.include=[]] - Tag values or grouped OR conditions to include.
 */
/**
 * Represents the result of a paginated query.
 *
 * @typedef {Object} PaginationResult
 * @property {any[]} items - Array of items returned for the current page.
 * @property {number} totalPages - Total number of available pages based on the query and per-page limit.
 * @property {number} totalItems - Total number of items matching the query without pagination.
 */
/**
 * Represents a flexible select query input, allowing for different forms.
 *
 * @typedef {(
 *   string |
 *   string[] |
 *   {
 *     aliases?: Record<string, string>; // Mapping of display names to real column names.
 *     values?: string[];                // List of column names to select.
 *     boost?: {                         // Boost configuration for weighted ranking.
 *       alias?: string;                 // The alias to associate with the boost configuration.
 *       value?: BoostValue[];           // List of boost rules to apply.
 *     };
 *   } |
 *   null
 * )} SelectQuery
 */
/**
 * Parameter cache used to build the WHERE clause.
 *
 * @typedef {Object} Pcache - Parameter cache used to build the WHERE clause.
 * @property {number} [pCache.index=1] - Starting parameter index for SQL placeholders (e.g., `$1`, `$2`...).
 * @property {any[]} [pCache.values=[]] - Collected values for SQL query binding.
 */
/**
 * Represents a free-form object with unknown values and arbitrary keys.
 *
 * @typedef {Record<string | number | symbol, any>} FreeObj
 *
 * An object type where keys can be strings, numbers, or symbols, and values can be any unknown type.
 * Useful for generic data containers where the structure is not strictly defined.
 */
/**
 * Represents conditions used in a SQL WHERE clause.
 *
 * @typedef {Object} WhereConditions
 * @property {'OR'|'AND'|'or'|'and'} [group] - Logical operator to combine conditions (`AND`/`OR`). Case-insensitive.
 *                                             Only used when `conditions` is provided.
 * @property {QueryGroup[]} [conditions] - Array of grouped `WhereConditions` or `QueryGroup` entries.
 *                                         Used for nesting logical clauses.
 *
 * @property {string|null|undefined} [funcName] - Optional function name applied to the column (e.g., UPPER, LOWER).
 * @property {string|null|undefined} [operator] - Comparison operator (e.g., '=', 'LIKE', 'IN').
 * @property {string|null|undefined} [value] - Value to compare against.
 * @property {string|null|undefined} [valType] - Custom function for value transformation (e.g., for SOUNDEX).
 * @property {'left'|'right'|null|undefined} [lPos] - Logical position indicator (e.g., 'left', 'right') for chaining.
 * @property {string|null|undefined} [newOp] - Replacement operator, used to override the main one.
 * @property {string|null|undefined} [column] - Name of the column to apply the condition on.
 */
/**
 * Represents a flexible condition group used in dynamic SQL WHERE clause generation.
 *
 * A `QueryGroup` can take two forms:
 *
 * 1. **Single condition object** — represents a single `WhereConditions` instance:
 *    ```js
 *    {
 *      column: 'name',
 *      operator: '=',
 *      value: 'pudding'
 *    }
 *    ```
 *
 * 2. **Named group of conditions** — an object mapping condition names or keys
 *    to individual `WhereConditions` objects:
 *    ```js
 *    {
 *      searchByName: {
 *        column: 'name',
 *        operator: 'ILIKE',
 *        value: '%fluttershy%'
 *      },
 *      searchByType: {
 *        column: 'type',
 *        operator: '=',
 *        value: 'pegasus'
 *      }
 *    }
 *    ```
 *
 * This structure allows dynamic grouping of multiple WHERE conditions
 * (useful for advanced filters, tag clauses, or scoped searches).
 *
 * @typedef {WhereConditions | Record<string, WhereConditions>} QueryGroup
 */
/**
 * Represents a boosting rule for weighted query ranking.
 *
 * @typedef {Object} BoostValue
 * @property {string[]} [columns] - List of columns to apply the boost on.
 * @property {''|'LIKE'|'ILIKE'} [operator=''] - Operator used in the condition (e.g., '=', 'LIKE').
 * @property {string|string[]} [value] - Value to match in the condition.
 * @property {boolean} [array=false] - When true, performs matching using `json_each()` for JSON/ARRAY columns instead of text comparison.
 * @property {number} [weight=1] - Weight factor to boost results matching the condition.
 */
/**
 * Each join object must contain:
 * - `table`: The name of the table to join.
 * - `compare`: The ON clause condition.
 * - `type` (optional): One of the supported JOIN types (e.g., 'left', 'inner'). Defaults to 'left'.
 *
 * @typedef {{ table: string; compare: string; type?: string; }} JoinObj
 */
/**
 * @typedef {Object} TableSettings
 * @property {string} [name]
 * @property {SelectQuery} [select='*'] - SELECT clause configuration. Can be simplified; complex expressions are auto-formatted.
 * @property {string|null} [join=null] - Optional JOIN table name.
 * @property {string|null} [joinCompare='t.key = j.key'] - Condition used to match JOIN tables.
 * @property {string|null} [order=null] - Optional ORDER BY clause.
 * @property {string} [id='key'] - Primary key column name.
 * @property {string|null} [subId=null] - Optional secondary key column name.
 */
/**
 * Configuration settings for a SQL entity, defining how it should be queried and joined.
 *
 * @typedef {Object} Settings
 * @property {string} select - The default columns to select in a query (e.g., `"*"`, or `"id, name"`).
 * @property {string} name - The name of the main table or view.
 * @property {string} id - The primary key column name.
 * @property {string|null} joinCompare - Optional column used to match in JOIN conditions (e.g., `"main.id = sub.fk_id"`).
 * @property {string|null} order - Default column used to order results (e.g., `"created_at DESC"`).
 * @property {string|null} subId - Secondary identifier column name (for composite keys or scoped tables).
 * @property {string|null} join - SQL JOIN clause to apply (e.g., `"LEFT JOIN profiles ON users.id = profiles.user_id"`).
 */
/**
 * A function that takes a WhereConditions object and returns a modified WhereConditions object.
 * Typically used to append or transform SQL WHERE clauses.
 *
 * @typedef {(conditions: WhereConditions) => WhereConditions} WhereConditionsFunc
 */
/**
 * A map of condition identifiers to their associated transformation functions.
 * Each key represents a named SQL condition function.
 *
 * @typedef {Record<string, WhereConditionsFunc>} SqlConditions
 */
/**
 * TinySQLQuery is a queries operating system developed to operate in a specific table.
 */
declare class PuddySqlQuery {
    /**
     * Safely retrieves the internal database instance.
     *
     * This method ensures that the current internal `#db` is a valid instance of `PuddySqlEngine`.
     * If the internal value is invalid or was not properly initialized, an error is thrown.
     *
     * @returns {PuddySqlEngine} The internal database instance.
     * @throws {Error} If the internal database is not a valid `PuddySqlEngine`.
     */
    getDb(): PuddySqlEngine;
    /**
     * Checks whether a specific SQL condition function is registered.
     *
     * @param {string} key - The condition identifier to look up.
     * @returns {boolean} - Returns true if the condition exists, otherwise false.
     */
    hasCondition(key: string): boolean;
    /**
     * Retrieves a registered SQL condition function by its identifier.
     *
     * @param {string} key - The condition identifier to retrieve.
     * @returns {WhereConditionsFunc} - The associated condition function.
     * @throws {Error} If the condition does not exist.
     */
    getCondition(key: string): WhereConditionsFunc;
    /**
     * Returns a shallow copy of all registered SQL condition functions.
     *
     * @returns {SqlConditions} - An object containing all condition functions mapped by key.
     */
    getConditions(): SqlConditions;
    /**
     * Registers a new condition under a unique key to be used in query generation.
     *
     * The `conditionHandler` determines how the condition will behave. It can be:
     * - A **string**, representing a SQL operator (e.g., '=', '!=', 'LIKE');
     * - An **object**, which must include an `operator` key (e.g., { operator: '>=' });
     * - A **function**, which receives a `condition` object and returns a full condition definition.
     *
     * If a `valueHandler` is provided, it must be a function that handles value transformation,
     * and will be stored under the same key in the internal value function map.
     *
     * This method does not allow overwriting an existing key in either condition or value handlers.
     *
     * @param {string} key - Unique identifier for the new condition type.
     * @param {string|WhereConditions|WhereConditionsFunc} conditionHandler - Defines the logic or operator of the condition.
     * @param {(function(string): string)|null} [valueHandler=null] - Optional custom function for value transformation (e.g., for SOUNDEX).
     *
     * @throws {Error} If the key is not a non-empty string.
     * @throws {Error} If the key already exists in either conditions or value handlers.
     * @throws {Error} If conditionHandler is not a string, object with `operator`, or function.
     * @throws {Error} If valueHandler is provided but is not a function.
     */
    addCondition(key: string, conditionHandler: string | WhereConditions | WhereConditionsFunc, valueHandler?: ((arg0: string) => string) | null): void;
    /**
     * Registers a SQL function-based condition with optional operator and value transformation.
     *
     * This helper wraps a SQL column in a function (e.g., `LOWER(column)`) and optionally
     * transforms the parameter using the same function (e.g., `LOWER($1)`), depending on config.
     *
     * It integrates with the dynamic condition system that uses:
     *   - `#conditions[name]` for SQL structure generation
     *   - `#customValFunc[valType]` for optional value transformations
     *
     * @param {string} funcName - SQL function name to wrap around the column (e.g., `LOWER`, `SOUNDEX`).
     * @param {boolean} [editParamByDefault=false] - If true, also applies the SQL function to the parameter by default.
     * @param {string} [operator='='] - Default SQL comparison operator (e.g., `=`, `!=`, `>`, `<`).
     *
     * -----------------------------------------------------
     *
     * Runtime Behavior:
     * - Uses `group.newOp` (if provided) to override the default operator.
     * - Uses `group.funcName` (if string) to override the default function name used in `valType`.
     * - If `funcName !== null` and `editParamByDefault === true`, the function will also apply to the param.
     * - The final SQL looks like: FUNC(column) OP FUNC($n), if both sides use the same function.
     *
     *
     * The `group` object passed at runtime may include:
     * @param {Object} group
     * @param {string} group.column - The column name to apply the function on.
     * @param {string} [group.newOp] - Optional override for the comparison operator.
     * @param {string|null} [group.funcName] - Optional override for the SQL function name
     *                                             (affects both SQL column and valType used in `#customValFunc`).
     *
     * @throws {TypeError} If `funcName` is not a non-empty string.
     * @throws {TypeError} If `editParamByDefault` is provided and is not a boolean.
     * @throws {TypeError} If `operator` is not a non-empty string.
     *
     * --------------------------------------------------------------------------------
     * How it's used in the system:
     *
     * ```js
     * const result = this.#conditions[group.operator](group);
     * const param = typeof this.#customValFunc[result.valType] === 'function'
     *   ? this.#customValFunc[result.valType](`$1`)
     *   : `$1`;
     * const sql = `${result.column} ${result.operator} ${param}`;
     * ```
     *
     * -----------------------------------------------------
     * @example
     * // Registers a ROUND() comparison with "!="
     * addConditionV2('ROUND', false, '!=');
     *
     * -----------------------------------------------------
     * @example
     * // Registers LOWER() with editParamByDefault
     * addConditionV2('LOWER', true);
     *
     * // Parses as: LOWER(username) = LOWER($1)
     * parse({ column: 'username', value: 'fluttershy', operator: 'LOWER' });
     *
     *  -----------------------------------------------------
     * @example
     * // Registers UPPER() = ? without editParamByDefault
     * addConditionV2('UPPER');
     *
     * // Parses as: UPPER(username) = $1
     * parse({ column: 'username', value: 'rarity', operator: 'UPPER' });
     *
     *  -----------------------------------------------------
     * @example
     * // Can be overridden at runtime:
     * addConditionV2('CEIL', true);
     *
     * parse({
     *  column: 'price',
     *  value: 3,
     *  newOp: '>',
     *  operator: 'CEIL',
     *  funcName: null
     * });
     *
     * // Result: CEIL(price) > 3
     */
    addConditionV2: (funcName: string, editParamByDefault?: boolean, operator?: string) => void;
    /**
     * Generates a SELECT clause based on the input, supporting SQL expressions, aliases,
     * and boosts using CASE statements.
     *
     * This method supports the following input formats:
     *
     * - `null` or `undefined`: returns '*'
     * - `string`: returns the parsed column/expression (with optional aliasing if `AS` is present)
     * - `string[]`: returns a comma-separated list of parsed columns
     * - `object`: supports structured input with:
     *   - `aliases`: key-value pairs of column names and aliases
     *   - `values`: array of column names or expressions
     *   - `boost`: object describing a weighted relevance score using CASE statements
     *     - Must include `alias` (string) and `value` (array of boost rules)
     *     - Each boost rule supports:
     *       - `columns` (string|string[]): target columns to apply the condition on (optional)
     *       - `value` (string|array): value(s) to compare, or a raw SQL condition if `columns` is omitted
     *       - `operator` (string): SQL comparison operator (default: 'LIKE', supports 'IN', '=', etc.)
     *       - `weight` (number): numeric weight applied when condition matches (default: 1)
     *     - If `columns` is omitted, the `value` is treated as a raw SQL condition inserted directly into the CASE.
     *
     * Escaping of all values is handled by `pg.escapeLiteral()` for SQL safety (PostgreSQL).
     *
     * @param {SelectQuery} [input = '*'] - Select clause definition.
     * @returns {string} - A valid SQL SELECT clause string.
     *
     * @throws {TypeError} If the input is of an invalid type.
     * @throws {Error} If `boost.alias` is missing or not a string.
     * @throws {Error} If `boost.value` is present but not an array.
     *
     * @example
     * this.selectGenerator();
     * // returns '*'
     *
     * this.selectGenerator('COUNT(*) AS total');
     * // returns 'COUNT(*) AS total'
     *
     * this.selectGenerator(['id', 'username']);
     * // returns 'id, username'
     *
     * this.selectGenerator({
     *   aliases: {
     *     id: 'image_id',
     *     uploader: 'user_name'
     *   },
     *   values: ['created_at', 'score']
     * });
     * // returns 'id AS image_id, uploader AS user_name, created_at, score'
     *
     * this.selectGenerator({
     *   aliases: {
     *     id: 'image_id',
     *     uploader: 'user_name'
     *   },
     *   values: ['created_at'],
     *   boost: {
     *     alias: 'relevance',
     *     value: [
     *       {
     *         columns: ['tags', 'description'],
     *         value: 'fluttershy',
     *         weight: 2
     *       },
     *       {
     *         columns: 'tags',
     *         value: 'pinkie pie',
     *         operator: 'LIKE',
     *         weight: 1.5
     *       },
     *       {
     *         columns: 'tags',
     *         value: 'oc',
     *         weight: -1
     *       },
     *       {
     *         value: "score > 100 AND views < 1000",
     *         weight: 5
     *       }
     *     ]
     *   }
     * });
     * // returns something like:
     * // CASE
     * //   WHEN tags LIKE '%fluttershy%' OR description LIKE '%fluttershy%' THEN 2
     * //   WHEN tags LIKE '%pinkie pie%' THEN 1.5
     * //   WHEN tags LIKE '%oc%' THEN -1
     * //   WHEN score > 100 AND views < 1000 THEN 5
     * //   ELSE 0
     * // END AS relevance, id AS image_id, uploader AS user_name, created_at
     */
    selectGenerator(input?: SelectQuery): string;
    /**
     * Helper function to parse individual columns or SQL expressions.
     * Supports aliasing and complex expressions.
     *
     * @param {string} column - Column name or SQL expression.
     * @param {string} [alias] - Alias for the column (optional).
     * @returns {string} - A valid SQL expression for SELECT clause.
     */
    parseColumn(column: string, alias?: string): string;
    /**
     * Extracts the value of a key from a JSON object using SQLite's json_extract function.
     * @param {string} where - The JSON column to extract from.
     * @param {string} name - The key or path to extract (dot notation).
     * @returns {string} SQL snippet to extract a value from JSON.
     */
    getJsonExtract: (where?: string, name?: string) => string;
    /**
     * Expands each element in a JSON array or each property in a JSON object into separate rows.
     * Intended for use in the FROM clause.
     * @param {string} source - JSON column or expression to expand.
     * @returns {string} SQL snippet calling json_each.
     */
    getJsonEach: (source?: string) => string;
    /**
     * Unrolls a JSON array from a specific key inside a JSON column using json_each.
     * Ideal for iterating over array elements in a FROM clause.
     * @param {string} where - The JSON column containing the array.
     * @param {string} name - The key of the JSON array.
     * @returns {string} SQL snippet to extract and expand a JSON array.
     */
    getArrayExtract: (where?: string, name?: string) => string;
    /**
     * Extracts a key from a JSON object and casts it to a given SQLite type (INTEGER, TEXT, REAL, etc.).
     * @param {string} where - The JSON column to extract from.
     * @param {string} name - The key or path to extract.
     * @param {string} type - The type to cast to (e.g., 'INTEGER', 'TEXT', 'REAL').
     * @returns {string} SQL snippet with cast applied.
     */
    getJsonCast: (where?: string, name?: string, type?: string) => string;
    /**
     * Updates the table by adding, removing, modifying or renaming columns.
     * @param {SqlTableConfig} changes - An array of changes to be made to the table.
     * Each change is defined by an array, where:
     *   - To add a column: ['ADD', 'columnName', 'columnType', 'columnOptions']
     *   - To remove a column: ['REMOVE', 'columnName']
     *   - To modify a column: ['MODIFY', 'columnName', 'newColumnType', 'newOptions']
     *   - To rename a column: ['RENAME', 'oldColumnName', 'newColumnName']
     * @returns {Promise<void>}
     *
     * @throws {TypeError} If `changes` is not an array of arrays.
     * @throws {Error} If any change has missing or invalid parameters.
     */
    updateTable(changes: SqlTableConfig): Promise<void>;
    /**
     * Drops the current table if it exists.
     *
     * This method executes a `DROP TABLE` query using the table name defined in `this.#settings.name`.
     * It's useful for resetting or cleaning up the database schema dynamically.
     * If the query fails due to connection issues (like `SQLITE_CANTOPEN` or `ECONNREFUSED`),
     * it rejects with the error; otherwise, it resolves with `false` to indicate failure.
     * On success, it resolves with `true`.
     *
     * @returns {Promise<boolean>} Resolves with `true` if the table was dropped, or `false` if there was an issue (other than connection errors).
     * @throws {Error} If there is an issue with the database or settings, or if the table can't be dropped.
     */
    dropTable(): Promise<boolean>;
    /**
     * Creates a table in the database based on provided column definitions.
     * Also stores the column structure in this.#table as an object keyed by column name.
     * If a column type is "TAGS", it will be replaced with "JSON" for SQL purposes,
     * and registered in #tagColumns using a PuddySqlTags instance,
     * but the original "TAGS" value will be preserved in this.#table.
     * @param {SqlTableConfig} columns - An array of column definitions.
     * Each column is defined by an array containing the column name, type, and optional configurations.
     * @returns {Promise<void>}
     *
     * @throws {TypeError} If any column definition is malformed.
     * @throws {Error} If table name is not defined in settings.
     */
    createTable(columns: SqlTableConfig): Promise<void>;
    /**
     * Checks whether a column is associated with a tag editor.
     * Tag editors are used for managing tag-based columns in SQL.
     *
     * @param {string} name - The column name to check.
     * @returns {boolean} - Returns true if the column has an associated tag editor.
     */
    hasTagEditor(name: string): boolean;
    /**
     * Retrieves the PuddySqlTags instance associated with a specific column.
     * Used when the column was defined as a "TAGS" column in the SQL table definition.
     *
     * @param {string} name - The column name to retrieve the tag editor for.
     * @returns {PuddySqlTags} - The tag editor instance.
     * @throws {Error} If the column is not associated with a tag editor.
     */
    getTagEditor(name: string): PuddySqlTags;
    /**
     * Returns a shallow copy of all column-to-tag-editor mappings.
     *
     * @returns {Record<string, PuddySqlTags>} - All tag editor instances mapped by column name.
     */
    getTagEditors(): Record<string, PuddySqlTags>;
    /**
     * Parses and validates fields from result rows based on SQL types in this.#table.
     * Converts known SQL types to native JS types.
     *
     * Supported types: BOOLEAN, INTEGER, BIGINT, FLOAT, TEXT, JSON, DATE, TIMESTAMP, etc.
     *
     * @param {any} result - The result row to check.
     * @returns {FreeObj}
     */
    resultChecker(result: any): FreeObj;
    /**
     * Escapes values inside the valueObj using type definitions from this.#table.
     * Only modifies the values that have a matching column in the table.
     * Uses the appropriate parser from #jsonEscapeAlias.
     * @param {FreeObj} valueObj - The object containing values to be escaped.
     * @returns {FreeObj} The same valueObj with its values escaped according to table definitions.
     */
    escapeValues(valueObj?: FreeObj): FreeObj;
    /**
     * Set or update database settings by merging with existing ones.
     * This function ensures safe fallback values and formats the SELECT clause.
     *
     * @param {TableSettings} [settings={}] - Partial configuration to apply. Will be merged with current settings.
     * @param {PuddySqlEngine} [db] - PuddySql Instance.
     */
    setDb(settings?: TableSettings, db?: PuddySqlEngine): void;
    /**
     * Retrieves the number of affected rows from a database operation result.
     *
     * This method abstracts differences between database engines, such as:
     * - SQLite: returns `result.changes`
     * - PostgreSQL: returns `result.rowCount`
     * - Fallback: `result.rowsAffected`, if defined
     *
     * @param {FreeObj|null} result - The result object returned by the database driver.
     * @returns {number} The number of affected rows, or null if it can't be determined.
     */
    getResultCount(result: FreeObj | null): number;
    /**
     * Check if a row with the given ID (and optional subId) exists.
     * @param {string|number} id - Primary key value.
     * @param {string|number} [subId] - Optional sub-ID for composite key.
     * @returns {Promise<boolean>}
     */
    has(id: string | number, subId?: string | number): Promise<boolean>;
    /**
     * Applies type-specific escaping to a single value based on the table's column definition.
     * @param {any} v - The raw value to be escaped.
     * @param {string} name - The column name associated with the value.
     * @returns {any} The escaped value if a valid type and handler exist; otherwise, the original value.
     */
    escapeValuesFix(v: any, name: string): any;
    /**
     * Updates records based on a complex WHERE clause defined by a filter object.
     * Instead of relying solely on an ID (or subId), this method uses parseWhere to
     * generate the conditions, and updates the given fields in valueObj.
     *
     * @param {FreeObj} valueObj - An object representing the columns and new values for the update.
     * @param {QueryGroup} filter - An object containing the conditions for the WHERE clause.
     * @returns {Promise<number>} - Count of rows that were updated.
     */
    advancedUpdate(valueObj?: FreeObj, filter?: QueryGroup): Promise<number>;
    /**
     * Update an existing record with given data.
     * Will not insert if the record doesn't exist.
     * @param {string|number} id - Primary key value.
     * @param {FreeObj} valueObj - Data to update.
     * @returns {Promise<number>} Count of rows were updated.
     */
    update(id: string | number, valueObj?: FreeObj): Promise<number>;
    /**
     * Insert or update one or more records with given data.
     *
     * ⚠️ **Important:** The table must have both `id` and `subId` configured as a composite **PRIMARY KEY**
     * (or as a **UNIQUE constraint**) for the upsert operation to work correctly with conflict resolution.
     *
     * If `valueObj` is an array, `id` must also be an array of the same length.
     * All objects inside the array must have identical keys.
     *
     * @param {string|number|Array<string|number>} id - Primary key value(s) for each record.
     * @param {FreeObj|FreeObj[]} valueObj - A single object or an array of objects containing the data to store.
     * @param {boolean} [onlyIfNew=false] - If true, only insert if the record(s) do not already exist.
     * @returns {Promise<FreeObj|FreeObj[]|null>} - Generated values will be returned, or null if nothing was generated.
     * @throws {Error} If `valueObj` is an array and `id` is not an array of the same length,
     *                 or if objects in `valueObj` array have mismatched keys.
     */
    set(id: string | number | Array<string | number>, valueObj?: FreeObj | FreeObj[], onlyIfNew?: boolean): Promise<FreeObj | FreeObj[] | null>;
    /**
     * Get a record by its ID (and optional subId).
     * @param {string|number} id - Primary key value.
     * @param {string|number} [subId] - Optional sub-ID for composite key.
     * @returns {Promise<FreeObj|null>}
     */
    get(id: string | number, subId?: string | number): Promise<FreeObj | null>;
    /**
     * Delete records based on a complex WHERE clause using a filter object.
     *
     * Uses the internal parseWhere method to build a flexible condition set.
     *
     * @param {QueryGroup} filter - An object containing the WHERE condition(s).
     * @returns {Promise<number>} - Number of rows deleted.
     */
    advancedDelete(filter?: QueryGroup): Promise<number>;
    /**
     * Delete a record by its ID (and optional subId).
     * @param {string|number} id - Primary key value.
     * @param {string|number} [subId] - Optional sub-ID for composite key.
     * @returns {Promise<number>} - Count of rows were updated.
     */
    delete(id: string | number, subId?: string | number): Promise<number>;
    /**
     * Get a limited number of rows from the database.
     * If an ID is provided, returns only the matching record(s) up to the specified count.
     * @param {number} count - Number of rows to retrieve.
     * @param {string|number|null} [filterId=null] - Optional ID to filter by.
     * @param {SelectQuery} [selectValue='*'] - Defines which columns or expressions should be selected in the query.
     * @returns {Promise<FreeObj[]>}
     */
    getAmount(count: number, filterId?: string | number | null, selectValue?: SelectQuery): Promise<FreeObj[]>;
    /**
     * Get all records from the table.
     * If an ID is provided, returns only the matching record(s).
     * @param {string|number|null} [filterId=null] - Optional ID to filter by.
     * @param {SelectQuery} [selectValue='*'] - Defines which columns or expressions should be selected in the query.
     * @returns {Promise<FreeObj[]>}
     */
    getAll(filterId?: string | number | null, selectValue?: SelectQuery): Promise<FreeObj[]>;
    /**
     * Executes a paginated query and returns results, total pages, and total item count.
     *
     * @param {string} query - The base SQL query (should not include LIMIT or OFFSET).
     * @param {any[]} params - The parameters for the SQL query.
     * @param {number} perPage - The number of items per page.
     * @param {number} page - The current page number (starting from 1).
     * @param {string} queryName - The query name to insert into the sql debug.
     * @returns {Promise<PaginationResult>}
     */
    execPagination(query: string, params: any[], perPage: number, page: number, queryName?: string): Promise<PaginationResult>;
    /**
     * Builds a SQL WHERE clause from a nested or flat condition structure.
     *
     * This internal helper method parses logical groupings (AND/OR) and formats the conditions into
     * SQL syntax, while managing parameter placeholders and values.
     *
     * It supports:
     * - Nested condition groups via `group` and `conditions`.
     * - Flat object-based filtering (legacy/fallback support).
     * - Single-condition objects.
     * - Dynamic operators through the internal `#conditions` handler.
     *
     * @param {Pcache} [pCache={ index: 1, values: [] }] - Placeholder cache object.
     * @param {QueryGroup} [group={}] - Grouped or single filter condition.
     * @returns {string} SQL-formatted WHERE clause (without the "WHERE" keyword).
     *
     * @example
     * const pCache = { index: 1, values: [] };
     * const clause = this.parseWhere(pCache, {
     *   group: 'OR',
     *   conditions: [
     *     { column: 'status', value: 'active' },
     *     { column: 'role', value: 'admin', operator: '=' }
     *   ]
     * });
     * // clause: "(status = $1) OR (role = $2)"
     * // pCache.values: ['active', 'admin']
     */
    parseWhere(pCache?: Pcache, group?: QueryGroup): string;
    /**
     * Generates a default LEFT JOIN clause based on internal settings.
     *
     * This method is used as a fallback when no custom join is provided.
     * It expects `this.#settings.join` to be a string containing the table name,
     * and `this.#settings.joinCompare` to be the ON condition.
     *
     * @returns {string} The default LEFT JOIN SQL snippet, or an empty string if no join is configured.
     */
    insertJoin(): string;
    /**
     * Parses and generates JOIN clauses based on the provided configuration.
     *
     * Supports multiple formats:
     * - If `join` is a single object: returns a single JOIN clause.
     * - If `join` is an array of objects: generates multiple JOINs with aliases (`j1`, `j2`, ...).
     * - If `join` is invalid or empty: falls back to `insertJoin()` using internal settings.
     *
     * @param {JoinObj|JoinObj[]|string|null} [join] - The join configuration(s).
     * @returns {string} One or more JOIN SQL snippets.
     */
    parseJoin(join?: JoinObj | JoinObj[] | string | null): string;
    /**
     * Finds the first item matching the filter, along with its position, page, and total info.
     * Uses a single SQL query to calculate everything efficiently.
     *
     * If selectValue is null, it only returns the pagination/position data, not the item itself.
     *
     * @param {Object} [searchData={}] - Main search configuration.
     * @param {QueryGroup} [searchData.q={}] - Nested criteria object.
     * @param {TagCriteria[]|TagCriteria|null} [searchData.tagCriteria] - One or multiple tag criteria groups.
     * @param {string[]} [searchData.tagCriteriaOps] - Optional logical operators between tag groups (e.g., ['AND', 'OR']).
     * @param {boolean} [searchData.isFlatTags=false] - Use the parseWhereFlat mode to tags.
     * @param {number} [searchData.perPage] - Number of items per page.
     * @param {SelectQuery} [searchData.select='*'] - Which columns to select. Set to null to skip item data.
     * @param {string} [searchData.order] - SQL ORDER BY clause. Defaults to configured order.
     * @param {string|JoinObj|JoinObj[]} [searchData.join] - JOIN definitions with table, compare, and optional type.
     * @returns {{ query: string; values: any[] | undefined; perPage: number; selectValue: SelectQuery; }}
     * @throws {Error} If searchData has invalid structure or values.
     */
    findQuery(searchData?: {
        q?: QueryGroup | undefined;
        tagCriteria?: TagCriteria | TagCriteria[] | null | undefined;
        tagCriteriaOps?: string[] | undefined;
        isFlatTags?: boolean | undefined;
        perPage?: number | undefined;
        select?: SelectQuery | undefined;
        order?: string | undefined;
        join?: string | JoinObj | JoinObj[] | undefined;
    }): {
        query: string;
        values: any[] | undefined;
        perPage: number;
        selectValue: SelectQuery;
    };
    /**
     * Finds the first item matching the filter, along with its position, page, and total info.
     * Uses a single SQL query to calculate everything efficiently.
     *
     * If selectValue is null, it only returns the pagination/position data, not the item itself.
     *
     * @param {Object} [searchData={}] - Main search configuration.
     * @param {QueryGroup} [searchData.q={}] - Nested criteria object.
     * @param {TagCriteria[]|TagCriteria|null} [searchData.tagCriteria] - One or multiple tag criteria groups.
     * @param {string[]} [searchData.tagCriteriaOps] - Optional logical operators between tag groups (e.g., ['AND', 'OR']).
     * @param {number} [searchData.perPage] - Number of items per page.
     * @param {SelectQuery} [searchData.select='*'] - Which columns to select. Set to null to skip item data.
     * @param {string} [searchData.order] - SQL ORDER BY clause. Defaults to configured order.
     * @param {string|JoinObj|JoinObj[]} [searchData.join] - JOIN definitions with table, compare, and optional type.
     * @returns {Promise<FindResult | null>}
     * @throws {Error} If searchData has invalid structure or values.
     */
    find(searchData?: {
        q?: QueryGroup | undefined;
        tagCriteria?: TagCriteria | TagCriteria[] | null | undefined;
        tagCriteriaOps?: string[] | undefined;
        perPage?: number | undefined;
        select?: SelectQuery | undefined;
        order?: string | undefined;
        join?: string | JoinObj | JoinObj[] | undefined;
    }): Promise<FindResult | null>;
    /**
     * Perform a filtered search with advanced nested criteria, pagination, and customizable settings.
     *
     * Supports complex logical groupings (AND/OR), flat condition style, custom ordering, and single or multiple joins.
     * Pagination can be enabled using `perPage`, and additional settings like `order`, `join`, and `limit` can be passed inside `searchData`.
     *
     * @param {Object} [searchData={}] - Main search configuration.
     * @param {QueryGroup} [searchData.q={}] - Nested criteria object.
     *        Can be a flat object style or grouped with `{ group: 'AND'|'OR', conditions: [...] }`.
     * @param {TagCriteria[]|TagCriteria|null} [searchData.tagsQ] - One or multiple tag criteria groups.
     * @param {string[]} [searchData.tagsOpsQ] - Optional logical operators between tag groups (e.g., ['AND', 'OR']).
     * @param {SelectQuery} [searchData.select='*'] - Defines which columns or expressions should be selected in the query.
     * @param {number|null} [searchData.perPage=null] - Number of results per page. If set, pagination is applied.
     * @param {boolean} [searchData.isFlatTags=false] - Use the parseWhereFlat mode to tags.
     * @param {number} [searchData.page=1] - Page number to retrieve when `perPage` is used.
     * @param {string} [searchData.order] - Custom `ORDER BY` clause (e.g. `'created_at DESC'`).
     * @param {string|JoinObj|JoinObj[]} [searchData.join] - A string for single join or array of objects for multiple joins.
     *        Each object should contain `{ table: 'name', compare: 'ON clause' }`.
     * @param {number} [searchData.limit] - Max number of results to return (ignored when `perPage` is used).
     * @returns {{ query: string; perPage: number | null; values: any[]; page: number; }}
     * @throws {Error} If searchData has invalid structure or values.
     *
     * @example
     * // Flat search:
     * await table.search({ q: { status: { value: 'active' } } });
     *
     * // Grouped search:
     * await table.search({
     *   q: {
     *     group: 'AND',
     *     conditions: [
     *       { column: 'status', value: 'active' },
     *       {
     *         group: 'OR',
     *         conditions: [
     *           { column: 'role', value: 'admin' },
     *           { column: 'role', value: 'mod' }
     *         ]
     *       }
     *     ]
     *   }
     * });
     *
     * // With pagination and custom joins:
     * await table.search({
     *   q: { status: { value: 'active' } },
     *   select: '*',
     *   perPage: 10,
     *   page: 2,
     *   join: [
     *     { type: 'left', table: 'profiles', compare: 't.profile_id = j1.id' },
     *     { type: 'left', table: 'roles', compare: 'j1.role_id = j2.id' }
     *   ],
     *   order: 'created_at DESC'
     * });
     */
    searchQuery(searchData?: {
        q?: QueryGroup | undefined;
        tagsQ?: TagCriteria | TagCriteria[] | null | undefined;
        tagsOpsQ?: string[] | undefined;
        select?: SelectQuery | undefined;
        perPage?: number | null | undefined;
        isFlatTags?: boolean | undefined;
        page?: number | undefined;
        order?: string | undefined;
        join?: string | JoinObj | JoinObj[] | undefined;
        limit?: number | undefined;
    }): {
        query: string;
        perPage: number | null;
        values: any[];
        page: number;
    };
    /**
     * Perform a filtered search with advanced nested criteria, pagination, and customizable settings.
     *
     * Supports complex logical groupings (AND/OR), flat condition style, custom ordering, and single or multiple joins.
     * Pagination can be enabled using `perPage`, and additional settings like `order`, `join`, and `limit` can be passed inside `searchData`.
     *
     * @param {Object} [searchData={}] - Main search configuration.
     * @param {QueryGroup} [searchData.q={}] - Nested criteria object.
     *        Can be a flat object style or grouped with `{ group: 'AND'|'OR', conditions: [...] }`.
     * @param {TagCriteria[]|TagCriteria|null} [searchData.tagsQ] - One or multiple tag criteria groups.
     * @param {string[]} [searchData.tagsOpsQ] - Optional logical operators between tag groups (e.g., ['AND', 'OR']).
     * @param {SelectQuery} [searchData.select='*'] - Defines which columns or expressions should be selected in the query.
     * @param {number|null} [searchData.perPage=null] - Number of results per page. If set, pagination is applied.
     * @param {number} [searchData.page=1] - Page number to retrieve when `perPage` is used.
     * @param {string} [searchData.order] - Custom `ORDER BY` clause (e.g. `'created_at DESC'`).
     * @param {string|JoinObj|JoinObj[]} [searchData.join] - A string for single join or array of objects for multiple joins.
     *        Each object should contain `{ table: 'name', compare: 'ON clause' }`.
     * @param {number} [searchData.limit] - Max number of results to return (ignored when `perPage` is used).
     * @returns {Promise<FreeObj[]|PaginationResult>} - Result rows matching the query.
     * @throws {Error} If searchData has invalid structure or values.
     */
    search(searchData?: {
        q?: QueryGroup | undefined;
        tagsQ?: TagCriteria | TagCriteria[] | null | undefined;
        tagsOpsQ?: string[] | undefined;
        select?: SelectQuery | undefined;
        perPage?: number | null | undefined;
        page?: number | undefined;
        order?: string | undefined;
        join?: string | JoinObj | JoinObj[] | undefined;
        limit?: number | undefined;
    }): Promise<FreeObj[] | PaginationResult>;
    #private;
}
import PuddySqlEngine from './PuddySqlEngine.mjs';
import PuddySqlTags from './PuddySqlTags.mjs';