/**
 * Fast SQLite3 driver for Bun.js
 * @since v0.0.83
 *
 * @example
 * ```ts
 * import { Database } from 'bun:sqlite';
 *
 * var db = new Database('app.db');
 * db.query('SELECT * FROM users WHERE name = ?').all('John');
 * // => [{ id: 1, name: 'John' }]
 * ```
 *
 * The following types can be used when binding parameters:
 *
 * | JavaScript type | SQLite type |
 * | -------------- | ----------- |
 * | `string` | `TEXT` |
 * | `number` | `INTEGER` or `DECIMAL` |
 * | `boolean` | `INTEGER` (1 or 0) |
 * | `Uint8Array` | `BLOB` |
 * | `Buffer` | `BLOB` |
 * | `bigint` | `INTEGER` |
 * | `null` | `NULL` |
 */
declare module "bun:sqlite" {
	export class Database implements Disposable {
		/**
		 * Open or create a SQLite3 database
		 *
		 * @param filename The filename of the database to open. Pass an empty string (`""`) or `":memory:"` or undefined for an in-memory database.
		 * @param options defaults to `{readwrite: true, create: true}`. If a number, then it's treated as `SQLITE_OPEN_*` constant flags.
		 *
		 * @example
		 *
		 * ```ts
		 * const db = new Database("mydb.sqlite");
		 * db.run("CREATE TABLE foo (bar TEXT)");
		 * db.run("INSERT INTO foo VALUES (?)", ["baz"]);
		 * console.log(db.query("SELECT * FROM foo").all());
		 * ```
		 *
		 * @example
		 *
		 * Open an in-memory database
		 *
		 * ```ts
		 * const db = new Database(":memory:");
		 * db.run("CREATE TABLE foo (bar TEXT)");
		 * db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]);
		 * console.log(db.query("SELECT * FROM foo").all());
		 * ```
		 *
		 * @example
		 *
		 * Open read-only
		 *
		 * ```ts
		 * const db = new Database("mydb.sqlite", {readonly: true});
		 * ```
		 */
		constructor(
			filename?: string,
			options?:
				| number
				| {
						/**
						 * Open the database as read-only (no write operations, no create).
						 *
						 * Equivalent to {@link constants.SQLITE_OPEN_READONLY}
						 */
						readonly?: boolean;
						/**
						 * Allow creating a new database
						 *
						 * Equivalent to {@link constants.SQLITE_OPEN_CREATE}
						 */
						create?: boolean;
						/**
						 * Open the database as read-write
						 *
						 * Equivalent to {@link constants.SQLITE_OPEN_READWRITE}
						 */
						readwrite?: boolean;

						/**
						 * When set to `true`, integers are returned as `bigint` types.
						 *
						 * When set to `false`, integers are returned as `number` types and truncated to 52 bits.
						 *
						 * @default false
						 * @since v1.1.14
						 */
						safeInteger?: boolean;

						/**
						 * When set to `false` or `undefined`:
						 * - Queries missing bound parameters will NOT throw an error
						 * - Bound named parameters in JavaScript need to exactly match the SQL query.
						 *
						 * @example
						 * ```ts
						 * const db = new Database(":memory:", { strict: false });
						 * db.run("INSERT INTO foo (name) VALUES ($name)", { $name: "foo" });
						 * ```
						 *
						 * When set to `true`:
						 * - Queries missing bound parameters will throw an error
						 * - Bound named parameters in JavaScript no longer need to be `$`, `:`, or `@`. The SQL query will remain prefixed.
						 *
						 * @example
						 * ```ts
						 * const db = new Database(":memory:", { strict: true });
						 * db.run("INSERT INTO foo (name) VALUES ($name)", { name: "foo" });
						 * ```
						 * @since v1.1.14
						 */
						strict?: boolean;
				  },
		);

		/**
		 * This is an alias of `new Database()`
		 *
		 * See {@link Database}
		 */
		static open(
			filename: string,
			options?:
				| number
				| {
						/**
						 * Open the database as read-only (no write operations, no create).
						 *
						 * Equivalent to {@link constants.SQLITE_OPEN_READONLY}
						 */
						readonly?: boolean;
						/**
						 * Allow creating a new database
						 *
						 * Equivalent to {@link constants.SQLITE_OPEN_CREATE}
						 */
						create?: boolean;
						/**
						 * Open the database as read-write
						 *
						 * Equivalent to {@link constants.SQLITE_OPEN_READWRITE}
						 */
						readwrite?: boolean;
				  },
		): Database;

		/**
		 * Execute a SQL query **without returning any results**.
		 *
		 * This does not cache the query, so if you want to run a query multiple times, you should use {@link prepare} instead.
		 *
		 * @example
		 * ```ts
		 * db.run("CREATE TABLE foo (bar TEXT)");
		 * db.run("INSERT INTO foo VALUES (?)", ["baz"]);
		 * ```
		 *
		 * Useful for queries like:
		 * - `CREATE TABLE`
		 * - `INSERT INTO`
		 * - `UPDATE`
		 * - `DELETE FROM`
		 * - `DROP TABLE`
		 * - `PRAGMA`
		 * - `ATTACH DATABASE`
		 * - `DETACH DATABASE`
		 * - `REINDEX`
		 * - `VACUUM`
		 * - `EXPLAIN ANALYZE`
		 * - `CREATE INDEX`
		 * - `CREATE TRIGGER`
		 * - `CREATE VIEW`
		 * - `CREATE VIRTUAL TABLE`
		 * - `CREATE TEMPORARY TABLE`
		 *
		 * @param sql The SQL query to run
		 *
		 * @param bindings Optional bindings for the query
		 *
		 * @returns `Database` instance
		 *
		 * Under the hood, this calls `sqlite3_prepare_v3` followed by `sqlite3_step` and `sqlite3_finalize`.
		 *
		 *  * The following types can be used when binding parameters:
		 *
		 * | JavaScript type | SQLite type |
		 * | -------------- | ----------- |
		 * | `string` | `TEXT` |
		 * | `number` | `INTEGER` or `DECIMAL` |
		 * | `boolean` | `INTEGER` (1 or 0) |
		 * | `Uint8Array` | `BLOB` |
		 * | `Buffer` | `BLOB` |
		 * | `bigint` | `INTEGER` |
		 * | `null` | `NULL` |
		 */
		run<ParamsType extends SQLQueryBindings[]>(
			sqlQuery: string,
			...bindings: ParamsType[]
		): Changes;
		/**
        This is an alias of {@link Database.prototype.run}
     */
		exec<ParamsType extends SQLQueryBindings[]>(
			sqlQuery: string,
			...bindings: ParamsType[]
		): Changes;

		/**
		 * Compile a SQL query and return a {@link Statement} object. This is the
		 * same as {@link prepare} except that it caches the compiled query.
		 *
		 * This **does not execute** the query, but instead prepares it for later
		 * execution and caches the compiled query if possible.
		 *
		 * @example
		 * ```ts
		 * // compile the query
		 * const stmt = db.query("SELECT * FROM foo WHERE bar = ?");
		 * // run the query
		 * stmt.all("baz");
		 *
		 * // run the query again
		 * stmt.all();
		 * ```
		 *
		 * @param sql The SQL query to compile
		 *
		 * @returns `Statment` instance
		 *
		 * Under the hood, this calls `sqlite3_prepare_v3`.
		 */
		query<ReturnType, ParamsType extends SQLQueryBindings | SQLQueryBindings[]>(
			sqlQuery: string,
		): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type
		Statement<ReturnType, ParamsType extends any[] ? ParamsType : [ParamsType]>;

		/**
		 * Compile a SQL query and return a {@link Statement} object.
		 *
		 * This does not cache the compiled query and does not execute the query.
		 *
		 * @example
		 * ```ts
		 * // compile the query
		 * const stmt = db.query("SELECT * FROM foo WHERE bar = ?");
		 * // run the query
		 * stmt.all("baz");
		 * ```
		 *
		 * @param sql The SQL query to compile
		 * @param params Optional bindings for the query
		 *
		 * @returns `Statment` instance
		 *
		 * Under the hood, this calls `sqlite3_prepare_v3`.
		 */
		prepare<
			ReturnType,
			ParamsType extends SQLQueryBindings | SQLQueryBindings[],
		>(
			sqlQuery: string,
			params?: ParamsType,
		): // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type
		Statement<ReturnType, ParamsType extends any[] ? ParamsType : [ParamsType]>;

		/**
		 * Is the database in a transaction?
		 *
		 * @returns `true` if the database is in a transaction, `false` otherwise
		 *
		 * @example
		 * ```ts
		 * db.run("CREATE TABLE foo (bar TEXT)");
		 * db.run("INSERT INTO foo VALUES (?)", ["baz"]);
		 * db.run("BEGIN");
		 * db.run("INSERT INTO foo VALUES (?)", ["qux"]);
		 * console.log(db.inTransaction());
		 * ```
		 */
		get inTransaction(): boolean;

		/**
		 * Close the database connection.
		 *
		 * It is safe to call this method multiple times. If the database is already
		 * closed, this is a no-op. Running queries after the database has been
		 * closed will throw an error.
		 *
		 * @example
		 * ```ts
		 * db.close();
		 * ```
		 * This is called automatically when the database instance is garbage collected.
		 *
		 * Internally, this calls `sqlite3_close_v2`.
		 */
		close(
			/**
			 * If `true`, then the database will throw an error if it is in use
			 * @default false
			 *
			 * When true, this calls `sqlite3_close` instead of `sqlite3_close_v2`.
			 *
			 * Learn more about this in the [sqlite3 documentation](https://www.sqlite.org/c3ref/close.html).
			 *
			 * Bun will automatically call close by default when the database instance is garbage collected.
			 * In The future, Bun may default `throwOnError` to be true but for backwards compatibility, it is false by default.
			 */
			throwOnError?: boolean,
		): void;

		/**
		 * The filename passed when `new Database()` was called
		 * @example
		 * ```ts
		 * const db = new Database("mydb.sqlite");
		 * console.log(db.filename);
		 * // => "mydb.sqlite"
		 * ```
		 */
		readonly filename: string;

		/**
		 * The underlying `sqlite3` database handle
		 *
		 * In native code, this is not a file descriptor, but an index into an array of database handles
		 */
		readonly handle: number;

		/**
		 * Load a SQLite3 extension
		 *
		 * macOS requires a custom SQLite3 library to be linked because the Apple build of SQLite for macOS disables loading extensions. See {@link Database.setCustomSQLite}
		 *
		 * Bun chooses the Apple build of SQLite on macOS because it brings a ~50% performance improvement.
		 *
		 * @param extension name/path of the extension to load
		 * @param entryPoint optional entry point of the extension
		 */
		loadExtension(extension: string, entryPoint?: string): void;

		/**
		 * Change the dynamic library path to SQLite
		 *
		 * @note macOS-only
		 *
		 * This only works before SQLite is loaded, so
		 * that's before you call `new Database()`.
		 *
		 * It can only be run once because this will load
		 * the SQLite library into the process.
		 *
		 * @param path The path to the SQLite library
		 */
		static setCustomSQLite(path: string): boolean;

		[Symbol.dispose](): void;

		/**
		 * Creates a function that always runs inside a transaction. When the
		 * function is invoked, it will begin a new transaction. When the function
		 * returns, the transaction will be committed. If an exception is thrown,
		 * the transaction will be rolled back (and the exception will propagate as
		 * usual).
		 *
		 * @param insideTransaction The callback which runs inside a transaction
		 *
		 * @example
		 * ```ts
		 * // setup
		 * import { Database } from "bun:sqlite";
		 * const db = Database.open(":memory:");
		 * db.exec(
		 *   "CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)"
		 * );
		 *
		 * const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)");
		 * const insertMany = db.transaction((cats) => {
		 *   for (const cat of cats) insert.run(cat);
		 * });
		 *
		 * insertMany([
		 *   { $name: "Joey", $age: 2 },
		 *   { $name: "Sally", $age: 4 },
		 *   { $name: "Junior", $age: 1 },
		 * ]);
		 * ```
		 */
		transaction(insideTransaction: (...args: any) => void): CallableFunction & {
			/**
			 * uses "BEGIN DEFERRED"
			 */
			deferred: (...args: any) => void;
			/**
			 * uses "BEGIN IMMEDIATE"
			 */
			immediate: (...args: any) => void;
			/**
			 * uses "BEGIN EXCLUSIVE"
			 */
			exclusive: (...args: any) => void;
		};

		/**
		 * Save the database to an in-memory {@link Buffer} object.
		 *
		 * Internally, this calls `sqlite3_serialize`.
		 *
		 * @param name Name to save the database as @default "main"
		 * @returns Buffer containing the serialized database
		 */
		serialize(name?: string): Buffer;

		/**
		 * Load a serialized SQLite3 database
		 *
		 * Internally, this calls `sqlite3_deserialize`.
		 *
		 * @param serialized Data to load
		 * @returns `Database` instance
		 *
		 * @example
		 * ```ts
		 * test("supports serialize/deserialize", () => {
		 *     const db = Database.open(":memory:");
		 *     db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)");
		 *     db.exec('INSERT INTO test (name) VALUES ("Hello")');
		 *     db.exec('INSERT INTO test (name) VALUES ("World")');
		 *
		 *     const input = db.serialize();
		 *     const db2 = new Database(input);
		 *
		 *     const stmt = db2.prepare("SELECT * FROM test");
		 *     expect(JSON.stringify(stmt.get())).toBe(
		 *       JSON.stringify({
		 *         id: 1,
		 *         name: "Hello",
		 *       }),
		 *     );
		 *
		 *     expect(JSON.stringify(stmt.all())).toBe(
		 *       JSON.stringify([
		 *         {
		 *           id: 1,
		 *           name: "Hello",
		 *         },
		 *         {
		 *           id: 2,
		 *           name: "World",
		 *         },
		 *       ]),
		 *     );
		 *     db2.exec("insert into test (name) values ('foo')");
		 *     expect(JSON.stringify(stmt.all())).toBe(
		 *       JSON.stringify([
		 *         {
		 *           id: 1,
		 *           name: "Hello",
		 *         },
		 *         {
		 *           id: 2,
		 *           name: "World",
		 *         },
		 *         {
		 *           id: 3,
		 *           name: "foo",
		 *         },
		 *       ]),
		 *     );
		 *
		 *     const db3 = Database.deserialize(input, true);
		 *     try {
		 *       db3.exec("insert into test (name) values ('foo')");
		 *       throw new Error("Expected error");
		 *     } catch (e) {
		 *       expect(e.message).toBe("attempt to write a readonly database");
		 *     }
		 * });
		 * ```
		 */
		static deserialize(
			serialized: NodeJS.TypedArray | ArrayBufferLike,
			isReadOnly?: boolean,
		): Database;

		/**
		 * See `sqlite3_file_control` for more information.
		 * @link https://www.sqlite.org/c3ref/file_control.html
		 */
		fileControl(op: number, arg?: ArrayBufferView | number): number;
		/**
		 * See `sqlite3_file_control` for more information.
		 * @link https://www.sqlite.org/c3ref/file_control.html
		 */
		fileControl(
			zDbName: string,
			op: number,
			arg?: ArrayBufferView | number,
		): number;
	}

	/**
	 * A prepared statement.
	 *
	 * This is returned by {@link Database.prepare} and {@link Database.query}.
	 *
	 * @example
	 * ```ts
	 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
	 * stmt.all("baz");
	 * // => [{bar: "baz"}]
	 * ```
	 *
	 * @example
	 * ```ts
	 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
	 * stmt.get("baz");
	 * // => {bar: "baz"}
	 * ```
	 *
	 * @example
	 * ```ts
	 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
	 * stmt.run("baz");
	 * // => undefined
	 * ```
	 */
	export class Statement<
		ReturnType = unknown,
		ParamsType extends SQLQueryBindings[] = any[],
	> implements Disposable
	{
		/**
		 * Creates a new prepared statement from native code.
		 *
		 * This is used internally by the {@link Database} class. Probably you don't need to call this yourself.
		 */
		constructor(nativeHandle: any);

		/**
		 * Execute the prepared statement and return all results as objects.
		 *
		 * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none.
		 *
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
		 *
		 * stmt.all("baz");
		 * // => [{bar: "baz"}]
		 *
		 * stmt.all();
		 * // => [{bar: "baz"}]
		 *
		 * stmt.all("foo");
		 * // => [{bar: "foo"}]
		 * ```
		 */
		all(...params: ParamsType): ReturnType[];

		/**
		 * Execute the prepared statement and return **the first** result.
		 *
		 * If no result is returned, this returns `null`.
		 *
		 * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none.
		 *
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
		 *
		 * stmt.all("baz");
		 * // => [{bar: "baz"}]
		 *
		 * stmt.all();
		 * // => [{bar: "baz"}]
		 *
		 * stmt.all("foo");
		 * // => [{bar: "foo"}]
		 * ```
		 *
		 * The following types can be used when binding parameters:
		 *
		 * | JavaScript type | SQLite type |
		 * | -------------- | ----------- |
		 * | `string` | `TEXT` |
		 * | `number` | `INTEGER` or `DECIMAL` |
		 * | `boolean` | `INTEGER` (1 or 0) |
		 * | `Uint8Array` | `BLOB` |
		 * | `Buffer` | `BLOB` |
		 * | `bigint` | `INTEGER` |
		 * | `null` | `NULL` |
		 */
		get(...params: ParamsType): ReturnType | null;

		/**
		 * Execute the prepared statement. This returns `undefined`.
		 *
		 * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none.
		 *
		 * @example
		 * ```ts
		 * const stmt = db.prepare("UPDATE foo SET bar = ?");
		 * stmt.run("baz");
		 * // => undefined
		 *
		 * stmt.run();
		 * // => undefined
		 *
		 * stmt.run("foo");
		 * // => undefined
		 * ```
		 *
		 * The following types can be used when binding parameters:
		 *
		 * | JavaScript type | SQLite type |
		 * | -------------- | ----------- |
		 * | `string` | `TEXT` |
		 * | `number` | `INTEGER` or `DECIMAL` |
		 * | `boolean` | `INTEGER` (1 or 0) |
		 * | `Uint8Array` | `BLOB` |
		 * | `Buffer` | `BLOB` |
		 * | `bigint` | `INTEGER` |
		 * | `null` | `NULL` |
		 */
		run(...params: ParamsType): Changes;

		/**
		 * Execute the prepared statement and return the results as an array of arrays.
		 *
		 * In Bun v0.6.7 and earlier, this method returned `null` if there were no
		 * results instead of `[]`. This was changed in v0.6.8 to align
		 * more with what people expect.
		 *
		 * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none.
		 *
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
		 *
		 * stmt.values("baz");
		 * // => [['baz']]
		 *
		 * stmt.values();
		 * // => [['baz']]
		 *
		 * stmt.values("foo");
		 * // => [['foo']]
		 *
		 * stmt.values("not-found");
		 * // => []
		 * ```
		 *
		 * The following types can be used when binding parameters:
		 *
		 * | JavaScript type | SQLite type |
		 * | ---------------|-------------|
		 * | `string` | `TEXT` |
		 * | `number` | `INTEGER` or `DECIMAL` |
		 * | `boolean` | `INTEGER` (1 or 0) |
		 * | `Uint8Array` | `BLOB` |
		 * | `Buffer` | `BLOB` |
		 * | `bigint` | `INTEGER` |
		 * | `null` | `NULL` |
		 */
		values(
			...params: ParamsType
		): Array<Array<string | bigint | number | boolean | Uint8Array>>;

		/**
		 * The names of the columns returned by the prepared statement.
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT bar FROM foo WHERE bar = ?");
		 *
		 * console.log(stmt.columnNames);
		 * // => ["bar"]
		 * ```
		 */
		readonly columnNames: string[];

		/**
		 * The number of parameters expected in the prepared statement.
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?");
		 * console.log(stmt.paramsCount);
		 * // => 1
		 * ```
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ? AND baz = ?");
		 * console.log(stmt.paramsCount);
		 * // => 2
		 * ```
		 */
		readonly paramsCount: number;

		/**
		 * Finalize the prepared statement, freeing the resources used by the
		 * statement and preventing it from being executed again.
		 *
		 * This is called automatically when the prepared statement is garbage collected.
		 *
		 * It is safe to call this multiple times. Calling this on a finalized
		 * statement has no effect.
		 *
		 * Internally, this calls `sqlite3_finalize`.
		 */
		finalize(): void;

		/**
		 * Calls {@link finalize} if it wasn't already called.
		 */
		[Symbol.dispose](): void;

		/**
		 * Return the expanded SQL string for the prepared statement.
		 *
		 * Internally, this calls `sqlite3_expanded_sql()` on the underlying `sqlite3_stmt`.
		 *
		 * @example
		 * ```ts
		 * const stmt = db.prepare("SELECT * FROM foo WHERE bar = ?", "baz");
		 * console.log(stmt.toString());
		 * // => "SELECT * FROM foo WHERE bar = 'baz'"
		 * console.log(stmt);
		 * // => "SELECT * FROM foo WHERE bar = 'baz'"
		 * ```
		 */
		toString(): string;

		/**
		 *
		 * Make {@link get} and {@link all} return an instance of the provided
		 * `Class` instead of the default `Object`.
		 *
		 * @param Class A class to use
		 * @returns The same statement instance, modified to return an instance of `Class`
		 *
		 * This lets you attach methods, getters, and setters to the returned
		 * objects.
		 *
		 * For performance reasons, constructors for classes are not called, which means
		 * initializers will not be called and private fields will not be
		 * accessible.
		 *
		 * @example
		 *
		 * ## Custom class
		 * ```ts
		 * class User {
		 *    rawBirthdate: string;
		 *    get birthdate() {
		 *      return new Date(this.rawBirthdate);
		 *    }
		 * }
		 *
		 * const db = new Database(":memory:");
		 * db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, rawBirthdate TEXT)");
		 * db.run("INSERT INTO users (rawBirthdate) VALUES ('1995-12-19')");
		 * const query = db.query("SELECT * FROM users");
		 * query.as(User);
		 * const user = query.get();
		 * console.log(user.birthdate);
		 * // => Date(1995, 11, 19)
		 * ```
		 */
		as<T = unknown>(Class: new (...args: any[]) => T): Statement<T, ParamsType>;

		/**
		 * Native object representing the underlying `sqlite3_stmt`
		 *
		 * This is left untyped because the ABI of the native bindings may change at any time.
		 */
		readonly native: any;
	}

	/**
	 * Constants from `sqlite3.h`
	 *
	 * This list isn't exhaustive, but some of the ones which are relevant
	 */
	export const constants: {
		/**
		 * Open the database as read-only (no write operations, no create).
		 * @constant 0x00000001
		 */
		SQLITE_OPEN_READONLY: number;
		/**
		 * Open the database for reading and writing
		 * @constant 0x00000002
		 */
		SQLITE_OPEN_READWRITE: number;
		/**
		 * Allow creating a new database
		 * @constant 0x00000004
		 */
		SQLITE_OPEN_CREATE: number;
		/**
		 * @constant 0x00000008
		 */
		SQLITE_OPEN_DELETEONCLOSE: number;
		/**
		 * @constant 0x00000010
		 */
		SQLITE_OPEN_EXCLUSIVE: number;
		/**
		 * @constant 0x00000020
		 */
		SQLITE_OPEN_AUTOPROXY: number;
		/**
		 * @constant 0x00000040
		 */
		SQLITE_OPEN_URI: number;
		/**
		 * @constant 0x00000080
		 */
		SQLITE_OPEN_MEMORY: number;
		/**
		 * @constant 0x00000100
		 */
		SQLITE_OPEN_MAIN_DB: number;
		/**
		 * @constant 0x00000200
		 */
		SQLITE_OPEN_TEMP_DB: number;
		/**
		 * @constant 0x00000400
		 */
		SQLITE_OPEN_TRANSIENT_DB: number;
		/**
		 * @constant 0x00000800
		 */
		SQLITE_OPEN_MAIN_JOURNAL: number;
		/**
		 * @constant 0x00001000
		 */
		SQLITE_OPEN_TEMP_JOURNAL: number;
		/**
		 * @constant 0x00002000
		 */
		SQLITE_OPEN_SUBJOURNAL: number;
		/**
		 * @constant 0x00004000
		 */
		SQLITE_OPEN_SUPER_JOURNAL: number;
		/**
		 * @constant 0x00008000
		 */
		SQLITE_OPEN_NOMUTEX: number;
		/**
		 * @constant 0x00010000
		 */
		SQLITE_OPEN_FULLMUTEX: number;
		/**
		 * @constant 0x00020000
		 */
		SQLITE_OPEN_SHAREDCACHE: number;
		/**
		 * @constant 0x00040000
		 */
		SQLITE_OPEN_PRIVATECACHE: number;
		/**
		 * @constant 0x00080000
		 */
		SQLITE_OPEN_WAL: number;
		/**
		 * @constant 0x01000000
		 */
		SQLITE_OPEN_NOFOLLOW: number;
		/**
		 * @constant 0x02000000
		 */
		SQLITE_OPEN_EXRESCODE: number;
		/**
		 * @constant 0x01
		 */
		SQLITE_PREPARE_PERSISTENT: number;
		/**
		 * @constant 0x02
		 */
		SQLITE_PREPARE_NORMALIZE: number;
		/**
		 * @constant 0x04
		 */
		SQLITE_PREPARE_NO_VTAB: number;

		/**
		 * @constant 1
		 */
		SQLITE_FCNTL_LOCKSTATE: number;
		/**
		 * @constant 2
		 */
		SQLITE_FCNTL_GET_LOCKPROXYFILE: number;
		/**
		 * @constant 3
		 */
		SQLITE_FCNTL_SET_LOCKPROXYFILE: number;
		/**
		 * @constant 4
		 */
		SQLITE_FCNTL_LAST_ERRNO: number;
		/**
		 * @constant 5
		 */
		SQLITE_FCNTL_SIZE_HINT: number;
		/**
		 * @constant 6
		 */
		SQLITE_FCNTL_CHUNK_SIZE: number;
		/**
		 * @constant 7
		 */
		SQLITE_FCNTL_FILE_POINTER: number;
		/**
		 * @constant 8
		 */
		SQLITE_FCNTL_SYNC_OMITTED: number;
		/**
		 * @constant 9
		 */
		SQLITE_FCNTL_WIN32_AV_RETRY: number;
		/**
		 * @constant 10
		 *
		 * Control whether or not the WAL is persisted
		 * Some versions of macOS configure WAL to be persistent by default.
		 *
		 * You can change this with code like the below:
		 * ```ts
		 * import { Database } from "bun:sqlite";
		 *
		 * const db = Database.open("mydb.sqlite");
		 * db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0);
		 * // enable WAL
		 * db.exec("PRAGMA journal_mode = WAL");
		 * // .. do some work
		 * db.close();
		 * ```
		 *
		 */
		SQLITE_FCNTL_PERSIST_WAL: number;
		/**
		 * @constant 11
		 */
		SQLITE_FCNTL_OVERWRITE: number;
		/**
		 * @constant 12
		 */
		SQLITE_FCNTL_VFSNAME: number;
		/**
		 * @constant 13
		 */
		SQLITE_FCNTL_POWERSAFE_OVERWRITE: number;
		/**
		 * @constant 14
		 */
		SQLITE_FCNTL_PRAGMA: number;
		/**
		 * @constant 15
		 */
		SQLITE_FCNTL_BUSYHANDLER: number;
		/**
		 * @constant 16
		 */
		SQLITE_FCNTL_TEMPFILENAME: number;
		/**
		 * @constant 18
		 */
		SQLITE_FCNTL_MMAP_SIZE: number;
		/**
		 * @constant 19
		 */
		SQLITE_FCNTL_TRACE: number;
		/**
		 * @constant 20
		 */
		SQLITE_FCNTL_HAS_MOVED: number;
		/**
		 * @constant 21
		 */
		SQLITE_FCNTL_SYNC: number;
		/**
		 * @constant 22
		 */
		SQLITE_FCNTL_COMMIT_PHASETWO: number;
		/**
		 * @constant 23
		 */
		SQLITE_FCNTL_WIN32_SET_HANDLE: number;
		/**
		 * @constant 24
		 */
		SQLITE_FCNTL_WAL_BLOCK: number;
		/**
		 * @constant 25
		 */
		SQLITE_FCNTL_ZIPVFS: number;
		/**
		 * @constant 26
		 */
		SQLITE_FCNTL_RBU: number;
		/**
		 * @constant 27
		 */
		SQLITE_FCNTL_VFS_POINTER: number;
		/**
		 * @constant 28
		 */
		SQLITE_FCNTL_JOURNAL_POINTER: number;
		/**
		 * @constant 29
		 */
		SQLITE_FCNTL_WIN32_GET_HANDLE: number;
		/**
		 * @constant 30
		 */
		SQLITE_FCNTL_PDB: number;
		/**
		 * @constant 31
		 */
		SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: number;
		/**
		 * @constant 32
		 */
		SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: number;
		/**
		 * @constant 33
		 */
		SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: number;
		/**
		 * @constant 34
		 */
		SQLITE_FCNTL_LOCK_TIMEOUT: number;
		/**
		 * @constant 35
		 */
		SQLITE_FCNTL_DATA_VERSION: number;
		/**
		 * @constant 36
		 */
		SQLITE_FCNTL_SIZE_LIMIT: number;
		/**
		 * @constant 37
		 */
		SQLITE_FCNTL_CKPT_DONE: number;
		/**
		 * @constant 38
		 */
		SQLITE_FCNTL_RESERVE_BYTES: number;
		/**
		 * @constant 39
		 */
		SQLITE_FCNTL_CKPT_START: number;
		/**
		 * @constant 40
		 */
		SQLITE_FCNTL_EXTERNAL_READER: number;
		/**
		 * @constant 41
		 */
		SQLITE_FCNTL_CKSM_FILE: number;
		/**
		 * @constant 42
		 */
		SQLITE_FCNTL_RESET_CACHE: number;
	};

	/**
	 * The native module implementing the sqlite3 C bindings
	 *
	 * It is lazily-initialized, so this will return `undefined` until the first
	 * call to new Database().
	 *
	 * The native module makes no gurantees about ABI stability, so it is left
	 * untyped
	 *
	 * If you need to use it directly for some reason, please let us know because
	 * that probably points to a deficiency in this API.
	 */
	export var native: any;

	export type SQLQueryBindings =
		| string
		| bigint
		| NodeJS.TypedArray
		| number
		| boolean
		| null
		| Record<
				string,
				string | bigint | NodeJS.TypedArray | number | boolean | null
		  >;

	export default Database;

	/**
	 * Errors from SQLite have a name `SQLiteError`.
	 *
	 */
	export class SQLiteError extends Error {
		readonly name: "SQLiteError";

		/**
		 * The SQLite3 extended error code
		 *
		 * This corresponds to `sqlite3_extended_errcode`.
		 *
		 * @since v1.0.21
		 */
		errno: number;

		/**
		 * The name of the SQLite3 error code
		 *
		 * @example
		 * "SQLITE_CONSTRAINT_UNIQUE"
		 *
		 * @since v1.0.21
		 */
		code?: string;

		/**
		 * The UTF-8 byte offset of the sqlite3 query that failed, if known
		 *
		 * This corresponds to `sqlite3_error_offset`.
		 *
		 * @since v1.0.21
		 */
		readonly byteOffset: number;
	}

	/**
	 * An object representing the changes made to the database since the last `run` or `exec` call.
	 *
	 * @since Bun v1.1.14
	 */
	interface Changes {
		/**
		 * The number of rows changed by the last `run` or `exec` call.
		 */
		changes: number;

		/**
		 * If `safeIntegers` is `true`, this is a `bigint`. Otherwise, it is a `number`.
		 */
		lastInsertRowid: number | bigint;
	}
}
