"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); var sql_exports = {}; __export(sql_exports, { DB_NOT_FOUND: () => DB_NOT_FOUND, DatabaseTable: () => DatabaseTable, SQL: () => SQL, SQLDatabaseManager: () => SQLDatabaseManager, Statement: () => Statement, tables: () => tables }); module.exports = __toCommonJS(sql_exports); var import_process_manager = require("./process-manager"); var import_fs = require("./fs"); const DB_NOT_FOUND = null; function getModule() { try { return require("better-sqlite3"); } catch { return null; } } class Statement { constructor(statement, db) { this.db = db; this.statement = statement; } run(data) { return this.db.run(this.statement, data); } all(data) { return this.db.all(this.statement, data); } get(data) { return this.db.get(this.statement, data); } toString() { return this.statement; } toJSON() { return this.statement; } } class SQLDatabaseManager extends import_process_manager.QueryProcessManager { constructor(module2, options) { super(module2, (query) => { if (!this.dbReady) { this.setupDatabase(); } try { switch (query.type) { case "load-extension": { if (!this.database) return null; this.loadExtensionFile(query.data); return true; } case "transaction": { const transaction = this.state.transactions.get(query.name); if (!transaction || !this.database) { return null; } const env = { db: this.database, statements: this.state.statements }; return transaction(query.data, env) || null; } case "exec": { if (!this.database) return { changes: 0 }; this.database.exec(query.data); return true; } case "get": { if (!this.database) { return null; } return this.extractStatement(query).get(query.data); } case "run": { if (!this.database) { return null; } return this.extractStatement(query).run(query.data); } case "all": { if (!this.database) { return null; } return this.extractStatement(query).all(query.data); } case "prepare": if (!this.database) { return null; } this.state.statements.set(query.data, this.database.prepare(query.data)); return query.data; } } catch (error) { return this.onError(error, query); } }); this.database = null; this.dbReady = false; this.options = options; this.state = { transactions: /* @__PURE__ */ new Map(), statements: /* @__PURE__ */ new Map() }; if (!this.isParentProcess) this.setupDatabase(); } onError(err, query) { if (this.options.onError) { const result = this.options.onError(err, query, false); if (result) return result; } return { queryError: { stack: err.stack, message: err.message, query } }; } cacheStatement(source) { source = source.trim(); let statement = this.state.statements.get(source); if (!statement) { statement = this.database.prepare(source); this.state.statements.set(source, statement); } return statement; } registerFunction(key, cb) { this.database.function(key, cb); } extractStatement(query) { query.statement = query.statement.trim(); const statement = query.noPrepare ? this.state.statements.get(query.statement) : this.cacheStatement(query.statement); if (!statement) throw new Error(`Missing cached statement "${query.statement}" where required`); return statement; } setupDatabase() { if (this.dbReady) return; this.dbReady = true; const { file, extension } = this.options; const Database = getModule(); this.database = Database ? new Database(file) : null; if (extension) this.loadExtensionFile(extension); } loadExtensionFile(extension) { return this.handleExtensions(require("../" + extension)); } handleExtensions(imports) { if (!this.database) return; const { functions, transactions: storedTransactions, statements: storedStatements, onDatabaseStart } = imports; if (onDatabaseStart) { onDatabaseStart.call(this, this.database); } if (functions) { for (const k in functions) { this.registerFunction(k, functions[k]); } } if (storedTransactions) { for (const t in storedTransactions) { const transaction = this.database.transaction(storedTransactions[t]); this.state.transactions.set(t, transaction); } } if (storedStatements) { for (const k in storedStatements) { const statement = this.database.prepare(storedStatements[k]); this.state.statements.set(statement.source, statement); } } } async query(input) { const result = await super.query(input); if (result?.queryError) { const err = new Error(result.queryError.message); err.stack = result.queryError.stack; if (this.options.onError) { const errResult = this.options.onError(err, result.queryError.query, true); if (errResult) return errResult; } throw err; } return result; } all(statement, data = [], noPrepare) { if (typeof statement !== "string") statement = statement.toString(); return this.query({ type: "all", statement, data, noPrepare }); } get(statement, data = [], noPrepare) { if (typeof statement !== "string") statement = statement.toString(); return this.query({ type: "get", statement, data, noPrepare }); } run(statement, data = [], noPrepare) { if (typeof statement !== "string") statement = statement.toString(); return this.query({ type: "run", statement, data, noPrepare }); } transaction(name, data = []) { return this.query({ type: "transaction", name, data }); } async prepare(statement) { const source = await this.query({ type: "prepare", data: statement }); if (!source) return null; return new Statement(source, this); } exec(data) { return this.query({ type: "exec", data }); } loadExtension(filepath) { return this.query({ type: "load-extension", data: filepath }); } async runFile(file) { const contents = await (0, import_fs.FS)(file).read(); return this.query({ type: "exec", data: contents }); } } const tables = /* @__PURE__ */ new Map(); class DatabaseTable { constructor(name, primaryKeyName, database) { this.name = name; this.database = database; this.primaryKeyName = primaryKeyName; tables.set(this.name, this); } async selectOne(entries, where) { const query = where || SQL.SQL``; query.append(" LIMIT 1"); const rows = await this.selectAll(entries, query); return rows?.[0] || null; } selectAll(entries, where) { const query = SQL.SQL`SELECT `; if (typeof entries === "string") { query.append(` ${entries} `); } else { for (let i = 0; i < entries.length; i++) { query.append(entries[i]); if (typeof entries[i + 1] !== "undefined") query.append(", "); } query.append(" "); } query.append(`FROM ${this.name} `); if (where) { query.append(" WHERE "); query.append(where); } return this.all(query); } get(entries, keyId) { const query = SQL.SQL``; query.append(this.primaryKeyName); query.append(SQL.SQL` = ${keyId}`); return this.selectOne(entries, query); } updateAll(toParams, where, limit) { const to = Object.entries(toParams); const query = SQL.SQL`UPDATE `; query.append(this.name + " SET "); for (let i = 0; i < to.length; i++) { const [k, v] = to[i]; query.append(`${k} = `); query.append(SQL.SQL`${v}`); if (typeof to[i + 1] !== "undefined") { query.append(", "); } } if (where) { query.append(` WHERE `); query.append(where); } if (limit) query.append(SQL.SQL` LIMIT ${limit}`); return this.run(query); } updateOne(to, where) { return this.updateAll(to, where, 1); } deleteAll(where, limit) { const query = SQL.SQL`DELETE FROM `; query.append(this.name); if (where) { query.append(" WHERE "); query.append(where); } if (limit) { query.append(SQL.SQL` LIMIT ${limit}`); } return this.run(query); } delete(keyEntry) { const query = SQL.SQL``; query.append(this.primaryKeyName); query.append(SQL.SQL` = ${keyEntry}`); return this.deleteOne(query); } deleteOne(where) { return this.deleteAll(where, 1); } insert(colMap, rest, isReplace = false) { const query = SQL.SQL``; query.append(`${isReplace ? "REPLACE" : "INSERT"} INTO ${this.name} (`); const keys = Object.keys(colMap); for (let i = 0; i < keys.length; i++) { query.append(keys[i]); if (typeof keys[i + 1] !== "undefined") query.append(", "); } query.append(") VALUES ("); for (let i = 0; i < keys.length; i++) { const key = keys[i]; query.append(SQL.SQL`${colMap[key]}`); if (typeof keys[i + 1] !== "undefined") query.append(", "); } query.append(") "); if (rest) query.append(rest); return this.database.run(query.sql, query.values); } replace(cols, rest) { return this.insert(cols, rest, true); } update(primaryKey, data) { const query = SQL.SQL``; query.append(this.primaryKeyName + " = "); query.append(SQL.SQL`${primaryKey}`); return this.updateOne(data, query); } // catch-alls for "we can't fit this query into any of the wrapper functions" run(sql) { return this.database.run(sql.sql, sql.values); } all(sql) { return this.database.all(sql.sql, sql.values); } } function getSQL(module2, input) { const { processes } = input; const PM = new SQLDatabaseManager(module2, input); if (PM.isParentProcess) { if (processes) PM.spawn(processes); } return PM; } const SQL = Object.assign(getSQL, { DatabaseTable, SQLDatabaseManager, tables, SQL: (() => { try { return require("sql-template-strings"); } catch { return () => { throw new Error("Using SQL-template-strings without it installed"); }; } })() }); //# sourceMappingURL=sql.js.map