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,132 lines (1,131 loc) • 50.6 kB
text/typescript
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" | "and" | "or" | 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?: string | undefined;
/**
* - Value to match in the condition.
*/
value?: string | string[] | 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 {string} [operator='LIKE'] - Operator used in the condition (e.g., '=', 'LIKE').
* @property {string|string[]} [value] - Value to match in the condition.
* @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.
*
* 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 {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;
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 {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;
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?: {