UNPKG

workers-qb

Version:

Zero dependencies Query Builder for Cloudflare Workers

1,172 lines (1,161 loc) 37.6 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { ConflictTypes: () => ConflictTypes, D1QB: () => D1QB, DOQB: () => DOQB, FetchTypes: () => FetchTypes, JoinTypes: () => JoinTypes, OrderTypes: () => OrderTypes, PGQB: () => PGQB, Query: () => Query, QueryBuilder: () => QueryBuilder, QueryWithExtra: () => QueryWithExtra, Raw: () => Raw, asyncLoggerWrapper: () => asyncLoggerWrapper, asyncMigrationsBuilder: () => asyncMigrationsBuilder, defaultLogger: () => defaultLogger, syncLoggerWrapper: () => syncLoggerWrapper, syncMigrationsBuilder: () => syncMigrationsBuilder, trimQuery: () => trimQuery }); module.exports = __toCommonJS(index_exports); // src/enums.ts var OrderTypes = /* @__PURE__ */ ((OrderTypes3) => { OrderTypes3["ASC"] = "ASC"; OrderTypes3["DESC"] = "DESC"; return OrderTypes3; })(OrderTypes || {}); var FetchTypes = /* @__PURE__ */ ((FetchTypes2) => { FetchTypes2["ONE"] = "ONE"; FetchTypes2["ALL"] = "ALL"; return FetchTypes2; })(FetchTypes || {}); var ConflictTypes = /* @__PURE__ */ ((ConflictTypes3) => { ConflictTypes3["ROLLBACK"] = "ROLLBACK"; ConflictTypes3["ABORT"] = "ABORT"; ConflictTypes3["FAIL"] = "FAIL"; ConflictTypes3["IGNORE"] = "IGNORE"; ConflictTypes3["REPLACE"] = "REPLACE"; return ConflictTypes3; })(ConflictTypes || {}); var JoinTypes = /* @__PURE__ */ ((JoinTypes2) => { JoinTypes2["INNER"] = "INNER"; JoinTypes2["LEFT"] = "LEFT"; JoinTypes2["CROSS"] = "CROSS"; return JoinTypes2; })(JoinTypes || {}); // src/logger.ts function defaultLogger(query, meta) { console.log(`[workers-qb][${meta.duration}ms] ${JSON.stringify(query)}`); } async function asyncLoggerWrapper(query, loggerFunction, innerFunction) { const start = Date.now(); try { return await innerFunction(); } catch (e) { throw e; } finally { if (loggerFunction) { if (Array.isArray(query)) { for (const q of query) { await loggerFunction(q.toObject(), { duration: Date.now() - start }); } } else { await loggerFunction(query.toObject(), { duration: Date.now() - start }); } } } } function syncLoggerWrapper(query, loggerFunction, innerFunction) { const start = Date.now(); try { return innerFunction(); } catch (e) { throw e; } finally { if (loggerFunction) { if (Array.isArray(query)) { for (const q of query) { loggerFunction(q.toObject(), { duration: Date.now() - start }); } } else { loggerFunction(query.toObject(), { duration: Date.now() - start }); } } } } // src/modularBuilder.ts var SelectBuilder = class _SelectBuilder { _debugger = false; _options = {}; _fetchAll; _fetchOne; constructor(options, fetchAll, fetchOne) { this._options = options; this._fetchAll = fetchAll; this._fetchOne = fetchOne; } setDebugger(state) { this._debugger = state; } tableName(tableName) { return new _SelectBuilder( { ...this._options, tableName }, this._fetchAll, this._fetchOne ); } fields(fields) { return this._parseArray("fields", this._options.fields, fields); } where(conditions, params) { const subQueryPlaceholders = this._options.subQueryPlaceholders ?? {}; let subQueryTokenNextId = this._options.subQueryTokenNextId ?? 0; const existingConditions = this._options.where && typeof this._options.where === "object" && "conditions" in this._options.where ? this._options.where.conditions : []; const existingParams = this._options.where && typeof this._options.where === "object" && "params" in this._options.where && this._options.where.params ? this._options.where.params : []; const currentInputConditions = Array.isArray(conditions) ? conditions : [conditions]; const currentInputParams = params === void 0 ? [] : Array.isArray(params) ? params : [params]; const processedNewConditions = []; const collectedPrimitiveParams = []; let paramIndex = 0; for (const conditionStr of currentInputConditions) { if (!conditionStr.includes("?")) { processedNewConditions.push(conditionStr); continue; } const conditionParts = conditionStr.split("?"); let builtCondition = conditionParts[0] ?? ""; for (let j = 0; j < conditionParts.length - 1; j++) { if (paramIndex >= currentInputParams.length) { throw new Error('Mismatch between "?" placeholders and parameters in where clause.'); } const currentParam = currentInputParams[paramIndex++]; const isSubQuery = typeof currentParam === "object" && currentParam !== null && ("tableName" in currentParam || "getOptions" in currentParam) && !currentParam.hasOwnProperty("_raw") || currentParam instanceof _SelectBuilder; if (isSubQuery) { const token = `__SUBQUERY_TOKEN_${subQueryTokenNextId++}__`; subQueryPlaceholders[token] = currentParam instanceof _SelectBuilder ? currentParam.getOptions() : "getOptions" in currentParam && typeof currentParam.getOptions === "function" ? currentParam.getOptions() : currentParam; builtCondition += token; } else { builtCondition += "?"; if (currentParam !== void 0) { collectedPrimitiveParams.push(currentParam); } } builtCondition += conditionParts[j + 1] ?? ""; } processedNewConditions.push(builtCondition); } if (paramIndex < currentInputParams.length) { throw new Error('Too many parameters provided for the given "?" placeholders in where clause.'); } return new _SelectBuilder( { ...this._options, subQueryPlaceholders, subQueryTokenNextId, where: { conditions: existingConditions.concat(processedNewConditions), params: existingParams.concat(collectedPrimitiveParams) } }, this._fetchAll, this._fetchOne ); } whereIn(fields, values) { let whereInCondition; let whereInParams; const seperateWithComma = (prev, next) => prev + ", " + next; if (values.length === 0) { return new _SelectBuilder( { ...this._options }, this._fetchAll, this._fetchOne ); } if (!Array.isArray(fields)) { whereInCondition = `(${fields}) IN (VALUES `; whereInCondition += values.map(() => "(?)").reduce(seperateWithComma); whereInCondition += ")"; whereInParams = values; } else { const fieldLength = fields.length; whereInCondition = `(${fields.map((val) => val).reduce(seperateWithComma)}) IN (VALUES `; const valuesString = `(${[...new Array(fieldLength).keys()].map(() => "?").reduce(seperateWithComma)})`; whereInCondition += [...new Array(values.length).keys()].map(() => valuesString).reduce(seperateWithComma); whereInCondition += ")"; whereInParams = values.flat(); } return this.where(whereInCondition, whereInParams); } join(join) { const joins = Array.isArray(join) ? join : [join]; const processedJoins = joins.map((j) => { if (j && typeof j.table === "object") { if (j.table instanceof _SelectBuilder) { return { ...j, table: j.table.getOptions() }; } } return j; }); return this._parseArray("join", this._options.join, processedJoins); } groupBy(groupBy) { return this._parseArray("groupBy", this._options.groupBy, groupBy); } having(conditions, params) { const subQueryPlaceholders = this._options.subQueryPlaceholders ?? {}; let subQueryTokenNextId = this._options.subQueryTokenNextId ?? 0; const existingConditions = this._options.having && typeof this._options.having === "object" && "conditions" in this._options.having ? this._options.having.conditions : []; const existingParams = this._options.having && typeof this._options.having === "object" && "params" in this._options.having && this._options.having.params ? this._options.having.params : []; const currentInputConditions = Array.isArray(conditions) ? conditions : [conditions]; const currentInputParams = params === void 0 ? [] : Array.isArray(params) ? params : [params]; const processedNewConditions = []; const collectedPrimitiveParams = []; let paramIndex = 0; for (const conditionStr of currentInputConditions) { if (!conditionStr.includes("?")) { processedNewConditions.push(conditionStr); continue; } const conditionParts = conditionStr.split("?"); let builtCondition = conditionParts[0] ?? ""; for (let j = 0; j < conditionParts.length - 1; j++) { if (paramIndex >= currentInputParams.length) { throw new Error('Mismatch between "?" placeholders and parameters in having clause.'); } const currentParam = currentInputParams[paramIndex++]; const isSubQuery = typeof currentParam === "object" && currentParam !== null && ("tableName" in currentParam || "getOptions" in currentParam) && !currentParam.hasOwnProperty("_raw") || currentParam instanceof _SelectBuilder; if (isSubQuery) { const token = `__SUBQUERY_TOKEN_${subQueryTokenNextId++}__`; subQueryPlaceholders[token] = currentParam instanceof _SelectBuilder ? currentParam.getOptions() : "getOptions" in currentParam && typeof currentParam.getOptions === "function" ? currentParam.getOptions() : currentParam; builtCondition += token; } else { builtCondition += "?"; if (currentParam !== void 0) { collectedPrimitiveParams.push(currentParam); } } builtCondition += conditionParts[j + 1] ?? ""; } processedNewConditions.push(builtCondition); } if (paramIndex < currentInputParams.length) { throw new Error('Too many parameters provided for the given "?" placeholders in having clause.'); } return new _SelectBuilder( { ...this._options, subQueryPlaceholders, subQueryTokenNextId, having: { conditions: existingConditions.concat(processedNewConditions), params: existingParams.concat(collectedPrimitiveParams) } }, this._fetchAll, this._fetchOne ); } orderBy(orderBy) { return this._parseArray("orderBy", this._options.orderBy, orderBy); } offset(offset) { return new _SelectBuilder( { ...this._options, offset }, this._fetchAll, this._fetchOne ); } limit(limit) { return new _SelectBuilder( { ...this._options, limit }, this._fetchAll, this._fetchOne ); } _parseArray(fieldName, option, value) { let val = []; if (!Array.isArray(value)) { val.push(value); } else { val = value; } if (option && Array.isArray(option)) { val = [...option, ...val]; } return new _SelectBuilder( { ...this._options, [fieldName]: val }, this._fetchAll, this._fetchOne ); } getQueryAll(options) { return this._fetchAll({ ...this._options, ...options }); } getQueryOne() { return this._fetchOne(this._options); } execute(options) { return this._fetchAll({ ...this._options, ...options }).execute(); } all(options) { return this._fetchAll({ ...this._options, ...options }).execute(); } one() { return this._fetchOne(this._options).execute(); } count() { return this._fetchOne(this._options).count(); } getOptions() { return this._options; } }; // src/tools.ts var Raw = class { isRaw = true; content; constructor(content) { this.content = content; } }; var Query = class { executeMethod; query; arguments; fetchType; constructor(executeMethod, query, args, fetchType) { this.executeMethod = executeMethod; this.query = trimQuery(query); this.arguments = args; this.fetchType = fetchType; } execute() { return this.executeMethod(this); } toObject() { return { query: this.query, args: this.arguments, fetchType: this.fetchType }; } }; var QueryWithExtra = class extends Query { countQuery; constructor(executeMethod, query, countQuery, args, fetchType) { super(executeMethod, query, args, fetchType); this.countQuery = countQuery; } count() { return this.executeMethod( new Query(this.executeMethod, this.countQuery, this.arguments, "ONE" /* ONE */) ); } }; function trimQuery(query) { return query.replace(/\s\s+/g, " "); } // src/builder.ts var QueryBuilder = class { options; loggerWrapper = asyncLoggerWrapper; constructor(options) { this.options = options || {}; } setDebugger(state) { if (state === true) { if (this.options.logger) { return; } this.options.logger = defaultLogger; } else { this.options.logger = void 0; } } execute(query) { throw new Error("Execute method not implemented"); } batchExecute(queryArray) { throw new Error("Batch execute method not implemented"); } lazyExecute(query) { throw new Error("Execute lazyExecute not implemented"); } createTable(params) { return new Query( (q) => { return this.execute(q); }, `CREATE TABLE ${params.ifNotExists ? "IF NOT EXISTS" : ""} ${params.tableName} ( ${params.schema})` ); } dropTable(params) { return new Query( (q) => { return this.execute(q); }, `DROP TABLE ${params.ifExists ? "IF EXISTS" : ""} ${params.tableName}` ); } select(tableName) { return new SelectBuilder( { tableName }, (params) => { return this.fetchAll(params); }, (params) => { return this.fetchOne(params); } ); } fetchOne(params) { const queryArgs = []; const countQueryArgs = []; const selectParamsForCount = { ...params, fields: "count(*) as total", offset: void 0, groupBy: void 0, limit: 1 }; if (params.subQueryPlaceholders) { selectParamsForCount.subQueryPlaceholders = params.subQueryPlaceholders; } const mainSql = this._select({ ...params, limit: 1 }, queryArgs); const countSql = this._select(selectParamsForCount, countQueryArgs); return new QueryWithExtra( (q) => { return this.execute(q); }, mainSql, countSql, queryArgs, // Use the populated queryArgs from the main _select call "ONE" /* ONE */ ); } fetchAll(params) { const queryArgs = []; const countQueryArgs = []; const mainQueryParams = { ...params, lazy: void 0 }; const countQueryParams = { ...params, fields: "count(*) as total", offset: void 0, groupBy: void 0, limit: 1, lazy: void 0 }; if (params.subQueryPlaceholders) { countQueryParams.subQueryPlaceholders = params.subQueryPlaceholders; } const mainSql = this._select(mainQueryParams, queryArgs); const countSql = this._select(countQueryParams, countQueryArgs); return new QueryWithExtra( (q) => { return params.lazy ? this.lazyExecute(q) : this.execute(q); }, mainSql, countSql, queryArgs, // Use the populated queryArgs from the main _select call "ALL" /* ALL */ ); } raw(params) { return new Query( (q) => { return this.execute(q); }, params.query, params.args, params.fetchType ); } insert(params) { let args = []; if (typeof params.onConflict === "object") { if (typeof params.onConflict?.where === "object" && !Array.isArray(params.onConflict?.where) && params.onConflict?.where?.params) { args = args.concat(params.onConflict.where?.params); } if (params.onConflict.data) { args = args.concat(this._parse_arguments(params.onConflict.data)); } } if (Array.isArray(params.data)) { for (const row of params.data) { args = args.concat(this._parse_arguments(row)); } } else { args = args.concat(this._parse_arguments(params.data)); } const fetchType = Array.isArray(params.data) ? "ALL" /* ALL */ : "ONE" /* ONE */; return new Query( (q) => { return this.execute(q); }, this._insert(params), args, fetchType ); } update(params) { let args = this._parse_arguments(params.data); if (typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params) { if (Array.isArray(params.where?.params)) { args = params.where?.params.concat(args); } else { args = [params.where?.params].concat(args); } } return new Query( (q) => { return this.execute(q); }, this._update(params), args, "ALL" /* ALL */ ); } delete(params) { return new Query( (q) => { return this.execute(q); }, this._delete(params), typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params ? Array.isArray(params.where?.params) ? params.where?.params : [params.where?.params] : void 0, "ALL" /* ALL */ ); } _parse_arguments(row) { return Object.values(row).filter((value) => { return !(value instanceof Raw); }); } _onConflict(resolution) { if (resolution) { if (typeof resolution === "object") { if (!Array.isArray(resolution.column)) { resolution.column = [resolution.column]; } const _update_query = this.update({ tableName: "_REPLACE_", data: resolution.data, where: resolution.where }).query.replace(" _REPLACE_", ""); return ` ON CONFLICT (${resolution.column.join(", ")}) DO ${_update_query}`; } return `OR ${resolution} `; } return ""; } _insert(params) { const rows = []; let data; if (!Array.isArray(params.data)) { data = [params.data]; } else { data = params.data; } if (!data || !data[0] || data.length === 0) { throw new Error("Insert data is undefined"); } const columns = Object.keys(data[0]).join(", "); let index = 1; let orConflict = ""; let onConflict = ""; if (params.onConflict && typeof params.onConflict === "object") { onConflict = this._onConflict(params.onConflict); if (typeof params.onConflict?.where === "object" && !Array.isArray(params.onConflict?.where) && params.onConflict?.where?.params) { if (Array.isArray(params.onConflict.where?.params)) { index += (params.onConflict.where?.params).length; } else { index += 1; } } if (params.onConflict.data) { index += this._parse_arguments(params.onConflict.data).length; } } else { orConflict = this._onConflict(params.onConflict); } for (const row of data) { const values = []; Object.values(row).forEach((value) => { if (value instanceof Raw) { values.push(value.content); } else { values.push(`?${index}`); index += 1; } }); rows.push(`(${values.join(", ")})`); } return `INSERT ${orConflict} INTO ${params.tableName} (${columns}) VALUES ${rows.join(", ")}` + onConflict + this._returning(params.returning); } _update(params) { const whereParamsLength = typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params ? Array.isArray(params.where?.params) ? Object.keys(params.where?.params).length : 1 : 0; let whereString = this._where(params.where); let parameterIndex = 1; if (whereString && whereString.match(/(?<!\d)\?(?!\d)/)) { whereString = whereString.replace(/\?/g, () => `?${parameterIndex++}`); } const set = []; let index = 1; for (const [key, value] of Object.entries(params.data)) { if (value instanceof Raw) { set.push(`${key} = ${value.content}`); } else { set.push(`${key} = ?${whereParamsLength + index}`); index += 1; } } return `UPDATE ${this._onConflict(params.onConflict)}${params.tableName} SET ${set.join(", ")}` + whereString + this._returning(params.returning); } _delete(params) { return `DELETE FROM ${params.tableName}` + this._where(params.where) + this._returning(params.returning) + this._orderBy(params.orderBy) + this._limit(params.limit) + this._offset(params.offset); } _select(params, queryArgs) { let newQueryArgs = queryArgs; const isTopLevelCall = queryArgs === void 0; if (isTopLevelCall) { newQueryArgs = []; } const currentQueryArgs = newQueryArgs; const context = { subQueryPlaceholders: params.subQueryPlaceholders, queryArgs: currentQueryArgs, toSQLCompiler: this._select.bind(this) }; return `SELECT ${this._fields(params.fields)} FROM ${params.tableName}` + this._join(params.join, context) + this._where(params.where, context) + this._groupBy(params.groupBy) + this._having(params.having, context) + this._orderBy(params.orderBy) + this._limit(params.limit) + this._offset(params.offset); } _fields(value) { if (!value) return "*"; if (typeof value === "string") return value; return value.join(", "); } _where(value, context) { if (!value) return ""; const currentContext = context ?? { queryArgs: [] }; let conditionStrings; let primitiveParams = []; if (typeof value === "object" && !Array.isArray(value)) { conditionStrings = Array.isArray(value.conditions) ? value.conditions : [value.conditions]; if (value.params) { primitiveParams = Array.isArray(value.params) ? value.params : [value.params]; } } else if (Array.isArray(value)) { conditionStrings = value; } else { conditionStrings = [value]; } if (conditionStrings.length === 0) return ""; let primitiveParamIndex = 0; const processedConditions = []; for (const conditionStr of conditionStrings) { const parts = conditionStr.split(/(__SUBQUERY_TOKEN_\d+__|\?)/g).filter(Boolean); let builtCondition = ""; for (const part of parts) { if (part === "?") { if (primitiveParamIndex >= primitiveParams.length) { throw new Error( 'SQL generation error: Not enough primitive parameters for "?" placeholders in WHERE clause.' ); } currentContext.queryArgs.push(primitiveParams[primitiveParamIndex++]); builtCondition += "?"; } else if (part.startsWith("__SUBQUERY_TOKEN_") && part.endsWith("__")) { if (!currentContext.subQueryPlaceholders || !currentContext.toSQLCompiler) { throw new Error("SQL generation error: Subquery context not provided for token processing."); } const subQueryParams = currentContext.subQueryPlaceholders[part]; if (!subQueryParams) { throw new Error(`SQL generation error: Subquery token ${part} not found in placeholders.`); } const subQuerySql = currentContext.toSQLCompiler(subQueryParams, currentContext.queryArgs); builtCondition += `(${subQuerySql})`; } else { builtCondition += part; } } processedConditions.push(builtCondition); } if (primitiveParamIndex < primitiveParams.length && primitiveParams.length > 0) { throw new Error( 'SQL generation error: Too many primitive parameters provided for "?" placeholders in WHERE clause.' ); } if (processedConditions.length === 0) return ""; if (processedConditions.length === 1) { return ` WHERE ${processedConditions[0]}`; } return ` WHERE (${processedConditions.join(") AND (")})`; } _join(value, context) { if (!value) return ""; let joinArray; if (!Array.isArray(value)) { joinArray = [value]; } else { joinArray = value; } const joinQuery = []; joinArray.forEach((item) => { const type = item.type ? `${item.type} ` : ""; let tableSql; if (typeof item.table === "string") { tableSql = item.table; } else if (item.table instanceof SelectBuilder) { tableSql = `(${context.toSQLCompiler(item.table.getOptions(), context.queryArgs)})`; } else { tableSql = `(${context.toSQLCompiler(item.table, context.queryArgs)})`; } joinQuery.push(`${type}JOIN ${tableSql}${item.alias ? ` AS ${item.alias}` : ""} ON ${item.on}`); }); return " " + joinQuery.join(" "); } _groupBy(value) { if (!value) return ""; if (typeof value === "string") return ` GROUP BY ${value}`; return ` GROUP BY ${value.join(", ")}`; } _having(value, context) { if (!value) return ""; const currentContext = context ?? { queryArgs: [] }; let conditionStrings; let primitiveParams = []; if (typeof value === "object" && !Array.isArray(value)) { conditionStrings = Array.isArray(value.conditions) ? value.conditions : [value.conditions]; if (value.params) { primitiveParams = Array.isArray(value.params) ? value.params : [value.params]; } } else if (Array.isArray(value)) { conditionStrings = value; } else { conditionStrings = [value]; } if (conditionStrings.length === 0) return ""; let primitiveParamIndex = 0; const processedConditions = []; for (const conditionStr of conditionStrings) { const parts = conditionStr.split(/(__SUBQUERY_TOKEN_\d+__|\?)/g).filter(Boolean); let builtCondition = ""; for (const part of parts) { if (part === "?") { if (primitiveParamIndex >= primitiveParams.length) { throw new Error( 'SQL generation error: Not enough primitive parameters for "?" placeholders in HAVING clause.' ); } currentContext.queryArgs.push(primitiveParams[primitiveParamIndex++]); builtCondition += "?"; } else if (part.startsWith("__SUBQUERY_TOKEN_") && part.endsWith("__")) { if (!currentContext.subQueryPlaceholders || !currentContext.toSQLCompiler) { throw new Error("SQL generation error: Subquery context not provided for token processing."); } const subQueryParams = currentContext.subQueryPlaceholders[part]; if (!subQueryParams) { throw new Error(`SQL generation error: Subquery token ${part} not found in placeholders.`); } const subQuerySql = currentContext.toSQLCompiler(subQueryParams, currentContext.queryArgs); builtCondition += `(${subQuerySql})`; } else { builtCondition += part; } } processedConditions.push(builtCondition); } if (primitiveParamIndex < primitiveParams.length && primitiveParams.length > 0) { throw new Error( 'SQL generation error: Too many primitive parameters provided for "?" placeholders in HAVING clause.' ); } if (processedConditions.length === 0) return ""; if (processedConditions.length === 1) { return ` HAVING ${processedConditions[0]}`; } return ` HAVING (${processedConditions.join(") AND (")})`; } _orderBy(value) { if (!value) return ""; if (typeof value === "string") return ` ORDER BY ${value}`; const order = []; if (Array.isArray(value)) { for (const val of value) { order.push(val); } } else { order.push(value); } const result = order.map((obj) => { if (typeof obj === "object") { const objs = []; Object.entries(obj).forEach(([key, item]) => { objs.push(`${key} ${item}`); }); return objs.join(", "); } return obj; }); return ` ORDER BY ${result.join(", ")}`; } _limit(value) { if (!value) return ""; return ` LIMIT ${value}`; } _offset(value) { if (!value) return ""; return ` OFFSET ${value}`; } _returning(value) { if (!value) return ""; if (typeof value === "string") return ` RETURNING ${value}`; return ` RETURNING ${value.join(", ")}`; } }; // src/migrations.ts var syncMigrationsBuilder = class { _builder; _migrations; _tableName; constructor(options, builder) { this._tableName = options.tableName || "migrations"; this._migrations = options.migrations; this._builder = builder; } initialize() { this._builder.createTable({ tableName: this._tableName, schema: `id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL`, ifNotExists: true }).execute(); return; } getApplied() { this.initialize(); const result = this._builder.fetchAll({ tableName: this._tableName, orderBy: "id" }).execute(); return result.results || []; } getUnapplied() { const appliedMigrations = this.getApplied().map((migration) => { return migration.name; }); const unappliedMigrations = []; for (const migration of this._migrations) { if (!appliedMigrations.includes(migration.name)) { unappliedMigrations.push(migration); } } return unappliedMigrations; } apply() { const appliedMigrations = []; for (const migration of this.getUnapplied()) { this._builder.raw({ query: ` ${migration.sql} INSERT INTO ${this._tableName} (name) values ('${migration.name}');` }).execute(); appliedMigrations.push(migration); } return appliedMigrations; } }; var asyncMigrationsBuilder = class { _builder; _migrations; _tableName; constructor(options, builder) { this._tableName = options.tableName || "migrations"; this._migrations = options.migrations; this._builder = builder; } async initialize() { await this._builder.createTable({ tableName: this._tableName, schema: `id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL`, ifNotExists: true }).execute(); return; } async getApplied() { await this.initialize(); const result = await this._builder.fetchAll({ tableName: this._tableName, orderBy: "id" }).execute(); return result.results || []; } async getUnapplied() { const appliedMigrations = (await this.getApplied()).map((migration) => { return migration.name; }); const unappliedMigrations = []; for (const migration of this._migrations) { if (!appliedMigrations.includes(migration.name)) { unappliedMigrations.push(migration); } } return unappliedMigrations; } async apply() { const appliedMigrations = []; for (const migration of await this.getUnapplied()) { await this._builder.raw({ query: ` ${migration.sql} INSERT INTO ${this._tableName} (name) values ('${migration.name}');` }).execute(); appliedMigrations.push(migration); } return appliedMigrations; } }; // src/databases/d1.ts var D1QB = class extends QueryBuilder { db; constructor(db, options) { super(options); this.db = db; } migrations(options) { return new asyncMigrationsBuilder(options, this); } async execute(query) { return await this.loggerWrapper(query, this.options.logger, async () => { let stmt = this.db.prepare(query.query); if (query.arguments) { stmt = stmt.bind(...query.arguments); } if (query.fetchType === "ONE" /* ONE */ || query.fetchType === "ALL" /* ALL */) { const resp = await stmt.all(); const meta = resp.meta; return { changes: meta?.changes, duration: meta?.duration, last_row_id: meta?.last_row_id, served_by: meta?.served_by, rowsRead: meta?.rows_read, rowsWritten: meta?.rows_written, meta: resp.meta, success: resp.success, results: query.fetchType === "ONE" /* ONE */ ? resp.results[0] : resp.results }; } return stmt.run(); }); } async batchExecute(queryArray) { return await this.loggerWrapper(queryArray, this.options.logger, async () => { const statements = queryArray.map((query) => { let stmt = this.db.prepare(query.query); if (query.arguments) { stmt = stmt.bind(...query.arguments); } return stmt; }); const responses = await this.db.batch(statements); return responses.map( (resp, i) => { if (queryArray && queryArray[i] !== void 0 && queryArray[i]?.fetchType) { return { changes: resp.meta?.changes, duration: resp.meta?.duration, last_row_id: resp.meta?.last_row_id, served_by: resp.meta?.served_by, rowsRead: resp.meta?.rows_read, rowsWritten: resp.meta?.rows_written, meta: resp.meta, success: resp.success, results: queryArray[i]?.fetchType === "ONE" /* ONE */ ? resp.results?.[0] : resp.results }; } return { changes: resp.meta?.changes, duration: resp.meta?.duration, last_row_id: resp.meta?.last_row_id, served_by: resp.meta?.served_by, rowsRead: resp.meta?.rows_read, rowsWritten: resp.meta?.rows_written, meta: resp.meta, success: resp.success }; } ); }); } }; // src/databases/do.ts var DOQB = class extends QueryBuilder { db; loggerWrapper = syncLoggerWrapper; constructor(db, options) { super(options); this.db = db; } migrations(options) { return new syncMigrationsBuilder(options, this); } execute(query) { return this.loggerWrapper(query, this.options.logger, () => { let cursor; if (query.arguments) { cursor = this.db.exec(query.query, ...query.arguments); } else { cursor = this.db.exec(query.query); } const result = cursor.toArray(); const rowsRead = cursor.rowsRead; const rowsWritten = cursor.rowsWritten; if (query.fetchType == "ONE" /* ONE */) { return { results: result.length > 0 ? result[0] : void 0, rowsRead, rowsWritten }; } return { results: result, rowsRead, rowsWritten }; }); } lazyExecute(query) { return this.loggerWrapper(query, this.options.logger, () => { let cursor; if (query.arguments) { cursor = this.db.exec(query.query, ...query.arguments); } else { cursor = this.db.exec(query.query); } return cursor; }); } }; // src/databases/pg.ts var PGQB = class extends QueryBuilder { db; _migrationsBuilder = asyncMigrationsBuilder; constructor(db, options) { super(options); this.db = db; } migrations(options) { return new asyncMigrationsBuilder(options, this); } async connect() { await this.db.connect(); } async close() { await this.db.end(); } async execute(query) { return await this.loggerWrapper(query, this.options.logger, async () => { const queryString = query.query.replaceAll("?", "$"); let result; if (query.arguments) { result = await this.db.query({ values: query.arguments, text: queryString }); } else { result = await this.db.query({ text: queryString }); } if (query.fetchType === "ONE" /* ONE */ || query.fetchType === "ALL" /* ALL */) { return { command: result.command, lastRowId: result.oid, rowCount: result.rowCount, results: query.fetchType === "ONE" /* ONE */ ? result.rows[0] : result.rows }; } return { command: result.command, lastRowId: result.oid, rowCount: result.rowCount }; }); } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { ConflictTypes, D1QB, DOQB, FetchTypes, JoinTypes, OrderTypes, PGQB, Query, QueryBuilder, QueryWithExtra, Raw, asyncLoggerWrapper, asyncMigrationsBuilder, defaultLogger, syncLoggerWrapper, syncMigrationsBuilder, trimQuery });