@starbemtech/star-db-query-builder
Version:
A query builder to be used with mysql or postgres
319 lines • 12.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createOffsetClause = exports.createLimitClause = exports.createGroupByClause = exports.createOrderByClause = exports.createWhereClause = exports.generateSetClause = exports.generatePlaceholders = exports.createSelectFields = void 0;
/**
* Converts an array of strings to a comma-separated string with quotes
*
* This function takes an array of strings and converts it to a comma-separated string
* with quotes. It handles the differences between PostgreSQL and MySQL syntax for
* string arrays.
*
* @param items - The array of strings to convert
* @param clientType - The type of database client
* @returns A comma-separated string with quotes
*
* @example
* const items = ['item1', 'item2', 'item3']
* const clientType = 'pg'
* const result = arrayToStringWithQuotes(items, clientType)
* // result will be: 'item1', 'item2', 'item3'
*/
const arrayToStringWithQuotes = (items, clientType) => {
const itemsWithQuotes = items.map((item) => clientType === 'pg' ? `${item}` : `${item}`);
return itemsWithQuotes.join(', ');
};
/**
* Generates a PostgreSQL placeholder for a parameter
*
* This function generates a PostgreSQL placeholder for a parameter. It returns
* a string with a dollar sign and the index of the parameter.
*
* @param index - The index of the parameter
* @returns A PostgreSQL placeholder
*
* @example
* const index = 1
* const placeholder = pgPlaceholderGenerator(index)
* // placeholder will be: $1
*/
const pgPlaceholderGenerator = (index) => `$${index}`;
/**
* Generates a MySQL placeholder for a parameter
*
* This function generates a MySQL placeholder for a parameter. It returns
* a string with a question mark.
*
* @returns A MySQL placeholder
*
* @example
* const placeholder = mysqlPlaceholderGenerator()
* // placeholder will be: ?
*/
const mysqlPlaceholderGenerator = () => `?`;
/**
* Creates a SELECT clause for a query
*
* This function creates a SELECT clause for a query. It takes an array of fields
* and a database client type and returns a string with the fields separated by commas.
*
* @param fields - The array of fields to select
* @param clientType - The type of database client
* @returns A string with the fields separated by commas
*
* @example
* const fields = ['id', 'name', 'email']
* const clientType = 'pg'
* const result = createSelectFields(fields, clientType)
* // result will be: "id, name, email"
*/
const createSelectFields = (fields = [], clientType) => {
return fields && fields.length > 0
? arrayToStringWithQuotes(fields, clientType)
: '*';
};
exports.createSelectFields = createSelectFields;
/**
* Generates placeholders for a query
*
* This function generates placeholders for a query. It takes an array of keys
* and a database client type and returns a string with the placeholders separated by commas.
*
* @param keys - The array of keys to generate placeholders for
* @param clientType - The type of database client
* @returns A string with the placeholders separated by commas
*
* @example
* const keys = ['id', 'name', 'email']
* const clientType = 'pg'
* const result = generatePlaceholders(keys, clientType)
* // result will be: $1, $2, $3
*/
const generatePlaceholders = (keys, clientType) => {
return keys
.map((_, index) => (clientType === 'pg' ? `$${index + 1}` : '?'))
.join(', ');
};
exports.generatePlaceholders = generatePlaceholders;
/**
* Generates a SET clause for a query
*
* This function generates a SET clause for a query. It takes an array of keys
* and a database client type and returns a string with the keys and placeholders separated by commas.
*
* @param keys - The array of keys to generate SET clause for
* @param clientType - The type of database client
* @returns A string with the keys and placeholders separated by commas
*
* @example
* const keys = ['id', 'name', 'email']
* const clientType = 'pg'
* const result = generateSetClause(keys, clientType)
* // result will be: "id = $1, name = $2, email = $3"
*/
const generateSetClause = (keys, clientType) => {
return keys
.map((key, index) => clientType === 'pg' ? `${key} = $${index + 1}` : `${key} = ?`)
.join(', ');
};
exports.generateSetClause = generateSetClause;
/**
* Creates a WHERE clause for a query
*
* This function creates a WHERE clause for a query. It takes an array of conditions
* and a database client type and returns a string with the conditions separated by AND.
*
* @param conditions - The array of conditions to create WHERE clause for
* @param startIndex - The index of the first parameter
* @param clientType - The type of database client
* @param unaccent - Whether to use unaccent function
* @returns A string with the conditions separated by AND
*
* @example
* const conditions = [{ field: 'name', operator: '=', value: 'John Doe' }]
* const startIndex = 1
* const clientType = 'pg'
* const unaccent = true
* const result = createWhereClause(conditions, startIndex, clientType, unaccent)
* // result will be: "name = $1"
*/
const createWhereClause = (conditions = {}, startIndex = 1, clientType, unaccent) => {
let index = startIndex;
const whereParts = [];
const values = [];
const processCondition = (key, condition) => {
if (typeof condition === 'object' && condition !== null) {
if ('operator' in condition && 'value' in condition) {
const { operator, value } = condition;
if (operator === 'NOT EXISTS' && typeof value === 'string') {
whereParts.push(`NOT EXISTS (${value})`);
}
else if (operator.includes('NULL')) {
whereParts.push(`${key} ${operator}`);
}
else if (Array.isArray(value)) {
const placeholders = value
.map(() => clientType === 'pg'
? pgPlaceholderGenerator(index++)
: mysqlPlaceholderGenerator())
.join(', ');
if (operator === 'BETWEEN') {
whereParts.push(`${key} ${operator} ${placeholders.replace(', ', ' AND ')}`);
}
else if (operator === 'IN') {
whereParts.push(`${key} ${operator} (${placeholders})`);
}
else {
whereParts.push(`${key} ${operator} (${placeholders})`);
}
values.push(...value);
}
else {
if (unaccent && clientType === 'pg') {
if (operator.toUpperCase() === 'ILIKE') {
whereParts.push(`unaccent(${key}::text) ILIKE unaccent(${pgPlaceholderGenerator(index)})`);
}
else {
whereParts.push(`unaccent(${key}::text) ${operator} unaccent(${pgPlaceholderGenerator(index)})`);
}
}
else {
whereParts.push(clientType === 'pg'
? `${key} ${operator} ${pgPlaceholderGenerator(index)}`
: `${key} ${operator} ${mysqlPlaceholderGenerator()}`);
}
index++;
values.push(value);
}
}
}
};
if ('JOINS' in conditions) {
const logicalOperator = conditions.JOINS ? 'AND' : 'OR';
const compositeConditions = conditions.JOINS;
if (Array.isArray(compositeConditions)) {
const subWhereParts = compositeConditions
.map((subCondition) => {
if (typeof subCondition === 'object' &&
!Array.isArray(subCondition) &&
subCondition !== null) {
const key = Object.keys(subCondition)[0];
const condition = subCondition[key];
// Adiciona o tratamento de unaccent nas condições de JOINS
processCondition(key, condition);
return whereParts.pop();
}
return '';
})
.filter((part) => part);
whereParts.push(`(${subWhereParts.join(` ${logicalOperator} `)})`);
}
}
else {
Object.entries(conditions).forEach(([key, value]) => processCondition(key, value));
}
if ('OR' in conditions || 'AND' in conditions) {
const logicalOperator = conditions.OR ? 'OR' : 'AND';
const compositeConditions = conditions.OR || conditions.AND;
if (Array.isArray(compositeConditions)) {
const subWhereParts = compositeConditions
.map((subCondition) => {
if (typeof subCondition === 'object' &&
!Array.isArray(subCondition) &&
subCondition !== null) {
const key = Object.keys(subCondition)[0];
const condition = subCondition[key];
processCondition(key, condition); // Certifica que o unaccent é processado aqui também
return whereParts.pop();
}
return '';
})
.filter((part) => part);
whereParts.push(`(${subWhereParts.join(` ${logicalOperator} `)})`);
}
}
const whereClause = whereParts.length > 0 ? ` WHERE ${whereParts.join(' AND ')}` : '';
return [whereClause, values, index];
};
exports.createWhereClause = createWhereClause;
/**
* Creates an ORDER BY clause for a query
*
* This function creates an ORDER BY clause for a query. It takes an array of
* order by fields and returns a string with the fields separated by commas.
*
* @param orderBy - The array of order by fields
* @returns A string with the fields separated by commas
*
* @example
* const orderBy = [{ field: 'created_at', direction: 'DESC' }]
* const result = createOrderByClause(orderBy)
* // result will be: "ORDER BY created_at DESC"
*/
const createOrderByClause = (orderBy) => {
if (!orderBy || orderBy.length === 0)
return '';
const clause = orderBy.map((o) => `${o.field} ${o.direction}`).join(', ');
return ` ORDER BY ${clause}`;
};
exports.createOrderByClause = createOrderByClause;
/**
* Creates a GROUP BY clause for a query
*
* This function creates a GROUP BY clause for a query. It takes an array of
* group by fields and returns a string with the fields separated by commas.
*
* @param groupBy - The array of group by fields
* @returns A string with the fields separated by commas
*
* @example
* const groupBy = ['status']
* const result = createGroupByClause(groupBy)
* // result will be: "GROUP BY status"
*/
const createGroupByClause = (groupBy) => {
if (!groupBy || groupBy.length === 0)
return '';
return ` GROUP BY ${groupBy.join(', ')}`;
};
exports.createGroupByClause = createGroupByClause;
/**
* Creates a LIMIT clause for a query
*
* This function creates a LIMIT clause for a query. It takes a limit number
* and returns a string with the limit.
*
* @param limit - The limit number
* @returns A string with the limit
*
* @example
* const limit = 10
* const result = createLimitClause(limit)
* // result will be: "LIMIT 10"
*/
const createLimitClause = (limit) => {
if (!limit)
return '';
return ` LIMIT ${limit}`;
};
exports.createLimitClause = createLimitClause;
/**
* Creates an OFFSET clause for a query
*
* This function creates an OFFSET clause for a query. It takes an offset number
* and returns a string with the offset.
*
* @param offset - The offset number
* @returns A string with the offset
*
* @example
* const offset = 10
* const result = createOffsetClause(offset)
* // result will be: "OFFSET 10"
*/
const createOffsetClause = (offset) => {
if (!offset)
return '';
return ` OFFSET ${offset}`;
};
exports.createOffsetClause = createOffsetClause;
//# sourceMappingURL=utils.js.map