@tursodatabase/sync-react-native 0.5.0-pre.4
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/README.md +117 -0
- package/android/CMakeLists.txt +53 -0
- package/android/build.gradle +84 -0
- package/android/cpp-adapter.cpp +49 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/turso/sync/reactnative/TursoBridge.java +44 -0
- package/android/src/main/java/com/turso/sync/reactnative/TursoModule.java +82 -0
- package/android/src/main/java/com/turso/sync/reactnative/TursoPackage.java +29 -0
- package/cpp/TursoConnectionHostObject.cpp +179 -0
- package/cpp/TursoConnectionHostObject.h +52 -0
- package/cpp/TursoDatabaseHostObject.cpp +98 -0
- package/cpp/TursoDatabaseHostObject.h +49 -0
- package/cpp/TursoHostObject.cpp +561 -0
- package/cpp/TursoHostObject.h +24 -0
- package/cpp/TursoStatementHostObject.cpp +414 -0
- package/cpp/TursoStatementHostObject.h +65 -0
- package/cpp/TursoSyncChangesHostObject.cpp +41 -0
- package/cpp/TursoSyncChangesHostObject.h +52 -0
- package/cpp/TursoSyncDatabaseHostObject.cpp +328 -0
- package/cpp/TursoSyncDatabaseHostObject.h +61 -0
- package/cpp/TursoSyncIoItemHostObject.cpp +304 -0
- package/cpp/TursoSyncIoItemHostObject.h +52 -0
- package/cpp/TursoSyncOperationHostObject.cpp +168 -0
- package/cpp/TursoSyncOperationHostObject.h +53 -0
- package/ios/TursoModule.h +8 -0
- package/ios/TursoModule.mm +95 -0
- package/lib/commonjs/Database.js +445 -0
- package/lib/commonjs/Database.js.map +1 -0
- package/lib/commonjs/Statement.js +339 -0
- package/lib/commonjs/Statement.js.map +1 -0
- package/lib/commonjs/index.js +229 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/internal/asyncOperation.js +124 -0
- package/lib/commonjs/internal/asyncOperation.js.map +1 -0
- package/lib/commonjs/internal/ioProcessor.js +315 -0
- package/lib/commonjs/internal/ioProcessor.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types.js +133 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/Database.js +441 -0
- package/lib/module/Database.js.map +1 -0
- package/lib/module/Statement.js +335 -0
- package/lib/module/Statement.js.map +1 -0
- package/lib/module/index.js +205 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/internal/asyncOperation.js +116 -0
- package/lib/module/internal/asyncOperation.js.map +1 -0
- package/lib/module/internal/ioProcessor.js +309 -0
- package/lib/module/internal/ioProcessor.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +163 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/Database.d.ts +140 -0
- package/lib/typescript/Database.d.ts.map +1 -0
- package/lib/typescript/Statement.d.ts +105 -0
- package/lib/typescript/Statement.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +175 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/internal/asyncOperation.d.ts +39 -0
- package/lib/typescript/internal/asyncOperation.d.ts.map +1 -0
- package/lib/typescript/internal/ioProcessor.d.ts +48 -0
- package/lib/typescript/internal/ioProcessor.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +316 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +97 -0
- package/src/Database.ts +480 -0
- package/src/Statement.ts +372 -0
- package/src/index.ts +240 -0
- package/src/internal/asyncOperation.ts +147 -0
- package/src/internal/ioProcessor.ts +328 -0
- package/src/types.ts +391 -0
- package/turso-sync-react-native.podspec +56 -0
package/src/Database.ts
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database
|
|
3
|
+
*
|
|
4
|
+
* Unified high-level API for both local and sync databases.
|
|
5
|
+
* Constructor determines whether to use local-only or sync mode based on config.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Statement } from './Statement';
|
|
9
|
+
import type {
|
|
10
|
+
NativeDatabase,
|
|
11
|
+
NativeSyncDatabase,
|
|
12
|
+
NativeConnection,
|
|
13
|
+
Row,
|
|
14
|
+
RunResult,
|
|
15
|
+
|
|
16
|
+
BindParams,
|
|
17
|
+
DatabaseOpts,
|
|
18
|
+
SyncStats,
|
|
19
|
+
EncryptionOpts,
|
|
20
|
+
} from './types';
|
|
21
|
+
import {
|
|
22
|
+
driveVoidOperation,
|
|
23
|
+
driveConnectionOperation,
|
|
24
|
+
driveChangesOperation,
|
|
25
|
+
driveStatsOperation,
|
|
26
|
+
} from './internal/asyncOperation';
|
|
27
|
+
import { drainSyncIo } from './internal/ioProcessor';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if config has sync properties (url field)
|
|
31
|
+
*/
|
|
32
|
+
function isSyncConfig(opts: DatabaseOpts): boolean {
|
|
33
|
+
return opts.url !== undefined && opts.url !== null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Calculate reserved bytes based on encryption cipher.
|
|
38
|
+
* These values match the Turso Cloud encryption settings.
|
|
39
|
+
*/
|
|
40
|
+
function getReservedBytesForCipher(encryption: EncryptionOpts | undefined): number {
|
|
41
|
+
if (!encryption) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
switch (encryption.cipher) {
|
|
46
|
+
case 'aes256gcm':
|
|
47
|
+
case 'aes128gcm':
|
|
48
|
+
case 'chacha20poly1305':
|
|
49
|
+
return 28;
|
|
50
|
+
case 'aegis128l':
|
|
51
|
+
case 'aegis128x2':
|
|
52
|
+
case 'aegis128x4':
|
|
53
|
+
return 32;
|
|
54
|
+
case 'aegis256':
|
|
55
|
+
case 'aegis256x2':
|
|
56
|
+
case 'aegis256x4':
|
|
57
|
+
return 48;
|
|
58
|
+
default:
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Database class - works for both local-only and sync databases
|
|
65
|
+
*
|
|
66
|
+
* All database operations are async to properly handle IO requirements:
|
|
67
|
+
* - For local databases: async allows yielding to JS event loop
|
|
68
|
+
* - For sync databases: async required for network operations
|
|
69
|
+
* - For partial sync: async required to load missing pages on-demand
|
|
70
|
+
*/
|
|
71
|
+
export class Database {
|
|
72
|
+
private _opts: DatabaseOpts;
|
|
73
|
+
private _nativeDb: NativeDatabase | null = null;
|
|
74
|
+
private _nativeSyncDb: NativeSyncDatabase | null = null;
|
|
75
|
+
private _connection: NativeConnection | null = null;
|
|
76
|
+
private _isSync = false;
|
|
77
|
+
private _connected = false;
|
|
78
|
+
private _closed = false;
|
|
79
|
+
private _extraIo?: () => Promise<void>;
|
|
80
|
+
private _ioContext?: {
|
|
81
|
+
authToken?: string | (() => string | Promise<string> | null);
|
|
82
|
+
baseUrl: string;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create a new database (doesn't connect yet - call connect())
|
|
87
|
+
*
|
|
88
|
+
* @param opts - Database options
|
|
89
|
+
*/
|
|
90
|
+
constructor(opts: DatabaseOpts) {
|
|
91
|
+
this._opts = opts;
|
|
92
|
+
this._isSync = isSyncConfig(opts);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Connect to the database (matches JavaScript bindings)
|
|
97
|
+
* For local databases: opens immediately
|
|
98
|
+
* For sync databases: bootstraps if needed
|
|
99
|
+
*/
|
|
100
|
+
async connect(): Promise<void> {
|
|
101
|
+
if (this._connected) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (this._isSync) {
|
|
106
|
+
await this.initSyncDatabase();
|
|
107
|
+
} else {
|
|
108
|
+
this.initLocalDatabase();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this._connected = true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Initialize local-only database
|
|
116
|
+
*/
|
|
117
|
+
private initLocalDatabase(): void {
|
|
118
|
+
if (typeof __TursoProxy === 'undefined') {
|
|
119
|
+
throw new Error('Turso native module not loaded');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const dbConfig = {
|
|
123
|
+
path: this._opts.path,
|
|
124
|
+
async_io: true, // Always use async IO in React Native
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Create native database (path normalization happens in C++ JSI layer)
|
|
128
|
+
this._nativeDb = __TursoProxy.newDatabase(this._opts.path, dbConfig);
|
|
129
|
+
|
|
130
|
+
// Open database
|
|
131
|
+
this._nativeDb.open();
|
|
132
|
+
|
|
133
|
+
// Get connection
|
|
134
|
+
this._connection = this._nativeDb.connect();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Initialize sync database
|
|
139
|
+
*/
|
|
140
|
+
private async initSyncDatabase(): Promise<void> {
|
|
141
|
+
if (typeof __TursoProxy === 'undefined') {
|
|
142
|
+
throw new Error('Turso native module not loaded');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Get URL (can be string or function)
|
|
146
|
+
let url: string | null = null;
|
|
147
|
+
if (typeof this._opts.url === 'function') {
|
|
148
|
+
url = this._opts.url();
|
|
149
|
+
} else if (typeof this._opts.url === 'string') {
|
|
150
|
+
url = this._opts.url;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!url) {
|
|
154
|
+
throw new Error('Sync database requires a URL');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Build dbConfig (path normalization happens in C++ JSI layer)
|
|
158
|
+
const dbConfig = {
|
|
159
|
+
path: this._opts.path,
|
|
160
|
+
async_io: true, // Always use async IO in React Native
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Calculate reserved bytes from cipher
|
|
164
|
+
const reservedBytes = getReservedBytesForCipher(this._opts.remoteEncryption);
|
|
165
|
+
|
|
166
|
+
// Build syncConfig with all options
|
|
167
|
+
const syncConfig: any = {
|
|
168
|
+
remoteUrl: url,
|
|
169
|
+
clientName: this._opts.clientName || 'turso-sync-react-native',
|
|
170
|
+
longPollTimeoutMs: this._opts.longPollTimeoutMs,
|
|
171
|
+
bootstrapIfEmpty: this._opts.bootstrapIfEmpty ?? true,
|
|
172
|
+
reservedBytes: reservedBytes,
|
|
173
|
+
// Remote encryption options (key is passed to sync engine for HTTP headers)
|
|
174
|
+
remoteEncryptionKey: this._opts.remoteEncryption?.key,
|
|
175
|
+
remoteEncryptionCipher: this._opts.remoteEncryption?.cipher,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Add partial sync options if present
|
|
179
|
+
if (this._opts.partialSyncExperimental) {
|
|
180
|
+
const partial = this._opts.partialSyncExperimental;
|
|
181
|
+
if (partial.bootstrapStrategy.kind === 'prefix') {
|
|
182
|
+
syncConfig.partialBootstrapStrategyPrefix = partial.bootstrapStrategy.length;
|
|
183
|
+
} else if (partial.bootstrapStrategy.kind === 'query') {
|
|
184
|
+
syncConfig.partialBootstrapStrategyQuery = partial.bootstrapStrategy.query;
|
|
185
|
+
}
|
|
186
|
+
syncConfig.partialBootstrapSegmentSize = partial.segmentSize;
|
|
187
|
+
syncConfig.partialBootstrapPrefetch = partial.prefetch;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Create native sync database
|
|
191
|
+
this._nativeSyncDb = __TursoProxy.newSyncDatabase(dbConfig, syncConfig);
|
|
192
|
+
|
|
193
|
+
// Create IO context with auth token and base URL
|
|
194
|
+
this._ioContext = {
|
|
195
|
+
authToken: this._opts.authToken,
|
|
196
|
+
baseUrl: url,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Create extraIo callback for partial sync support
|
|
200
|
+
// This callback drains the sync engine's IO queue during statement execution
|
|
201
|
+
this._extraIo = async () => {
|
|
202
|
+
if (this._nativeSyncDb && this._ioContext) {
|
|
203
|
+
await drainSyncIo(this._nativeSyncDb, this._ioContext);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Bootstrap/open database
|
|
208
|
+
const operation = this._nativeSyncDb.create();
|
|
209
|
+
await driveVoidOperation(operation, this._nativeSyncDb, this._ioContext);
|
|
210
|
+
|
|
211
|
+
// Get connection
|
|
212
|
+
const connOperation = this._nativeSyncDb.connect();
|
|
213
|
+
this._connection = await driveConnectionOperation(connOperation, this._nativeSyncDb, this._ioContext);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Prepare a SQL statement
|
|
218
|
+
*
|
|
219
|
+
* @param sql - SQL statement to prepare
|
|
220
|
+
* @returns Prepared statement
|
|
221
|
+
*/
|
|
222
|
+
prepare(sql: string): Statement {
|
|
223
|
+
this.checkOpen();
|
|
224
|
+
|
|
225
|
+
if (!this._connection) {
|
|
226
|
+
throw new Error('No connection available');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const nativeStmt = this._connection.prepareSingle(sql);
|
|
230
|
+
// Pass extraIo callback for partial sync support
|
|
231
|
+
return new Statement(nativeStmt, this._extraIo);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Execute SQL without returning results (for DDL, multi-statement SQL)
|
|
236
|
+
*
|
|
237
|
+
* @param sql - SQL to execute
|
|
238
|
+
*/
|
|
239
|
+
async exec(sql: string): Promise<void> {
|
|
240
|
+
this.checkOpen();
|
|
241
|
+
|
|
242
|
+
if (!this._connection) {
|
|
243
|
+
throw new Error('No connection available');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Use prepareFirst to handle multiple statements
|
|
247
|
+
let remaining = sql.trim();
|
|
248
|
+
|
|
249
|
+
while (remaining.length > 0) {
|
|
250
|
+
const result = this._connection.prepareFirst(remaining);
|
|
251
|
+
|
|
252
|
+
if (!result.statement) {
|
|
253
|
+
break; // No more statements
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Wrap in Statement to get IO handling
|
|
257
|
+
const stmt = new Statement(result.statement, this._extraIo);
|
|
258
|
+
try {
|
|
259
|
+
// Execute - will handle IO if needed
|
|
260
|
+
await stmt.run();
|
|
261
|
+
} finally {
|
|
262
|
+
stmt.finalize();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Move to next statement
|
|
266
|
+
remaining = sql.substring(result.tailIdx).trim();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Execute statement and return result info
|
|
272
|
+
*
|
|
273
|
+
* @param sql - SQL statement
|
|
274
|
+
* @param params - Bind parameters
|
|
275
|
+
* @returns Run result with changes and lastInsertRowid
|
|
276
|
+
*/
|
|
277
|
+
async run(sql: string, ...params: BindParams[]): Promise<RunResult> {
|
|
278
|
+
const stmt = this.prepare(sql);
|
|
279
|
+
try {
|
|
280
|
+
return await stmt.run(...params);
|
|
281
|
+
} finally {
|
|
282
|
+
stmt.finalize();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Execute query and return first row
|
|
288
|
+
*
|
|
289
|
+
* @param sql - SQL query
|
|
290
|
+
* @param params - Bind parameters
|
|
291
|
+
* @returns First row or undefined
|
|
292
|
+
*/
|
|
293
|
+
async get(sql: string, ...params: BindParams[]): Promise<Row | undefined> {
|
|
294
|
+
const stmt = this.prepare(sql);
|
|
295
|
+
try {
|
|
296
|
+
return await stmt.get(...params);
|
|
297
|
+
} finally {
|
|
298
|
+
stmt.finalize();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Execute query and return all rows
|
|
304
|
+
*
|
|
305
|
+
* @param sql - SQL query
|
|
306
|
+
* @param params - Bind parameters
|
|
307
|
+
* @returns All rows
|
|
308
|
+
*/
|
|
309
|
+
async all(sql: string, ...params: BindParams[]): Promise<Row[]> {
|
|
310
|
+
const stmt = this.prepare(sql);
|
|
311
|
+
try {
|
|
312
|
+
return await stmt.all(...params);
|
|
313
|
+
} finally {
|
|
314
|
+
stmt.finalize();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Execute function within a transaction
|
|
320
|
+
*
|
|
321
|
+
* @param fn - Function to execute
|
|
322
|
+
* @returns Function result
|
|
323
|
+
*/
|
|
324
|
+
async transaction<T>(fn: () => T | Promise<T>): Promise<T> {
|
|
325
|
+
this.checkOpen();
|
|
326
|
+
await this.exec('BEGIN');
|
|
327
|
+
try {
|
|
328
|
+
const result = await fn();
|
|
329
|
+
await this.exec('COMMIT');
|
|
330
|
+
return result;
|
|
331
|
+
} catch (error) {
|
|
332
|
+
await this.exec('ROLLBACK');
|
|
333
|
+
throw error;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Push local changes to remote (sync databases only)
|
|
339
|
+
*/
|
|
340
|
+
async push(): Promise<void> {
|
|
341
|
+
if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {
|
|
342
|
+
throw new Error('push() is only available for sync databases');
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const operation = this._nativeSyncDb.pushChanges();
|
|
346
|
+
await driveVoidOperation(operation, this._nativeSyncDb, this._ioContext);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Pull remote changes and apply locally (sync databases only)
|
|
351
|
+
*
|
|
352
|
+
* @returns true if changes were applied, false if no changes
|
|
353
|
+
*/
|
|
354
|
+
async pull(): Promise<boolean> {
|
|
355
|
+
if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {
|
|
356
|
+
throw new Error('pull() is only available for sync databases');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Wait for changes
|
|
360
|
+
const waitOperation = this._nativeSyncDb.waitChanges();
|
|
361
|
+
const changes = await driveChangesOperation(waitOperation, this._nativeSyncDb, this._ioContext);
|
|
362
|
+
|
|
363
|
+
// If no changes, return false
|
|
364
|
+
if (!changes) {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Apply changes
|
|
369
|
+
const applyOperation = this._nativeSyncDb.applyChanges(changes);
|
|
370
|
+
await driveVoidOperation(applyOperation, this._nativeSyncDb, this._ioContext);
|
|
371
|
+
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Get sync statistics (sync databases only)
|
|
377
|
+
*
|
|
378
|
+
* @returns Sync stats
|
|
379
|
+
*/
|
|
380
|
+
async stats(): Promise<SyncStats> {
|
|
381
|
+
if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {
|
|
382
|
+
throw new Error('stats() is only available for sync databases');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const operation = this._nativeSyncDb.stats();
|
|
386
|
+
return driveStatsOperation(operation, this._nativeSyncDb, this._ioContext);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Checkpoint database (sync databases only)
|
|
391
|
+
*/
|
|
392
|
+
async checkpoint(): Promise<void> {
|
|
393
|
+
if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {
|
|
394
|
+
throw new Error('checkpoint() is only available for sync databases');
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const operation = this._nativeSyncDb.checkpoint();
|
|
398
|
+
await driveVoidOperation(operation, this._nativeSyncDb, this._ioContext);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Close the database
|
|
403
|
+
*/
|
|
404
|
+
close(): void {
|
|
405
|
+
if (this._closed) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (this._connection) {
|
|
410
|
+
this._connection.close();
|
|
411
|
+
this._connection = null;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (this._nativeDb) {
|
|
415
|
+
this._nativeDb.close();
|
|
416
|
+
this._nativeDb = null;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (this._nativeSyncDb) {
|
|
420
|
+
this._nativeSyncDb.close();
|
|
421
|
+
this._nativeSyncDb = null;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
this._connected = false;
|
|
425
|
+
this._closed = true;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Get database path
|
|
430
|
+
*/
|
|
431
|
+
get path(): string {
|
|
432
|
+
return this._opts.path;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Check if database is a sync database
|
|
437
|
+
*/
|
|
438
|
+
get isSync(): boolean {
|
|
439
|
+
return this._isSync;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Check if database is open
|
|
444
|
+
*/
|
|
445
|
+
get open(): boolean {
|
|
446
|
+
return !this._closed && this._connection !== null;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Check if in transaction
|
|
451
|
+
*/
|
|
452
|
+
get inTransaction(): boolean {
|
|
453
|
+
if (!this._connection) {
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
return !this._connection.getAutocommit();
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Get last insert rowid
|
|
461
|
+
*/
|
|
462
|
+
get lastInsertRowid(): number {
|
|
463
|
+
if (!this._connection) {
|
|
464
|
+
return 0;
|
|
465
|
+
}
|
|
466
|
+
return this._connection.lastInsertRowid();
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Check if open and throw if not
|
|
471
|
+
*/
|
|
472
|
+
private checkOpen(): void {
|
|
473
|
+
if (this._closed) {
|
|
474
|
+
throw new Error('Database is closed');
|
|
475
|
+
}
|
|
476
|
+
if (!this._connected || !this._connection) {
|
|
477
|
+
throw new Error('Database not connected. Call connect() first.');
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|