"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Database = void 0; const Statement_1 = require("./Statement"); const migrate_1 = require("./utils/migrate"); const strings_1 = require("./utils/strings"); const format_error_1 = require("./utils/format-error"); /** * Promisified wrapper for the sqlite3#Database interface. */ class Database { constructor(config) { this.config = config; this.db = null; } /** * Event handler when verbose mode is enabled. * @see https://github.com/mapbox/node-sqlite3/wiki/Debugging */ on(event, listener) { this.db.on(event, listener); } /** * Returns the underlying sqlite3 Database instance */ getDatabaseInstance() { return this.db; } /** * Opens the database */ open() { return new Promise((resolve, reject) => { let { filename, mode, driver } = this.config; // https://github.com/mapbox/node-sqlite3/wiki/API#new-sqlite3databasefilename-mode-callback if (filename === null || filename === undefined) { throw new Error('sqlite: filename cannot be null / undefined'); } if (!driver) { throw new Error('sqlite: driver is not defined'); } if (mode) { this.db = new driver(filename, mode, err => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(); }); } else { this.db = new driver(filename, err => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(); }); } }); } /** * Closes the database. */ close() { return new Promise((resolve, reject) => { this.db.close(err => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(); }); }); } /** * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaseconfigureoption-value */ configure(option, value) { this.db.configure(option, value); } /** * Runs the SQL query with the specified parameters. It does not retrieve any result data. * The function returns the Database object for which it was called to allow for function chaining. * * @param {string} sql The SQL query to run. * * @param {any} [params, ...] When the SQL statement contains placeholders, you * can pass them in here. They will be bound to the statement before it is * executed. There are three ways of passing bind parameters: directly in * the function's arguments, as an array, and as an object for named * parameters. This automatically sanitizes inputs. * * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaserunsql-param--callback */ run(sql, ...params) { return new Promise((resolve, reject) => { const sqlObj = (0, strings_1.toSqlParams)(sql, params); this.db.run(sqlObj.sql, ...sqlObj.params, function (err) { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve({ stmt: new Statement_1.Statement(this.stmt), lastID: this.lastID, changes: this.changes }); }); }); } /** * Runs the SQL query with the specified parameters and resolves with * with the first result row afterwards. If the result set is empty, returns undefined. * * The property names correspond to the column names of the result set. * It is impossible to access them by column index; the only supported way is by column name. * * @param {string} sql The SQL query to run. * * @param {any} [params, ...] When the SQL statement contains placeholders, you * can pass them in here. They will be bound to the statement before it is * executed. There are three ways of passing bind parameters: directly in * the function's arguments, as an array, and as an object for named * parameters. This automatically sanitizes inputs. * * @see https://github.com/mapbox/node-sqlite3/wiki/API#databasegetsql-param--callback */ get(sql, ...params) { return new Promise((resolve, reject) => { const sqlObj = (0, strings_1.toSqlParams)(sql, params); this.db.get(sqlObj.sql, ...sqlObj.params, (err, row) => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(row); }); }); } each(sql, ...params) { return new Promise((resolve, reject) => { const callback = params.pop(); if (!callback || typeof callback !== 'function') { throw new Error('sqlite: Last param of Database#each() must be a callback function'); } if (params.length > 0) { const positional = params.pop(); if (typeof positional === 'function') { throw new Error('sqlite: Database#each() should only have a single callback defined. See readme for usage.'); } params.push(positional); } const sqlObj = (0, strings_1.toSqlParams)(sql, params); this.db.each(sqlObj.sql, ...sqlObj.params, (err, row) => { if (err) { return callback((0, format_error_1.formatError)(err), null); } callback(null, row); }, (err, count) => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(count); }); }); } /** * Runs the SQL query with the specified parameters. The parameters are the same as the * Database#run function, with the following differences: * * If the result set is empty, it will be an empty array, otherwise it will * have an object for each result row which * in turn contains the values of that row, like the Database#get function. * * Note that it first retrieves all result rows and stores them in memory. * For queries that have potentially large result sets, use the Database#each * function to retrieve all rows or Database#prepare followed by multiple * Statement#get calls to retrieve a previously unknown amount of rows. * * @param {string} sql The SQL query to run. * * @param {any} [params, ...] When the SQL statement contains placeholders, you * can pass them in here. They will be bound to the statement before it is * executed. There are three ways of passing bind parameters: directly in * the function's arguments, as an array, and as an object for named * parameters. This automatically sanitizes inputs. * * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaseallsql-param--callback */ all(sql, ...params) { return new Promise((resolve, reject) => { const sqlObj = (0, strings_1.toSqlParams)(sql, params); this.db.all(sqlObj.sql, ...sqlObj.params, (err, rows) => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(rows); }); }); } /** * Runs all SQL queries in the supplied string. No result rows are retrieved. If a query fails, * no subsequent statements will be executed (wrap it in a transaction if you want all * or none to be executed). * * Note: This function will only execute statements up to the first NULL byte. * Comments are not allowed and will lead to runtime errors. * * @param {string} sql The SQL query to run. * @see https://github.com/mapbox/node-sqlite3/wiki/API#databaseexecsql-callback */ exec(sql) { return new Promise((resolve, reject) => { const sqlObj = (0, strings_1.toSqlParams)(sql); this.db.exec(sqlObj.sql, err => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(); }); }); } /** * Prepares the SQL statement and optionally binds the specified parameters. * When bind parameters are supplied, they are bound to the prepared statement. * * @param {string} sql The SQL query to run. * @param {any} [params, ...] When the SQL statement contains placeholders, you * can pass them in here. They will be bound to the statement before it is * executed. There are three ways of passing bind parameters: directly in * the function's arguments, as an array, and as an object for named * parameters. This automatically sanitizes inputs. * @returns Promise Statement object */ prepare(sql, ...params) { return new Promise((resolve, reject) => { const sqlObj = (0, strings_1.toSqlParams)(sql, params); const stmt = this.db.prepare(sqlObj.sql, ...sqlObj.params, err => { if (err) { return reject(err); } resolve(new Statement_1.Statement(stmt)); }); }); } /** * Loads a compiled SQLite extension into the database connection object. * * @param {string} path Filename of the extension to load */ loadExtension(path) { return new Promise((resolve, reject) => { this.db.loadExtension(path, err => { if (err) { return reject((0, format_error_1.formatError)(err)); } resolve(); }); }); } /** * Performs a database migration. */ async migrate(config) { await (0, migrate_1.migrate)(this, config); } /** * The methods underneath requires creative work to implement. PRs / proposals accepted! */ /* * Unsure if serialize can be made into a promise. */ serialize() { throw new Error('sqlite: Currently not implemented. Use getDatabaseInstance().serialize() instead.'); } /* * Unsure if parallelize can be made into a promise. */ parallelize() { throw new Error('sqlite: Currently not implemented. Use getDatabaseInstance().parallelize() instead.'); } } exports.Database = Database; //# sourceMappingURL=Database.js.map