UNPKG

d1-orm

Version:

A simple strictly typed ORM for Cloudflare's D1 product

151 lines 5.96 kB
/** * @enum {string} - The type of the query */ export var QueryType; (function (QueryType) { QueryType["SELECT"] = "SELECT"; QueryType["INSERT"] = "INSERT"; QueryType["INSERT_OR_REPLACE"] = "INSERT or REPLACE"; QueryType["UPDATE"] = "UPDATE"; QueryType["DELETE"] = "DELETE"; QueryType["UPSERT"] = "UPSERT"; })(QueryType || (QueryType = {})); /** * @param type - The type of query to generate, see {@link QueryType} * @param tableName - The table to query * @param options - The options for the query, see {@link GenerateQueryOptions} * @typeParam T - The type of the object to query. This is generally not needed to be specified, but can be useful if you're calling this yourself instead of through a {@link Model}. * @returns The query and bindings to be executed */ export function GenerateQuery(type, tableName, options = {}, primaryKeys = "id") { if (typeof tableName !== "string" || !tableName.length) { throw new Error("Invalid table name"); } let query = ""; const bindings = []; switch (type) { case QueryType.SELECT: { query = `SELECT * FROM \`${tableName}\``; if (options.where) { const whereStmt = []; for (const [key, value] of Object.entries(options.where)) { whereStmt.push(`${key} = ?`); bindings.push(value); } if (whereStmt.length) query += ` WHERE ${whereStmt.join(" AND ")}`; } if (options.orderBy) { query += " ORDER BY " + transformOrderBy(options.orderBy); } if (options.limit) { query += ` LIMIT ${options.limit}`; if (options.offset) { query += ` OFFSET ${options.offset}`; } } break; } case QueryType.DELETE: { query = `DELETE FROM \`${tableName}\``; if (options.where) { const whereStmt = []; for (const [key, value] of Object.entries(options.where)) { whereStmt.push(`${key} = ?`); bindings.push(value); } if (whereStmt.length) query += ` WHERE ${whereStmt.join(" AND ")}`; } break; } case QueryType.INSERT_OR_REPLACE: case QueryType.INSERT: { query = `${type} INTO \`${tableName}\``; if (typeof options.data !== "object" || Object.getOwnPropertyNames(options.data).length === 0) { throw new Error("Must provide data to insert"); } const keys = []; for (const [key, value] of Object.entries(options.data)) { keys.push(key); bindings.push(value); } query += ` (${keys.join(", ")}) VALUES (${"?" .repeat(keys.length) .split("") .join(", ")})`; break; } case QueryType.UPDATE: { query = `UPDATE \`${tableName}\``; if (typeof options.data !== "object" || Object.getOwnPropertyNames(options.data).length === 0) { throw new Error("Must provide data to update"); } const keys = []; for (const [key, value] of Object.entries(options.data)) { keys.push(`${key} = ?`); bindings.push(value); } query += ` SET ${keys.join(", ")}`; if (options.where) { const whereStmt = []; for (const [key, value] of Object.entries(options.where)) { whereStmt.push(`${key} = ?`); bindings.push(value); } if (whereStmt.length) query += ` WHERE ${whereStmt.join(" AND ")}`; } break; } case QueryType.UPSERT: { const insertDataKeys = Object.keys(options.data ?? {}); const updateDataKeys = Object.keys(options.upsertOnlyUpdateData ?? {}); const whereKeys = Object.keys(options.where ?? {}); bindings.push(...Object.values(options.data ?? {}), ...Object.values(options.upsertOnlyUpdateData ?? {}), ...Object.values(options.where ?? {})); if (insertDataKeys.length === 0 || updateDataKeys.length === 0 || whereKeys.length === 0) { throw new Error("Must provide data to insert with, data to update with, and where keys in Upsert"); } query = `INSERT INTO \`${tableName}\` (${insertDataKeys.join(", ")})`; query += ` VALUES (${"?" .repeat(insertDataKeys.length) .split("") .join(", ")})`; const primaryKeyStr = Array.isArray(primaryKeys) ? primaryKeys.join(", ") : primaryKeys; query += ` ON CONFLICT (${primaryKeyStr}) DO UPDATE SET`; query += ` ${updateDataKeys.map((key) => `${key} = ?`).join(", ")}`; query += ` WHERE ${whereKeys.map((key) => `${key} = ?`).join(" AND ")}`; break; } default: throw new Error("Invalid QueryType provided"); } return { query, bindings, }; } /** * @private * @hidden */ export function transformOrderBy(orderBy) { if (Array.isArray(orderBy)) { return orderBy.map(transformOrderBy).join(", "); } if (typeof orderBy === "string" || typeof orderBy === "symbol" || typeof orderBy === "number") { return `"${String(orderBy)}"`; } return (`"${String(orderBy.column)}"` + (orderBy.descending ? " DESC" : "") + (orderBy.nullLast ? " NULLS LAST" : "")); } //# sourceMappingURL=queryBuilder.js.map