@photostructure/sqlite 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +36 -2
  2. package/README.md +45 -484
  3. package/SECURITY.md +27 -84
  4. package/binding.gyp +69 -22
  5. package/dist/index.cjs +185 -18
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +552 -100
  8. package/dist/index.d.mts +552 -100
  9. package/dist/index.d.ts +552 -100
  10. package/dist/index.mjs +183 -18
  11. package/dist/index.mjs.map +1 -1
  12. package/package.json +51 -41
  13. package/prebuilds/darwin-arm64/@photostructure+sqlite.glibc.node +0 -0
  14. package/prebuilds/darwin-x64/@photostructure+sqlite.glibc.node +0 -0
  15. package/prebuilds/linux-arm64/@photostructure+sqlite.glibc.node +0 -0
  16. package/prebuilds/linux-arm64/@photostructure+sqlite.musl.node +0 -0
  17. package/prebuilds/linux-x64/@photostructure+sqlite.glibc.node +0 -0
  18. package/prebuilds/linux-x64/@photostructure+sqlite.musl.node +0 -0
  19. package/prebuilds/test_extension.so +0 -0
  20. package/prebuilds/win32-x64/@photostructure+sqlite.glibc.node +0 -0
  21. package/src/aggregate_function.cpp +503 -235
  22. package/src/aggregate_function.h +57 -42
  23. package/src/binding.cpp +117 -14
  24. package/src/dirname.ts +1 -1
  25. package/src/index.ts +122 -332
  26. package/src/lru-cache.ts +84 -0
  27. package/src/shims/env-inl.h +6 -15
  28. package/src/shims/node_errors.h +4 -0
  29. package/src/shims/sqlite_errors.h +162 -0
  30. package/src/shims/util.h +29 -4
  31. package/src/sql-tag-store.ts +140 -0
  32. package/src/sqlite_exception.h +49 -0
  33. package/src/sqlite_impl.cpp +711 -127
  34. package/src/sqlite_impl.h +84 -6
  35. package/src/{stack_path.ts → stack-path.ts} +7 -1
  36. package/src/types/aggregate-options.ts +22 -0
  37. package/src/types/changeset-apply-options.ts +18 -0
  38. package/src/types/database-sync-instance.ts +203 -0
  39. package/src/types/database-sync-options.ts +69 -0
  40. package/src/types/session-options.ts +10 -0
  41. package/src/types/sql-tag-store-instance.ts +51 -0
  42. package/src/types/sqlite-authorization-actions.ts +77 -0
  43. package/src/types/sqlite-authorization-results.ts +15 -0
  44. package/src/types/sqlite-changeset-conflict-types.ts +19 -0
  45. package/src/types/sqlite-changeset-resolution.ts +15 -0
  46. package/src/types/sqlite-open-flags.ts +50 -0
  47. package/src/types/statement-sync-instance.ts +73 -0
  48. package/src/types/user-functions-options.ts +14 -0
  49. package/src/upstream/node_sqlite.cc +960 -259
  50. package/src/upstream/node_sqlite.h +127 -2
  51. package/src/upstream/sqlite.js +1 -14
  52. package/src/upstream/sqlite3.c +4510 -1411
  53. package/src/upstream/sqlite3.h +390 -195
  54. package/src/upstream/sqlite3ext.h +7 -0
  55. package/src/user_function.cpp +88 -36
  56. package/src/user_function.h +2 -1
package/dist/index.d.mts CHANGED
@@ -1,44 +1,103 @@
1
1
  /**
2
- * Configuration options for opening a database.
3
- * This interface matches Node.js sqlite module's DatabaseSyncOptions.
2
+ * Configuration options for creating SQLite aggregate functions.
3
+ * Used with `DatabaseSync.aggregate()` to define custom aggregate operations.
4
4
  */
5
- interface DatabaseSyncOptions {
6
- /** Path to the database file. Use ':memory:' for an in-memory database. */
7
- readonly location?: string;
8
- /** If true, the database is opened in read-only mode. @default false */
9
- readonly readOnly?: boolean;
10
- /** If true, foreign key constraints are enforced. @default true */
11
- readonly enableForeignKeyConstraints?: boolean;
5
+ interface AggregateOptions {
6
+ /** The initial value for the aggregation. */
7
+ readonly start?: any;
8
+ /** Function called for each row to update the aggregate state. */
9
+ readonly step: (accumulator: any, ...args: any[]) => any;
10
+ /** Optional function for window function support to reverse a step. */
11
+ readonly inverse?: (accumulator: any, ...args: any[]) => any;
12
+ /** Optional function to compute the final result from the accumulator. */
13
+ readonly result?: (accumulator: any) => any;
14
+ /** If `true`, sets the `SQLITE_DETERMINISTIC` flag. @default false */
15
+ readonly deterministic?: boolean;
16
+ /** If `true`, sets the `SQLITE_DIRECTONLY` flag. @default false */
17
+ readonly directOnly?: boolean;
18
+ /** If `true`, converts integer arguments to `BigInt`s. @default false */
19
+ readonly useBigIntArguments?: boolean;
20
+ /** If `true`, allows function to be invoked with variable arguments. @default false */
21
+ readonly varargs?: boolean;
22
+ }
23
+
24
+ /**
25
+ * Configuration options for applying changesets to a database.
26
+ * Used with `DatabaseSync.applyChangeset()` to handle conflicts and filter tables.
27
+ */
28
+ interface ChangesetApplyOptions {
12
29
  /**
13
- * If true, double-quoted string literals are allowed.
14
- *
15
- * If enabled, double quotes can be misinterpreted as identifiers instead of
16
- * string literals, leading to confusing errors.
17
- *
18
- * **The SQLite documentation strongly recommends avoiding double-quoted
19
- * strings entirely.**
20
-
21
- * @see https://sqlite.org/quirks.html#dblquote
22
- * @default false
30
+ * Function called when a conflict is detected during changeset application.
31
+ * @param conflictType The type of conflict (SQLITE_CHANGESET_CONFLICT, etc.)
32
+ * @returns One of SQLITE_CHANGESET_OMIT, SQLITE_CHANGESET_REPLACE, or SQLITE_CHANGESET_ABORT
23
33
  */
24
- readonly enableDoubleQuotedStringLiterals?: boolean;
34
+ readonly onConflict?: (conflictType: number) => number;
25
35
  /**
26
- * Sets the busy timeout in milliseconds.
27
- * @default 5000
36
+ * Function called to filter which tables to apply changes to.
37
+ * @param tableName The name of the table
38
+ * @returns true to include the table, false to skip it
28
39
  */
29
- readonly timeout?: number;
30
- /** If true, enables loading of SQLite extensions. @default false */
31
- readonly allowExtension?: boolean;
40
+ readonly filter?: (tableName: string) => boolean;
32
41
  }
42
+
33
43
  /**
34
- * Options for creating a prepared statement.
44
+ * Configuration options for creating SQLite sessions.
45
+ * Used with `DatabaseSync.createSession()` to track database changes.
35
46
  */
36
- interface StatementOptions {
37
- /** If true, the prepared statement's expandedSQL property will contain the expanded SQL. @default false */
38
- readonly expandedSQL?: boolean;
39
- /** If true, anonymous parameters are enabled for the statement. @default false */
40
- readonly anonymousParameters?: boolean;
47
+ interface SessionOptions {
48
+ /** The table to track changes for. If omitted, all tables are tracked. */
49
+ readonly table?: string;
50
+ /** The database name. @default "main" */
51
+ readonly db?: string;
41
52
  }
53
+
54
+ /**
55
+ * SQLTagStore provides cached prepared statements via tagged template syntax.
56
+ * Statements are cached by their SQL string and reused across invocations.
57
+ */
58
+ interface SQLTagStoreInstance {
59
+ /** Returns the associated database instance. */
60
+ readonly db: DatabaseSyncInstance;
61
+ /** Returns the maximum capacity of the statement cache. */
62
+ readonly capacity: number;
63
+ /**
64
+ * Returns the current number of cached statements.
65
+ */
66
+ size(): number;
67
+ /**
68
+ * Clears all cached statements.
69
+ */
70
+ clear(): void;
71
+ /**
72
+ * Execute an INSERT, UPDATE, DELETE or other statement that doesn't return rows.
73
+ * @param strings Template literal strings array.
74
+ * @param values Values to bind to the placeholders.
75
+ * @returns An object with `changes` and `lastInsertRowid`.
76
+ */
77
+ run(strings: TemplateStringsArray, ...values: unknown[]): {
78
+ changes: number;
79
+ lastInsertRowid: number | bigint;
80
+ };
81
+ /**
82
+ * Execute a query and return the first row, or undefined if no rows.
83
+ * @param strings Template literal strings array.
84
+ * @param values Values to bind to the placeholders.
85
+ */
86
+ get(strings: TemplateStringsArray, ...values: unknown[]): unknown;
87
+ /**
88
+ * Execute a query and return all rows as an array.
89
+ * @param strings Template literal strings array.
90
+ * @param values Values to bind to the placeholders.
91
+ */
92
+ all(strings: TemplateStringsArray, ...values: unknown[]): unknown[];
93
+ /**
94
+ * Execute a query and return an iterator over the rows.
95
+ * @param strings Template literal strings array.
96
+ * @param values Values to bind to the placeholders.
97
+ */
98
+ iterate(strings: TemplateStringsArray, ...values: unknown[]): IterableIterator<unknown>;
99
+ }
100
+
42
101
  /**
43
102
  * A prepared SQL statement that can be executed multiple times with different parameters.
44
103
  * This interface represents an instance of the StatementSync class.
@@ -48,6 +107,8 @@ interface StatementSyncInstance {
48
107
  readonly sourceSQL: string;
49
108
  /** The expanded SQL string with bound parameters, if expandedSQL option was set. */
50
109
  readonly expandedSQL: string | undefined;
110
+ /** Whether this statement has been finalized. */
111
+ readonly finalized: boolean;
51
112
  /**
52
113
  * This method executes a prepared statement and returns an object.
53
114
  * @param parameters Optional named and anonymous parameters to bind to the statement.
@@ -86,6 +147,11 @@ interface StatementSyncInstance {
86
147
  * @param allowBareNamedParameters If true, allows bare named parameters. @default false
87
148
  */
88
149
  setAllowBareNamedParameters(allowBareNamedParameters: boolean): void;
150
+ /**
151
+ * Set whether to allow unknown named parameters in SQL.
152
+ * @param enabled If true, unknown named parameters are ignored. If false, they throw an error. @default false
153
+ */
154
+ setAllowUnknownNamedParameters(enabled: boolean): void;
89
155
  /**
90
156
  * Set whether to return results as arrays rather than objects.
91
157
  * @param returnArrays If true, return results as arrays. @default false
@@ -108,6 +174,11 @@ interface StatementSyncInstance {
108
174
  /** Dispose of the statement resources using the explicit resource management protocol. */
109
175
  [Symbol.dispose](): void;
110
176
  }
177
+
178
+ /**
179
+ * Configuration options for creating SQLite user-defined functions.
180
+ * Used with `DatabaseSync.function()` to customize function behavior.
181
+ */
111
182
  interface UserFunctionOptions {
112
183
  /** If `true`, sets the `SQLITE_DETERMINISTIC` flag. @default false */
113
184
  readonly deterministic?: boolean;
@@ -118,44 +189,7 @@ interface UserFunctionOptions {
118
189
  /** If `true`, allows function to be invoked with variable arguments. @default false */
119
190
  readonly varargs?: boolean;
120
191
  }
121
- interface AggregateOptions {
122
- /** The initial value for the aggregation. */
123
- readonly start?: any;
124
- /** Function called for each row to update the aggregate state. */
125
- readonly step: (accumulator: any, ...args: any[]) => any;
126
- /** Optional function for window function support to reverse a step. */
127
- readonly inverse?: (accumulator: any, ...args: any[]) => any;
128
- /** Optional function to compute the final result from the accumulator. */
129
- readonly result?: (accumulator: any) => any;
130
- /** If `true`, sets the `SQLITE_DETERMINISTIC` flag. @default false */
131
- readonly deterministic?: boolean;
132
- /** If `true`, sets the `SQLITE_DIRECTONLY` flag. @default false */
133
- readonly directOnly?: boolean;
134
- /** If `true`, converts integer arguments to `BigInt`s. @default false */
135
- readonly useBigIntArguments?: boolean;
136
- /** If `true`, allows function to be invoked with variable arguments. @default false */
137
- readonly varargs?: boolean;
138
- }
139
- interface SessionOptions {
140
- /** The table to track changes for. If omitted, all tables are tracked. */
141
- readonly table?: string;
142
- /** The database name. @default "main" */
143
- readonly db?: string;
144
- }
145
- interface ChangesetApplyOptions {
146
- /**
147
- * Function called when a conflict is detected during changeset application.
148
- * @param conflictType The type of conflict (SQLITE_CHANGESET_CONFLICT, etc.)
149
- * @returns One of SQLITE_CHANGESET_OMIT, SQLITE_CHANGESET_REPLACE, or SQLITE_CHANGESET_ABORT
150
- */
151
- readonly onConflict?: (conflictType: number) => number;
152
- /**
153
- * Function called to filter which tables to apply changes to.
154
- * @param tableName The name of the table
155
- * @returns true to include the table, false to skip it
156
- */
157
- readonly filter?: (tableName: string) => boolean;
158
- }
192
+
159
193
  /**
160
194
  * Represents a SQLite database connection.
161
195
  * This interface represents an instance of the DatabaseSync class.
@@ -166,11 +200,10 @@ interface DatabaseSyncInstance {
166
200
  /** Indicates whether a transaction is currently active. */
167
201
  readonly isTransaction: boolean;
168
202
  /**
169
- * Opens a database connection. This method is called automatically when creating
170
- * a DatabaseSync instance, so typically should not be called directly.
171
- * @param configuration Optional configuration for opening the database.
203
+ * Opens a database connection. This method should only be used when the database
204
+ * was created with { open: false }. An exception is thrown if the database is already open.
172
205
  */
173
- open(configuration?: DatabaseSyncOptions): void;
206
+ open(): void;
174
207
  /**
175
208
  * Closes the database connection. This method should be called to ensure that
176
209
  * the database connection is properly cleaned up. Once a database is closed,
@@ -223,6 +256,18 @@ interface DatabaseSyncInstance {
223
256
  * @returns A Session object for recording changes.
224
257
  */
225
258
  createSession(options?: SessionOptions): Session;
259
+ /**
260
+ * Create a new SQLTagStore for cached prepared statements via tagged template syntax.
261
+ * @param capacity Optional maximum number of statements to cache. @default 1000
262
+ * @returns A SQLTagStore instance.
263
+ * @example
264
+ * ```typescript
265
+ * const sql = db.createTagStore();
266
+ * sql.run`INSERT INTO users VALUES (${id}, ${name})`;
267
+ * const user = sql.get`SELECT * FROM users WHERE id = ${id}`;
268
+ * ```
269
+ */
270
+ createTagStore(capacity?: number): SQLTagStoreInstance;
226
271
  /**
227
272
  * Apply a changeset to the database.
228
273
  * @param changeset The changeset data to apply.
@@ -241,6 +286,47 @@ interface DatabaseSyncInstance {
241
286
  * @param entryPoint Optional entry point function name. If not provided, uses the default entry point.
242
287
  */
243
288
  loadExtension(path: string, entryPoint?: string): void;
289
+ /**
290
+ * Enables or disables the defensive flag. When the defensive flag is active,
291
+ * language features that allow ordinary SQL to deliberately corrupt the
292
+ * database file are disabled.
293
+ * @param active Whether to enable or disable the defensive flag.
294
+ * @see https://sqlite.org/c3ref/c_dbconfig_defensive.html
295
+ */
296
+ enableDefensive(active: boolean): void;
297
+ /**
298
+ * Sets an authorization callback that is invoked before each SQL operation.
299
+ * The authorizer can allow, deny, or ignore each operation.
300
+ *
301
+ * @param callback The authorization callback function, or null to remove the authorizer.
302
+ * - actionCode: The action being requested (e.g., SQLITE_SELECT, SQLITE_INSERT)
303
+ * - param1: First parameter (varies by action, often table name)
304
+ * - param2: Second parameter (varies by action, often column name)
305
+ * - param3: Third parameter (usually database name like "main")
306
+ * - param4: Fourth parameter (trigger or view name if applicable)
307
+ *
308
+ * The callback must return one of:
309
+ * - constants.SQLITE_OK: Allow the operation
310
+ * - constants.SQLITE_DENY: Deny the operation and abort the SQL statement
311
+ * - constants.SQLITE_IGNORE: Silently ignore/skip the operation
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * // Block all DELETE operations
316
+ * db.setAuthorizer((actionCode, table, column, dbName, trigger) => {
317
+ * if (actionCode === constants.SQLITE_DELETE) {
318
+ * return constants.SQLITE_DENY;
319
+ * }
320
+ * return constants.SQLITE_OK;
321
+ * });
322
+ *
323
+ * // Remove the authorizer
324
+ * db.setAuthorizer(null);
325
+ * ```
326
+ *
327
+ * @see https://sqlite.org/c3ref/set_authorizer.html
328
+ */
329
+ setAuthorizer(callback: ((actionCode: number, param1: string | null, param2: string | null, param3: string | null, param4: string | null) => number) | null): void;
244
330
  /**
245
331
  * Makes a backup of the database. This method abstracts the sqlite3_backup_init(),
246
332
  * sqlite3_backup_step() and sqlite3_backup_finish() functions.
@@ -282,6 +368,344 @@ interface DatabaseSyncInstance {
282
368
  /** Dispose of the database resources using the explicit resource management protocol. */
283
369
  [Symbol.dispose](): void;
284
370
  }
371
+
372
+ /**
373
+ * SQLTagStore provides cached prepared statements via tagged template syntax.
374
+ *
375
+ * @example
376
+ * ```js
377
+ * const sql = db.createTagStore();
378
+ * sql.run`INSERT INTO users VALUES (${id}, ${name})`;
379
+ * const user = sql.get`SELECT * FROM users WHERE id = ${id}`;
380
+ * ```
381
+ */
382
+ declare class SQLTagStore {
383
+ private readonly database;
384
+ private readonly cache;
385
+ private readonly maxCapacity;
386
+ constructor(db: DatabaseSyncInstance, capacity?: number);
387
+ /**
388
+ * Returns the associated database instance.
389
+ */
390
+ get db(): DatabaseSyncInstance;
391
+ /**
392
+ * Returns the maximum capacity of the statement cache.
393
+ */
394
+ get capacity(): number;
395
+ /**
396
+ * Returns the current number of cached statements.
397
+ */
398
+ size(): number;
399
+ /**
400
+ * Clears all cached statements.
401
+ */
402
+ clear(): void;
403
+ /**
404
+ * Execute an INSERT, UPDATE, DELETE or other statement that doesn't return rows.
405
+ * Returns an object with `changes` and `lastInsertRowid`.
406
+ */
407
+ run(strings: TemplateStringsArray, ...values: unknown[]): {
408
+ changes: number;
409
+ lastInsertRowid: number | bigint;
410
+ };
411
+ /**
412
+ * Execute a query and return the first row, or undefined if no rows.
413
+ */
414
+ get(strings: TemplateStringsArray, ...values: unknown[]): unknown;
415
+ /**
416
+ * Execute a query and return all rows as an array.
417
+ */
418
+ all(strings: TemplateStringsArray, ...values: unknown[]): unknown[];
419
+ /**
420
+ * Execute a query and return an iterator over the rows.
421
+ */
422
+ iterate(strings: TemplateStringsArray, ...values: unknown[]): IterableIterator<unknown>;
423
+ /**
424
+ * Get a cached statement or prepare a new one.
425
+ * If a cached statement has been finalized, it's evicted and a new one is prepared.
426
+ */
427
+ private getOrPrepare;
428
+ /**
429
+ * Build the SQL string by joining template parts with `?` placeholders.
430
+ */
431
+ private buildSQL;
432
+ }
433
+
434
+ /**
435
+ * Configuration options for opening a database.
436
+ * This interface matches Node.js sqlite module's DatabaseSyncOptions.
437
+ */
438
+ interface DatabaseSyncOptions {
439
+ /** Path to the database file. Use ':memory:' for an in-memory database. */
440
+ readonly location?: string;
441
+ /** If true, the database is opened in read-only mode. @default false */
442
+ readonly readOnly?: boolean;
443
+ /** If true, foreign key constraints are enforced. @default true */
444
+ readonly enableForeignKeyConstraints?: boolean;
445
+ /**
446
+ * If true, double-quoted string literals are allowed.
447
+ *
448
+ * If enabled, double quotes can be misinterpreted as identifiers instead of
449
+ * string literals, leading to confusing errors.
450
+ *
451
+ * **The SQLite documentation strongly recommends avoiding double-quoted
452
+ * strings entirely.**
453
+
454
+ * @see https://sqlite.org/quirks.html#dblquote
455
+ * @default false
456
+ */
457
+ readonly enableDoubleQuotedStringLiterals?: boolean;
458
+ /**
459
+ * Sets the busy timeout in milliseconds.
460
+ * @default 0
461
+ */
462
+ readonly timeout?: number;
463
+ /** If true, enables loading of SQLite extensions. @default false */
464
+ readonly allowExtension?: boolean;
465
+ /**
466
+ * If true, SQLite integers are returned as JavaScript BigInt values.
467
+ * If false, integers are returned as JavaScript numbers.
468
+ * @default false
469
+ */
470
+ readonly readBigInts?: boolean;
471
+ /**
472
+ * If true, query results are returned as arrays instead of objects.
473
+ * @default false
474
+ */
475
+ readonly returnArrays?: boolean;
476
+ /**
477
+ * If true, allows binding named parameters without the prefix character.
478
+ * For example, allows using 'foo' instead of ':foo' or '$foo'.
479
+ * @default true
480
+ */
481
+ readonly allowBareNamedParameters?: boolean;
482
+ /**
483
+ * If true, unknown named parameters are ignored during binding.
484
+ * If false, an exception is thrown for unknown named parameters.
485
+ * @default false
486
+ */
487
+ readonly allowUnknownNamedParameters?: boolean;
488
+ /**
489
+ * If true, enables the defensive flag. When the defensive flag is enabled,
490
+ * language features that allow ordinary SQL to deliberately corrupt the
491
+ * database file are disabled. The defensive flag can also be set using
492
+ * `enableDefensive()`.
493
+ * @see https://sqlite.org/c3ref/c_dbconfig_defensive.html
494
+ * @default false
495
+ */
496
+ readonly defensive?: boolean;
497
+ /**
498
+ * If true, the database is opened immediately. If false, the database is not opened until the first operation.
499
+ * @default true
500
+ */
501
+ readonly open?: boolean;
502
+ }
503
+
504
+ /**
505
+ * Authorization action codes passed to `setAuthorizer()` callbacks.
506
+ *
507
+ * These constants are compatible with `node:sqlite`.
508
+ *
509
+ * @see https://sqlite.org/c3ref/c_alter_table.html
510
+ */
511
+ interface SqliteAuthorizationActions {
512
+ /** Create a new index. */
513
+ SQLITE_CREATE_INDEX: number;
514
+ /** Create a new table. */
515
+ SQLITE_CREATE_TABLE: number;
516
+ /** Create a new temporary index. */
517
+ SQLITE_CREATE_TEMP_INDEX: number;
518
+ /** Create a new temporary table. */
519
+ SQLITE_CREATE_TEMP_TABLE: number;
520
+ /** Create a new temporary trigger. */
521
+ SQLITE_CREATE_TEMP_TRIGGER: number;
522
+ /** Create a new temporary view. */
523
+ SQLITE_CREATE_TEMP_VIEW: number;
524
+ /** Create a new trigger. */
525
+ SQLITE_CREATE_TRIGGER: number;
526
+ /** Create a new view. */
527
+ SQLITE_CREATE_VIEW: number;
528
+ /** Delete rows from a table. */
529
+ SQLITE_DELETE: number;
530
+ /** Drop an index. */
531
+ SQLITE_DROP_INDEX: number;
532
+ /** Drop a table. */
533
+ SQLITE_DROP_TABLE: number;
534
+ /** Drop a temporary index. */
535
+ SQLITE_DROP_TEMP_INDEX: number;
536
+ /** Drop a temporary table. */
537
+ SQLITE_DROP_TEMP_TABLE: number;
538
+ /** Drop a temporary trigger. */
539
+ SQLITE_DROP_TEMP_TRIGGER: number;
540
+ /** Drop a temporary view. */
541
+ SQLITE_DROP_TEMP_VIEW: number;
542
+ /** Drop a trigger. */
543
+ SQLITE_DROP_TRIGGER: number;
544
+ /** Drop a view. */
545
+ SQLITE_DROP_VIEW: number;
546
+ /** Insert rows into a table. */
547
+ SQLITE_INSERT: number;
548
+ /** Execute a PRAGMA statement. */
549
+ SQLITE_PRAGMA: number;
550
+ /** Read a column from a table. */
551
+ SQLITE_READ: number;
552
+ /** Execute a SELECT statement. */
553
+ SQLITE_SELECT: number;
554
+ /** Begin/commit/rollback a transaction. */
555
+ SQLITE_TRANSACTION: number;
556
+ /** Update rows in a table. */
557
+ SQLITE_UPDATE: number;
558
+ /** Attach a database. */
559
+ SQLITE_ATTACH: number;
560
+ /** Detach a database. */
561
+ SQLITE_DETACH: number;
562
+ /** Alter a table. */
563
+ SQLITE_ALTER_TABLE: number;
564
+ /** Reindex. */
565
+ SQLITE_REINDEX: number;
566
+ /** Analyze a table or index. */
567
+ SQLITE_ANALYZE: number;
568
+ /** Create a virtual table. */
569
+ SQLITE_CREATE_VTABLE: number;
570
+ /** Drop a virtual table. */
571
+ SQLITE_DROP_VTABLE: number;
572
+ /** Call a function. */
573
+ SQLITE_FUNCTION: number;
574
+ /** Create/release/rollback a savepoint. */
575
+ SQLITE_SAVEPOINT: number;
576
+ /** No longer used (historical). */
577
+ SQLITE_COPY: number;
578
+ /** Recursive query. */
579
+ SQLITE_RECURSIVE: number;
580
+ }
581
+
582
+ /**
583
+ * Authorization callback return values for `setAuthorizer()`.
584
+ *
585
+ * These constants are compatible with `node:sqlite`.
586
+ *
587
+ * @see https://sqlite.org/c3ref/c_deny.html
588
+ */
589
+ interface SqliteAuthorizationResults {
590
+ /** Allow the operation. */
591
+ SQLITE_OK: number;
592
+ /** Deny the operation and abort the SQL statement with an error. */
593
+ SQLITE_DENY: number;
594
+ /** Silently ignore/skip the operation (e.g., return NULL for column reads). */
595
+ SQLITE_IGNORE: number;
596
+ }
597
+
598
+ /**
599
+ * Changeset conflict type codes passed to `applyChangeset()` callbacks.
600
+ *
601
+ * These constants are compatible with `node:sqlite`.
602
+ *
603
+ * @see https://sqlite.org/session/c_changeset_conflict.html
604
+ */
605
+ interface SqliteChangesetConflictTypes {
606
+ /** Data conflict - row exists but values differ. */
607
+ SQLITE_CHANGESET_DATA: number;
608
+ /** Row not found in target database. */
609
+ SQLITE_CHANGESET_NOTFOUND: number;
610
+ /** Primary key conflict. */
611
+ SQLITE_CHANGESET_CONFLICT: number;
612
+ /** Constraint violation (NOT NULL, CHECK, etc.). */
613
+ SQLITE_CHANGESET_CONSTRAINT: number;
614
+ /** Foreign key constraint violation. */
615
+ SQLITE_CHANGESET_FOREIGN_KEY: number;
616
+ }
617
+
618
+ /**
619
+ * Changeset conflict resolution return values for `applyChangeset()` callbacks.
620
+ *
621
+ * These constants are compatible with `node:sqlite`.
622
+ *
623
+ * @see https://sqlite.org/session/sqlite3changeset_apply.html
624
+ */
625
+ interface SqliteChangesetResolution {
626
+ /** Skip conflicting changes. */
627
+ SQLITE_CHANGESET_OMIT: number;
628
+ /** Replace conflicting changes. */
629
+ SQLITE_CHANGESET_REPLACE: number;
630
+ /** Abort on conflict. */
631
+ SQLITE_CHANGESET_ABORT: number;
632
+ }
633
+
634
+ /**
635
+ * SQLite database open flags.
636
+ *
637
+ * **Note:** These constants are an extension beyond `node:sqlite`.
638
+ * The `node:sqlite` module does not export `SQLITE_OPEN_*` constants.
639
+ *
640
+ * @see https://sqlite.org/c3ref/open.html
641
+ */
642
+ interface SqliteOpenFlags {
643
+ /** Open database for reading only. */
644
+ SQLITE_OPEN_READONLY: number;
645
+ /** Open database for reading and writing. */
646
+ SQLITE_OPEN_READWRITE: number;
647
+ /** Create database if it doesn't exist. */
648
+ SQLITE_OPEN_CREATE: number;
649
+ /** Delete database file on close. */
650
+ SQLITE_OPEN_DELETEONCLOSE: number;
651
+ /** Open with exclusive access. */
652
+ SQLITE_OPEN_EXCLUSIVE: number;
653
+ /** Use automatic proxy for locking. */
654
+ SQLITE_OPEN_AUTOPROXY: number;
655
+ /** Interpret filename as URI. */
656
+ SQLITE_OPEN_URI: number;
657
+ /** Open in-memory database. */
658
+ SQLITE_OPEN_MEMORY: number;
659
+ /** Open main database file. */
660
+ SQLITE_OPEN_MAIN_DB: number;
661
+ /** Open temporary database file. */
662
+ SQLITE_OPEN_TEMP_DB: number;
663
+ /** Open transient in-memory database. */
664
+ SQLITE_OPEN_TRANSIENT_DB: number;
665
+ /** Open main journal file. */
666
+ SQLITE_OPEN_MAIN_JOURNAL: number;
667
+ /** Open temporary journal file. */
668
+ SQLITE_OPEN_TEMP_JOURNAL: number;
669
+ /** Open subjournal file. */
670
+ SQLITE_OPEN_SUBJOURNAL: number;
671
+ /** Open super-journal file. */
672
+ SQLITE_OPEN_SUPER_JOURNAL: number;
673
+ /** Open without mutex. */
674
+ SQLITE_OPEN_NOMUTEX: number;
675
+ /** Open with full mutex. */
676
+ SQLITE_OPEN_FULLMUTEX: number;
677
+ /** Enable shared cache mode. */
678
+ SQLITE_OPEN_SHAREDCACHE: number;
679
+ /** Enable private cache mode. */
680
+ SQLITE_OPEN_PRIVATECACHE: number;
681
+ /** Open WAL file. */
682
+ SQLITE_OPEN_WAL: number;
683
+ }
684
+
685
+ /**
686
+ * All SQLite constants exported by this module.
687
+ *
688
+ * This is a union of all constant category interfaces:
689
+ * - {@link SqliteOpenFlags} - Database open flags (extension beyond `node:sqlite`)
690
+ * - {@link SqliteChangesetResolution} - Changeset conflict resolution values
691
+ * - {@link SqliteChangesetConflictTypes} - Changeset conflict type codes
692
+ * - {@link SqliteAuthorizationResults} - Authorization return values
693
+ * - {@link SqliteAuthorizationActions} - Authorization action codes
694
+ *
695
+ * **Note:** The categorized interfaces (`SqliteOpenFlags`, etc.) are extensions
696
+ * provided by `@photostructure/sqlite`. The `node:sqlite` module exports only
697
+ * a flat `constants` object without these type categories.
698
+ */
699
+ type SqliteConstants = SqliteOpenFlags & SqliteChangesetResolution & SqliteChangesetConflictTypes & SqliteAuthorizationResults & SqliteAuthorizationActions;
700
+ /**
701
+ * Options for creating a prepared statement.
702
+ */
703
+ interface StatementOptions {
704
+ /** If true, the prepared statement's expandedSQL property will contain the expanded SQL. @default false */
705
+ readonly expandedSQL?: boolean;
706
+ /** If true, anonymous parameters are enabled for the statement. @default false */
707
+ readonly anonymousParameters?: boolean;
708
+ }
285
709
  /**
286
710
  * The main SQLite module interface.
287
711
  */
@@ -303,31 +727,14 @@ interface SqliteModule {
303
727
  Session: new () => Session;
304
728
  /**
305
729
  * SQLite constants for various operations and flags.
306
- */
307
- constants: {
308
- /** Open database for reading only. */
309
- SQLITE_OPEN_READONLY: number;
310
- /** Open database for reading and writing. */
311
- SQLITE_OPEN_READWRITE: number;
312
- /** Create database if it doesn't exist. */
313
- SQLITE_OPEN_CREATE: number;
314
- /** Skip conflicting changes. */
315
- SQLITE_CHANGESET_OMIT: number;
316
- /** Replace conflicting changes. */
317
- SQLITE_CHANGESET_REPLACE: number;
318
- /** Abort on conflict. */
319
- SQLITE_CHANGESET_ABORT: number;
320
- /** Data conflict type. */
321
- SQLITE_CHANGESET_DATA: number;
322
- /** Row not found conflict. */
323
- SQLITE_CHANGESET_NOTFOUND: number;
324
- /** General conflict. */
325
- SQLITE_CHANGESET_CONFLICT: number;
326
- /** Constraint violation. */
327
- SQLITE_CHANGESET_CONSTRAINT: number;
328
- /** Foreign key constraint violation. */
329
- SQLITE_CHANGESET_FOREIGN_KEY: number;
330
- };
730
+ * @see {@link SqliteConstants} for the type definition
731
+ * @see {@link SqliteOpenFlags} for database open flags (extension beyond `node:sqlite`)
732
+ * @see {@link SqliteChangesetResolution} for changeset conflict resolution values
733
+ * @see {@link SqliteChangesetConflictTypes} for changeset conflict type codes
734
+ * @see {@link SqliteAuthorizationResults} for authorization return values
735
+ * @see {@link SqliteAuthorizationActions} for authorization action codes
736
+ */
737
+ constants: SqliteConstants;
331
738
  }
332
739
  /**
333
740
  * The DatabaseSync class represents a synchronous connection to a SQLite database.
@@ -389,6 +796,7 @@ interface Session {
389
796
  * ```
390
797
  */
391
798
  declare const Session: SqliteModule["Session"];
799
+
392
800
  /**
393
801
  * SQLite constants for various operations and flags.
394
802
  *
@@ -402,7 +810,51 @@ declare const Session: SqliteModule["Session"];
402
810
  * });
403
811
  * ```
404
812
  */
405
- declare const constants: SqliteModule["constants"];
813
+ declare const constants: SqliteConstants;
814
+ /**
815
+ * Options for the backup() function.
816
+ */
817
+ interface BackupOptions {
818
+ /** Number of pages to be transmitted in each batch of the backup. @default 100 */
819
+ rate?: number;
820
+ /** Name of the source database. Can be 'main' or any attached database. @default 'main' */
821
+ source?: string;
822
+ /** Name of the target database. Can be 'main' or any attached database. @default 'main' */
823
+ target?: string;
824
+ /** Callback function that will be called with progress information. */
825
+ progress?: (info: {
826
+ totalPages: number;
827
+ remainingPages: number;
828
+ }) => void;
829
+ }
830
+ /**
831
+ * Standalone function to make a backup of a database.
832
+ *
833
+ * This function matches the Node.js `node:sqlite` module API which exports
834
+ * `backup()` as a standalone function in addition to the `db.backup()` method.
835
+ *
836
+ * @param sourceDb The database to backup from.
837
+ * @param destination The path where the backup will be created.
838
+ * @param options Optional configuration for the backup operation.
839
+ * @returns A promise that resolves when the backup is completed.
840
+ *
841
+ * @example
842
+ * ```typescript
843
+ * import { DatabaseSync, backup } from '@photostructure/sqlite';
844
+ *
845
+ * const db = new DatabaseSync('./source.db');
846
+ * await backup(db, './backup.db');
847
+ *
848
+ * // With options
849
+ * await backup(db, './backup.db', {
850
+ * rate: 10,
851
+ * progress: ({ totalPages, remainingPages }) => {
852
+ * console.log(`Progress: ${totalPages - remainingPages}/${totalPages}`);
853
+ * }
854
+ * });
855
+ * ```
856
+ */
857
+ declare const backup: (sourceDb: DatabaseSyncInstance, destination: string | Buffer | URL, options?: BackupOptions) => Promise<number>;
406
858
  declare const _default: SqliteModule;
407
859
 
408
- export { type AggregateOptions, type ChangesetApplyOptions, DatabaseSync, type DatabaseSyncInstance, type DatabaseSyncOptions, Session, type SessionOptions, type SqliteModule, type StatementOptions, StatementSync, type StatementSyncInstance, type UserFunctionOptions, constants, _default as default };
860
+ export { type AggregateOptions, type BackupOptions, type ChangesetApplyOptions, DatabaseSync, type DatabaseSyncInstance, type DatabaseSyncOptions, SQLTagStore, type SQLTagStoreInstance, Session, type SessionOptions, type SqliteAuthorizationActions, type SqliteAuthorizationResults, type SqliteChangesetConflictTypes, type SqliteChangesetResolution, type SqliteConstants, type SqliteModule, type SqliteOpenFlags, type StatementOptions, StatementSync, type StatementSyncInstance, type UserFunctionOptions, backup, constants, _default as default };