diff --git a/src/index.ts b/src/index.ts
index a01840f..f968008 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,7 +1,290 @@
 import { NativeModules, Platform } from 'react-native';
 
+export type Scalar =
+  | string
+  | number
+  | boolean
+  | null
+  | ArrayBuffer
+  | ArrayBufferView;
+
+/**
+ * Object returned by SQL Query executions {
+ *  insertId: Represent the auto-generated row id if applicable
+ *  rowsAffected: Number of affected rows if result of a update query
+ *  message: if status === 1, here you will find error description
+ *  rows: if status is undefined or 0 this object will contain the query results
+ * }
+ *
+ * @interface QueryResult
+ */
+export type QueryResult = {
+  insertId?: number;
+  rowsAffected: number;
+  res?: any[];
+  rows: Array<Record<string, Scalar>>;
+  // An array of intermediate results, just values without column names
+  rawRows?: Scalar[][];
+  columnNames?: string[];
+  /**
+   * Query metadata, available only for select query results
+   */
+  metadata?: ColumnMetadata[];
+};
+
+/**
+ * Column metadata
+ * Describes some information about columns fetched by the query
+ */
+export type ColumnMetadata = {
+  /** The name used for this column for this result set */
+  name: string;
+  /** The declared column type for this column, when fetched directly from a table or a View resulting from a table column. "UNKNOWN" for dynamic values, like function returned ones. */
+  type: string;
+  /**
+   * The index for this column for this result set*/
+  index: number;
+};
+
+/**
+ * Allows the execution of bulk of sql commands
+ * inside a transaction
+ * If a single query must be executed many times with different arguments, its preferred
+ * to declare it a single time, and use an array of array parameters.
+ */
+export type SQLBatchTuple = [string] | [string, Array<any> | Array<Array<any>>];
+
+export type UpdateHookOperation = 'INSERT' | 'DELETE' | 'UPDATE';
+
+/**
+ * status: 0 or undefined for correct execution, 1 for error
+ * message: if status === 1, here you will find error description
+ * rowsAffected: Number of affected rows if status == 0
+ */
+export type BatchQueryResult = {
+  rowsAffected?: number;
+};
+
+/**
+ * Result of loading a file and executing every line as a SQL command
+ * Similar to BatchQueryResult
+ */
+export type FileLoadResult = BatchQueryResult & {
+  commands?: number;
+};
+
+export type Transaction = {
+  commit: () => Promise<QueryResult>;
+  execute: (query: string, params?: Scalar[]) => Promise<QueryResult>;
+  rollback: () => Promise<QueryResult>;
+};
+
+type PendingTransaction = {
+  /*
+   * The start function should not throw or return a promise because the
+   * queue just calls it and does not monitor for failures or completions.
+   *
+   * It should catch any errors and call the resolve or reject of the wrapping
+   * promise when complete.
+   *
+   * It should also automatically commit or rollback the transaction if needed
+   */
+  start: () => void;
+};
+
+export type PreparedStatement = {
+  bind: (params: any[]) => Promise<void>;
+  execute: () => Promise<QueryResult>;
+};
+
+type InternalDB = {
+  close: () => void;
+  delete: (location?: string) => void;
+  attach: (
+    mainDbName: string,
+    dbNameToAttach: string,
+    alias: string,
+    location?: string
+  ) => void;
+  detach: (mainDbName: string, alias: string) => void;
+  transaction: (fn: (tx: Transaction) => Promise<void>) => Promise<void>;
+  executeSync: (query: string, params?: Scalar[]) => QueryResult;
+  execute: (query: string, params?: Scalar[]) => Promise<QueryResult>;
+  executeWithHostObjects: (
+    query: string,
+    params?: Scalar[]
+  ) => Promise<QueryResult>;
+  executeBatch: (commands: SQLBatchTuple[]) => Promise<BatchQueryResult>;
+  loadFile: (location: string) => Promise<FileLoadResult>;
+  updateHook: (
+    callback?:
+      | ((params: {
+          table: string;
+          operation: UpdateHookOperation;
+          row?: any;
+          rowId: number;
+        }) => void)
+      | null
+  ) => void;
+  commitHook: (callback?: (() => void) | null) => void;
+  rollbackHook: (callback?: (() => void) | null) => void;
+  prepareStatement: (query: string) => PreparedStatement;
+  loadExtension: (path: string, entryPoint?: string) => void;
+  executeRaw: (query: string, params?: Scalar[]) => Promise<any[]>;
+  getDbPath: (location?: string) => string;
+  reactiveExecute: (params: {
+    query: string;
+    arguments: any[];
+    fireOn: {
+      table: string;
+      ids?: number[];
+    }[];
+    callback: (response: any) => void;
+  }) => () => void;
+  /** This function is only available for libsql.
+   * Allows to trigger a sync the database with it's remote replica
+   * In order for this function to work you need to use openSync or openRemote functions
+   * with libsql: true in the package.json
+   *
+   * The database is hosted in turso
+   **/
+  sync: () => void;
+  flushPendingReactiveQueries: () => Promise<void>;
+};
+
+export type DB = {
+  close: () => void;
+  delete: (location?: string) => void;
+  attach: (
+    mainDbName: string,
+    dbNameToAttach: string,
+    alias: string,
+    location?: string
+  ) => void;
+  detach: (mainDbName: string, alias: string) => void;
+  transaction: (fn: (tx: Transaction) => Promise<void>) => Promise<void>;
+  /**
+   * Sync version of the execute function
+   * It will block the JS thread and therefore your UI and should be used with caution
+   *
+   * When writing your queries, you can use the ? character as a placeholder for parameters
+   * The parameters will be automatically escaped and sanitized
+   *
+   * Example:
+   * db.executeSync('SELECT * FROM table WHERE id = ?', [1]);
+   *
+   * If you are writing a query that doesn't require parameters, you can omit the second argument
+   *
+   * If you are writing to the database YOU SHOULD BE USING TRANSACTIONS!
+   * Transactions protect you from partial writes and ensure that your data is always in a consistent state
+   *
+   * @param query
+   * @param params
+   * @returns QueryResult
+   */
+  executeSync: (query: string, params?: Scalar[]) => QueryResult;
+  /**
+   * Basic query execution function, it is async don't forget to await it
+   *
+   * When writing your queries, you can use the ? character as a placeholder for parameters
+   * The parameters will be automatically escaped and sanitized
+   *
+   * Example:
+   * await db.execute('SELECT * FROM table WHERE id = ?', [1]);
+   *
+   * If you are writing a query that doesn't require parameters, you can omit the second argument
+   *
+   * If you are writing to the database YOU SHOULD BE USING TRANSACTIONS!
+   * Transactions protect you from partial writes and ensure that your data is always in a consistent state
+   *
+   * @param query string of your SQL query
+   * @param params a list of parameters to bind to the query, if any
+   * @returns Promise<QueryResult> with the result of the query
+   */
+  execute: (query: string, params?: Scalar[]) => Promise<QueryResult>;
+  /**
+   * Similar to the execute function but returns the response in HostObjects
+   * Read more about HostObjects in the documentation and their pitfalls
+   *
+   * Will be a lot faster than the normal execute functions when returning data but you will pay when accessing the fields
+   * as the conversion is done the moment you access any field
+   * @param query
+   * @param params
+   * @returns
+   */
+  executeWithHostObjects: (
+    query: string,
+    params?: Scalar[]
+  ) => Promise<QueryResult>;
+  executeBatch: (commands: SQLBatchTuple[]) => Promise<BatchQueryResult>;
+  loadFile: (location: string) => Promise<FileLoadResult>;
+  updateHook: (
+    callback?:
+      | ((params: {
+          table: string;
+          operation: UpdateHookOperation;
+          row?: any;
+          rowId: number;
+        }) => void)
+      | null
+  ) => void;
+  commitHook: (callback?: (() => void) | null) => void;
+  rollbackHook: (callback?: (() => void) | null) => void;
+  /**
+   * Constructs a prepared statement from the query string
+   * The statement can be re-bound with parameters and executed
+   * The performance gain is significant when the same query is executed multiple times, NOT when the query is executed (once)
+   * The cost lies in the preparation of the statement as it is compiled and optimized by the sqlite engine, the params can then rebound
+   * but the query itself is already optimized
+   *
+   * @param query string of your SQL query
+   * @returns Prepared statement object
+   */
+  prepareStatement: (query: string) => PreparedStatement;
+  loadExtension: (path: string, entryPoint?: string) => void;
+  executeRaw: (query: string, params?: Scalar[]) => Promise<any[]>;
+  getDbPath: (location?: string) => string;
+  reactiveExecute: (params: {
+    query: string;
+    arguments: any[];
+    fireOn: {
+      table: string;
+      ids?: number[];
+    }[];
+    callback: (response: any) => void;
+  }) => () => void;
+  /** This function is only available for libsql.
+   * Allows to trigger a sync the database with it's remote replica
+   * In order for this function to work you need to use openSync or openRemote functions
+   * with libsql: true in the package.json
+   *
+   * The database is hosted in turso
+   **/
+  sync: () => void;
+};
+
+export type DBParams = {
+  url?: string;
+  authToken?: string;
+  name?: string;
+  location?: string;
+  syncInterval?: number;
+};
+
+export type OPSQLiteProxy = {
+  open: (options: {
+    name: string;
+    location?: string;
+    encryptionKey?: string;
+  }) => InternalDB;
+  openRemote: (options: { url: string; authToken: string }) => InternalDB;
+  openSync: (options: DBParams) => InternalDB;
+  isSQLCipher: () => boolean;
+  isLibsql: () => boolean;
+  isIOSEmbedded: () => boolean;
+};
+
 declare global {
-  function nativeCallSyncHook(): unknown;
   var __OPSQLiteProxy: object | undefined;
 }
 
@@ -41,12 +324,7 @@ export const {
   ? NativeModules.OPSQLite.getConstants()
   : NativeModules.OPSQLite;
 
-const locks: Record<
-  string,
-  { queue: PendingTransaction[]; inProgress: boolean }
-> = {};
-
-function enhanceDB(db: DB, options: any): DB {
+function enhanceDB(db: InternalDB, options: DBParams): DB {
   const lock = {
     queue: [] as PendingTransaction[],
     inProgress: false,
@@ -72,7 +350,8 @@ function enhanceDB(db: DB, options: any): DB {
     }
   };
 
-  // spreading the object is not working, so we need to do it manually
+  // spreading the object does not work with HostObjects (db)
+  // We need to manually assign the fields
   let enhancedDb = {
     delete: db.delete,
     attach: db.attach,
@@ -87,11 +366,7 @@ function enhanceDB(db: DB, options: any): DB {
     getDbPath: db.getDbPath,
     reactiveExecute: db.reactiveExecute,
     sync: db.sync,
-    flushPendingReactiveQueries: db.flushPendingReactiveQueries,
-    close: () => {
-      db.close();
-      delete locks[options.url];
-    },
+    close: db.close,
     executeWithHostObjects: async (
       query: string,
       params?: Scalar[]
@@ -121,7 +396,7 @@ function enhanceDB(db: DB, options: any): DB {
         ? db.executeSync(query, sanitizedParams as Scalar[])
         : db.executeSync(query);
 
-      let rows: any[] = [];
+      let rows: Record<string, Scalar>[] = [];
       for (let i = 0; i < (intermediateResult.rawRows?.length ?? 0); i++) {
         let row: Record<string, Scalar> = {};
         let rawRow = intermediateResult.rawRows![i]!;
@@ -160,9 +435,9 @@ function enhanceDB(db: DB, options: any): DB {
         sanitizedParams as Scalar[]
       );
 
-      let rows: any[] = [];
+      let rows: Record<string, Scalar>[] = [];
       for (let i = 0; i < (intermediateResult.rawRows?.length ?? 0); i++) {
-        let row: any = {};
+        let row: Record<string, Scalar> = {};
         let rawRow = intermediateResult.rawRows![i]!;
         for (let j = 0; j < intermediateResult.columnNames!.length; j++) {
           let columnName = intermediateResult.columnNames![j]!;
@@ -186,7 +461,7 @@ function enhanceDB(db: DB, options: any): DB {
       const stmt = db.prepareStatement(query);
 
       return {
-        bind: async (params: any[]) => {
+        bind: async (params: Scalar[]) => {
           const sanitizedParams = params.map((p) => {
             if (ArrayBuffer.isView(p)) {
               return p.buffer;
@@ -205,10 +480,12 @@ function enhanceDB(db: DB, options: any): DB {
     ): Promise<void> => {
       let isFinalized = false;
 
-      const execute = async (query: string, params?: any[] | undefined) => {
+      const execute = async (query: string, params?: Scalar[]) => {
         if (isFinalized) {
           throw Error(
-            `OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
+            `OP-Sqlite Error: Database: ${
+              options.name || options.url
+            }. Cannot execute query on finalized transaction`
           );
         }
         return await enhancedDb.execute(query, params);
@@ -217,12 +494,14 @@ function enhanceDB(db: DB, options: any): DB {
       const commit = async (): Promise<QueryResult> => {
         if (isFinalized) {
           throw Error(
-            `OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
+            `OP-Sqlite Error: Database: ${
+              options.name || options.url
+            }. Cannot execute query on finalized transaction`
           );
         }
         const result = await enhancedDb.execute('COMMIT;');
 
-        await enhancedDb.flushPendingReactiveQueries();
+        await db.flushPendingReactiveQueries();
 
         isFinalized = true;
         return result;
@@ -231,7 +510,9 @@ function enhanceDB(db: DB, options: any): DB {
       const rollback = async (): Promise<QueryResult> => {
         if (isFinalized) {
           throw Error(
-            `OP-Sqlite Error: Database: ${options.url}. Cannot execute query on finalized transaction`
+            `OP-Sqlite Error: Database: ${
+              options.name || options.url
+            }. Cannot execute query on finalized transaction`
           );
         }
         const result = await enhancedDb.execute('ROLLBACK;');
@@ -253,7 +534,6 @@ function enhanceDB(db: DB, options: any): DB {
             await commit();
           }
         } catch (executionError) {
-          // console.warn('transaction error', executionError);
           if (!isFinalized) {
             try {
               await rollback();
@@ -286,10 +566,11 @@ function enhanceDB(db: DB, options: any): DB {
   return enhancedDb;
 }
 
-/** Open a replicating connection via libsql to a turso db
+/**
+ * Open a replicating connection via libsql to a turso db
  * libsql needs to be enabled on your package.json
  */
-export const openSync = (options: {
+export const openSync = (params: {
   url: string;
   authToken: string;
   name: string;
@@ -300,44 +581,56 @@ export const openSync = (options: {
     throw new Error('This function is only available for libsql');
   }
 
-  const db = OPSQLite.openSync(options);
-  const enhancedDb = enhanceDB(db, options);
+  const db = OPSQLite.openSync(params);
+  const enhancedDb = enhanceDB(db, params);
 
   return enhancedDb;
 };
 
-/** Open a remote connection via libsql to a turso db
+/**
+ * Open a remote connection via libsql to a turso db
  * libsql needs to be enabled on your package.json
  */
-export const openRemote = (options: { url: string; authToken: string }): DB => {
+export const openRemote = (params: { url: string; authToken: string }): DB => {
   if (!isLibsql()) {
     throw new Error('This function is only available for libsql');
   }
 
-  const db = OPSQLite.openRemote(options);
-  const enhancedDb = enhanceDB(db, options);
+  const db = OPSQLite.openRemote(params);
+  const enhancedDb = enhanceDB(db, params);
 
   return enhancedDb;
 };
 
-export const open = (options: {
+/**
+ * Open a connection to a local sqlite or sqlcipher database
+ * If you want libsql remote or sync connections, use openSync or openRemote
+ */
+export const open = (params: {
   name: string;
   location?: string;
   encryptionKey?: string;
 }): DB => {
-  if (options.location?.startsWith('file://')) {
+  if (params.location?.startsWith('file://')) {
     console.warn(
       "[op-sqlite] You are passing a path with 'file://' prefix, it's automatically removed"
     );
-    options.location = options.location.substring(7);
+    params.location = params.location.substring(7);
   }
 
-  const db = OPSQLite.open(options);
-  const enhancedDb = enhanceDB(db, options);
+  const db = OPSQLite.open(params);
+  const enhancedDb = enhanceDB(db, params);
 
   return enhancedDb;
 };
 
+/**
+ * Moves the database from the assets folder to the default path (check the docs) or to a custom path
+ * It DOES NOT OVERWRITE the database if it already exists in the destination path
+ * if you want to overwrite the database, you need to pass the overwrite flag as true
+ * @param args object with the parameters for the operaiton
+ * @returns promise, rejects if failed to move the database, resolves if the operation was successful
+ */
 export const moveAssetsDatabase = async (args: {
   filename: string;
   path?: string;
@@ -346,6 +639,14 @@ export const moveAssetsDatabase = async (args: {
   return NativeModules.OPSQLite.moveAssetsDatabase(args);
 };
 
+/**
+ * Used to load a dylib file that contains a sqlite 3 extension/plugin
+ * It returns the raw path to the actual file which then needs to be passed to the loadExtension function
+ * Check the docs for more information
+ * @param bundle the iOS bundle identifier of the .framework
+ * @param name the file name of the dylib file
+ * @returns
+ */
 export const getDylibPath = (bundle: string, name: string): string => {
   return NativeModules.OPSQLite.getDylibPath(bundle, name);
 };
diff --git a/src/types.d.ts b/src/types.d.ts
deleted file mode 100644
index 3adb2dd..0000000
--- a/src/types.d.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-type Scalar = string | number | boolean | null | ArrayBuffer | ArrayBufferView;
-
-/**
- * Object returned by SQL Query executions {
- *  insertId: Represent the auto-generated row id if applicable
- *  rowsAffected: Number of affected rows if result of a update query
- *  message: if status === 1, here you will find error description
- *  rows: if status is undefined or 0 this object will contain the query results
- * }
- *
- * @interface QueryResult
- */
-type QueryResult = {
-  insertId?: number;
-  rowsAffected: number;
-  res?: any[];
-  rows: Array<Record<string, Scalar>>;
-  // An array of intermediate results, just values without column names
-  rawRows?: Scalar[][];
-  columnNames?: string[];
-  /**
-   * Query metadata, available only for select query results
-   */
-  metadata?: ColumnMetadata[];
-};
-
-/**
- * Column metadata
- * Describes some information about columns fetched by the query
- */
-type ColumnMetadata = {
-  /** The name used for this column for this result set */
-  name: string;
-  /** The declared column type for this column, when fetched directly from a table or a View resulting from a table column. "UNKNOWN" for dynamic values, like function returned ones. */
-  type: string;
-  /**
-   * The index for this column for this result set*/
-  index: number;
-};
-
-/**
- * Allows the execution of bulk of sql commands
- * inside a transaction
- * If a single query must be executed many times with different arguments, its preferred
- * to declare it a single time, and use an array of array parameters.
- */
-type SQLBatchTuple = [string] | [string, Array<any> | Array<Array<any>>];
-
-type UpdateHookOperation = 'INSERT' | 'DELETE' | 'UPDATE';
-
-/**
- * status: 0 or undefined for correct execution, 1 for error
- * message: if status === 1, here you will find error description
- * rowsAffected: Number of affected rows if status == 0
- */
-type BatchQueryResult = {
-  rowsAffected?: number;
-};
-
-/**
- * Result of loading a file and executing every line as a SQL command
- * Similar to BatchQueryResult
- */
-type FileLoadResult = BatchQueryResult & {
-  commands?: number;
-};
-
-type Transaction = {
-  commit: () => Promise<QueryResult>;
-  execute: (query: string, params?: Scalar[]) => Promise<QueryResult>;
-  rollback: () => Promise<QueryResult>;
-};
-
-type PendingTransaction = {
-  /*
-   * The start function should not throw or return a promise because the
-   * queue just calls it and does not monitor for failures or completions.
-   *
-   * It should catch any errors and call the resolve or reject of the wrapping
-   * promise when complete.
-   *
-   * It should also automatically commit or rollback the transaction if needed
-   */
-  start: () => void;
-};
-
-type PreparedStatement = {
-  bind: (params: any[]) => Promise<void>;
-  execute: () => Promise<QueryResult>;
-};
-
-type DB = {
-  close: () => void;
-  delete: (location?: string) => void;
-  attach: (
-    mainDbName: string,
-    dbNameToAttach: string,
-    alias: string,
-    location?: string
-  ) => void;
-  detach: (mainDbName: string, alias: string) => void;
-  transaction: (fn: (tx: Transaction) => Promise<void>) => Promise<void>;
-  executeSync: (query: string, params?: Scalar[]) => QueryResult;
-  execute: (query: string, params?: Scalar[]) => Promise<QueryResult>;
-  executeWithHostObjects: (
-    query: string,
-    params?: Scalar[]
-  ) => Promise<QueryResult>;
-  executeBatch: (commands: SQLBatchTuple[]) => Promise<BatchQueryResult>;
-  loadFile: (location: string) => Promise<FileLoadResult>;
-  updateHook: (
-    callback?:
-      | ((params: {
-          table: string;
-          operation: UpdateHookOperation;
-          row?: any;
-          rowId: number;
-        }) => void)
-      | null
-  ) => void;
-  commitHook: (callback?: (() => void) | null) => void;
-  rollbackHook: (callback?: (() => void) | null) => void;
-  prepareStatement: (query: string) => PreparedStatement;
-  loadExtension: (path: string, entryPoint?: string) => void;
-  executeRaw: (query: string, params?: Scalar[]) => Promise<any[]>;
-  getDbPath: (location?: string) => string;
-  reactiveExecute: (params: {
-    query: string;
-    arguments: any[];
-    fireOn: {
-      table: string;
-      ids?: number[];
-    }[];
-    callback: (response: any) => void;
-  }) => () => void;
-  /** This function is only available for libsql.
-   * Allows to trigger a sync the database with it's remote replica
-   * In order for this function to work you need to use openSync or openRemote functions
-   * with libsql: true in the package.json
-   *
-   * The database is hosted in turso
-   **/
-  sync: () => void;
-  flushPendingReactiveQueries: () => Promise<void>;
-};
-
-type OPSQLiteProxy = {
-  open: (options: {
-    name: string;
-    location?: string;
-    encryptionKey?: string;
-  }) => DB;
-  openRemote: (options: { url: string; authToken: string }) => DB;
-  openSync: (options: {
-    url: string;
-    authToken: string;
-    name: string;
-    location?: string;
-    syncInterval?: number;
-  }) => DB;
-  isSQLCipher: () => boolean;
-  isLibsql: () => boolean;
-  isIOSEmbedded: () => boolean;
-};