@photostructure/sqlite 0.2.1 → 0.4.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.
- package/CHANGELOG.md +61 -15
- package/README.md +5 -4
- package/binding.gyp +2 -2
- package/dist/index.cjs +159 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +286 -91
- package/dist/index.d.mts +286 -91
- package/dist/index.d.ts +286 -91
- package/dist/index.mjs +156 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +74 -65
- package/prebuilds/darwin-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/darwin-x64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-arm64/@photostructure+sqlite.musl.node +0 -0
- package/prebuilds/linux-x64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-x64/@photostructure+sqlite.musl.node +0 -0
- package/prebuilds/test_extension.so +0 -0
- package/prebuilds/win32-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+sqlite.glibc.node +0 -0
- package/scripts/prebuild-linux-glibc.sh +6 -4
- package/src/aggregate_function.cpp +222 -114
- package/src/aggregate_function.h +5 -6
- package/src/binding.cpp +30 -21
- package/src/enhance.ts +228 -0
- package/src/index.ts +83 -9
- package/src/shims/node_errors.h +34 -15
- package/src/shims/sqlite_errors.h +34 -8
- package/src/sql-tag-store.ts +7 -10
- package/src/sqlite_impl.cpp +1044 -394
- package/src/sqlite_impl.h +46 -7
- package/src/transaction.ts +178 -0
- package/src/types/database-sync-instance.ts +6 -40
- package/src/types/pragma-options.ts +23 -0
- package/src/types/sql-tag-store-instance.ts +1 -1
- package/src/types/statement-sync-instance.ts +38 -12
- package/src/types/transaction.ts +72 -0
- package/src/upstream/node_sqlite.cc +143 -43
- package/src/upstream/node_sqlite.h +15 -11
- package/src/upstream/sqlite3.c +102 -58
- package/src/upstream/sqlite3.h +5 -5
- package/src/user_function.cpp +138 -141
- package/src/user_function.h +3 -0
package/dist/index.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ interface SQLTagStoreInstance {
|
|
|
63
63
|
/**
|
|
64
64
|
* Returns the current number of cached statements.
|
|
65
65
|
*/
|
|
66
|
-
size
|
|
66
|
+
readonly size: number;
|
|
67
67
|
/**
|
|
68
68
|
* Clears all cached statements.
|
|
69
69
|
*/
|
|
@@ -98,6 +98,41 @@ interface SQLTagStoreInstance {
|
|
|
98
98
|
iterate(strings: TemplateStringsArray, ...values: unknown[]): IterableIterator<unknown>;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Metadata about a column in a prepared statement's result set.
|
|
103
|
+
* Matches Node.js sqlite module's StatementColumnMetadata.
|
|
104
|
+
*/
|
|
105
|
+
interface StatementColumnMetadata {
|
|
106
|
+
/**
|
|
107
|
+
* The unaliased name of the column in the origin table, or `null` if the
|
|
108
|
+
* column is the result of an expression or subquery.
|
|
109
|
+
* This property is the result of `sqlite3_column_origin_name()`.
|
|
110
|
+
*/
|
|
111
|
+
column: string | null;
|
|
112
|
+
/**
|
|
113
|
+
* The unaliased name of the origin database, or `null` if the column is
|
|
114
|
+
* the result of an expression or subquery.
|
|
115
|
+
* This property is the result of `sqlite3_column_database_name()`.
|
|
116
|
+
*/
|
|
117
|
+
database: string | null;
|
|
118
|
+
/**
|
|
119
|
+
* The name assigned to the column in the result set of a SELECT statement.
|
|
120
|
+
* This property is the result of `sqlite3_column_name()`.
|
|
121
|
+
*/
|
|
122
|
+
name: string;
|
|
123
|
+
/**
|
|
124
|
+
* The unaliased name of the origin table, or `null` if the column is
|
|
125
|
+
* the result of an expression or subquery.
|
|
126
|
+
* This property is the result of `sqlite3_column_table_name()`.
|
|
127
|
+
*/
|
|
128
|
+
table: string | null;
|
|
129
|
+
/**
|
|
130
|
+
* The declared data type of the column, or `null` if the column is
|
|
131
|
+
* the result of an expression or subquery.
|
|
132
|
+
* This property is the result of `sqlite3_column_decltype()`.
|
|
133
|
+
*/
|
|
134
|
+
type: string | null;
|
|
135
|
+
}
|
|
101
136
|
/**
|
|
102
137
|
* A prepared SQL statement that can be executed multiple times with different parameters.
|
|
103
138
|
* This interface represents an instance of the StatementSync class.
|
|
@@ -107,8 +142,6 @@ interface StatementSyncInstance {
|
|
|
107
142
|
readonly sourceSQL: string;
|
|
108
143
|
/** The expanded SQL string with bound parameters, if expandedSQL option was set. */
|
|
109
144
|
readonly expandedSQL: string | undefined;
|
|
110
|
-
/** Whether this statement has been finalized. */
|
|
111
|
-
readonly finalized: boolean;
|
|
112
145
|
/**
|
|
113
146
|
* This method executes a prepared statement and returns an object.
|
|
114
147
|
* @param parameters Optional named and anonymous parameters to bind to the statement.
|
|
@@ -159,20 +192,9 @@ interface StatementSyncInstance {
|
|
|
159
192
|
setReturnArrays(returnArrays: boolean): void;
|
|
160
193
|
/**
|
|
161
194
|
* Returns an array of objects, each representing a column in the statement's result set.
|
|
162
|
-
*
|
|
163
|
-
* @returns Array of column metadata objects.
|
|
164
|
-
*/
|
|
165
|
-
columns(): Array<{
|
|
166
|
-
name: string;
|
|
167
|
-
type?: string;
|
|
168
|
-
}>;
|
|
169
|
-
/**
|
|
170
|
-
* Finalizes the prepared statement and releases its resources.
|
|
171
|
-
* Called automatically by Symbol.dispose.
|
|
195
|
+
* @returns Array of column metadata objects with name, column, database, table, and type.
|
|
172
196
|
*/
|
|
173
|
-
|
|
174
|
-
/** Dispose of the statement resources using the explicit resource management protocol. */
|
|
175
|
-
[Symbol.dispose](): void;
|
|
197
|
+
columns(): StatementColumnMetadata[];
|
|
176
198
|
}
|
|
177
199
|
|
|
178
200
|
/**
|
|
@@ -274,7 +296,7 @@ interface DatabaseSyncInstance {
|
|
|
274
296
|
* @param options Optional configuration for applying the changeset.
|
|
275
297
|
* @returns true if successful, false if aborted.
|
|
276
298
|
*/
|
|
277
|
-
applyChangeset(changeset:
|
|
299
|
+
applyChangeset(changeset: Uint8Array, options?: ChangesetApplyOptions): boolean;
|
|
278
300
|
/**
|
|
279
301
|
* Enables or disables the loading of SQLite extensions.
|
|
280
302
|
* @param enable If true, enables extension loading. If false, disables it.
|
|
@@ -327,44 +349,6 @@ interface DatabaseSyncInstance {
|
|
|
327
349
|
* @see https://sqlite.org/c3ref/set_authorizer.html
|
|
328
350
|
*/
|
|
329
351
|
setAuthorizer(callback: ((actionCode: number, param1: string | null, param2: string | null, param3: string | null, param4: string | null) => number) | null): void;
|
|
330
|
-
/**
|
|
331
|
-
* Makes a backup of the database. This method abstracts the sqlite3_backup_init(),
|
|
332
|
-
* sqlite3_backup_step() and sqlite3_backup_finish() functions.
|
|
333
|
-
*
|
|
334
|
-
* The backed-up database can be used normally during the backup process. Mutations
|
|
335
|
-
* coming from the same connection will be reflected in the backup right away.
|
|
336
|
-
* However, mutations from other connections will cause the backup process to restart.
|
|
337
|
-
*
|
|
338
|
-
* @param path The path where the backup will be created. If the file already exists, the contents will be overwritten.
|
|
339
|
-
* @param options Optional configuration for the backup operation.
|
|
340
|
-
* @param options.rate Number of pages to be transmitted in each batch of the backup. @default 100
|
|
341
|
-
* @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'
|
|
342
|
-
* @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'
|
|
343
|
-
* @param options.progress Callback function that will be called with the number of pages copied and the total number of pages.
|
|
344
|
-
* @returns A promise that resolves when the backup is completed and rejects if an error occurs.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* // Basic backup
|
|
348
|
-
* await db.backup('./backup.db');
|
|
349
|
-
*
|
|
350
|
-
* @example
|
|
351
|
-
* // Backup with progress
|
|
352
|
-
* await db.backup('./backup.db', {
|
|
353
|
-
* rate: 10,
|
|
354
|
-
* progress: ({ totalPages, remainingPages }) => {
|
|
355
|
-
* console.log(`Progress: ${totalPages - remainingPages}/${totalPages}`);
|
|
356
|
-
* }
|
|
357
|
-
* });
|
|
358
|
-
*/
|
|
359
|
-
backup(path: string | Buffer | URL, options?: {
|
|
360
|
-
rate?: number;
|
|
361
|
-
source?: string;
|
|
362
|
-
target?: string;
|
|
363
|
-
progress?: (info: {
|
|
364
|
-
totalPages: number;
|
|
365
|
-
remainingPages: number;
|
|
366
|
-
}) => void;
|
|
367
|
-
}): Promise<number>;
|
|
368
352
|
/** Dispose of the database resources using the explicit resource management protocol. */
|
|
369
353
|
[Symbol.dispose](): void;
|
|
370
354
|
}
|
|
@@ -395,7 +379,7 @@ declare class SQLTagStore {
|
|
|
395
379
|
/**
|
|
396
380
|
* Returns the current number of cached statements.
|
|
397
381
|
*/
|
|
398
|
-
size(): number;
|
|
382
|
+
get size(): number;
|
|
399
383
|
/**
|
|
400
384
|
* Clears all cached statements.
|
|
401
385
|
*/
|
|
@@ -422,7 +406,6 @@ declare class SQLTagStore {
|
|
|
422
406
|
iterate(strings: TemplateStringsArray, ...values: unknown[]): IterableIterator<unknown>;
|
|
423
407
|
/**
|
|
424
408
|
* 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
409
|
*/
|
|
427
410
|
private getOrPrepare;
|
|
428
411
|
/**
|
|
@@ -682,6 +665,218 @@ interface SqliteOpenFlags {
|
|
|
682
665
|
SQLITE_OPEN_WAL: number;
|
|
683
666
|
}
|
|
684
667
|
|
|
668
|
+
/**
|
|
669
|
+
* Options for the pragma() method.
|
|
670
|
+
*
|
|
671
|
+
* @see https://sqlite.org/pragma.html
|
|
672
|
+
*/
|
|
673
|
+
interface PragmaOptions {
|
|
674
|
+
/**
|
|
675
|
+
* When true, returns only the first column of the first row.
|
|
676
|
+
* This is useful for pragmas that return a single value.
|
|
677
|
+
*
|
|
678
|
+
* @default false
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* ```typescript
|
|
682
|
+
* // Without simple: returns [{ cache_size: -16000 }]
|
|
683
|
+
* db.pragma('cache_size');
|
|
684
|
+
*
|
|
685
|
+
* // With simple: returns -16000
|
|
686
|
+
* db.pragma('cache_size', { simple: true });
|
|
687
|
+
* ```
|
|
688
|
+
*/
|
|
689
|
+
readonly simple?: boolean;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Transaction isolation modes supported by SQLite.
|
|
694
|
+
*
|
|
695
|
+
* @see https://sqlite.org/lang_transaction.html
|
|
696
|
+
*/
|
|
697
|
+
type TransactionMode = "deferred" | "immediate" | "exclusive";
|
|
698
|
+
/**
|
|
699
|
+
* A function wrapped in a transaction. When called, it automatically:
|
|
700
|
+
* - Begins a transaction (or savepoint if nested)
|
|
701
|
+
* - Executes the wrapped function
|
|
702
|
+
* - Commits on success, rolls back on error
|
|
703
|
+
*
|
|
704
|
+
* The function also has variants for different transaction modes accessible as
|
|
705
|
+
* properties (`.deferred`, `.immediate`, `.exclusive`).
|
|
706
|
+
*
|
|
707
|
+
* **Note:** Each variant is itself a `TransactionFunction` with circular
|
|
708
|
+
* references to all other variants. This matches better-sqlite3's behavior
|
|
709
|
+
* where you can chain variants like `txn.deferred.immediate()` - the last
|
|
710
|
+
* variant in the chain determines the actual transaction mode used.
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* ```typescript
|
|
714
|
+
* const insertMany = db.transaction((items: Item[]) => {
|
|
715
|
+
* for (const item of items) insert.run(item);
|
|
716
|
+
* return items.length;
|
|
717
|
+
* });
|
|
718
|
+
*
|
|
719
|
+
* // Use default mode (DEFERRED)
|
|
720
|
+
* insertMany([{ id: 1 }, { id: 2 }]);
|
|
721
|
+
*
|
|
722
|
+
* // Use IMMEDIATE mode for write transactions
|
|
723
|
+
* insertMany.immediate([{ id: 3 }, { id: 4 }]);
|
|
724
|
+
*
|
|
725
|
+
* // Use EXCLUSIVE mode for exclusive access
|
|
726
|
+
* insertMany.exclusive([{ id: 5 }, { id: 6 }]);
|
|
727
|
+
* ```
|
|
728
|
+
*/
|
|
729
|
+
interface TransactionFunction<F extends (...args: any[]) => any> {
|
|
730
|
+
/**
|
|
731
|
+
* Execute the wrapped function within a transaction using the default mode (DEFERRED).
|
|
732
|
+
*/
|
|
733
|
+
(...args: Parameters<F>): ReturnType<F>;
|
|
734
|
+
/**
|
|
735
|
+
* Execute with DEFERRED transaction mode.
|
|
736
|
+
* The database lock is not acquired until the first read or write operation.
|
|
737
|
+
* This is the default SQLite behavior.
|
|
738
|
+
*/
|
|
739
|
+
readonly deferred: TransactionFunction<F>;
|
|
740
|
+
/**
|
|
741
|
+
* Execute with IMMEDIATE transaction mode.
|
|
742
|
+
* Acquires a write lock immediately, blocking other writers.
|
|
743
|
+
* Recommended for transactions that will write to prevent SQLITE_BUSY errors.
|
|
744
|
+
*/
|
|
745
|
+
readonly immediate: TransactionFunction<F>;
|
|
746
|
+
/**
|
|
747
|
+
* Execute with EXCLUSIVE transaction mode.
|
|
748
|
+
* Acquires an exclusive lock immediately, blocking all other connections.
|
|
749
|
+
* Use sparingly as it prevents all concurrent access.
|
|
750
|
+
*/
|
|
751
|
+
readonly exclusive: TransactionFunction<F>;
|
|
752
|
+
/**
|
|
753
|
+
* The database connection this transaction function is bound to.
|
|
754
|
+
*/
|
|
755
|
+
readonly database: DatabaseSyncInstance;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Enhancement utilities for adding better-sqlite3-style methods to any
|
|
760
|
+
* compatible database, including `node:sqlite` DatabaseSync and this package's
|
|
761
|
+
* DatabaseSync.
|
|
762
|
+
*
|
|
763
|
+
* This module provides the `enhance()` function which adds `.pragma()` and
|
|
764
|
+
* `.transaction()` methods to database instances that don't have them (e.g.,
|
|
765
|
+
* node:sqlite DatabaseSync).
|
|
766
|
+
*/
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Minimal interface for a database that can be enhanced. This matches the
|
|
770
|
+
* subset of functionality needed by pragma() and transaction().
|
|
771
|
+
*/
|
|
772
|
+
interface EnhanceableDatabaseSync {
|
|
773
|
+
/** Execute SQL without returning results */
|
|
774
|
+
exec(sql: string): void;
|
|
775
|
+
/** Prepare a statement that can return results */
|
|
776
|
+
prepare(sql: string): {
|
|
777
|
+
all(): unknown[];
|
|
778
|
+
};
|
|
779
|
+
/** Whether a transaction is currently active */
|
|
780
|
+
readonly isTransaction: boolean;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Interface for an enhanced database with pragma() and transaction() methods.
|
|
784
|
+
*/
|
|
785
|
+
interface EnhancedMethods {
|
|
786
|
+
/**
|
|
787
|
+
* Executes a PRAGMA statement and returns its result.
|
|
788
|
+
*
|
|
789
|
+
* @param source The PRAGMA command (without "PRAGMA" prefix)
|
|
790
|
+
* @param options Optional configuration
|
|
791
|
+
* @returns Array of rows, or single value if `simple: true`
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* ```typescript
|
|
795
|
+
* db.pragma('cache_size', { simple: true }); // -16000
|
|
796
|
+
* db.pragma('journal_mode = wal');
|
|
797
|
+
* ```
|
|
798
|
+
*/
|
|
799
|
+
pragma(source: string, options?: PragmaOptions): unknown;
|
|
800
|
+
/**
|
|
801
|
+
* Creates a function that always runs inside a transaction.
|
|
802
|
+
*
|
|
803
|
+
* @param fn The function to wrap in a transaction
|
|
804
|
+
* @returns A transaction function with `.deferred`, `.immediate`,
|
|
805
|
+
* `.exclusive` variants
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```typescript
|
|
809
|
+
* const insertMany = db.transaction((items) => {
|
|
810
|
+
* for (const item of items) insert.run(item);
|
|
811
|
+
* });
|
|
812
|
+
* insertMany(['a', 'b', 'c']); // All in one transaction
|
|
813
|
+
* ```
|
|
814
|
+
*/
|
|
815
|
+
transaction<F extends (...args: any[]) => any>(fn: F): TransactionFunction<F>;
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* A database instance that has been enhanced with pragma() and transaction() methods.
|
|
819
|
+
*/
|
|
820
|
+
type EnhancedDatabaseSync<T extends EnhanceableDatabaseSync> = T & EnhancedMethods;
|
|
821
|
+
/**
|
|
822
|
+
* Ensures that `.pragma()` and `.transaction()` methods are available on the
|
|
823
|
+
* given database.
|
|
824
|
+
*
|
|
825
|
+
* This function can enhance:
|
|
826
|
+
* - `node:sqlite` DatabaseSync instances (adds the methods)
|
|
827
|
+
* - `@photostructure/sqlite` DatabaseSync instances (no-op, already has these
|
|
828
|
+
* methods)
|
|
829
|
+
* - Any object with compatible `exec()`, `prepare()`, and `isTransaction`
|
|
830
|
+
*
|
|
831
|
+
* The enhancement is done by adding methods directly to the instance, not the
|
|
832
|
+
* prototype, so it won't affect other instances or the original class.
|
|
833
|
+
*
|
|
834
|
+
* @param db The database instance to enhance
|
|
835
|
+
* @returns The same instance with `.pragma()` and `.transaction()` methods
|
|
836
|
+
* guaranteed
|
|
837
|
+
*
|
|
838
|
+
* @example
|
|
839
|
+
* ```typescript
|
|
840
|
+
* // With node:sqlite
|
|
841
|
+
* import { DatabaseSync } from 'node:sqlite';
|
|
842
|
+
* import { enhance } from '@photostructure/sqlite';
|
|
843
|
+
*
|
|
844
|
+
* const db = enhance(new DatabaseSync(':memory:'));
|
|
845
|
+
*
|
|
846
|
+
* // Now you can use better-sqlite3-style methods
|
|
847
|
+
* db.pragma('journal_mode = wal');
|
|
848
|
+
* const insertMany = db.transaction((items) => {
|
|
849
|
+
* for (const item of items) insert.run(item);
|
|
850
|
+
* });
|
|
851
|
+
* ```
|
|
852
|
+
*
|
|
853
|
+
* @example
|
|
854
|
+
* ```typescript
|
|
855
|
+
* // With @photostructure/sqlite (no-op, already enhanced)
|
|
856
|
+
* import { DatabaseSync, enhance } from '@photostructure/sqlite';
|
|
857
|
+
*
|
|
858
|
+
* const db = enhance(new DatabaseSync(':memory:'));
|
|
859
|
+
* // db already had these methods, enhance() just returns it unchanged
|
|
860
|
+
* ```
|
|
861
|
+
*/
|
|
862
|
+
declare function enhance<T extends EnhanceableDatabaseSync>(db: T): EnhancedDatabaseSync<T>;
|
|
863
|
+
/**
|
|
864
|
+
* Type guard to check if a database has enhanced methods.
|
|
865
|
+
*
|
|
866
|
+
* @param db The database to check
|
|
867
|
+
* @returns True if the database has `.pragma()` and `.transaction()` methods
|
|
868
|
+
*
|
|
869
|
+
* @example
|
|
870
|
+
* ```typescript
|
|
871
|
+
* import { isEnhanced } from '@photostructure/sqlite';
|
|
872
|
+
*
|
|
873
|
+
* if (isEnhanced(db)) {
|
|
874
|
+
* db.pragma('cache_size', { simple: true });
|
|
875
|
+
* }
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
declare function isEnhanced(db: EnhanceableDatabaseSync): db is EnhanceableDatabaseSync & EnhancedMethods;
|
|
879
|
+
|
|
685
880
|
/**
|
|
686
881
|
* All SQLite constants exported by this module.
|
|
687
882
|
*
|
|
@@ -699,12 +894,41 @@ interface SqliteOpenFlags {
|
|
|
699
894
|
type SqliteConstants = SqliteOpenFlags & SqliteChangesetResolution & SqliteChangesetConflictTypes & SqliteAuthorizationResults & SqliteAuthorizationActions;
|
|
700
895
|
/**
|
|
701
896
|
* Options for creating a prepared statement.
|
|
897
|
+
*
|
|
898
|
+
* **Note:** The per-statement override options (`readBigInts`, `returnArrays`,
|
|
899
|
+
* `allowBareNamedParameters`, `allowUnknownNamedParameters`) are a **Node.js v25+**
|
|
900
|
+
* feature. On Node.js v24 and earlier, `node:sqlite` silently ignores these options.
|
|
901
|
+
* This library implements them for forward compatibility with Node.js v25+.
|
|
702
902
|
*/
|
|
703
903
|
interface StatementOptions {
|
|
704
904
|
/** If true, the prepared statement's expandedSQL property will contain the expanded SQL. @default false */
|
|
705
905
|
readonly expandedSQL?: boolean;
|
|
706
906
|
/** If true, anonymous parameters are enabled for the statement. @default false */
|
|
707
907
|
readonly anonymousParameters?: boolean;
|
|
908
|
+
/**
|
|
909
|
+
* If true, read integer values as JavaScript BigInt. Overrides database-level setting.
|
|
910
|
+
* **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.
|
|
911
|
+
* @default database default
|
|
912
|
+
*/
|
|
913
|
+
readonly readBigInts?: boolean;
|
|
914
|
+
/**
|
|
915
|
+
* If true, return results as arrays rather than objects. Overrides database-level setting.
|
|
916
|
+
* **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.
|
|
917
|
+
* @default database default
|
|
918
|
+
*/
|
|
919
|
+
readonly returnArrays?: boolean;
|
|
920
|
+
/**
|
|
921
|
+
* If true, allows bare named parameters (without prefix). Overrides database-level setting.
|
|
922
|
+
* **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.
|
|
923
|
+
* @default database default
|
|
924
|
+
*/
|
|
925
|
+
readonly allowBareNamedParameters?: boolean;
|
|
926
|
+
/**
|
|
927
|
+
* If true, unknown named parameters are ignored. Overrides database-level setting.
|
|
928
|
+
* **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.
|
|
929
|
+
* @default database default
|
|
930
|
+
*/
|
|
931
|
+
readonly allowUnknownNamedParameters?: boolean;
|
|
708
932
|
}
|
|
709
933
|
/**
|
|
710
934
|
* The main SQLite module interface.
|
|
@@ -736,48 +960,19 @@ interface SqliteModule {
|
|
|
736
960
|
*/
|
|
737
961
|
constants: SqliteConstants;
|
|
738
962
|
}
|
|
739
|
-
/**
|
|
740
|
-
* The DatabaseSync class represents a synchronous connection to a SQLite database.
|
|
741
|
-
* All database operations are performed synchronously, blocking the thread until completion.
|
|
742
|
-
*
|
|
743
|
-
* @example
|
|
744
|
-
* ```typescript
|
|
745
|
-
* import { DatabaseSync } from '@photostructure/sqlite';
|
|
746
|
-
*
|
|
747
|
-
* // Create an in-memory database
|
|
748
|
-
* const db = new DatabaseSync(':memory:');
|
|
749
|
-
*
|
|
750
|
-
* // Create a file-based database
|
|
751
|
-
* const fileDb = new DatabaseSync('./mydata.db');
|
|
752
|
-
*
|
|
753
|
-
* // Create with options
|
|
754
|
-
* const readOnlyDb = new DatabaseSync('./data.db', { readOnly: true });
|
|
755
|
-
* ```
|
|
756
|
-
*/
|
|
757
963
|
declare const DatabaseSync: SqliteModule["DatabaseSync"];
|
|
758
|
-
/**
|
|
759
|
-
* The StatementSync class represents a prepared SQL statement.
|
|
760
|
-
* This class should not be instantiated directly; use DatabaseSync.prepare() instead.
|
|
761
|
-
*
|
|
762
|
-
* @example
|
|
763
|
-
* ```typescript
|
|
764
|
-
* const stmt = db.prepare('SELECT * FROM users WHERE id = ?');
|
|
765
|
-
* const user = stmt.get(123);
|
|
766
|
-
* stmt.finalize();
|
|
767
|
-
* ```
|
|
768
|
-
*/
|
|
769
964
|
declare const StatementSync: SqliteModule["StatementSync"];
|
|
770
965
|
interface Session {
|
|
771
966
|
/**
|
|
772
967
|
* Generate a changeset containing all changes recorded by the session.
|
|
773
|
-
* @returns A
|
|
968
|
+
* @returns A Uint8Array containing the changeset data.
|
|
774
969
|
*/
|
|
775
|
-
changeset():
|
|
970
|
+
changeset(): Uint8Array;
|
|
776
971
|
/**
|
|
777
972
|
* Generate a patchset containing all changes recorded by the session.
|
|
778
|
-
* @returns A
|
|
973
|
+
* @returns A Uint8Array containing the patchset data.
|
|
779
974
|
*/
|
|
780
|
-
patchset():
|
|
975
|
+
patchset(): Uint8Array;
|
|
781
976
|
/**
|
|
782
977
|
* Close the session and release its resources.
|
|
783
978
|
*/
|
|
@@ -857,4 +1052,4 @@ interface BackupOptions {
|
|
|
857
1052
|
declare const backup: (sourceDb: DatabaseSyncInstance, destination: string | Buffer | URL, options?: BackupOptions) => Promise<number>;
|
|
858
1053
|
declare const _default: SqliteModule;
|
|
859
1054
|
|
|
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 };
|
|
1055
|
+
export { type AggregateOptions, type BackupOptions, type ChangesetApplyOptions, DatabaseSync, type DatabaseSyncInstance, type DatabaseSyncOptions, type EnhanceableDatabaseSync, type EnhancedDatabaseSync, type EnhancedMethods, type PragmaOptions, SQLTagStore, type SQLTagStoreInstance, Session, type SessionOptions, type SqliteAuthorizationActions, type SqliteAuthorizationResults, type SqliteChangesetConflictTypes, type SqliteChangesetResolution, type SqliteConstants, type SqliteModule, type SqliteOpenFlags, type StatementColumnMetadata, type StatementOptions, StatementSync, type StatementSyncInstance, type TransactionFunction, type TransactionMode, type UserFunctionOptions, backup, constants, _default as default, enhance, isEnhanced };
|
package/dist/index.mjs
CHANGED
|
@@ -154,7 +154,9 @@ var SQLTagStore = class {
|
|
|
154
154
|
maxCapacity;
|
|
155
155
|
constructor(db, capacity = DEFAULT_CAPACITY) {
|
|
156
156
|
if (!db.isOpen) {
|
|
157
|
-
|
|
157
|
+
const err = new Error("database is not open");
|
|
158
|
+
err.code = "ERR_INVALID_STATE";
|
|
159
|
+
throw err;
|
|
158
160
|
}
|
|
159
161
|
this.database = db;
|
|
160
162
|
this.maxCapacity = capacity;
|
|
@@ -175,7 +177,7 @@ var SQLTagStore = class {
|
|
|
175
177
|
/**
|
|
176
178
|
* Returns the current number of cached statements.
|
|
177
179
|
*/
|
|
178
|
-
size() {
|
|
180
|
+
get size() {
|
|
179
181
|
return this.cache.size();
|
|
180
182
|
}
|
|
181
183
|
/**
|
|
@@ -215,19 +217,15 @@ var SQLTagStore = class {
|
|
|
215
217
|
}
|
|
216
218
|
/**
|
|
217
219
|
* Get a cached statement or prepare a new one.
|
|
218
|
-
* If a cached statement has been finalized, it's evicted and a new one is prepared.
|
|
219
220
|
*/
|
|
220
221
|
getOrPrepare(strings) {
|
|
221
222
|
if (!this.database.isOpen) {
|
|
222
|
-
throw new Error("
|
|
223
|
+
throw new Error("database is not open");
|
|
223
224
|
}
|
|
224
225
|
const sql = this.buildSQL(strings);
|
|
225
226
|
const cached = this.cache.get(sql);
|
|
226
227
|
if (cached) {
|
|
227
|
-
|
|
228
|
-
return cached;
|
|
229
|
-
}
|
|
230
|
-
this.cache.delete(sql);
|
|
228
|
+
return cached;
|
|
231
229
|
}
|
|
232
230
|
const stmt = this.database.prepare(sql);
|
|
233
231
|
this.cache.set(sql, stmt);
|
|
@@ -245,13 +243,158 @@ var SQLTagStore = class {
|
|
|
245
243
|
}
|
|
246
244
|
};
|
|
247
245
|
|
|
246
|
+
// src/transaction.ts
|
|
247
|
+
var savepointCounter = 0;
|
|
248
|
+
function createTransaction(db, fn) {
|
|
249
|
+
if (typeof fn !== "function") {
|
|
250
|
+
throw new TypeError("Expected first argument to be a function");
|
|
251
|
+
}
|
|
252
|
+
const variants = {
|
|
253
|
+
deferred: createVariant(db, fn, "deferred"),
|
|
254
|
+
immediate: createVariant(db, fn, "immediate"),
|
|
255
|
+
exclusive: createVariant(db, fn, "exclusive")
|
|
256
|
+
};
|
|
257
|
+
const defaultFn = variants.deferred;
|
|
258
|
+
for (const variant of Object.values(variants)) {
|
|
259
|
+
Object.defineProperties(variant, {
|
|
260
|
+
deferred: { value: variants.deferred, enumerable: true },
|
|
261
|
+
immediate: { value: variants.immediate, enumerable: true },
|
|
262
|
+
exclusive: { value: variants.exclusive, enumerable: true },
|
|
263
|
+
database: { value: db, enumerable: true }
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return defaultFn;
|
|
267
|
+
}
|
|
268
|
+
function createVariant(db, fn, mode) {
|
|
269
|
+
const beginStatement = getBeginStatement(mode);
|
|
270
|
+
return function transactionWrapper(...args) {
|
|
271
|
+
const isNested = db.isTransaction;
|
|
272
|
+
let begin;
|
|
273
|
+
let commit;
|
|
274
|
+
let rollback;
|
|
275
|
+
if (isNested) {
|
|
276
|
+
const savepointName = `\`_txn_${++savepointCounter}\``;
|
|
277
|
+
begin = `SAVEPOINT ${savepointName}`;
|
|
278
|
+
commit = `RELEASE ${savepointName}`;
|
|
279
|
+
rollback = `ROLLBACK TO ${savepointName}`;
|
|
280
|
+
} else {
|
|
281
|
+
begin = beginStatement;
|
|
282
|
+
commit = "COMMIT";
|
|
283
|
+
rollback = "ROLLBACK";
|
|
284
|
+
}
|
|
285
|
+
db.exec(begin);
|
|
286
|
+
try {
|
|
287
|
+
const result = fn.apply(this, args);
|
|
288
|
+
if (result !== null && typeof result === "object" && "then" in result) {
|
|
289
|
+
throw new TypeError(
|
|
290
|
+
"Transaction function must not return a Promise. SQLite transactions are synchronous and cannot span across async operations. Use synchronous code within transactions."
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
db.exec(commit);
|
|
294
|
+
return result;
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (db.isTransaction) {
|
|
297
|
+
db.exec(rollback);
|
|
298
|
+
if (isNested) {
|
|
299
|
+
db.exec(commit);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function getBeginStatement(mode) {
|
|
307
|
+
switch (mode) {
|
|
308
|
+
case "deferred":
|
|
309
|
+
return "BEGIN DEFERRED";
|
|
310
|
+
case "immediate":
|
|
311
|
+
return "BEGIN IMMEDIATE";
|
|
312
|
+
case "exclusive":
|
|
313
|
+
return "BEGIN EXCLUSIVE";
|
|
314
|
+
default:
|
|
315
|
+
throw new Error(`Unknown transaction mode: ${mode}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/enhance.ts
|
|
320
|
+
function pragmaImpl(source, options) {
|
|
321
|
+
if (typeof source !== "string") {
|
|
322
|
+
throw new TypeError("Expected first argument to be a string");
|
|
323
|
+
}
|
|
324
|
+
if (options != null && typeof options !== "object") {
|
|
325
|
+
throw new TypeError("Expected second argument to be an options object");
|
|
326
|
+
}
|
|
327
|
+
const simple = options?.simple === true;
|
|
328
|
+
if (options != null && "simple" in options && typeof options.simple !== "boolean") {
|
|
329
|
+
throw new TypeError('Expected the "simple" option to be a boolean');
|
|
330
|
+
}
|
|
331
|
+
const stmt = this.prepare(`PRAGMA ${source}`);
|
|
332
|
+
const rows = stmt.all();
|
|
333
|
+
if (simple) {
|
|
334
|
+
const firstRow = rows[0];
|
|
335
|
+
if (firstRow == null) {
|
|
336
|
+
return void 0;
|
|
337
|
+
}
|
|
338
|
+
const keys = Object.keys(firstRow);
|
|
339
|
+
const firstKey = keys[0];
|
|
340
|
+
if (firstKey == null) {
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
343
|
+
return firstRow[firstKey];
|
|
344
|
+
}
|
|
345
|
+
return rows;
|
|
346
|
+
}
|
|
347
|
+
function transactionImpl(fn) {
|
|
348
|
+
return createTransaction(this, fn);
|
|
349
|
+
}
|
|
350
|
+
function hasEnhancedMethods(db) {
|
|
351
|
+
return typeof db.pragma === "function" && typeof db.transaction === "function";
|
|
352
|
+
}
|
|
353
|
+
function enhance(db) {
|
|
354
|
+
if (hasEnhancedMethods(db)) {
|
|
355
|
+
return db;
|
|
356
|
+
}
|
|
357
|
+
Object.defineProperty(db, "pragma", {
|
|
358
|
+
value: pragmaImpl,
|
|
359
|
+
writable: true,
|
|
360
|
+
configurable: true,
|
|
361
|
+
enumerable: false
|
|
362
|
+
});
|
|
363
|
+
Object.defineProperty(db, "transaction", {
|
|
364
|
+
value: transactionImpl,
|
|
365
|
+
writable: true,
|
|
366
|
+
configurable: true,
|
|
367
|
+
enumerable: false
|
|
368
|
+
});
|
|
369
|
+
return db;
|
|
370
|
+
}
|
|
371
|
+
function isEnhanced(db) {
|
|
372
|
+
return hasEnhancedMethods(db);
|
|
373
|
+
}
|
|
374
|
+
|
|
248
375
|
// src/index.ts
|
|
249
376
|
var binding = nodeGypBuild(join(_dirname(), ".."));
|
|
250
|
-
var
|
|
377
|
+
var _DatabaseSync = binding.DatabaseSync;
|
|
378
|
+
var DatabaseSync = function DatabaseSync2(...args) {
|
|
379
|
+
if (!new.target) {
|
|
380
|
+
const err = new TypeError("Cannot call constructor without `new`");
|
|
381
|
+
err.code = "ERR_CONSTRUCT_CALL_REQUIRED";
|
|
382
|
+
throw err;
|
|
383
|
+
}
|
|
384
|
+
return Reflect.construct(_DatabaseSync, args, new.target);
|
|
385
|
+
};
|
|
386
|
+
Object.setPrototypeOf(DatabaseSync, _DatabaseSync);
|
|
387
|
+
DatabaseSync.prototype = _DatabaseSync.prototype;
|
|
251
388
|
DatabaseSync.prototype.createTagStore = function(capacity) {
|
|
252
389
|
return new SQLTagStore(this, capacity);
|
|
253
390
|
};
|
|
254
|
-
var
|
|
391
|
+
var _StatementSync = binding.StatementSync;
|
|
392
|
+
var StatementSync = function StatementSync2() {
|
|
393
|
+
const err = new TypeError("Illegal constructor");
|
|
394
|
+
err.code = "ERR_ILLEGAL_CONSTRUCTOR";
|
|
395
|
+
throw err;
|
|
396
|
+
};
|
|
397
|
+
StatementSync.prototype = _StatementSync.prototype;
|
|
255
398
|
var Session = binding.Session;
|
|
256
399
|
var constants = binding.constants;
|
|
257
400
|
var backup = binding.backup;
|
|
@@ -263,6 +406,8 @@ export {
|
|
|
263
406
|
StatementSync,
|
|
264
407
|
backup,
|
|
265
408
|
constants,
|
|
266
|
-
index_default as default
|
|
409
|
+
index_default as default,
|
|
410
|
+
enhance,
|
|
411
|
+
isEnhanced
|
|
267
412
|
};
|
|
268
413
|
//# sourceMappingURL=index.mjs.map
|