sqlite-prepare
Version:
A type-safe SQL query builder for Cloudflare D1
112 lines (111 loc) • 3.98 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.raw = raw;
exports.build = build;
exports.prepare = prepare;
function raw(stringsOrValue, ...values) {
// Handle tagged template literal case
if (typeof stringsOrValue !== 'string') {
let result = '';
stringsOrValue.forEach((str, i) => {
result += str + (values[i] !== undefined ? values[i] : '');
});
return { __raw: true, value: result };
}
// Handle regular function call case
return { __raw: true, value: stringsOrValue };
}
/**
* Builds a SQL query with parameterized values
*
* @param strings - SQL query string with placeholders or template strings array
* @param values - Values to interpolate into the query
* @returns A SQLQuery object with the query string and parameters
*
* @example
* // Using a template literal
* const userId = 123;
* const query = build`SELECT * FROM users WHERE id = ${userId}`;
*
* @example
* // Using an array for IN clause
* const roleIds = [1, 2, 3];
* const query = build`SELECT * FROM users WHERE role_id IN ${roleIds}`;
*
* @example
* // Using a raw SQL fragment
* const query = build`SELECT * FROM users WHERE ${raw('created_at > NOW()')}`;
*
* @example
* // Using a subquery
* const subquery = build`SELECT id FROM active_users`;
* const query = build`SELECT * FROM users WHERE id IN ${subquery}`;
*/
function build(strings, ...values) {
let query;
let params = [];
// Handle regular string with question marks
if (typeof strings === 'string') {
query = strings;
params = values;
}
else {
// Handle template literals case
query = '';
for (let i = 0; i < strings.length; i++) {
query += strings[i];
if (i < values.length) {
const value = values[i];
// Check for various formats
if (Array.isArray(value)) {
// Handle arrays for IN clauses
if (value.length === 0) {
// Empty IN clause is usually a logical error, but can be handled
query += '(NULL)';
}
else {
query += '(' + value.map(() => '?').join(', ') + ')';
params.push(...value);
}
}
else if (value && typeof value === 'object') {
if ('__raw' in value && value.__raw === true) {
// Raw SQL
query += value.value;
}
else if ('query' in value && 'params' in value) {
// Handle nested SQLQuery objects (subqueries)
query += '(' + value.query + ')';
params.push(...value.params);
}
else if (value instanceof Date) {
// Handle Date objects specially
query += '?';
params.push(value);
}
else if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
// Handle binary data specially
query += '?';
params.push(value);
}
else {
// Regular object - stringify for JSON storage
query += '?';
params.push(JSON.stringify(value));
}
}
else {
// Regular value
query += '?';
params.push(value);
}
}
}
}
return { query, params };
}
;
function prepare(db, stringOrStrings, ...values) {
const q = build(stringOrStrings, ...values);
return db.prepare(q.query).bind(...(q.params));
}