@megaorm/sqlite
Version:
This package provides a simple, high-level, unified API for interacting with SQLite databases.
207 lines • 9.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SQLite = void 0;
const sqlite3_1 = require("sqlite3");
const errors_1 = require("@megaorm/errors");
const errors_2 = require("@megaorm/errors");
const errors_3 = require("@megaorm/errors");
const errors_4 = require("@megaorm/errors");
const errors_5 = require("@megaorm/errors");
const errors_6 = require("@megaorm/errors");
const test_1 = require("@megaorm/test");
/**
* SQLite driver responsible for creating SQLite connections.
* @implements `MegaDriver` interface.
* @example
*
* // Create a new SQLite driver using a file-based database
* const driver = new SQLite('./database.sqlite');
*
* // Create a new SQLite driver using an in-memory database
* const driver = new SQLite(':memory:');
*
* // Create connection
* const connection = await driver.create();
*
* // Execute your queries
* const result = await connection.query(sql, values);
* console.log(result);
*
* // Begin a transaction
* await connection.beginTransaction();
*
* // Commit transaction
* await connection.commit();
*
* // Rollback transaction
* await connection.rollback();
*
* @note
* SQLite supports two types of databases:
* 1. **File-based database**: The database is stored in a file on disk (e.g., `./database.sqlite`). Data is persisted.
* 2. **In-memory database**: The database is stored entirely in memory and is not persisted to disk. When the connection is closed or the application stops, all data is lost.
*/
class SQLite {
/**
* Constructs a SQLite driver with the given options.
* @param path SQLite database file path like `./database.sqlite`, or `:memory:` for an in-memory database.
* @example
*
* // Create a new SQLite driver with a file-based database
* const driver = new SQLite('./database.sqlite');
*
* // Create a new SQLite driver with an in-memory database
* const driver = new SQLite(':memory:');
*
* @note
* - **File-based databases** are persistent. You can use them for long-term storage
* - **In-memory databases** are non-persistent. They are faster because they don't involve file I/O, but all data is lost when the connection is closed or the application stops. Useful for testing or temporary data storage.
*/
constructor(path) {
if (!(0, test_1.isStr)(path)) {
throw new errors_2.CreateConnectionError(`Invalid SQLite path: ${String(path)}`);
}
this.path = path;
this.id = Symbol('SQLite');
}
/**
* Creates a new SQLite connection.
* @returns A `Promise` that resolves with a new SQLite connection.
* @throws `CreateConnectionError` If connection creation fails.
* @example
*
* // Create a new SQLite driver
* const driver = new SQLite(path);
*
* // Create connection
* const connection = await driver.create();
*
* // Execute your queries
* const result = await connection.query(sql, values);
* console.log(result);
*
* // Begin a transaction
* await connection.beginTransaction();
*
* // Commit transaction
* await connection.commit();
*
* // Rollback transaction
* await connection.rollback();
*
* @note
* - When using `:memory:` as the path, SQLite creates an in-memory database that is non-persistent.
* - For a file-based database, the path should point to a valid file location like `./database.sqlite`
* - An in-memory database can be ideal for tests and temporary storage because you lose all data once the application ends.
*/
create() {
return new Promise((resolve, reject) => {
// Create connection using SQLite3
const db = new sqlite3_1.Database(this.path, (error) => {
if ((0, test_1.isError)(error)) {
return reject(new errors_2.CreateConnectionError(error.message));
}
// Enable foreign key constraints
db.run('PRAGMA foreign_keys = ON', undefined, (error) => {
if ((0, test_1.isError)(error)) {
return reject(new errors_2.CreateConnectionError(error.message));
}
const sqlite = {
id: Symbol('MegaConnection'),
driver: this,
query(sql, values) {
return new Promise((resolve, reject) => {
if (!(0, test_1.isStr)(sql)) {
return reject(new errors_1.QueryError(`Invalid query: ${String(sql)}`));
}
if ((0, test_1.isDefined)(values)) {
if (!(0, test_1.isArr)(values)) {
return reject(new errors_1.QueryError(`Invalid query values: ${String(values)}`));
}
values.forEach((value) => {
if (!(0, test_1.isNum)(value) && !(0, test_1.isStr)(value)) {
return reject(new errors_1.QueryError(`Invalid query value: ${String(value)}`));
}
});
}
// Handle SELECT queries
if (/^\s*SELECT/i.test(sql)) {
return db.all(sql, values, (error, rows) => {
if ((0, test_1.isError)(error)) {
return reject(new errors_1.QueryError(error.message));
}
return resolve(rows);
});
}
// Handle other query types
db.run(sql, values, function (error) {
if (error)
return reject(new errors_1.QueryError(error.message));
// Handle INSERT queries
if (/^\s*INSERT/i.test(sql)) {
// Check if it was a single insert or bulk insert
if (this.changes === 1) {
return resolve(this.lastID); // Return the last inserted ID for single inserts
}
return resolve(undefined); // Return undefined for bulk insert
}
return resolve(undefined);
});
});
},
close() {
return new Promise((resolve, reject) => {
db.close((error) => {
if ((0, test_1.isError)(error)) {
return reject(new errors_3.CloseConnectionError(error.message));
}
const assign = (Error) => {
return function reject() {
return Promise.reject(new Error('Cannot perform further operations once the connection is closed'));
};
};
// Reset
sqlite.close = assign(errors_3.CloseConnectionError);
sqlite.query = assign(errors_1.QueryError);
sqlite.beginTransaction = assign(errors_4.BeginTransactionError);
sqlite.commit = assign(errors_5.CommitTransactionError);
sqlite.rollback = assign(errors_6.RollbackTransactionError);
// Resolve
resolve();
});
});
},
beginTransaction() {
return new Promise((resolve, reject) => {
return sqlite
.query('BEGIN TRANSACTION;')
.then(() => resolve())
.catch((error) => reject(new errors_4.BeginTransactionError(error.message)));
});
},
commit() {
return new Promise((resolve, reject) => {
return sqlite
.query('COMMIT;')
.then(() => resolve())
.catch((error) => reject(new errors_5.CommitTransactionError(error.message)));
});
},
rollback() {
return new Promise((resolve, reject) => {
return sqlite
.query('ROLLBACK;')
.then(() => resolve())
.catch((error) => reject(new errors_6.RollbackTransactionError(error.message)));
});
},
};
// Resolve
resolve(sqlite);
});
});
});
}
}
exports.SQLite = SQLite;
//# sourceMappingURL=index.js.map