@photostructure/sqlite 0.0.1 → 0.2.1
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 +38 -2
- package/README.md +47 -483
- package/SECURITY.md +27 -83
- package/binding.gyp +69 -22
- package/dist/index.cjs +185 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +552 -100
- package/dist/index.d.mts +552 -100
- package/dist/index.d.ts +552 -100
- package/dist/index.mjs +183 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +51 -41
- 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/src/aggregate_function.cpp +503 -235
- package/src/aggregate_function.h +57 -42
- package/src/binding.cpp +117 -14
- package/src/dirname.ts +1 -1
- package/src/index.ts +122 -332
- package/src/lru-cache.ts +84 -0
- package/src/shims/env-inl.h +6 -15
- package/src/shims/node_errors.h +7 -1
- package/src/shims/sqlite_errors.h +168 -0
- package/src/shims/util.h +29 -4
- package/src/sql-tag-store.ts +140 -0
- package/src/sqlite_exception.h +49 -0
- package/src/sqlite_impl.cpp +736 -129
- package/src/sqlite_impl.h +84 -6
- package/src/{stack_path.ts → stack-path.ts} +7 -1
- package/src/types/aggregate-options.ts +22 -0
- package/src/types/changeset-apply-options.ts +18 -0
- package/src/types/database-sync-instance.ts +203 -0
- package/src/types/database-sync-options.ts +69 -0
- package/src/types/session-options.ts +10 -0
- package/src/types/sql-tag-store-instance.ts +51 -0
- package/src/types/sqlite-authorization-actions.ts +77 -0
- package/src/types/sqlite-authorization-results.ts +15 -0
- package/src/types/sqlite-changeset-conflict-types.ts +19 -0
- package/src/types/sqlite-changeset-resolution.ts +15 -0
- package/src/types/sqlite-open-flags.ts +50 -0
- package/src/types/statement-sync-instance.ts +73 -0
- package/src/types/user-functions-options.ts +14 -0
- package/src/upstream/node_sqlite.cc +960 -259
- package/src/upstream/node_sqlite.h +127 -2
- package/src/upstream/sqlite.js +1 -14
- package/src/upstream/sqlite3.c +4510 -1411
- package/src/upstream/sqlite3.h +390 -195
- package/src/upstream/sqlite3ext.h +7 -0
- package/src/user_function.cpp +88 -36
- package/src/user_function.h +2 -1
package/src/sqlite_impl.h
CHANGED
|
@@ -82,12 +82,38 @@ public:
|
|
|
82
82
|
void set_timeout(int timeout) { timeout_ = timeout; }
|
|
83
83
|
int get_timeout() const { return timeout_; }
|
|
84
84
|
|
|
85
|
+
bool get_read_big_ints() const { return read_big_ints_; }
|
|
86
|
+
void set_read_big_ints(bool flag) { read_big_ints_ = flag; }
|
|
87
|
+
|
|
88
|
+
bool get_return_arrays() const { return return_arrays_; }
|
|
89
|
+
void set_return_arrays(bool flag) { return_arrays_ = flag; }
|
|
90
|
+
|
|
91
|
+
bool get_allow_bare_named_params() const { return allow_bare_named_params_; }
|
|
92
|
+
void set_allow_bare_named_params(bool flag) {
|
|
93
|
+
allow_bare_named_params_ = flag;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
bool get_allow_unknown_named_params() const {
|
|
97
|
+
return allow_unknown_named_params_;
|
|
98
|
+
}
|
|
99
|
+
void set_allow_unknown_named_params(bool flag) {
|
|
100
|
+
allow_unknown_named_params_ = flag;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
bool get_enable_defensive() const { return defensive_; }
|
|
104
|
+
void set_enable_defensive(bool flag) { defensive_ = flag; }
|
|
105
|
+
|
|
85
106
|
private:
|
|
86
107
|
std::string location_;
|
|
87
108
|
bool read_only_ = false;
|
|
88
109
|
bool enable_foreign_keys_ = true;
|
|
89
110
|
bool enable_dqs_ = false;
|
|
90
111
|
int timeout_ = 0;
|
|
112
|
+
bool read_big_ints_ = false;
|
|
113
|
+
bool return_arrays_ = false;
|
|
114
|
+
bool allow_bare_named_params_ = true;
|
|
115
|
+
bool allow_unknown_named_params_ = false;
|
|
116
|
+
bool defensive_ = false;
|
|
91
117
|
};
|
|
92
118
|
|
|
93
119
|
// Main database class
|
|
@@ -103,6 +129,7 @@ public:
|
|
|
103
129
|
// Database operations
|
|
104
130
|
Napi::Value Open(const Napi::CallbackInfo &info);
|
|
105
131
|
Napi::Value Close(const Napi::CallbackInfo &info);
|
|
132
|
+
Napi::Value Dispose(const Napi::CallbackInfo &info);
|
|
106
133
|
Napi::Value Prepare(const Napi::CallbackInfo &info);
|
|
107
134
|
Napi::Value Exec(const Napi::CallbackInfo &info);
|
|
108
135
|
|
|
@@ -125,6 +152,9 @@ public:
|
|
|
125
152
|
Napi::Value EnableLoadExtension(const Napi::CallbackInfo &info);
|
|
126
153
|
Napi::Value LoadExtension(const Napi::CallbackInfo &info);
|
|
127
154
|
|
|
155
|
+
// Defensive mode
|
|
156
|
+
Napi::Value EnableDefensive(const Napi::CallbackInfo &info);
|
|
157
|
+
|
|
128
158
|
// Session support
|
|
129
159
|
Napi::Value CreateSession(const Napi::CallbackInfo &info);
|
|
130
160
|
Napi::Value ApplyChangeset(const Napi::CallbackInfo &info);
|
|
@@ -132,11 +162,39 @@ public:
|
|
|
132
162
|
// Backup support
|
|
133
163
|
Napi::Value Backup(const Napi::CallbackInfo &info);
|
|
134
164
|
|
|
165
|
+
// Authorization API
|
|
166
|
+
Napi::Value SetAuthorizer(const Napi::CallbackInfo &info);
|
|
167
|
+
|
|
168
|
+
// Static callback for SQLite authorization
|
|
169
|
+
static int AuthorizerCallback(void *user_data, int action_code,
|
|
170
|
+
const char *param1, const char *param2,
|
|
171
|
+
const char *param3, const char *param4);
|
|
172
|
+
|
|
135
173
|
// Session management
|
|
136
174
|
void AddSession(Session *session);
|
|
137
175
|
void RemoveSession(Session *session);
|
|
138
176
|
void DeleteAllSessions();
|
|
139
177
|
|
|
178
|
+
// Error handling for user functions
|
|
179
|
+
void SetIgnoreNextSQLiteError(bool ignore) {
|
|
180
|
+
ignore_next_sqlite_error_ = ignore;
|
|
181
|
+
}
|
|
182
|
+
bool ShouldIgnoreSQLiteError() const { return ignore_next_sqlite_error_; }
|
|
183
|
+
|
|
184
|
+
// Deferred exception handling for authorizer callbacks
|
|
185
|
+
void SetDeferredAuthorizerException(const std::string &message) {
|
|
186
|
+
deferred_authorizer_exception_ = message;
|
|
187
|
+
}
|
|
188
|
+
void ClearDeferredAuthorizerException() {
|
|
189
|
+
deferred_authorizer_exception_.reset();
|
|
190
|
+
}
|
|
191
|
+
bool HasDeferredAuthorizerException() const {
|
|
192
|
+
return deferred_authorizer_exception_.has_value();
|
|
193
|
+
}
|
|
194
|
+
const std::string &GetDeferredAuthorizerException() const {
|
|
195
|
+
return deferred_authorizer_exception_.value();
|
|
196
|
+
}
|
|
197
|
+
|
|
140
198
|
private:
|
|
141
199
|
void InternalOpen(DatabaseOpenConfiguration config);
|
|
142
200
|
void InternalClose();
|
|
@@ -150,10 +208,22 @@ private:
|
|
|
150
208
|
std::set<Session *> sessions_; // Track all active sessions
|
|
151
209
|
mutable std::mutex sessions_mutex_; // Protect sessions_ for thread safety
|
|
152
210
|
std::thread::id creation_thread_;
|
|
153
|
-
napi_env env_;
|
|
211
|
+
napi_env env_; // Store for cleanup purposes
|
|
212
|
+
bool ignore_next_sqlite_error_ = false; // For user function error handling
|
|
213
|
+
|
|
214
|
+
// Deferred exception from authorizer callback - stored when exception occurs
|
|
215
|
+
// in callback context, thrown after SQLite operation completes
|
|
216
|
+
std::optional<std::string> deferred_authorizer_exception_;
|
|
217
|
+
|
|
218
|
+
// Authorization callback storage
|
|
219
|
+
std::unique_ptr<Napi::FunctionReference> authorizer_callback_;
|
|
220
|
+
|
|
221
|
+
// Store database-level defaults for statement options
|
|
222
|
+
DatabaseOpenConfiguration config_;
|
|
154
223
|
|
|
155
224
|
bool ValidateThread(Napi::Env env) const;
|
|
156
225
|
friend class Session;
|
|
226
|
+
friend class StatementSync;
|
|
157
227
|
};
|
|
158
228
|
|
|
159
229
|
// Statement class
|
|
@@ -175,15 +245,18 @@ public:
|
|
|
175
245
|
Napi::Value All(const Napi::CallbackInfo &info);
|
|
176
246
|
Napi::Value Iterate(const Napi::CallbackInfo &info);
|
|
177
247
|
Napi::Value FinalizeStatement(const Napi::CallbackInfo &info);
|
|
248
|
+
Napi::Value Dispose(const Napi::CallbackInfo &info);
|
|
178
249
|
|
|
179
250
|
// Properties
|
|
180
251
|
Napi::Value SourceSQLGetter(const Napi::CallbackInfo &info);
|
|
181
252
|
Napi::Value ExpandedSQLGetter(const Napi::CallbackInfo &info);
|
|
253
|
+
Napi::Value FinalizedGetter(const Napi::CallbackInfo &info);
|
|
182
254
|
|
|
183
255
|
// Configuration methods
|
|
184
256
|
Napi::Value SetReadBigInts(const Napi::CallbackInfo &info);
|
|
185
257
|
Napi::Value SetReturnArrays(const Napi::CallbackInfo &info);
|
|
186
258
|
Napi::Value SetAllowBareNamedParameters(const Napi::CallbackInfo &info);
|
|
259
|
+
Napi::Value SetAllowUnknownNamedParameters(const Napi::CallbackInfo &info);
|
|
187
260
|
|
|
188
261
|
// Metadata methods
|
|
189
262
|
Napi::Value Columns(const Napi::CallbackInfo &info);
|
|
@@ -194,7 +267,11 @@ private:
|
|
|
194
267
|
Napi::Value CreateResult();
|
|
195
268
|
void Reset();
|
|
196
269
|
|
|
197
|
-
DatabaseSync *database_;
|
|
270
|
+
DatabaseSync *database_ = nullptr;
|
|
271
|
+
// Strong reference to database object to prevent GC while statement exists.
|
|
272
|
+
// This fixes use-after-free when database is GC'd before its statements.
|
|
273
|
+
// See: https://github.com/nodejs/node/pull/56840
|
|
274
|
+
Napi::ObjectReference database_ref_;
|
|
198
275
|
sqlite3_stmt *statement_ = nullptr;
|
|
199
276
|
std::string source_sql_;
|
|
200
277
|
bool finalized_ = false;
|
|
@@ -204,6 +281,7 @@ private:
|
|
|
204
281
|
bool use_big_ints_ = false;
|
|
205
282
|
bool return_arrays_ = false;
|
|
206
283
|
bool allow_bare_named_params_ = false;
|
|
284
|
+
bool allow_unknown_named_params_ = false;
|
|
207
285
|
|
|
208
286
|
// Bare named parameters mapping (bare name -> full name with prefix)
|
|
209
287
|
std::optional<std::map<std::string, std::string>> bare_named_params_;
|
|
@@ -246,6 +324,7 @@ public:
|
|
|
246
324
|
Napi::Value Changeset(const Napi::CallbackInfo &info);
|
|
247
325
|
Napi::Value Patchset(const Napi::CallbackInfo &info);
|
|
248
326
|
Napi::Value Close(const Napi::CallbackInfo &info);
|
|
327
|
+
Napi::Value Dispose(const Napi::CallbackInfo &info);
|
|
249
328
|
|
|
250
329
|
// Get the underlying SQLite session
|
|
251
330
|
sqlite3_session *GetSession() const { return session_; }
|
|
@@ -272,10 +351,9 @@ struct BackupProgress {
|
|
|
272
351
|
// Backup job for asynchronous database backup
|
|
273
352
|
class BackupJob : public Napi::AsyncProgressWorker<BackupProgress> {
|
|
274
353
|
public:
|
|
275
|
-
BackupJob(Napi::Env env, DatabaseSync *source,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
Napi::Promise::Deferred deferred);
|
|
354
|
+
BackupJob(Napi::Env env, DatabaseSync *source, std::string destination_path,
|
|
355
|
+
std::string source_db, std::string dest_db, int pages,
|
|
356
|
+
Napi::Function progress_func, Napi::Promise::Deferred deferred);
|
|
279
357
|
~BackupJob();
|
|
280
358
|
|
|
281
359
|
void Execute(const ExecutionProgress &progress) override;
|
|
@@ -12,6 +12,10 @@ export function getCallerDirname(): string {
|
|
|
12
12
|
const patterns =
|
|
13
13
|
process.platform === "win32"
|
|
14
14
|
? [
|
|
15
|
+
// File URLs: "at functionName (file:///C:/path/file.js:1:1)"
|
|
16
|
+
/\bat\s.+?\((?<path>file:\/\/\/.+?):\d+:\d+\)$/,
|
|
17
|
+
// File URLs direct: "at file:///C:/path/file.js:1:1"
|
|
18
|
+
/\bat\s(?<path>file:\/\/\/.+?):\d+:\d+$/,
|
|
15
19
|
// Standard: "at functionName (C:\path\file.js:1:1)"
|
|
16
20
|
/\bat\s.+?\((?<path>[A-Z]:\\.+):\d+:\d+\)$/,
|
|
17
21
|
// direct: "at C:\path\file.js:1:1"
|
|
@@ -25,7 +29,8 @@ const patterns =
|
|
|
25
29
|
// Standard: "at functionName (/path/file.js:1:1)"
|
|
26
30
|
/\bat\s.+?\((?<path>\/.+?):\d+:\d+\)$/,
|
|
27
31
|
// Anonymous or direct: "at /path/file.js:1:1"
|
|
28
|
-
|
|
32
|
+
// eslint-disable-next-line security/detect-unsafe-regex -- Pattern is safe: no nested quantifiers
|
|
33
|
+
/\bat\s(?:[^\s()]+\s)?(?<path>\/[^:]+):\d+:\d+$/,
|
|
29
34
|
];
|
|
30
35
|
|
|
31
36
|
const MaybeUrlRE = /^[a-z]{2,5}:\/\//i;
|
|
@@ -42,6 +47,7 @@ export function extractCallerPath(stack: string): string {
|
|
|
42
47
|
throw new Error("Invalid stack trace format: missing caller frame");
|
|
43
48
|
}
|
|
44
49
|
for (let i = callerFrame + 1; i < frames.length; i++) {
|
|
50
|
+
// eslint-disable-next-line security/detect-object-injection -- Index is from controlled for-loop
|
|
45
51
|
const frame = frames[i];
|
|
46
52
|
for (const pattern of patterns) {
|
|
47
53
|
const g = frame?.trim().match(pattern)?.groups;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for creating SQLite aggregate functions.
|
|
3
|
+
* Used with `DatabaseSync.aggregate()` to define custom aggregate operations.
|
|
4
|
+
*/
|
|
5
|
+
export 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
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for applying changesets to a database.
|
|
3
|
+
* Used with `DatabaseSync.applyChangeset()` to handle conflicts and filter tables.
|
|
4
|
+
*/
|
|
5
|
+
export interface ChangesetApplyOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Function called when a conflict is detected during changeset application.
|
|
8
|
+
* @param conflictType The type of conflict (SQLITE_CHANGESET_CONFLICT, etc.)
|
|
9
|
+
* @returns One of SQLITE_CHANGESET_OMIT, SQLITE_CHANGESET_REPLACE, or SQLITE_CHANGESET_ABORT
|
|
10
|
+
*/
|
|
11
|
+
readonly onConflict?: (conflictType: number) => number;
|
|
12
|
+
/**
|
|
13
|
+
* Function called to filter which tables to apply changes to.
|
|
14
|
+
* @param tableName The name of the table
|
|
15
|
+
* @returns true to include the table, false to skip it
|
|
16
|
+
*/
|
|
17
|
+
readonly filter?: (tableName: string) => boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { Session, StatementOptions } from "../index";
|
|
2
|
+
import { AggregateOptions } from "./aggregate-options";
|
|
3
|
+
import { ChangesetApplyOptions } from "./changeset-apply-options";
|
|
4
|
+
import { SessionOptions } from "./session-options";
|
|
5
|
+
import { SQLTagStoreInstance } from "./sql-tag-store-instance";
|
|
6
|
+
import { StatementSyncInstance } from "./statement-sync-instance";
|
|
7
|
+
import { UserFunctionOptions } from "./user-functions-options";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Represents a SQLite database connection.
|
|
11
|
+
* This interface represents an instance of the DatabaseSync class.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export interface DatabaseSyncInstance {
|
|
15
|
+
/** Indicates whether the database connection is open. */
|
|
16
|
+
readonly isOpen: boolean;
|
|
17
|
+
/** Indicates whether a transaction is currently active. */
|
|
18
|
+
readonly isTransaction: boolean;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Opens a database connection. This method should only be used when the database
|
|
22
|
+
* was created with { open: false }. An exception is thrown if the database is already open.
|
|
23
|
+
*/
|
|
24
|
+
open(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Closes the database connection. This method should be called to ensure that
|
|
27
|
+
* the database connection is properly cleaned up. Once a database is closed,
|
|
28
|
+
* it cannot be used again.
|
|
29
|
+
*/
|
|
30
|
+
close(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the location of the database file. For attached databases, you can specify
|
|
33
|
+
* the database name. Returns null for in-memory databases.
|
|
34
|
+
* @param dbName The name of the database. Defaults to 'main' (the primary database).
|
|
35
|
+
* @returns The file path of the database, or null for in-memory databases.
|
|
36
|
+
*/
|
|
37
|
+
location(dbName?: string): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Compiles an SQL statement and returns a StatementSyncInstance object.
|
|
40
|
+
* @param sql The SQL statement to prepare.
|
|
41
|
+
* @param options Optional configuration for the statement.
|
|
42
|
+
* @returns A StatementSyncInstance object that can be executed multiple times.
|
|
43
|
+
*/
|
|
44
|
+
prepare(sql: string, options?: StatementOptions): StatementSyncInstance;
|
|
45
|
+
/**
|
|
46
|
+
* This method allows one or more SQL statements to be executed without
|
|
47
|
+
* returning any results. This is useful for commands like CREATE TABLE,
|
|
48
|
+
* INSERT, UPDATE, or DELETE.
|
|
49
|
+
* @param sql The SQL statement(s) to execute.
|
|
50
|
+
*/
|
|
51
|
+
exec(sql: string): void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* This method creates SQLite user-defined functions, wrapping sqlite3_create_function_v2().
|
|
55
|
+
* @param name The name of the SQLite function to create.
|
|
56
|
+
* @param func The JavaScript function to call when the SQLite function is invoked.
|
|
57
|
+
*/
|
|
58
|
+
function(name: string, func: Function): void;
|
|
59
|
+
/**
|
|
60
|
+
* This method creates SQLite user-defined functions, wrapping sqlite3_create_function_v2().
|
|
61
|
+
* @param name The name of the SQLite function to create.
|
|
62
|
+
* @param options Optional configuration settings.
|
|
63
|
+
* @param func The JavaScript function to call when the SQLite function is invoked.
|
|
64
|
+
*/
|
|
65
|
+
function(name: string, options: UserFunctionOptions, func: Function): void;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* This method creates SQLite aggregate functions, wrapping sqlite3_create_window_function().
|
|
69
|
+
* @param name The name of the SQLite aggregate function to create.
|
|
70
|
+
* @param options Configuration object containing step function and other settings.
|
|
71
|
+
*/
|
|
72
|
+
aggregate(name: string, options: AggregateOptions): void;
|
|
73
|
+
/**
|
|
74
|
+
* Create a new session to record database changes.
|
|
75
|
+
* @param options Optional configuration for the session.
|
|
76
|
+
* @returns A Session object for recording changes.
|
|
77
|
+
*/
|
|
78
|
+
createSession(options?: SessionOptions): Session;
|
|
79
|
+
/**
|
|
80
|
+
* Create a new SQLTagStore for cached prepared statements via tagged template syntax.
|
|
81
|
+
* @param capacity Optional maximum number of statements to cache. @default 1000
|
|
82
|
+
* @returns A SQLTagStore instance.
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const sql = db.createTagStore();
|
|
86
|
+
* sql.run`INSERT INTO users VALUES (${id}, ${name})`;
|
|
87
|
+
* const user = sql.get`SELECT * FROM users WHERE id = ${id}`;
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
createTagStore(capacity?: number): SQLTagStoreInstance;
|
|
91
|
+
/**
|
|
92
|
+
* Apply a changeset to the database.
|
|
93
|
+
* @param changeset The changeset data to apply.
|
|
94
|
+
* @param options Optional configuration for applying the changeset.
|
|
95
|
+
* @returns true if successful, false if aborted.
|
|
96
|
+
*/
|
|
97
|
+
applyChangeset(changeset: Buffer, options?: ChangesetApplyOptions): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Enables or disables the loading of SQLite extensions.
|
|
100
|
+
* @param enable If true, enables extension loading. If false, disables it.
|
|
101
|
+
*/
|
|
102
|
+
enableLoadExtension(enable: boolean): void;
|
|
103
|
+
/**
|
|
104
|
+
* Loads an SQLite extension from the specified file path.
|
|
105
|
+
* @param path The path to the extension library.
|
|
106
|
+
* @param entryPoint Optional entry point function name. If not provided, uses the default entry point.
|
|
107
|
+
*/
|
|
108
|
+
loadExtension(path: string, entryPoint?: string): void;
|
|
109
|
+
/**
|
|
110
|
+
* Enables or disables the defensive flag. When the defensive flag is active,
|
|
111
|
+
* language features that allow ordinary SQL to deliberately corrupt the
|
|
112
|
+
* database file are disabled.
|
|
113
|
+
* @param active Whether to enable or disable the defensive flag.
|
|
114
|
+
* @see https://sqlite.org/c3ref/c_dbconfig_defensive.html
|
|
115
|
+
*/
|
|
116
|
+
enableDefensive(active: boolean): void;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Sets an authorization callback that is invoked before each SQL operation.
|
|
120
|
+
* The authorizer can allow, deny, or ignore each operation.
|
|
121
|
+
*
|
|
122
|
+
* @param callback The authorization callback function, or null to remove the authorizer.
|
|
123
|
+
* - actionCode: The action being requested (e.g., SQLITE_SELECT, SQLITE_INSERT)
|
|
124
|
+
* - param1: First parameter (varies by action, often table name)
|
|
125
|
+
* - param2: Second parameter (varies by action, often column name)
|
|
126
|
+
* - param3: Third parameter (usually database name like "main")
|
|
127
|
+
* - param4: Fourth parameter (trigger or view name if applicable)
|
|
128
|
+
*
|
|
129
|
+
* The callback must return one of:
|
|
130
|
+
* - constants.SQLITE_OK: Allow the operation
|
|
131
|
+
* - constants.SQLITE_DENY: Deny the operation and abort the SQL statement
|
|
132
|
+
* - constants.SQLITE_IGNORE: Silently ignore/skip the operation
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // Block all DELETE operations
|
|
137
|
+
* db.setAuthorizer((actionCode, table, column, dbName, trigger) => {
|
|
138
|
+
* if (actionCode === constants.SQLITE_DELETE) {
|
|
139
|
+
* return constants.SQLITE_DENY;
|
|
140
|
+
* }
|
|
141
|
+
* return constants.SQLITE_OK;
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // Remove the authorizer
|
|
145
|
+
* db.setAuthorizer(null);
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @see https://sqlite.org/c3ref/set_authorizer.html
|
|
149
|
+
*/
|
|
150
|
+
setAuthorizer(
|
|
151
|
+
callback:
|
|
152
|
+
| ((
|
|
153
|
+
actionCode: number,
|
|
154
|
+
param1: string | null,
|
|
155
|
+
param2: string | null,
|
|
156
|
+
param3: string | null,
|
|
157
|
+
param4: string | null,
|
|
158
|
+
) => number)
|
|
159
|
+
| null,
|
|
160
|
+
): void;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Makes a backup of the database. This method abstracts the sqlite3_backup_init(),
|
|
164
|
+
* sqlite3_backup_step() and sqlite3_backup_finish() functions.
|
|
165
|
+
*
|
|
166
|
+
* The backed-up database can be used normally during the backup process. Mutations
|
|
167
|
+
* coming from the same connection will be reflected in the backup right away.
|
|
168
|
+
* However, mutations from other connections will cause the backup process to restart.
|
|
169
|
+
*
|
|
170
|
+
* @param path The path where the backup will be created. If the file already exists, the contents will be overwritten.
|
|
171
|
+
* @param options Optional configuration for the backup operation.
|
|
172
|
+
* @param options.rate Number of pages to be transmitted in each batch of the backup. @default 100
|
|
173
|
+
* @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'
|
|
174
|
+
* @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'
|
|
175
|
+
* @param options.progress Callback function that will be called with the number of pages copied and the total number of pages.
|
|
176
|
+
* @returns A promise that resolves when the backup is completed and rejects if an error occurs.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* // Basic backup
|
|
180
|
+
* await db.backup('./backup.db');
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* // Backup with progress
|
|
184
|
+
* await db.backup('./backup.db', {
|
|
185
|
+
* rate: 10,
|
|
186
|
+
* progress: ({ totalPages, remainingPages }) => {
|
|
187
|
+
* console.log(`Progress: ${totalPages - remainingPages}/${totalPages}`);
|
|
188
|
+
* }
|
|
189
|
+
* });
|
|
190
|
+
*/
|
|
191
|
+
backup(
|
|
192
|
+
path: string | Buffer | URL,
|
|
193
|
+
options?: {
|
|
194
|
+
rate?: number;
|
|
195
|
+
source?: string;
|
|
196
|
+
target?: string;
|
|
197
|
+
progress?: (info: { totalPages: number; remainingPages: number }) => void;
|
|
198
|
+
},
|
|
199
|
+
): Promise<number>;
|
|
200
|
+
|
|
201
|
+
/** Dispose of the database resources using the explicit resource management protocol. */
|
|
202
|
+
[Symbol.dispose](): void;
|
|
203
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for opening a database.
|
|
3
|
+
* This interface matches Node.js sqlite module's DatabaseSyncOptions.
|
|
4
|
+
*/
|
|
5
|
+
export 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;
|
|
12
|
+
/**
|
|
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
|
|
23
|
+
*/
|
|
24
|
+
readonly enableDoubleQuotedStringLiterals?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Sets the busy timeout in milliseconds.
|
|
27
|
+
* @default 0
|
|
28
|
+
*/
|
|
29
|
+
readonly timeout?: number;
|
|
30
|
+
/** If true, enables loading of SQLite extensions. @default false */
|
|
31
|
+
readonly allowExtension?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* If true, SQLite integers are returned as JavaScript BigInt values.
|
|
34
|
+
* If false, integers are returned as JavaScript numbers.
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
readonly readBigInts?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* If true, query results are returned as arrays instead of objects.
|
|
40
|
+
* @default false
|
|
41
|
+
*/
|
|
42
|
+
readonly returnArrays?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* If true, allows binding named parameters without the prefix character.
|
|
45
|
+
* For example, allows using 'foo' instead of ':foo' or '$foo'.
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
readonly allowBareNamedParameters?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* If true, unknown named parameters are ignored during binding.
|
|
51
|
+
* If false, an exception is thrown for unknown named parameters.
|
|
52
|
+
* @default false
|
|
53
|
+
*/
|
|
54
|
+
readonly allowUnknownNamedParameters?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* If true, enables the defensive flag. When the defensive flag is enabled,
|
|
57
|
+
* language features that allow ordinary SQL to deliberately corrupt the
|
|
58
|
+
* database file are disabled. The defensive flag can also be set using
|
|
59
|
+
* `enableDefensive()`.
|
|
60
|
+
* @see https://sqlite.org/c3ref/c_dbconfig_defensive.html
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
readonly defensive?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* If true, the database is opened immediately. If false, the database is not opened until the first operation.
|
|
66
|
+
* @default true
|
|
67
|
+
*/
|
|
68
|
+
readonly open?: boolean;
|
|
69
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for creating SQLite sessions.
|
|
3
|
+
* Used with `DatabaseSync.createSession()` to track database changes.
|
|
4
|
+
*/
|
|
5
|
+
export interface SessionOptions {
|
|
6
|
+
/** The table to track changes for. If omitted, all tables are tracked. */
|
|
7
|
+
readonly table?: string;
|
|
8
|
+
/** The database name. @default "main" */
|
|
9
|
+
readonly db?: string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { DatabaseSyncInstance } from "./database-sync-instance";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SQLTagStore provides cached prepared statements via tagged template syntax.
|
|
5
|
+
* Statements are cached by their SQL string and reused across invocations.
|
|
6
|
+
*/
|
|
7
|
+
export interface SQLTagStoreInstance {
|
|
8
|
+
/** Returns the associated database instance. */
|
|
9
|
+
readonly db: DatabaseSyncInstance;
|
|
10
|
+
/** Returns the maximum capacity of the statement cache. */
|
|
11
|
+
readonly capacity: number;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the current number of cached statements.
|
|
14
|
+
*/
|
|
15
|
+
size(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Clears all cached statements.
|
|
18
|
+
*/
|
|
19
|
+
clear(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Execute an INSERT, UPDATE, DELETE or other statement that doesn't return rows.
|
|
22
|
+
* @param strings Template literal strings array.
|
|
23
|
+
* @param values Values to bind to the placeholders.
|
|
24
|
+
* @returns An object with `changes` and `lastInsertRowid`.
|
|
25
|
+
*/
|
|
26
|
+
run(
|
|
27
|
+
strings: TemplateStringsArray,
|
|
28
|
+
...values: unknown[]
|
|
29
|
+
): { changes: number; lastInsertRowid: number | bigint };
|
|
30
|
+
/**
|
|
31
|
+
* Execute a query and return the first row, or undefined if no rows.
|
|
32
|
+
* @param strings Template literal strings array.
|
|
33
|
+
* @param values Values to bind to the placeholders.
|
|
34
|
+
*/
|
|
35
|
+
get(strings: TemplateStringsArray, ...values: unknown[]): unknown;
|
|
36
|
+
/**
|
|
37
|
+
* Execute a query and return all rows as an array.
|
|
38
|
+
* @param strings Template literal strings array.
|
|
39
|
+
* @param values Values to bind to the placeholders.
|
|
40
|
+
*/
|
|
41
|
+
all(strings: TemplateStringsArray, ...values: unknown[]): unknown[];
|
|
42
|
+
/**
|
|
43
|
+
* Execute a query and return an iterator over the rows.
|
|
44
|
+
* @param strings Template literal strings array.
|
|
45
|
+
* @param values Values to bind to the placeholders.
|
|
46
|
+
*/
|
|
47
|
+
iterate(
|
|
48
|
+
strings: TemplateStringsArray,
|
|
49
|
+
...values: unknown[]
|
|
50
|
+
): IterableIterator<unknown>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authorization action codes passed to `setAuthorizer()` callbacks.
|
|
3
|
+
*
|
|
4
|
+
* These constants are compatible with `node:sqlite`.
|
|
5
|
+
*
|
|
6
|
+
* @see https://sqlite.org/c3ref/c_alter_table.html
|
|
7
|
+
*/
|
|
8
|
+
export interface SqliteAuthorizationActions {
|
|
9
|
+
/** Create a new index. */
|
|
10
|
+
SQLITE_CREATE_INDEX: number;
|
|
11
|
+
/** Create a new table. */
|
|
12
|
+
SQLITE_CREATE_TABLE: number;
|
|
13
|
+
/** Create a new temporary index. */
|
|
14
|
+
SQLITE_CREATE_TEMP_INDEX: number;
|
|
15
|
+
/** Create a new temporary table. */
|
|
16
|
+
SQLITE_CREATE_TEMP_TABLE: number;
|
|
17
|
+
/** Create a new temporary trigger. */
|
|
18
|
+
SQLITE_CREATE_TEMP_TRIGGER: number;
|
|
19
|
+
/** Create a new temporary view. */
|
|
20
|
+
SQLITE_CREATE_TEMP_VIEW: number;
|
|
21
|
+
/** Create a new trigger. */
|
|
22
|
+
SQLITE_CREATE_TRIGGER: number;
|
|
23
|
+
/** Create a new view. */
|
|
24
|
+
SQLITE_CREATE_VIEW: number;
|
|
25
|
+
/** Delete rows from a table. */
|
|
26
|
+
SQLITE_DELETE: number;
|
|
27
|
+
/** Drop an index. */
|
|
28
|
+
SQLITE_DROP_INDEX: number;
|
|
29
|
+
/** Drop a table. */
|
|
30
|
+
SQLITE_DROP_TABLE: number;
|
|
31
|
+
/** Drop a temporary index. */
|
|
32
|
+
SQLITE_DROP_TEMP_INDEX: number;
|
|
33
|
+
/** Drop a temporary table. */
|
|
34
|
+
SQLITE_DROP_TEMP_TABLE: number;
|
|
35
|
+
/** Drop a temporary trigger. */
|
|
36
|
+
SQLITE_DROP_TEMP_TRIGGER: number;
|
|
37
|
+
/** Drop a temporary view. */
|
|
38
|
+
SQLITE_DROP_TEMP_VIEW: number;
|
|
39
|
+
/** Drop a trigger. */
|
|
40
|
+
SQLITE_DROP_TRIGGER: number;
|
|
41
|
+
/** Drop a view. */
|
|
42
|
+
SQLITE_DROP_VIEW: number;
|
|
43
|
+
/** Insert rows into a table. */
|
|
44
|
+
SQLITE_INSERT: number;
|
|
45
|
+
/** Execute a PRAGMA statement. */
|
|
46
|
+
SQLITE_PRAGMA: number;
|
|
47
|
+
/** Read a column from a table. */
|
|
48
|
+
SQLITE_READ: number;
|
|
49
|
+
/** Execute a SELECT statement. */
|
|
50
|
+
SQLITE_SELECT: number;
|
|
51
|
+
/** Begin/commit/rollback a transaction. */
|
|
52
|
+
SQLITE_TRANSACTION: number;
|
|
53
|
+
/** Update rows in a table. */
|
|
54
|
+
SQLITE_UPDATE: number;
|
|
55
|
+
/** Attach a database. */
|
|
56
|
+
SQLITE_ATTACH: number;
|
|
57
|
+
/** Detach a database. */
|
|
58
|
+
SQLITE_DETACH: number;
|
|
59
|
+
/** Alter a table. */
|
|
60
|
+
SQLITE_ALTER_TABLE: number;
|
|
61
|
+
/** Reindex. */
|
|
62
|
+
SQLITE_REINDEX: number;
|
|
63
|
+
/** Analyze a table or index. */
|
|
64
|
+
SQLITE_ANALYZE: number;
|
|
65
|
+
/** Create a virtual table. */
|
|
66
|
+
SQLITE_CREATE_VTABLE: number;
|
|
67
|
+
/** Drop a virtual table. */
|
|
68
|
+
SQLITE_DROP_VTABLE: number;
|
|
69
|
+
/** Call a function. */
|
|
70
|
+
SQLITE_FUNCTION: number;
|
|
71
|
+
/** Create/release/rollback a savepoint. */
|
|
72
|
+
SQLITE_SAVEPOINT: number;
|
|
73
|
+
/** No longer used (historical). */
|
|
74
|
+
SQLITE_COPY: number;
|
|
75
|
+
/** Recursive query. */
|
|
76
|
+
SQLITE_RECURSIVE: number;
|
|
77
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authorization callback return values for `setAuthorizer()`.
|
|
3
|
+
*
|
|
4
|
+
* These constants are compatible with `node:sqlite`.
|
|
5
|
+
*
|
|
6
|
+
* @see https://sqlite.org/c3ref/c_deny.html
|
|
7
|
+
*/
|
|
8
|
+
export interface SqliteAuthorizationResults {
|
|
9
|
+
/** Allow the operation. */
|
|
10
|
+
SQLITE_OK: number;
|
|
11
|
+
/** Deny the operation and abort the SQL statement with an error. */
|
|
12
|
+
SQLITE_DENY: number;
|
|
13
|
+
/** Silently ignore/skip the operation (e.g., return NULL for column reads). */
|
|
14
|
+
SQLITE_IGNORE: number;
|
|
15
|
+
}
|