{"version":3,"sources":["../src/index.ts","../src/stack_path.ts","../src/dirname.ts"],"sourcesContent":["// Load the native binding with support for both CJS and ESM\nimport nodeGypBuild from \"node-gyp-build\";\nimport { join } from \"node:path\";\nimport { _dirname } from \"./dirname\";\n\n// Use _dirname() helper that works in both CJS/ESM and Jest\nconst binding = nodeGypBuild(join(_dirname(), \"..\"));\n\n/**\n * Configuration options for opening a database.\n * This interface matches Node.js sqlite module's DatabaseSyncOptions.\n */\nexport interface DatabaseSyncOptions {\n  /** Path to the database file. Use ':memory:' for an in-memory database. */\n  readonly location?: string;\n  /** If true, the database is opened in read-only mode. @default false */\n  readonly readOnly?: boolean;\n  /** If true, foreign key constraints are enforced. @default true */\n  readonly enableForeignKeyConstraints?: boolean;\n  /** \n   * If true, double-quoted string literals are allowed. \n   *\n   * If enabled, double quotes can be misinterpreted as identifiers instead of\n   * string literals, leading to confusing errors. \n   *\n   * **The SQLite documentation strongly recommends avoiding double-quoted\n   * strings entirely.**\n\n   * @see https://sqlite.org/quirks.html#dblquote\n   * @default false \n   */\n  readonly enableDoubleQuotedStringLiterals?: boolean;\n  /**\n   * Sets the busy timeout in milliseconds.\n   * @default 5000\n   */\n  readonly timeout?: number;\n  /** If true, enables loading of SQLite extensions. @default false */\n  readonly allowExtension?: boolean;\n}\n\n/**\n * Options for creating a prepared statement.\n */\nexport interface StatementOptions {\n  /** If true, the prepared statement's expandedSQL property will contain the expanded SQL. @default false */\n  readonly expandedSQL?: boolean;\n  /** If true, anonymous parameters are enabled for the statement. @default false */\n  readonly anonymousParameters?: boolean;\n}\n\n/**\n * A prepared SQL statement that can be executed multiple times with different parameters.\n * This interface represents an instance of the StatementSync class.\n */\nexport interface StatementSyncInstance {\n  /** The original SQL source string. */\n  readonly sourceSQL: string;\n  /** The expanded SQL string with bound parameters, if expandedSQL option was set. */\n  readonly expandedSQL: string | undefined;\n  /**\n   * This method executes a prepared statement and returns an object.\n   * @param parameters Optional named and anonymous parameters to bind to the statement.\n   * @returns An object with the number of changes and the last insert rowid.\n   */\n  run(...parameters: any[]): {\n    changes: number;\n    lastInsertRowid: number | bigint;\n  };\n  /**\n   * This method executes a prepared statement and returns the first result row.\n   * @param parameters Optional named and anonymous parameters to bind to the statement.\n   * @returns The first row from the query results, or undefined if no rows.\n   */\n  get(...parameters: any[]): any;\n  /**\n   * This method executes a prepared statement and returns all results as an array.\n   * @param parameters Optional named and anonymous parameters to bind to the statement.\n   * @returns An array of row objects from the query results.\n   */\n  all(...parameters: any[]): any[];\n  /**\n   * This method executes a prepared statement and returns an iterable iterator of objects.\n   * Each object represents a row from the query results.\n   * @param parameters Optional named and anonymous parameters to bind to the statement.\n   * @returns An iterable iterator of row objects.\n   */\n  iterate(...parameters: any[]): IterableIterator<any>;\n  /**\n   * Set whether to read integer values as JavaScript BigInt.\n   * @param readBigInts If true, read integers as BigInts. @default false\n   */\n  setReadBigInts(readBigInts: boolean): void;\n  /**\n   * Set whether to allow bare named parameters in SQL.\n   * @param allowBareNamedParameters If true, allows bare named parameters. @default false\n   */\n  setAllowBareNamedParameters(allowBareNamedParameters: boolean): void;\n  /**\n   * Set whether to return results as arrays rather than objects.\n   * @param returnArrays If true, return results as arrays. @default false\n   */\n  setReturnArrays(returnArrays: boolean): void;\n  /**\n   * Returns an array of objects, each representing a column in the statement's result set.\n   * Each object has a 'name' property for the column name and a 'type' property for the SQLite type.\n   * @returns Array of column metadata objects.\n   */\n  columns(): Array<{ name: string; type?: string }>;\n  /**\n   * Finalizes the prepared statement and releases its resources.\n   * Called automatically by Symbol.dispose.\n   */\n  finalize(): void;\n  /** Dispose of the statement resources using the explicit resource management protocol. */\n  [Symbol.dispose](): void;\n}\n\nexport interface UserFunctionOptions {\n  /** If `true`, sets the `SQLITE_DETERMINISTIC` flag. @default false */\n  readonly deterministic?: boolean;\n  /** If `true`, sets the `SQLITE_DIRECTONLY` flag. @default false */\n  readonly directOnly?: boolean;\n  /** If `true`, converts integer arguments to `BigInt`s. @default false */\n  readonly useBigIntArguments?: boolean;\n  /** If `true`, allows function to be invoked with variable arguments. @default false */\n  readonly varargs?: boolean;\n}\n\nexport interface AggregateOptions {\n  /** The initial value for the aggregation. */\n  readonly start?: any;\n  /** Function called for each row to update the aggregate state. */\n  readonly step: (accumulator: any, ...args: any[]) => any;\n  /** Optional function for window function support to reverse a step. */\n  readonly inverse?: (accumulator: any, ...args: any[]) => any;\n  /** Optional function to compute the final result from the accumulator. */\n  readonly result?: (accumulator: any) => any;\n  /** If `true`, sets the `SQLITE_DETERMINISTIC` flag. @default false */\n  readonly deterministic?: boolean;\n  /** If `true`, sets the `SQLITE_DIRECTONLY` flag. @default false */\n  readonly directOnly?: boolean;\n  /** If `true`, converts integer arguments to `BigInt`s. @default false */\n  readonly useBigIntArguments?: boolean;\n  /** If `true`, allows function to be invoked with variable arguments. @default false */\n  readonly varargs?: boolean;\n}\n\nexport interface SessionOptions {\n  /** The table to track changes for. If omitted, all tables are tracked. */\n  readonly table?: string;\n  /** The database name. @default \"main\" */\n  readonly db?: string;\n}\n\nexport interface Session {\n  /**\n   * Generate a changeset containing all changes recorded by the session.\n   * @returns A Buffer containing the changeset data.\n   */\n  changeset(): Buffer;\n  /**\n   * Generate a patchset containing all changes recorded by the session.\n   * @returns A Buffer containing the patchset data.\n   */\n  patchset(): Buffer;\n  /**\n   * Close the session and release its resources.\n   */\n  close(): void;\n}\n\nexport interface ChangesetApplyOptions {\n  /**\n   * Function called when a conflict is detected during changeset application.\n   * @param conflictType The type of conflict (SQLITE_CHANGESET_CONFLICT, etc.)\n   * @returns One of SQLITE_CHANGESET_OMIT, SQLITE_CHANGESET_REPLACE, or SQLITE_CHANGESET_ABORT\n   */\n  readonly onConflict?: (conflictType: number) => number;\n  /**\n   * Function called to filter which tables to apply changes to.\n   * @param tableName The name of the table\n   * @returns true to include the table, false to skip it\n   */\n  readonly filter?: (tableName: string) => boolean;\n}\n\n/**\n * Represents a SQLite database connection.\n * This interface represents an instance of the DatabaseSync class.\n */\nexport interface DatabaseSyncInstance {\n  /** Indicates whether the database connection is open. */\n  readonly isOpen: boolean;\n  /** Indicates whether a transaction is currently active. */\n  readonly isTransaction: boolean;\n\n  /**\n   * Opens a database connection. This method is called automatically when creating\n   * a DatabaseSync instance, so typically should not be called directly.\n   * @param configuration Optional configuration for opening the database.\n   */\n  open(configuration?: DatabaseSyncOptions): void;\n  /**\n   * Closes the database connection. This method should be called to ensure that\n   * the database connection is properly cleaned up. Once a database is closed,\n   * it cannot be used again.\n   */\n  close(): void;\n  /**\n   * Returns the location of the database file. For attached databases, you can specify\n   * the database name. Returns null for in-memory databases.\n   * @param dbName The name of the database. Defaults to 'main' (the primary database).\n   * @returns The file path of the database, or null for in-memory databases.\n   */\n  location(dbName?: string): string | null;\n  /**\n   * Compiles an SQL statement and returns a StatementSyncInstance object.\n   * @param sql The SQL statement to prepare.\n   * @param options Optional configuration for the statement.\n   * @returns A StatementSyncInstance object that can be executed multiple times.\n   */\n  prepare(sql: string, options?: StatementOptions): StatementSyncInstance;\n  /**\n   * This method allows one or more SQL statements to be executed without\n   * returning any results. This is useful for commands like CREATE TABLE,\n   * INSERT, UPDATE, or DELETE.\n   * @param sql The SQL statement(s) to execute.\n   */\n  exec(sql: string): void;\n\n  /**\n   * This method creates SQLite user-defined functions, wrapping sqlite3_create_function_v2().\n   * @param name The name of the SQLite function to create.\n   * @param func The JavaScript function to call when the SQLite function is invoked.\n   */\n  function(name: string, func: Function): void;\n  /**\n   * This method creates SQLite user-defined functions, wrapping sqlite3_create_function_v2().\n   * @param name The name of the SQLite function to create.\n   * @param options Optional configuration settings.\n   * @param func The JavaScript function to call when the SQLite function is invoked.\n   */\n  function(name: string, options: UserFunctionOptions, func: Function): void;\n\n  /**\n   * This method creates SQLite aggregate functions, wrapping sqlite3_create_window_function().\n   * @param name The name of the SQLite aggregate function to create.\n   * @param options Configuration object containing step function and other settings.\n   */\n  aggregate(name: string, options: AggregateOptions): void;\n  /**\n   * Create a new session to record database changes.\n   * @param options Optional configuration for the session.\n   * @returns A Session object for recording changes.\n   */\n  createSession(options?: SessionOptions): Session;\n  /**\n   * Apply a changeset to the database.\n   * @param changeset The changeset data to apply.\n   * @param options Optional configuration for applying the changeset.\n   * @returns true if successful, false if aborted.\n   */\n  applyChangeset(changeset: Buffer, options?: ChangesetApplyOptions): boolean;\n  /**\n   * Enables or disables the loading of SQLite extensions.\n   * @param enable If true, enables extension loading. If false, disables it.\n   */\n  enableLoadExtension(enable: boolean): void;\n  /**\n   * Loads an SQLite extension from the specified file path.\n   * @param path The path to the extension library.\n   * @param entryPoint Optional entry point function name. If not provided, uses the default entry point.\n   */\n  loadExtension(path: string, entryPoint?: string): void;\n\n  /**\n   * Makes a backup of the database. This method abstracts the sqlite3_backup_init(),\n   * sqlite3_backup_step() and sqlite3_backup_finish() functions.\n   *\n   * The backed-up database can be used normally during the backup process. Mutations\n   * coming from the same connection will be reflected in the backup right away.\n   * However, mutations from other connections will cause the backup process to restart.\n   *\n   * @param path The path where the backup will be created. If the file already exists, the contents will be overwritten.\n   * @param options Optional configuration for the backup operation.\n   * @param options.rate Number of pages to be transmitted in each batch of the backup. @default 100\n   * @param options.source Name of the source database. This can be 'main' (the default primary database) or any other database that have been added with ATTACH DATABASE. @default 'main'\n   * @param options.target Name of the target database. This can be 'main' (the default primary database) or any other database that have been added with ATTACH DATABASE. @default 'main'\n   * @param options.progress Callback function that will be called with the number of pages copied and the total number of pages.\n   * @returns A promise that resolves when the backup is completed and rejects if an error occurs.\n   *\n   * @example\n   * // Basic backup\n   * await db.backup('./backup.db');\n   *\n   * @example\n   * // Backup with progress\n   * await db.backup('./backup.db', {\n   *   rate: 10,\n   *   progress: ({ totalPages, remainingPages }) => {\n   *     console.log(`Progress: ${totalPages - remainingPages}/${totalPages}`);\n   *   }\n   * });\n   */\n  backup(\n    path: string | Buffer | URL,\n    options?: {\n      rate?: number;\n      source?: string;\n      target?: string;\n      progress?: (info: { totalPages: number; remainingPages: number }) => void;\n    },\n  ): Promise<number>;\n\n  /** Dispose of the database resources using the explicit resource management protocol. */\n  [Symbol.dispose](): void;\n}\n\n/**\n * The main SQLite module interface.\n */\nexport interface SqliteModule {\n  /**\n   * The DatabaseSync class represents a synchronous connection to a SQLite database.\n   * All operations are performed synchronously, blocking until completion.\n   */\n  DatabaseSync: new (\n    location?: string | Buffer | URL,\n    options?: DatabaseSyncOptions,\n  ) => DatabaseSyncInstance;\n  /**\n   * The StatementSync class represents a synchronous prepared statement.\n   * This class should not be instantiated directly; use Database.prepare() instead.\n   */\n  StatementSync: new (\n    database: DatabaseSyncInstance,\n    sql: string,\n    options?: StatementOptions,\n  ) => StatementSyncInstance;\n  /**\n   * The Session class for recording database changes.\n   * This class should not be instantiated directly; use Database.createSession() instead.\n   */\n  Session: new () => Session;\n  /**\n   * SQLite constants for various operations and flags.\n   */\n  constants: {\n    /** Open database for reading only. */\n    SQLITE_OPEN_READONLY: number;\n    /** Open database for reading and writing. */\n    SQLITE_OPEN_READWRITE: number;\n    /** Create database if it doesn't exist. */\n    SQLITE_OPEN_CREATE: number;\n    // Changeset constants\n    /** Skip conflicting changes. */\n    SQLITE_CHANGESET_OMIT: number;\n    /** Replace conflicting changes. */\n    SQLITE_CHANGESET_REPLACE: number;\n    /** Abort on conflict. */\n    SQLITE_CHANGESET_ABORT: number;\n    /** Data conflict type. */\n    SQLITE_CHANGESET_DATA: number;\n    /** Row not found conflict. */\n    SQLITE_CHANGESET_NOTFOUND: number;\n    /** General conflict. */\n    SQLITE_CHANGESET_CONFLICT: number;\n    /** Constraint violation. */\n    SQLITE_CHANGESET_CONSTRAINT: number;\n    /** Foreign key constraint violation. */\n    SQLITE_CHANGESET_FOREIGN_KEY: number;\n    // ... more constants\n  };\n}\n\n// Add Symbol.dispose to the native classes\nif (binding.DatabaseSync && typeof Symbol.dispose !== \"undefined\") {\n  binding.DatabaseSync.prototype[Symbol.dispose] = function () {\n    try {\n      this.close();\n    } catch {\n      // Ignore errors during disposal\n    }\n  };\n}\n\nif (binding.StatementSync && typeof Symbol.dispose !== \"undefined\") {\n  binding.StatementSync.prototype[Symbol.dispose] = function () {\n    try {\n      this.finalize();\n    } catch {\n      // Ignore errors during disposal\n    }\n  };\n}\n\n// Export the native binding with TypeScript types\n\n/**\n * The DatabaseSync class represents a synchronous connection to a SQLite database.\n * All database operations are performed synchronously, blocking the thread until completion.\n *\n * @example\n * ```typescript\n * import { DatabaseSync } from '@photostructure/sqlite';\n *\n * // Create an in-memory database\n * const db = new DatabaseSync(':memory:');\n *\n * // Create a file-based database\n * const fileDb = new DatabaseSync('./mydata.db');\n *\n * // Create with options\n * const readOnlyDb = new DatabaseSync('./data.db', { readOnly: true });\n * ```\n */\nexport const DatabaseSync =\n  binding.DatabaseSync as SqliteModule[\"DatabaseSync\"];\n\n/**\n * The StatementSync class represents a prepared SQL statement.\n * This class should not be instantiated directly; use DatabaseSync.prepare() instead.\n *\n * @example\n * ```typescript\n * const stmt = db.prepare('SELECT * FROM users WHERE id = ?');\n * const user = stmt.get(123);\n * stmt.finalize();\n * ```\n */\nexport const StatementSync =\n  binding.StatementSync as SqliteModule[\"StatementSync\"];\n\n/**\n * The Session class for recording database changes.\n * This class should not be instantiated directly; use DatabaseSync.createSession() instead.\n *\n * @example\n * ```typescript\n * const session = db.createSession({ table: 'users' });\n * // Make some changes to the users table\n * const changeset = session.changeset();\n * session.close();\n * ```\n */\nexport const Session = binding.Session as SqliteModule[\"Session\"];\n\n/**\n * SQLite constants for various operations and flags.\n *\n * @example\n * ```typescript\n * import { constants } from '@photostructure/sqlite';\n *\n * const db = new DatabaseSync('./data.db', {\n *   readOnly: true,\n *   // Uses SQLITE_OPEN_READONLY internally\n * });\n * ```\n */\nexport const constants = binding.constants as SqliteModule[\"constants\"];\n\n// Default export for CommonJS compatibility\nexport default binding as SqliteModule;\n","import { dirname } from \"node:path\";\n\nexport function getCallerDirname(): string {\n  const e = new Error();\n  if (e.stack == null) {\n    Error.captureStackTrace(e);\n  }\n  return dirname(extractCallerPath(e.stack as string));\n}\n\n// Comprehensive regex patterns for different stack frame formats\nconst patterns =\n  process.platform === \"win32\"\n    ? [\n        // Standard: \"at functionName (C:\\path\\file.js:1:1)\"\n        /\\bat\\s.+?\\((?<path>[A-Z]:\\\\.+):\\d+:\\d+\\)$/,\n        // direct: \"at C:\\path\\file.js:1:1\"\n        /\\bat\\s(?<path>[A-Z]:\\\\.+):\\d+:\\d+$/,\n        // UNC: \"at functionName (\\\\server\\share\\path\\file.js:1:1)\"\n        /\\bat\\s.+?\\((?<path>\\\\\\\\.+):\\d+:\\d+\\)$/,\n        // direct: \"at \\\\server\\share\\path\\file.js:1:1\"\n        /\\bat\\s(?<path>\\\\\\\\.+):\\d+:\\d+$/,\n      ]\n    : [\n        // Standard: \"at functionName (/path/file.js:1:1)\"\n        /\\bat\\s.+?\\((?<path>\\/.+?):\\d+:\\d+\\)$/,\n        // Anonymous or direct: \"at /path/file.js:1:1\"\n        /\\bat\\s(.+[^/]\\s)?(?<path>\\/.+?):\\d+:\\d+$/,\n      ];\n\nconst MaybeUrlRE = /^[a-z]{2,5}:\\/\\//i;\n\n// only exposed for tests:\nexport function extractCallerPath(stack: string): string {\n  const frames = stack.split(\"\\n\").filter(Boolean);\n\n  // First find getCallerDirname() in the stack:\n  const callerFrame = frames.findIndex((frame) =>\n    frame.includes(\"getCallerDirname\"),\n  );\n  if (callerFrame === -1) {\n    throw new Error(\"Invalid stack trace format: missing caller frame\");\n  }\n  for (let i = callerFrame + 1; i < frames.length; i++) {\n    const frame = frames[i];\n    for (const pattern of patterns) {\n      const g = frame?.trim().match(pattern)?.groups;\n      if (g != null && g[\"path\"]) {\n        const path = g[\"path\"];\n        // Windows requires us to check if it's a reasonable URL, as URL accepts\n        // \"C:\\\\path\\\\file.txt\" as valid (!!)\n        if (MaybeUrlRE.test(path)) {\n          try {\n            return new URL(path).pathname;\n          } catch {\n            // ignore\n          }\n        }\n        return path;\n      }\n    }\n  }\n  throw new Error(\"Invalid stack trace format: no parsable frames\");\n}\n","import { getCallerDirname } from \"./stack_path\";\n\n// Thanks to tsup shims, __dirname should always be defined except when run by\n// jest (which will use the stack_path shim)\nexport function _dirname() {\n  try {\n    if (typeof __dirname !== \"undefined\") return __dirname;\n  } catch {\n    // ignore\n  }\n  // we must be in jest. Use the stack_path ~~hack~~ shim:\n  return getCallerDirname();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,4BAAyB;AACzB,IAAAA,oBAAqB;;;ACFrB,uBAAwB;AAEjB,SAAS,mBAA2B;AACzC,QAAM,IAAI,IAAI,MAAM;AACpB,MAAI,EAAE,SAAS,MAAM;AACnB,UAAM,kBAAkB,CAAC;AAAA,EAC3B;AACA,aAAO,0BAAQ,kBAAkB,EAAE,KAAe,CAAC;AACrD;AAGA,IAAM,WACJ,QAAQ,aAAa,UACjB;AAAA;AAAA,EAEE;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF,IACA;AAAA;AAAA,EAEE;AAAA;AAAA,EAEA;AACF;AAEN,IAAM,aAAa;AAGZ,SAAS,kBAAkB,OAAuB;AACvD,QAAM,SAAS,MAAM,MAAM,IAAI,EAAE,OAAO,OAAO;AAG/C,QAAM,cAAc,OAAO;AAAA,IAAU,CAAC,UACpC,MAAM,SAAS,kBAAkB;AAAA,EACnC;AACA,MAAI,gBAAgB,IAAI;AACtB,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,WAAS,IAAI,cAAc,GAAG,IAAI,OAAO,QAAQ,KAAK;AACpD,UAAM,QAAQ,OAAO,CAAC;AACtB,eAAW,WAAW,UAAU;AAC9B,YAAM,IAAI,OAAO,KAAK,EAAE,MAAM,OAAO,GAAG;AACxC,UAAI,KAAK,QAAQ,EAAE,MAAM,GAAG;AAC1B,cAAM,OAAO,EAAE,MAAM;AAGrB,YAAI,WAAW,KAAK,IAAI,GAAG;AACzB,cAAI;AACF,mBAAO,IAAI,IAAI,IAAI,EAAE;AAAA,UACvB,QAAQ;AAAA,UAER;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,MAAM,gDAAgD;AAClE;;;AC3DO,SAAS,WAAW;AACzB,MAAI;AACF,QAAI,OAAO,cAAc,YAAa,QAAO;AAAA,EAC/C,QAAQ;AAAA,EAER;AAEA,SAAO,iBAAiB;AAC1B;;;AFNA,IAAM,cAAU,sBAAAC,aAAa,wBAAK,SAAS,GAAG,IAAI,CAAC;AAmXnD,IAAI,QAAQ,gBAAgB,OAAO,OAAO,YAAY,aAAa;AACjE,UAAQ,aAAa,UAAU,OAAO,OAAO,IAAI,WAAY;AAC3D,QAAI;AACF,WAAK,MAAM;AAAA,IACb,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEA,IAAI,QAAQ,iBAAiB,OAAO,OAAO,YAAY,aAAa;AAClE,UAAQ,cAAc,UAAU,OAAO,OAAO,IAAI,WAAY;AAC5D,QAAI;AACF,WAAK,SAAS;AAAA,IAChB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAsBO,IAAM,eACX,QAAQ;AAaH,IAAM,gBACX,QAAQ;AAcH,IAAM,UAAU,QAAQ;AAexB,IAAM,YAAY,QAAQ;AAGjC,IAAO,gBAAQ;","names":["import_node_path","nodeGypBuild"]}